@garygentry/feature-forge 0.3.1 → 0.3.4
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.
- package/adapters/claude/.feature-forge-bundle.json +1 -1
- package/adapters/claude/agents/forge-verifier.md +3 -1
- package/adapters/claude/references/decisions/single-writer-threat-model.md +53 -0
- package/adapters/claude/references/epic-manifest-schema.json +6 -1
- package/adapters/claude/references/epic-state-schema.json +50 -0
- package/adapters/claude/references/forge-config-schema.json +19 -1
- package/adapters/claude/references/forge-decisions-schema.json +33 -0
- package/adapters/claude/references/pipeline-state-schema.json +38 -4
- package/adapters/claude/references/ralph-loop-contract.md +6 -3
- package/adapters/claude/references/shared-conventions.md +77 -3
- package/adapters/claude/references/stage-exit-protocol.md +391 -143
- package/adapters/claude/scripts/epic-manifest.py +495 -91
- package/adapters/claude/scripts/fix-sweep.py +1180 -0
- package/adapters/claude/scripts/forge-bootstrap.py +57 -5
- package/adapters/claude/scripts/forge-session.py +4241 -146
- package/adapters/claude/scripts/validate-traceability.py +86 -5
- package/adapters/claude/skills/forge/SKILL.md +10 -9
- package/adapters/claude/skills/forge/references/pipeline-state-schema.json +38 -4
- package/adapters/claude/skills/forge/references/shared-conventions.md +77 -3
- package/adapters/claude/skills/forge/references/stage-exit-protocol.md +391 -143
- package/adapters/claude/skills/forge-0-epic/SKILL.md +7 -2
- package/adapters/claude/skills/forge-0-epic/references/edit-mode.md +29 -25
- package/adapters/claude/skills/forge-0-epic/references/epic-manifest-subcommands.md +5 -0
- package/adapters/claude/skills/forge-0-epic/references/pipeline-state-schema.json +38 -4
- package/adapters/claude/skills/forge-0-epic/references/shared-conventions.md +77 -3
- package/adapters/claude/skills/forge-0-epic/references/stage-exit-protocol.md +391 -143
- package/adapters/claude/skills/forge-1-prd/SKILL.md +17 -4
- package/adapters/claude/skills/forge-1-prd/references/shared-conventions.md +77 -3
- package/adapters/claude/skills/forge-1-prd/references/stage-exit-protocol.md +391 -143
- package/adapters/claude/skills/forge-2-tech/SKILL.md +18 -4
- package/adapters/claude/skills/forge-2-tech/references/shared-conventions.md +77 -3
- package/adapters/claude/skills/forge-2-tech/references/stage-exit-protocol.md +391 -143
- package/adapters/claude/skills/forge-3-specs/SKILL.md +9 -3
- package/adapters/claude/skills/forge-3-specs/references/shared-conventions.md +77 -3
- package/adapters/claude/skills/forge-3-specs/references/spec-archetypes.md +9 -0
- package/adapters/claude/skills/forge-3-specs/references/stage-exit-protocol.md +391 -143
- package/adapters/claude/skills/forge-4-backlog/SKILL.md +56 -5
- package/adapters/claude/skills/forge-4-backlog/references/shared-conventions.md +77 -3
- package/adapters/claude/skills/forge-4-backlog/references/stage-exit-protocol.md +391 -143
- package/adapters/claude/skills/forge-5-loop/SKILL.md +67 -69
- package/adapters/claude/skills/forge-5-loop/references/agent-selection.md +16 -0
- package/adapters/claude/skills/forge-5-loop/references/ralph-loop-contract.md +6 -3
- package/adapters/claude/skills/forge-5-loop/references/recovery-procedure.md +349 -0
- package/adapters/claude/skills/forge-5-loop/references/result-reporting.md +101 -33
- package/adapters/claude/skills/forge-5-loop/references/runner-contract.md +26 -6
- package/adapters/claude/skills/forge-5-loop/references/shared-conventions.md +77 -3
- package/adapters/claude/skills/forge-5-loop/references/stage-exit-protocol.md +391 -143
- package/adapters/claude/skills/forge-6-docs/SKILL.md +75 -8
- package/adapters/claude/skills/forge-6-docs/references/shared-conventions.md +77 -3
- package/adapters/claude/skills/forge-6-docs/references/stage-exit-protocol.md +516 -0
- package/adapters/claude/skills/forge-fix/SKILL.md +119 -33
- package/adapters/claude/skills/forge-fix/references/shared-conventions.md +77 -3
- package/adapters/claude/skills/forge-fix/references/stage-exit-protocol.md +391 -143
- package/adapters/claude/skills/forge-guide/references/forge-config-schema.json +19 -1
- package/adapters/claude/skills/forge-guide/references/ralph-loop-contract.md +6 -3
- package/adapters/claude/skills/forge-guide/references/shared-conventions.md +77 -3
- package/adapters/claude/skills/forge-verify/SKILL.md +82 -51
- package/adapters/claude/skills/forge-verify/references/decisions/single-writer-threat-model.md +53 -0
- package/adapters/claude/skills/forge-verify/references/findings-template.md +69 -49
- package/adapters/claude/skills/forge-verify/references/shared-conventions.md +77 -3
- package/adapters/claude/skills/forge-verify/references/stage-exit-protocol.md +516 -0
- package/adapters/claude/skills/forge-verify/references/verification-checklists/backlog.md +73 -0
- package/adapters/claude/skills/forge-verify/references/verification-checklists/epic.md +4 -3
- package/adapters/claude/skills/forge-verify/references/verification-checklists/impl.md +85 -0
- package/adapters/claude/skills/forge-verify/references/verification-checklists/specs.md +45 -1
- package/adapters/codex/.feature-forge-bundle.json +1 -1
- package/adapters/codex/agents/forge-verifier.toml +3 -1
- package/adapters/codex/references/decisions/single-writer-threat-model.md +53 -0
- package/adapters/codex/references/epic-manifest-schema.json +6 -1
- package/adapters/codex/references/epic-state-schema.json +50 -0
- package/adapters/codex/references/forge-config-schema.json +19 -1
- package/adapters/codex/references/forge-decisions-schema.json +33 -0
- package/adapters/codex/references/pipeline-state-schema.json +38 -4
- package/adapters/codex/references/process-overview.md +2 -2
- package/adapters/codex/references/ralph-loop-contract.md +6 -3
- package/adapters/codex/references/shared-conventions.md +102 -28
- package/adapters/codex/references/stage-exit-protocol.md +395 -147
- package/adapters/codex/scripts/epic-manifest.py +495 -91
- package/adapters/codex/scripts/fix-sweep.py +1180 -0
- package/adapters/codex/scripts/forge-bootstrap.py +57 -5
- package/adapters/codex/scripts/forge-session.py +4241 -146
- package/adapters/codex/scripts/validate-traceability.py +86 -5
- package/adapters/codex/skills/forge/SKILL.md +13 -12
- package/adapters/codex/skills/forge/references/pipeline-state-schema.json +38 -4
- package/adapters/codex/skills/forge/references/process-overview.md +2 -2
- package/adapters/codex/skills/forge/references/shared-conventions.md +102 -28
- package/adapters/codex/skills/forge/references/stage-exit-protocol.md +395 -147
- package/adapters/codex/skills/forge-0-epic/SKILL.md +7 -2
- package/adapters/codex/skills/forge-0-epic/references/edit-mode.md +37 -33
- package/adapters/codex/skills/forge-0-epic/references/epic-manifest-subcommands.md +8 -3
- package/adapters/codex/skills/forge-0-epic/references/pipeline-state-schema.json +38 -4
- package/adapters/codex/skills/forge-0-epic/references/shared-conventions.md +102 -28
- package/adapters/codex/skills/forge-0-epic/references/stage-exit-protocol.md +395 -147
- package/adapters/codex/skills/forge-1-prd/SKILL.md +17 -4
- package/adapters/codex/skills/forge-1-prd/references/shared-conventions.md +102 -28
- package/adapters/codex/skills/forge-1-prd/references/stage-exit-protocol.md +395 -147
- package/adapters/codex/skills/forge-2-tech/SKILL.md +18 -4
- package/adapters/codex/skills/forge-2-tech/references/shared-conventions.md +102 -28
- package/adapters/codex/skills/forge-2-tech/references/stage-exit-protocol.md +395 -147
- package/adapters/codex/skills/forge-3-specs/SKILL.md +9 -3
- package/adapters/codex/skills/forge-3-specs/references/shared-conventions.md +102 -28
- package/adapters/codex/skills/forge-3-specs/references/spec-archetypes.md +9 -0
- package/adapters/codex/skills/forge-3-specs/references/stage-exit-protocol.md +395 -147
- package/adapters/codex/skills/forge-4-backlog/SKILL.md +56 -5
- package/adapters/codex/skills/forge-4-backlog/references/shared-conventions.md +102 -28
- package/adapters/codex/skills/forge-4-backlog/references/stage-exit-protocol.md +395 -147
- package/adapters/codex/skills/forge-5-loop/SKILL.md +67 -69
- package/adapters/codex/skills/forge-5-loop/references/agent-selection.md +17 -1
- package/adapters/codex/skills/forge-5-loop/references/ralph-loop-contract.md +6 -3
- package/adapters/codex/skills/forge-5-loop/references/recovery-procedure.md +349 -0
- package/adapters/codex/skills/forge-5-loop/references/result-reporting.md +101 -33
- package/adapters/codex/skills/forge-5-loop/references/runner-contract.md +30 -10
- package/adapters/codex/skills/forge-5-loop/references/shared-conventions.md +102 -28
- package/adapters/codex/skills/forge-5-loop/references/stage-exit-protocol.md +395 -147
- package/adapters/codex/skills/forge-6-docs/SKILL.md +75 -8
- package/adapters/codex/skills/forge-6-docs/references/shared-conventions.md +102 -28
- package/adapters/codex/skills/forge-6-docs/references/stage-exit-protocol.md +516 -0
- package/adapters/codex/skills/forge-fix/SKILL.md +118 -32
- package/adapters/codex/skills/forge-fix/references/shared-conventions.md +102 -28
- package/adapters/codex/skills/forge-fix/references/stage-exit-protocol.md +395 -147
- package/adapters/codex/skills/forge-guide/SKILL.md +1 -1
- package/adapters/codex/skills/forge-guide/references/forge-config-schema.json +19 -1
- package/adapters/codex/skills/forge-guide/references/process-overview.md +2 -2
- package/adapters/codex/skills/forge-guide/references/ralph-loop-contract.md +6 -3
- package/adapters/codex/skills/forge-guide/references/shared-conventions.md +102 -28
- package/adapters/codex/skills/forge-init/SKILL.md +1 -1
- package/adapters/codex/skills/forge-verify/SKILL.md +82 -51
- package/adapters/codex/skills/forge-verify/references/decisions/single-writer-threat-model.md +53 -0
- package/adapters/codex/skills/forge-verify/references/findings-template.md +70 -50
- package/adapters/codex/skills/forge-verify/references/shared-conventions.md +102 -28
- package/adapters/codex/skills/forge-verify/references/stage-exit-protocol.md +516 -0
- package/adapters/codex/skills/forge-verify/references/verification-checklists/backlog.md +73 -0
- package/adapters/codex/skills/forge-verify/references/verification-checklists/epic.md +5 -4
- package/adapters/codex/skills/forge-verify/references/verification-checklists/impl.md +85 -0
- package/adapters/codex/skills/forge-verify/references/verification-checklists/specs.md +45 -1
- package/adapters/copilot/.feature-forge-bundle.json +1 -1
- package/adapters/copilot/agents/forge-verifier.md +3 -1
- package/adapters/copilot/references/decisions/single-writer-threat-model.md +53 -0
- package/adapters/copilot/references/epic-manifest-schema.json +6 -1
- package/adapters/copilot/references/epic-state-schema.json +50 -0
- package/adapters/copilot/references/forge-config-schema.json +19 -1
- package/adapters/copilot/references/forge-decisions-schema.json +33 -0
- package/adapters/copilot/references/pipeline-state-schema.json +38 -4
- package/adapters/copilot/references/process-overview.md +2 -2
- package/adapters/copilot/references/ralph-loop-contract.md +6 -3
- package/adapters/copilot/references/shared-conventions.md +102 -28
- package/adapters/copilot/references/stage-exit-protocol.md +395 -147
- package/adapters/copilot/scripts/epic-manifest.py +495 -91
- package/adapters/copilot/scripts/fix-sweep.py +1180 -0
- package/adapters/copilot/scripts/forge-bootstrap.py +57 -5
- package/adapters/copilot/scripts/forge-session.py +4241 -146
- package/adapters/copilot/scripts/validate-traceability.py +86 -5
- package/adapters/copilot/skills/forge/forge.md +13 -12
- package/adapters/copilot/skills/forge/references/pipeline-state-schema.json +38 -4
- package/adapters/copilot/skills/forge/references/process-overview.md +2 -2
- package/adapters/copilot/skills/forge/references/shared-conventions.md +102 -28
- package/adapters/copilot/skills/forge/references/stage-exit-protocol.md +395 -147
- package/adapters/copilot/skills/forge-0-epic/forge-0-epic.md +7 -2
- package/adapters/copilot/skills/forge-0-epic/references/edit-mode.md +37 -33
- package/adapters/copilot/skills/forge-0-epic/references/epic-manifest-subcommands.md +8 -3
- package/adapters/copilot/skills/forge-0-epic/references/pipeline-state-schema.json +38 -4
- package/adapters/copilot/skills/forge-0-epic/references/shared-conventions.md +102 -28
- package/adapters/copilot/skills/forge-0-epic/references/stage-exit-protocol.md +395 -147
- package/adapters/copilot/skills/forge-1-prd/forge-1-prd.md +17 -4
- package/adapters/copilot/skills/forge-1-prd/references/shared-conventions.md +102 -28
- package/adapters/copilot/skills/forge-1-prd/references/stage-exit-protocol.md +395 -147
- package/adapters/copilot/skills/forge-2-tech/forge-2-tech.md +18 -4
- package/adapters/copilot/skills/forge-2-tech/references/shared-conventions.md +102 -28
- package/adapters/copilot/skills/forge-2-tech/references/stage-exit-protocol.md +395 -147
- package/adapters/copilot/skills/forge-3-specs/forge-3-specs.md +9 -3
- package/adapters/copilot/skills/forge-3-specs/references/shared-conventions.md +102 -28
- package/adapters/copilot/skills/forge-3-specs/references/spec-archetypes.md +9 -0
- package/adapters/copilot/skills/forge-3-specs/references/stage-exit-protocol.md +395 -147
- package/adapters/copilot/skills/forge-4-backlog/forge-4-backlog.md +56 -5
- package/adapters/copilot/skills/forge-4-backlog/references/shared-conventions.md +102 -28
- package/adapters/copilot/skills/forge-4-backlog/references/stage-exit-protocol.md +395 -147
- package/adapters/copilot/skills/forge-5-loop/forge-5-loop.md +67 -69
- package/adapters/copilot/skills/forge-5-loop/references/agent-selection.md +17 -1
- package/adapters/copilot/skills/forge-5-loop/references/ralph-loop-contract.md +6 -3
- package/adapters/copilot/skills/forge-5-loop/references/recovery-procedure.md +349 -0
- package/adapters/copilot/skills/forge-5-loop/references/result-reporting.md +101 -33
- package/adapters/copilot/skills/forge-5-loop/references/runner-contract.md +30 -10
- package/adapters/copilot/skills/forge-5-loop/references/shared-conventions.md +102 -28
- package/adapters/copilot/skills/forge-5-loop/references/stage-exit-protocol.md +395 -147
- package/adapters/copilot/skills/forge-6-docs/forge-6-docs.md +75 -8
- package/adapters/copilot/skills/forge-6-docs/references/shared-conventions.md +102 -28
- package/adapters/copilot/skills/forge-6-docs/references/stage-exit-protocol.md +516 -0
- package/adapters/copilot/skills/forge-fix/forge-fix.md +118 -32
- package/adapters/copilot/skills/forge-fix/references/shared-conventions.md +102 -28
- package/adapters/copilot/skills/forge-fix/references/stage-exit-protocol.md +395 -147
- package/adapters/copilot/skills/forge-guide/forge-guide.md +1 -1
- package/adapters/copilot/skills/forge-guide/references/forge-config-schema.json +19 -1
- package/adapters/copilot/skills/forge-guide/references/process-overview.md +2 -2
- package/adapters/copilot/skills/forge-guide/references/ralph-loop-contract.md +6 -3
- package/adapters/copilot/skills/forge-guide/references/shared-conventions.md +102 -28
- package/adapters/copilot/skills/forge-init/forge-init.md +1 -1
- package/adapters/copilot/skills/forge-verify/forge-verify.md +82 -51
- package/adapters/copilot/skills/forge-verify/references/decisions/single-writer-threat-model.md +53 -0
- package/adapters/copilot/skills/forge-verify/references/findings-template.md +70 -50
- package/adapters/copilot/skills/forge-verify/references/shared-conventions.md +102 -28
- package/adapters/copilot/skills/forge-verify/references/stage-exit-protocol.md +516 -0
- package/adapters/copilot/skills/forge-verify/references/verification-checklists/backlog.md +73 -0
- package/adapters/copilot/skills/forge-verify/references/verification-checklists/epic.md +5 -4
- package/adapters/copilot/skills/forge-verify/references/verification-checklists/impl.md +85 -0
- package/adapters/copilot/skills/forge-verify/references/verification-checklists/specs.md +45 -1
- package/adapters/cursor/.feature-forge-bundle.json +1 -1
- package/adapters/cursor/agents/forge-verifier.mdc +3 -1
- package/adapters/cursor/references/decisions/single-writer-threat-model.md +53 -0
- package/adapters/cursor/references/epic-manifest-schema.json +6 -1
- package/adapters/cursor/references/epic-state-schema.json +50 -0
- package/adapters/cursor/references/forge-config-schema.json +19 -1
- package/adapters/cursor/references/forge-decisions-schema.json +33 -0
- package/adapters/cursor/references/pipeline-state-schema.json +38 -4
- package/adapters/cursor/references/process-overview.md +2 -2
- package/adapters/cursor/references/ralph-loop-contract.md +6 -3
- package/adapters/cursor/references/shared-conventions.md +102 -28
- package/adapters/cursor/references/stage-exit-protocol.md +395 -147
- package/adapters/cursor/scripts/epic-manifest.py +495 -91
- package/adapters/cursor/scripts/fix-sweep.py +1180 -0
- package/adapters/cursor/scripts/forge-bootstrap.py +57 -5
- package/adapters/cursor/scripts/forge-session.py +4241 -146
- package/adapters/cursor/scripts/validate-traceability.py +86 -5
- package/adapters/cursor/skills/forge/forge.mdc +13 -12
- package/adapters/cursor/skills/forge/references/pipeline-state-schema.json +38 -4
- package/adapters/cursor/skills/forge/references/process-overview.md +2 -2
- package/adapters/cursor/skills/forge/references/shared-conventions.md +102 -28
- package/adapters/cursor/skills/forge/references/stage-exit-protocol.md +395 -147
- package/adapters/cursor/skills/forge-0-epic/forge-0-epic.mdc +7 -2
- package/adapters/cursor/skills/forge-0-epic/references/edit-mode.md +37 -33
- package/adapters/cursor/skills/forge-0-epic/references/epic-manifest-subcommands.md +8 -3
- package/adapters/cursor/skills/forge-0-epic/references/pipeline-state-schema.json +38 -4
- package/adapters/cursor/skills/forge-0-epic/references/shared-conventions.md +102 -28
- package/adapters/cursor/skills/forge-0-epic/references/stage-exit-protocol.md +395 -147
- package/adapters/cursor/skills/forge-1-prd/forge-1-prd.mdc +17 -4
- package/adapters/cursor/skills/forge-1-prd/references/shared-conventions.md +102 -28
- package/adapters/cursor/skills/forge-1-prd/references/stage-exit-protocol.md +395 -147
- package/adapters/cursor/skills/forge-2-tech/forge-2-tech.mdc +18 -4
- package/adapters/cursor/skills/forge-2-tech/references/shared-conventions.md +102 -28
- package/adapters/cursor/skills/forge-2-tech/references/stage-exit-protocol.md +395 -147
- package/adapters/cursor/skills/forge-3-specs/forge-3-specs.mdc +9 -3
- package/adapters/cursor/skills/forge-3-specs/references/shared-conventions.md +102 -28
- package/adapters/cursor/skills/forge-3-specs/references/spec-archetypes.md +9 -0
- package/adapters/cursor/skills/forge-3-specs/references/stage-exit-protocol.md +395 -147
- package/adapters/cursor/skills/forge-4-backlog/forge-4-backlog.mdc +56 -5
- package/adapters/cursor/skills/forge-4-backlog/references/shared-conventions.md +102 -28
- package/adapters/cursor/skills/forge-4-backlog/references/stage-exit-protocol.md +395 -147
- package/adapters/cursor/skills/forge-5-loop/forge-5-loop.mdc +67 -69
- package/adapters/cursor/skills/forge-5-loop/references/agent-selection.md +17 -1
- package/adapters/cursor/skills/forge-5-loop/references/ralph-loop-contract.md +6 -3
- package/adapters/cursor/skills/forge-5-loop/references/recovery-procedure.md +349 -0
- package/adapters/cursor/skills/forge-5-loop/references/result-reporting.md +101 -33
- package/adapters/cursor/skills/forge-5-loop/references/runner-contract.md +30 -10
- package/adapters/cursor/skills/forge-5-loop/references/shared-conventions.md +102 -28
- package/adapters/cursor/skills/forge-5-loop/references/stage-exit-protocol.md +395 -147
- package/adapters/cursor/skills/forge-6-docs/forge-6-docs.mdc +75 -8
- package/adapters/cursor/skills/forge-6-docs/references/shared-conventions.md +102 -28
- package/adapters/cursor/skills/forge-6-docs/references/stage-exit-protocol.md +516 -0
- package/adapters/cursor/skills/forge-fix/forge-fix.mdc +118 -32
- package/adapters/cursor/skills/forge-fix/references/shared-conventions.md +102 -28
- package/adapters/cursor/skills/forge-fix/references/stage-exit-protocol.md +395 -147
- package/adapters/cursor/skills/forge-guide/forge-guide.mdc +1 -1
- package/adapters/cursor/skills/forge-guide/references/forge-config-schema.json +19 -1
- package/adapters/cursor/skills/forge-guide/references/process-overview.md +2 -2
- package/adapters/cursor/skills/forge-guide/references/ralph-loop-contract.md +6 -3
- package/adapters/cursor/skills/forge-guide/references/shared-conventions.md +102 -28
- package/adapters/cursor/skills/forge-init/forge-init.mdc +1 -1
- package/adapters/cursor/skills/forge-verify/forge-verify.mdc +82 -51
- package/adapters/cursor/skills/forge-verify/references/decisions/single-writer-threat-model.md +53 -0
- package/adapters/cursor/skills/forge-verify/references/findings-template.md +70 -50
- package/adapters/cursor/skills/forge-verify/references/shared-conventions.md +102 -28
- package/adapters/cursor/skills/forge-verify/references/stage-exit-protocol.md +516 -0
- package/adapters/cursor/skills/forge-verify/references/verification-checklists/backlog.md +73 -0
- package/adapters/cursor/skills/forge-verify/references/verification-checklists/epic.md +5 -4
- package/adapters/cursor/skills/forge-verify/references/verification-checklists/impl.md +85 -0
- package/adapters/cursor/skills/forge-verify/references/verification-checklists/specs.md +45 -1
- package/adapters/gemini/.feature-forge-bundle.json +1 -1
- package/adapters/gemini/agents/forge-verifier.md +3 -1
- package/adapters/gemini/gemini-extension.json +1 -1
- package/adapters/gemini/references/decisions/single-writer-threat-model.md +53 -0
- package/adapters/gemini/references/epic-manifest-schema.json +6 -1
- package/adapters/gemini/references/epic-state-schema.json +50 -0
- package/adapters/gemini/references/forge-config-schema.json +19 -1
- package/adapters/gemini/references/forge-decisions-schema.json +33 -0
- package/adapters/gemini/references/pipeline-state-schema.json +38 -4
- package/adapters/gemini/references/process-overview.md +2 -2
- package/adapters/gemini/references/ralph-loop-contract.md +6 -3
- package/adapters/gemini/references/shared-conventions.md +102 -28
- package/adapters/gemini/references/stage-exit-protocol.md +395 -147
- package/adapters/gemini/scripts/epic-manifest.py +495 -91
- package/adapters/gemini/scripts/fix-sweep.py +1180 -0
- package/adapters/gemini/scripts/forge-bootstrap.py +57 -5
- package/adapters/gemini/scripts/forge-session.py +4241 -146
- package/adapters/gemini/scripts/validate-traceability.py +86 -5
- package/adapters/gemini/skills/forge/forge.md +13 -12
- package/adapters/gemini/skills/forge/references/pipeline-state-schema.json +38 -4
- package/adapters/gemini/skills/forge/references/process-overview.md +2 -2
- package/adapters/gemini/skills/forge/references/shared-conventions.md +102 -28
- package/adapters/gemini/skills/forge/references/stage-exit-protocol.md +395 -147
- package/adapters/gemini/skills/forge-0-epic/forge-0-epic.md +7 -2
- package/adapters/gemini/skills/forge-0-epic/references/edit-mode.md +37 -33
- package/adapters/gemini/skills/forge-0-epic/references/epic-manifest-subcommands.md +8 -3
- package/adapters/gemini/skills/forge-0-epic/references/pipeline-state-schema.json +38 -4
- package/adapters/gemini/skills/forge-0-epic/references/shared-conventions.md +102 -28
- package/adapters/gemini/skills/forge-0-epic/references/stage-exit-protocol.md +395 -147
- package/adapters/gemini/skills/forge-1-prd/forge-1-prd.md +17 -4
- package/adapters/gemini/skills/forge-1-prd/references/shared-conventions.md +102 -28
- package/adapters/gemini/skills/forge-1-prd/references/stage-exit-protocol.md +395 -147
- package/adapters/gemini/skills/forge-2-tech/forge-2-tech.md +18 -4
- package/adapters/gemini/skills/forge-2-tech/references/shared-conventions.md +102 -28
- package/adapters/gemini/skills/forge-2-tech/references/stage-exit-protocol.md +395 -147
- package/adapters/gemini/skills/forge-3-specs/forge-3-specs.md +9 -3
- package/adapters/gemini/skills/forge-3-specs/references/shared-conventions.md +102 -28
- package/adapters/gemini/skills/forge-3-specs/references/spec-archetypes.md +9 -0
- package/adapters/gemini/skills/forge-3-specs/references/stage-exit-protocol.md +395 -147
- package/adapters/gemini/skills/forge-4-backlog/forge-4-backlog.md +56 -5
- package/adapters/gemini/skills/forge-4-backlog/references/shared-conventions.md +102 -28
- package/adapters/gemini/skills/forge-4-backlog/references/stage-exit-protocol.md +395 -147
- package/adapters/gemini/skills/forge-5-loop/forge-5-loop.md +67 -69
- package/adapters/gemini/skills/forge-5-loop/references/agent-selection.md +17 -1
- package/adapters/gemini/skills/forge-5-loop/references/ralph-loop-contract.md +6 -3
- package/adapters/gemini/skills/forge-5-loop/references/recovery-procedure.md +349 -0
- package/adapters/gemini/skills/forge-5-loop/references/result-reporting.md +101 -33
- package/adapters/gemini/skills/forge-5-loop/references/runner-contract.md +30 -10
- package/adapters/gemini/skills/forge-5-loop/references/shared-conventions.md +102 -28
- package/adapters/gemini/skills/forge-5-loop/references/stage-exit-protocol.md +395 -147
- package/adapters/gemini/skills/forge-6-docs/forge-6-docs.md +75 -8
- package/adapters/gemini/skills/forge-6-docs/references/shared-conventions.md +102 -28
- package/adapters/gemini/skills/forge-6-docs/references/stage-exit-protocol.md +516 -0
- package/adapters/gemini/skills/forge-fix/forge-fix.md +118 -32
- package/adapters/gemini/skills/forge-fix/references/shared-conventions.md +102 -28
- package/adapters/gemini/skills/forge-fix/references/stage-exit-protocol.md +395 -147
- package/adapters/gemini/skills/forge-guide/forge-guide.md +1 -1
- package/adapters/gemini/skills/forge-guide/references/forge-config-schema.json +19 -1
- package/adapters/gemini/skills/forge-guide/references/process-overview.md +2 -2
- package/adapters/gemini/skills/forge-guide/references/ralph-loop-contract.md +6 -3
- package/adapters/gemini/skills/forge-guide/references/shared-conventions.md +102 -28
- package/adapters/gemini/skills/forge-init/forge-init.md +1 -1
- package/adapters/gemini/skills/forge-verify/forge-verify.md +82 -51
- package/adapters/gemini/skills/forge-verify/references/decisions/single-writer-threat-model.md +53 -0
- package/adapters/gemini/skills/forge-verify/references/findings-template.md +70 -50
- package/adapters/gemini/skills/forge-verify/references/shared-conventions.md +102 -28
- package/adapters/gemini/skills/forge-verify/references/stage-exit-protocol.md +516 -0
- package/adapters/gemini/skills/forge-verify/references/verification-checklists/backlog.md +73 -0
- package/adapters/gemini/skills/forge-verify/references/verification-checklists/epic.md +5 -4
- package/adapters/gemini/skills/forge-verify/references/verification-checklists/impl.md +85 -0
- package/adapters/gemini/skills/forge-verify/references/verification-checklists/specs.md +45 -1
- package/adapters/pi/.feature-forge-bundle.json +1 -1
- package/adapters/pi/agents/forge-verifier.md +3 -1
- package/adapters/pi/references/decisions/single-writer-threat-model.md +53 -0
- package/adapters/pi/references/epic-manifest-schema.json +6 -1
- package/adapters/pi/references/epic-state-schema.json +50 -0
- package/adapters/pi/references/forge-config-schema.json +19 -1
- package/adapters/pi/references/forge-decisions-schema.json +33 -0
- package/adapters/pi/references/pipeline-state-schema.json +38 -4
- package/adapters/pi/references/process-overview.md +2 -2
- package/adapters/pi/references/ralph-loop-contract.md +6 -3
- package/adapters/pi/references/shared-conventions.md +91 -17
- package/adapters/pi/references/stage-exit-protocol.md +395 -147
- package/adapters/pi/scripts/epic-manifest.py +495 -91
- package/adapters/pi/scripts/fix-sweep.py +1180 -0
- package/adapters/pi/scripts/forge-bootstrap.py +57 -5
- package/adapters/pi/scripts/forge-session.py +4241 -146
- package/adapters/pi/scripts/validate-traceability.py +86 -5
- package/adapters/pi/skills/forge/SKILL.md +10 -9
- package/adapters/pi/skills/forge/references/pipeline-state-schema.json +38 -4
- package/adapters/pi/skills/forge/references/process-overview.md +2 -2
- package/adapters/pi/skills/forge/references/shared-conventions.md +91 -17
- package/adapters/pi/skills/forge/references/stage-exit-protocol.md +395 -147
- package/adapters/pi/skills/forge-0-epic/SKILL.md +7 -2
- package/adapters/pi/skills/forge-0-epic/references/edit-mode.md +31 -27
- package/adapters/pi/skills/forge-0-epic/references/epic-manifest-subcommands.md +6 -1
- package/adapters/pi/skills/forge-0-epic/references/pipeline-state-schema.json +38 -4
- package/adapters/pi/skills/forge-0-epic/references/shared-conventions.md +91 -17
- package/adapters/pi/skills/forge-0-epic/references/stage-exit-protocol.md +395 -147
- package/adapters/pi/skills/forge-1-prd/SKILL.md +17 -4
- package/adapters/pi/skills/forge-1-prd/references/shared-conventions.md +91 -17
- package/adapters/pi/skills/forge-1-prd/references/stage-exit-protocol.md +395 -147
- package/adapters/pi/skills/forge-2-tech/SKILL.md +18 -4
- package/adapters/pi/skills/forge-2-tech/references/shared-conventions.md +91 -17
- package/adapters/pi/skills/forge-2-tech/references/stage-exit-protocol.md +395 -147
- package/adapters/pi/skills/forge-3-specs/SKILL.md +9 -3
- package/adapters/pi/skills/forge-3-specs/references/shared-conventions.md +91 -17
- package/adapters/pi/skills/forge-3-specs/references/spec-archetypes.md +9 -0
- package/adapters/pi/skills/forge-3-specs/references/stage-exit-protocol.md +395 -147
- package/adapters/pi/skills/forge-4-backlog/SKILL.md +56 -5
- package/adapters/pi/skills/forge-4-backlog/references/shared-conventions.md +91 -17
- package/adapters/pi/skills/forge-4-backlog/references/stage-exit-protocol.md +395 -147
- package/adapters/pi/skills/forge-5-loop/SKILL.md +67 -69
- package/adapters/pi/skills/forge-5-loop/references/agent-selection.md +16 -0
- package/adapters/pi/skills/forge-5-loop/references/ralph-loop-contract.md +6 -3
- package/adapters/pi/skills/forge-5-loop/references/recovery-procedure.md +349 -0
- package/adapters/pi/skills/forge-5-loop/references/result-reporting.md +101 -33
- package/adapters/pi/skills/forge-5-loop/references/runner-contract.md +29 -9
- package/adapters/pi/skills/forge-5-loop/references/shared-conventions.md +91 -17
- package/adapters/pi/skills/forge-5-loop/references/stage-exit-protocol.md +395 -147
- package/adapters/pi/skills/forge-6-docs/SKILL.md +75 -8
- package/adapters/pi/skills/forge-6-docs/references/shared-conventions.md +91 -17
- package/adapters/pi/skills/forge-6-docs/references/stage-exit-protocol.md +516 -0
- package/adapters/pi/skills/forge-fix/SKILL.md +118 -32
- package/adapters/pi/skills/forge-fix/references/shared-conventions.md +91 -17
- package/adapters/pi/skills/forge-fix/references/stage-exit-protocol.md +395 -147
- package/adapters/pi/skills/forge-guide/references/forge-config-schema.json +19 -1
- package/adapters/pi/skills/forge-guide/references/process-overview.md +2 -2
- package/adapters/pi/skills/forge-guide/references/ralph-loop-contract.md +6 -3
- package/adapters/pi/skills/forge-guide/references/shared-conventions.md +91 -17
- package/adapters/pi/skills/forge-verify/SKILL.md +81 -50
- package/adapters/pi/skills/forge-verify/references/decisions/single-writer-threat-model.md +53 -0
- package/adapters/pi/skills/forge-verify/references/findings-template.md +69 -49
- package/adapters/pi/skills/forge-verify/references/shared-conventions.md +91 -17
- package/adapters/pi/skills/forge-verify/references/stage-exit-protocol.md +516 -0
- package/adapters/pi/skills/forge-verify/references/verification-checklists/backlog.md +73 -0
- package/adapters/pi/skills/forge-verify/references/verification-checklists/epic.md +5 -4
- package/adapters/pi/skills/forge-verify/references/verification-checklists/impl.md +85 -0
- package/adapters/pi/skills/forge-verify/references/verification-checklists/specs.md +45 -1
- package/package.json +1 -1
- package/adapters/claude/skills/forge-verify/references/pipeline-state-schema.json +0 -191
- package/adapters/codex/skills/forge-verify/references/pipeline-state-schema.json +0 -191
- package/adapters/copilot/skills/forge-verify/references/pipeline-state-schema.json +0 -191
- package/adapters/cursor/skills/forge-verify/references/pipeline-state-schema.json +0 -191
- package/adapters/gemini/skills/forge-verify/references/pipeline-state-schema.json +0 -191
- package/adapters/pi/skills/forge-verify/references/pipeline-state-schema.json +0 -191
|
@@ -5,12 +5,20 @@ Extracts REQ-XXX-NN identifiers from a PRD file and checks that every
|
|
|
5
5
|
requirement is referenced in at least one implementation spec document.
|
|
6
6
|
Also reports orphaned references (IDs found in specs but not in PRD).
|
|
7
7
|
|
|
8
|
+
A suite may legitimately mention a *foreign* requirement id — most often when a
|
|
9
|
+
spec quotes an antecedent feature's test docstrings verbatim, carrying that
|
|
10
|
+
feature's ids into this suite's text. Those are not this suite's requirements and
|
|
11
|
+
are not orphans. Declare them with --allow-orphan, or one id per line in
|
|
12
|
+
<specs-dir>/.traceability-allowlist; allowed ids are reported, never silently
|
|
13
|
+
dropped.
|
|
14
|
+
|
|
8
15
|
Usage:
|
|
9
16
|
python validate-traceability.py <prd-path> <specs-dir> [--json]
|
|
17
|
+
[--allow-orphan REQ-ID ...]
|
|
10
18
|
|
|
11
19
|
Exit codes:
|
|
12
|
-
0 = all requirements covered
|
|
13
|
-
1 =
|
|
20
|
+
0 = all requirements covered; no orphans other than allowlisted ones
|
|
21
|
+
1 = uncovered requirements, or orphans that are not allowlisted
|
|
14
22
|
2 = file not found or read error
|
|
15
23
|
"""
|
|
16
24
|
|
|
@@ -27,12 +35,46 @@ from pathlib import Path
|
|
|
27
35
|
#: character stays `[A-Z]` so a lowercase or digit-led token is still not an ID.
|
|
28
36
|
REQ_PATTERN = re.compile(r"REQ-[A-Z][A-Z0-9]*-\d+")
|
|
29
37
|
|
|
38
|
+
#: Optional per-suite allowlist of foreign requirement ids, read from the specs dir.
|
|
39
|
+
#: One id per line; blank lines and `#` comments ignored. Kept beside the suite it
|
|
40
|
+
#: describes rather than hardcoded here, so this validator stays generic across
|
|
41
|
+
#: repos and suites.
|
|
42
|
+
ALLOWLIST_FILENAME = ".traceability-allowlist"
|
|
43
|
+
|
|
30
44
|
|
|
31
45
|
def extract_req_ids(text: str) -> set[str]:
|
|
32
46
|
"""Extract all unique REQ-XXX-NN identifiers from text."""
|
|
33
47
|
return set(REQ_PATTERN.findall(text))
|
|
34
48
|
|
|
35
49
|
|
|
50
|
+
def read_allowlist_file(specs_dir: Path) -> set[str]:
|
|
51
|
+
"""Read <specs-dir>/.traceability-allowlist, if present.
|
|
52
|
+
|
|
53
|
+
A missing file is not an error — most suites have no foreign ids at all.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
specs_dir: The suite's specs directory, searched for the allowlist file.
|
|
57
|
+
|
|
58
|
+
Returns:
|
|
59
|
+
The declared foreign requirement ids; an empty set when the file is
|
|
60
|
+
absent or unreadable.
|
|
61
|
+
"""
|
|
62
|
+
allowlist_path = specs_dir / ALLOWLIST_FILENAME
|
|
63
|
+
if not allowlist_path.exists():
|
|
64
|
+
return set()
|
|
65
|
+
try:
|
|
66
|
+
text = allowlist_path.read_text()
|
|
67
|
+
except OSError as e:
|
|
68
|
+
print(f"Warning: Could not read {allowlist_path}: {e}", file=sys.stderr)
|
|
69
|
+
return set()
|
|
70
|
+
ids: set[str] = set()
|
|
71
|
+
for raw_line in text.splitlines():
|
|
72
|
+
line = raw_line.split("#", 1)[0].strip()
|
|
73
|
+
if line:
|
|
74
|
+
ids.add(line)
|
|
75
|
+
return ids
|
|
76
|
+
|
|
77
|
+
|
|
36
78
|
def main() -> int:
|
|
37
79
|
parser = argparse.ArgumentParser(
|
|
38
80
|
description="Validate requirement traceability between PRD and specs"
|
|
@@ -42,6 +84,17 @@ def main() -> int:
|
|
|
42
84
|
parser.add_argument(
|
|
43
85
|
"--json", action="store_true", dest="json_output", help="Output as JSON"
|
|
44
86
|
)
|
|
87
|
+
parser.add_argument(
|
|
88
|
+
"--allow-orphan",
|
|
89
|
+
action="append",
|
|
90
|
+
default=[],
|
|
91
|
+
dest="allow_orphan",
|
|
92
|
+
metavar="REQ-ID",
|
|
93
|
+
help=(
|
|
94
|
+
"Requirement id that may appear in the specs without being defined in "
|
|
95
|
+
f"this suite's PRD (repeatable). Merged with {ALLOWLIST_FILENAME}."
|
|
96
|
+
),
|
|
97
|
+
)
|
|
45
98
|
args = parser.parse_args()
|
|
46
99
|
|
|
47
100
|
prd_path = Path(args.prd_path)
|
|
@@ -96,9 +149,16 @@ def main() -> int:
|
|
|
96
149
|
except OSError:
|
|
97
150
|
pass
|
|
98
151
|
|
|
99
|
-
# Analysis
|
|
152
|
+
# Analysis. Allowed foreign ids are subtracted from the orphan set but reported
|
|
153
|
+
# below, so an allowlist entry is always visible rather than an invisible pass.
|
|
154
|
+
allowlist = read_allowlist_file(specs_dir) | set(args.allow_orphan)
|
|
100
155
|
uncovered = sorted(prd_reqs - all_spec_reqs)
|
|
101
|
-
|
|
156
|
+
raw_orphaned = all_spec_reqs - prd_reqs
|
|
157
|
+
allowed_orphans = sorted(raw_orphaned & allowlist)
|
|
158
|
+
orphaned = sorted(raw_orphaned - allowlist)
|
|
159
|
+
# An allowlist entry that no longer matches anything is stale — surface it so the
|
|
160
|
+
# list cannot quietly outlive the quotation that justified it.
|
|
161
|
+
unused_allowlist = sorted(allowlist - raw_orphaned)
|
|
102
162
|
|
|
103
163
|
# Per-requirement coverage map
|
|
104
164
|
coverage: dict[str, list[str]] = {}
|
|
@@ -118,6 +178,8 @@ def main() -> int:
|
|
|
118
178
|
"total_spec_files": len(spec_files),
|
|
119
179
|
"uncovered_requirements": uncovered,
|
|
120
180
|
"orphaned_references": orphaned,
|
|
181
|
+
"allowed_orphans": allowed_orphans,
|
|
182
|
+
"unused_allowlist_entries": unused_allowlist,
|
|
121
183
|
"coverage": coverage,
|
|
122
184
|
"valid": not has_issues,
|
|
123
185
|
}
|
|
@@ -142,8 +204,27 @@ def main() -> int:
|
|
|
142
204
|
print(f" - {req_id}: found in {', '.join(sources)} but not in PRD")
|
|
143
205
|
print()
|
|
144
206
|
|
|
207
|
+
if allowed_orphans:
|
|
208
|
+
print(f"ALLOWED FOREIGN REFERENCES ({len(allowed_orphans)}):")
|
|
209
|
+
for req_id in allowed_orphans:
|
|
210
|
+
sources = [
|
|
211
|
+
name for name, reqs in spec_reqs.items() if req_id in reqs
|
|
212
|
+
]
|
|
213
|
+
print(f" - {req_id}: found in {', '.join(sources)}; allowlisted")
|
|
214
|
+
print()
|
|
215
|
+
|
|
216
|
+
if unused_allowlist:
|
|
217
|
+
print(f"STALE ALLOWLIST ENTRIES ({len(unused_allowlist)}):")
|
|
218
|
+
for req_id in unused_allowlist:
|
|
219
|
+
print(
|
|
220
|
+
f" - {req_id}: allowlisted but no longer referenced — remove it "
|
|
221
|
+
f"from <specs-dir>/{ALLOWLIST_FILENAME} "
|
|
222
|
+
f"(advisory; does not fail this check)"
|
|
223
|
+
)
|
|
224
|
+
print()
|
|
225
|
+
|
|
145
226
|
if not has_issues:
|
|
146
|
-
print("All requirements covered. No orphaned references.")
|
|
227
|
+
print("All requirements covered. No unallowlisted orphaned references.")
|
|
147
228
|
else:
|
|
148
229
|
total_issues = len(uncovered) + len(orphaned)
|
|
149
230
|
print(f"Found {total_issues} issue(s).")
|
|
@@ -41,7 +41,7 @@ R="$(bash -c 'for d in "${CLAUDE_PLUGIN_ROOT:-}" "$HOME"/.claude/skills/feature-
|
|
|
41
41
|
[ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
|
|
42
42
|
python3 "$R/scripts/forge-session.py" rank-features --specs-dir "{specsDir}" --json
|
|
43
43
|
```
|
|
44
|
-
This returns `{active: [...], counts: {...}}` with active features sorted by `updatedAt` **descending** (row 0 is the most recent). Each row carries `currentStage`, `nextStage`, `nextCommand`, `verifyPending`, `verifyCommand`, `verifyStage`, `verifyState` (`fresh`/`stale`/`failing`/`never`/`none`), `autoVerify` (the effective per-stage setting), `autoFix` (the single source of stage order), and `verifyGate` (`none`/`auto`/`standard` — the single resolved verify-gate, computed once by the ranker; read it rather than re-deriving from `verifyPending`+`autoVerify`). A top-level `invalidAutoVerifyKeys` array appears when `forge.config.json` has `autoVerifyStages` keys outside the five verify-capable stages — surface it as a one-line warning. The `active` list excludes nested epic members surfaced in Tier 1 — but the ranker scans them too, so ignore rows whose `epic` is non-null here (they belong to the epic rollup).
|
|
44
|
+
This returns `{active: [...], counts: {...}}` with active features sorted by `updatedAt` **descending** (row 0 is the most recent). Each row carries `currentStage`, `nextStage`, `nextCommand`, `verifyPending`, `verifyCommand`, `verifyStage`, `verifyState` (`fresh`/`stale`/`failing`/`never`/`auto-pending`/`none` — `auto-pending` means automatic verification was **scheduled and recorded on disk but has not run yet**: verification is *owed*, never "never verified", and never resolved), `autoVerify` (the effective per-stage setting), `autoFix` (the single source of stage order), and `verifyGate` (`none`/`auto`/`standard` — the single resolved verify-gate, computed once by the ranker; read it rather than re-deriving from `verifyPending`+`autoVerify`). A top-level `invalidAutoVerifyKeys` array appears when `forge.config.json` has `autoVerifyStages` keys outside the five verify-capable stages — surface it as a one-line warning. The `active` list excludes nested epic members surfaced in Tier 1 — but the ranker scans them too, so ignore rows whose `epic` is non-null here (they belong to the epic rollup).
|
|
45
45
|
- **Pick the feature:** if exactly one active standalone pipeline exists, show its dashboard. If multiple exist, use `AskUserQuestion` — **list the most-recently-updated first, labeled `(recommended)`**, each option's description showing its `currentStage` and a relative age ("updated 2h ago"). Always include a free-form escape ("A different feature / something else") so the user is never boxed in. Then render the chosen feature's dashboard.
|
|
46
46
|
|
|
47
47
|
If no epics and no standalone features exist **on the current branch**, do not conclude the pipeline is empty yet — the state may live on topic branches (a fresh clone / default-branch session sees nothing on disk). Run `discover-feature --all` (via the standard prelude: `python3 "$R/scripts/forge-session.py" discover-feature --all --specs-dir "{specsDir}" --json`). If it surfaces features, list them with their branches and offer to switch (explicit accept + clean tree only, per the Feature Directory Resolution block), then render that feature's dashboard. Only when `--all` also returns nothing, say: "No active feature pipelines found. Start one with `/feature-forge:forge-1-prd <feature-name>` or group several with `/feature-forge:forge-0-epic <epic-name>`." Never fabricate a dashboard from memory of earlier sessions.
|
|
@@ -82,6 +82,7 @@ Use these status indicators:
|
|
|
82
82
|
- ✅🔍 = verified and fixes applied
|
|
83
83
|
- ⏭️ = verification skipped (user chose to proceed without verifying)
|
|
84
84
|
- ⚠️ = stale (built against an older version of an upstream artifact)
|
|
85
|
+
- ⏳ = **automatic verification owed** — the row's `verifyState` is `auto-pending`: verification was scheduled at the producing stage's exit and has not run. Annotate the row with the obligation sentence, naming the served stage and the retry command: `{feature}: automatic verification is still pending for {verifyStage}; run {verifyCommand} to resolve it.` (when the recorded scheduled revision differs from the current one, append both revision numbers). Never render an ⏳ row as ⬜/never-verified — the obligation is recorded on disk and is outstanding, not un-attempted. Do not dump or reformat the state file.
|
|
85
86
|
|
|
86
87
|
### 3b. Drive to the Next Stage
|
|
87
88
|
|
|
@@ -96,7 +97,7 @@ After rendering a **per-feature** dashboard for an **active** pipeline (skip thi
|
|
|
96
97
|
- **Epic member** (this feature's `rank-features` row has a non-null `epic`, i.e. its `.pipeline-state.json` carries an `epic` back-pointer): run `epic-manifest.py render-status "{epic}" --specs-dir "{specsDir}" --json` (standard prelude; you likely already have this from the Tier-1 epic rollup — reuse it rather than re-running). Then:
|
|
97
98
|
- If `actionable` is non-empty, offer the next member via `AskUserQuestion`: *"Epic '{epic}' has {total−complete} feature(s) left — next up: **{actionable[0].name}** (`{actionable[0].nextCommand}`). Start it now?"* On accept, drive it exactly like a normal next stage (honor `autoInvokeNextStage` + `Skill`-tool availability per step 3's Continue-in-this-session rule; else print `{nextCommand}`). List any remaining `actionable` members as also-available.
|
|
98
99
|
- If `actionable` is empty but the epic is **not** fully complete (members blocked on unmet `dependsOn`), say so and point at the blockers rather than offering a start.
|
|
99
|
-
- If the epic is **fully complete** (`rollup.complete == rollup.total`, `total > 0`), congratulate on the whole epic
|
|
100
|
+
- If the epic is **fully complete** (`rollup.complete == rollup.total`, `total > 0`), congratulate on the whole epic. Offer the epic-level architecture doc **only when every member row's `docsStatus` is `complete` or `skipped`** (#173 — the orchestration rollup counts loop-completeness, so it reads full before any docs exist; a `skipped` docs stage satisfies by decision, #197). When some members' docs are still unwritten, point at the next docs run (`/feature-forge:forge-6-docs {member}`) instead of the epic doc. Either way, mention the epic can be marked complete (`/feature-forge:forge {epic}` renders the finished dashboard).
|
|
100
101
|
- **Standalone** (row's `epic` is null): offer to start a fresh feature — *"Start a new feature: `/feature-forge:forge-1-prd <feature-name>` (or group several with `/feature-forge:forge-0-epic <epic-name>`)."* Then, from the `rank-features` `active` list, surface any **other** active pipelines (exclude this just-completed one) as a one-line list with their `nextCommand`s so the user can jump straight back into in-flight work. If the **detached-epic hint above fired** for this feature, lead with that recovery path (`docs/recovery-detached-epic-member.md`) — the split-brain reconcile is the more likely next action than starting something new.
|
|
101
102
|
|
|
102
103
|
**2. Check the context window.** Run the context-usage helper so you can advise whether to continue here or start the next stage in a fresh session:
|
|
@@ -108,13 +109,13 @@ python3 "$R/scripts/forge-session.py" context-usage --json
|
|
|
108
109
|
- `{"available": true, ...}` → note `pct` (e.g. "context ~68% full") and `overThreshold`. Window/threshold come from `contextWindowTokens` / `contextWarnThreshold` in `forge.config.json` (the helper defaults to a 200k window and 0.7 threshold, and auto-bumps the assumed window to 1M once observed usage exceeds 200k; **on a 1M-context model set `contextWindowTokens: 1000000` so the percentage is accurate below 200k too** — 1M can't be detected from the transcript until usage crosses 200k).
|
|
109
110
|
- `{"available": false, ...}` → omit context advice silently (non-Claude host, or a fresh session with no transcript). Never treat this as an error.
|
|
110
111
|
|
|
111
|
-
**2b. Auto-verify catch-up (when `verifyPending` is true).** Under this behavior the just-completed authoring stage runs auto-verify **in-stage** (`references/stage-exit-protocol.md`, in-stage verify block), which clears `verifyPending` — so on the normal path this branch does **nothing**. It fires only as a **catch-up
|
|
112
|
+
**2b. Auto-verify catch-up (when `verifyPending` is true).** Under this behavior the just-completed authoring stage runs auto-verify **in-stage** (`references/stage-exit-protocol.md`, in-stage verify block), which clears `verifyPending` — so on the normal path this branch does **nothing**. It fires only as a **catch-up**, for any of three reasons: the producing stage could not dispatch a clean-room subagent (non-Claude host); it ran before this behavior landed; or the stage exit **recorded durable `auto-verify-pending` debt** that was never discharged — the row's `verifyState` is `auto-pending`, meaning verification was scheduled on disk and never ran (a dropped or declined in-stage dispatch, a crash, or a cleared session). **This branch fires on an `auto-pending` row**: the debt is owed and recorded, so treat it exactly like any other outstanding verification and never as "never verified" or as already discharged. Lead with the obligation sentence from the legend before acting. When it does fire, decide whether verify runs automatically (identical logic to the in-stage run, so a stage that already verified is never double-verified):
|
|
112
113
|
|
|
113
|
-
- **`autoVerify` is true for the just-completed `verifyStage`** → **skip the verify question entirely** and run verify now, *provided it can run clean-room*. Auto-verify is safe to run unattended only because verify executes in a fresh `forge-verifier` subagent that inherits none of this session's context (so no `/clear` is needed and only a compact digest returns). Guard the clean-room assumption: proceed unattended **only when the `Agent` tool + `forge-verifier` subagent are available**. Invoke `feature-forge:forge-verify` via the `Skill` tool in **require-clean (`auto`) mode
|
|
114
|
+
- **`autoVerify` is true for the just-completed `verifyStage`** → **skip the verify question entirely** and run verify now, *provided it can run clean-room*. Auto-verify is safe to run unattended only because verify executes in a fresh `forge-verifier` subagent that inherits none of this session's context (so no `/clear` is needed and only a compact digest returns). Guard the clean-room assumption: proceed unattended **only when the `Agent` tool + `forge-verifier` subagent are available**. Invoke `feature-forge:forge-verify` via the `Skill` tool in **require-clean (`auto`) mode**, passing the literal `owner: nested` token in the invocation prompt — you are the dispatcher here, so **you** are the sole terminal owner and the branch skill prints no terminal block of its own (see "Branch ownership: the `owner:` token" in `references/stage-exit-protocol.md`). This is a **delegate-and-resume** site (see "Caller-side resumption" in the same reference): on the sub-skill's return, control returns here — continue at the matching outcome branch below. In require-clean mode forge-verify refuses to run inline and returns a sentinel if the subagent is not dispatchable (see `skills/forge-verify/SKILL.md`). Then:
|
|
114
115
|
- **Sentinel returned (clean-room unavailable)** → do **not** run verify inline. Degrade to the manual gate: fall through to step 3 with the **"Verify `{stage}` first (manual)"** option included, and if `overThreshold`, recommend "/clear, then verify in a clean session." Verify state stays outstanding; the stage is never advanced on false assurance.
|
|
115
116
|
- **Verify passed / no findings** → proceed to the normal advance gate (step 3), no verify option.
|
|
116
117
|
- **Verify found findings** →
|
|
117
|
-
- **`autoFix` is true AND preconditions hold** — the findings document has **zero unresolved decision points** and the **working tree is clean** → invoke `feature-forge:forge-fix` via the `Skill` tool, then run a **mandatory re-verify** (require-clean mode). Advance only if the re-verify passes. On **any** precondition miss (decisions required, dirty tree), a forge-fix early stop, or a red re-verify → fall back to the digest + prompt below (never a silent partial mutation).
|
|
118
|
+
- **`autoFix` is true AND preconditions hold** — the findings document has **zero unresolved decision points** and the **working tree is clean** → invoke `feature-forge:forge-fix` via the `Skill` tool with the literal `owner: nested` token in the invocation prompt, then run a **mandatory re-verify** (require-clean mode, also `owner: nested`). Every call in this catch-up chain is nested and prints no terminal block — you remain the sole terminal owner and print exactly one closing block after the chain settles. Advance only if the re-verify passes. On **any** precondition miss (decisions required, dirty tree), a forge-fix early stop, or a red re-verify → fall back to the digest + prompt below (never a silent partial mutation).
|
|
118
119
|
- **`autoFix` is false (default), or preconditions failed** → present a **compact findings digest** as text, then `AskUserQuestion`: *Apply fixes now (forge-fix)* / *Review findings* / *Skip & advance*.
|
|
119
120
|
- **`autoVerify` is false/unconfigured** → do not auto-run; use the advance gate in step 3, which gains the folded opt-in verify options ("Verify `{stage}` now" and "Verify `{stage}` now + enable auto-verify going forward").
|
|
120
121
|
|
|
@@ -128,8 +129,8 @@ python3 "$R/scripts/forge-session.py" context-usage --json
|
|
|
128
129
|
|
|
129
130
|
**4. Act on the choice.**
|
|
130
131
|
- **Clean session** (the default) → give the exact next command and the `/clear`-then-re-run instruction; do not invoke anything (you cannot `/clear` for the user).
|
|
131
|
-
- **Continue in this session** → if `autoInvokeNextStage` is true (default) **and** the `Skill` tool is available, invoke the chosen stage **via the `Skill` tool** in this same session (e.g. `skill: "feature-forge:forge-3-specs"`, `args: "{feature}"`) — no retyping, no paste. If `autoInvokeNextStage` is false, or the `Skill` tool is unavailable (a non-Claude host), fall back to printing `{nextCommand}` prominently for the user to run.
|
|
132
|
-
- **Verify now / Verify now + enable auto-verify** → invoke `feature-forge:forge-verify` via the `Skill` tool (require-clean mode). For the **enable-auto-verify** variant, additionally patch `autoVerify: true` into `forge.config.json` in place (preserve formatting and other keys) — never a silent write. On a non-Claude host or when degrading to the manual/inline gate, print `{verifyCommand}` instead.
|
|
132
|
+
- **Continue in this session** → if `autoInvokeNextStage` is true (default) **and** the `Skill` tool is available, invoke the chosen stage **via the `Skill` tool** in this same session (e.g. `skill: "feature-forge:forge-3-specs"`, `args: "{feature}"`) — no retyping, no paste. This advance is a **terminal handoff** (see "Caller-side resumption" in `references/stage-exit-protocol.md`): the invoked stage owns the terminal from here — the navigator's job ends at the invocation, deliberately, not by omission. If `autoInvokeNextStage` is false, or the `Skill` tool is unavailable (a non-Claude host), fall back to printing `{nextCommand}` prominently for the user to run.
|
|
133
|
+
- **Verify now / Verify now + enable auto-verify** → invoke `feature-forge:forge-verify` via the `Skill` tool (require-clean mode) with the literal `owner: nested` token. **Every navigator dispatch of `forge-verify`/`forge-fix` — the step 2b catch-up chain, this gate, and the "Apply fixes now" choice of the findings digest — carries `owner: nested`**, so the branch skill returns its structured result and prints no terminal block, and the navigator stays the sole terminal owner. Each is a **delegate-and-resume** site: on return, control returns to this gate's flow — act on the result (digest, gate, or advance) yourself; the branch skill's own close never ends the dashboard turn. For the **enable-auto-verify** variant, additionally patch `autoVerify: true` into `forge.config.json` in place (preserve formatting and other keys) — never a silent write. On a non-Claude host or when degrading to the manual/inline gate, print `{verifyCommand}` instead.
|
|
133
134
|
- **Different stage** → honor the free-form request.
|
|
134
135
|
|
|
135
136
|
**Host fallback.** On a non-Claude host or when the `Skill`/`Agent` tools are unavailable, auto-verify never runs unattended — fall back to printing `{verifyCommand}` exactly as today, mirroring `autoInvokeNextStage`.
|
|
@@ -150,7 +151,7 @@ and render from its output:
|
|
|
150
151
|
|
|
151
152
|
- **Epic header:** name + `status` (active | paused | abandoned | complete).
|
|
152
153
|
- **Dependency graph:** each feature with its `dependsOn`, as an arrow list or indented tree (the helper guarantees the graph is acyclic).
|
|
153
|
-
- **Per-feature rows:** reuse the **existing status indicators** below (
|
|
154
|
+
- **Per-feature rows:** reuse the **existing status indicators** below (✅/✅⚠️/🔄/⬜/❌/✅🔍/⏭️/⚠️/⏳), driven by each feature's derived `stage`/`status`. Mark `blocked` features and list their `unmetDeps`. `render-status --json` also emits an owed-automatic-verification obligation in its `warnings` array for any member carrying that debt — surface those lines verbatim rather than restating them, and mark those members ⏳, never ⬜.
|
|
154
155
|
- **Pending epic changes:** for any feature with `openEpicChangeRequests > 0`, append a ⚠️ marker and a hint: *"N pending epic change(s) — run `/feature-forge:forge-0-epic {epic}` to reconcile."* If `blockingEpicChangeRequests > 0`, use a stronger marker (⚠️ **blocking**) and word it *"reconcile the epic **before** writing specs"* — this mirrors the pause-now vs finish-then split that stage-exit already routes on. Take these counts **only** from `render-status --json` (`features[].openEpicChangeRequests` / `.blockingEpicChangeRequests`); do not read member `.pipeline-state.json` directly for them.
|
|
155
156
|
- **Actionable vs blocked:** list the `actionable` set and the recommended `nextCommand`.
|
|
156
157
|
- **Rollup:** `{complete}/{total} features complete`.
|
|
@@ -214,7 +215,7 @@ Support these sub-commands for pipeline lifecycle management:
|
|
|
214
215
|
- `/feature-forge:forge run [{feature}]` — **Opt-in auto-advance.** Drive the feature through consecutive stages in one session instead of confirming each boundary. This is a convenience wrapper over **3b. Drive to the Next Stage** — same stage order, same context gate — just looped:
|
|
215
216
|
1. Resolve the feature (if omitted, use the recency default from `rank-features`; if multiple are equally plausible, ask once via `AskUserQuestion`).
|
|
216
217
|
2. **Before each stage,** run `forge-session.py context-usage`. If `overThreshold` is true, **stop** and recommend a clean session (give the exact `{nextCommand}` and the `/clear`-then-re-run instruction) — never auto-`/clear`.
|
|
217
|
-
3. Otherwise invoke the next stage's skill via the `Skill` tool,
|
|
218
|
+
3. Otherwise invoke the next stage's skill via the `Skill` tool as a **delegate-and-resume** invocation, declaring the resume point at the invocation (see "Caller-side resumption: the declared resume point" in `references/stage-exit-protocol.md`): when the stage skill returns, control returns to **this loop, at step 2**, in the same turn — re-read state and continue. The invoked stage's own closing posture never ends the `run` loop.
|
|
218
219
|
4. **Stop conditions:** the next stage is an interview/decision point that calls `AskUserQuestion` (PRD and tech inherently pause for input — let them); `nextStage` is `null` (pipeline complete); context over threshold; or a stage signals it needs human input / is blocked. Always report where the loop stopped and why.
|
|
219
220
|
Per-stage confirmation (3b) remains the default — `run` is only used when the user explicitly asks to "run" / "drive" / "auto-advance" the pipeline. On a non-Claude host where the `Skill` tool is unavailable, fall back to printing the ordered list of commands to run.
|
|
220
221
|
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
},
|
|
38
38
|
"notes": {
|
|
39
39
|
"type": "string",
|
|
40
|
-
"description": "Free-form notes persisted between sessions (user can add context before stepping away)"
|
|
40
|
+
"description": "Free-form notes persisted between sessions (user can add context before stepping away). A single string with latest-note-wins semantics: `state-note` (its only sanctioned writer) OVERWRITES the previous value — an author folds any still-relevant earlier note into the one combined string. Read by the navigator dashboard AND by each downstream stage's Step 1 carried-over note check (forge-2-tech through forge-5-loop), which surfaces it as stage input; it never overrides artifacts or config."
|
|
41
41
|
},
|
|
42
42
|
"epicChangeRequests": {
|
|
43
43
|
"type": "array",
|
|
@@ -127,7 +127,7 @@
|
|
|
127
127
|
"forge-4-backlog": { "$ref": "#/definitions/stageEntry" },
|
|
128
128
|
"forge-verify-backlog": { "$ref": "#/definitions/verifyEntry" },
|
|
129
129
|
"forge-5-loop": { "$ref": "#/definitions/stageEntry" },
|
|
130
|
-
"forge-6-docs": { "$ref": "#/definitions/
|
|
130
|
+
"forge-6-docs": { "$ref": "#/definitions/docsStageEntry" },
|
|
131
131
|
"forge-verify-impl": { "$ref": "#/definitions/verifyEntry" },
|
|
132
132
|
"forge-verify-prd": { "$ref": "#/definitions/verifyEntry" },
|
|
133
133
|
"forge-verify-tech": { "$ref": "#/definitions/verifyEntry" }
|
|
@@ -165,13 +165,45 @@
|
|
|
165
165
|
}
|
|
166
166
|
}
|
|
167
167
|
},
|
|
168
|
+
"docsStageEntry": {
|
|
169
|
+
"type": "object",
|
|
170
|
+
"required": ["status"],
|
|
171
|
+
"description": "The forge-6-docs stage entry: identical to stageEntry except that `skipped` is a legal status and `skippedAt` records when the deliberate skip was written (by the `state-skip` verb, never by hand). `skipped` is a terminal, done-for-selection status — the pipeline ends without the stage claiming artifacts it never produced (#197). Deliberately scoped to the docs stage: a skipped PRD or specs stage is not a representable state, so the shared stageEntry enum does NOT carry `skipped`.",
|
|
172
|
+
"properties": {
|
|
173
|
+
"status": {
|
|
174
|
+
"type": "string",
|
|
175
|
+
"enum": ["pending", "in-progress", "complete", "stale", "skipped"]
|
|
176
|
+
},
|
|
177
|
+
"version": {
|
|
178
|
+
"type": "integer",
|
|
179
|
+
"description": "Incremented each time this stage's artifacts are revised"
|
|
180
|
+
},
|
|
181
|
+
"artifacts": {
|
|
182
|
+
"type": "array",
|
|
183
|
+
"items": { "type": "string" },
|
|
184
|
+
"description": "Relative paths to artifacts produced by this stage"
|
|
185
|
+
},
|
|
186
|
+
"startedAt": { "type": ["string", "null"], "format": "date-time" },
|
|
187
|
+
"completedAt": { "type": ["string", "null"], "format": "date-time" },
|
|
188
|
+
"skippedAt": { "type": ["string", "null"], "format": "date-time", "description": "UTC ISO-8601 timestamp of the deliberate skip (status: skipped). Written by `state-skip`; absent on every other status." },
|
|
189
|
+
"commitHash": {
|
|
190
|
+
"type": ["string", "null"],
|
|
191
|
+
"description": "Git commit SHA of this stage's artifact commit (Commit 1 of the two-commit Git Commit Protocol in shared-conventions.md). Written by a small follow-up commit so it points at the artifact commit itself, never at an orphaned amend or the hash-recording commit. null until recorded (or when there was no new artifact commit)."
|
|
192
|
+
},
|
|
193
|
+
"basedOnVersions": {
|
|
194
|
+
"type": "object",
|
|
195
|
+
"description": "Upstream stage versions this artifact was built against",
|
|
196
|
+
"additionalProperties": { "type": "integer" }
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
},
|
|
168
200
|
"verifyEntry": {
|
|
169
201
|
"type": "object",
|
|
170
202
|
"required": ["status"],
|
|
171
203
|
"properties": {
|
|
172
204
|
"status": {
|
|
173
205
|
"type": "string",
|
|
174
|
-
"enum": ["pending", "passed", "findings-reported", "findings-applied", "skipped"]
|
|
206
|
+
"enum": ["pending", "auto-verify-pending", "passed", "findings-reported", "findings-applied", "skipped"]
|
|
175
207
|
},
|
|
176
208
|
"findingsFile": {
|
|
177
209
|
"type": ["string", "null"],
|
|
@@ -184,7 +216,9 @@
|
|
|
184
216
|
"verifiedAt": { "type": ["string", "null"], "format": "date-time" },
|
|
185
217
|
"fixedAt": { "type": ["string", "null"], "format": "date-time" },
|
|
186
218
|
"commitHash": { "type": ["string", "null"], "description": "Git commit SHA of the verify/fix artifact commit. Recorded via the two-commit Git Commit Protocol (shared-conventions.md) so it points at the artifact commit, never an orphaned amend." },
|
|
187
|
-
"verifiedStageVersion": { "type": ["integer", "null"], "description": "The production stage's `version` at the moment this verify was resolved. The navigator's freshness ledger compares it to the stage's current `version`: equal means the verify is fresh; a mismatch (artifact revised since) or an absent field (legacy state) means stale, so auto-verify re-fires. Recorded by forge-verify/forge-fix when writing a passed/findings-applied status." }
|
|
219
|
+
"verifiedStageVersion": { "type": ["integer", "null"], "description": "The production stage's `version` at the moment this verify was resolved. The navigator's freshness ledger compares it to the stage's current `version`: equal means the verify is fresh; a mismatch (artifact revised since) or an absent field (legacy state) means stale, so auto-verify re-fires. Recorded by forge-verify/forge-fix when writing a passed/findings-applied status." },
|
|
220
|
+
"scheduledAt": { "type": ["string", "null"], "format": "date-time", "description": "UTC ISO-8601 timestamp at which unattended in-stage verification was scheduled for this entry. Written alongside the `auto-verify-pending` status and DELETED (not nulled) by any terminal result, so an absent field means 'not scheduled'." },
|
|
221
|
+
"scheduledStageVersion": { "type": ["integer", "null"], "minimum": 1, "description": "The artifact revision current when verification was scheduled — the production stage's `version` for a feature, the epic manifest's `revision` for an epic. Makes rescheduling idempotent (an identical revision does not rewrite the entry) and lets a read tell debt owed on the current artifact from debt stranded on an older one. Deleted by any terminal result." }
|
|
188
222
|
}
|
|
189
223
|
}
|
|
190
224
|
}
|
|
@@ -36,7 +36,7 @@ I found that the codebase uses React and TanStack Router.
|
|
|
36
36
|
|
|
37
37
|
### Decision Support: Help the User Choose
|
|
38
38
|
|
|
39
|
-
When
|
|
39
|
+
When a question posed through `AskUserQuestion` carries substantive options (a real choice — not a trivial yes/no confirmation), do not just list them. The interview stages have already done codebase research and integration analysis; surfacing that synthesis at the decision moment is the whole point. For every such question:
|
|
40
40
|
|
|
41
41
|
- **Lead with a recommended option.** Place it first and label it `(recommended)` (matching the `AskUserQuestion` "(Recommended)" convention).
|
|
42
42
|
- **Put the trade-off in each option's `description`.** Say why you'd pick it and what you give up versus the alternatives — the cost, not just the benefit.
|
|
@@ -53,6 +53,17 @@ For genuinely comparable artifacts (competing module structures, two code snippe
|
|
|
53
53
|
|
|
54
54
|
The **Branch Setup** block below is the reference pattern: a strong recommendation as the first option, rationale inline, the alternative still available, never a hard-stop.
|
|
55
55
|
|
|
56
|
+
## Stage Review Gate
|
|
57
|
+
|
|
58
|
+
Every authoring stage ends its "Review with User" step in exactly one of two shapes. Which shape a stage uses is declared **here, once** — each stage's review step points at this block by title, and the shape is never re-derived from the surrounding prose or inferred from how sibling stages behave (three stages block and one does not; majority-shape inference is precisely the failure this block exists to prevent):
|
|
59
|
+
|
|
60
|
+
- **Blocking review (gate).** The stage presents the artifact and collects feedback through `AskUserQuestion`; it does **not** proceed until the user answers, iterating until they confirm. Stages: **forge-1-prd** (Step 5), **forge-2-tech** (Step 6), **forge-3-specs** (Step 6).
|
|
61
|
+
- **Non-blocking review (invitation).** The stage states the artifact is ready and invites adjustments **as a statement, not a question** — and then **proceeds to the next step in the same turn unless the user asks for changes**. The invitation obliges the agent to *continue*: emitting the invitation sentence and stopping treats the non-gate as a gate and strands the stage `in-progress` with its completion step unrun — a defect, not caution. Stage: **forge-4-backlog** (Step 6).
|
|
62
|
+
|
|
63
|
+
**Why the shapes differ.** A blocking review guards an artifact whose content was just authored from open-ended interview or synthesis — the user is the only authority on "complete", so the stage must wait. forge-4's backlog is *derived* from specs the user already approved, was planned interactively in its Step 3, and is machine-validated in its Step 5; a second hard gate would re-ask a settled question, and the loop never launches without forge-5-loop's own Step 2d confirmation anyway. The invitation is a courtesy checkpoint, not an approval gate (removed deliberately in #78's consistency sweep).
|
|
64
|
+
|
|
65
|
+
A stage that changes shape changes it **in this block first**; the per-stage pointer stays a pointer.
|
|
66
|
+
|
|
56
67
|
## Configuration Reading
|
|
57
68
|
|
|
58
69
|
Read `forge.config.json` from the project root. If it doesn't exist, use defaults.
|
|
@@ -130,7 +141,7 @@ mkdir -p "<specsDir>"
|
|
|
130
141
|
[ -f "<specsDir>/AGENTS.md" ] || cp "$R/references/templates/specs-hygiene/AGENTS.md" "<specsDir>/AGENTS.md"
|
|
131
142
|
```
|
|
132
143
|
|
|
133
|
-
If the host is Claude (the
|
|
144
|
+
If the host is Claude (the Claude-native question tool is available), also ensure the Claude-framed variant:
|
|
134
145
|
|
|
135
146
|
```bash
|
|
136
147
|
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')"
|
|
@@ -191,6 +202,44 @@ Pipeline state is written by the `state-*` verbs of `scripts/forge-session.py`
|
|
|
191
202
|
|
|
192
203
|
If a `state-*` verb exits 2, surface the plain `Error:` line from stderr verbatim, do **not** proceed to the next step of the surrounding protocol, and do **not** hand-author the JSON as a workaround. The stage remains resumable because the entry stamp is already on disk — re-run the verb once the cause is fixed.
|
|
193
204
|
|
|
205
|
+
**The nine `state-*` verbs.** `state-enter` (Stage-Entry Guard), `state-artifact` (incremental artifact tracking), `state-complete` (Git Commit Protocol), `state-skip` (the deliberate forge-6-docs documentation skip — scoped to that one stage; writes `status: "skipped"` + `skippedAt`, refuses to erase a record of docs that exist, and is the only sanctioned writer of a skipped docs stage), `state-branch` (Branch Setup and Branch Reconciliation), `state-note` (the Immediate Downstream Note below, and the optional completion note at stage closure), `state-decision` (deferred decisions), `state-ecr` (epic change requests), and `state-verify` (one `forge-verify-*` verification transition — below). The `--epic` member requirement and the exit-2 failure protocol above apply to **every** one of them, `state-verify` included; no verify entry is ever hand-authored.
|
|
206
|
+
|
|
207
|
+
### `state-verify` — verification results and provenance
|
|
208
|
+
|
|
209
|
+
`state-verify` writes exactly one `stages.forge-verify-{token}` entry — the verification result for the production stage named by `--stage` — plus the top-level `updatedAt`, and nothing else. `--stage` takes the **served production stage** (`forge-0-epic` through `forge-5-loop`; `forge-6-docs` has no verification token and is rejected). Add `--epic "{epic}"` when the feature is an epic member — required, per the member rule above. Result mode passes `--status` (`auto-verify-pending`, `passed`, `findings-reported`, `findings-applied`, or `skipped`) with whatever `--findings-file`, `--findings-count`, and `--verified-stage-version` that status requires; contradictory metadata is refused before any write. `passed` may additionally carry `--findings-file` + `--findings-count` together for an **advisory-only** report (`inconsistency`/`improvement` findings only, per forge-verify's severity floor) — the stage resolves without a fix round and the report stays attached:
|
|
210
|
+
|
|
211
|
+
**`auto-verify-pending` is not a skill-facing status.** It is written by `stage-exit`'s scheduling boundary, which records the debt automatically when auto-verify is effective for a stage. The value is accepted on this CLI so the entry stays inspectable and repairable, not so a skill can hand-schedule verification: no skill body and no reference passes it, and none should. Every other status in the list is the recorded *result* of a verification that ran (or was explicitly skipped); this one records that one was *owed*.
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
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')"
|
|
215
|
+
[ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
|
|
216
|
+
python3 "$R/scripts/forge-session.py" state-verify \
|
|
217
|
+
--feature "{feature}" --stage "{served-production-stage}" --status "<status>" \
|
|
218
|
+
--specs-dir "{specsDir}"
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Provenance follows the same two-commit sequence as `state-complete`: the result transition above writes `commitHash: null`, Commit 1 records the findings document and the state, and a second `state-verify` call records the full 40-hex hash of Commit 1 and touches nothing else (never `--amend`; an abbreviated hash is refused rather than expanded). Add `--epic "{epic}"` for an epic member — required, per the member rule above:
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
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')"
|
|
225
|
+
[ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
|
|
226
|
+
python3 "$R/scripts/forge-session.py" state-verify \
|
|
227
|
+
--feature "{feature}" --stage "{served-production-stage}" \
|
|
228
|
+
--commit-hash "$(git rev-parse HEAD)" --specs-dir "{specsDir}"
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Epic-scoped verification is the single exception to the member rule: with `--stage forge-0-epic`, `--feature` names the **epic** and `--epic` must be absent or exactly equal to it. That call writes `{specsDir}/{epic}/.epic-state.json` and never a member's `.pipeline-state.json`, and its freshness version is the epic manifest's `revision`, never a member's stage version:
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
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')"
|
|
235
|
+
[ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
|
|
236
|
+
python3 "$R/scripts/forge-session.py" state-verify \
|
|
237
|
+
--feature "{epic}" --stage forge-0-epic --status "<status>" \
|
|
238
|
+
--specs-dir "{specsDir}"
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
On exit 2 the verification result is **not** recorded: surface the `Error:` line verbatim, name the feature (and epic), and do not claim the verification was persisted or advance past it.
|
|
242
|
+
|
|
194
243
|
### Staleness Detection (Read-Time)
|
|
195
244
|
|
|
196
245
|
When loading upstream artifacts as prerequisites, check `basedOnVersions` in the pipeline state for this stage. If any upstream stage's current version is newer than the version recorded in `basedOnVersions`, warn the user before proceeding:
|
|
@@ -199,6 +248,31 @@ When loading upstream artifacts as prerequisites, check `basedOnVersions` in the
|
|
|
199
248
|
|
|
200
249
|
Frame the choice with its cost: re-running re-derives this stage from the current upstream (safest, but discards any hand-edits to this stage's artifacts); proceeding stale is faster but risks baking outdated assumptions into everything downstream. Recommend re-running unless the user knows the upstream change doesn't affect this stage.
|
|
201
250
|
|
|
251
|
+
## Immediate Downstream Note (Parking Lot)
|
|
252
|
+
|
|
253
|
+
When an interview raises a concern that belongs to a *later stage of this same feature*, acknowledge it and persist it **immediately, at the moment it is raised** — not at stage closure — by running `state-note` with a concise one-line statement of the concern. Add `--epic "{epic}"` when this feature is an epic member — required, per the Pipeline State Protocol above; omitting it for a member is an error and must never be allowed to fall back to a same-named flat feature.
|
|
254
|
+
|
|
255
|
+
```bash
|
|
256
|
+
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')"
|
|
257
|
+
[ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
|
|
258
|
+
python3 "$R/scripts/forge-session.py" state-note \
|
|
259
|
+
--feature "{feature}" --note "<concise downstream concern>" \
|
|
260
|
+
--specs-dir "{specsDir}"
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
`state-note` **overwrites** the single top-level `notes` string — it does not append. To preserve an earlier note, read the current `notes` value out of the feature's `.pipeline-state.json` first and pass one combined concise string in a single `--note`; never edit or round-trip the JSON by hand. This interview-time call is separate from the optional completion note offered at stage closure and must not be deferred until then — a session that ends before closure would otherwise lose the concern entirely.
|
|
264
|
+
|
|
265
|
+
On `UsageError`/exit 2, surface the `Error:` line verbatim together with the named feature (and epic) and the recovery instruction, and **stop claiming the concern was recorded** — it was not. Epic *decomposition* changes are not notes: they go through `state-ecr` into `epicChangeRequests`, never into `notes`.
|
|
266
|
+
|
|
267
|
+
## Verify Capability
|
|
268
|
+
|
|
269
|
+
Skills that close a stage pass `--verify-capability interactive|manual` to `stage-exit`. The full determination rule, the Standard Verify Gate, and the recovery path live in `references/stage-exit-protocol.md`; the two facts that are most often gotten wrong:
|
|
270
|
+
|
|
271
|
+
- **Dispatch capability is *permitted* dispatch, not a listed tool.** The question is "**may I dispatch `forge-verifier` right now**", not "is a subagent-dispatch tool in my tool surface". A session can carry a standing host instruction against dispatching subagents unless the user asked; such instructions are injected by the harness, sit outside this project's control, and outrank skill prose. Classify on permission, up front.
|
|
272
|
+
- **A consent requirement is `interactive`, not `manual`.** When dispatch is barred only *unless the user asked* and a question mechanism is available, pass `interactive`: the gate's own affirmative choice supplies the missing user request. Pass `manual` only when there is **no** question mechanism **and** **no** permitted dispatch.
|
|
273
|
+
|
|
274
|
+
A bar on unsolicited dispatch is never grounds to skip verification, and never grounds to fence the production successor while verification is unresolved. On the `runInStageVerify: true` path the emitted `verifyGate` stays `none`: reuse the Standard Verify Gate block for consent with **choice 2 omitted** (auto-verify is already effective, so "enable auto-verify going forward" is a no-op), leaving exactly two choices: *Verify now* (recommended) and *Skip for now*. The clean-room `forge-verifier` is **dispatched on the affirmative choice**, never merely printed for the user to run later; *Skip for now* is persisted as an explicit `skipped` before any advancing block.
|
|
275
|
+
|
|
202
276
|
## Branch Setup
|
|
203
277
|
|
|
204
278
|
Invoke this block at the **very start** of a pipeline entry point — `forge-1-prd` (standalone feature) and `forge-0-epic` (epic) — **before** any directory resolution or interview, so the rest of the run lands on the intended branch. `{label}` is the feature name (forge-1-prd) or epic name (forge-0-epic); `{scope}` is `feature` or `epic` correspondingly.
|
|
@@ -332,7 +406,7 @@ Invoke this block **at the head of any post-entry step that writes a stage artif
|
|
|
332
406
|
|
|
333
407
|
1. **Proceed** when `stages.{stage}.status` is `"in-progress"` (this session's Entry Stamp — you are finishing the run you started) or absent/`pending`. Run the write / exit normally.
|
|
334
408
|
|
|
335
|
-
2. **Detect-and-refuse** when ALL of these hold: `stages.{stage}.status ∈ {"complete", "stale"}` **AND** the stage's artifacts (incl. `TRACEABILITY.md` for forge-3-specs) exist on disk **AND** a `commitHash` is recorded for the stage **AND** you did **not** author this stage earlier in the current session. This is a stale/replayed continuation of an already-finished, committed stage. Do **not** overwrite the artifact or re-run the exit. Route instead to the **Stage-Entry Guard**'s *Re-authoring* path: surface the same `AskUserQuestion`
|
|
409
|
+
2. **Detect-and-refuse** when ALL of these hold: `stages.{stage}.status ∈ {"complete", "stale"}` **AND** the stage's artifacts (incl. `TRACEABILITY.md` for forge-3-specs) exist on disk **AND** a `commitHash` is recorded for the stage **AND** you did **not** author this stage earlier in the current session. This is a stale/replayed continuation of an already-finished, committed stage. Do **not** overwrite the artifact or re-run the exit. Route instead to the **Stage-Entry Guard**'s *Re-authoring* path: surface the same warning via `AskUserQuestion` ("A completed {stage} artifact already exists for '{feature}' (v{n}{, marked stale}). Continuing will create a new version. Proceed?"). Only on explicit confirmation re-enter from the Entry Stamp (the version bumps at exit); otherwise **stop** and report that the stage is already complete — cite the recorded `commitHash` and offer `/feature-forge:forge {feature}` to see true state.
|
|
336
410
|
|
|
337
411
|
When you cannot confirm you authored the current run, treat it as a replay and refuse: a false refuse costs one confirmation click; a false proceed overwrites a committed artifact and re-churns a stage version. `--force` follows Force Mode (skip the gate, treat as a deliberate re-author).
|
|
338
412
|
|