feat(reqstool): dogfood OpenSpec <-> reqstool traceability#84
Merged
Conversation
Bootstrap the OpenSpec spec layer and derive the reqstool SSOT for this repo, mirroring reqstool-client#407. Adds 3 capability specs (decorator-definitions, decorator-processing, yaml-export) backing DECORATORS_001-003 / SVC_DECORATORS_001-003, re-tags src with @Requirements/@svcs (including genuine self-application: SVCs is tagged with DECORATORS_001 via the Requirements decorator it implements alongside), and wires tests/resources' previously-unused fixture files into a new e2e test instead of leaving them dead. Converts the decorator-mechanics unit tests in test_decorators.py from `@Requirements(...)`/`@SVCs(...)` decorator syntax to direct calls (`Requirements(...)(func)`) -- the decorator syntax form made the nested, intentionally-fake REQ_*/SVC_* IDs in those tests show up as real AST-discoverable annotations once this repo's own processor self-applies to its own tests, which `reqstool validate --strict` correctly rejected as references to non-existent requirement/SVC IDs. CI matrix on [pypi, main] via shared reqstool/.github actions, with a new scripts/generate_annotations.py self-apply step (excluding tests/resources for the same fake-ID reason above) feeding `reqstool status`/`validate`. Signed-off-by: Jimisola Laursen <jimisola@jimisola.com>
jimisola
commented
Jun 24, 2026
jimisola
left a comment
Member
Author
There was a problem hiding this comment.
Full PR Review — Consolidated Findings
Ran 7 parallel checks (review, code-review, smells, advanced-smells, security, cruft, testing) scoped to this PR's diff. No correctness bugs found. Findings below, ordered by severity — all will be addressed in a follow-up commit.
| # | Prio | Location | Finding |
|---|---|---|---|
| 1 | Medium | .github/workflows/build.yml:50-57 |
validate-reqstool only runs on the main matrix leg; reqstool-status --fail-if-incomplete runs on both legs. Clarifying which check is the actual required gate on the pypi leg. |
| 2 | Low | scripts/generate_annotations.py:11 |
tests/integration is scanned but only contains empty __init__.py stubs — a no-op, easy to mistake for real coverage. |
| 3 | Low | scripts/generate_annotations.py:1 |
Missing the # Copyright © LFV header used by every other .py file in this repo. |
| 4 | Low | src/reqstool_python_decorators/decorators/decorators.py:14 |
@Requirements("DECORATORS_001") is applied only to SVCs (not Requirements, which can't self-tag — its own name isn't bound yet at definition time) with no comment explaining the asymmetry. |
| 5 | Low | tests/unit/reqstool_decorators/test_decorators.py |
10 near-identical 3-line test blocks with no shared helper. |
| 6 | Low | tests/e2e/reqstool_decorators/test_process_e2e.py:31-37 |
e2e test never asserts fullyQualifiedName or the YAML schema-header line — the parts of the pipeline most exposed to real filesystem behavior. |
| 7 | Info | .github/workflows/build.yml |
build/reqstool/annotations.yml and hatch build's output coexist in build/ only because hatch build doesn't clean it — fragile if that ever changes. |
Non-issues (flagged by an agent but already correct): pinning reqstool/.github's shared actions to a main-branch SHA (the established convention across this rollout — that repo has no release/tag scheme); the 3 near-identical openspec/specs/*/spec.md files (intentional thin-pointer pattern, content lives in docs/reqstool/*.yml).
Automated — /x:full-pr-review
- Drop tests/integration from the self-apply scan (empty stub dirs, was a misleading no-op) - Add missing copyright header to scripts/generate_annotations.py - Document why @requirements("DECORATORS_001") is tagged on SVCs rather than Requirements (self-reference ordering constraint) - Clarify in build.yml which step is the actual required gate (reqstool status) vs. supplementary (validate-reqstool, main-only) and note the build/ directory ordering dependency - Strengthen the e2e test with assertions on fullyQualifiedName and the YAML schema header, the parts of the pipeline most exposed to real filesystem behavior - Collapse the 10 near-identical decorator-mechanics unit tests into 3 parametrized tests, removing repeated boilerplate 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
decorator-definitions,decorator-processing,yaml-export) backingDECORATORS_001-003/SVC_DECORATORS_001-003.src/with@Requirements/@SVCs, including genuine self-application:SVCsis tagged withDECORATORS_001via theRequirementsdecorator it's implemented alongside (no chicken-and-egg compiled-processor problem here, unlike the Java annotation-processor repos — confirms the assumption noted in the rollout plan).tests/resources/test_decorators/*fixture files (never referenced by any test) into a newtests/e2e/reqstool_decorators/test_process_e2e.pytest exercising the full pipeline against real decorator syntax.test_decorators.pyfrom@Requirements(...)/@SVCs(...)decorator syntax to direct calls (Requirements(...)(func)). The decorator-syntax form made the nested, intentionally-fakeREQ_*/SVC_*IDs in those tests show up as real AST-discoverable annotations once this repo's own processor self-applies to its own tests —reqstool validate --strictcorrectly rejected those as references to non-existent requirement/SVC IDs. Newscripts/generate_annotations.pyself-apply step also excludestests/resourcesfor the same reason.build.yml) now runs the self-apply step and gates onreqstool status/validatevia a[pypi, main]matrix calling the sharedreqstool/.githubactions, plus the reusablevalidate-openspecworkflow..claude/settings.json,.mcp.json,CONTRIBUTING.mdprerequisites, and.gitignorecarve-out added from the start, matching the pattern now established across the rollout.Validation
hatch run dev:pytest— 36/36 passhatch run dev:black --check/hatch run dev:flake8— cleanopenspec validate --specs --strict— 3/3 passedreqstool validate --strict local -p docs/reqstool— all checks passed (no warnings)reqstool status --check-all-reqs-met local -p docs/reqstool— 3/3 complete, PASSreqstool mcp local -p docs/reqstool,get_statustool) — outputs agree exactly (3/3 complete, identical test counts)Test plan
pypiandmainmatrix legsvalidate-openspecjob greenhttps://claude.ai/code/session_015rzqRsXwmTz2rR9hjwYU3Q