requirements-as-code 0.7.1__tar.gz → 0.7.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. {requirements_as_code-0.7.1/requirements_as_code.egg-info → requirements_as_code-0.7.2}/PKG-INFO +1 -1
  2. requirements_as_code-0.7.2/planning/prompt/rac-agent-compression.md +12 -0
  3. requirements_as_code-0.7.2/planning/prompt/rac-agent-instructions.md +24 -0
  4. requirements_as_code-0.7.2/planning/prompt/rac-agent-release-gate-major.md +261 -0
  5. requirements_as_code-0.7.2/planning/prompt/rac-agent-release-gate-minor.md +23 -0
  6. requirements_as_code-0.7.2/planning/prompt/rac-agent-session-start.md +23 -0
  7. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/rac/artifacts.py +6 -0
  8. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/rac/cli.py +33 -7
  9. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/rac/outputs.py +65 -1
  10. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/rac/relationships.py +199 -0
  11. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2/requirements_as_code.egg-info}/PKG-INFO +1 -1
  12. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/requirements_as_code.egg-info/SOURCES.txt +16 -0
  13. requirements_as_code-0.7.2/tests/fixtures/relationship_validation/ambiguous_target/adr-004-alt.md +13 -0
  14. requirements_as_code-0.7.2/tests/fixtures/relationship_validation/ambiguous_target/adr-004.md +13 -0
  15. requirements_as_code-0.7.2/tests/fixtures/relationship_validation/ambiguous_target/req-001.md +13 -0
  16. requirements_as_code-0.7.2/tests/fixtures/relationship_validation/broken/search.md +13 -0
  17. requirements_as_code-0.7.2/tests/fixtures/relationship_validation/duplicate/adr-004-alt.md +13 -0
  18. requirements_as_code-0.7.2/tests/fixtures/relationship_validation/duplicate/adr-004.md +13 -0
  19. requirements_as_code-0.7.2/tests/fixtures/relationship_validation/resolved/adr-004.md +17 -0
  20. requirements_as_code-0.7.2/tests/fixtures/relationship_validation/resolved/req-001.md +13 -0
  21. requirements_as_code-0.7.2/tests/fixtures/relationship_validation/resolved/roadmap-q3.md +17 -0
  22. requirements_as_code-0.7.2/tests/fixtures/relationship_validation/self_reference/adr-004.md +17 -0
  23. requirements_as_code-0.7.2/tests/test_relationship_validation.py +265 -0
  24. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/.github/workflows/python-publish.yml +0 -0
  25. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/.gitignore +0 -0
  26. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/LICENSE +0 -0
  27. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/README.md +0 -0
  28. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/examples/example_dashboard_v1.md +0 -0
  29. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/examples/example_dashboard_v2.md +0 -0
  30. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/adr/adr-001-markdown-first.md +0 -0
  31. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/adr/adr-002-ai-optional.md +0 -0
  32. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/adr/adr-003-structured-outputs-first.md +0 -0
  33. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/adr/adr-004-artifact-model.md +0 -0
  34. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/adr/adr-005-cli-first.md +0 -0
  35. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/adr/adr-006-ingest-over-rewrite.md +0 -0
  36. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/adr/adr-007-json-contract-stability.md +0 -0
  37. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/adr/adr-008-agent-ready-architecture.md +0 -0
  38. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/adr/adr-009-ai-assisted-development.md +0 -0
  39. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/adr/adr-010-documents-are-not-artifacts.md +0 -0
  40. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/adr/adr-011-file-first-pipeline.md +0 -0
  41. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/adr/adr-012-open-core-strategy.md +0 -0
  42. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/adr/adr-013-leverage-existing-source-control-systems.md +0 -0
  43. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/adr/adr-014-viewer-agnostic-knowledge-artifacts.md +0 -0
  44. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/adr/adr-015-explorer-as-consumer.md +0 -0
  45. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/adr/adr-016-relationships-as-structural-references.md +0 -0
  46. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/adr/adr-017-rac-managed-knowledge-not-work.md +0 -0
  47. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/designs/explorer-command-surface.md +0 -0
  48. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/designs/explorer-first-run-experience.md +0 -0
  49. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/designs/explorer-health-model.md +0 -0
  50. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/designs/explorer-import-workflow.md +0 -0
  51. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/designs/explorer-knowledge-graph.md +0 -0
  52. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/designs/explorer-visual-system.md +0 -0
  53. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/future/v1.0-workspace-analysis.md +0 -0
  54. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/future/v1.1-review-engine.md +0 -0
  55. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/future/v1.2-mcp-server.md +0 -0
  56. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/future/v1.4-claude-skills.md +0 -0
  57. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/future/v1.4-python-sdk.md +0 -0
  58. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/roadmap/archive/v0.5-decisions.md +0 -0
  59. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/roadmap/archive/v0.7-prompts.md +0 -0
  60. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/roadmap/v0.2-stats.md +0 -0
  61. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/roadmap/v0.3-ingest.md +0 -0
  62. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/roadmap/v0.3.1-formats.md +0 -0
  63. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/roadmap/v0.4-inspect.md +0 -0
  64. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/roadmap/v0.4.1-expansion.md +0 -0
  65. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/roadmap/v0.4.1-inspect-expansion.md +0 -0
  66. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/roadmap/v0.4.2-decision-metadata.md +0 -0
  67. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/roadmap/v0.5.0-artifact-improvement.md +0 -0
  68. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/roadmap/v0.5.1-guided-improvement.md +0 -0
  69. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/roadmap/v0.5.2-schema.md +0 -0
  70. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/roadmap/v0.6.0-roadmap-artifacts.md +0 -0
  71. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/roadmap/v0.6.1-roadmap-improvement.md +0 -0
  72. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/roadmap/v0.6.2-prompt-artifact.md +0 -0
  73. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/roadmap/v0.6.3-design-artifacts.md +0 -0
  74. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/roadmap/v0.7.0-relationship-metadata.md +0 -0
  75. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/roadmap/v0.7.1-relationship-inspection.md +0 -0
  76. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/roadmap/v0.7.2-relationship-validation.md +0 -0
  77. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/roadmap/v0.7.3-repo-intelligence.md +0 -0
  78. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/roadmap/v0.7.4-repo-indexing.md +0 -0
  79. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/roadmap/v0.8.0-service-api.md +0 -0
  80. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/roadmap/v0.8.1-repository-model.md +0 -0
  81. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/roadmap/v0.8.2-interactive-runtime-readiness.md +0 -0
  82. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/roadmap/v0.8.3-integration-freeze.md +0 -0
  83. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/roadmap/v0.9.0-explorer-foundation.md +0 -0
  84. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/roadmap/v0.9.1-explorer-experience.md +0 -0
  85. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/roadmap/v0.9.2-knowledge-operations.md +0 -0
  86. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/planning/roadmap/v0.9.3-intelligence-views.md +0 -0
  87. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/pyproject.toml +0 -0
  88. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/rac/__init__.py +0 -0
  89. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/rac/classification.py +0 -0
  90. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/rac/diff.py +0 -0
  91. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/rac/fs.py +0 -0
  92. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/rac/improve.py +0 -0
  93. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/rac/ingest.py +0 -0
  94. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/rac/inspect.py +0 -0
  95. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/rac/models.py +0 -0
  96. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/rac/parser.py +0 -0
  97. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/rac/schema.py +0 -0
  98. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/rac/stats.py +0 -0
  99. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/rac/validate.py +0 -0
  100. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/requirements_as_code.egg-info/dependency_links.txt +0 -0
  101. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/requirements_as_code.egg-info/entry_points.txt +0 -0
  102. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/requirements_as_code.egg-info/requires.txt +0 -0
  103. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/requirements_as_code.egg-info/top_level.txt +0 -0
  104. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/setup.cfg +0 -0
  105. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/conftest.py +0 -0
  106. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/decision/bad_category.md +0 -0
  107. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/decision/bad_status.md +0 -0
  108. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/decision/minimal.md +0 -0
  109. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/decision/portfolio/01_accepted_arch.md +0 -0
  110. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/decision/portfolio/02_proposed_process.md +0 -0
  111. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/decision/portfolio/03_no_metadata.md +0 -0
  112. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/decision/with_metadata.md +0 -0
  113. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/design/minimal.md +0 -0
  114. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/design/missing_constraints.md +0 -0
  115. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/design/valid.md +0 -0
  116. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/diff/new.md +0 -0
  117. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/diff/old.md +0 -0
  118. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/ingest/sample.md +0 -0
  119. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/inspect/ambiguous.md +0 -0
  120. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/inspect/decision.md +0 -0
  121. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/inspect/nested/another_requirement.md +0 -0
  122. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/inspect/requirement.md +0 -0
  123. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/invalid/duplicate_ids.md +0 -0
  124. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/invalid/empty_req_text.md +0 -0
  125. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/invalid/malformed_id.md +0 -0
  126. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/invalid/missing_id.md +0 -0
  127. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/invalid/missing_problem.md +0 -0
  128. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/invalid/missing_requirements.md +0 -0
  129. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/invalid/missing_title.md +0 -0
  130. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/invalid/multiple_titles.md +0 -0
  131. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/no_relationships/decision.md +0 -0
  132. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/no_relationships/requirement.md +0 -0
  133. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/portfolio/broken.md +0 -0
  134. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/portfolio/feature_a.md +0 -0
  135. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/portfolio/feature_b.md +0 -0
  136. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/portfolio/sub/feature_c.md +0 -0
  137. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/prompt/minimal.md +0 -0
  138. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/prompt/missing_output.md +0 -0
  139. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/prompt/valid.md +0 -0
  140. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/relationships/decision_with_links.md +0 -0
  141. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/relationships/design_with_links.md +0 -0
  142. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/relationships/prompt_with_links.md +0 -0
  143. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/relationships/requirement_with_links.md +0 -0
  144. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/relationships/roadmap_with_links.md +0 -0
  145. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/roadmap/minimal.md +0 -0
  146. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/roadmap/missing_initiatives.md +0 -0
  147. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/roadmap/valid.md +0 -0
  148. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/valid/bullet_requirements.md +0 -0
  149. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/valid/feature.md +0 -0
  150. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/valid/minimal.md +0 -0
  151. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/fixtures/valid/warnings.md +0 -0
  152. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/test_cli.py +0 -0
  153. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/test_decision_metadata.py +0 -0
  154. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/test_design.py +0 -0
  155. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/test_diff.py +0 -0
  156. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/test_improve.py +0 -0
  157. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/test_ingest.py +0 -0
  158. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/test_inspect.py +0 -0
  159. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/test_parser.py +0 -0
  160. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/test_prompt.py +0 -0
  161. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/test_relationships.py +0 -0
  162. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/test_relationships_cmd.py +0 -0
  163. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/test_roadmap.py +0 -0
  164. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/test_schema.py +0 -0
  165. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/test_stats.py +0 -0
  166. {requirements_as_code-0.7.1 → requirements_as_code-0.7.2}/tests/test_validate.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: requirements-as-code
3
- Version: 0.7.1
3
+ Version: 0.7.2
4
4
  Summary: RAC — lint and diff product requirements written in Markdown.
5
5
  Author: tcballard
6
6
  License-Expression: MIT
@@ -0,0 +1,12 @@
1
+ Create a compact handoff for a fresh coding session.
2
+
3
+ Include only:
4
+ - goal
5
+ - approved scope
6
+ - files changed or likely touched
7
+ - architecture constraints
8
+ - tests required
9
+ - commands to run
10
+ - unresolved questions
11
+
12
+ Do not include conversation history.
@@ -0,0 +1,24 @@
1
+ # RAC Agent Instructions
2
+
3
+ Before coding:
4
+ - Refresh from origin/main unless told otherwise.
5
+ - Read the target roadmap file and relevant ADRs.
6
+ - Produce a plan before implementation.
7
+ - Do not expand release scope beyond the roadmap.
8
+
9
+ Release discipline:
10
+ - Work on a feature branch, not main.
11
+ - Do not include Claude attribution in commits.
12
+ - After GitHub merge, refresh local main.
13
+ - Prune merged branches when asked.
14
+
15
+ Architecture:
16
+ - Prefer schema-driven artifact behavior.
17
+ - Do not add artifact-specific validation paths if a generic path can handle it.
18
+ - Keep classification separate from validation.
19
+ - Invalid but recognizable artifacts may still classify as their artifact type.
20
+
21
+ Testing:
22
+ - Add negative boundary tests for each new artifact type.
23
+ - Test that adjacent artifact types do not misclassify as each other.
24
+ - Run pytest before commit.
@@ -0,0 +1,261 @@
1
+ We are preparing a major release for RAC.
2
+
3
+ Your job is to run a release gate review, not to implement changes yet.
4
+
5
+ Context:
6
+ - RAC is a Markdown-first CLI for requirements-as-code.
7
+ - The system supports typed product artifacts such as Requirements, Decisions, Roadmaps, Designs, and related schema/template/improve/inspect/stats behavior.
8
+ - The product goal is deterministic artifact recognition, structural validation, useful CLI feedback, and stable JSON contracts.
9
+ - The release must not drift into project management, UI rendering, semantic scoring, AI interpretation, collaboration workflows, databases, accounts, or web-app behavior unless explicitly approved.
10
+
11
+ Review the current repository against these gates:
12
+
13
+ ## 1. Product scope gate
14
+
15
+ Identify anything in this release that exceeds the intended product boundary.
16
+
17
+ Check for:
18
+ - behavior that interprets artifact quality instead of validating structure
19
+ - workflow/project-management behavior
20
+ - semantic relationship analysis
21
+ - UI/design-token/rendering behavior
22
+ - hidden AI-like inference
23
+ - new concepts not documented in roadmap, ADRs, or release notes
24
+ - CLI behavior that surprises the user
25
+
26
+ Return:
27
+ - PASS / BLOCK
28
+ - exact files or commands involved
29
+ - required scope cuts before release
30
+
31
+ ## 2. Architecture consistency gate
32
+
33
+ Review whether the artifact model is still coherent.
34
+
35
+ Check:
36
+ - whether classification, validation, stats, schema, templates, inspect, and improve use shared artifact metadata where possible
37
+ - whether any artifact has special-case logic that should be generalized
38
+ - whether Roadmap, Design, Decision, and Requirement behavior follow the same architectural pattern
39
+ - whether new code duplicates existing artifact handling
40
+ - whether any module is becoming too large or too coupled
41
+ - whether public contracts are separated from implementation details
42
+
43
+ Return:
44
+ - PASS / BLOCK
45
+ - duplicated paths
46
+ - special cases that should be removed
47
+ - proposed simplification before release
48
+
49
+ ## 3. Duplication and deletion gate
50
+
51
+ This is a hard simplification review.
52
+
53
+ Answer these directly:
54
+
55
+ - What code became obsolete during this release?
56
+ - What can be deleted before release?
57
+ - What logic was copied instead of shared?
58
+ - Which artifact-specific branches can be collapsed into generic artifact-spec-driven behavior?
59
+ - Did any file grow past a size where it should be split?
60
+ - Are there old fixtures, examples, or docs that now contradict the current model?
61
+ - Are there stale branches, stale roadmap files, or stale TODOs that should be cleaned up?
62
+
63
+ Return:
64
+ - required deletions
65
+ - optional cleanup
66
+ - changes that should wait until after release
67
+
68
+ ## 4. CLI contract gate
69
+
70
+ Review every public command affected by this release.
71
+
72
+ Commands to check:
73
+ - rac validate
74
+ - rac diff
75
+ - rac stats
76
+ - rac inspect
77
+ - rac improve
78
+ - rac schema
79
+ - rac ingest, if touched
80
+
81
+ For each affected command, verify:
82
+ - human output is stable and understandable
83
+ - JSON output is stable and documented
84
+ - exit codes are intentional
85
+ - invalid input behavior is clear
86
+ - warnings vs errors are consistent
87
+ - unsupported artifact behavior is explicit
88
+ - examples in README/docs still work
89
+
90
+ Return a table:
91
+
92
+ Command | Changed? | Human output ok? | JSON ok? | Exit codes ok? | Docs ok? | Blockers
93
+
94
+ ## 5. Classification boundary gate
95
+
96
+ Review artifact classification behavior.
97
+
98
+ Check:
99
+ - Requirements do not classify as Design
100
+ - Designs do not classify as Requirements
101
+ - Roadmaps classify by approved structure, not loose title matching alone except where explicitly intended
102
+ - UI/design-themed titles alone do not classify as Design
103
+ - invalid but recognizable artifacts classify correctly, then fail validation separately
104
+ - incomplete artifacts behave according to the spec
105
+ - mixed documents do not produce surprising classifications
106
+ - negative fixtures exist for adjacent artifact types
107
+
108
+ Return:
109
+ - PASS / BLOCK
110
+ - missing boundary tests
111
+ - risky classification rules
112
+ - recommended fixture additions
113
+
114
+ ## 6. Validation and schema gate
115
+
116
+ Check that validation behavior and schema output agree.
117
+
118
+ Verify:
119
+ - required sections match the artifact specs
120
+ - recommended and optional sections are consistent across schema, templates, validation, and docs
121
+ - metadata vocabularies are enforced consistently
122
+ - missing required sections produce clear errors
123
+ - invalid metadata values produce clear errors
124
+ - schema JSON is stable and documented
125
+ - template output follows canonical section order
126
+
127
+ Return:
128
+ - mismatches
129
+ - missing tests
130
+ - release blockers
131
+
132
+ ## 7. Test and verification gate
133
+
134
+ Do not accept “tests pass” as enough.
135
+
136
+ Run or identify the exact commands needed to verify the release.
137
+
138
+ Check:
139
+ - unit tests for changed behavior
140
+ - CLI smoke tests
141
+ - classification boundary tests
142
+ - negative fixtures
143
+ - JSON output snapshots or equivalent assertions
144
+ - docs examples manually or automatically verified
145
+ - packaging/build check
146
+ - import check from a clean environment, if practical
147
+
148
+ Return:
149
+ - exact commands run
150
+ - exact commands still needed
151
+ - failures
152
+ - missing test files
153
+ - blockers
154
+
155
+ If tests are missing for new behavior, mark the release BLOCKED.
156
+
157
+ ## 8. Documentation gate
158
+
159
+ Review documentation from a new user’s point of view.
160
+
161
+ Check:
162
+ - README reflects current commands
163
+ - artifact docs match implementation
164
+ - examples use current output
165
+ - release notes or changelog entry exists
166
+ - ADRs are not contradicted
167
+ - roadmap item is updated or marked complete
168
+ - install/publish instructions are still accurate
169
+ - known limitations are explicit
170
+
171
+ Return:
172
+ - stale docs
173
+ - missing docs
174
+ - docs that overpromise behavior
175
+
176
+ ## 9. Release hygiene gate
177
+
178
+ Check repository and release state.
179
+
180
+ Verify:
181
+ - working tree is clean
182
+ - release branch is based on current origin/main
183
+ - merged branches are pruned or listed for pruning
184
+ - version number is updated consistently
185
+ - package metadata is correct
186
+ - no generated Claude attribution appears in commits, PR text, release notes, or docs
187
+ - CI is green
188
+ - build artifacts are not accidentally committed
189
+ - no credentials or local paths leaked
190
+
191
+ Return:
192
+ - PASS / BLOCK
193
+ - exact commands to confirm state
194
+ - required cleanup
195
+
196
+ ## 10. Backward compatibility and migration gate
197
+
198
+ Identify anything that could break existing users.
199
+
200
+ Check:
201
+ - command names
202
+ - arguments and flags
203
+ - JSON field names
204
+ - exit codes
205
+ - artifact classification behavior
206
+ - validation strictness
207
+ - package extras
208
+ - import paths
209
+ - documented examples
210
+
211
+ Return:
212
+ - breaking changes
213
+ - whether each breaking change is intentional
214
+ - migration note required
215
+ - release blocker if undocumented
216
+
217
+ ## Output format
218
+
219
+ Return the review in this structure:
220
+
221
+ # Major Release Gate Review
222
+
223
+ ## Decision
224
+ PASS or BLOCK
225
+
226
+ ## Release blockers
227
+ List only issues that must be fixed before release.
228
+
229
+ ## Required simplifications
230
+ List duplication, deletion, or extraction work required before release.
231
+
232
+ ## Test evidence
233
+ List commands run and results. If not run, say NOT RUN.
234
+
235
+ ## Product scope issues
236
+ List any behavior that exceeds the intended boundary.
237
+
238
+ ## Architecture issues
239
+ List duplicated or inconsistent implementation paths.
240
+
241
+ ## CLI contract issues
242
+ List command/output/JSON/exit-code problems.
243
+
244
+ ## Documentation issues
245
+ List stale, missing, or overpromising docs.
246
+
247
+ ## Release hygiene issues
248
+ List branch/version/CI/commit/publishing concerns.
249
+
250
+ ## Safe to defer
251
+ List cleanup that is real but not release-blocking.
252
+
253
+ ## Exact next actions
254
+ Give a short checklist of the next changes to make.
255
+
256
+ Important rules:
257
+ - Do not implement anything in this pass.
258
+ - Do not invent test results. If you did not run a command, mark it NOT RUN.
259
+ - Cite exact files and commands.
260
+ - Treat missing tests for new public behavior as a blocker.
261
+ - Treat duplicated artifact-specific
@@ -0,0 +1,23 @@
1
+ # Minor Release Gate
2
+
3
+ Before completing any 0.x.n release:
4
+
5
+ ## Duplication
6
+ - Did this release add artifact-specific classification logic?
7
+ - Did it duplicate validation, schema, template, stats, or improve behavior?
8
+ - Can new behavior be expressed through ArtifactSpec instead?
9
+ - Are there two sources of truth for sections, metadata, or guidance?
10
+
11
+ ## Simplification
12
+ - What code became obsolete?
13
+ - What branch or special case can be removed?
14
+ - Did any file grow past the agreed limit?
15
+ - Should a helper be extracted?
16
+ - Did this release increase the number of artifact-specific conditionals?
17
+
18
+ ## Verification
19
+ - Are there negative classification tests?
20
+ - Are adjacent artifact types tested against each other?
21
+ - Are incomplete-but-recognizable artifacts tested?
22
+ - Are CLI human and JSON outputs tested?
23
+ - Was pytest run before commit?
@@ -0,0 +1,23 @@
1
+ We are working on RAC, a Python CLI for requirements-as-code.
2
+
3
+ RAC models product-management Markdown artifacts as deterministic, typed artifacts.
4
+ Current artifact families include Requirements, Decisions, Roadmaps, Prompts, and Design.
5
+
6
+ Core principles:
7
+ - Markdown-first.
8
+ - Deterministic classification.
9
+ - Structural validation, not semantic scoring unless explicitly planned.
10
+ - CLI contracts matter: human output, JSON output, exit codes, and templates must be specified.
11
+ - Version numbers are scope fences.
12
+ - Prefer schema/artifact-spec-driven behavior over artifact-specific branches.
13
+ - Invalid but recognizable artifacts may still classify as their artifact type, then fail validation.
14
+
15
+ Before coding:
16
+ 1. Refresh from `origin/main`.
17
+ 2. Confirm branch state.
18
+ 3. Read the relevant roadmap item.
19
+ 4. Check against ADRs.
20
+ 5. Produce an implementation contract.
21
+ 6. Wait for approval.
22
+
23
+ Do not implement until I approve the plan.
@@ -50,6 +50,12 @@ class ArtifactSpec:
50
50
  # matching, so synonyms contribute to confidence. Matching is deterministic
51
51
  # (dict lookup) and case-insensitive (headings are normalized first).
52
52
  synonyms: dict[str, str] = field(default_factory=dict)
53
+ # Canonical-identifier section (v0.7.2 relationship validation): the normalized
54
+ # section name whose value is this artifact type's identifier, consulted by
55
+ # ``rac.relationships.artifact_identifier`` before falling back to the filename
56
+ # stem. A forward hook — no spec sets it today; relationship resolution works
57
+ # from the ``## ID`` section and filename stem until a type opts in.
58
+ id_field: str | None = None
53
59
 
54
60
  @property
55
61
  def expected(self) -> tuple[str, ...]:
@@ -8,13 +8,14 @@ Commands:
8
8
  rac inspect <file.md | -> [--json]
9
9
  rac improve <file.md | -> [--json | --template]
10
10
  rac schema [--list] [type] [--json | --template]
11
- rac relationships <dir | file.md> [--json] [--top-level]
11
+ rac relationships <dir | file.md> [--validate] [--json] [--top-level]
12
12
 
13
13
  Exit codes:
14
14
  0 success (incl. inspect/improve reporting Unknown; relationships found or
15
- not)
15
+ not; --validate with all references resolved)
16
16
  1 validate: errors found; stats: no valid known artifacts; ingest:
17
- conversion failed
17
+ conversion failed; relationships --validate: broken/ambiguous/self
18
+ references or duplicate identifiers found
18
19
  2 usage / IO error (file not found, not a directory, unsupported type,
19
20
  refuse-to-overwrite)
20
21
  """
@@ -36,6 +37,8 @@ from .parser import parse, parse_file
36
37
  from .relationships import (
37
38
  build_relationship_report,
38
39
  build_relationship_report_file,
40
+ validate_relationships,
41
+ validate_relationships_file,
39
42
  )
40
43
  from .schema import available_schemas, schema_reference
41
44
  from .stats import collect_stats
@@ -244,10 +247,10 @@ def cmd_schema(args: argparse.Namespace) -> int:
244
247
 
245
248
  def cmd_relationships(args: argparse.Namespace) -> int:
246
249
  path = Path(args.path)
250
+ # --recursive is the default; --top-level disables it. If both are given,
251
+ # --top-level wins (mirrors `rac inspect`).
247
252
  if path.is_dir():
248
- # --recursive is the default; --top-level disables it. If both are given,
249
- # --top-level wins (mirrors `rac inspect`).
250
- report = build_relationship_report(args.path, recursive=not args.top_level)
253
+ is_dir = True
251
254
  elif path.is_file():
252
255
  if path.suffix.lower() not in (".md", ".markdown"):
253
256
  print(
@@ -256,11 +259,28 @@ def cmd_relationships(args: argparse.Namespace) -> int:
256
259
  file=sys.stderr,
257
260
  )
258
261
  raise SystemExit(EXIT_USAGE)
259
- report = build_relationship_report_file(args.path)
262
+ is_dir = False
260
263
  else:
261
264
  print(f"rac: path not found: {args.path}", file=sys.stderr)
262
265
  raise SystemExit(EXIT_USAGE)
263
266
 
267
+ if args.validate:
268
+ if is_dir:
269
+ report = validate_relationships(args.path, recursive=not args.top_level)
270
+ else:
271
+ report = validate_relationships_file(args.path)
272
+ if args.json:
273
+ print(outputs.render_relationship_validation_json(report))
274
+ else:
275
+ print(outputs.render_relationship_validation_human(report))
276
+ # Validation-style exit codes (REQ-007): 0 when everything resolves, 1 when
277
+ # any issue is found, 2 (above) for usage errors.
278
+ return EXIT_OK if report.ok else EXIT_VALIDATION_FAILED
279
+
280
+ if is_dir:
281
+ report = build_relationship_report(args.path, recursive=not args.top_level)
282
+ else:
283
+ report = build_relationship_report_file(args.path)
264
284
  if args.json:
265
285
  print(outputs.render_relationships_json(report))
266
286
  else:
@@ -432,6 +452,12 @@ def build_parser() -> argparse.ArgumentParser:
432
452
  p_relationships.add_argument(
433
453
  "--json", action="store_true", help="Emit JSON instead of human-readable text."
434
454
  )
455
+ p_relationships.add_argument(
456
+ "--validate",
457
+ action="store_true",
458
+ help="Resolve references against discovered artifacts; exit 1 if any are "
459
+ "broken, ambiguous, self-referencing, or have duplicate identifiers.",
460
+ )
435
461
  p_relationships.add_argument(
436
462
  "--top-level",
437
463
  action="store_true",
@@ -16,7 +16,14 @@ from .improve import ImprovementResult
16
16
  from .ingest import IngestResult
17
17
  from .inspect import DirectoryInspection, InspectionResult
18
18
  from .models import Diff, Issue, Product
19
- from .relationships import RelationshipReport
19
+ from .relationships import (
20
+ ISSUE_DUPLICATE_IDENTIFIER,
21
+ ISSUE_SELF_REFERENCE,
22
+ ISSUE_TARGET_AMBIGUOUS,
23
+ ISSUE_TARGET_NOT_FOUND,
24
+ RelationshipReport,
25
+ RelationshipValidation,
26
+ )
20
27
  from .schema import SchemaReference, template_sections
21
28
  from .stats import PortfolioStats
22
29
 
@@ -679,6 +686,63 @@ def render_relationships_json(report: RelationshipReport) -> str:
679
686
  return json.dumps(payload, indent=2)
680
687
 
681
688
 
689
+ # --- relationship validation -------------------------------------------------
690
+
691
+ # Suffix shown after a broken reference, per issue code.
692
+ _REF_ISSUE_SUFFIX = {
693
+ ISSUE_TARGET_NOT_FOUND: "not found",
694
+ ISSUE_TARGET_AMBIGUOUS: "ambiguous",
695
+ ISSUE_SELF_REFERENCE: "self-reference",
696
+ }
697
+
698
+
699
+ def render_relationship_validation_human(report: RelationshipValidation) -> str:
700
+ lines = [
701
+ _bold("Relationship Validation"),
702
+ "",
703
+ f"Relationships Checked: {report.relationships_checked}",
704
+ f"Validation Issues: {report.validation_issues}",
705
+ ]
706
+
707
+ duplicates = [i for i in report.issues if i.code == ISSUE_DUPLICATE_IDENTIFIER]
708
+ references = [i for i in report.issues if i.code != ISSUE_DUPLICATE_IDENTIFIER]
709
+
710
+ if duplicates:
711
+ lines += ["", _bold("Duplicate Identifiers")]
712
+ for issue in duplicates:
713
+ count = len(issue.paths or [])
714
+ lines.append(_red(f"✗ {issue.identifier} ({count} files)"))
715
+ lines.extend(f" - {p}" for p in issue.paths or [])
716
+
717
+ if references:
718
+ lines += ["", _bold("Broken Relationships")]
719
+ current_source = None
720
+ current_section = None
721
+ for issue in references:
722
+ if issue.source_path != current_source:
723
+ current_source = issue.source_path
724
+ current_section = None
725
+ lines += ["", issue.source_path or "<input>"]
726
+ if issue.relationship != current_section:
727
+ current_section = issue.relationship
728
+ lines.append(f" {_relationship_label(issue.relationship or '')}:")
729
+ suffix = _REF_ISSUE_SUFFIX.get(issue.code, issue.code)
730
+ lines.append(_red(f" ✗ {issue.target} {suffix}"))
731
+
732
+ return "\n".join(lines)
733
+
734
+
735
+ def render_relationship_validation_json(report: RelationshipValidation) -> str:
736
+ payload = {
737
+ "directory": report.directory,
738
+ "recursive": report.recursive,
739
+ "relationships_checked": report.relationships_checked,
740
+ "validation_issues": report.validation_issues,
741
+ "issues": [issue.to_dict() for issue in report.issues],
742
+ }
743
+ return json.dumps(payload, indent=2)
744
+
745
+
682
746
  # --- ingest ------------------------------------------------------------------
683
747
 
684
748