@garygentry/feature-forge 0.2.14 → 0.3.0

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 (227) hide show
  1. package/README.md +6 -3
  2. package/adapters/GENERATION-REPORT.md +20 -0
  3. package/adapters/claude/.feature-forge-bundle.json +1 -1
  4. package/adapters/claude/references/forge-config-schema.json +2 -2
  5. package/adapters/claude/scripts/forge-root.sh +47 -3
  6. package/adapters/claude/scripts/forge-session.py +30 -8
  7. package/adapters/claude/skills/forge-4-backlog/references/forge-config-schema.json +2 -2
  8. package/adapters/claude/skills/forge-5-loop/references/forge-config-schema.json +2 -2
  9. package/adapters/claude/skills/forge-guide/references/forge-config-schema.json +2 -2
  10. package/adapters/codex/.feature-forge-bundle.json +1 -1
  11. package/adapters/codex/references/forge-config-schema.json +2 -2
  12. package/adapters/codex/scripts/forge-root.sh +47 -3
  13. package/adapters/codex/scripts/forge-session.py +30 -8
  14. package/adapters/codex/skills/forge-4-backlog/references/forge-config-schema.json +2 -2
  15. package/adapters/codex/skills/forge-5-loop/references/forge-config-schema.json +2 -2
  16. package/adapters/codex/skills/forge-guide/references/forge-config-schema.json +2 -2
  17. package/adapters/copilot/.feature-forge-bundle.json +1 -1
  18. package/adapters/copilot/references/forge-config-schema.json +2 -2
  19. package/adapters/copilot/scripts/forge-root.sh +47 -3
  20. package/adapters/copilot/scripts/forge-session.py +30 -8
  21. package/adapters/copilot/skills/forge-4-backlog/references/forge-config-schema.json +2 -2
  22. package/adapters/copilot/skills/forge-5-loop/references/forge-config-schema.json +2 -2
  23. package/adapters/copilot/skills/forge-guide/references/forge-config-schema.json +2 -2
  24. package/adapters/cursor/.feature-forge-bundle.json +1 -1
  25. package/adapters/cursor/references/forge-config-schema.json +2 -2
  26. package/adapters/cursor/scripts/forge-root.sh +47 -3
  27. package/adapters/cursor/scripts/forge-session.py +30 -8
  28. package/adapters/cursor/skills/forge-4-backlog/references/forge-config-schema.json +2 -2
  29. package/adapters/cursor/skills/forge-5-loop/references/forge-config-schema.json +2 -2
  30. package/adapters/cursor/skills/forge-guide/references/forge-config-schema.json +2 -2
  31. package/adapters/gemini/.feature-forge-bundle.json +1 -1
  32. package/adapters/gemini/gemini-extension.json +1 -1
  33. package/adapters/gemini/references/forge-config-schema.json +2 -2
  34. package/adapters/gemini/scripts/forge-root.sh +47 -3
  35. package/adapters/gemini/scripts/forge-session.py +30 -8
  36. package/adapters/gemini/skills/forge-4-backlog/references/forge-config-schema.json +2 -2
  37. package/adapters/gemini/skills/forge-5-loop/references/forge-config-schema.json +2 -2
  38. package/adapters/gemini/skills/forge-guide/references/forge-config-schema.json +2 -2
  39. package/adapters/pi/.feature-forge-bundle.json +6 -0
  40. package/adapters/pi/agents/forge-researcher.md +139 -0
  41. package/adapters/pi/agents/forge-spec-writer.md +116 -0
  42. package/adapters/pi/agents/forge-verifier.md +126 -0
  43. package/adapters/pi/extensions/ask-user-question/LICENSE +21 -0
  44. package/adapters/pi/extensions/ask-user-question/README.md +91 -0
  45. package/adapters/pi/extensions/ask-user-question/ask-user-question.ts +298 -0
  46. package/adapters/pi/extensions/ask-user-question/config.ts +78 -0
  47. package/adapters/pi/extensions/ask-user-question/events.ts +57 -0
  48. package/adapters/pi/extensions/ask-user-question/index.ts +61 -0
  49. package/adapters/pi/extensions/ask-user-question/locales/de.json +27 -0
  50. package/adapters/pi/extensions/ask-user-question/locales/en.json +27 -0
  51. package/adapters/pi/extensions/ask-user-question/locales/es.json +27 -0
  52. package/adapters/pi/extensions/ask-user-question/locales/fr.json +27 -0
  53. package/adapters/pi/extensions/ask-user-question/locales/pt-BR.json +27 -0
  54. package/adapters/pi/extensions/ask-user-question/locales/pt.json +27 -0
  55. package/adapters/pi/extensions/ask-user-question/locales/ru.json +27 -0
  56. package/adapters/pi/extensions/ask-user-question/locales/uk.json +27 -0
  57. package/adapters/pi/extensions/ask-user-question/locales/zh.json +29 -0
  58. package/adapters/pi/extensions/ask-user-question/reconcile.ts +49 -0
  59. package/adapters/pi/extensions/ask-user-question/rpc-fallback.ts +168 -0
  60. package/adapters/pi/extensions/ask-user-question/state/build-questionnaire.ts +302 -0
  61. package/adapters/pi/extensions/ask-user-question/state/i18n-bridge.ts +53 -0
  62. package/adapters/pi/extensions/ask-user-question/state/key-router.ts +277 -0
  63. package/adapters/pi/extensions/ask-user-question/state/questionnaire-session.ts +234 -0
  64. package/adapters/pi/extensions/ask-user-question/state/row-intent.ts +145 -0
  65. package/adapters/pi/extensions/ask-user-question/state/selectors/contract.ts +26 -0
  66. package/adapters/pi/extensions/ask-user-question/state/selectors/derivations.ts +42 -0
  67. package/adapters/pi/extensions/ask-user-question/state/selectors/focus.ts +19 -0
  68. package/adapters/pi/extensions/ask-user-question/state/selectors/projections.ts +101 -0
  69. package/adapters/pi/extensions/ask-user-question/state/state-reducer.ts +292 -0
  70. package/adapters/pi/extensions/ask-user-question/state/state.ts +55 -0
  71. package/adapters/pi/extensions/ask-user-question/tool/format-answer.ts +31 -0
  72. package/adapters/pi/extensions/ask-user-question/tool/response-envelope.ts +49 -0
  73. package/adapters/pi/extensions/ask-user-question/tool/types.ts +147 -0
  74. package/adapters/pi/extensions/ask-user-question/tool/validate-questionnaire.ts +58 -0
  75. package/adapters/pi/extensions/ask-user-question/vendor-config-shim.ts +65 -0
  76. package/adapters/pi/extensions/ask-user-question/view/component-binding.ts +47 -0
  77. package/adapters/pi/extensions/ask-user-question/view/components/inline-input.ts +98 -0
  78. package/adapters/pi/extensions/ask-user-question/view/components/multi-select-view.ts +193 -0
  79. package/adapters/pi/extensions/ask-user-question/view/components/option-list-view.ts +70 -0
  80. package/adapters/pi/extensions/ask-user-question/view/components/preview/markdown-content-cache.ts +79 -0
  81. package/adapters/pi/extensions/ask-user-question/view/components/preview/preview-block-renderer.ts +111 -0
  82. package/adapters/pi/extensions/ask-user-question/view/components/preview/preview-box-renderer.ts +88 -0
  83. package/adapters/pi/extensions/ask-user-question/view/components/preview/preview-layout-decider.ts +202 -0
  84. package/adapters/pi/extensions/ask-user-question/view/components/preview/preview-pane.ts +228 -0
  85. package/adapters/pi/extensions/ask-user-question/view/components/submit-picker.ts +67 -0
  86. package/adapters/pi/extensions/ask-user-question/view/components/tab-bar.ts +59 -0
  87. package/adapters/pi/extensions/ask-user-question/view/components/wrapping-select.ts +293 -0
  88. package/adapters/pi/extensions/ask-user-question/view/dialog-builder.ts +224 -0
  89. package/adapters/pi/extensions/ask-user-question/view/props-adapter.ts +125 -0
  90. package/adapters/pi/extensions/ask-user-question/view/stateful-view.ts +26 -0
  91. package/adapters/pi/extensions/ask-user-question/view/tab-components.ts +18 -0
  92. package/adapters/pi/extensions/ask-user-question/view/tab-content-strategy.ts +252 -0
  93. package/adapters/pi/package.json +26 -0
  94. package/adapters/pi/references/epic-manifest-schema.json +125 -0
  95. package/adapters/pi/references/forge-config-schema.json +236 -0
  96. package/adapters/pi/references/pipeline-state-schema.json +191 -0
  97. package/adapters/pi/references/portable-root.md +71 -0
  98. package/adapters/pi/references/process-overview.md +143 -0
  99. package/adapters/pi/references/ralph-loop-contract.md +221 -0
  100. package/adapters/pi/references/shared-conventions.md +295 -0
  101. package/adapters/pi/references/skill-frontmatter.schema.json +17 -0
  102. package/adapters/pi/references/stack-resolution.md +54 -0
  103. package/adapters/pi/references/stacks/_generic.md +111 -0
  104. package/adapters/pi/references/stacks/go.md +157 -0
  105. package/adapters/pi/references/stacks/python.md +184 -0
  106. package/adapters/pi/references/stacks/rust.md +170 -0
  107. package/adapters/pi/references/stacks/typescript.md +134 -0
  108. package/adapters/pi/references/stage-exit-protocol.md +258 -0
  109. package/adapters/pi/references/templates/specs-hygiene/AGENTS.md +32 -0
  110. package/adapters/pi/references/templates/specs-hygiene/CLAUDE.md +31 -0
  111. package/adapters/pi/references/vendor-construct-inventory.md +50 -0
  112. package/adapters/pi/scripts/epic-manifest.py +1694 -0
  113. package/adapters/pi/scripts/forge-bootstrap.py +1070 -0
  114. package/adapters/pi/scripts/forge-init.sh +58 -0
  115. package/adapters/pi/scripts/forge-root.sh +179 -0
  116. package/adapters/pi/scripts/forge-session.py +1888 -0
  117. package/adapters/pi/scripts/validate-traceability.py +150 -0
  118. package/adapters/pi/skills/forge/SKILL.md +243 -0
  119. package/adapters/pi/skills/forge/references/pipeline-state-schema.json +191 -0
  120. package/adapters/pi/skills/forge/references/process-overview.md +143 -0
  121. package/adapters/pi/skills/forge/references/shared-conventions.md +295 -0
  122. package/adapters/pi/skills/forge/references/stage-exit-protocol.md +258 -0
  123. package/adapters/pi/skills/forge-0-epic/SKILL.md +308 -0
  124. package/adapters/pi/skills/forge-0-epic/references/edit-mode.md +266 -0
  125. package/adapters/pi/skills/forge-0-epic/references/epic-manifest-subcommands.md +75 -0
  126. package/adapters/pi/skills/forge-0-epic/references/pipeline-state-schema.json +191 -0
  127. package/adapters/pi/skills/forge-0-epic/references/portable-root.md +71 -0
  128. package/adapters/pi/skills/forge-0-epic/references/shared-conventions.md +295 -0
  129. package/adapters/pi/skills/forge-0-epic/references/stage-exit-protocol.md +258 -0
  130. package/adapters/pi/skills/forge-1-prd/SKILL.md +164 -0
  131. package/adapters/pi/skills/forge-1-prd/references/pipeline-state-schema.json +191 -0
  132. package/adapters/pi/skills/forge-1-prd/references/prd-template.md +106 -0
  133. package/adapters/pi/skills/forge-1-prd/references/shared-conventions.md +295 -0
  134. package/adapters/pi/skills/forge-1-prd/references/stage-exit-protocol.md +258 -0
  135. package/adapters/pi/skills/forge-2-tech/SKILL.md +225 -0
  136. package/adapters/pi/skills/forge-2-tech/references/pipeline-state-schema.json +191 -0
  137. package/adapters/pi/skills/forge-2-tech/references/shared-conventions.md +295 -0
  138. package/adapters/pi/skills/forge-2-tech/references/stack-discovery-checklist.md +95 -0
  139. package/adapters/pi/skills/forge-2-tech/references/stack-resolution.md +54 -0
  140. package/adapters/pi/skills/forge-2-tech/references/stacks/_generic.md +111 -0
  141. package/adapters/pi/skills/forge-2-tech/references/stacks/go.md +157 -0
  142. package/adapters/pi/skills/forge-2-tech/references/stacks/python.md +184 -0
  143. package/adapters/pi/skills/forge-2-tech/references/stacks/rust.md +170 -0
  144. package/adapters/pi/skills/forge-2-tech/references/stacks/typescript.md +134 -0
  145. package/adapters/pi/skills/forge-2-tech/references/stage-exit-protocol.md +258 -0
  146. package/adapters/pi/skills/forge-3-specs/SKILL.md +178 -0
  147. package/adapters/pi/skills/forge-3-specs/references/pipeline-state-schema.json +191 -0
  148. package/adapters/pi/skills/forge-3-specs/references/shared-conventions.md +295 -0
  149. package/adapters/pi/skills/forge-3-specs/references/spec-archetypes.md +106 -0
  150. package/adapters/pi/skills/forge-3-specs/references/spec-examples.md +71 -0
  151. package/adapters/pi/skills/forge-3-specs/references/stacks/_generic.md +111 -0
  152. package/adapters/pi/skills/forge-3-specs/references/stacks/go.md +157 -0
  153. package/adapters/pi/skills/forge-3-specs/references/stacks/python.md +184 -0
  154. package/adapters/pi/skills/forge-3-specs/references/stacks/rust.md +170 -0
  155. package/adapters/pi/skills/forge-3-specs/references/stacks/typescript.md +134 -0
  156. package/adapters/pi/skills/forge-3-specs/references/stage-exit-protocol.md +258 -0
  157. package/adapters/pi/skills/forge-4-backlog/SKILL.md +175 -0
  158. package/adapters/pi/skills/forge-4-backlog/references/forge-config-schema.json +236 -0
  159. package/adapters/pi/skills/forge-4-backlog/references/pipeline-state-schema.json +191 -0
  160. package/adapters/pi/skills/forge-4-backlog/references/shared-conventions.md +295 -0
  161. package/adapters/pi/skills/forge-4-backlog/references/stage-exit-protocol.md +258 -0
  162. package/adapters/pi/skills/forge-5-loop/SKILL.md +314 -0
  163. package/adapters/pi/skills/forge-5-loop/references/forge-config-schema.json +236 -0
  164. package/adapters/pi/skills/forge-5-loop/references/ralph-loop-contract.md +221 -0
  165. package/adapters/pi/skills/forge-5-loop/references/result-reporting.md +85 -0
  166. package/adapters/pi/skills/forge-5-loop/references/runner-contract.md +341 -0
  167. package/adapters/pi/skills/forge-5-loop/references/shared-conventions.md +295 -0
  168. package/adapters/pi/skills/forge-5-loop/references/stage-exit-protocol.md +258 -0
  169. package/adapters/pi/skills/forge-6-docs/SKILL.md +202 -0
  170. package/adapters/pi/skills/forge-6-docs/references/doc-conventions.md +126 -0
  171. package/adapters/pi/skills/forge-6-docs/references/pipeline-state-schema.json +191 -0
  172. package/adapters/pi/skills/forge-6-docs/references/shared-conventions.md +295 -0
  173. package/adapters/pi/skills/forge-bootstrap/SKILL.md +250 -0
  174. package/adapters/pi/skills/forge-bootstrap/references/templates/ci/github-actions.yml +12 -0
  175. package/adapters/pi/skills/forge-bootstrap/references/templates/generic/run.sh +3 -0
  176. package/adapters/pi/skills/forge-bootstrap/references/templates/generic/test.sh +13 -0
  177. package/adapters/pi/skills/forge-bootstrap/references/templates/go/go.mod +3 -0
  178. package/adapters/pi/skills/forge-bootstrap/references/templates/go/main.go +12 -0
  179. package/adapters/pi/skills/forge-bootstrap/references/templates/go/main_test.go +11 -0
  180. package/adapters/pi/skills/forge-bootstrap/references/templates/hygiene/AGENTS.md +35 -0
  181. package/adapters/pi/skills/forge-bootstrap/references/templates/hygiene/CLAUDE.md +36 -0
  182. package/adapters/pi/skills/forge-bootstrap/references/templates/hygiene/README.md +11 -0
  183. package/adapters/pi/skills/forge-bootstrap/references/templates/licenses/Apache-2.0/LICENSE +198 -0
  184. package/adapters/pi/skills/forge-bootstrap/references/templates/licenses/MIT/LICENSE +21 -0
  185. package/adapters/pi/skills/forge-bootstrap/references/templates/python/pyproject.toml +24 -0
  186. package/adapters/pi/skills/forge-bootstrap/references/templates/python/src/{{PKG}}/__init__.py +5 -0
  187. package/adapters/pi/skills/forge-bootstrap/references/templates/python/src/{{PKG}}/main.py +13 -0
  188. package/adapters/pi/skills/forge-bootstrap/references/templates/python/tests/test_smoke.py +8 -0
  189. package/adapters/pi/skills/forge-bootstrap/references/templates/rust/Cargo.toml +15 -0
  190. package/adapters/pi/skills/forge-bootstrap/references/templates/rust/src/lib.rs +7 -0
  191. package/adapters/pi/skills/forge-bootstrap/references/templates/rust/src/main.rs +5 -0
  192. package/adapters/pi/skills/forge-bootstrap/references/templates/rust/tests/smoke.rs +6 -0
  193. package/adapters/pi/skills/forge-bootstrap/references/templates/typescript/package.json +15 -0
  194. package/adapters/pi/skills/forge-bootstrap/references/templates/typescript/src/index.ts +4 -0
  195. package/adapters/pi/skills/forge-bootstrap/references/templates/typescript/test/smoke.test.ts +6 -0
  196. package/adapters/pi/skills/forge-bootstrap/references/templates/typescript/tsconfig.json +14 -0
  197. package/adapters/pi/skills/forge-fix/SKILL.md +98 -0
  198. package/adapters/pi/skills/forge-fix/references/shared-conventions.md +295 -0
  199. package/adapters/pi/skills/forge-fix/references/stage-exit-protocol.md +258 -0
  200. package/adapters/pi/skills/forge-guide/SKILL.md +192 -0
  201. package/adapters/pi/skills/forge-guide/references/forge-config-schema.json +236 -0
  202. package/adapters/pi/skills/forge-guide/references/process-overview.md +143 -0
  203. package/adapters/pi/skills/forge-guide/references/ralph-loop-contract.md +221 -0
  204. package/adapters/pi/skills/forge-guide/references/shared-conventions.md +295 -0
  205. package/adapters/pi/skills/forge-guide/references/stack-resolution.md +54 -0
  206. package/adapters/pi/skills/forge-guide/references/stacks/_generic.md +111 -0
  207. package/adapters/pi/skills/forge-guide/references/stacks/go.md +157 -0
  208. package/adapters/pi/skills/forge-guide/references/stacks/python.md +184 -0
  209. package/adapters/pi/skills/forge-guide/references/stacks/rust.md +170 -0
  210. package/adapters/pi/skills/forge-guide/references/stacks/typescript.md +134 -0
  211. package/adapters/pi/skills/forge-init/SKILL.md +72 -0
  212. package/adapters/pi/skills/forge-verify/SKILL.md +273 -0
  213. package/adapters/pi/skills/forge-verify/references/pipeline-state-schema.json +191 -0
  214. package/adapters/pi/skills/forge-verify/references/shared-conventions.md +295 -0
  215. package/adapters/pi/skills/forge-verify/references/verification-checklists.md +477 -0
  216. package/dist/agent-targets.d.ts +1 -1
  217. package/dist/agent-targets.js +23 -3
  218. package/dist/detect.d.ts +1 -1
  219. package/dist/detect.js +2 -1
  220. package/dist/manifest.d.ts +1 -1
  221. package/dist/manifest.js +2 -2
  222. package/dist/placements.js +5 -1
  223. package/dist/rauf.d.ts +4 -4
  224. package/dist/rauf.js +3 -3
  225. package/dist/types.d.ts +31 -6
  226. package/dist/types.js +6 -3
  227. package/package.json +14 -3
@@ -0,0 +1,477 @@
1
+ # Verification Checklists
2
+
3
+ Detailed checklists for each verification mode. Execute EVERY check — do not skip.
4
+
5
+ > **Stack-specific details:** When a stack profile exists at `references/stacks/{stack}.md`, load it alongside this checklist for language-specific check criteria (e.g., what "valid syntax" means, what the type check command is, how module exports work).
6
+
7
+ ## PRD Mode Checklist
8
+
9
+ ### Completeness
10
+ - [ ] **CHECK-P01**: All template sections from `references/prd-template.md` are populated
11
+ - [ ] **CHECK-P02**: No TBD or TODO placeholders remain in the document
12
+ - [ ] **CHECK-P03**: Out-of-scope section exists and is specific (not just "everything else")
13
+ - [ ] **CHECK-P04**: Open questions section contains only actionable items (not vague concerns)
14
+ - [ ] **CHECK-P05**: Success criteria are measurable and verifiable
15
+
16
+ ### Requirement Quality
17
+ - [ ] **CHECK-P06**: Every requirement has a unique ID (REQ-XXX-NN format)
18
+ - [ ] **CHECK-P07**: Every requirement has a priority assigned (P0/P1/P2)
19
+ - [ ] **CHECK-P08**: Every requirement is testable/verifiable — could you write an acceptance test for it?
20
+ - [ ] **CHECK-P09**: No requirements contain technology decisions (specific libraries, frameworks, or implementation choices) unless clearly labeled as constraints with justification
21
+ - [ ] **CHECK-P10**: User stories cover all identified actors/personas
22
+
23
+ ### Non-Functional Requirements
24
+ - [ ] **CHECK-P11**: Non-functional requirements are quantified where applicable (latency targets, uptime SLAs, throughput minimums)
25
+ - [ ] **CHECK-P12**: Security requirements are explicit, not assumed
26
+ - [ ] **CHECK-P13**: Constraints section distinguishes mandates (must) from preferences (should/nice-to-have)
27
+
28
+ ### Open-Ended Analysis
29
+ - [ ] **CHECK-P14**: Are there implicit requirements that should be made explicit? (e.g., assumptions about authentication, authorization, data retention)
30
+ - [ ] **CHECK-P15**: Are there requirement conflicts or tensions? (e.g., performance vs. completeness, simplicity vs. flexibility)
31
+
32
+ ## Tech-Spec Mode Checklist
33
+
34
+ ### Requirement Traceability
35
+ - [ ] **CHECK-T01**: Every tech decision traces to at least one PRD requirement (REQ-XXX-NN)
36
+ - [ ] **CHECK-T02**: No tech decisions contradict PRD constraints
37
+ - [ ] **CHECK-T03**: Every P0 PRD requirement has a corresponding tech decision or is explicitly deferred with rationale
38
+
39
+ ### Integration Analysis
40
+ - [ ] **CHECK-T04**: Integration analysis section is complete — all packages identified
41
+ - [ ] **CHECK-T05**: Import paths and function signatures are verified against actual source code
42
+ - [ ] **CHECK-T06**: For each integration point: shared types/contracts are explicitly named
43
+ - [ ] **CHECK-T07**: For each integration point: data flow direction is clear
44
+ - [ ] **CHECK-T08**: Changes required to existing packages are specified
45
+
46
+ ### Design Quality
47
+ - [ ] **CHECK-T09**: Alternatives considered for major decisions (not just "we chose X")
48
+ - [ ] **CHECK-T10**: Error handling strategy is defined (error types, propagation, recovery)
49
+ - [ ] **CHECK-T11**: Testing approach is specified (unit, integration, e2e strategy)
50
+ - [ ] **CHECK-T12**: Data model aligns with PRD data requirements
51
+
52
+ ### Completeness
53
+ - [ ] **CHECK-T13**: Package/module structure is defined with exports map
54
+ - [ ] **CHECK-T14**: Configuration approach is specified
55
+ - [ ] **CHECK-T15**: Migration/deployment considerations are addressed if applicable
56
+
57
+ ### Open-Ended Analysis
58
+ - [ ] **CHECK-T16**: Are there integration points that could cause implementation surprises? (e.g., undocumented behavior, version incompatibilities, missing APIs)
59
+ - [ ] **CHECK-T17**: Are there scalability concerns unaddressed by the current design? (e.g., data growth, concurrent users, resource limits)
60
+
61
+ ## Specs Mode Checklist
62
+
63
+ ### Requirement Coverage
64
+ - [ ] **CHECK-S01**: Every PRD requirement (REQ-XXX-NN) is referenced by at least one implementation spec
65
+ - [ ] **CHECK-S02**: Every P0 (must-have) requirement has detailed implementation guidance, not just a mention
66
+ - [ ] **CHECK-S03**: Every P1 requirement is at least acknowledged with an implementation approach
67
+ - [ ] **CHECK-S04**: No implementation spec sections exist that don't trace to a PRD requirement or tech-spec decision (orphaned specs indicate scope creep)
68
+
69
+ ### Tech Spec ↔ Implementation Spec Consistency
70
+ - [ ] **CHECK-S05**: Every technology decision in the tech spec is reflected in the implementation specs
71
+ - [ ] **CHECK-S06**: Package structure in 01-architecture-layout.md matches what the tech spec describes
72
+ - [ ] **CHECK-S07**: Dependencies listed in the tech spec match those in the architecture spec
73
+ - [ ] **CHECK-S08**: No implementation spec contradicts a tech-spec decision
74
+
75
+ ### Type System Integrity
76
+ - [ ] **CHECK-S09**: All type definitions in 00-core-definitions.md are valid syntax in the project's language (not pseudocode)
77
+ - [ ] **CHECK-S10**: All types referenced in other spec docs are defined in 00-core-definitions.md or an explicit external package
78
+ - [ ] **CHECK-S11**: Error classes form a consistent hierarchy with no gaps
79
+ - [ ] **CHECK-S12**: No duplicate or conflicting type definitions across documents
80
+ - [ ] **CHECK-S13**: Every type/interface/struct has documentation comments on every field (JSDoc, docstrings, godoc, etc.)
81
+
82
+ ### Cross-Reference Consistency
83
+ - [ ] **CHECK-S14**: All file references between spec documents point to actual files
84
+ - [ ] **CHECK-S15**: Section references (e.g., "see section 3.2 of 02-provider-registry.md") point to actual sections
85
+ - [ ] **CHECK-S16**: Dependency ordering between spec docs is consistent (no circular dependencies)
86
+ - [ ] **CHECK-S17**: Import paths referenced in specs are consistent with the exports map in 01-architecture-layout.md
87
+
88
+ ### Error Handling Coverage
89
+ - [ ] **CHECK-S18**: Every operation that can fail has an error type defined
90
+ - [ ] **CHECK-S19**: Error propagation is described: where errors are thrown, caught, transformed, and surfaced
91
+ - [ ] **CHECK-S20**: User-facing error messages are specified (not just error codes)
92
+ - [ ] **CHECK-S21**: Recovery behavior is described for recoverable errors
93
+
94
+ ### Integration Point Completeness
95
+ - [ ] **CHECK-S22**: Every package listed in the tech spec's integration section has corresponding detail in the implementation specs
96
+ - [ ] **CHECK-S23**: For each integration: the shared types/contracts are explicitly named
97
+ - [ ] **CHECK-S24**: For each integration: data flow direction is clear
98
+ - [ ] **CHECK-S25**: If integration requires changes to existing packages, those changes are specified
99
+ - [ ] **CHECK-S26**: Import paths match actual package export maps
100
+
101
+ ### Edge Cases and Non-Functional
102
+ - [ ] **CHECK-S27**: Concurrent access scenarios are addressed if relevant
103
+ - [ ] **CHECK-S28**: Empty/null/undefined inputs are handled
104
+ - [ ] **CHECK-S29**: Performance-sensitive paths are identified
105
+ - [ ] **CHECK-S30**: Security considerations from PRD are reflected in implementation
106
+ - [ ] **CHECK-S31**: Observability (logging, metrics, tracing) approach is specified if PRD requires it
107
+ - [ ] **CHECK-S32**: Each implementation spec has a clear "public API" section that defines what is exported vs internal
108
+
109
+ ### Testing Strategy
110
+ - [ ] **CHECK-S33**: Testing strategy document exists
111
+ - [ ] **CHECK-S34**: Test approach covers unit, integration, and e2e as appropriate
112
+ - [ ] **CHECK-S35**: Mock/fixture strategy is defined for external dependencies
113
+ - [ ] **CHECK-S36**: Coverage targets are stated
114
+ - [ ] **CHECK-S37**: Test fixtures and mocks defined in specs align with real interface shapes from 00-core-definitions.md
115
+
116
+ ### Traceability
117
+ - [ ] **CHECK-S38**: Build a complete traceability matrix from every REQ-XXX-NN to the spec document and section that implements it. Any REQ ID not found in at least one spec is a gap finding.
118
+
119
+ ## Backlog Mode Checklist
120
+
121
+ ### Schema Compliance
122
+ - [ ] **CHECK-B01**: backlog.json is valid JSON
123
+ - [ ] **CHECK-B02**: Every item has all required fields: id, type, priority, title, description, acceptanceCriteria, status, dependsOn, specReferences
124
+ - [ ] **CHECK-B03**: All `id` values are unique
125
+ - [ ] **CHECK-B04**: All `type` values are valid (feature, bugfix, chore, etc.)
126
+ - [ ] **CHECK-B05**: All `priority` values are valid numbers
127
+ - [ ] **CHECK-B06**: All `status` values are valid (pending, in-progress, complete, etc.)
128
+
129
+ ### Spec Coverage
130
+ - [ ] **CHECK-B07**: Every implementation spec document is referenced by at least one backlog item
131
+ - [ ] **CHECK-B08**: Every P0 PRD requirement is covered by at least one backlog item's acceptance criteria
132
+ - [ ] **CHECK-B09**: No backlog item references a spec file that doesn't exist
133
+ - [ ] **CHECK-B10**: specReferences paths are valid relative paths to actual files
134
+
135
+ ### Task Quality
136
+ - [ ] **CHECK-B11**: Each item is scoped to be completable in a single rauf loop iteration
137
+ - [ ] **CHECK-B12**: Descriptions are detailed enough for a fresh agent with no prior context
138
+ - [ ] **CHECK-B13**: Acceptance criteria are objectively verifiable (not subjective like "works well")
139
+ - [ ] **CHECK-B14**: Each item specifies what files to create or modify
140
+
141
+ ### Dependency Ordering
142
+ - [ ] **CHECK-B15**: `dependsOn` references are valid item IDs
143
+ - [ ] **CHECK-B16**: No circular dependencies exist
144
+ - [ ] **CHECK-B17**: Foundation items (types, scaffold) have no dependencies
145
+ - [ ] **CHECK-B18**: Items that depend on types/interfaces reference the item that creates them
146
+ - [ ] **CHECK-B19**: Priority ordering is consistent with dependency ordering (dependencies should have equal or higher priority)
147
+
148
+ ### Completeness
149
+ - [ ] **CHECK-B20**: There is an item for the initial package scaffold
150
+ - [ ] **CHECK-B21**: There is an item for shared types and error hierarchy
151
+ - [ ] **CHECK-B22**: There are items for each major subsystem
152
+ - [ ] **CHECK-B23**: There are items for integration wiring (not just isolated subsystems)
153
+ - [ ] **CHECK-B24**: There are items for tests (or testing is included in each feature item's acceptance criteria)
154
+ - [ ] **CHECK-B25**: No large items that try to do too many things (should be broken down)
155
+
156
+ ### Generated-Artifact Freshness
157
+ - [ ] **CHECK-B26**: **Generated-artifact freshness vs. `testCommand` `--check` gates** (#145). When a
158
+ project's configured `testCommand` (forge.config.json) gates on **staleness of generated artifacts**
159
+ — sub-commands of the shape `<generator> --check` / `--verify` / `:check` that fail if a checked-in
160
+ generated file is out of date with its source — every backlog item that regenerates *one* gated
161
+ artifact must regenerate (and commit) **all** the sibling artifacts those same `--check` gates
162
+ depend on, or the item will pass locally yet red-gate on the stale-generated check. Verify
163
+ heuristically:
164
+ 1. **Enumerate the gates.** String-scan `testCommand` for `--check`-style freshness sub-commands and
165
+ collect the generator/artifact each one guards (e.g. `build-benchmarks --check` guards
166
+ `partner-program-benchmarks`). If the command shape is unrecognized (no parseable `--check`
167
+ tokens), this check is **advisory / not-applicable** — never a hard fail.
168
+ 2. **A gate with no regenerator.** If a `--check` gate guards an artifact that **no** backlog item
169
+ regenerates, and some item edits that artifact's *source*, flag a `gap`: the source change will
170
+ trip the freshness gate with nothing scheduled to refresh the output.
171
+ 3. **Partial regeneration.** If an item regenerates a proper subset of the artifacts gated by the
172
+ `--check` set it touches (e.g. runs `build-partner-programs` + `build-analysis` but the gate also
173
+ covers `build-benchmarks`), flag an `inconsistency` naming the missing generator(s) and
174
+ recommending they be added to that item's execute + commit sequence. Same posture as the authoring
175
+ guidance in `forge-4-backlog` / rauf `author-backlog`: enumerate the whole `--check`-gated set, not
176
+ just the artifact the item is "about".
177
+
178
+ ### Artifact Lifecycle Consistency
179
+ - [ ] **CHECK-B27**: **No test item forcing a lifecycle transition another item forbids** (#150).
180
+ *Advisory heuristic — keyword/artifact-name based; **not-applicable** when no lifecycle vocabulary is
181
+ present, **never** a hard fail.* A **lifecycle state** (draft / published / released / approved /
182
+ reviewed / signed-off / gated) is a downstream-project concept forge does not itself track — but a
183
+ backlog can still encode a **contradiction** about one named artifact: item A pins artifact `X` as
184
+ *draft* / *unpublished* / *unreviewed* while item B asserts (in its acceptance criteria or a test it
185
+ adds) that `X` is *published* / *released* / *approved*, with **no** publishing/review item for `X`
186
+ anywhere in B's dependency closure. That leaves a **test/e2e item as the only thing forcing the
187
+ transition** — and since the autonomous loop can neither publish a package nor stand in for a human
188
+ reviewer, asked to make such a test green it **fabricates** the publication or sign-off (a provenance
189
+ defect a `--review` pass has caught in the wild). Verify heuristically:
190
+ 1. **Find lifecycle assertions.** Scan item titles/descriptions/`acceptanceCriteria` for a named
191
+ artifact paired with a lifecycle-state keyword — earlier states (`draft` / `unpublished` /
192
+ `pending review` / `unreleased`) vs later states (`published` / `released` / `approved` / `live` /
193
+ `signed-off` / `gated`). If **no** item carries such vocabulary, this check is **not-applicable**.
194
+ 2. **Pair by artifact name.** Group assertions that reference the **same named artifact**. A pair
195
+ where one item requires the *earlier* state and another asserts the *later* state is a candidate.
196
+ 3. **Check the dependency closure.** If the later-state item has **no** publish / review / human-gated
197
+ item for that artifact in its transitive `dependsOn`, flag an `inconsistency`: name the artifact,
198
+ both items, and recommend either (a) adding a `dependsOn` on an explicit human-gated publish/review
199
+ item that legitimately produces the state, or (b) re-asserting the state via a dev-build / fixture
200
+ path — never letting a test item be the sole driver of the transition (mirrors the authoring
201
+ guidance in `forge-4-backlog` / rauf `author-backlog`). **Report, do not repair.**
202
+
203
+ > **Anti-pattern (visible even where the heuristic can't fire):** a test/e2e item whose pass condition
204
+ > is "artifact `X` is published / approved / reviewed" while the backlog contains no human-gated
205
+ > publish or review item producing that state. The autonomous loop cannot publish or sign off on
206
+ > behalf of a human; asked to make such a test green it will **fabricate** the published/reviewed
207
+ > provenance. Any item asserting a human-gated lifecycle state must trace — via `dependsOn` — to the
208
+ > item that legitimately produces it, or assert the state through a dev-build / fixture path instead.
209
+
210
+ ## Implementation Mode Checklist
211
+
212
+ ### Spec Compliance
213
+ - [ ] **CHECK-I01**: Every file listed in 01-architecture-layout.md exists
214
+ - [ ] **CHECK-I02**: Package.json exports map matches what the spec describes
215
+ - [ ] **CHECK-I03**: Every type in 00-core-definitions.md is implemented
216
+ - [ ] **CHECK-I04**: Every error class is implemented with correct properties
217
+
218
+ ### Backlog Completion
219
+ - [ ] **CHECK-I05**: Every backlog item marked "complete" has its acceptance criteria met
220
+ - [ ] **CHECK-I06**: No backlog items are still "pending" or "in-progress"
221
+ - [ ] **CHECK-I07**: Acceptance criteria can be verified by reading the code
222
+
223
+ ### Integration
224
+ - [ ] **CHECK-I08**: Import paths work (no broken imports)
225
+ - [ ] **CHECK-I09**: Module exports/entry points re-export everything the spec says they should
226
+ - [ ] **CHECK-I10**: Types shared with other packages are compatible
227
+ - [ ] **CHECK-I11**: Type checking / linting passes for the module (`{typeCheckCommand}` from forge.config.json succeeds)
228
+ - [ ] **CHECK-I12**: Type checking / linting passes for modules that depend on this one
229
+
230
+ ### Code Quality
231
+ - [ ] **CHECK-I13**: No placeholder or TODO comments that should have been resolved
232
+ - [ ] **CHECK-I14**: Error handling matches what the specs describe
233
+ - [ ] **CHECK-I15**: No hardcoded values that should be configurable
234
+ - [ ] **CHECK-I16**: Tests exist and pass
235
+ - [ ] **CHECK-I17**: No obvious missing test cases for documented edge cases
236
+
237
+ ### Documentation
238
+ - [ ] **CHECK-I18**: Package has a README or the docs directory has been populated
239
+ - [ ] **CHECK-I19**: Exported functions/classes have documentation comments (JSDoc, docstrings, godoc, etc.)
240
+ - [ ] **CHECK-I20**: Configuration options are documented
241
+
242
+ ### Runnability
243
+
244
+ > **When these fire:** only at impl-verify **completion** (impl mode runs post-loop), never mid-loop — an early skeleton that only compiles is not punished. **Both degrade gracefully:** a feature with no runnable surface (a pure library with no bootstrap contract) or no configured `smokeCommand` yields an **advisory not-applicable** finding, never a hard fail — the same way a null `{typeCheckCommand}` is handled. These exist because `CHECK-I01..I20` are all static reads + typecheck/lint + "tests exist"; nothing here asserts the assembled application actually **runs**. A bootstrap that is exported and unit-tested (each test calls it manually) but never wired into a runtime entrypoint passes every other check yet serves no real request (#121).
245
+
246
+ - [ ] **CHECK-I21**: **End-to-end smoke passes.** If `smokeCommand` from forge.config.json is set, execute it — it boots the wired entrypoint and drives one happy-path request end-to-end; **pass iff exit 0**. A non-zero exit is an `error` finding (the assembled app does not run — quote the command's failing output). If `smokeCommand` is `null`, this is **advisory**: emit a `not-applicable` finding recommending the user configure a `smokeCommand` so "clean" means "it runs" (never fabricate or guess a command — run only the user-configured one, exactly as `CHECK-I11` runs only a configured `{typeCheckCommand}`).
247
+ - **Prefer the dev runtime the developer actually uses (#149).** Recommend the configured `smokeCommand` boot the app in its **development** mode — the dev server / watch loop / HMR runtime — not only a clean production build. The failure modes that a static typecheck and a prod smoke both miss live in the dev runtime: **module-graph-identity** bugs (a "singleton" duplicated across a re-evaluated module graph, so the initialized instance and the one the request path reads are different objects) and **watch-loop** bugs (an init that fires once but never re-fires on hot reload, or fires on every reload and leaks). A prod build evaluates the graph once and hides both. When the project is served in dev during development, the `smokeCommand` should exercise that same runtime.
248
+ - **For a fix, re-verify in the mode the bug manifested.** When impl-verify runs after a **fix** (not a greenfield build), re-run the smoke in the **same runtime mode where the original bug appeared** — a bug reproduced in dev/watch mode is not proven fixed by a green prod-mode smoke, and vice versa. Note the mode in the finding so "smoke passed" is unambiguous about *which* runtime was exercised.
249
+ - [ ] **CHECK-I22**: **Runtime-required bootstrap has a non-test caller.** Every exported bootstrap / `init*` / singleton-populator the specs mark as **required for runtime** must have ≥1 **non-test** call site on a runtime path — an entrypoint such as `main` / `instrumentation` / a route / a layout / a worker, NOT only test files. Statically grep for each such symbol's references (use the stack profile `references/stacks/{stack}.md` **Runtime Entrypoints & Bootstrap-Wiring Sites** list for what counts as a runtime entrypoint in this language). A symbol that is exported and covered by tests but referenced **only** from test files is a `gap` — the #121 walking-skeleton (bootstrap wired to nothing). Degrades naturally: a feature whose specs mark no bootstrap symbol as runtime-required is `not-applicable`. Weaker than `CHECK-I21` (it proves a call site exists, not that the boot succeeds), so it complements rather than replaces the smoke.
250
+ - [ ] **CHECK-I23**: **Heavy bootstrap wired into a universal startup entry — recommend lazy init** (#149). *Advisory heuristic — a `gap`/`improvement` at most, **never** a hard fail.* When a runtime-required `init`/bootstrap/singleton-populator is wired into a **framework bootstrap entry that runs on every startup** (a Next.js `instrumentation.ts`, an app-server preload/`register` hook, a global setup module) **and** that init pulls in a **large server-only import graph** (DB clients, ORMs, queue/background workers, telemetry exporters, the whole service layer), recommend moving to **lazy initialization at the entry that already loads that graph** — the first route / handler / worker that needs it — rather than eager wiring at the universal entry. Eager wiring drags the heavy graph into every cold start, and in dev into every module re-evaluation (the watch-loop cost `CHECK-I21` also targets). **Detect statically:** from the stack profile's **Runtime Entrypoints & Bootstrap-Wiring Sites** list, identify this stack's universal bootstrap entries; grep those files for imports of the feature's runtime-required bootstrap symbols (`CHECK-I22`) and for the server-only heavy-import markers the profile names. A match → an `improvement`/`gap` finding naming the entry, the heavy graph it pulls, and the lazier call site to move initialization to. Degrades to `not-applicable` when the stack has no universal bootstrap entry, when no heavy init is wired there, or when the profile lists no bootstrap-wiring sites — **report, do not repair.**
251
+
252
+ ## Epic Mode Checklist
253
+
254
+ Run `epic-manifest.py validate "{epic}" --specs-dir "{specsDir}" --json` once; map its
255
+ findings to E01/E02/E03/E08. Then perform the judgment checks E04–E07, E09, and E10 by
256
+ reading the manifest, EPIC.md, completed members' specs, and (for E10) sibling members'
257
+ committed tests.
258
+
259
+ ```bash
260
+ R="$(bash -c 'for d in "${CLAUDE_PLUGIN_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/feature-forge/* "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done')"
261
+ [ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
262
+ python3 "$R/scripts/epic-manifest.py" validate "{epic}" --specs-dir "{specsDir}" --json
263
+ ```
264
+
265
+ ### Manifest Integrity (helper-delegated)
266
+ - [ ] **CHECK-E01**: `epic-manifest.json` conforms to `epic-manifest-schema.json`
267
+ (delegated: `validate` reports `schema` / `corrupt-json` findings).
268
+ - [ ] **CHECK-E02**: the `dependsOn` graph is **acyclic** (delegated: `validate` reports
269
+ `cycle`).
270
+ - [ ] **CHECK-E03**: no dangling `dependsOn` / `consumes.from` — every reference names a
271
+ feature in `features[]` (delegated: `validate` reports `dangling-ref`).
272
+ - [ ] **CHECK-E08**: **global name uniqueness** across the specs tree — no feature name
273
+ resolves to more than one feature-shaped dir (delegated: `validate` / `check-name`
274
+ report `duplicate-name` / `ambiguous`). Surfaced non-fatally for manual cleanup.
275
+
276
+ ### Charter & Contract Coverage (verifier judgment)
277
+ - [ ] **CHECK-E04**: **charter coverage** — every feature has a non-empty `charter`
278
+ stating scope **and** contract obligations (REQ-EPIC-04).
279
+ - [ ] **CHECK-E05**: each feature has a meaningful `exposes`/`consumes` declaration — flag
280
+ a feature with empty contracts that the narrative implies should have them
281
+ (REQ-EPIC-03). (Empty is *schema-legal* but suspicious for a feature other features
282
+ depend on.)
283
+ - [ ] **CHECK-E06**: **EPIC.md ⇆ manifest contract drift, for completed features only** —
284
+ the contracts in `EPIC.md` match the manifest `exposes`/`consumes`, and a completed
285
+ feature's specs actually deliver what it `exposes`. Drift between EPIC.md prose and the
286
+ manifest, or between the manifest and the built spec, is a finding (REQ-VERIFY-01).
287
+ - [ ] **CHECK-E07**: **back-pointer ⇆ manifest consistency** — every member's
288
+ `.pipeline-state.json` `epic` value names this epic, and every `features[]` entry has a
289
+ matching member directory. On conflict the **manifest wins** (REQ-STATE-01); report, do
290
+ not auto-repair.
291
+ - [ ] **CHECK-E09**: **open epic change requests** — any member whose `.pipeline-state.json`
292
+ carries `epicChangeRequests[]` entries with `status: "open"` is surfaced as a **non-fatal**
293
+ finding (one per open request). Severity keys off `blocksCurrent`: a **blocking** request →
294
+ `inconsistency` (the epic decomposition and an in-flight member disagree; specs written now
295
+ would build on a soon-invalid premise), a **non-blocking** request → `improvement` (a
296
+ peer/downstream change to reconcile when convenient). Name the request's `kind`, `target`,
297
+ and `rationale`, and point at `/skill:forge-0-epic {epic}` to reconcile. **Report, do
298
+ not repair** (same posture as CHECK-E07). Which members have open requests comes from the
299
+ same `render-status --json` counts the navigator uses (`features[].openEpicChangeRequests` /
300
+ `.blockingEpicChangeRequests`); the per-request `kind`/`target`/`rationale` detail is read
301
+ from the member `.pipeline-state.json` already loaded in Step 2. This is the pre-emptive
302
+ surface for the divergence class CHECK-E06/E07 otherwise catch only after the fact.
303
+ - [ ] **CHECK-E10**: **cross-member shared-state test coupling** (#144). A member that writes or
304
+ migrates a file a *sibling's* committed tests already pin will break the sibling's suite the
305
+ moment it runs — blocking every one of its own commits from a green test gate — yet nothing in
306
+ E04–E09 catches it (contracts cover code symbols, not shared data files). Detect it heuristically,
307
+ per member `M`:
308
+ 1. **Collect `M`'s mutated paths.** Take `M`'s `mutatesShared[]` from the manifest if present
309
+ (the authored precision hint). If absent or empty, fall back to grepping `M`'s specs
310
+ (change-maps / "files this writes") and backlog item `execute` steps for project-root-relative
311
+ paths it creates, writes, or migrates (data corpora, generated fixtures, migration outputs —
312
+ not `M`'s own source modules or its own tests).
313
+ 2. **Grep sibling tests for reads of those paths.** For every *other* member `S` that is already
314
+ **`complete`** (derived status — its regression suite is live and gating), grep `S`'s committed
315
+ **test** files/globs for a read/import/load of any path in step 1. Use the stack profile
316
+ (`references/stacks/{stack}.md`) for what a test glob looks like in this language.
317
+ 3. **Emit the finding.** A hit → a non-fatal `inconsistency` finding: name `M`, the shared path,
318
+ the sibling `S` and the specific test, and **recommend a reconciliation backlog item** on `M`
319
+ (regenerate/re-pin `S`'s fixture, or update `S`'s test to the new shape) scheduled *before*
320
+ `M`'s first mutating item — so the coupling is planned, not discovered mid-loop on a red gate.
321
+ **Report, do not repair** (same posture as CHECK-E07/E09). Degrades to a clean no-op when no
322
+ member declares or greps a shared write, or when no completed sibling reads it — never a
323
+ spurious hard-fail.
324
+
325
+ ## Findings Document Template (Step 4)
326
+
327
+ Write findings to `{specsDir}/{feature}/.verification/VERIFY-{mode}-{YYYY-MM-DD}.md`
328
+ (for epic mode, `{specsDir}/{epic}/.verification/VERIFY-epic-{YYYY-MM-DD}.md` — same
329
+ format, with `{mode}=epic`). Ensure the `.verification/` subdirectory exists first.
330
+
331
+ ```markdown
332
+ # Verification Report: {feature} ({mode})
333
+ Date: {YYYY-MM-DD}
334
+ Pipeline Stage: {currentStage}
335
+ Artifacts Reviewed: {list of files}
336
+
337
+ ## Summary
338
+ - Total findings: {N}
339
+ - Gaps: {N}
340
+ - Inconsistencies: {N}
341
+ - Improvements: {N}
342
+ - Errors: {N}
343
+
344
+ ## Findings
345
+
346
+ ### V-001: {Short title}
347
+ - **Severity:** gap | inconsistency | improvement | error
348
+ - **Location:** {filename}, section {N.N}
349
+ - **Issue:** {Detailed description of what's wrong}
350
+ - **Suggested fix:** {Specific, actionable fix a fresh agent can apply}
351
+ - **References:** {Other files/sections involved}
352
+ - **Checklist:** {CHECK-XXX IDs that this finding relates to}
353
+
354
+ ### V-002: ...
355
+
356
+ ## Fix Execution Plan
357
+
358
+ ### User Decisions Required
359
+ {List any findings that need user input before fixes can be applied. If none, write "None — all fixes can be applied directly."}
360
+
361
+ ### Execution Steps
362
+
363
+ Apply these steps in order. Each step is self-contained — a fresh agent can
364
+ execute it without prior context beyond this document.
365
+
366
+ #### Step {N}: {Short title}
367
+ - **Files:** {exact file paths to edit}
368
+ - **Addresses:** {V-NNN finding IDs}
369
+ - **Checklist:** {CHECK-XXX IDs}
370
+ - **Action:** {Exact description of what to change — specific enough for a fresh agent}
371
+ - **Depends on:** {Step N or "none"}
372
+ - **Rationale:** {Why this order, why grouped this way}
373
+ ```
374
+
375
+ ## Example Findings (Step 4)
376
+
377
+ Here are complete example findings showing the expected quality:
378
+
379
+ **Gap example:**
380
+ ```
381
+ ### V-003: Missing retry logic for rate-limited API calls
382
+ - **Severity:** gap
383
+ - **Location:** specs/auth/03-session-management.md, section 3.2 "Token Refresh"
384
+ - **Issue:** PRD.md REQ-ERR-04 requires retry behavior when external auth providers rate-limit requests. The spec only handles rate limits by throwing `ProviderRateLimitError` — no retry logic, backoff strategy, or max-retry count is specified.
385
+ - **Suggested fix:** Add a "Retry Strategy" subsection to section 3.2 specifying: exponential backoff starting at 500ms, max 3 retries, circuit breaker after 5 consecutive failures. Reference the error type from 00-core-definitions.md.
386
+ - **References:** PRD.md REQ-ERR-04, 00-core-definitions.md (ProviderRateLimitError)
387
+ ```
388
+
389
+ **Inconsistency example:**
390
+ ```
391
+ ### V-007: Conflicting session duration constants
392
+ - **Severity:** inconsistency
393
+ - **Location:** 00-core-definitions.md section 2.3 vs 03-session-management.md section 1.1
394
+ - **Issue:** 00-core-definitions.md defines `SESSION_DURATION_MS = 7 * 24 * 60 * 60 * 1000` (7 days), but 03-session-management.md section 1.1 states "sessions expire after 30 days." These contradict each other.
395
+ - **Suggested fix:** Align both documents to the PRD requirement. PRD.md REQ-SEC-03 says "sessions should have a reasonable expiry" without specifying a duration — use `AskUserQuestion` to ask the user which value is intended, then update both documents.
396
+ - **References:** PRD.md REQ-SEC-03, 00-core-definitions.md section 2.3, 03-session-management.md section 1.1
397
+ ```
398
+
399
+ **Improvement example:**
400
+ ```
401
+ ### V-012: Testing strategy lacks fixture factory pattern
402
+ - **Severity:** improvement
403
+ - **Location:** specs/auth/08-testing-strategy.md, section 3 "Test Fixtures"
404
+ - **Issue:** The testing strategy describes test data inline in each test file. For a feature with 15+ test files, this leads to duplicated fixture data. A factory pattern would reduce duplication and make tests more maintainable.
405
+ - **Suggested fix:** Add a "Fixture Factories" subsection describing a `createTestSession()`, `createTestUser()` factory pattern in a shared `__fixtures__/` directory, consistent with how @repo/db handles test fixtures.
406
+ - **References:** 01-architecture-layout.md (directory structure), packages/db/src/__fixtures__/ (existing pattern)
407
+ ```
408
+
409
+ ## Epic Mode State Write Detail (Step 6)
410
+
411
+ Epic mode is **epic-scoped**, not per-feature: record its result into the epic-level
412
+ state file `{specsDir}/{epic}/.epic-state.json` — **never** into any member's
413
+ `.pipeline-state.json`. This file holds only epic-scoped stage entries (currently just
414
+ `forge-verify-epic`) and carries **no cached per-feature member status** (so it does not
415
+ violate REQ-STATE-02; per-feature status is always derived live from each member's
416
+ `.pipeline-state.json`).
417
+
418
+ Set `stages.forge-verify-epic.status` to `findings-reported` (or `passed` if zero
419
+ findings), recording `findingsFile`, `findingsCount`, and `verifiedAt`. The minimal
420
+ shape:
421
+
422
+ ```jsonc
423
+ {
424
+ "epic": "auth-overhaul", // matches the manifest `epic`
425
+ "stages": {
426
+ "forge-verify-epic": {
427
+ "status": "findings-reported", // "findings-reported" | "passed" | "findings-applied"
428
+ "findingsFile": ".verification/VERIFY-epic-2026-06-12.md",
429
+ "findingsCount": 3,
430
+ "verifiedAt": "2026-06-12T00:00:00Z"
431
+ }
432
+ }
433
+ }
434
+ ```
435
+
436
+ **Write mechanism.** `epic-manifest.py` exposes no subcommand that writes this file, so
437
+ the skill writes it **directly**, using an atomic temp-file + `os.replace()` pattern
438
+ (mirroring `02-manifest-helper-cli.md §3.3`): serialize the merged state to a sibling
439
+ temp file in `{specsDir}/{epic}/`, flush, then `os.replace()` it into place. Create the
440
+ file **lazily on first write** (a missing file is simply created; an existing file is
441
+ read, its `stages.forge-verify-epic` entry merged/replaced, and rewritten). On any I/O
442
+ failure, **report the error and leave any prior `.epic-state.json` intact** (never a
443
+ partial write). For example:
444
+
445
+ ```bash
446
+ python3 - "$SPECS_DIR/$EPIC" <<'PY'
447
+ import json, os, sys, tempfile
448
+ from pathlib import Path
449
+ epic_dir = Path(sys.argv[1])
450
+ path = epic_dir / ".epic-state.json"
451
+ state = {}
452
+ if path.exists():
453
+ state = json.loads(path.read_text())
454
+ state.setdefault("epic", epic_dir.name)
455
+ state.setdefault("stages", {})
456
+ state["stages"]["forge-verify-epic"] = {
457
+ "status": "findings-reported", # or "passed" when findingsCount == 0
458
+ "findingsFile": ".verification/VERIFY-epic-2026-06-12.md",
459
+ "findingsCount": 3,
460
+ "verifiedAt": "2026-06-12T00:00:00Z",
461
+ }
462
+ fd, tmp = tempfile.mkstemp(dir=str(epic_dir), prefix=".epic-state.", suffix=".tmp")
463
+ try:
464
+ with os.fdopen(fd, "w") as f:
465
+ json.dump(state, f, indent=2)
466
+ f.flush()
467
+ os.fsync(f.fileno())
468
+ os.replace(tmp, path)
469
+ except OSError as e:
470
+ try:
471
+ os.unlink(tmp)
472
+ except OSError:
473
+ pass
474
+ print(f"failed to write .epic-state.json: {e}", file=sys.stderr)
475
+ raise
476
+ PY
477
+ ```
@@ -67,7 +67,7 @@ export declare function confidenceFor(target: AgentTarget, scope: Scope): Confid
67
67
  export declare function detectAgent(id: AgentId, opts?: ResolveOpts): DetectionResult;
68
68
  /** Options for {@link detectAgents}: {@link ResolveOpts} plus a single-agent scope (REQ-FLAG-01). */
69
69
  export interface DetectAgentsOpts extends ResolveOpts {
70
- /** Restrict detection to this one agent (`--agent/-a`). Absent ⇒ all five (REQ-DET-03). */
70
+ /** Restrict detection to this one agent (`--agent/-a`). Absent ⇒ all agents (REQ-DET-03). */
71
71
  readonly only?: AgentId;
72
72
  }
73
73
  /**
@@ -40,6 +40,24 @@ export function resolveRoots(opts) {
40
40
  function scopeRootFor(scope, roots) {
41
41
  return scope === "global" ? roots.home : roots.cwd;
42
42
  }
43
+ /** Select a scope-specific config dir name, falling back to the legacy single field. */
44
+ function configDirNameFor(target, scope) {
45
+ if (scope === "global")
46
+ return target.globalConfigDirName ?? target.configDirName;
47
+ return target.projectConfigDirName ?? target.configDirName;
48
+ }
49
+ /** Select a scope-specific install base dir, falling back to the legacy single field. */
50
+ function installBaseDirFor(target, scope) {
51
+ if (scope === "global")
52
+ return target.globalInstallBaseDir ?? target.installBaseDir;
53
+ return target.projectInstallBaseDir ?? target.installBaseDir;
54
+ }
55
+ /** Select a scope-specific install subpath, falling back to the legacy single field. */
56
+ function installSubpathFor(target, scope) {
57
+ if (scope === "global")
58
+ return target.globalInstallSubpath ?? target.installSubpath;
59
+ return target.projectInstallSubpath ?? target.installSubpath;
60
+ }
43
61
  /**
44
62
  * Derive the absolute install destination for one agent under a given scope (REQ-DET-01,
45
63
  * REQ-FLAG-02):
@@ -58,7 +76,9 @@ function scopeRootFor(scope, roots) {
58
76
  export function destinationFor(target, scope, opts) {
59
77
  const roots = resolveRoots(opts);
60
78
  const root = scopeRootFor(scope, roots);
61
- return path.resolve(root, target.installBaseDir, ...(target.installSubpath ? [target.installSubpath] : []), FEATURE_FORGE_NS);
79
+ const installBaseDir = installBaseDirFor(target, scope);
80
+ const installSubpath = installSubpathFor(target, scope);
81
+ return path.resolve(root, installBaseDir, ...(installSubpath ? [installSubpath] : []), FEATURE_FORGE_NS);
62
82
  }
63
83
  /**
64
84
  * The filesystem containment boundary every write for `target` is checked against (REQ-SEC-02):
@@ -68,7 +88,7 @@ export function destinationFor(target, scope, opts) {
68
88
  */
69
89
  export function agentRootFor(target, scope, opts) {
70
90
  const roots = resolveRoots(opts);
71
- return path.resolve(scopeRootFor(scope, roots), target.installBaseDir);
91
+ return path.resolve(scopeRootFor(scope, roots), installBaseDirFor(target, scope));
72
92
  }
73
93
  /**
74
94
  * The effective confidence for `target` under `scope` (A4): the per-row `projectConfidence`
@@ -95,7 +115,7 @@ export function detectAgent(id, opts) {
95
115
  const roots = resolveRoots(opts);
96
116
  const root = scopeRootFor(scope, roots);
97
117
  // Primary signal (REQ-DET-02): presence of the config dir under the active scope root.
98
- const configDir = path.resolve(root, target.configDirName);
118
+ const configDir = path.resolve(root, configDirNameFor(target, scope));
99
119
  const detected = probeConfigDir(configDir);
100
120
  return {
101
121
  agent: id,
package/dist/detect.d.ts CHANGED
@@ -16,7 +16,7 @@ import type { AgentId } from "./types.js";
16
16
  * instant, REQ-PERF-01) and never creates the dir (REQ-DET-04). Any stat failure
17
17
  * (`ENOENT` not present, `EACCES` unreadable, or a non-directory at the path) ⇒ `false`.
18
18
  *
19
- * Synchronous by design: exactly one stat per agent (five total), so async adds no
19
+ * Synchronous by design: exactly one stat per agent, so async adds no
20
20
  * throughput and would complicate the pure-derivation surface.
21
21
  */
22
22
  export declare function probeConfigDir(configDir: string): boolean;
package/dist/detect.js CHANGED
@@ -17,7 +17,7 @@ import { execFileSync } from "node:child_process";
17
17
  * instant, REQ-PERF-01) and never creates the dir (REQ-DET-04). Any stat failure
18
18
  * (`ENOENT` not present, `EACCES` unreadable, or a non-directory at the path) ⇒ `false`.
19
19
  *
20
- * Synchronous by design: exactly one stat per agent (five total), so async adds no
20
+ * Synchronous by design: exactly one stat per agent, so async adds no
21
21
  * throughput and would complicate the pure-derivation surface.
22
22
  */
23
23
  export function probeConfigDir(configDir) {
@@ -34,6 +34,7 @@ const CLI_NAMES = {
34
34
  codex: "codex",
35
35
  copilot: "copilot",
36
36
  gemini: "gemini",
37
+ pi: "pi",
37
38
  // cursor: intentionally omitted — IDE/GUI agent, no canonical CLI on PATH (REQ-DET-02).
38
39
  };
39
40
  /** The real resolver: `which <bin>` (POSIX) / `where <bin>` (Windows). Any failure ⇒ false. */
@@ -28,7 +28,7 @@ export interface BuildManifestArgs {
28
28
  readonly skills: readonly string[];
29
29
  /** SHA-256 over the source bundle's canonical (sorted-path) file set — drift anchor (spec 03). */
30
30
  readonly sourceHash: string;
31
- /** Recorded pinned rauf coordinate (e.g. "@garygentry/rauf@0.12.0"); `null` when `--skip-rauf` (spec 06). */
31
+ /** Recorded pinned rauf coordinate (e.g. "@garygentry/rauf@0.13.0"); `null` when `--skip-rauf` (spec 06). */
32
32
  readonly raufPin: string | null;
33
33
  /** Symlink mode only: the source bundle the namespace dir links to (REQ-SAFE-02). */
34
34
  readonly link?: {
package/dist/manifest.js CHANGED
@@ -10,7 +10,7 @@
10
10
  */
11
11
  import * as fs from "node:fs";
12
12
  import * as path from "node:path";
13
- import { AGENT_TARGETS, MANIFEST_PREFIX, SCHEMA_VERSION, ok, err, READABLE_SCHEMA_VERSIONS, } from "./types.js";
13
+ import { AGENT_IDS, AGENT_TARGETS, MANIFEST_PREFIX, SCHEMA_VERSION, ok, err, READABLE_SCHEMA_VERSIONS, } from "./types.js";
14
14
  import { destinationFor } from "./agent-targets.js";
15
15
  /**
16
16
  * Assemble an {@link InstallManifest} from an apply result (REQ-SAFE-01/03). Pure — no I/O.
@@ -146,7 +146,7 @@ export function writeManifest(p, m) {
146
146
  });
147
147
  }
148
148
  }
149
- const AGENT_IDS_SET = new Set(["claude", "codex", "copilot", "cursor", "gemini"]);
149
+ const AGENT_IDS_SET = new Set(AGENT_IDS);
150
150
  /** Structural validation of a parsed manifest (internal to manifest.ts). */
151
151
  function validateManifest(x) {
152
152
  if (typeof x !== "object" || x === null)
@@ -23,7 +23,11 @@ export function resolvePlacements(target, scope, opts) {
23
23
  const roots = resolveRoots(opts);
24
24
  const scopeRoot = scope === "global" ? roots.home : roots.cwd;
25
25
  return (target.placements ?? []).map((spec) => {
26
- const root = path.resolve(scopeRoot, spec.baseDir);
26
+ // Scope-aware second root: pi mirrors into `~/.pi/agent/agents` (global) but `.pi/agents`
27
+ // (project), which one `baseDir` string cannot express. Fall back to `baseDir` for the common
28
+ // case (codex/copilot) where the second root is scope-invariant.
29
+ const baseDir = (scope === "global" ? spec.globalBaseDir : spec.projectBaseDir) ?? spec.baseDir;
30
+ const root = path.resolve(scopeRoot, baseDir);
27
31
  return { kind: spec.kind, root, destination: path.resolve(root, spec.subpath), spec };
28
32
  });
29
33
  }
package/dist/rauf.d.ts CHANGED
@@ -19,13 +19,13 @@ import { type Result } from "./types.js";
19
19
  *
20
20
  * Shape: `<name>@<version>` — the SCOPED package `@garygentry/rauf` (the unscoped `rauf` name is
21
21
  * blocked by npm's similarity filter). Advanced on each feature-forge release to a new
22
- * known-compatible rauf (REQ-RAUF-03). The current rauf version is 0.12.0.
22
+ * known-compatible rauf (REQ-RAUF-03). The current rauf version is 0.13.0.
23
23
  *
24
- * rauf is now PUBLISHED (rauf#28): `@garygentry/rauf@0.12.0` resolves from the npm registry, so the
24
+ * rauf is now PUBLISHED (rauf#28): `@garygentry/rauf@0.13.0` resolves from the npm registry, so the
25
25
  * preflight below passes by default. (Historically this pin pointed at an unpublished package and
26
26
  * the preflight was a designed-to-fail check — see the `--skip-rauf` escape hatch.)
27
27
  */
28
- export declare const RAUF_PIN = "@garygentry/rauf@0.12.0";
28
+ export declare const RAUF_PIN = "@garygentry/rauf@0.13.0";
29
29
  /**
30
30
  * An injectable, READ-ONLY registry query (D1). Given a coordinate `name@version`, returns the
31
31
  * resolved version string on success, or an `InstallerError` if it is not resolvable.
@@ -37,7 +37,7 @@ export declare const RAUF_PIN = "@garygentry/rauf@0.12.0";
37
37
  * Contract: the query MUST be read-only — it MUST NOT install, MUST NOT mutate global npm
38
38
  * state, and MUST NOT execute rauf. `npm view` satisfies this (it only reads registry metadata).
39
39
  *
40
- * @param coordinate - the `name@version` to resolve, e.g. "@garygentry/rauf@0.12.0"
40
+ * @param coordinate - the `name@version` to resolve, e.g. "@garygentry/rauf@0.13.0"
41
41
  * @returns Result<string> — the resolved version on success; RAUF_UNRESOLVABLE on failure.
42
42
  */
43
43
  export type RegistryQuery = (coordinate: string) => Result<string>;