feat(reqstool): dogfood OpenSpec ↔ reqstool traceability#166
Merged
Conversation
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>
2 tasks
jimisola
commented
Jun 23, 2026
jimisola
left a comment
Member
Author
There was a problem hiding this comment.
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
openspec/specs/(annotation-definitions,annotation-processing,yaml-export);docs/reqstool/SSOT withANNOTATIONS_001-003/SVC_ANNOTATIONS_001-003.@Requirements/@SVCsannotations to itself — including to theRequirements/SVCsannotation declarations themselves (legal since both targetTYPE) and toAbstractAnnotationsProcessor'sprocess()/exportToYAML()methods. Added a newself-applyMaven profile: two-pass build (mvn -DskipTests install→ re-compile/testCompilewithannotationProcessorPathspointing at the just-installed jar), the same chicken-and-egg pattern the Maven/Gradle plugins use for their own self-application.SVCsTests.java'stestMultipleSVCsinstantiatedRequirementsinstead ofSVCs.build.yml):[pypi, main]matrix via sharedreqstool/.githubactions. Main/test annotation outputs land in separategenerated-sources/generated-test-sourcesdirectories with no existing mojo to combine them (unlike the Maven/Gradle plugins) — added ayqmerge step producingtarget/reqstool/annotations.yml, plus avalidate-openspecjob..claude/settings.json(auto-enables thereqstool/reqstool-openspecplugins) andCONTRIBUTING.mdprerequisites 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-clientgap: annotating theRequirements/SVCsdeclarations with themselves producesElementKind.ANNOTATION_TYPE, which:annotations.schema.json'selementKindenum didn't allow — fixed in reqstool-client#419 (issue: #418).CHECKconstraint instorage/schema.pyalso didn't allow — and because the insert usesINSERT OR IGNORE, theCHECKviolation 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 passinstall→self-applyprofile →yqmerge →reqstool status): 3/3 requirements complete, PASSreqstool validate --strict— all checks passedopenspec validate --specs --strict— 3/3 specs passedpypi/mainmatrix,validate-openspec) — depends on reqstool-client#419 merging for themainleg to pass