Skip to content

feat(reqstool): dogfood OpenSpec ↔ reqstool traceability#166

Merged
jimisola merged 2 commits into
mainfrom
feat/openspec-dogfooding
Jun 23, 2026
Merged

feat(reqstool): dogfood OpenSpec ↔ reqstool traceability#166
jimisola merged 2 commits into
mainfrom
feat/openspec-dogfooding

Conversation

@jimisola

Copy link
Copy Markdown
Member

Summary

  • Bootstraps the OpenSpec spec layer + reqstool SSOT for this library, mirroring reqstool-client#407's pattern.
  • 3 capability specs in openspec/specs/ (annotation-definitions, annotation-processing, yaml-export); docs/reqstool/ SSOT with ANNOTATIONS_001-003 / SVC_ANNOTATIONS_001-003.
  • Self-applies this library's own @Requirements/@SVCs annotations to itself — including to the Requirements/SVCs annotation declarations themselves (legal since both target TYPE) and to AbstractAnnotationsProcessor's process()/exportToYAML() methods. Added a new self-apply Maven profile: two-pass build (mvn -DskipTests install → re-compile/testCompile with annotationProcessorPaths pointing at the just-installed jar), the same chicken-and-egg pattern the Maven/Gradle plugins use for their own self-application.
  • Fixed a real bug found along the way: SVCsTests.java's testMultipleSVCs instantiated Requirements instead of SVCs.
  • CI (build.yml): [pypi, main] matrix via shared reqstool/.github actions. Main/test annotation outputs land in separate generated-sources/generated-test-sources directories with no existing mojo to combine them (unlike the Maven/Gradle plugins) — added a yq merge step producing target/reqstool/annotations.yml, plus a validate-openspec job.
  • .claude/settings.json (auto-enables the reqstool/reqstool-openspec plugins) and CONTRIBUTING.md prerequisites added from the start this time, per the pattern just fixed in reqstool-java-gradle-plugin#69 / reqstool-java-maven-plugin#176 / reqstool-python-poetry-plugin#132.

Found and fixed upstream

Self-applying surfaced a real reqstool-client gap: annotating the Requirements/SVCs declarations with themselves produces ElementKind.ANNOTATION_TYPE, which:

  1. annotations.schema.json's elementKind enum didn't allow — fixed in reqstool-client#419 (issue: #418).
  2. A second, independent CHECK constraint in storage/schema.py also didn't allow — and because the insert uses INSERT OR IGNORE, the CHECK violation was silently swallowed with no warning logged, just silently dropping the requirement's implementation data. Also fixed in #419. This is exactly the kind of silent-drift bug this rollout's validation step exists to catch.

Test plan

  • mvn clean verify — all tests pass
  • Full self-apply sequence (installself-apply profile → yq merge → reqstool status): 3/3 requirements complete, PASS
  • reqstool validate --strict — all checks passed
  • openspec validate --specs --strict — 3/3 specs passed
  • CI green on this PR (pypi/main matrix, validate-openspec) — depends on reqstool-client#419 merging for the main leg to pass
  • Note: only CLI validation was performed (no CLI-vs-MCP parity check) — low risk since this dataset has no skipped/missing-test scenarios, the known CLI/MCP divergence area (reqstool-client#411)

Bootstraps the OpenSpec spec layer and reqstool SSOT for this library,
mirroring reqstool-client#407's pattern:

- 3 capability specs in openspec/specs/ (annotation-definitions,
  annotation-processing, yaml-export); docs/reqstool/ SSOT with
  ANNOTATIONS_001-003 / SVC_ANNOTATIONS_001-003
- Self-applies this library's own @Requirements/@svcs annotations to
  its own Requirements/SVCs declarations and AbstractAnnotationsProcessor's
  process()/exportToYAML() methods -- via a new `self-apply` Maven
  profile (two-pass: install, then re-compile main+test with
  annotationProcessorPaths pointing at the just-installed jar)
- Fixes a real bug along the way: SVCsTests.java's testMultipleSVCs
  instantiated Requirements instead of SVCs
- CI (build.yml): [pypi, main] matrix via shared reqstool/.github
  actions; self-apply + yq-merge step (main/test annotation outputs
  land in separate generated-sources dirs with no existing mojo to
  combine them, unlike the Maven/Gradle plugins) producing
  target/reqstool/annotations.yml; validate-openspec job
- .claude/settings.json (auto-enables reqstool/reqstool-openspec
  plugins) and CONTRIBUTING.md prerequisites added from the start,
  per the pattern fixed in reqstool-java-gradle-plugin#69/
  reqstool-java-maven-plugin#176/reqstool-python-poetry-plugin#132

Found and fixed upstream along the way: reqstool-client#418/#419 --
annotations.schema.json's elementKind enum (and a second, independent
CHECK constraint in storage/schema.py) was missing ANNOTATION_TYPE,
the ElementKind Java reports for @interface declarations. The CHECK
constraint gap was silently swallowing inserts via `INSERT OR IGNORE`
with no warning logged, the kind of silent-drift bug this dogfooding
rollout's CLI-vs-MCP/schema validation step exists to catch.

Validated: reqstool status (3/3 PASS), reqstool validate --strict,
openspec validate --specs --strict (3 passed), full test suite green.
CLI-only validation performed (no MCP parity check) -- low risk given
no skipped/missing-test scenarios are present here, the known CLI/MCP
divergence area (reqstool-client#411).

Signed-off-by: Jimisola Laursen <jimisola@jimisola.com>

@jimisola jimisola left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Full PR Review — Consolidated Findings

Ran 7 checks (review, code-review, smells, advanced-smells, security, cruft, testing) against this PR's diff.

# Prio Location Finding Resolution
1 Low AnnotationsProcessorTests.java:19 New SVCs import appended out of alphabetical order Fixing — cosmetic
2 Low build.yml:30-37 yq/grep merge logic embedded inline in workflow YAML, untestable in isolation Extracting to a script
3 Info SVCs.java:15 SVCs.java/Requirements.java both self-tag @Requirements({"ANNOTATIONS_001"}) — flagged by 2 checks as worth confirming Verified intentional: ANNOTATIONS_001 covers both annotation definitions in one requirement. No fix.
4 Info openspec/openspecui.hooks.ts Zero tests for the hand-rolled MCP stdio client; resolves reqstool via bare PATH Out of scope — byte-identical scaffolding already merged as-is in reqstool-client, reqstool-java-gradle-plugin#69, reqstool-java-maven-plugin#176, reqstool-python-poetry-plugin#132. Org-wide follow-up, not this PR.
5 Info .claude/settings.json Marketplace source unpinned, autoUpdate: true, auto-enables plugins Out of scope — same deliberate org convention already merged in 4 sibling repos this rollout.
6 Info pom.xml self-apply profile Only exercised by CI, no isolated Maven Invoker IT Out of scope — matches the Maven/Gradle plugins' existing self-application pattern.

No blocking correctness or security issues specific to this PR. Items 4-6 are intentional, already-established patterns shared identically across this rollout's other PRs — changing them here alone would diverge from the convention rather than fix a gap.

Automated — /x:full-pr-review

- Extract the main/test annotations.yml merge logic from build.yml
  into scripts/combine-annotations.sh, so it's testable/runnable
  outside CI rather than only living as inline workflow YAML
- Fix import ordering in AbstractAnnotationsProcessor.java and
  AnnotationsProcessorTests.java (io.github.reqstool.* grouped with
  other imports, not appended out of order)

Other findings from the review were judged out of scope for this PR:
the openspecui.hooks.ts MCP client and .claude/settings.json
auto-enable pattern are byte-identical to what's already merged
across reqstool-client and the other three dogfooded repos this
rollout, and the self-apply Maven profile being CI-only (no isolated
Invoker IT) matches the Maven/Gradle plugins' existing pattern.

Signed-off-by: Jimisola Laursen <jimisola@jimisola.com>
@jimisola jimisola merged commit 72680a8 into main Jun 23, 2026
6 of 7 checks passed
@jimisola jimisola deleted the feat/openspec-dogfooding branch June 23, 2026 21:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant