@garygentry/feature-forge 0.3.2 → 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-state-schema.json +50 -0
- package/adapters/claude/references/forge-config-schema.json +18 -0
- package/adapters/claude/references/forge-decisions-schema.json +33 -0
- package/adapters/claude/references/pipeline-state-schema.json +34 -2
- package/adapters/claude/references/ralph-loop-contract.md +6 -3
- package/adapters/claude/references/shared-conventions.md +15 -4
- package/adapters/claude/references/stage-exit-protocol.md +55 -11
- package/adapters/claude/scripts/epic-manifest.py +82 -4
- package/adapters/claude/scripts/fix-sweep.py +1180 -0
- package/adapters/claude/scripts/forge-session.py +1124 -26
- package/adapters/claude/skills/forge/SKILL.md +5 -5
- package/adapters/claude/skills/forge/references/pipeline-state-schema.json +34 -2
- package/adapters/claude/skills/forge/references/shared-conventions.md +15 -4
- package/adapters/claude/skills/forge/references/stage-exit-protocol.md +55 -11
- package/adapters/claude/skills/forge-0-epic/references/edit-mode.md +5 -1
- 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 +34 -2
- package/adapters/claude/skills/forge-0-epic/references/shared-conventions.md +15 -4
- package/adapters/claude/skills/forge-0-epic/references/stage-exit-protocol.md +55 -11
- package/adapters/claude/skills/forge-1-prd/SKILL.md +3 -1
- package/adapters/claude/skills/forge-1-prd/references/shared-conventions.md +15 -4
- package/adapters/claude/skills/forge-1-prd/references/stage-exit-protocol.md +55 -11
- package/adapters/claude/skills/forge-2-tech/SKILL.md +5 -1
- package/adapters/claude/skills/forge-2-tech/references/shared-conventions.md +15 -4
- package/adapters/claude/skills/forge-2-tech/references/stage-exit-protocol.md +55 -11
- package/adapters/claude/skills/forge-3-specs/SKILL.md +5 -1
- package/adapters/claude/skills/forge-3-specs/references/shared-conventions.md +15 -4
- package/adapters/claude/skills/forge-3-specs/references/stage-exit-protocol.md +55 -11
- package/adapters/claude/skills/forge-4-backlog/SKILL.md +41 -3
- package/adapters/claude/skills/forge-4-backlog/references/shared-conventions.md +15 -4
- package/adapters/claude/skills/forge-4-backlog/references/stage-exit-protocol.md +55 -11
- package/adapters/claude/skills/forge-5-loop/SKILL.md +36 -36
- 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 +40 -11
- package/adapters/claude/skills/forge-5-loop/references/runner-contract.md +22 -4
- package/adapters/claude/skills/forge-5-loop/references/shared-conventions.md +15 -4
- package/adapters/claude/skills/forge-5-loop/references/stage-exit-protocol.md +55 -11
- package/adapters/claude/skills/forge-6-docs/SKILL.md +29 -6
- package/adapters/claude/skills/forge-6-docs/references/shared-conventions.md +15 -4
- package/adapters/claude/skills/forge-6-docs/references/stage-exit-protocol.md +55 -11
- package/adapters/claude/skills/forge-fix/SKILL.md +34 -0
- package/adapters/claude/skills/forge-fix/references/shared-conventions.md +15 -4
- package/adapters/claude/skills/forge-fix/references/stage-exit-protocol.md +55 -11
- package/adapters/claude/skills/forge-guide/references/forge-config-schema.json +18 -0
- package/adapters/claude/skills/forge-guide/references/ralph-loop-contract.md +6 -3
- package/adapters/claude/skills/forge-guide/references/shared-conventions.md +15 -4
- package/adapters/claude/skills/forge-verify/SKILL.md +10 -11
- 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 +30 -0
- package/adapters/claude/skills/forge-verify/references/shared-conventions.md +15 -4
- package/adapters/claude/skills/forge-verify/references/stage-exit-protocol.md +55 -11
- package/adapters/claude/skills/forge-verify/references/verification-checklists/backlog.md +73 -0
- package/adapters/claude/skills/forge-verify/references/verification-checklists/impl.md +85 -0
- package/adapters/claude/skills/forge-verify/references/verification-checklists/specs.md +43 -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-state-schema.json +50 -0
- package/adapters/codex/references/forge-config-schema.json +18 -0
- package/adapters/codex/references/forge-decisions-schema.json +33 -0
- package/adapters/codex/references/pipeline-state-schema.json +34 -2
- 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 +44 -33
- package/adapters/codex/references/stage-exit-protocol.md +64 -20
- package/adapters/codex/scripts/epic-manifest.py +82 -4
- package/adapters/codex/scripts/fix-sweep.py +1180 -0
- package/adapters/codex/scripts/forge-session.py +1124 -26
- package/adapters/codex/skills/forge/SKILL.md +8 -8
- package/adapters/codex/skills/forge/references/pipeline-state-schema.json +34 -2
- package/adapters/codex/skills/forge/references/process-overview.md +2 -2
- package/adapters/codex/skills/forge/references/shared-conventions.md +44 -33
- package/adapters/codex/skills/forge/references/stage-exit-protocol.md +64 -20
- package/adapters/codex/skills/forge-0-epic/references/edit-mode.md +14 -10
- 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 +34 -2
- package/adapters/codex/skills/forge-0-epic/references/shared-conventions.md +44 -33
- package/adapters/codex/skills/forge-0-epic/references/stage-exit-protocol.md +64 -20
- package/adapters/codex/skills/forge-1-prd/SKILL.md +3 -1
- package/adapters/codex/skills/forge-1-prd/references/shared-conventions.md +44 -33
- package/adapters/codex/skills/forge-1-prd/references/stage-exit-protocol.md +64 -20
- package/adapters/codex/skills/forge-2-tech/SKILL.md +5 -1
- package/adapters/codex/skills/forge-2-tech/references/shared-conventions.md +44 -33
- package/adapters/codex/skills/forge-2-tech/references/stage-exit-protocol.md +64 -20
- package/adapters/codex/skills/forge-3-specs/SKILL.md +5 -1
- package/adapters/codex/skills/forge-3-specs/references/shared-conventions.md +44 -33
- package/adapters/codex/skills/forge-3-specs/references/stage-exit-protocol.md +64 -20
- package/adapters/codex/skills/forge-4-backlog/SKILL.md +41 -3
- package/adapters/codex/skills/forge-4-backlog/references/shared-conventions.md +44 -33
- package/adapters/codex/skills/forge-4-backlog/references/stage-exit-protocol.md +64 -20
- package/adapters/codex/skills/forge-5-loop/SKILL.md +36 -36
- 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 +40 -11
- package/adapters/codex/skills/forge-5-loop/references/runner-contract.md +26 -8
- package/adapters/codex/skills/forge-5-loop/references/shared-conventions.md +44 -33
- package/adapters/codex/skills/forge-5-loop/references/stage-exit-protocol.md +64 -20
- package/adapters/codex/skills/forge-6-docs/SKILL.md +29 -6
- package/adapters/codex/skills/forge-6-docs/references/shared-conventions.md +44 -33
- package/adapters/codex/skills/forge-6-docs/references/stage-exit-protocol.md +64 -20
- package/adapters/codex/skills/forge-fix/SKILL.md +34 -0
- package/adapters/codex/skills/forge-fix/references/shared-conventions.md +44 -33
- package/adapters/codex/skills/forge-fix/references/stage-exit-protocol.md +64 -20
- package/adapters/codex/skills/forge-guide/SKILL.md +1 -1
- package/adapters/codex/skills/forge-guide/references/forge-config-schema.json +18 -0
- 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 +44 -33
- package/adapters/codex/skills/forge-init/SKILL.md +1 -1
- package/adapters/codex/skills/forge-verify/SKILL.md +11 -12
- 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 +32 -2
- package/adapters/codex/skills/forge-verify/references/shared-conventions.md +44 -33
- package/adapters/codex/skills/forge-verify/references/stage-exit-protocol.md +64 -20
- package/adapters/codex/skills/forge-verify/references/verification-checklists/backlog.md +73 -0
- package/adapters/codex/skills/forge-verify/references/verification-checklists/epic.md +1 -1
- package/adapters/codex/skills/forge-verify/references/verification-checklists/impl.md +85 -0
- package/adapters/codex/skills/forge-verify/references/verification-checklists/specs.md +43 -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-state-schema.json +50 -0
- package/adapters/copilot/references/forge-config-schema.json +18 -0
- package/adapters/copilot/references/forge-decisions-schema.json +33 -0
- package/adapters/copilot/references/pipeline-state-schema.json +34 -2
- 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 +44 -33
- package/adapters/copilot/references/stage-exit-protocol.md +64 -20
- package/adapters/copilot/scripts/epic-manifest.py +82 -4
- package/adapters/copilot/scripts/fix-sweep.py +1180 -0
- package/adapters/copilot/scripts/forge-session.py +1124 -26
- package/adapters/copilot/skills/forge/forge.md +8 -8
- package/adapters/copilot/skills/forge/references/pipeline-state-schema.json +34 -2
- package/adapters/copilot/skills/forge/references/process-overview.md +2 -2
- package/adapters/copilot/skills/forge/references/shared-conventions.md +44 -33
- package/adapters/copilot/skills/forge/references/stage-exit-protocol.md +64 -20
- package/adapters/copilot/skills/forge-0-epic/references/edit-mode.md +14 -10
- 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 +34 -2
- package/adapters/copilot/skills/forge-0-epic/references/shared-conventions.md +44 -33
- package/adapters/copilot/skills/forge-0-epic/references/stage-exit-protocol.md +64 -20
- package/adapters/copilot/skills/forge-1-prd/forge-1-prd.md +3 -1
- package/adapters/copilot/skills/forge-1-prd/references/shared-conventions.md +44 -33
- package/adapters/copilot/skills/forge-1-prd/references/stage-exit-protocol.md +64 -20
- package/adapters/copilot/skills/forge-2-tech/forge-2-tech.md +5 -1
- package/adapters/copilot/skills/forge-2-tech/references/shared-conventions.md +44 -33
- package/adapters/copilot/skills/forge-2-tech/references/stage-exit-protocol.md +64 -20
- package/adapters/copilot/skills/forge-3-specs/forge-3-specs.md +5 -1
- package/adapters/copilot/skills/forge-3-specs/references/shared-conventions.md +44 -33
- package/adapters/copilot/skills/forge-3-specs/references/stage-exit-protocol.md +64 -20
- package/adapters/copilot/skills/forge-4-backlog/forge-4-backlog.md +41 -3
- package/adapters/copilot/skills/forge-4-backlog/references/shared-conventions.md +44 -33
- package/adapters/copilot/skills/forge-4-backlog/references/stage-exit-protocol.md +64 -20
- package/adapters/copilot/skills/forge-5-loop/forge-5-loop.md +36 -36
- 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 +40 -11
- package/adapters/copilot/skills/forge-5-loop/references/runner-contract.md +26 -8
- package/adapters/copilot/skills/forge-5-loop/references/shared-conventions.md +44 -33
- package/adapters/copilot/skills/forge-5-loop/references/stage-exit-protocol.md +64 -20
- package/adapters/copilot/skills/forge-6-docs/forge-6-docs.md +29 -6
- package/adapters/copilot/skills/forge-6-docs/references/shared-conventions.md +44 -33
- package/adapters/copilot/skills/forge-6-docs/references/stage-exit-protocol.md +64 -20
- package/adapters/copilot/skills/forge-fix/forge-fix.md +34 -0
- package/adapters/copilot/skills/forge-fix/references/shared-conventions.md +44 -33
- package/adapters/copilot/skills/forge-fix/references/stage-exit-protocol.md +64 -20
- package/adapters/copilot/skills/forge-guide/forge-guide.md +1 -1
- package/adapters/copilot/skills/forge-guide/references/forge-config-schema.json +18 -0
- 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 +44 -33
- package/adapters/copilot/skills/forge-init/forge-init.md +1 -1
- package/adapters/copilot/skills/forge-verify/forge-verify.md +11 -12
- 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 +32 -2
- package/adapters/copilot/skills/forge-verify/references/shared-conventions.md +44 -33
- package/adapters/copilot/skills/forge-verify/references/stage-exit-protocol.md +64 -20
- package/adapters/copilot/skills/forge-verify/references/verification-checklists/backlog.md +73 -0
- package/adapters/copilot/skills/forge-verify/references/verification-checklists/epic.md +1 -1
- package/adapters/copilot/skills/forge-verify/references/verification-checklists/impl.md +85 -0
- package/adapters/copilot/skills/forge-verify/references/verification-checklists/specs.md +43 -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-state-schema.json +50 -0
- package/adapters/cursor/references/forge-config-schema.json +18 -0
- package/adapters/cursor/references/forge-decisions-schema.json +33 -0
- package/adapters/cursor/references/pipeline-state-schema.json +34 -2
- 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 +44 -33
- package/adapters/cursor/references/stage-exit-protocol.md +64 -20
- package/adapters/cursor/scripts/epic-manifest.py +82 -4
- package/adapters/cursor/scripts/fix-sweep.py +1180 -0
- package/adapters/cursor/scripts/forge-session.py +1124 -26
- package/adapters/cursor/skills/forge/forge.mdc +8 -8
- package/adapters/cursor/skills/forge/references/pipeline-state-schema.json +34 -2
- package/adapters/cursor/skills/forge/references/process-overview.md +2 -2
- package/adapters/cursor/skills/forge/references/shared-conventions.md +44 -33
- package/adapters/cursor/skills/forge/references/stage-exit-protocol.md +64 -20
- package/adapters/cursor/skills/forge-0-epic/references/edit-mode.md +14 -10
- 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 +34 -2
- package/adapters/cursor/skills/forge-0-epic/references/shared-conventions.md +44 -33
- package/adapters/cursor/skills/forge-0-epic/references/stage-exit-protocol.md +64 -20
- package/adapters/cursor/skills/forge-1-prd/forge-1-prd.mdc +3 -1
- package/adapters/cursor/skills/forge-1-prd/references/shared-conventions.md +44 -33
- package/adapters/cursor/skills/forge-1-prd/references/stage-exit-protocol.md +64 -20
- package/adapters/cursor/skills/forge-2-tech/forge-2-tech.mdc +5 -1
- package/adapters/cursor/skills/forge-2-tech/references/shared-conventions.md +44 -33
- package/adapters/cursor/skills/forge-2-tech/references/stage-exit-protocol.md +64 -20
- package/adapters/cursor/skills/forge-3-specs/forge-3-specs.mdc +5 -1
- package/adapters/cursor/skills/forge-3-specs/references/shared-conventions.md +44 -33
- package/adapters/cursor/skills/forge-3-specs/references/stage-exit-protocol.md +64 -20
- package/adapters/cursor/skills/forge-4-backlog/forge-4-backlog.mdc +41 -3
- package/adapters/cursor/skills/forge-4-backlog/references/shared-conventions.md +44 -33
- package/adapters/cursor/skills/forge-4-backlog/references/stage-exit-protocol.md +64 -20
- package/adapters/cursor/skills/forge-5-loop/forge-5-loop.mdc +36 -36
- 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 +40 -11
- package/adapters/cursor/skills/forge-5-loop/references/runner-contract.md +26 -8
- package/adapters/cursor/skills/forge-5-loop/references/shared-conventions.md +44 -33
- package/adapters/cursor/skills/forge-5-loop/references/stage-exit-protocol.md +64 -20
- package/adapters/cursor/skills/forge-6-docs/forge-6-docs.mdc +29 -6
- package/adapters/cursor/skills/forge-6-docs/references/shared-conventions.md +44 -33
- package/adapters/cursor/skills/forge-6-docs/references/stage-exit-protocol.md +64 -20
- package/adapters/cursor/skills/forge-fix/forge-fix.mdc +34 -0
- package/adapters/cursor/skills/forge-fix/references/shared-conventions.md +44 -33
- package/adapters/cursor/skills/forge-fix/references/stage-exit-protocol.md +64 -20
- package/adapters/cursor/skills/forge-guide/forge-guide.mdc +1 -1
- package/adapters/cursor/skills/forge-guide/references/forge-config-schema.json +18 -0
- 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 +44 -33
- package/adapters/cursor/skills/forge-init/forge-init.mdc +1 -1
- package/adapters/cursor/skills/forge-verify/forge-verify.mdc +11 -12
- 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 +32 -2
- package/adapters/cursor/skills/forge-verify/references/shared-conventions.md +44 -33
- package/adapters/cursor/skills/forge-verify/references/stage-exit-protocol.md +64 -20
- package/adapters/cursor/skills/forge-verify/references/verification-checklists/backlog.md +73 -0
- package/adapters/cursor/skills/forge-verify/references/verification-checklists/epic.md +1 -1
- package/adapters/cursor/skills/forge-verify/references/verification-checklists/impl.md +85 -0
- package/adapters/cursor/skills/forge-verify/references/verification-checklists/specs.md +43 -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-state-schema.json +50 -0
- package/adapters/gemini/references/forge-config-schema.json +18 -0
- package/adapters/gemini/references/forge-decisions-schema.json +33 -0
- package/adapters/gemini/references/pipeline-state-schema.json +34 -2
- 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 +44 -33
- package/adapters/gemini/references/stage-exit-protocol.md +64 -20
- package/adapters/gemini/scripts/epic-manifest.py +82 -4
- package/adapters/gemini/scripts/fix-sweep.py +1180 -0
- package/adapters/gemini/scripts/forge-session.py +1124 -26
- package/adapters/gemini/skills/forge/forge.md +8 -8
- package/adapters/gemini/skills/forge/references/pipeline-state-schema.json +34 -2
- package/adapters/gemini/skills/forge/references/process-overview.md +2 -2
- package/adapters/gemini/skills/forge/references/shared-conventions.md +44 -33
- package/adapters/gemini/skills/forge/references/stage-exit-protocol.md +64 -20
- package/adapters/gemini/skills/forge-0-epic/references/edit-mode.md +14 -10
- 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 +34 -2
- package/adapters/gemini/skills/forge-0-epic/references/shared-conventions.md +44 -33
- package/adapters/gemini/skills/forge-0-epic/references/stage-exit-protocol.md +64 -20
- package/adapters/gemini/skills/forge-1-prd/forge-1-prd.md +3 -1
- package/adapters/gemini/skills/forge-1-prd/references/shared-conventions.md +44 -33
- package/adapters/gemini/skills/forge-1-prd/references/stage-exit-protocol.md +64 -20
- package/adapters/gemini/skills/forge-2-tech/forge-2-tech.md +5 -1
- package/adapters/gemini/skills/forge-2-tech/references/shared-conventions.md +44 -33
- package/adapters/gemini/skills/forge-2-tech/references/stage-exit-protocol.md +64 -20
- package/adapters/gemini/skills/forge-3-specs/forge-3-specs.md +5 -1
- package/adapters/gemini/skills/forge-3-specs/references/shared-conventions.md +44 -33
- package/adapters/gemini/skills/forge-3-specs/references/stage-exit-protocol.md +64 -20
- package/adapters/gemini/skills/forge-4-backlog/forge-4-backlog.md +41 -3
- package/adapters/gemini/skills/forge-4-backlog/references/shared-conventions.md +44 -33
- package/adapters/gemini/skills/forge-4-backlog/references/stage-exit-protocol.md +64 -20
- package/adapters/gemini/skills/forge-5-loop/forge-5-loop.md +36 -36
- 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 +40 -11
- package/adapters/gemini/skills/forge-5-loop/references/runner-contract.md +26 -8
- package/adapters/gemini/skills/forge-5-loop/references/shared-conventions.md +44 -33
- package/adapters/gemini/skills/forge-5-loop/references/stage-exit-protocol.md +64 -20
- package/adapters/gemini/skills/forge-6-docs/forge-6-docs.md +29 -6
- package/adapters/gemini/skills/forge-6-docs/references/shared-conventions.md +44 -33
- package/adapters/gemini/skills/forge-6-docs/references/stage-exit-protocol.md +64 -20
- package/adapters/gemini/skills/forge-fix/forge-fix.md +34 -0
- package/adapters/gemini/skills/forge-fix/references/shared-conventions.md +44 -33
- package/adapters/gemini/skills/forge-fix/references/stage-exit-protocol.md +64 -20
- package/adapters/gemini/skills/forge-guide/forge-guide.md +1 -1
- package/adapters/gemini/skills/forge-guide/references/forge-config-schema.json +18 -0
- 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 +44 -33
- package/adapters/gemini/skills/forge-init/forge-init.md +1 -1
- package/adapters/gemini/skills/forge-verify/forge-verify.md +11 -12
- 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 +32 -2
- package/adapters/gemini/skills/forge-verify/references/shared-conventions.md +44 -33
- package/adapters/gemini/skills/forge-verify/references/stage-exit-protocol.md +64 -20
- package/adapters/gemini/skills/forge-verify/references/verification-checklists/backlog.md +73 -0
- package/adapters/gemini/skills/forge-verify/references/verification-checklists/epic.md +1 -1
- package/adapters/gemini/skills/forge-verify/references/verification-checklists/impl.md +85 -0
- package/adapters/gemini/skills/forge-verify/references/verification-checklists/specs.md +43 -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-state-schema.json +50 -0
- package/adapters/pi/references/forge-config-schema.json +18 -0
- package/adapters/pi/references/forge-decisions-schema.json +33 -0
- package/adapters/pi/references/pipeline-state-schema.json +34 -2
- 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 +33 -22
- package/adapters/pi/references/stage-exit-protocol.md +63 -19
- package/adapters/pi/scripts/epic-manifest.py +82 -4
- package/adapters/pi/scripts/fix-sweep.py +1180 -0
- package/adapters/pi/scripts/forge-session.py +1124 -26
- package/adapters/pi/skills/forge/SKILL.md +5 -5
- package/adapters/pi/skills/forge/references/pipeline-state-schema.json +34 -2
- package/adapters/pi/skills/forge/references/process-overview.md +2 -2
- package/adapters/pi/skills/forge/references/shared-conventions.md +33 -22
- package/adapters/pi/skills/forge/references/stage-exit-protocol.md +63 -19
- package/adapters/pi/skills/forge-0-epic/references/edit-mode.md +8 -4
- 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 +34 -2
- package/adapters/pi/skills/forge-0-epic/references/shared-conventions.md +33 -22
- package/adapters/pi/skills/forge-0-epic/references/stage-exit-protocol.md +63 -19
- package/adapters/pi/skills/forge-1-prd/SKILL.md +3 -1
- package/adapters/pi/skills/forge-1-prd/references/shared-conventions.md +33 -22
- package/adapters/pi/skills/forge-1-prd/references/stage-exit-protocol.md +63 -19
- package/adapters/pi/skills/forge-2-tech/SKILL.md +5 -1
- package/adapters/pi/skills/forge-2-tech/references/shared-conventions.md +33 -22
- package/adapters/pi/skills/forge-2-tech/references/stage-exit-protocol.md +63 -19
- package/adapters/pi/skills/forge-3-specs/SKILL.md +5 -1
- package/adapters/pi/skills/forge-3-specs/references/shared-conventions.md +33 -22
- package/adapters/pi/skills/forge-3-specs/references/stage-exit-protocol.md +63 -19
- package/adapters/pi/skills/forge-4-backlog/SKILL.md +41 -3
- package/adapters/pi/skills/forge-4-backlog/references/shared-conventions.md +33 -22
- package/adapters/pi/skills/forge-4-backlog/references/stage-exit-protocol.md +63 -19
- package/adapters/pi/skills/forge-5-loop/SKILL.md +36 -36
- 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 +40 -11
- package/adapters/pi/skills/forge-5-loop/references/runner-contract.md +25 -7
- package/adapters/pi/skills/forge-5-loop/references/shared-conventions.md +33 -22
- package/adapters/pi/skills/forge-5-loop/references/stage-exit-protocol.md +63 -19
- package/adapters/pi/skills/forge-6-docs/SKILL.md +29 -6
- package/adapters/pi/skills/forge-6-docs/references/shared-conventions.md +33 -22
- package/adapters/pi/skills/forge-6-docs/references/stage-exit-protocol.md +63 -19
- package/adapters/pi/skills/forge-fix/SKILL.md +34 -0
- package/adapters/pi/skills/forge-fix/references/shared-conventions.md +33 -22
- package/adapters/pi/skills/forge-fix/references/stage-exit-protocol.md +63 -19
- package/adapters/pi/skills/forge-guide/references/forge-config-schema.json +18 -0
- 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 +33 -22
- package/adapters/pi/skills/forge-verify/SKILL.md +10 -11
- 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 +31 -1
- package/adapters/pi/skills/forge-verify/references/shared-conventions.md +33 -22
- package/adapters/pi/skills/forge-verify/references/stage-exit-protocol.md +63 -19
- package/adapters/pi/skills/forge-verify/references/verification-checklists/backlog.md +73 -0
- package/adapters/pi/skills/forge-verify/references/verification-checklists/epic.md +1 -1
- package/adapters/pi/skills/forge-verify/references/verification-checklists/impl.md +85 -0
- package/adapters/pi/skills/forge-verify/references/verification-checklists/specs.md +43 -1
- package/package.json +1 -1
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
# forge-5-loop — Post-Run Recovery Procedure
|
|
2
|
+
|
|
3
|
+
The named procedure that turns a needs-human / blocked loop stop into a resumable backlog
|
|
4
|
+
without losing the operator's decision. It runs **after** a loop run ends — entered
|
|
5
|
+
**unconditionally** from SKILL Step 4c on every run close, whatever the counts say (the
|
|
6
|
+
`needs_human` / `item_blocked` live-event handling in `runner-contract.md` collects
|
|
7
|
+
answers early for it, but is **not** the entry condition) — and it runs again as the
|
|
8
|
+
**re-entry point** on a fresh session (§3).
|
|
9
|
+
Its seven ordered steps: **enumerate → cluster → consolidated prompts →
|
|
10
|
+
record-at-collection → apply → prove → gate & exit**.
|
|
11
|
+
|
|
12
|
+
Notation: `{backlogDir}` is the resolved backlog directory (SKILL Step 2b);
|
|
13
|
+
`{stateDir}` is the effective-config `loopRunner.stateDir` (default `.rauf`); `$R` is the
|
|
14
|
+
plugin root the SKILL's bootstrap prelude resolves; runner commands are the substituted
|
|
15
|
+
`loopRunner.*Command` forms with the SKILL's token substitution (`{bin}` etc.).
|
|
16
|
+
|
|
17
|
+
## 1. Scope and the failure rule
|
|
18
|
+
|
|
19
|
+
The procedure orchestrates scripted substrate; it never improvises state. Decisions live
|
|
20
|
+
in `{backlogDir}/{stateDir}/forge-decisions.json` — append-only, written **only** by the
|
|
21
|
+
`decision-record` / `decision-list` / `decision-apply` verbs of
|
|
22
|
+
`scripts/forge-session.py` (schema: `references/forge-decisions-schema.json`), never by
|
|
23
|
+
hand. Being under the git-ignored state dir, the record survives session end and context
|
|
24
|
+
clear but never dirties the working tree that §4 inspects.
|
|
25
|
+
|
|
26
|
+
**The failure rule (applies to every step).** Any scripted step that exits non-zero, and
|
|
27
|
+
any runner invocation that errors or returns unparseable output, is surfaced **verbatim**
|
|
28
|
+
and **STOPS** the procedure with a **failed recovery** report — never reported as
|
|
29
|
+
recorded/succeeded. A failed *apply* (step 5) is distinguishable from a
|
|
30
|
+
ran-but-nothing-moved *proof* failure (step 6) because the former never reaches step 6
|
|
31
|
+
(§6).
|
|
32
|
+
|
|
33
|
+
## 2. The seven steps
|
|
34
|
+
|
|
35
|
+
### Step 1 — Enumerate
|
|
36
|
+
|
|
37
|
+
- **Input:** `{backlogDir}`; the runner's authoritative item list.
|
|
38
|
+
- **CLI:**
|
|
39
|
+
```
|
|
40
|
+
python3 "$R/scripts/forge-session.py" decision-list --backlog-dir {backlogDir} --unapplied --json
|
|
41
|
+
{bin} backlog list . --backlog {backlogDir} --json # the substituted listCommand
|
|
42
|
+
```
|
|
43
|
+
The unapplied set is the **latest entry per `itemId` with `appliedAt == null`** —
|
|
44
|
+
deferrals included, applied items excluded.
|
|
45
|
+
- **Decision point:** if the unapplied set is **empty** and no item is
|
|
46
|
+
`blocked`/`needsHuman`, there is nothing to decide or apply: **skip steps 2–6 and go
|
|
47
|
+
straight to step 7 — never exit around it.** Step 7's §4 tree reconciliation still
|
|
48
|
+
runs (it is what catches work stranded without any signal), and its `resolved` gate
|
|
49
|
+
does not apply — **an empty affected set never selects `resolved`**; the SKILL Step 7
|
|
50
|
+
ladder falls through to its count-based rungs. Combined with the clean-tree silence
|
|
51
|
+
of §4.1, this keeps a happy-path run free of any new prompt; the only new happy-path
|
|
52
|
+
output is the Step 2a depth line.
|
|
53
|
+
- **Output:** the unapplied-decision set (each entry's `itemId`, `question`,
|
|
54
|
+
`answer|null`, `deferred`, `clusterId?`), and the live blocked/needs-human item set.
|
|
55
|
+
- **Error:** a `decision-list` exit 2 (unknown dir, unparseable record) stops the
|
|
56
|
+
procedure. A failed `listCommand` read stops it as a failed recovery.
|
|
57
|
+
|
|
58
|
+
### Step 2 — Cluster
|
|
59
|
+
|
|
60
|
+
- **Input:** the blocked/needs-human items from step 1, each carrying its
|
|
61
|
+
`blockedReason` (where the runner lands the `RAUF_NEEDS_HUMAN:<reason>` text).
|
|
62
|
+
- **CLI:**
|
|
63
|
+
```
|
|
64
|
+
python3 "$R/scripts/forge-session.py" backlog-topology --items-stdin --cluster --json < items.json
|
|
65
|
+
```
|
|
66
|
+
fed the **same** `listCommand` JSON already obtained (single data source — never a
|
|
67
|
+
`backlog.json` path). Returns `clusters[]`: each with `memberIds`, `memberReasons`,
|
|
68
|
+
`sharedTokens`, and the **union** of members' gated subtrees (`gatedIds` +
|
|
69
|
+
`gatedCount`).
|
|
70
|
+
- **Decision point:** you **may merge or refine** candidate clusters by judgment —
|
|
71
|
+
under-clustering is the deliberately-chosen failure direction of the scripted helper,
|
|
72
|
+
so its clusters are a floor, not a ceiling. You have no scripted *split* authority.
|
|
73
|
+
- **Output:** the final cluster set (scripted candidates ± your merges), each with its
|
|
74
|
+
member ids and blast-radius numbers.
|
|
75
|
+
- **Error:** a `backlog-topology` exit 2 stops the procedure.
|
|
76
|
+
|
|
77
|
+
### Step 3 — Consolidated prompts
|
|
78
|
+
|
|
79
|
+
- **Input:** the final cluster set from step 2.
|
|
80
|
+
- **Mechanism:** `AskUserQuestion` (never inline prose).
|
|
81
|
+
- For any cluster of **two or more** items: emit **exactly one** consolidated question
|
|
82
|
+
that **names every affected item id** and states the **full gated subtree** the
|
|
83
|
+
cluster gates. Frame it by **blast radius** — e.g. *"This one decision gates 13 of
|
|
84
|
+
16 backlog items (items 2, 3, …). Answer it once."* — never one prompt per member.
|
|
85
|
+
- Singleton clusters prompt per item (today's per-item shape).
|
|
86
|
+
- **Security:** prompts **MUST NOT solicit secrets**. Ask for the *decision* (which
|
|
87
|
+
path, which policy), never a credential/token/key value. The decision record has no
|
|
88
|
+
credential-shaped field and is treated as repo-visible content.
|
|
89
|
+
- **Decision point:** the operator may **answer**, **defer** the decision, or request
|
|
90
|
+
**cancel the run early** — all three branches proceed to step 4 (nothing is acted on
|
|
91
|
+
before it is recorded).
|
|
92
|
+
- **Output:** per cluster/item, one of {answer text, deferral, cancel-early}.
|
|
93
|
+
- **Citation:** the blast-radius framing is derived from `backlog-topology --cluster`
|
|
94
|
+
gated-subtree output (member ids + counts) — the prompt cites that source; a
|
|
95
|
+
"gates N/M" claim the topology output contradicts is a defect.
|
|
96
|
+
|
|
97
|
+
### Step 4 — Record at collection
|
|
98
|
+
|
|
99
|
+
- **Input:** every branch outcome from step 3.
|
|
100
|
+
- **CLI (one call per decision, BEFORE anything is applied):**
|
|
101
|
+
```
|
|
102
|
+
# answered singleton
|
|
103
|
+
python3 "$R/scripts/forge-session.py" decision-record --backlog-dir {backlogDir} \
|
|
104
|
+
--item ID --question "Q" --answer "A"
|
|
105
|
+
# deferred, or cancel-early (both record a deferral: no --answer)
|
|
106
|
+
python3 "$R/scripts/forge-session.py" decision-record --backlog-dir {backlogDir} \
|
|
107
|
+
--item ID --question "Q" --deferred
|
|
108
|
+
# consolidated answer: one entry per affected item, shared clusterId
|
|
109
|
+
python3 "$R/scripts/forge-session.py" decision-record --backlog-dir {backlogDir} \
|
|
110
|
+
--item ID1 --item ID2 --item ID3 --question "Q" --answer "A" --cluster c1
|
|
111
|
+
```
|
|
112
|
+
(`--actor` defaults to `forge-5-loop@<host>` — a machine label, never user identity.)
|
|
113
|
+
- **Decision point:** a decision is recorded on **every** branch — answered, deferred,
|
|
114
|
+
**and** cancel-early — and it is recorded **before** step 5 acts on anything. A
|
|
115
|
+
cancel-early is recorded as a **deferral** (`answer: null`, `deferred: true`,
|
|
116
|
+
`question` carrying the original needs-human text) — there is no third entry form. A
|
|
117
|
+
recorded-but-unapplied entry (`appliedAt == null`) is exactly what step 1 re-surfaces
|
|
118
|
+
on the next launch (§3).
|
|
119
|
+
- **Consolidated:** one entry per affected item, all sharing one `clusterId` (minted
|
|
120
|
+
`c` + lowest member id). Items stay **independently re-decidable**: a later per-item
|
|
121
|
+
entry supersedes the cluster entry for that item only.
|
|
122
|
+
- **Output:** durable append-only entries in `forge-decisions.json`; the write is
|
|
123
|
+
atomic.
|
|
124
|
+
- **Error:** any `decision-record` exit 2 (both/neither of `--answer`/`--deferred`,
|
|
125
|
+
unknown dir, failed atomic write) is surfaced verbatim and stops the procedure. The
|
|
126
|
+
answer is **not** applied if it was not recorded.
|
|
127
|
+
|
|
128
|
+
### Step 5 — Apply
|
|
129
|
+
|
|
130
|
+
- **Version probe (once, at the start of this step):** run the substituted
|
|
131
|
+
`loopRunner.versionCommand` (default `{bin} version --json`), parse
|
|
132
|
+
`{ "version": "<semver>" }`, and numerically semver-compare it against
|
|
133
|
+
`RECOVERY_MIN_RUNNER_VERSION` (a `scripts/forge-session.py` module constant, `0.14.0`
|
|
134
|
+
— the capability threshold for `{bin} backlog answer`; **not**
|
|
135
|
+
`loopRunner.minRunnerVersion`, which stays the launch floor). A probe miss
|
|
136
|
+
(missing/old/unparseable version) is **never** a hard failure — it selects the
|
|
137
|
+
degraded path and is reported with `loopRunner.installHint`.
|
|
138
|
+
- **Apply per item** (full dispatch table in §5):
|
|
139
|
+
- needs-human item, runner **≥** threshold →
|
|
140
|
+
`{bin} backlog answer . {id} "{answer}" --backlog {backlogDir} --json`
|
|
141
|
+
(the answer text is threaded into the next iteration's prompt).
|
|
142
|
+
- needs-human item, runner **<** threshold → **degraded path:**
|
|
143
|
+
`{bin} backlog unblock . {id} --backlog {backlogDir} --json` — the item is genuinely
|
|
144
|
+
unblocked and the answer stays durable in `forge-decisions.json`, but the recovery
|
|
145
|
+
report **must state explicitly** that the answer was **not** injected into the next
|
|
146
|
+
iteration's prompt, with the `installHint` upgrade hint attached.
|
|
147
|
+
- plain (non-needs-human) blocked item → `{bin} backlog unblock` at **every** runner
|
|
148
|
+
version.
|
|
149
|
+
- **Stamp:** after each runner apply **succeeds**, run
|
|
150
|
+
```
|
|
151
|
+
python3 "$R/scripts/forge-session.py" decision-apply --backlog-dir {backlogDir} --item ID
|
|
152
|
+
```
|
|
153
|
+
which stamps `appliedAt`/`appliedBy` on the item's latest entry. `decision-apply` is
|
|
154
|
+
called **only after** the runner apply returned success — a stamped record means the
|
|
155
|
+
runner actually accepted the change.
|
|
156
|
+
- **Error:** a runner apply that **errors** (non-zero exit — item missing, not
|
|
157
|
+
`blocked`, or any failure) is a **failed apply**: surface it verbatim, do **not** call
|
|
158
|
+
`decision-apply`, stop the procedure, report failed recovery. This is distinct from a
|
|
159
|
+
version-probe miss (which routes to the degraded path, not a failure) and from step
|
|
160
|
+
6's ran-but-nothing-moved failure (§6).
|
|
161
|
+
|
|
162
|
+
### Step 6 — Prove
|
|
163
|
+
|
|
164
|
+
- **Input:** the affected item set that step 5 applied.
|
|
165
|
+
- **CLI:** re-read per-item state via the substituted `loopRunner.listCommand`
|
|
166
|
+
(`{bin} backlog list . --backlog {backlogDir} --json`) and test **each** affected
|
|
167
|
+
item: `status != "blocked"` — which, per the runner's derivation
|
|
168
|
+
(needs-human ⇔ `status=="blocked" && needsHuman==true`), also removes it from the
|
|
169
|
+
needs-human count, so the single test covers both flags. Aggregate `backlogSummary`
|
|
170
|
+
counts are **never** the test. An affected item **missing** from the re-read counts
|
|
171
|
+
as a non-mover.
|
|
172
|
+
- **Decision point:** **all** affected items moved → proceed to step 7. **Any**
|
|
173
|
+
non-mover — including a partial move where some items moved and others did not — is a
|
|
174
|
+
**failed recovery**: report it, **naming the movers and the non-movers** from their
|
|
175
|
+
item `status` fields.
|
|
176
|
+
- **Output:** either "all moved → continue" or a failed-recovery report.
|
|
177
|
+
- **Citation:** the movers/non-movers are named from the per-item `listCommand` re-read
|
|
178
|
+
(`status` fields), never from aggregate counts — a report that contradicts the
|
|
179
|
+
per-item read is a defect.
|
|
180
|
+
|
|
181
|
+
### Step 7 — Gate & exit
|
|
182
|
+
|
|
183
|
+
- **Tree reconciliation first.** Before any outcome is selected, run the **Post-Run
|
|
184
|
+
Tree Reconciliation** section (§4). It runs on every recovery pass — including passes
|
|
185
|
+
with no needs-human items — and is silent on a clean tree.
|
|
186
|
+
- **Evaluate the `resolved` gate — all three must hold:**
|
|
187
|
+
1. `decision-list --unapplied` is **empty for the affected items**. The verb returns
|
|
188
|
+
the **global** latest-unapplied-per-item set, so **intersect** that payload's
|
|
189
|
+
entries (each carries `itemId`) with this session's affected-item set and test
|
|
190
|
+
only that intersection for emptiness — an unrelated item's stray deferral must not
|
|
191
|
+
suppress a legitimate `resolved`.
|
|
192
|
+
2. `git status --porcelain` is **clean** (git-ignored `{stateDir}` artifacts are
|
|
193
|
+
invisible to porcelain — the exclusion holds by construction).
|
|
194
|
+
3. the per-item re-read (step 6) shows **every** affected item left
|
|
195
|
+
`blocked`/`needsHuman`.
|
|
196
|
+
- **Select the outcome:** on all-three-pass, select `resolved` — the first rung of the
|
|
197
|
+
ladder in `result-reporting.md`, so a resolved stop never re-triggers the needs-human
|
|
198
|
+
branch its own recovery just cleared. **Any one gate failing falls the ladder
|
|
199
|
+
through** to `needs-human` / `blocked` / `deferred` / `partial` / `complete` exactly
|
|
200
|
+
as today. `resolved` routes **resume** — its NEXT-STEPS block fences
|
|
201
|
+
`/feature-forge:forge-5-loop {feature}`, never the navigator.
|
|
202
|
+
- **CLI:** the close runs through the Scripted Stage Exit (SKILL Step 7):
|
|
203
|
+
`stage-exit … --outcome resolved …`. `stage-exit` does **not** re-verify the gate
|
|
204
|
+
server-side (it has no runner access) — enforcement is procedural: this step.
|
|
205
|
+
- **Citation:** the `resolved` outcome text cites the three gate evaluations
|
|
206
|
+
(`decision-list --unapplied` empty, porcelain empty, per-item re-read all-moved).
|
|
207
|
+
Claiming `resolved` without those preconditions is a reportable defect.
|
|
208
|
+
|
|
209
|
+
## 3. Fresh-session re-entry
|
|
210
|
+
|
|
211
|
+
The procedure is the **re-entry point** on a fresh session / next launch — this is what
|
|
212
|
+
makes a decision survive session end and context clear.
|
|
213
|
+
|
|
214
|
+
On a new session, **step 1** enumerates every entry with `appliedAt == null` from a
|
|
215
|
+
*previous* session — answered-but-not-yet-applied decisions, deferrals, and cancel-early
|
|
216
|
+
deferrals alike. Those entries are re-surfaced:
|
|
217
|
+
|
|
218
|
+
- An entry that already carries an **answer** (`answer != null`, `deferred == false`,
|
|
219
|
+
`appliedAt == null`) **skips step 3's prompt** for that item — the operator already
|
|
220
|
+
decided; the procedure proceeds straight to step 5 (apply) and step 6 (prove). The
|
|
221
|
+
answer collected last session is applied this session without re-asking.
|
|
222
|
+
- A **deferral** (`deferred == true`) re-surfaces through step 3 as an open decision —
|
|
223
|
+
the operator is asked again, and their new answer appends a **new** entry
|
|
224
|
+
(append-only); the deferral's audit fields are never destroyed.
|
|
225
|
+
|
|
226
|
+
Because entries are durable and untracked, a session boundary, crash, or context clear
|
|
227
|
+
between "operator answered" and "answer applied" never costs the decision — step 1 of
|
|
228
|
+
the next launch finds it.
|
|
229
|
+
|
|
230
|
+
## 4. Post-Run Tree Reconciliation
|
|
231
|
+
|
|
232
|
+
Invoked from step 7 after the run ends and **before** any outcome is selected. It runs
|
|
233
|
+
on **every** recovery pass — including passes with no needs-human items, which step 1
|
|
234
|
+
routes here directly, and SKILL Step 4c enters the procedure on every run close —
|
|
235
|
+
because it is the "tree" half of recovery. Four sub-steps.
|
|
236
|
+
|
|
237
|
+
### 4.1 Detect
|
|
238
|
+
|
|
239
|
+
- **CLI:** `git status --porcelain`.
|
|
240
|
+
- **Clean tree → SILENT.** Empty output ⇒ no prompt, no output, no operator decision.
|
|
241
|
+
The decision record and all runner state under `{stateDir}` are git-ignored and
|
|
242
|
+
therefore never appear in porcelain output — decision writes never dirty the tree
|
|
243
|
+
this step inspects.
|
|
244
|
+
- **Dirty tree → proceed to 4.2.**
|
|
245
|
+
- **Error:** a `git status` failure (not a git repo, git error) is surfaced verbatim;
|
|
246
|
+
reconciliation is skipped (there is nothing git-native to reconcile), the rest of the
|
|
247
|
+
procedure continues.
|
|
248
|
+
|
|
249
|
+
### 4.2 Attribute (best-effort, runner-native)
|
|
250
|
+
|
|
251
|
+
Best-effort attribution of dirty paths to the backlog item(s) that produced them, from
|
|
252
|
+
runner-native evidence — reliable per-item provenance is **not** a prerequisite.
|
|
253
|
+
|
|
254
|
+
- **Read `{backlogDir}/{stateDir}/state.json`** (the runner's loop state):
|
|
255
|
+
`baseCommitHash` (the HEAD captured at run start — the baseline for
|
|
256
|
+
`git log {baseCommitHash}..HEAD`), `completedItems` / `blockedItems` (item ids that
|
|
257
|
+
finished / blocked), `currentItem` (the item in flight when the run stopped — a
|
|
258
|
+
strong candidate for uncommitted changes), `startedAt` and
|
|
259
|
+
`iteration`/`maxIterations` (run identity + budget).
|
|
260
|
+
- **Read `{backlogDir}/{stateDir}/events.ndjson`** — one JSON object per line; parse
|
|
261
|
+
line-by-line (there is **no** runner CLI for events; the file is read directly). The
|
|
262
|
+
per-iteration `item_selected`, `llm_spawned`, and `llm_exited` records — each
|
|
263
|
+
carrying an `itemId` and a `timestamp` — name which items ran during the window and
|
|
264
|
+
in what order.
|
|
265
|
+
- **Map dirty paths → candidate items:** the `currentItem` and the most recent
|
|
266
|
+
`item_selected`/`llm_spawned` without a matching clean `llm_exited` are the items "in
|
|
267
|
+
flight when the run died"; `git log {baseCommitHash}..HEAD` names what was already
|
|
268
|
+
committed for which item (the runner commits `[rauf] <id>: <title>`). Present the
|
|
269
|
+
mapping as **CANDIDATES, never asserted**.
|
|
270
|
+
- **Degradation (detection never aborts):** if `state.json` or `events.ndjson` is
|
|
271
|
+
missing, unreadable, or unparseable, **degrade** to the fully-unattributed path —
|
|
272
|
+
everything goes into 4.3's single consolidated decision. Detection (4.1) is never
|
|
273
|
+
aborted by an evidence-parse failure.
|
|
274
|
+
- **Citation:** the presentation cites `git status --porcelain` paths +
|
|
275
|
+
`{stateDir}/state.json` / `events.ndjson` run evidence, with every attribution
|
|
276
|
+
explicitly labelled a **candidate**.
|
|
277
|
+
|
|
278
|
+
### 4.3 Decide
|
|
279
|
+
|
|
280
|
+
- **Mechanism:** `AskUserQuestion` (never inline prose).
|
|
281
|
+
- **One question per attributed item-group:** for each candidate item-group from 4.2,
|
|
282
|
+
offer **commit-for-that-item** / **stash** / **discard**.
|
|
283
|
+
- **Unattributable changes → ONE consolidated decision:** everything that could not
|
|
284
|
+
be attributed is presented as a single grouped question, not dropped.
|
|
285
|
+
- **Discard guard:** **discard is NEVER the default** and requires its **own explicit
|
|
286
|
+
confirmation** — a second, dedicated question via `AskUserQuestion` confirming the specific paths
|
|
287
|
+
to be discarded before any `git checkout`/`git restore`/`git clean` runs. No path is
|
|
288
|
+
discarded on a single click.
|
|
289
|
+
- **Output:** per group, an executed reconciliation (commit / stash / confirmed
|
|
290
|
+
discard) or a deferral the operator can revisit.
|
|
291
|
+
|
|
292
|
+
### 4.4 Launch blocker
|
|
293
|
+
|
|
294
|
+
The next launch's `### 1g. Stranded-Work Pre-flight` (SKILL Step 1) STOPS on a dirty
|
|
295
|
+
tree when a prior run's `{backlogDir}/{stateDir}/state.json` exists, names that run
|
|
296
|
+
(its `startedAt`, `currentItem`, `blockedItems`), and points at this section to
|
|
297
|
+
commit / stash / discard the stranded work before relaunch. The runner's own
|
|
298
|
+
uncommitted-changes launch refusal remains the backstop for a dirty tree with no
|
|
299
|
+
prior-run state.
|
|
300
|
+
|
|
301
|
+
## 5. Apply-mechanism dispatch (version gate & the degraded path)
|
|
302
|
+
|
|
303
|
+
| Runner version | Item kind | Apply mechanism | What the report says |
|
|
304
|
+
|---|---|---|---|
|
|
305
|
+
| `≥ RECOVERY_MIN_RUNNER_VERSION` | needs-human (has an answer) | `{bin} backlog answer . {id} "{answer}" --backlog {backlogDir} --json` | Answer applied and threaded into the next iteration's prompt. |
|
|
306
|
+
| `≥ RECOVERY_MIN_RUNNER_VERSION` | plain blocked | `{bin} backlog unblock . {id} --backlog {backlogDir} --json` | Item unblocked. |
|
|
307
|
+
| `< RECOVERY_MIN_RUNNER_VERSION` (or probe miss) | needs-human | **DEGRADE:** `{bin} backlog unblock . {id} --backlog {backlogDir} --json` | Item unblocked; **answer was NOT injected into the next prompt** (durable in `forge-decisions.json`); `{installHint}` — upgrade to a runner that ships `backlog answer` to thread it. |
|
|
308
|
+
| any version (incl. probe miss) | plain blocked | `{bin} backlog unblock . {id} --backlog {backlogDir} --json` | Item unblocked. |
|
|
309
|
+
|
|
310
|
+
Key properties:
|
|
311
|
+
|
|
312
|
+
- **Plain blocked items always use `unblock`, at every version** — they carry no answer
|
|
313
|
+
to thread. The version gate only ever changes the needs-human path.
|
|
314
|
+
- **The degraded needs-human path genuinely unblocks** (the runner clears
|
|
315
|
+
`status`/`blockedReason`/`needsHuman`/`deferred`), so recovery works across the whole
|
|
316
|
+
supported runner floor. The only capability lost below the threshold is
|
|
317
|
+
prompt-threading — the answer remains durable in the decision record and re-surfaces
|
|
318
|
+
via `decision-list --unapplied` if re-decided.
|
|
319
|
+
- **The report is honest either way:** the degraded path states explicitly that the
|
|
320
|
+
answer was not threaded, with the upgrade hint.
|
|
321
|
+
|
|
322
|
+
## 6. Failure taxonomy
|
|
323
|
+
|
|
324
|
+
| Failure | When it occurs | Reaches the step-6 per-item test? | Report |
|
|
325
|
+
|---|---|---|---|
|
|
326
|
+
| **Failed apply** | `{bin} backlog answer` / `unblock` exits non-zero (corrupt backlog, I/O error, not-blocked/not-found refusal); or the post-apply re-read is unparseable | **No** — stops *before* the test | Verbatim runner error + which item; **failed recovery**; procedure stops; never claimed succeeded |
|
|
327
|
+
| **Ran-but-nothing-moved** | Every apply exited 0, but the step-6 per-item test finds a non-mover | **Yes** — *is* the test failing | Movers/non-movers named from `status` fields; **failed recovery** |
|
|
328
|
+
| **Version-probe miss** | `versionCommand` missing/unparseable, or version `< RECOVERY_MIN_RUNNER_VERSION` | N/A — selects the degraded path (§5) | Degraded path proceeds; not-threaded caveat + `installHint`; **not** a failed recovery |
|
|
329
|
+
|
|
330
|
+
Rules: never report recorded/succeeded past a failed step; a failed apply stops before
|
|
331
|
+
the per-item test, so a runner that errored is never conflated with a runner that ran
|
|
332
|
+
cleanly but moved nothing; `decision-apply` is not called for a failed item — the record
|
|
333
|
+
stays unapplied and re-surfaces next launch; a probe miss degrades, it never fails
|
|
334
|
+
recovery.
|
|
335
|
+
|
|
336
|
+
## 7. Report citations (REQ-OBS-01)
|
|
337
|
+
|
|
338
|
+
Every report surface this procedure produces names the authoritative source it derived
|
|
339
|
+
its claims from; a claim that source contradicts is a reportable defect. Each report
|
|
340
|
+
surface names the authoritative source it derives its claims from:
|
|
341
|
+
|
|
342
|
+
| Report surface | Authoritative citation basis |
|
|
343
|
+
|---|---|
|
|
344
|
+
| Pending / starvation template | `backlogSummary` counts + `backlog-topology` output over `listCommand` JSON; iteration counters from `state.json` (`iteration`/`maxIterations`) |
|
|
345
|
+
| Failed-recovery report (§2 step 6) | The per-item `listCommand` re-read — movers/non-movers named from item `status`, never aggregate counts |
|
|
346
|
+
| `resolved` outcome text | The three gate evaluations: `decision-list --unapplied` (empty), `git status --porcelain` (empty), per-item re-read (all affected left `blocked`) |
|
|
347
|
+
| Consolidated blast-radius prompt (§2 step 3) | `backlog-topology --cluster` gated-subtree output (member ids + counts) |
|
|
348
|
+
| Tree-reconciliation presentation (§4) | `git status --porcelain` paths + `state.json`/`events.ndjson` run evidence, attributions explicitly presented as **candidates** |
|
|
349
|
+
| Step 2a depth line | The same `backlog-topology` output (`maxChainDepth`) |
|
|
@@ -64,28 +64,57 @@ Loop completed for {feature}.
|
|
|
64
64
|
Deferred: {deferred} items (no signal after retries — likely just need another pass)
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
-
**Some items still pending
|
|
67
|
+
**Some items still pending** — the parenthetical cause is chosen, never hardcoded:
|
|
68
68
|
```
|
|
69
69
|
Loop completed for {feature}.
|
|
70
70
|
Completed: {done}/{total}
|
|
71
|
-
Pending: {pending} items (
|
|
71
|
+
Pending: {pending} items ({cause})
|
|
72
72
|
Blocked: {blocked} items
|
|
73
73
|
```
|
|
74
|
+
Render `{cause}` as "iteration limit reached" **only** when `iteration == maxIterations`
|
|
75
|
+
AND `selectable > 0` — cite the `iteration`/`maxIterations` counters from
|
|
76
|
+
`{loopRunner.stateDir}/state.json` and `selectable` from `backlog-topology --items-stdin
|
|
77
|
+
--json` run over the same authoritative item JSON as the counts above. Otherwise —
|
|
78
|
+
`selectable == 0` with items still pending while `iteration < maxIterations` — the
|
|
79
|
+
iteration limit was NOT the constraint: drop the parenthetical and render this
|
|
80
|
+
dependency-starvation report instead, naming each blocking root and its gated-subtree
|
|
81
|
+
size from `backlog-topology`'s `starvation.blockingRoots[].{id, gatedCount}` and
|
|
82
|
+
`itemCount`, then close the stage with `--cause dependency-starvation` in Step 7:
|
|
83
|
+
```
|
|
84
|
+
Loop stopped for {feature} with {pending} item(s) still pending, but the iteration
|
|
85
|
+
limit was NOT the constraint ({iteration}/{maxIterations} iterations used).
|
|
86
|
+
No pending item was selectable — every one is gated behind unblocked roots:
|
|
87
|
+
- {rootId}: {rootTitle} — gates {gatedCount}/{itemCount} items
|
|
88
|
+
Unblock these roots (their subtrees free up on the next run), then run the loop again.
|
|
89
|
+
```
|
|
90
|
+
Both branches cite their authoritative source: the iteration-limit branch the
|
|
91
|
+
`state.json` iteration counters, the starvation branch the backlog summary counts plus
|
|
92
|
+
the `backlog-topology` output (`selectable`, `blockingRoots`, `gatedCount`,
|
|
93
|
+
`itemCount`). A cause any of those counters contradicts — e.g. "iteration limit
|
|
94
|
+
reached" while `iteration < maxIterations` — is a reportable defect.
|
|
74
95
|
|
|
75
96
|
## Selecting the one `LoopOutcome` (Step 7)
|
|
76
97
|
|
|
77
98
|
After Step 5's `state-complete`, select exactly **one** `LoopOutcome` from Step 4a's
|
|
78
99
|
authoritative final counts. Walk this ladder in order and stop at the first match:
|
|
79
100
|
|
|
80
|
-
1. **`
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
101
|
+
1. **`resolved`** — the Post-Run Recovery Procedure
|
|
102
|
+
(`references/recovery-procedure.md`) ran this session with a **non-empty**
|
|
103
|
+
affected-item set and its gate passed: every affected needs-human item has an
|
|
104
|
+
applied decision record, the working tree is clean, and each affected item left
|
|
105
|
+
`blocked`/`needsHuman` per the per-item re-read. This outranks `needs-human` so a
|
|
106
|
+
stop the recovery just cleared is not re-reported as still needing a human. (Step
|
|
107
|
+
4c runs the procedure on every close, so an empty affected set is the common case —
|
|
108
|
+
it never selects `resolved`; fall through.)
|
|
109
|
+
2. **`needs-human`** — otherwise, `needsHuman > 0`. This wins even when blocked
|
|
110
|
+
items also exist: a decision only a human can make outranks work that merely
|
|
111
|
+
could not proceed.
|
|
112
|
+
3. **`blocked`** — otherwise, genuine `blocked > 0`.
|
|
113
|
+
4. **`deferred`** — otherwise, runner-deferred items exist (the "false blocks" the
|
|
85
114
|
runner gave up on after retries).
|
|
86
|
-
|
|
115
|
+
5. **`partial`** — otherwise, `pending`/`in_progress` items remain because the
|
|
87
116
|
iteration limit was reached.
|
|
88
|
-
|
|
117
|
+
6. **`complete`** — otherwise, and **only** when every item is `done`.
|
|
89
118
|
|
|
90
119
|
This is a priority order, not a set. A run reporting both a needs-human and a blocked
|
|
91
120
|
count renders both reports above and still exits `needs-human`.
|
|
@@ -95,8 +124,8 @@ reported only that its process finished; the final backlog state decides. A clea
|
|
|
95
124
|
exit 0 that still leaves pending items is `partial`, never `complete` — and
|
|
96
125
|
`complete` is legitimate only when the counts show every item `done`.
|
|
97
126
|
|
|
98
|
-
**Retrying the non-complete outcomes.** `partial` and `
|
|
99
|
-
resume; `blocked` and `needs-human` fence the navigator. Whichever you land on, the
|
|
127
|
+
**Retrying the non-complete outcomes.** `partial`, `deferred`, and `resolved` fence
|
|
128
|
+
the loop resume; `blocked` and `needs-human` fence the navigator. Whichever you land on, the
|
|
100
129
|
runner's own retry flags still apply to the next run — e.g. rauf's `--retry-blocked`
|
|
101
130
|
picks the set-aside blocked and deferred items back up at Step 2d. Mention that as
|
|
102
131
|
plain prose in the report if it helps; never as a second command block.
|
|
@@ -31,7 +31,7 @@ pass after all iterations complete (an extra agent session that re-examines the
|
|
|
31
31
|
finished work and can file follow-up backlog items). feature-forge treats **running
|
|
32
32
|
with review as the recommended default** — a review pass is cheap relative to the
|
|
33
33
|
loop it audits, and catches gaps before the pipeline moves on to docs. So Step 2d
|
|
34
|
-
adds a **"Run mode"** question to the confirmation
|
|
34
|
+
adds a **"Run mode"** question, via `AskUserQuestion`, to the confirmation surface with a
|
|
35
35
|
**fixed, non-improvised option order** (determinism is the point — the option set
|
|
36
36
|
must not vary run-to-run):
|
|
37
37
|
|
|
@@ -47,6 +47,19 @@ Run mode:
|
|
|
47
47
|
review pass and also unblocks/retries the previously blocked items.
|
|
48
48
|
```
|
|
49
49
|
|
|
50
|
+
**`loopRunner.reviewMode` gate (`"prompt"` default | `"always"` | `"never"`).**
|
|
51
|
+
The Run-mode question above is presented only when the effective
|
|
52
|
+
`loopRunner.reviewMode` is `"prompt"` — the default, byte-identical to today.
|
|
53
|
+
`"always"` **skips the question** and appends `--review` unconditionally; the
|
|
54
|
+
confirmation's rendered command line still shows `--review`, so the choice is
|
|
55
|
+
never hidden. `"never"` **skips the question** and launches the bare rendered
|
|
56
|
+
command. Under `"always"`/`"never"`, when — and only when — the Step 2a tally has
|
|
57
|
+
`blocked > 0`, present a **narrower situational question** in the question's
|
|
58
|
+
place offering only the retry-blocked choice (on yes, additionally append
|
|
59
|
+
`--retry-blocked`; the `--review` decision is already fixed by the mode and is
|
|
60
|
+
**not** re-asked); with no blocked items, the Run-mode surface asks nothing. An
|
|
61
|
+
unrecognized value behaves as `"prompt"`.
|
|
62
|
+
|
|
50
63
|
Notes:
|
|
51
64
|
|
|
52
65
|
- **Option 1 is the default** and the confirmation's rendered command line shows
|
|
@@ -179,12 +192,17 @@ high and the noise low:
|
|
|
179
192
|
immediately** and send a **`PushNotification`** (an hours-long run means the user has
|
|
180
193
|
likely stepped away). **Important — the loop is NOT paused:** the runner has set that
|
|
181
194
|
item aside and kept working other items. So report *what* needs a human and *which*
|
|
182
|
-
item, then either (a) collect the user's answer via `AskUserQuestion`
|
|
183
|
-
|
|
184
|
-
|
|
195
|
+
item, then either (a) collect the user's answer via `AskUserQuestion` and **record it via
|
|
196
|
+
`decision-record` now** — SKILL Step 4c's unconditional **Post-Run Recovery Procedure**
|
|
197
|
+
pass (`references/recovery-procedure.md`) applies it after the run ends — or (b) offer
|
|
198
|
+
to **cancel the run early** (also recorded via `decision-record` — a deferral) if the
|
|
199
|
+
answer changes the whole plan. Do not tell the user the loop is waiting on their reply
|
|
200
|
+
— it isn't.
|
|
185
201
|
- **`item_blocked`** → surface the blocked item + reason now (visibility) and
|
|
186
202
|
accumulate for the final summary. Use `{rendered statusJsonCommand}` to distinguish a
|
|
187
203
|
genuine `blocked` from a runner-`deferred` "false block" (`backlogSummary.deferred`).
|
|
204
|
+
No action is needed now: Step 4c's recovery pass offers the unblock after the run
|
|
205
|
+
ends — a blocked-only run (no `needs_human` event) still enters it.
|
|
188
206
|
- **`loop_error`** → a real failure (this is also what a circuit-breaker halt — too many
|
|
189
207
|
consecutive infra failures — emits). Surface now and `PushNotification`. Offer
|
|
190
208
|
inspection / `--force` / re-run as appropriate.
|
|
@@ -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,7 +202,7 @@ 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
|
|
|
194
|
-
**The
|
|
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.
|
|
195
206
|
|
|
196
207
|
### `state-verify` — verification results and provenance
|
|
197
208
|
|
|
@@ -395,7 +406,7 @@ Invoke this block **at the head of any post-entry step that writes a stage artif
|
|
|
395
406
|
|
|
396
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.
|
|
397
408
|
|
|
398
|
-
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.
|
|
399
410
|
|
|
400
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).
|
|
401
412
|
|