Skip to content

feat(reqstool): dogfood OpenSpec <-> reqstool traceability#93

Open
jimisola wants to merge 2 commits into
mainfrom
feat/openspec-dogfooding
Open

feat(reqstool): dogfood OpenSpec <-> reqstool traceability#93
jimisola wants to merge 2 commits into
mainfrom
feat/openspec-dogfooding

Conversation

@jimisola

Copy link
Copy Markdown
Member

Summary

Bootstraps the OpenSpec spec layer and derives the reqstool requirement traceability SSOT for this repo, mirroring reqstool-client#407, reqstool-python-decorators#84, and reqstool-typescript-tags#113.

  • docs/reqstool/{requirements,software_verification_cases,reqstool_config}.yml with 2 capability-prefixed requirements (HATCH_PLUGIN_001/002) covering annotation generation during build and sdist bundling. Only 2 capabilities vs. reqstool-python-poetry-plugin's 5 — Hatch's build-hook model doesn't need a separate pyproject.toml include-registration step or a root-file-cleanup step; it appends directly into the already-built sdist tarball
  • openspec/specs/{annotation-generation,sdist-bundling} thin ID-reference spec files
  • Tagged ReqstoolBuildHook.initialize/.finalize with @Requirements; tagged the existing e2e test (test_build_e2e.py, the only test that meaningfully exercises the hook against a real hatchling build of a fixture project) with @SVCs for both capabilities
  • scripts/generate_annotations.py self-applies the decorator processor to this repo's own src/tests/unit/tests/e2e — no chicken-and-egg problem, same as fix: fix check_release workflow to actually validate releases #84. tests/fixtures is excluded (its own self-contained fixture project has unrelated decorated REQ_001/SVC_001); tests/integration is empty stub packages, omitted until real tests land
  • CI: new [pypi, main] matrix on the build job, then self-apply, reqstool-status (required gate), and validate-reqstool (main leg only, supplementary); new validate-openspec job
  • .claude/settings.json + .mcp.json wire up the reqstool-ai plugins/MCP server

Test plan

  • hatch build --target wheel && hatch run dev:pytest && hatch build — 1 passed / 1 skipped (pre-existing skip, unrelated to this PR)
  • hatch run dev:python scripts/generate_annotations.py — clean self-apply, no fixture-ID pollution
  • reqstool validate --strict local -p docs/reqstool — pass
  • reqstool status --check-all-reqs-met local -p docs/reqstool — 2/2 complete
  • CLI vs MCP (reqstool mcp local -p docs/reqstool, get_requirements_status) — agree
  • openspec validate --specs --strict — 2/2 pass

Bootstraps the OpenSpec spec layer and derives the reqstool requirement
traceability SSOT for this repo, mirroring reqstool-client#407 and
reqstool-python-decorators#84:

- docs/reqstool/{requirements,software_verification_cases,reqstool_config}.yml
  with 2 capability-prefixed requirements (HATCH_PLUGIN_001/002) covering
  annotation generation during build and sdist bundling. Only 2 capabilities
  vs. poetry-plugin's 5: Hatch's build-hook model doesn't need a separate
  pyproject.toml include-registration step or a root-file-cleanup step --
  it appends directly into the already-built sdist tarball
- openspec/specs/{annotation-generation,sdist-bundling} thin ID-reference
  spec files
- Tagged ReqstoolBuildHook.initialize/.finalize with @requirements; tagged
  the existing e2e test (test_build_e2e.py, the only test that meaningfully
  exercises the hook against a real hatchling build of a fixture project)
  with @svcs for both capabilities
- scripts/generate_annotations.py self-applies the decorator processor to
  this repo's own src/tests/unit/tests/e2e -- no chicken-and-egg problem,
  same as reqstool-python-decorators#84. tests/fixtures is excluded (its own
  self-contained fixture project has unrelated decorated REQ_001/SVC_001);
  tests/integration is empty stub packages, omitted until real tests land
- CI: new [pypi, main] matrix on the build job running the existing wheel
  build + test + full build steps, then self-apply, reqstool-status
  (required gate), and validate-reqstool (main leg only, supplementary);
  new validate-openspec job
- .claude/settings.json + .mcp.json wire up the reqstool-ai plugins/MCP
  server; .gitignore carve-out for .claude/settings.json

Validated: 1 passed/1 skipped (pre-existing skip, unrelated to this PR)
test run, reqstool validate --strict and reqstool status
--check-all-reqs-met both pass (2/2 complete), CLI and MCP
(get_requirements_status) agree exactly, openspec validate --specs --strict
2/2 pass.

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

7 parallel checks (review, code-review, smells, advanced-smells, security, cruft, testing) ran against this diff.

# Prio Location Finding Found by
1 Medium tests/e2e/.../test_build_e2e.py:25 Single test verifies both SVC_HATCH_PLUGIN_001 and SVC_HATCH_PLUGIN_002 — a failure in one hook conflates both SVCs' pass/fail status advanced-smells, testing
2 Low tests/e2e/.../test_build_e2e.py:18-22 _append_to_sdist_tar_gz's manual_verification_results/test_results branches are untested even though HATCH_PLUGIN_002's description covers them review
3 Low .github/workflows/build.yml:57-61 Comment says reqstool status is "the actual required check on the pypi leg" but it runs unconditionally on both legs cruft
4 Low .github/workflows/build.yml (4 lines) Same commit SHA repeated 4 times with no single source of truth smells, code-review, cruft

All 4 fixed in a follow-up commit.

3 additional items raised by individual checks were verified as false positives or intentional, consistent with this org's dogfooding-rollout precedent (#84, #113), and are not tracked as findings:

  • manual_verification_results.yml referenced but absent in reqstool_config.yml — identical pattern in #84/#113, verified locally that reqstool validate/status tolerate it.
  • revision: "0.1.0" flagged as stale vs. package version — revision tracks requirement-baseline, not package version; same convention used in #84/#113.
  • MCP hook timeout/test_results glob breadth/self-apply allow-list/pre-existing skipped unit stub — inherited boilerplate identical to prior merged repos, or pre-existing and out of scope for this PR.

Automated — /x:full-pr-review

- Split the single e2e test into test_hatch_build_generates_annotations_yml
  (@svcs SVC_HATCH_PLUGIN_001) and test_hatch_build_sdist_bundles_reqstool_dataset
  (@svcs SVC_HATCH_PLUGIN_002), so a regression in one hook method no longer
  conflates both SVCs' pass/fail status in the traceability dataset
- Extended the sdist-bundling test to cover the previously-untested
  manual_verification_results.yml and test_results branches of
  _append_to_sdist_tar_gz: added a real manual_verification_results.yml fixture,
  carved out a .gitignore exception so the fixture's build/test-results/junit.xml
  can be committed, and asserted reqstool_config.yml records the configured
  test_results glob (the hook only records the glob pattern as metadata, it
  doesn't bundle the actual XML into the tarball -- confirmed by re-reading
  _append_to_sdist_tar_gz)
- Fixed a misleading build.yml comment implying reqstool-status only runs on the
  pypi leg; it runs unconditionally on both
- Added a one-line note flagging the 4 SHA-pinned reqstool/.github refs that need
  to stay in sync when bumped

Re-validated: 2 passed/1 skipped (pre-existing skip, unrelated), reqstool
validate --strict and reqstool status --check-all-reqs-met both pass (2/2
complete, now mapped to 2 independent tests instead of 1 shared one), openspec
validate --specs --strict 2/2, black clean.

Signed-off-by: Jimisola Laursen <jimisola@jimisola.com>
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