@garygentry/feature-forge 0.3.5 → 0.3.7
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/README.md +1 -1
- package/adapters/GENERATION-REPORT.md +20 -0
- package/adapters/claude/.claude-plugin/plugin.json +16 -0
- package/adapters/claude/.feature-forge-bundle.json +1 -1
- package/adapters/claude/agents/forge-verifier.md +16 -5
- package/adapters/claude/references/forge-config-schema.json +5 -5
- package/adapters/claude/references/portable-root.md +20 -16
- package/adapters/claude/references/preflight-and-self-heal.md +183 -0
- package/adapters/claude/references/process-overview.md +1 -1
- package/adapters/claude/references/ralph-loop-contract.md +12 -8
- package/adapters/claude/references/select-outcome.md +138 -0
- package/adapters/claude/references/shared-conventions.md +176 -23
- package/adapters/claude/references/skill-frontmatter.schema.json +3 -1
- package/adapters/claude/references/stack-resolution.md +1 -1
- package/adapters/claude/references/stage-exit-protocol.md +19 -4
- package/adapters/claude/references/templates/root-hygiene/AGENTS.md +14 -0
- package/adapters/claude/references/templates/root-hygiene/CLAUDE.md +14 -0
- package/adapters/claude/references/templates/specs-hygiene/AGENTS.md +3 -1
- package/adapters/claude/references/templates/specs-hygiene/CLAUDE.md +2 -1
- package/adapters/claude/references/verifier-patterns/MEMORY.md +35 -0
- package/adapters/claude/references/verifier-patterns/pattern_absence_claims.md +36 -0
- package/adapters/claude/references/verifier-patterns/pattern_carveout_sibling_semantics.md +34 -0
- package/adapters/claude/references/verifier-patterns/pattern_deviation_judgment.md +36 -0
- package/adapters/claude/references/verifier-patterns/pattern_enum_vocabulary_ripple.md +43 -0
- package/adapters/claude/references/verifier-patterns/pattern_extend_the_existing.md +31 -0
- package/adapters/claude/references/verifier-patterns/pattern_guard_substitution_detection.md +34 -0
- package/adapters/claude/references/verifier-patterns/pattern_mechanical_rewrite_damage.md +30 -0
- package/adapters/claude/references/verifier-patterns/pattern_postfix_reverify.md +82 -0
- package/adapters/claude/references/verifier-patterns/pattern_proximity_window_guards.md +26 -0
- package/adapters/claude/references/verifier-patterns/pattern_scratch_root_probes.md +40 -0
- package/adapters/claude/references/verifier-patterns/pattern_self_referential_control.md +26 -0
- package/adapters/claude/references/verifier-patterns/pattern_sibling_docstring_sweep.md +28 -0
- package/adapters/claude/references/verifier-patterns/pattern_spec_literals_are_claims.md +45 -0
- package/adapters/claude/references/verifier-patterns/pattern_stale_counts_after_split.md +36 -0
- package/adapters/claude/references/verifier-patterns/pattern_test_count_units.md +20 -0
- package/adapters/claude/references/verifier-patterns/pattern_vacuous_self_reading_tests.md +32 -0
- package/adapters/claude/references/verify-state.md +98 -0
- package/adapters/claude/scripts/forge-bootstrap.py +23 -2
- package/adapters/claude/scripts/forge-root.sh +104 -21
- package/adapters/claude/scripts/forge-session.py +620 -6969
- package/adapters/claude/scripts/forge_session/__init__.py +11 -0
- package/adapters/claude/scripts/forge_session/_common.py +1566 -0
- package/adapters/claude/scripts/forge_session/_doctor_util.py +218 -0
- package/adapters/claude/scripts/forge_session/cli.py +1067 -0
- package/adapters/claude/scripts/forge_session/decisions.py +355 -0
- package/adapters/claude/scripts/forge_session/discover.py +472 -0
- package/adapters/claude/scripts/forge_session/doctor.py +2144 -0
- package/adapters/claude/scripts/forge_session/exit.py +1081 -0
- package/adapters/claude/scripts/forge_session/outcomes.py +574 -0
- package/adapters/claude/scripts/forge_session/routes.py +1162 -0
- package/adapters/claude/scripts/forge_session/state.py +1479 -0
- package/adapters/claude/scripts/forge_session/topology.py +443 -0
- package/adapters/claude/skills/forge/SKILL.md +7 -7
- package/adapters/claude/skills/forge/references/process-overview.md +1 -1
- package/adapters/claude/skills/forge/references/shared-conventions.md +176 -23
- package/adapters/claude/skills/forge/references/stage-exit-protocol.md +19 -4
- package/adapters/claude/skills/forge-0-epic/SKILL.md +7 -7
- package/adapters/claude/skills/forge-0-epic/references/edit-mode.md +9 -5
- package/adapters/claude/skills/forge-0-epic/references/epic-manifest-subcommands.md +6 -1
- package/adapters/claude/skills/forge-0-epic/references/portable-root.md +20 -16
- package/adapters/claude/skills/forge-0-epic/references/shared-conventions.md +176 -23
- package/adapters/claude/skills/forge-0-epic/references/stage-exit-protocol.md +19 -4
- package/adapters/claude/skills/forge-1-prd/SKILL.md +7 -7
- package/adapters/claude/skills/forge-1-prd/references/shared-conventions.md +176 -23
- package/adapters/claude/skills/forge-1-prd/references/stage-exit-protocol.md +19 -4
- package/adapters/claude/skills/forge-2-tech/SKILL.md +7 -7
- package/adapters/claude/skills/forge-2-tech/references/shared-conventions.md +176 -23
- package/adapters/claude/skills/forge-2-tech/references/stack-resolution.md +1 -1
- package/adapters/claude/skills/forge-2-tech/references/stage-exit-protocol.md +19 -4
- package/adapters/claude/skills/forge-3-specs/SKILL.md +5 -5
- package/adapters/claude/skills/forge-3-specs/references/shared-conventions.md +176 -23
- package/adapters/claude/skills/forge-3-specs/references/stage-exit-protocol.md +19 -4
- package/adapters/claude/skills/forge-4-backlog/SKILL.md +16 -8
- package/adapters/claude/skills/forge-4-backlog/references/shared-conventions.md +176 -23
- package/adapters/claude/skills/forge-4-backlog/references/stage-exit-protocol.md +19 -4
- package/adapters/claude/skills/forge-4-backlog/references/verify-state.md +98 -0
- package/adapters/claude/skills/forge-5-loop/SKILL.md +36 -41
- package/adapters/claude/skills/forge-5-loop/references/agent-selection.md +4 -0
- package/adapters/claude/skills/forge-5-loop/references/preflight-and-self-heal.md +183 -0
- package/adapters/claude/skills/forge-5-loop/references/ralph-loop-contract.md +12 -8
- package/adapters/claude/skills/forge-5-loop/references/recovery-procedure.md +10 -0
- package/adapters/claude/skills/forge-5-loop/references/runner-contract.md +17 -7
- package/adapters/claude/skills/forge-5-loop/references/shared-conventions.md +176 -23
- package/adapters/claude/skills/forge-5-loop/references/stage-exit-protocol.md +19 -4
- package/adapters/claude/skills/forge-5-loop/references/verify-state.md +98 -0
- package/adapters/claude/skills/forge-6-docs/SKILL.md +21 -14
- package/adapters/claude/skills/forge-6-docs/references/shared-conventions.md +176 -23
- package/adapters/claude/skills/forge-6-docs/references/stage-exit-protocol.md +19 -4
- package/adapters/claude/skills/forge-6-docs/references/verify-state.md +98 -0
- package/adapters/claude/skills/forge-bootstrap/SKILL.md +19 -10
- package/adapters/claude/skills/forge-bootstrap/references/shared-conventions.md +572 -0
- package/adapters/claude/skills/forge-fix/SKILL.md +15 -18
- package/adapters/claude/skills/forge-fix/references/select-outcome.md +138 -0
- package/adapters/claude/skills/forge-fix/references/shared-conventions.md +176 -23
- package/adapters/claude/skills/forge-fix/references/stage-exit-protocol.md +19 -4
- package/adapters/claude/skills/forge-guide/SKILL.md +87 -1
- package/adapters/claude/skills/forge-guide/references/forge-config-schema.json +5 -5
- package/adapters/claude/skills/forge-guide/references/preflight-and-self-heal.md +183 -0
- package/adapters/claude/skills/forge-guide/references/process-overview.md +1 -1
- package/adapters/claude/skills/forge-guide/references/ralph-loop-contract.md +12 -8
- package/adapters/claude/skills/forge-guide/references/shared-conventions.md +176 -23
- package/adapters/claude/skills/forge-guide/references/stack-resolution.md +1 -1
- package/adapters/claude/skills/forge-init/SKILL.md +58 -7
- package/adapters/claude/skills/forge-init/references/preflight-and-self-heal.md +183 -0
- package/adapters/claude/skills/forge-init/references/shared-conventions.md +572 -0
- package/adapters/claude/skills/forge-verify/SKILL.md +25 -26
- package/adapters/claude/skills/forge-verify/references/findings-template.md +8 -8
- package/adapters/claude/skills/forge-verify/references/select-outcome.md +138 -0
- package/adapters/claude/skills/forge-verify/references/shared-conventions.md +176 -23
- package/adapters/claude/skills/forge-verify/references/stage-exit-protocol.md +19 -4
- package/adapters/claude/skills/forge-verify/references/verification-checklists/epic.md +1 -1
- package/adapters/claude/skills/forge-verify/references/verifier-patterns/MEMORY.md +35 -0
- package/adapters/claude/skills/forge-verify/references/verifier-patterns/pattern_absence_claims.md +36 -0
- package/adapters/claude/skills/forge-verify/references/verifier-patterns/pattern_carveout_sibling_semantics.md +34 -0
- package/adapters/claude/skills/forge-verify/references/verifier-patterns/pattern_deviation_judgment.md +36 -0
- package/adapters/claude/skills/forge-verify/references/verifier-patterns/pattern_enum_vocabulary_ripple.md +43 -0
- package/adapters/claude/skills/forge-verify/references/verifier-patterns/pattern_extend_the_existing.md +31 -0
- package/adapters/claude/skills/forge-verify/references/verifier-patterns/pattern_guard_substitution_detection.md +34 -0
- package/adapters/claude/skills/forge-verify/references/verifier-patterns/pattern_mechanical_rewrite_damage.md +30 -0
- package/adapters/claude/skills/forge-verify/references/verifier-patterns/pattern_postfix_reverify.md +82 -0
- package/adapters/claude/skills/forge-verify/references/verifier-patterns/pattern_proximity_window_guards.md +26 -0
- package/adapters/claude/skills/forge-verify/references/verifier-patterns/pattern_scratch_root_probes.md +40 -0
- package/adapters/claude/skills/forge-verify/references/verifier-patterns/pattern_self_referential_control.md +26 -0
- package/adapters/claude/skills/forge-verify/references/verifier-patterns/pattern_sibling_docstring_sweep.md +28 -0
- package/adapters/claude/skills/forge-verify/references/verifier-patterns/pattern_spec_literals_are_claims.md +45 -0
- package/adapters/claude/skills/forge-verify/references/verifier-patterns/pattern_stale_counts_after_split.md +36 -0
- package/adapters/claude/skills/forge-verify/references/verifier-patterns/pattern_test_count_units.md +20 -0
- package/adapters/claude/skills/forge-verify/references/verifier-patterns/pattern_vacuous_self_reading_tests.md +32 -0
- package/adapters/codex/.feature-forge-bundle.json +1 -1
- package/adapters/codex/agents/forge-researcher.toml +1 -1
- package/adapters/codex/agents/forge-verifier.toml +17 -6
- package/adapters/codex/references/forge-config-schema.json +7 -7
- package/adapters/codex/references/portable-root.md +20 -16
- package/adapters/codex/references/preflight-and-self-heal.md +183 -0
- package/adapters/codex/references/process-overview.md +10 -10
- package/adapters/codex/references/ralph-loop-contract.md +12 -8
- package/adapters/codex/references/select-outcome.md +138 -0
- package/adapters/codex/references/shared-conventions.md +189 -36
- package/adapters/codex/references/skill-frontmatter.schema.json +3 -1
- package/adapters/codex/references/stack-resolution.md +1 -1
- package/adapters/codex/references/stage-exit-protocol.md +22 -7
- package/adapters/codex/references/templates/root-hygiene/AGENTS.md +14 -0
- package/adapters/codex/references/templates/root-hygiene/CLAUDE.md +14 -0
- package/adapters/codex/references/templates/specs-hygiene/AGENTS.md +3 -1
- package/adapters/codex/references/templates/specs-hygiene/CLAUDE.md +2 -1
- package/adapters/codex/references/verifier-patterns/MEMORY.md +35 -0
- package/adapters/codex/references/verifier-patterns/pattern_absence_claims.md +36 -0
- package/adapters/codex/references/verifier-patterns/pattern_carveout_sibling_semantics.md +34 -0
- package/adapters/codex/references/verifier-patterns/pattern_deviation_judgment.md +36 -0
- package/adapters/codex/references/verifier-patterns/pattern_enum_vocabulary_ripple.md +43 -0
- package/adapters/codex/references/verifier-patterns/pattern_extend_the_existing.md +31 -0
- package/adapters/codex/references/verifier-patterns/pattern_guard_substitution_detection.md +34 -0
- package/adapters/codex/references/verifier-patterns/pattern_mechanical_rewrite_damage.md +30 -0
- package/adapters/codex/references/verifier-patterns/pattern_postfix_reverify.md +82 -0
- package/adapters/codex/references/verifier-patterns/pattern_proximity_window_guards.md +26 -0
- package/adapters/codex/references/verifier-patterns/pattern_scratch_root_probes.md +40 -0
- package/adapters/codex/references/verifier-patterns/pattern_self_referential_control.md +26 -0
- package/adapters/codex/references/verifier-patterns/pattern_sibling_docstring_sweep.md +28 -0
- package/adapters/codex/references/verifier-patterns/pattern_spec_literals_are_claims.md +45 -0
- package/adapters/codex/references/verifier-patterns/pattern_stale_counts_after_split.md +36 -0
- package/adapters/codex/references/verifier-patterns/pattern_test_count_units.md +20 -0
- package/adapters/codex/references/verifier-patterns/pattern_vacuous_self_reading_tests.md +32 -0
- package/adapters/codex/references/verify-state.md +98 -0
- package/adapters/codex/scripts/forge-bootstrap.py +23 -2
- package/adapters/codex/scripts/forge-root.sh +104 -21
- package/adapters/codex/scripts/forge-session.py +620 -6969
- package/adapters/codex/scripts/forge_session/__init__.py +11 -0
- package/adapters/codex/scripts/forge_session/_common.py +1566 -0
- package/adapters/codex/scripts/forge_session/_doctor_util.py +218 -0
- package/adapters/codex/scripts/forge_session/cli.py +1067 -0
- package/adapters/codex/scripts/forge_session/decisions.py +355 -0
- package/adapters/codex/scripts/forge_session/discover.py +472 -0
- package/adapters/codex/scripts/forge_session/doctor.py +2144 -0
- package/adapters/codex/scripts/forge_session/exit.py +1081 -0
- package/adapters/codex/scripts/forge_session/outcomes.py +574 -0
- package/adapters/codex/scripts/forge_session/routes.py +1162 -0
- package/adapters/codex/scripts/forge_session/state.py +1479 -0
- package/adapters/codex/scripts/forge_session/topology.py +443 -0
- package/adapters/codex/skills/forge/SKILL.md +40 -40
- package/adapters/codex/skills/forge/references/process-overview.md +10 -10
- package/adapters/codex/skills/forge/references/shared-conventions.md +189 -36
- package/adapters/codex/skills/forge/references/stage-exit-protocol.md +22 -7
- package/adapters/codex/skills/forge-0-epic/SKILL.md +15 -15
- 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/portable-root.md +20 -16
- package/adapters/codex/skills/forge-0-epic/references/shared-conventions.md +189 -36
- package/adapters/codex/skills/forge-0-epic/references/stage-exit-protocol.md +22 -7
- package/adapters/codex/skills/forge-1-prd/SKILL.md +15 -15
- package/adapters/codex/skills/forge-1-prd/references/shared-conventions.md +189 -36
- package/adapters/codex/skills/forge-1-prd/references/stage-exit-protocol.md +22 -7
- package/adapters/codex/skills/forge-2-tech/SKILL.md +15 -15
- package/adapters/codex/skills/forge-2-tech/references/shared-conventions.md +189 -36
- package/adapters/codex/skills/forge-2-tech/references/stack-resolution.md +1 -1
- package/adapters/codex/skills/forge-2-tech/references/stage-exit-protocol.md +22 -7
- package/adapters/codex/skills/forge-3-specs/SKILL.md +10 -10
- package/adapters/codex/skills/forge-3-specs/references/shared-conventions.md +189 -36
- package/adapters/codex/skills/forge-3-specs/references/stage-exit-protocol.md +22 -7
- package/adapters/codex/skills/forge-4-backlog/SKILL.md +19 -11
- package/adapters/codex/skills/forge-4-backlog/references/shared-conventions.md +189 -36
- package/adapters/codex/skills/forge-4-backlog/references/stage-exit-protocol.md +22 -7
- package/adapters/codex/skills/forge-4-backlog/references/verify-state.md +98 -0
- package/adapters/codex/skills/forge-5-loop/SKILL.md +48 -53
- package/adapters/codex/skills/forge-5-loop/references/agent-selection.md +5 -1
- package/adapters/codex/skills/forge-5-loop/references/preflight-and-self-heal.md +183 -0
- package/adapters/codex/skills/forge-5-loop/references/ralph-loop-contract.md +12 -8
- package/adapters/codex/skills/forge-5-loop/references/recovery-procedure.md +14 -4
- package/adapters/codex/skills/forge-5-loop/references/runner-contract.md +20 -10
- package/adapters/codex/skills/forge-5-loop/references/shared-conventions.md +189 -36
- package/adapters/codex/skills/forge-5-loop/references/stage-exit-protocol.md +22 -7
- package/adapters/codex/skills/forge-5-loop/references/verify-state.md +98 -0
- package/adapters/codex/skills/forge-6-docs/SKILL.md +27 -20
- package/adapters/codex/skills/forge-6-docs/references/shared-conventions.md +189 -36
- package/adapters/codex/skills/forge-6-docs/references/stage-exit-protocol.md +22 -7
- package/adapters/codex/skills/forge-6-docs/references/verify-state.md +98 -0
- package/adapters/codex/skills/forge-bootstrap/SKILL.md +23 -15
- package/adapters/codex/skills/forge-bootstrap/references/shared-conventions.md +572 -0
- package/adapters/codex/skills/forge-bootstrap/references/templates/hygiene/CLAUDE.md +2 -2
- package/adapters/codex/skills/forge-fix/SKILL.md +27 -30
- package/adapters/codex/skills/forge-fix/references/select-outcome.md +138 -0
- package/adapters/codex/skills/forge-fix/references/shared-conventions.md +189 -36
- package/adapters/codex/skills/forge-fix/references/stage-exit-protocol.md +22 -7
- package/adapters/codex/skills/forge-guide/SKILL.md +84 -7
- package/adapters/codex/skills/forge-guide/references/forge-config-schema.json +7 -7
- package/adapters/codex/skills/forge-guide/references/preflight-and-self-heal.md +183 -0
- package/adapters/codex/skills/forge-guide/references/process-overview.md +10 -10
- package/adapters/codex/skills/forge-guide/references/ralph-loop-contract.md +12 -8
- package/adapters/codex/skills/forge-guide/references/shared-conventions.md +189 -36
- package/adapters/codex/skills/forge-guide/references/stack-resolution.md +1 -1
- package/adapters/codex/skills/forge-init/SKILL.md +62 -12
- package/adapters/codex/skills/forge-init/references/preflight-and-self-heal.md +183 -0
- package/adapters/codex/skills/forge-init/references/shared-conventions.md +572 -0
- package/adapters/codex/skills/forge-verify/SKILL.md +32 -33
- package/adapters/codex/skills/forge-verify/references/findings-template.md +8 -8
- package/adapters/codex/skills/forge-verify/references/select-outcome.md +138 -0
- package/adapters/codex/skills/forge-verify/references/shared-conventions.md +189 -36
- package/adapters/codex/skills/forge-verify/references/stage-exit-protocol.md +22 -7
- package/adapters/codex/skills/forge-verify/references/verification-checklists/epic.md +2 -2
- package/adapters/codex/skills/forge-verify/references/verifier-patterns/MEMORY.md +35 -0
- package/adapters/codex/skills/forge-verify/references/verifier-patterns/pattern_absence_claims.md +36 -0
- package/adapters/codex/skills/forge-verify/references/verifier-patterns/pattern_carveout_sibling_semantics.md +34 -0
- package/adapters/codex/skills/forge-verify/references/verifier-patterns/pattern_deviation_judgment.md +36 -0
- package/adapters/codex/skills/forge-verify/references/verifier-patterns/pattern_enum_vocabulary_ripple.md +43 -0
- package/adapters/codex/skills/forge-verify/references/verifier-patterns/pattern_extend_the_existing.md +31 -0
- package/adapters/codex/skills/forge-verify/references/verifier-patterns/pattern_guard_substitution_detection.md +34 -0
- package/adapters/codex/skills/forge-verify/references/verifier-patterns/pattern_mechanical_rewrite_damage.md +30 -0
- package/adapters/codex/skills/forge-verify/references/verifier-patterns/pattern_postfix_reverify.md +82 -0
- package/adapters/codex/skills/forge-verify/references/verifier-patterns/pattern_proximity_window_guards.md +26 -0
- package/adapters/codex/skills/forge-verify/references/verifier-patterns/pattern_scratch_root_probes.md +40 -0
- package/adapters/codex/skills/forge-verify/references/verifier-patterns/pattern_self_referential_control.md +26 -0
- package/adapters/codex/skills/forge-verify/references/verifier-patterns/pattern_sibling_docstring_sweep.md +28 -0
- package/adapters/codex/skills/forge-verify/references/verifier-patterns/pattern_spec_literals_are_claims.md +45 -0
- package/adapters/codex/skills/forge-verify/references/verifier-patterns/pattern_stale_counts_after_split.md +36 -0
- package/adapters/codex/skills/forge-verify/references/verifier-patterns/pattern_test_count_units.md +20 -0
- package/adapters/codex/skills/forge-verify/references/verifier-patterns/pattern_vacuous_self_reading_tests.md +32 -0
- package/adapters/copilot/.feature-forge-bundle.json +1 -1
- package/adapters/copilot/agents/forge-researcher.md +1 -1
- package/adapters/copilot/agents/forge-verifier.md +17 -6
- package/adapters/copilot/references/forge-config-schema.json +7 -7
- package/adapters/copilot/references/portable-root.md +20 -16
- package/adapters/copilot/references/preflight-and-self-heal.md +183 -0
- package/adapters/copilot/references/process-overview.md +10 -10
- package/adapters/copilot/references/ralph-loop-contract.md +12 -8
- package/adapters/copilot/references/select-outcome.md +138 -0
- package/adapters/copilot/references/shared-conventions.md +189 -36
- package/adapters/copilot/references/skill-frontmatter.schema.json +3 -1
- package/adapters/copilot/references/stack-resolution.md +1 -1
- package/adapters/copilot/references/stage-exit-protocol.md +22 -7
- package/adapters/copilot/references/templates/root-hygiene/AGENTS.md +14 -0
- package/adapters/copilot/references/templates/root-hygiene/CLAUDE.md +14 -0
- package/adapters/copilot/references/templates/specs-hygiene/AGENTS.md +3 -1
- package/adapters/copilot/references/templates/specs-hygiene/CLAUDE.md +2 -1
- package/adapters/copilot/references/verifier-patterns/MEMORY.md +35 -0
- package/adapters/copilot/references/verifier-patterns/pattern_absence_claims.md +36 -0
- package/adapters/copilot/references/verifier-patterns/pattern_carveout_sibling_semantics.md +34 -0
- package/adapters/copilot/references/verifier-patterns/pattern_deviation_judgment.md +36 -0
- package/adapters/copilot/references/verifier-patterns/pattern_enum_vocabulary_ripple.md +43 -0
- package/adapters/copilot/references/verifier-patterns/pattern_extend_the_existing.md +31 -0
- package/adapters/copilot/references/verifier-patterns/pattern_guard_substitution_detection.md +34 -0
- package/adapters/copilot/references/verifier-patterns/pattern_mechanical_rewrite_damage.md +30 -0
- package/adapters/copilot/references/verifier-patterns/pattern_postfix_reverify.md +82 -0
- package/adapters/copilot/references/verifier-patterns/pattern_proximity_window_guards.md +26 -0
- package/adapters/copilot/references/verifier-patterns/pattern_scratch_root_probes.md +40 -0
- package/adapters/copilot/references/verifier-patterns/pattern_self_referential_control.md +26 -0
- package/adapters/copilot/references/verifier-patterns/pattern_sibling_docstring_sweep.md +28 -0
- package/adapters/copilot/references/verifier-patterns/pattern_spec_literals_are_claims.md +45 -0
- package/adapters/copilot/references/verifier-patterns/pattern_stale_counts_after_split.md +36 -0
- package/adapters/copilot/references/verifier-patterns/pattern_test_count_units.md +20 -0
- package/adapters/copilot/references/verifier-patterns/pattern_vacuous_self_reading_tests.md +32 -0
- package/adapters/copilot/references/verify-state.md +98 -0
- package/adapters/copilot/scripts/forge-bootstrap.py +23 -2
- package/adapters/copilot/scripts/forge-root.sh +104 -21
- package/adapters/copilot/scripts/forge-session.py +620 -6969
- package/adapters/copilot/scripts/forge_session/__init__.py +11 -0
- package/adapters/copilot/scripts/forge_session/_common.py +1566 -0
- package/adapters/copilot/scripts/forge_session/_doctor_util.py +218 -0
- package/adapters/copilot/scripts/forge_session/cli.py +1067 -0
- package/adapters/copilot/scripts/forge_session/decisions.py +355 -0
- package/adapters/copilot/scripts/forge_session/discover.py +472 -0
- package/adapters/copilot/scripts/forge_session/doctor.py +2144 -0
- package/adapters/copilot/scripts/forge_session/exit.py +1081 -0
- package/adapters/copilot/scripts/forge_session/outcomes.py +574 -0
- package/adapters/copilot/scripts/forge_session/routes.py +1162 -0
- package/adapters/copilot/scripts/forge_session/state.py +1479 -0
- package/adapters/copilot/scripts/forge_session/topology.py +443 -0
- package/adapters/copilot/skills/forge/forge.md +40 -40
- package/adapters/copilot/skills/forge/references/process-overview.md +10 -10
- package/adapters/copilot/skills/forge/references/shared-conventions.md +189 -36
- package/adapters/copilot/skills/forge/references/stage-exit-protocol.md +22 -7
- package/adapters/copilot/skills/forge-0-epic/forge-0-epic.md +15 -15
- 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/portable-root.md +20 -16
- package/adapters/copilot/skills/forge-0-epic/references/shared-conventions.md +189 -36
- package/adapters/copilot/skills/forge-0-epic/references/stage-exit-protocol.md +22 -7
- package/adapters/copilot/skills/forge-1-prd/forge-1-prd.md +15 -15
- package/adapters/copilot/skills/forge-1-prd/references/shared-conventions.md +189 -36
- package/adapters/copilot/skills/forge-1-prd/references/stage-exit-protocol.md +22 -7
- package/adapters/copilot/skills/forge-2-tech/forge-2-tech.md +15 -15
- package/adapters/copilot/skills/forge-2-tech/references/shared-conventions.md +189 -36
- package/adapters/copilot/skills/forge-2-tech/references/stack-resolution.md +1 -1
- package/adapters/copilot/skills/forge-2-tech/references/stage-exit-protocol.md +22 -7
- package/adapters/copilot/skills/forge-3-specs/forge-3-specs.md +10 -10
- package/adapters/copilot/skills/forge-3-specs/references/shared-conventions.md +189 -36
- package/adapters/copilot/skills/forge-3-specs/references/stage-exit-protocol.md +22 -7
- package/adapters/copilot/skills/forge-4-backlog/forge-4-backlog.md +19 -11
- package/adapters/copilot/skills/forge-4-backlog/references/shared-conventions.md +189 -36
- package/adapters/copilot/skills/forge-4-backlog/references/stage-exit-protocol.md +22 -7
- package/adapters/copilot/skills/forge-4-backlog/references/verify-state.md +98 -0
- package/adapters/copilot/skills/forge-5-loop/forge-5-loop.md +48 -53
- package/adapters/copilot/skills/forge-5-loop/references/agent-selection.md +5 -1
- package/adapters/copilot/skills/forge-5-loop/references/preflight-and-self-heal.md +183 -0
- package/adapters/copilot/skills/forge-5-loop/references/ralph-loop-contract.md +12 -8
- package/adapters/copilot/skills/forge-5-loop/references/recovery-procedure.md +14 -4
- package/adapters/copilot/skills/forge-5-loop/references/runner-contract.md +20 -10
- package/adapters/copilot/skills/forge-5-loop/references/shared-conventions.md +189 -36
- package/adapters/copilot/skills/forge-5-loop/references/stage-exit-protocol.md +22 -7
- package/adapters/copilot/skills/forge-5-loop/references/verify-state.md +98 -0
- package/adapters/copilot/skills/forge-6-docs/forge-6-docs.md +27 -20
- package/adapters/copilot/skills/forge-6-docs/references/shared-conventions.md +189 -36
- package/adapters/copilot/skills/forge-6-docs/references/stage-exit-protocol.md +22 -7
- package/adapters/copilot/skills/forge-6-docs/references/verify-state.md +98 -0
- package/adapters/copilot/skills/forge-bootstrap/forge-bootstrap.md +23 -15
- package/adapters/copilot/skills/forge-bootstrap/references/shared-conventions.md +572 -0
- package/adapters/copilot/skills/forge-bootstrap/references/templates/hygiene/CLAUDE.md +2 -2
- package/adapters/copilot/skills/forge-fix/forge-fix.md +27 -30
- package/adapters/copilot/skills/forge-fix/references/select-outcome.md +138 -0
- package/adapters/copilot/skills/forge-fix/references/shared-conventions.md +189 -36
- package/adapters/copilot/skills/forge-fix/references/stage-exit-protocol.md +22 -7
- package/adapters/copilot/skills/forge-guide/forge-guide.md +84 -7
- package/adapters/copilot/skills/forge-guide/references/forge-config-schema.json +7 -7
- package/adapters/copilot/skills/forge-guide/references/preflight-and-self-heal.md +183 -0
- package/adapters/copilot/skills/forge-guide/references/process-overview.md +10 -10
- package/adapters/copilot/skills/forge-guide/references/ralph-loop-contract.md +12 -8
- package/adapters/copilot/skills/forge-guide/references/shared-conventions.md +189 -36
- package/adapters/copilot/skills/forge-guide/references/stack-resolution.md +1 -1
- package/adapters/copilot/skills/forge-init/forge-init.md +62 -12
- package/adapters/copilot/skills/forge-init/references/preflight-and-self-heal.md +183 -0
- package/adapters/copilot/skills/forge-init/references/shared-conventions.md +572 -0
- package/adapters/copilot/skills/forge-verify/forge-verify.md +32 -33
- package/adapters/copilot/skills/forge-verify/references/findings-template.md +8 -8
- package/adapters/copilot/skills/forge-verify/references/select-outcome.md +138 -0
- package/adapters/copilot/skills/forge-verify/references/shared-conventions.md +189 -36
- package/adapters/copilot/skills/forge-verify/references/stage-exit-protocol.md +22 -7
- package/adapters/copilot/skills/forge-verify/references/verification-checklists/epic.md +2 -2
- package/adapters/copilot/skills/forge-verify/references/verifier-patterns/MEMORY.md +35 -0
- package/adapters/copilot/skills/forge-verify/references/verifier-patterns/pattern_absence_claims.md +36 -0
- package/adapters/copilot/skills/forge-verify/references/verifier-patterns/pattern_carveout_sibling_semantics.md +34 -0
- package/adapters/copilot/skills/forge-verify/references/verifier-patterns/pattern_deviation_judgment.md +36 -0
- package/adapters/copilot/skills/forge-verify/references/verifier-patterns/pattern_enum_vocabulary_ripple.md +43 -0
- package/adapters/copilot/skills/forge-verify/references/verifier-patterns/pattern_extend_the_existing.md +31 -0
- package/adapters/copilot/skills/forge-verify/references/verifier-patterns/pattern_guard_substitution_detection.md +34 -0
- package/adapters/copilot/skills/forge-verify/references/verifier-patterns/pattern_mechanical_rewrite_damage.md +30 -0
- package/adapters/copilot/skills/forge-verify/references/verifier-patterns/pattern_postfix_reverify.md +82 -0
- package/adapters/copilot/skills/forge-verify/references/verifier-patterns/pattern_proximity_window_guards.md +26 -0
- package/adapters/copilot/skills/forge-verify/references/verifier-patterns/pattern_scratch_root_probes.md +40 -0
- package/adapters/copilot/skills/forge-verify/references/verifier-patterns/pattern_self_referential_control.md +26 -0
- package/adapters/copilot/skills/forge-verify/references/verifier-patterns/pattern_sibling_docstring_sweep.md +28 -0
- package/adapters/copilot/skills/forge-verify/references/verifier-patterns/pattern_spec_literals_are_claims.md +45 -0
- package/adapters/copilot/skills/forge-verify/references/verifier-patterns/pattern_stale_counts_after_split.md +36 -0
- package/adapters/copilot/skills/forge-verify/references/verifier-patterns/pattern_test_count_units.md +20 -0
- package/adapters/copilot/skills/forge-verify/references/verifier-patterns/pattern_vacuous_self_reading_tests.md +32 -0
- package/adapters/cursor/.feature-forge-bundle.json +1 -1
- package/adapters/cursor/agents/forge-researcher.mdc +1 -1
- package/adapters/cursor/agents/forge-verifier.mdc +17 -6
- package/adapters/cursor/references/forge-config-schema.json +7 -7
- package/adapters/cursor/references/portable-root.md +20 -16
- package/adapters/cursor/references/preflight-and-self-heal.md +183 -0
- package/adapters/cursor/references/process-overview.md +10 -10
- package/adapters/cursor/references/ralph-loop-contract.md +12 -8
- package/adapters/cursor/references/select-outcome.md +138 -0
- package/adapters/cursor/references/shared-conventions.md +189 -36
- package/adapters/cursor/references/skill-frontmatter.schema.json +3 -1
- package/adapters/cursor/references/stack-resolution.md +1 -1
- package/adapters/cursor/references/stage-exit-protocol.md +22 -7
- package/adapters/cursor/references/templates/root-hygiene/AGENTS.md +14 -0
- package/adapters/cursor/references/templates/root-hygiene/CLAUDE.md +14 -0
- package/adapters/cursor/references/templates/specs-hygiene/AGENTS.md +3 -1
- package/adapters/cursor/references/templates/specs-hygiene/CLAUDE.md +2 -1
- package/adapters/cursor/references/verifier-patterns/MEMORY.md +35 -0
- package/adapters/cursor/references/verifier-patterns/pattern_absence_claims.md +36 -0
- package/adapters/cursor/references/verifier-patterns/pattern_carveout_sibling_semantics.md +34 -0
- package/adapters/cursor/references/verifier-patterns/pattern_deviation_judgment.md +36 -0
- package/adapters/cursor/references/verifier-patterns/pattern_enum_vocabulary_ripple.md +43 -0
- package/adapters/cursor/references/verifier-patterns/pattern_extend_the_existing.md +31 -0
- package/adapters/cursor/references/verifier-patterns/pattern_guard_substitution_detection.md +34 -0
- package/adapters/cursor/references/verifier-patterns/pattern_mechanical_rewrite_damage.md +30 -0
- package/adapters/cursor/references/verifier-patterns/pattern_postfix_reverify.md +82 -0
- package/adapters/cursor/references/verifier-patterns/pattern_proximity_window_guards.md +26 -0
- package/adapters/cursor/references/verifier-patterns/pattern_scratch_root_probes.md +40 -0
- package/adapters/cursor/references/verifier-patterns/pattern_self_referential_control.md +26 -0
- package/adapters/cursor/references/verifier-patterns/pattern_sibling_docstring_sweep.md +28 -0
- package/adapters/cursor/references/verifier-patterns/pattern_spec_literals_are_claims.md +45 -0
- package/adapters/cursor/references/verifier-patterns/pattern_stale_counts_after_split.md +36 -0
- package/adapters/cursor/references/verifier-patterns/pattern_test_count_units.md +20 -0
- package/adapters/cursor/references/verifier-patterns/pattern_vacuous_self_reading_tests.md +32 -0
- package/adapters/cursor/references/verify-state.md +98 -0
- package/adapters/cursor/scripts/forge-bootstrap.py +23 -2
- package/adapters/cursor/scripts/forge-root.sh +104 -21
- package/adapters/cursor/scripts/forge-session.py +620 -6969
- package/adapters/cursor/scripts/forge_session/__init__.py +11 -0
- package/adapters/cursor/scripts/forge_session/_common.py +1566 -0
- package/adapters/cursor/scripts/forge_session/_doctor_util.py +218 -0
- package/adapters/cursor/scripts/forge_session/cli.py +1067 -0
- package/adapters/cursor/scripts/forge_session/decisions.py +355 -0
- package/adapters/cursor/scripts/forge_session/discover.py +472 -0
- package/adapters/cursor/scripts/forge_session/doctor.py +2144 -0
- package/adapters/cursor/scripts/forge_session/exit.py +1081 -0
- package/adapters/cursor/scripts/forge_session/outcomes.py +574 -0
- package/adapters/cursor/scripts/forge_session/routes.py +1162 -0
- package/adapters/cursor/scripts/forge_session/state.py +1479 -0
- package/adapters/cursor/scripts/forge_session/topology.py +443 -0
- package/adapters/cursor/skills/forge/forge.mdc +40 -40
- package/adapters/cursor/skills/forge/references/process-overview.md +10 -10
- package/adapters/cursor/skills/forge/references/shared-conventions.md +189 -36
- package/adapters/cursor/skills/forge/references/stage-exit-protocol.md +22 -7
- package/adapters/cursor/skills/forge-0-epic/forge-0-epic.mdc +15 -15
- 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/portable-root.md +20 -16
- package/adapters/cursor/skills/forge-0-epic/references/shared-conventions.md +189 -36
- package/adapters/cursor/skills/forge-0-epic/references/stage-exit-protocol.md +22 -7
- package/adapters/cursor/skills/forge-1-prd/forge-1-prd.mdc +15 -15
- package/adapters/cursor/skills/forge-1-prd/references/shared-conventions.md +189 -36
- package/adapters/cursor/skills/forge-1-prd/references/stage-exit-protocol.md +22 -7
- package/adapters/cursor/skills/forge-2-tech/forge-2-tech.mdc +15 -15
- package/adapters/cursor/skills/forge-2-tech/references/shared-conventions.md +189 -36
- package/adapters/cursor/skills/forge-2-tech/references/stack-resolution.md +1 -1
- package/adapters/cursor/skills/forge-2-tech/references/stage-exit-protocol.md +22 -7
- package/adapters/cursor/skills/forge-3-specs/forge-3-specs.mdc +10 -10
- package/adapters/cursor/skills/forge-3-specs/references/shared-conventions.md +189 -36
- package/adapters/cursor/skills/forge-3-specs/references/stage-exit-protocol.md +22 -7
- package/adapters/cursor/skills/forge-4-backlog/forge-4-backlog.mdc +19 -11
- package/adapters/cursor/skills/forge-4-backlog/references/shared-conventions.md +189 -36
- package/adapters/cursor/skills/forge-4-backlog/references/stage-exit-protocol.md +22 -7
- package/adapters/cursor/skills/forge-4-backlog/references/verify-state.md +98 -0
- package/adapters/cursor/skills/forge-5-loop/forge-5-loop.mdc +48 -53
- package/adapters/cursor/skills/forge-5-loop/references/agent-selection.md +5 -1
- package/adapters/cursor/skills/forge-5-loop/references/preflight-and-self-heal.md +183 -0
- package/adapters/cursor/skills/forge-5-loop/references/ralph-loop-contract.md +12 -8
- package/adapters/cursor/skills/forge-5-loop/references/recovery-procedure.md +14 -4
- package/adapters/cursor/skills/forge-5-loop/references/runner-contract.md +20 -10
- package/adapters/cursor/skills/forge-5-loop/references/shared-conventions.md +189 -36
- package/adapters/cursor/skills/forge-5-loop/references/stage-exit-protocol.md +22 -7
- package/adapters/cursor/skills/forge-5-loop/references/verify-state.md +98 -0
- package/adapters/cursor/skills/forge-6-docs/forge-6-docs.mdc +27 -20
- package/adapters/cursor/skills/forge-6-docs/references/shared-conventions.md +189 -36
- package/adapters/cursor/skills/forge-6-docs/references/stage-exit-protocol.md +22 -7
- package/adapters/cursor/skills/forge-6-docs/references/verify-state.md +98 -0
- package/adapters/cursor/skills/forge-bootstrap/forge-bootstrap.mdc +23 -15
- package/adapters/cursor/skills/forge-bootstrap/references/shared-conventions.md +572 -0
- package/adapters/cursor/skills/forge-bootstrap/references/templates/hygiene/CLAUDE.md +2 -2
- package/adapters/cursor/skills/forge-fix/forge-fix.mdc +27 -30
- package/adapters/cursor/skills/forge-fix/references/select-outcome.md +138 -0
- package/adapters/cursor/skills/forge-fix/references/shared-conventions.md +189 -36
- package/adapters/cursor/skills/forge-fix/references/stage-exit-protocol.md +22 -7
- package/adapters/cursor/skills/forge-guide/forge-guide.mdc +84 -7
- package/adapters/cursor/skills/forge-guide/references/forge-config-schema.json +7 -7
- package/adapters/cursor/skills/forge-guide/references/preflight-and-self-heal.md +183 -0
- package/adapters/cursor/skills/forge-guide/references/process-overview.md +10 -10
- package/adapters/cursor/skills/forge-guide/references/ralph-loop-contract.md +12 -8
- package/adapters/cursor/skills/forge-guide/references/shared-conventions.md +189 -36
- package/adapters/cursor/skills/forge-guide/references/stack-resolution.md +1 -1
- package/adapters/cursor/skills/forge-init/forge-init.mdc +62 -12
- package/adapters/cursor/skills/forge-init/references/preflight-and-self-heal.md +183 -0
- package/adapters/cursor/skills/forge-init/references/shared-conventions.md +572 -0
- package/adapters/cursor/skills/forge-verify/forge-verify.mdc +32 -33
- package/adapters/cursor/skills/forge-verify/references/findings-template.md +8 -8
- package/adapters/cursor/skills/forge-verify/references/select-outcome.md +138 -0
- package/adapters/cursor/skills/forge-verify/references/shared-conventions.md +189 -36
- package/adapters/cursor/skills/forge-verify/references/stage-exit-protocol.md +22 -7
- package/adapters/cursor/skills/forge-verify/references/verification-checklists/epic.md +2 -2
- package/adapters/cursor/skills/forge-verify/references/verifier-patterns/MEMORY.md +35 -0
- package/adapters/cursor/skills/forge-verify/references/verifier-patterns/pattern_absence_claims.md +36 -0
- package/adapters/cursor/skills/forge-verify/references/verifier-patterns/pattern_carveout_sibling_semantics.md +34 -0
- package/adapters/cursor/skills/forge-verify/references/verifier-patterns/pattern_deviation_judgment.md +36 -0
- package/adapters/cursor/skills/forge-verify/references/verifier-patterns/pattern_enum_vocabulary_ripple.md +43 -0
- package/adapters/cursor/skills/forge-verify/references/verifier-patterns/pattern_extend_the_existing.md +31 -0
- package/adapters/cursor/skills/forge-verify/references/verifier-patterns/pattern_guard_substitution_detection.md +34 -0
- package/adapters/cursor/skills/forge-verify/references/verifier-patterns/pattern_mechanical_rewrite_damage.md +30 -0
- package/adapters/cursor/skills/forge-verify/references/verifier-patterns/pattern_postfix_reverify.md +82 -0
- package/adapters/cursor/skills/forge-verify/references/verifier-patterns/pattern_proximity_window_guards.md +26 -0
- package/adapters/cursor/skills/forge-verify/references/verifier-patterns/pattern_scratch_root_probes.md +40 -0
- package/adapters/cursor/skills/forge-verify/references/verifier-patterns/pattern_self_referential_control.md +26 -0
- package/adapters/cursor/skills/forge-verify/references/verifier-patterns/pattern_sibling_docstring_sweep.md +28 -0
- package/adapters/cursor/skills/forge-verify/references/verifier-patterns/pattern_spec_literals_are_claims.md +45 -0
- package/adapters/cursor/skills/forge-verify/references/verifier-patterns/pattern_stale_counts_after_split.md +36 -0
- package/adapters/cursor/skills/forge-verify/references/verifier-patterns/pattern_test_count_units.md +20 -0
- package/adapters/cursor/skills/forge-verify/references/verifier-patterns/pattern_vacuous_self_reading_tests.md +32 -0
- package/adapters/gemini/.feature-forge-bundle.json +1 -1
- package/adapters/gemini/agents/forge-researcher.md +1 -1
- package/adapters/gemini/agents/forge-verifier.md +17 -6
- package/adapters/gemini/gemini-extension.json +13 -13
- package/adapters/gemini/references/forge-config-schema.json +7 -7
- package/adapters/gemini/references/portable-root.md +20 -16
- package/adapters/gemini/references/preflight-and-self-heal.md +183 -0
- package/adapters/gemini/references/process-overview.md +10 -10
- package/adapters/gemini/references/ralph-loop-contract.md +12 -8
- package/adapters/gemini/references/select-outcome.md +138 -0
- package/adapters/gemini/references/shared-conventions.md +189 -36
- package/adapters/gemini/references/skill-frontmatter.schema.json +3 -1
- package/adapters/gemini/references/stack-resolution.md +1 -1
- package/adapters/gemini/references/stage-exit-protocol.md +22 -7
- package/adapters/gemini/references/templates/root-hygiene/AGENTS.md +14 -0
- package/adapters/gemini/references/templates/root-hygiene/CLAUDE.md +14 -0
- package/adapters/gemini/references/templates/specs-hygiene/AGENTS.md +3 -1
- package/adapters/gemini/references/templates/specs-hygiene/CLAUDE.md +2 -1
- package/adapters/gemini/references/verifier-patterns/MEMORY.md +35 -0
- package/adapters/gemini/references/verifier-patterns/pattern_absence_claims.md +36 -0
- package/adapters/gemini/references/verifier-patterns/pattern_carveout_sibling_semantics.md +34 -0
- package/adapters/gemini/references/verifier-patterns/pattern_deviation_judgment.md +36 -0
- package/adapters/gemini/references/verifier-patterns/pattern_enum_vocabulary_ripple.md +43 -0
- package/adapters/gemini/references/verifier-patterns/pattern_extend_the_existing.md +31 -0
- package/adapters/gemini/references/verifier-patterns/pattern_guard_substitution_detection.md +34 -0
- package/adapters/gemini/references/verifier-patterns/pattern_mechanical_rewrite_damage.md +30 -0
- package/adapters/gemini/references/verifier-patterns/pattern_postfix_reverify.md +82 -0
- package/adapters/gemini/references/verifier-patterns/pattern_proximity_window_guards.md +26 -0
- package/adapters/gemini/references/verifier-patterns/pattern_scratch_root_probes.md +40 -0
- package/adapters/gemini/references/verifier-patterns/pattern_self_referential_control.md +26 -0
- package/adapters/gemini/references/verifier-patterns/pattern_sibling_docstring_sweep.md +28 -0
- package/adapters/gemini/references/verifier-patterns/pattern_spec_literals_are_claims.md +45 -0
- package/adapters/gemini/references/verifier-patterns/pattern_stale_counts_after_split.md +36 -0
- package/adapters/gemini/references/verifier-patterns/pattern_test_count_units.md +20 -0
- package/adapters/gemini/references/verifier-patterns/pattern_vacuous_self_reading_tests.md +32 -0
- package/adapters/gemini/references/verify-state.md +98 -0
- package/adapters/gemini/scripts/forge-bootstrap.py +23 -2
- package/adapters/gemini/scripts/forge-root.sh +104 -21
- package/adapters/gemini/scripts/forge-session.py +620 -6969
- package/adapters/gemini/scripts/forge_session/__init__.py +11 -0
- package/adapters/gemini/scripts/forge_session/_common.py +1566 -0
- package/adapters/gemini/scripts/forge_session/_doctor_util.py +218 -0
- package/adapters/gemini/scripts/forge_session/cli.py +1067 -0
- package/adapters/gemini/scripts/forge_session/decisions.py +355 -0
- package/adapters/gemini/scripts/forge_session/discover.py +472 -0
- package/adapters/gemini/scripts/forge_session/doctor.py +2144 -0
- package/adapters/gemini/scripts/forge_session/exit.py +1081 -0
- package/adapters/gemini/scripts/forge_session/outcomes.py +574 -0
- package/adapters/gemini/scripts/forge_session/routes.py +1162 -0
- package/adapters/gemini/scripts/forge_session/state.py +1479 -0
- package/adapters/gemini/scripts/forge_session/topology.py +443 -0
- package/adapters/gemini/skills/forge/forge.md +40 -40
- package/adapters/gemini/skills/forge/references/process-overview.md +10 -10
- package/adapters/gemini/skills/forge/references/shared-conventions.md +189 -36
- package/adapters/gemini/skills/forge/references/stage-exit-protocol.md +22 -7
- package/adapters/gemini/skills/forge-0-epic/forge-0-epic.md +15 -15
- 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/portable-root.md +20 -16
- package/adapters/gemini/skills/forge-0-epic/references/shared-conventions.md +189 -36
- package/adapters/gemini/skills/forge-0-epic/references/stage-exit-protocol.md +22 -7
- package/adapters/gemini/skills/forge-1-prd/forge-1-prd.md +15 -15
- package/adapters/gemini/skills/forge-1-prd/references/shared-conventions.md +189 -36
- package/adapters/gemini/skills/forge-1-prd/references/stage-exit-protocol.md +22 -7
- package/adapters/gemini/skills/forge-2-tech/forge-2-tech.md +15 -15
- package/adapters/gemini/skills/forge-2-tech/references/shared-conventions.md +189 -36
- package/adapters/gemini/skills/forge-2-tech/references/stack-resolution.md +1 -1
- package/adapters/gemini/skills/forge-2-tech/references/stage-exit-protocol.md +22 -7
- package/adapters/gemini/skills/forge-3-specs/forge-3-specs.md +10 -10
- package/adapters/gemini/skills/forge-3-specs/references/shared-conventions.md +189 -36
- package/adapters/gemini/skills/forge-3-specs/references/stage-exit-protocol.md +22 -7
- package/adapters/gemini/skills/forge-4-backlog/forge-4-backlog.md +19 -11
- package/adapters/gemini/skills/forge-4-backlog/references/shared-conventions.md +189 -36
- package/adapters/gemini/skills/forge-4-backlog/references/stage-exit-protocol.md +22 -7
- package/adapters/gemini/skills/forge-4-backlog/references/verify-state.md +98 -0
- package/adapters/gemini/skills/forge-5-loop/forge-5-loop.md +48 -53
- package/adapters/gemini/skills/forge-5-loop/references/agent-selection.md +5 -1
- package/adapters/gemini/skills/forge-5-loop/references/preflight-and-self-heal.md +183 -0
- package/adapters/gemini/skills/forge-5-loop/references/ralph-loop-contract.md +12 -8
- package/adapters/gemini/skills/forge-5-loop/references/recovery-procedure.md +14 -4
- package/adapters/gemini/skills/forge-5-loop/references/runner-contract.md +20 -10
- package/adapters/gemini/skills/forge-5-loop/references/shared-conventions.md +189 -36
- package/adapters/gemini/skills/forge-5-loop/references/stage-exit-protocol.md +22 -7
- package/adapters/gemini/skills/forge-5-loop/references/verify-state.md +98 -0
- package/adapters/gemini/skills/forge-6-docs/forge-6-docs.md +27 -20
- package/adapters/gemini/skills/forge-6-docs/references/shared-conventions.md +189 -36
- package/adapters/gemini/skills/forge-6-docs/references/stage-exit-protocol.md +22 -7
- package/adapters/gemini/skills/forge-6-docs/references/verify-state.md +98 -0
- package/adapters/gemini/skills/forge-bootstrap/forge-bootstrap.md +23 -15
- package/adapters/gemini/skills/forge-bootstrap/references/shared-conventions.md +572 -0
- package/adapters/gemini/skills/forge-bootstrap/references/templates/hygiene/CLAUDE.md +2 -2
- package/adapters/gemini/skills/forge-fix/forge-fix.md +27 -30
- package/adapters/gemini/skills/forge-fix/references/select-outcome.md +138 -0
- package/adapters/gemini/skills/forge-fix/references/shared-conventions.md +189 -36
- package/adapters/gemini/skills/forge-fix/references/stage-exit-protocol.md +22 -7
- package/adapters/gemini/skills/forge-guide/forge-guide.md +84 -7
- package/adapters/gemini/skills/forge-guide/references/forge-config-schema.json +7 -7
- package/adapters/gemini/skills/forge-guide/references/preflight-and-self-heal.md +183 -0
- package/adapters/gemini/skills/forge-guide/references/process-overview.md +10 -10
- package/adapters/gemini/skills/forge-guide/references/ralph-loop-contract.md +12 -8
- package/adapters/gemini/skills/forge-guide/references/shared-conventions.md +189 -36
- package/adapters/gemini/skills/forge-guide/references/stack-resolution.md +1 -1
- package/adapters/gemini/skills/forge-init/forge-init.md +62 -12
- package/adapters/gemini/skills/forge-init/references/preflight-and-self-heal.md +183 -0
- package/adapters/gemini/skills/forge-init/references/shared-conventions.md +572 -0
- package/adapters/gemini/skills/forge-verify/forge-verify.md +32 -33
- package/adapters/gemini/skills/forge-verify/references/findings-template.md +8 -8
- package/adapters/gemini/skills/forge-verify/references/select-outcome.md +138 -0
- package/adapters/gemini/skills/forge-verify/references/shared-conventions.md +189 -36
- package/adapters/gemini/skills/forge-verify/references/stage-exit-protocol.md +22 -7
- package/adapters/gemini/skills/forge-verify/references/verification-checklists/epic.md +2 -2
- package/adapters/gemini/skills/forge-verify/references/verifier-patterns/MEMORY.md +35 -0
- package/adapters/gemini/skills/forge-verify/references/verifier-patterns/pattern_absence_claims.md +36 -0
- package/adapters/gemini/skills/forge-verify/references/verifier-patterns/pattern_carveout_sibling_semantics.md +34 -0
- package/adapters/gemini/skills/forge-verify/references/verifier-patterns/pattern_deviation_judgment.md +36 -0
- package/adapters/gemini/skills/forge-verify/references/verifier-patterns/pattern_enum_vocabulary_ripple.md +43 -0
- package/adapters/gemini/skills/forge-verify/references/verifier-patterns/pattern_extend_the_existing.md +31 -0
- package/adapters/gemini/skills/forge-verify/references/verifier-patterns/pattern_guard_substitution_detection.md +34 -0
- package/adapters/gemini/skills/forge-verify/references/verifier-patterns/pattern_mechanical_rewrite_damage.md +30 -0
- package/adapters/gemini/skills/forge-verify/references/verifier-patterns/pattern_postfix_reverify.md +82 -0
- package/adapters/gemini/skills/forge-verify/references/verifier-patterns/pattern_proximity_window_guards.md +26 -0
- package/adapters/gemini/skills/forge-verify/references/verifier-patterns/pattern_scratch_root_probes.md +40 -0
- package/adapters/gemini/skills/forge-verify/references/verifier-patterns/pattern_self_referential_control.md +26 -0
- package/adapters/gemini/skills/forge-verify/references/verifier-patterns/pattern_sibling_docstring_sweep.md +28 -0
- package/adapters/gemini/skills/forge-verify/references/verifier-patterns/pattern_spec_literals_are_claims.md +45 -0
- package/adapters/gemini/skills/forge-verify/references/verifier-patterns/pattern_stale_counts_after_split.md +36 -0
- package/adapters/gemini/skills/forge-verify/references/verifier-patterns/pattern_test_count_units.md +20 -0
- package/adapters/gemini/skills/forge-verify/references/verifier-patterns/pattern_vacuous_self_reading_tests.md +32 -0
- package/adapters/pi/.feature-forge-bundle.json +1 -1
- package/adapters/pi/agents/forge-verifier.md +16 -5
- package/adapters/pi/extensions/forge-invocation-args/README.md +106 -0
- package/adapters/pi/extensions/forge-invocation-args/index.ts +31 -0
- package/adapters/pi/extensions/forge-invocation-args/wiring.ts +172 -0
- package/adapters/pi/extensions/forge-loop-supervisor/events.ts +90 -0
- package/adapters/pi/extensions/forge-loop-supervisor/index.ts +114 -0
- package/adapters/pi/extensions/forge-loop-supervisor/registry.ts +137 -0
- package/adapters/pi/extensions/forge-loop-supervisor/supervisor.ts +185 -0
- package/adapters/pi/extensions/forge-loop-supervisor/tailer.ts +137 -0
- package/adapters/pi/extensions/forge-loop-supervisor/types.ts +87 -0
- package/adapters/pi/extensions/forge-loop-supervisor/wiring.ts +423 -0
- package/adapters/pi/package.json +3 -1
- package/adapters/pi/references/forge-config-schema.json +5 -5
- package/adapters/pi/references/portable-root.md +20 -16
- package/adapters/pi/references/preflight-and-self-heal.md +183 -0
- package/adapters/pi/references/ralph-loop-contract.md +12 -8
- package/adapters/pi/references/select-outcome.md +138 -0
- package/adapters/pi/references/shared-conventions.md +176 -23
- package/adapters/pi/references/skill-frontmatter.schema.json +3 -1
- package/adapters/pi/references/stack-resolution.md +1 -1
- package/adapters/pi/references/stage-exit-protocol.md +19 -4
- package/adapters/pi/references/templates/root-hygiene/AGENTS.md +14 -0
- package/adapters/pi/references/templates/root-hygiene/CLAUDE.md +14 -0
- package/adapters/pi/references/templates/specs-hygiene/AGENTS.md +3 -1
- package/adapters/pi/references/templates/specs-hygiene/CLAUDE.md +2 -1
- package/adapters/pi/references/verifier-patterns/MEMORY.md +35 -0
- package/adapters/pi/references/verifier-patterns/pattern_absence_claims.md +36 -0
- package/adapters/pi/references/verifier-patterns/pattern_carveout_sibling_semantics.md +34 -0
- package/adapters/pi/references/verifier-patterns/pattern_deviation_judgment.md +36 -0
- package/adapters/pi/references/verifier-patterns/pattern_enum_vocabulary_ripple.md +43 -0
- package/adapters/pi/references/verifier-patterns/pattern_extend_the_existing.md +31 -0
- package/adapters/pi/references/verifier-patterns/pattern_guard_substitution_detection.md +34 -0
- package/adapters/pi/references/verifier-patterns/pattern_mechanical_rewrite_damage.md +30 -0
- package/adapters/pi/references/verifier-patterns/pattern_postfix_reverify.md +82 -0
- package/adapters/pi/references/verifier-patterns/pattern_proximity_window_guards.md +26 -0
- package/adapters/pi/references/verifier-patterns/pattern_scratch_root_probes.md +40 -0
- package/adapters/pi/references/verifier-patterns/pattern_self_referential_control.md +26 -0
- package/adapters/pi/references/verifier-patterns/pattern_sibling_docstring_sweep.md +28 -0
- package/adapters/pi/references/verifier-patterns/pattern_spec_literals_are_claims.md +45 -0
- package/adapters/pi/references/verifier-patterns/pattern_stale_counts_after_split.md +36 -0
- package/adapters/pi/references/verifier-patterns/pattern_test_count_units.md +20 -0
- package/adapters/pi/references/verifier-patterns/pattern_vacuous_self_reading_tests.md +32 -0
- package/adapters/pi/references/verify-state.md +98 -0
- package/adapters/pi/scripts/forge-bootstrap.py +23 -2
- package/adapters/pi/scripts/forge-root.sh +104 -21
- package/adapters/pi/scripts/forge-session.py +620 -6969
- package/adapters/pi/scripts/forge_session/__init__.py +11 -0
- package/adapters/pi/scripts/forge_session/_common.py +1566 -0
- package/adapters/pi/scripts/forge_session/_doctor_util.py +218 -0
- package/adapters/pi/scripts/forge_session/cli.py +1067 -0
- package/adapters/pi/scripts/forge_session/decisions.py +355 -0
- package/adapters/pi/scripts/forge_session/discover.py +472 -0
- package/adapters/pi/scripts/forge_session/doctor.py +2144 -0
- package/adapters/pi/scripts/forge_session/exit.py +1081 -0
- package/adapters/pi/scripts/forge_session/outcomes.py +574 -0
- package/adapters/pi/scripts/forge_session/routes.py +1162 -0
- package/adapters/pi/scripts/forge_session/state.py +1479 -0
- package/adapters/pi/scripts/forge_session/topology.py +443 -0
- package/adapters/pi/skills/forge/SKILL.md +13 -9
- package/adapters/pi/skills/forge/references/shared-conventions.md +176 -23
- package/adapters/pi/skills/forge/references/stage-exit-protocol.md +19 -4
- package/adapters/pi/skills/forge-0-epic/SKILL.md +13 -9
- package/adapters/pi/skills/forge-0-epic/references/edit-mode.md +9 -5
- package/adapters/pi/skills/forge-0-epic/references/epic-manifest-subcommands.md +6 -1
- package/adapters/pi/skills/forge-0-epic/references/portable-root.md +20 -16
- package/adapters/pi/skills/forge-0-epic/references/shared-conventions.md +176 -23
- package/adapters/pi/skills/forge-0-epic/references/stage-exit-protocol.md +19 -4
- package/adapters/pi/skills/forge-1-prd/SKILL.md +13 -9
- package/adapters/pi/skills/forge-1-prd/references/shared-conventions.md +176 -23
- package/adapters/pi/skills/forge-1-prd/references/stage-exit-protocol.md +19 -4
- package/adapters/pi/skills/forge-2-tech/SKILL.md +12 -8
- package/adapters/pi/skills/forge-2-tech/references/shared-conventions.md +176 -23
- package/adapters/pi/skills/forge-2-tech/references/stack-resolution.md +1 -1
- package/adapters/pi/skills/forge-2-tech/references/stage-exit-protocol.md +19 -4
- package/adapters/pi/skills/forge-3-specs/SKILL.md +11 -7
- package/adapters/pi/skills/forge-3-specs/references/shared-conventions.md +176 -23
- package/adapters/pi/skills/forge-3-specs/references/stage-exit-protocol.md +19 -4
- package/adapters/pi/skills/forge-4-backlog/SKILL.md +22 -10
- package/adapters/pi/skills/forge-4-backlog/references/shared-conventions.md +176 -23
- package/adapters/pi/skills/forge-4-backlog/references/stage-exit-protocol.md +19 -4
- package/adapters/pi/skills/forge-4-backlog/references/verify-state.md +98 -0
- package/adapters/pi/skills/forge-5-loop/SKILL.md +47 -45
- package/adapters/pi/skills/forge-5-loop/references/agent-selection.md +4 -0
- package/adapters/pi/skills/forge-5-loop/references/preflight-and-self-heal.md +183 -0
- package/adapters/pi/skills/forge-5-loop/references/ralph-loop-contract.md +12 -8
- package/adapters/pi/skills/forge-5-loop/references/recovery-procedure.md +10 -0
- package/adapters/pi/skills/forge-5-loop/references/runner-contract.md +22 -9
- package/adapters/pi/skills/forge-5-loop/references/shared-conventions.md +176 -23
- package/adapters/pi/skills/forge-5-loop/references/stage-exit-protocol.md +19 -4
- package/adapters/pi/skills/forge-5-loop/references/verify-state.md +98 -0
- package/adapters/pi/skills/forge-6-docs/SKILL.md +27 -16
- package/adapters/pi/skills/forge-6-docs/references/shared-conventions.md +176 -23
- package/adapters/pi/skills/forge-6-docs/references/stage-exit-protocol.md +19 -4
- package/adapters/pi/skills/forge-6-docs/references/verify-state.md +98 -0
- package/adapters/pi/skills/forge-bootstrap/SKILL.md +24 -12
- package/adapters/pi/skills/forge-bootstrap/references/shared-conventions.md +572 -0
- package/adapters/pi/skills/forge-fix/SKILL.md +21 -20
- package/adapters/pi/skills/forge-fix/references/select-outcome.md +138 -0
- package/adapters/pi/skills/forge-fix/references/shared-conventions.md +176 -23
- package/adapters/pi/skills/forge-fix/references/stage-exit-protocol.md +19 -4
- package/adapters/pi/skills/forge-guide/SKILL.md +83 -2
- package/adapters/pi/skills/forge-guide/references/forge-config-schema.json +5 -5
- package/adapters/pi/skills/forge-guide/references/preflight-and-self-heal.md +183 -0
- package/adapters/pi/skills/forge-guide/references/ralph-loop-contract.md +12 -8
- package/adapters/pi/skills/forge-guide/references/shared-conventions.md +176 -23
- package/adapters/pi/skills/forge-guide/references/stack-resolution.md +1 -1
- package/adapters/pi/skills/forge-init/SKILL.md +63 -9
- package/adapters/pi/skills/forge-init/references/preflight-and-self-heal.md +183 -0
- package/adapters/pi/skills/forge-init/references/shared-conventions.md +572 -0
- package/adapters/pi/skills/forge-verify/SKILL.md +26 -23
- package/adapters/pi/skills/forge-verify/references/findings-template.md +7 -7
- package/adapters/pi/skills/forge-verify/references/select-outcome.md +138 -0
- package/adapters/pi/skills/forge-verify/references/shared-conventions.md +176 -23
- package/adapters/pi/skills/forge-verify/references/stage-exit-protocol.md +19 -4
- package/adapters/pi/skills/forge-verify/references/verification-checklists/epic.md +1 -1
- package/adapters/pi/skills/forge-verify/references/verifier-patterns/MEMORY.md +35 -0
- package/adapters/pi/skills/forge-verify/references/verifier-patterns/pattern_absence_claims.md +36 -0
- package/adapters/pi/skills/forge-verify/references/verifier-patterns/pattern_carveout_sibling_semantics.md +34 -0
- package/adapters/pi/skills/forge-verify/references/verifier-patterns/pattern_deviation_judgment.md +36 -0
- package/adapters/pi/skills/forge-verify/references/verifier-patterns/pattern_enum_vocabulary_ripple.md +43 -0
- package/adapters/pi/skills/forge-verify/references/verifier-patterns/pattern_extend_the_existing.md +31 -0
- package/adapters/pi/skills/forge-verify/references/verifier-patterns/pattern_guard_substitution_detection.md +34 -0
- package/adapters/pi/skills/forge-verify/references/verifier-patterns/pattern_mechanical_rewrite_damage.md +30 -0
- package/adapters/pi/skills/forge-verify/references/verifier-patterns/pattern_postfix_reverify.md +82 -0
- package/adapters/pi/skills/forge-verify/references/verifier-patterns/pattern_proximity_window_guards.md +26 -0
- package/adapters/pi/skills/forge-verify/references/verifier-patterns/pattern_scratch_root_probes.md +40 -0
- package/adapters/pi/skills/forge-verify/references/verifier-patterns/pattern_self_referential_control.md +26 -0
- package/adapters/pi/skills/forge-verify/references/verifier-patterns/pattern_sibling_docstring_sweep.md +28 -0
- package/adapters/pi/skills/forge-verify/references/verifier-patterns/pattern_spec_literals_are_claims.md +45 -0
- package/adapters/pi/skills/forge-verify/references/verifier-patterns/pattern_stale_counts_after_split.md +36 -0
- package/adapters/pi/skills/forge-verify/references/verifier-patterns/pattern_test_count_units.md +20 -0
- package/adapters/pi/skills/forge-verify/references/verifier-patterns/pattern_vacuous_self_reading_tests.md +32 -0
- package/dist/manifest.d.ts +1 -1
- package/dist/rauf.d.ts +3 -3
- package/dist/rauf.js +2 -2
- package/dist/source.d.ts +5 -2
- package/dist/source.js +5 -2
- package/dist/types.d.ts +1 -1
- package/dist/types.js +1 -1
- package/package.json +9 -2
|
@@ -0,0 +1,1067 @@
|
|
|
1
|
+
"""Argument parsing and command dispatch for the forge-session CLI (#279 P4.1).
|
|
2
|
+
|
|
3
|
+
``main()`` is the single entry point the hyphen-named shim ``scripts/forge-session.py``
|
|
4
|
+
calls. Every verb's business logic lives in a sibling package module
|
|
5
|
+
(``discover``/``doctor``/``outcomes``/``state``/``exit``/``routes``/``decisions``/
|
|
6
|
+
``topology``); this module owns only the argparse construction, the per-verb dispatch,
|
|
7
|
+
the ``rank-features``/``context-usage``/``effective-config`` verbs (the small read-only
|
|
8
|
+
reporters that never earned their own module), and the shared ``_emit`` helper.
|
|
9
|
+
|
|
10
|
+
All verb names, flags, exit codes, and JSON shapes are frozen — this module is a pure
|
|
11
|
+
relocation of the dispatch that used to live in the shim body.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import argparse
|
|
17
|
+
import json
|
|
18
|
+
import sys
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
from typing import Callable, Final, NoReturn, get_args
|
|
21
|
+
|
|
22
|
+
from forge_session._common import (
|
|
23
|
+
ExitOwner,
|
|
24
|
+
FeatureRow,
|
|
25
|
+
PRODUCTION_STAGES,
|
|
26
|
+
UsageError,
|
|
27
|
+
VERIFY_MODE_TO_STAGE,
|
|
28
|
+
VERIFY_RESULT_STATUSES,
|
|
29
|
+
VERIFY_STAGES,
|
|
30
|
+
VERIFY_TOKEN_BY_STAGE,
|
|
31
|
+
VerifyCapability,
|
|
32
|
+
EXIT_HOSTS,
|
|
33
|
+
EXIT_STAGES,
|
|
34
|
+
_counts,
|
|
35
|
+
_default_schema_path,
|
|
36
|
+
load_effective_config,
|
|
37
|
+
build_rows,
|
|
38
|
+
invalid_auto_verify_keys,
|
|
39
|
+
resolve_loop_runner_layers,
|
|
40
|
+
)
|
|
41
|
+
from forge_session.decisions import (
|
|
42
|
+
_default_actor,
|
|
43
|
+
_print_decision_apply,
|
|
44
|
+
_print_decision_list,
|
|
45
|
+
_print_decision_record,
|
|
46
|
+
cmd_decision_apply,
|
|
47
|
+
cmd_decision_list,
|
|
48
|
+
cmd_decision_record,
|
|
49
|
+
)
|
|
50
|
+
from forge_session.discover import (
|
|
51
|
+
_print_check_epic_base,
|
|
52
|
+
_print_discover,
|
|
53
|
+
_print_discover_all,
|
|
54
|
+
_print_reconcile,
|
|
55
|
+
check_epic_base,
|
|
56
|
+
discover_all,
|
|
57
|
+
discover_feature,
|
|
58
|
+
reconcile_branch,
|
|
59
|
+
)
|
|
60
|
+
from forge_session.doctor import (
|
|
61
|
+
DOCTOR_CHECK_IDS,
|
|
62
|
+
_print_doctor,
|
|
63
|
+
doctor_report,
|
|
64
|
+
)
|
|
65
|
+
from forge_session.exit import (
|
|
66
|
+
_EXIT_PRODUCTION_STAGES,
|
|
67
|
+
_print_stage_exit,
|
|
68
|
+
stage_exit,
|
|
69
|
+
)
|
|
70
|
+
from forge_session.outcomes import (
|
|
71
|
+
select_outcome,
|
|
72
|
+
verify_state_for_stage,
|
|
73
|
+
)
|
|
74
|
+
from forge_session.state import (
|
|
75
|
+
_parse_based_on,
|
|
76
|
+
_parse_bool,
|
|
77
|
+
_print_state_artifact,
|
|
78
|
+
_print_state_branch,
|
|
79
|
+
_print_state_complete,
|
|
80
|
+
_print_state_decision,
|
|
81
|
+
_print_state_ecr,
|
|
82
|
+
_print_state_enter,
|
|
83
|
+
_print_state_note,
|
|
84
|
+
_print_state_skip,
|
|
85
|
+
_print_state_verify,
|
|
86
|
+
cmd_state_artifact,
|
|
87
|
+
cmd_state_branch,
|
|
88
|
+
cmd_state_complete,
|
|
89
|
+
cmd_state_decision,
|
|
90
|
+
cmd_state_ecr,
|
|
91
|
+
cmd_state_enter,
|
|
92
|
+
cmd_state_note,
|
|
93
|
+
cmd_state_skip,
|
|
94
|
+
cmd_state_verify,
|
|
95
|
+
)
|
|
96
|
+
from forge_session.topology import (
|
|
97
|
+
_load_topology_items,
|
|
98
|
+
_print_topology,
|
|
99
|
+
cmd_backlog_topology,
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
# --------------------------------------------------------------------------- #
|
|
104
|
+
# CLI-only argparse-choice domains
|
|
105
|
+
#
|
|
106
|
+
# These enumerations exist ONLY to constrain a flag's `choices`; no package module
|
|
107
|
+
# imports them (they are referenced only in main()'s argparse), so they live here
|
|
108
|
+
# beside the parser that uses them rather than in the shared _common layer.
|
|
109
|
+
# --------------------------------------------------------------------------- #
|
|
110
|
+
|
|
111
|
+
#: The --stage domain for the state-write verbs: the six PRODUCTION_STAGES (order-
|
|
112
|
+
#: sensitive) plus forge-0-epic, which also carries a stageEntry but is excluded from
|
|
113
|
+
#: the next-stage walk.
|
|
114
|
+
STATE_VERB_STAGES: Final[tuple[str, ...]] = ("forge-0-epic", *PRODUCTION_STAGES)
|
|
115
|
+
|
|
116
|
+
#: The `--raised-by` / `--target-stage` domains for `state-decision`, and the
|
|
117
|
+
#: `--kind` / `--raised-by` domains for `state-ecr`. SOURCE OF TRUTH:
|
|
118
|
+
#: references/pipeline-state-schema.json (the `deferredDecisions` and
|
|
119
|
+
#: `epicChangeRequests` array item enums). Mirrored here so an out-of-enum value is
|
|
120
|
+
#: rejected at parse time; a drift guard asserts they still match the schema.
|
|
121
|
+
DECISION_RAISED_BY: Final[tuple[str, ...]] = (
|
|
122
|
+
"forge-1-prd",
|
|
123
|
+
"forge-2-tech",
|
|
124
|
+
"forge-3-specs",
|
|
125
|
+
"forge-4-backlog",
|
|
126
|
+
)
|
|
127
|
+
DECISION_TARGET_STAGES: Final[tuple[str, ...]] = (
|
|
128
|
+
"forge-1-prd",
|
|
129
|
+
"forge-2-tech",
|
|
130
|
+
"forge-3-specs",
|
|
131
|
+
"forge-4-backlog",
|
|
132
|
+
"forge-5-loop",
|
|
133
|
+
"forge-6-docs",
|
|
134
|
+
)
|
|
135
|
+
ECR_KINDS: Final[tuple[str, ...]] = ("add-feature", "redep", "move-boundary", "split")
|
|
136
|
+
ECR_RAISED_BY: Final[tuple[str, ...]] = ("forge-1-prd", "forge-2-tech")
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
# --------------------------------------------------------------------------- #
|
|
140
|
+
# Context-window usage (the `context-usage` verb)
|
|
141
|
+
# --------------------------------------------------------------------------- #
|
|
142
|
+
|
|
143
|
+
#: Default context window when the model can't be inferred and config is silent.
|
|
144
|
+
_DEFAULT_WINDOW: Final = 200_000
|
|
145
|
+
#: Window for 1M-context models (model id carries a `[1m]` / `-1m` marker).
|
|
146
|
+
_WIDE_WINDOW: Final = 1_000_000
|
|
147
|
+
#: Default fraction of the window past which a clean session is recommended.
|
|
148
|
+
_DEFAULT_THRESHOLD: Final = 0.7
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def _cwd_slug(cwd: Path) -> str:
|
|
152
|
+
"""Map a working directory to its Claude Code project-dir slug.
|
|
153
|
+
|
|
154
|
+
Claude Code names the per-project transcript dir by replacing path
|
|
155
|
+
separators (and dots) in the absolute cwd with hyphens, e.g.
|
|
156
|
+
``/home/u/proj`` -> ``-home-u-proj``.
|
|
157
|
+
"""
|
|
158
|
+
return str(cwd.resolve()).replace("/", "-").replace(".", "-")
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def _latest_transcript(cwd: Path) -> Path | None:
|
|
162
|
+
"""Return the most-recently-modified transcript JSONL for this cwd, if any."""
|
|
163
|
+
project_dir = Path.home() / ".claude" / "projects" / _cwd_slug(cwd)
|
|
164
|
+
if not project_dir.is_dir():
|
|
165
|
+
return None
|
|
166
|
+
transcripts = [p for p in project_dir.glob("*.jsonl") if p.is_file()]
|
|
167
|
+
if not transcripts:
|
|
168
|
+
return None
|
|
169
|
+
return max(transcripts, key=lambda p: p.stat().st_mtime)
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def _last_usage(transcript: Path) -> tuple[int, str | None] | None:
|
|
173
|
+
"""Scan a transcript from the end for the last `usage` record.
|
|
174
|
+
|
|
175
|
+
Returns ``(token_total, model_id)`` where the total sums
|
|
176
|
+
``input_tokens + cache_creation_input_tokens + cache_read_input_tokens +
|
|
177
|
+
output_tokens`` of the most recent message carrying a usage object — i.e. the
|
|
178
|
+
current context occupancy. Returns ``None`` if no usable record is found.
|
|
179
|
+
"""
|
|
180
|
+
try:
|
|
181
|
+
lines = transcript.read_text(encoding="utf-8").splitlines()
|
|
182
|
+
except OSError:
|
|
183
|
+
return None
|
|
184
|
+
for line in reversed(lines):
|
|
185
|
+
line = line.strip()
|
|
186
|
+
if not line or '"usage"' not in line:
|
|
187
|
+
continue
|
|
188
|
+
try:
|
|
189
|
+
record = json.loads(line)
|
|
190
|
+
except json.JSONDecodeError:
|
|
191
|
+
continue
|
|
192
|
+
message = record.get("message")
|
|
193
|
+
usage = message.get("usage") if isinstance(message, dict) else record.get("usage")
|
|
194
|
+
if not isinstance(usage, dict):
|
|
195
|
+
continue
|
|
196
|
+
# A malformed transcript may carry a non-numeric usage field; skip that
|
|
197
|
+
# record rather than crash the whole context-usage read (ValueError/TypeError).
|
|
198
|
+
try:
|
|
199
|
+
total = (
|
|
200
|
+
int(usage.get("input_tokens", 0) or 0)
|
|
201
|
+
+ int(usage.get("cache_creation_input_tokens", 0) or 0)
|
|
202
|
+
+ int(usage.get("cache_read_input_tokens", 0) or 0)
|
|
203
|
+
+ int(usage.get("output_tokens", 0) or 0)
|
|
204
|
+
)
|
|
205
|
+
except (TypeError, ValueError):
|
|
206
|
+
continue
|
|
207
|
+
if total <= 0:
|
|
208
|
+
continue
|
|
209
|
+
model = message.get("model") if isinstance(message, dict) else record.get("model")
|
|
210
|
+
return total, (model if isinstance(model, str) else None)
|
|
211
|
+
return None
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def _infer_window(model: str | None) -> int:
|
|
215
|
+
"""Infer the context window from a model id (1M-context markers -> wide)."""
|
|
216
|
+
if model and ("[1m]" in model.lower() or "-1m" in model.lower()):
|
|
217
|
+
return _WIDE_WINDOW
|
|
218
|
+
return _DEFAULT_WINDOW
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def context_usage(
|
|
222
|
+
config_path: Path,
|
|
223
|
+
window_override: int | None,
|
|
224
|
+
threshold_override: float | None,
|
|
225
|
+
) -> dict:
|
|
226
|
+
"""Compute live context-window occupancy for the current session.
|
|
227
|
+
|
|
228
|
+
Window precedence: ``--window`` > config ``contextWindowTokens`` > inferred
|
|
229
|
+
from the transcript's model id > ``_DEFAULT_WINDOW``. When inferring (no
|
|
230
|
+
override, no config) and the observed token total already exceeds the default
|
|
231
|
+
window, the window is auto-bumped to ``_WIDE_WINDOW`` — observed tokens above
|
|
232
|
+
200k prove a wider (1M-beta) window is active, so this corrects the reading
|
|
233
|
+
without ever under-reporting a genuine 200k session. Threshold precedence:
|
|
234
|
+
``--threshold`` > config ``contextWarnThreshold`` > ``_DEFAULT_THRESHOLD``.
|
|
235
|
+
|
|
236
|
+
Returns a dict with ``available: True`` and ``{tokens, windowTokens, pct,
|
|
237
|
+
overThreshold, recommendation, model}`` when usage is found, or
|
|
238
|
+
``{available: False, reason}`` otherwise. Never raises for a missing
|
|
239
|
+
transcript — that is the expected non-Claude / fresh-session path.
|
|
240
|
+
"""
|
|
241
|
+
# One read of the effective config (committed + machine-local overlay) for both keys —
|
|
242
|
+
# not once per key (#324: load_effective_config touches two files).
|
|
243
|
+
config = load_effective_config(config_path)
|
|
244
|
+
threshold = threshold_override
|
|
245
|
+
if threshold is None:
|
|
246
|
+
cfg_threshold = config.get("contextWarnThreshold")
|
|
247
|
+
threshold = (
|
|
248
|
+
float(cfg_threshold)
|
|
249
|
+
if isinstance(cfg_threshold, (int, float))
|
|
250
|
+
else _DEFAULT_THRESHOLD
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
transcript = _latest_transcript(Path.cwd())
|
|
254
|
+
if transcript is None:
|
|
255
|
+
return {"available": False, "reason": "no session transcript found"}
|
|
256
|
+
found = _last_usage(transcript)
|
|
257
|
+
if found is None:
|
|
258
|
+
return {"available": False, "reason": "no usage record in transcript"}
|
|
259
|
+
tokens, model = found
|
|
260
|
+
|
|
261
|
+
window = window_override
|
|
262
|
+
if window is None or window <= 0:
|
|
263
|
+
cfg_window = config.get("contextWindowTokens")
|
|
264
|
+
if isinstance(cfg_window, int) and cfg_window > 0:
|
|
265
|
+
window = cfg_window
|
|
266
|
+
else:
|
|
267
|
+
# Inferring (no override, no config). Start from the model marker /
|
|
268
|
+
# conservative default, then auto-bump: observed tokens above the
|
|
269
|
+
# default window PROVE a wider window is active (a 200k session can
|
|
270
|
+
# never exceed 200k), so widen to 1M rather than report a nonsensical
|
|
271
|
+
# >100%. Never under-reports a real 200k session, which can't trip it.
|
|
272
|
+
window = _infer_window(model)
|
|
273
|
+
if tokens > window:
|
|
274
|
+
window = _WIDE_WINDOW
|
|
275
|
+
|
|
276
|
+
pct = round(tokens / window, 4)
|
|
277
|
+
over = pct >= threshold
|
|
278
|
+
if over:
|
|
279
|
+
recommendation = "clean-session"
|
|
280
|
+
else:
|
|
281
|
+
recommendation = "continue"
|
|
282
|
+
return {
|
|
283
|
+
"available": True,
|
|
284
|
+
"tokens": tokens,
|
|
285
|
+
"windowTokens": window,
|
|
286
|
+
"pct": pct,
|
|
287
|
+
"threshold": threshold,
|
|
288
|
+
"overThreshold": over,
|
|
289
|
+
"recommendation": recommendation,
|
|
290
|
+
"model": model,
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
# --------------------------------------------------------------------------- #
|
|
295
|
+
# CLI dispatch
|
|
296
|
+
# --------------------------------------------------------------------------- #
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
def _emit(payload: dict, json_output: bool, printer: Callable[[dict], None]) -> None:
|
|
300
|
+
"""Emit a state-verb result: the full JSON echo on --json, else the printer.
|
|
301
|
+
|
|
302
|
+
Args:
|
|
303
|
+
payload: The verb's resulting state dict.
|
|
304
|
+
json_output: The ``--json`` flag.
|
|
305
|
+
printer: The verb's one-line human-readable printer.
|
|
306
|
+
"""
|
|
307
|
+
if json_output:
|
|
308
|
+
print(json.dumps(payload, indent=2, ensure_ascii=False))
|
|
309
|
+
else:
|
|
310
|
+
printer(payload)
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
def _print_rank_table(rows: list[FeatureRow], counts: dict[str, int]) -> None:
|
|
314
|
+
"""Print a human-readable recency-ranked feature list."""
|
|
315
|
+
print(
|
|
316
|
+
f"Active: {counts['active']} "
|
|
317
|
+
f"(paused: {counts['paused']}, abandoned: {counts['abandoned']})"
|
|
318
|
+
)
|
|
319
|
+
if not rows:
|
|
320
|
+
print(" (no active feature pipelines)")
|
|
321
|
+
return
|
|
322
|
+
for idx, row in enumerate(rows):
|
|
323
|
+
marker = "→" if idx == 0 else " "
|
|
324
|
+
label = row["name"] + (f" [{row['epic']}]" if row["epic"] else "")
|
|
325
|
+
nxt = row["nextCommand"] or "complete"
|
|
326
|
+
print(f" {marker} {label}: {row['currentStage']} — next: {nxt}")
|
|
327
|
+
if row["verifyPending"]:
|
|
328
|
+
# Owed automatic verification is an obligation, not an offer — the
|
|
329
|
+
# full diagnostic sentence went to stderr, so keep this line honest
|
|
330
|
+
# rather than repeating it (REQ-DEBT-02).
|
|
331
|
+
offer = (
|
|
332
|
+
"automatic verification owed"
|
|
333
|
+
if row["verifyState"] == "auto-pending"
|
|
334
|
+
else "verify available"
|
|
335
|
+
)
|
|
336
|
+
print(f" ({offer}: {row['verifyCommand']})")
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
def _print_context(usage: dict) -> None:
|
|
340
|
+
"""Print a one-line human-readable context-usage summary."""
|
|
341
|
+
if not usage.get("available"):
|
|
342
|
+
print(f"context usage: unavailable ({usage.get('reason', 'unknown')})")
|
|
343
|
+
return
|
|
344
|
+
pct = round(usage["pct"] * 100, 1)
|
|
345
|
+
flag = " — over threshold, clean session recommended" if usage["overThreshold"] else ""
|
|
346
|
+
print(
|
|
347
|
+
f"context: {usage['tokens']:,} / {usage['windowTokens']:,} tokens "
|
|
348
|
+
f"(~{pct}%){flag}"
|
|
349
|
+
)
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
def _print_effective_config(
|
|
353
|
+
resolved: dict[str, object], layers: dict[str, object] | None = None
|
|
354
|
+
) -> None:
|
|
355
|
+
"""Print the resolved loopRunner config as an aligned key: value table.
|
|
356
|
+
|
|
357
|
+
Args:
|
|
358
|
+
resolved: The resolved loopRunner object from ``resolve_loop_runner``.
|
|
359
|
+
layers: Optional per-field provenance (env/local/committed/default, #324); when
|
|
360
|
+
given, each row is annotated with the layer that set it.
|
|
361
|
+
"""
|
|
362
|
+
print("Effective loopRunner config:")
|
|
363
|
+
width = max((len(k) for k in resolved), default=0)
|
|
364
|
+
for key in sorted(resolved):
|
|
365
|
+
suffix = f" [{layers[key]}]" if layers and key in layers else ""
|
|
366
|
+
print(f" {key.ljust(width)} : {resolved[key]!r}{suffix}")
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
class _ErrorPrefixParser(argparse.ArgumentParser):
|
|
370
|
+
"""An argparse parser whose failures use this CLI's ``Error: ...`` exit-2 form.
|
|
371
|
+
|
|
372
|
+
``stage-exit`` carries two contracts that argparse cannot satisfy together out
|
|
373
|
+
of the box: its enum flags MUST be registered with typed ``choices`` drawn from
|
|
374
|
+
the shared literal domains, AND any invalid input must print
|
|
375
|
+
``Error: <actionable message>`` to stderr and return exit 2 with no payload and
|
|
376
|
+
no sentinel. Stock argparse leads with ``usage:``, so the reconciliation lives
|
|
377
|
+
here rather than in a hand-rolled second validation pass that would drift from
|
|
378
|
+
the ``choices`` it duplicates.
|
|
379
|
+
|
|
380
|
+
``parse_args`` runs before ``main``'s ``UsageError`` handler, so this exits
|
|
381
|
+
directly instead of raising. ``add_subparsers`` defaults ``parser_class`` to
|
|
382
|
+
``type(self)``, so every subcommand inherits the same form — matching the
|
|
383
|
+
``UsageError`` path they already share.
|
|
384
|
+
"""
|
|
385
|
+
|
|
386
|
+
def error(self, message: str) -> NoReturn: # noqa: D102 - argparse override
|
|
387
|
+
self.exit(2, f"Error: {message}\nTry '{self.prog} --help' for usage.\n")
|
|
388
|
+
|
|
389
|
+
|
|
390
|
+
def main() -> int:
|
|
391
|
+
parser = _ErrorPrefixParser(prog="forge-session.py", description=__doc__)
|
|
392
|
+
sub = parser.add_subparsers(dest="cmd", required=True)
|
|
393
|
+
|
|
394
|
+
p_rank = sub.add_parser("rank-features", help="Rank active features by recency")
|
|
395
|
+
p_rank.add_argument("--specs-dir", default="./specs", help="Specs directory")
|
|
396
|
+
p_rank.add_argument("--config", default="./forge.config.json", help="forge.config.json path")
|
|
397
|
+
p_rank.add_argument("--json", action="store_true", dest="json_output")
|
|
398
|
+
|
|
399
|
+
p_ctx = sub.add_parser("context-usage", help="Report live context-window usage")
|
|
400
|
+
p_ctx.add_argument("--config", default="./forge.config.json", help="forge.config.json path")
|
|
401
|
+
p_ctx.add_argument("--window", type=int, default=None, help="Override context window size")
|
|
402
|
+
p_ctx.add_argument("--threshold", type=float, default=None, help="Override warn fraction (0-1)")
|
|
403
|
+
p_ctx.add_argument("--json", action="store_true", dest="json_output")
|
|
404
|
+
|
|
405
|
+
p_doc = sub.add_parser("doctor", help="Capture pipeline ground truth for debugging")
|
|
406
|
+
p_doc.add_argument("--specs-dir", default="./specs", help="Specs directory")
|
|
407
|
+
p_doc.add_argument("--config", default="./forge.config.json", help="forge.config.json path")
|
|
408
|
+
p_doc.add_argument(
|
|
409
|
+
"--schema", default=None,
|
|
410
|
+
help="Override the bundled forge-config-schema.json (chiefly for tests)",
|
|
411
|
+
)
|
|
412
|
+
p_doc.add_argument(
|
|
413
|
+
"--check", action="append", dest="checks", metavar="ID", choices=DOCTOR_CHECK_IDS,
|
|
414
|
+
help="Run only this check (repeatable); legacy fields are always reported",
|
|
415
|
+
)
|
|
416
|
+
p_doc.add_argument(
|
|
417
|
+
"--verbose", action="store_true",
|
|
418
|
+
help="Also print the ok/na check lines in the human report",
|
|
419
|
+
)
|
|
420
|
+
p_doc.add_argument("--json", action="store_true", dest="json_output")
|
|
421
|
+
|
|
422
|
+
p_disc = sub.add_parser(
|
|
423
|
+
"discover-feature", help="Find a feature's pipeline state across all branches"
|
|
424
|
+
)
|
|
425
|
+
p_disc.add_argument("name", nargs="?", default=None,
|
|
426
|
+
help="Feature name to discover (omit with --all)")
|
|
427
|
+
p_disc.add_argument("--all", action="store_true", dest="discover_all",
|
|
428
|
+
help="Discover every feature across all branches (empty-dashboard)")
|
|
429
|
+
p_disc.add_argument("--specs-dir", default="./specs", help="Specs directory")
|
|
430
|
+
p_disc.add_argument("--json", action="store_true", dest="json_output")
|
|
431
|
+
|
|
432
|
+
p_recon = sub.add_parser(
|
|
433
|
+
"reconcile-branch",
|
|
434
|
+
help="Decide whether a feature's recorded branch should adopt the current branch",
|
|
435
|
+
)
|
|
436
|
+
p_recon.add_argument("--feature", required=True, help="Feature name")
|
|
437
|
+
p_recon.add_argument("--specs-dir", default="./specs", help="Specs directory")
|
|
438
|
+
p_recon.add_argument("--config", default="./forge.config.json", help="forge.config.json path")
|
|
439
|
+
p_recon.add_argument("--epic", default=None, help="Epic name for a nested member")
|
|
440
|
+
p_recon.add_argument("--json", action="store_true", dest="json_output")
|
|
441
|
+
|
|
442
|
+
p_base = sub.add_parser(
|
|
443
|
+
"check-epic-base",
|
|
444
|
+
help="Verify HEAD contains the epic manifest for a resolved nested member",
|
|
445
|
+
)
|
|
446
|
+
p_base.add_argument("--feature", required=True, help="Feature name")
|
|
447
|
+
p_base.add_argument("--specs-dir", default="./specs", help="Specs directory")
|
|
448
|
+
p_base.add_argument("--config", default="./forge.config.json", help="forge.config.json path")
|
|
449
|
+
p_base.add_argument("--epic", default=None, help="Epic name for a nested member")
|
|
450
|
+
p_base.add_argument("--json", action="store_true", dest="json_output")
|
|
451
|
+
|
|
452
|
+
p_exit = sub.add_parser(
|
|
453
|
+
"stage-exit", help="Emit the Scripted Stage Exit directives + NEXT-STEPS block"
|
|
454
|
+
)
|
|
455
|
+
p_exit.add_argument("--feature", required=True,
|
|
456
|
+
help="Feature name (the epic name for forge-0-epic)")
|
|
457
|
+
p_exit.add_argument("--stage", required=True, choices=EXIT_STAGES,
|
|
458
|
+
help="The just-completed stage (or branch skill)")
|
|
459
|
+
p_exit.add_argument("--served-stage", default=None, dest="served_stage",
|
|
460
|
+
choices=_EXIT_PRODUCTION_STAGES,
|
|
461
|
+
help="Production stage a verify/fix diversion served")
|
|
462
|
+
p_exit.add_argument("--verify-mode", default=None, dest="verify_mode",
|
|
463
|
+
choices=tuple(VERIFY_MODE_TO_STAGE),
|
|
464
|
+
help="Verify mode; maps to --served-stage when unique")
|
|
465
|
+
# No argparse `choices`: the accepted outcome domain differs per stage, which
|
|
466
|
+
# argparse cannot express. `stage_exit` validates it against EXIT_OUTCOMES.
|
|
467
|
+
p_exit.add_argument("--outcome", default=None,
|
|
468
|
+
help="Stage-specific outcome (loop/docs/verify/fix only)")
|
|
469
|
+
p_exit.add_argument(
|
|
470
|
+
"--cause", default=None, dest="cause", choices=("dependency-starvation",),
|
|
471
|
+
help="Pending-attribution cause; valid only with "
|
|
472
|
+
"--stage forge-5-loop --outcome partial",
|
|
473
|
+
)
|
|
474
|
+
p_exit.add_argument("--owner", default=None, choices=get_args(ExitOwner),
|
|
475
|
+
help="Branch terminal ownership (forge-verify/forge-fix only)")
|
|
476
|
+
p_exit.add_argument("--verify-capability", default="manual",
|
|
477
|
+
dest="verify_capability", choices=get_args(VerifyCapability),
|
|
478
|
+
help="interactive only with BOTH a question mechanism and "
|
|
479
|
+
"permitted clean-room verifier dispatch")
|
|
480
|
+
p_exit.add_argument("--specs-dir", default="./specs", help="Specs directory")
|
|
481
|
+
p_exit.add_argument("--config", default="./forge.config.json", help="forge.config.json path")
|
|
482
|
+
p_exit.add_argument("--epic", default=None, help="Epic name for a nested member")
|
|
483
|
+
p_exit.add_argument("--next-feature", default=None, dest="next_feature",
|
|
484
|
+
help="First actionable feature (epic handoff next-command arg)")
|
|
485
|
+
p_exit.add_argument("--host", default="claude", choices=EXIT_HOSTS,
|
|
486
|
+
help="Host wording for the NEXT-STEPS block")
|
|
487
|
+
p_exit.add_argument("--json", action="store_true", dest="json_output")
|
|
488
|
+
|
|
489
|
+
p_sel = sub.add_parser(
|
|
490
|
+
"select-outcome",
|
|
491
|
+
help="Derive the deterministic stage-exit --outcome for a verify/fix run",
|
|
492
|
+
)
|
|
493
|
+
p_sel.add_argument("--feature", required=True, help="Feature name")
|
|
494
|
+
p_sel.add_argument("--served-stage", required=True, dest="served_stage",
|
|
495
|
+
choices=tuple(VERIFY_TOKEN_BY_STAGE),
|
|
496
|
+
help="Production stage the verify/fix run served")
|
|
497
|
+
p_sel.add_argument("--skill", required=True, choices=("verify", "fix"),
|
|
498
|
+
help="Which branch skill is choosing its exit outcome")
|
|
499
|
+
p_sel.add_argument("--specs-dir", default="./specs", help="Specs directory")
|
|
500
|
+
p_sel.add_argument("--epic", default=None, help="Epic name for a nested member")
|
|
501
|
+
# Runtime signals for the outcomes disk cannot record (see references/select-outcome.md).
|
|
502
|
+
p_sel.add_argument("--op-failure", action="store_true", dest="op_failure",
|
|
503
|
+
help="a dispatch/step/validation/commit/state-write failed → failed")
|
|
504
|
+
p_sel.add_argument("--user-deferred", action="store_true", dest="user_deferred",
|
|
505
|
+
help="fix only: user explicitly deferred the fix/re-verify → deferred")
|
|
506
|
+
p_sel.add_argument("--decisions-open", action="store_true", dest="decisions_open",
|
|
507
|
+
help="fix only: unresolved user decisions block fixes → decisions")
|
|
508
|
+
p_sel.add_argument("--json", action="store_true", dest="json_output")
|
|
509
|
+
|
|
510
|
+
p_vst = sub.add_parser(
|
|
511
|
+
"verify-state",
|
|
512
|
+
help="Classify a served stage's verification into one VerifyStateCase",
|
|
513
|
+
)
|
|
514
|
+
p_vst.add_argument("--feature", required=True, help="Feature name")
|
|
515
|
+
p_vst.add_argument("--for-stage", required=True, dest="for_stage",
|
|
516
|
+
choices=tuple(VERIFY_TOKEN_BY_STAGE),
|
|
517
|
+
help="Production stage whose forge-verify-* entry to classify")
|
|
518
|
+
p_vst.add_argument("--specs-dir", default="./specs", help="Specs directory")
|
|
519
|
+
p_vst.add_argument("--epic", default=None, help="Epic name for a nested member")
|
|
520
|
+
p_vst.add_argument("--json", action="store_true", dest="json_output")
|
|
521
|
+
|
|
522
|
+
p_eff = sub.add_parser(
|
|
523
|
+
"effective-config",
|
|
524
|
+
help="Resolve the loopRunner config from schema defaults + user overrides",
|
|
525
|
+
)
|
|
526
|
+
p_eff.add_argument("--config", default="./forge.config.json", help="forge.config.json path")
|
|
527
|
+
p_eff.add_argument(
|
|
528
|
+
"--schema", default=None,
|
|
529
|
+
help="forge-config-schema.json path (default: bundled references/ copy)",
|
|
530
|
+
)
|
|
531
|
+
p_eff.add_argument("--json", action="store_true", dest="json_output")
|
|
532
|
+
|
|
533
|
+
p_enter = sub.add_parser(
|
|
534
|
+
"state-enter", help="Stamp a stage as in-progress (Entry Stamp)"
|
|
535
|
+
)
|
|
536
|
+
p_enter.add_argument("--feature", required=True, help="Feature name")
|
|
537
|
+
p_enter.add_argument("--stage", required=True, choices=STATE_VERB_STAGES,
|
|
538
|
+
help="The stage being entered")
|
|
539
|
+
p_enter.add_argument("--specs-dir", default="./specs", help="Specs directory")
|
|
540
|
+
p_enter.add_argument("--epic", default=None, help="Epic name for a nested member")
|
|
541
|
+
p_enter.add_argument("--json", action="store_true", dest="json_output")
|
|
542
|
+
|
|
543
|
+
p_art = sub.add_parser(
|
|
544
|
+
"state-artifact", help="Append artifact paths to a stage (de-duplicating)"
|
|
545
|
+
)
|
|
546
|
+
p_art.add_argument("--feature", required=True, help="Feature name")
|
|
547
|
+
p_art.add_argument("--stage", required=True, choices=STATE_VERB_STAGES,
|
|
548
|
+
help="The stage producing the artifact")
|
|
549
|
+
p_art.add_argument("--path", required=True, action="append", dest="paths",
|
|
550
|
+
metavar="PATH",
|
|
551
|
+
help="Artifact path relative to the feature dir (repeatable)")
|
|
552
|
+
p_art.add_argument("--specs-dir", default="./specs", help="Specs directory")
|
|
553
|
+
p_art.add_argument("--epic", default=None, help="Epic name for a nested member")
|
|
554
|
+
p_art.add_argument("--json", action="store_true", dest="json_output")
|
|
555
|
+
|
|
556
|
+
p_comp = sub.add_parser(
|
|
557
|
+
"state-complete", help="Mark a stage complete; bump version; cascade staleness"
|
|
558
|
+
)
|
|
559
|
+
p_comp.add_argument("--feature", required=True, help="Feature name")
|
|
560
|
+
p_comp.add_argument("--stage", required=True, choices=STATE_VERB_STAGES,
|
|
561
|
+
help="The stage being completed")
|
|
562
|
+
p_comp.add_argument("--version", type=int, required=True,
|
|
563
|
+
help="This stage's new version (integer)")
|
|
564
|
+
p_comp.add_argument("--based-on", action="append", default=[], dest="based_on",
|
|
565
|
+
metavar="STAGE=N",
|
|
566
|
+
help="Upstream version this artifact was built on (repeatable)")
|
|
567
|
+
p_comp.add_argument("--artifact", action="append", default=[], dest="artifacts",
|
|
568
|
+
metavar="PATH",
|
|
569
|
+
help="Artifact path produced by this stage (repeatable)")
|
|
570
|
+
p_comp.add_argument("--commit-hash", default=None, dest="commit_hash",
|
|
571
|
+
help="Commit 2 follow-up: record the artifact commit's hash")
|
|
572
|
+
p_comp.add_argument("--status", default=None,
|
|
573
|
+
choices=("complete", "in-progress"),
|
|
574
|
+
help="Terminal status to record (default: complete). "
|
|
575
|
+
"Use in-progress for a partial forge-5-loop run -- the "
|
|
576
|
+
"stage still records completedAt/version/basedOnVersions/"
|
|
577
|
+
"artifacts; only the status differs.")
|
|
578
|
+
p_comp.add_argument("--resumable", action="store_true",
|
|
579
|
+
help="Failed-Commit-1 revert (L245): record ONLY status="
|
|
580
|
+
"in-progress, leaving completedAt/version/basedOnVersions/"
|
|
581
|
+
"artifacts/commitHash untouched and firing no cascade. "
|
|
582
|
+
"Implies --status in-progress.")
|
|
583
|
+
p_comp.add_argument("--preserve-commit-hash", action="store_true",
|
|
584
|
+
dest="preserve_commit_hash",
|
|
585
|
+
help="Do not reset commitHash to null on completion "
|
|
586
|
+
"(the Git Commit Protocol's 'Nothing to commit' branch)")
|
|
587
|
+
p_comp.add_argument("--specs-dir", default="./specs", help="Specs directory")
|
|
588
|
+
p_comp.add_argument("--epic", default=None, help="Epic name for a nested member")
|
|
589
|
+
p_comp.add_argument("--json", action="store_true", dest="json_output")
|
|
590
|
+
|
|
591
|
+
p_skip = sub.add_parser(
|
|
592
|
+
"state-skip", help="Record forge-6-docs as deliberately skipped (#197)"
|
|
593
|
+
)
|
|
594
|
+
p_skip.add_argument("--feature", required=True, help="Feature name")
|
|
595
|
+
p_skip.add_argument("--stage", required=True, choices=("forge-6-docs",),
|
|
596
|
+
help="The stage being skipped (only forge-6-docs is skippable)")
|
|
597
|
+
p_skip.add_argument("--specs-dir", default="./specs", help="Specs directory")
|
|
598
|
+
p_skip.add_argument("--epic", default=None, help="Epic name for a nested member")
|
|
599
|
+
p_skip.add_argument("--json", action="store_true", dest="json_output")
|
|
600
|
+
|
|
601
|
+
p_br = sub.add_parser("state-branch", help="Set the top-level branch field")
|
|
602
|
+
p_br.add_argument("--feature", required=True, help="Feature name")
|
|
603
|
+
p_br.add_argument("--branch", required=True, help="Branch name to record")
|
|
604
|
+
p_br.add_argument("--specs-dir", default="./specs", help="Specs directory")
|
|
605
|
+
p_br.add_argument("--epic", default=None, help="Epic name for a nested member")
|
|
606
|
+
p_br.add_argument("--json", action="store_true", dest="json_output")
|
|
607
|
+
|
|
608
|
+
p_note = sub.add_parser("state-note", help="Set the top-level notes field")
|
|
609
|
+
p_note.add_argument("--feature", required=True, help="Feature name")
|
|
610
|
+
p_note.add_argument("--note", required=True, help="Note text to persist")
|
|
611
|
+
p_note.add_argument("--specs-dir", default="./specs", help="Specs directory")
|
|
612
|
+
p_note.add_argument("--epic", default=None, help="Epic name for a nested member")
|
|
613
|
+
p_note.add_argument("--json", action="store_true", dest="json_output")
|
|
614
|
+
|
|
615
|
+
p_dec = sub.add_parser(
|
|
616
|
+
"state-decision", help="Append a deferred decision (status: open)"
|
|
617
|
+
)
|
|
618
|
+
p_dec.add_argument("--feature", required=True, help="Feature name")
|
|
619
|
+
p_dec.add_argument("--question", required=True,
|
|
620
|
+
help="The deferred decision, phrased for the target stage")
|
|
621
|
+
p_dec.add_argument("--raised-by", required=True, dest="raised_by",
|
|
622
|
+
choices=DECISION_RAISED_BY,
|
|
623
|
+
help="The stage deferring the decision")
|
|
624
|
+
p_dec.add_argument("--rationale", default=None, help="Why it is deferred (optional)")
|
|
625
|
+
p_dec.add_argument("--target-stage", default=None, dest="target_stage",
|
|
626
|
+
choices=DECISION_TARGET_STAGES,
|
|
627
|
+
help="The stage that should resolve it (optional)")
|
|
628
|
+
p_dec.add_argument("--specs-dir", default="./specs", help="Specs directory")
|
|
629
|
+
p_dec.add_argument("--epic", default=None, help="Epic name for a nested member")
|
|
630
|
+
p_dec.add_argument("--json", action="store_true", dest="json_output")
|
|
631
|
+
|
|
632
|
+
p_ecr = sub.add_parser(
|
|
633
|
+
"state-ecr", help="Append an epic change request (status: open)"
|
|
634
|
+
)
|
|
635
|
+
p_ecr.add_argument("--feature", required=True, help="Feature name")
|
|
636
|
+
p_ecr.add_argument("--kind", required=True, choices=ECR_KINDS,
|
|
637
|
+
help="The decomposition change kind")
|
|
638
|
+
p_ecr.add_argument("--target", required=True,
|
|
639
|
+
help="The sibling feature to add, or the feature/boundary affected")
|
|
640
|
+
p_ecr.add_argument("--rationale", required=True, help="Why the epic must change")
|
|
641
|
+
p_ecr.add_argument("--raised-by", required=True, dest="raised_by",
|
|
642
|
+
choices=ECR_RAISED_BY,
|
|
643
|
+
help="The stage that detected the epic-level concern")
|
|
644
|
+
p_ecr.add_argument("--blocks-current", required=True, dest="blocks_current",
|
|
645
|
+
metavar="true|false",
|
|
646
|
+
help="true → pause-now (reconcile before proceeding); "
|
|
647
|
+
"false → finish-then-edit")
|
|
648
|
+
p_ecr.add_argument("--specs-dir", default="./specs", help="Specs directory")
|
|
649
|
+
p_ecr.add_argument("--epic", default=None, help="Epic name for a nested member")
|
|
650
|
+
p_ecr.add_argument("--json", action="store_true", dest="json_output")
|
|
651
|
+
|
|
652
|
+
p_ver = sub.add_parser(
|
|
653
|
+
"state-verify", help="Write one forge-verify-* transition (result or provenance)"
|
|
654
|
+
)
|
|
655
|
+
p_ver.add_argument("--feature", required=True,
|
|
656
|
+
help="Feature name (the EPIC name for --stage forge-0-epic)")
|
|
657
|
+
p_ver.add_argument("--stage", required=True, choices=VERIFY_STAGES,
|
|
658
|
+
help="The production stage this verify entry serves "
|
|
659
|
+
"(forge-6-docs has no verification token)")
|
|
660
|
+
p_ver.add_argument("--status", default=None, choices=VERIFY_RESULT_STATUSES,
|
|
661
|
+
help="Result mode: the transition to record "
|
|
662
|
+
"(mutually exclusive with --commit-hash)")
|
|
663
|
+
p_ver.add_argument("--findings-file", default=None, dest="findings_file",
|
|
664
|
+
metavar="PATH",
|
|
665
|
+
help="Findings document, relative to and contained by the "
|
|
666
|
+
"feature directory (required by findings-reported)")
|
|
667
|
+
p_ver.add_argument("--findings-count", type=int, default=None,
|
|
668
|
+
dest="findings_count", metavar="N",
|
|
669
|
+
help="Number of findings in --findings-file (0 is meaningful)")
|
|
670
|
+
p_ver.add_argument("--verified-stage-version", type=int, default=None,
|
|
671
|
+
dest="verified_stage_version", metavar="N",
|
|
672
|
+
help="The served stage's current version, for the freshness "
|
|
673
|
+
"ledger (rejected by findings-applied)")
|
|
674
|
+
p_ver.add_argument("--commit-hash", default=None, dest="commit_hash",
|
|
675
|
+
help="Commit-2 provenance mode: the full 40-hex Commit-1 hash")
|
|
676
|
+
p_ver.add_argument("--specs-dir", default="./specs", help="Specs directory")
|
|
677
|
+
p_ver.add_argument("--epic", default=None, help="Epic name for a nested member")
|
|
678
|
+
p_ver.add_argument("--json", action="store_true", dest="json_output")
|
|
679
|
+
|
|
680
|
+
p_drec = sub.add_parser(
|
|
681
|
+
"decision-record", help="Append a needs-human decision entry (append-only)"
|
|
682
|
+
)
|
|
683
|
+
p_drec.add_argument("--backlog-dir", required=True, dest="backlog_dir",
|
|
684
|
+
help="Resolved backlog directory (e.g. specs/loop-recovery)")
|
|
685
|
+
p_drec.add_argument("--item", required=True, action="append", dest="item_ids",
|
|
686
|
+
metavar="ID", help="Backlog item id (repeatable — one entry per id)")
|
|
687
|
+
p_drec.add_argument("--question", required=True, help="The needs-human question text")
|
|
688
|
+
_ans = p_drec.add_mutually_exclusive_group(required=True)
|
|
689
|
+
_ans.add_argument("--answer", default=None, help="The operator's answer")
|
|
690
|
+
_ans.add_argument("--deferred", action="store_true",
|
|
691
|
+
help="Record a deferral / cancel-early (answer: null)")
|
|
692
|
+
p_drec.add_argument("--cluster", default=None, dest="cluster_id", metavar="CID",
|
|
693
|
+
help="Shared clusterId for one consolidated decision (REQ-CLU-04)")
|
|
694
|
+
p_drec.add_argument("--actor", default=None,
|
|
695
|
+
help="Session/actor label for recordedBy (default forge-5-loop@<host>)")
|
|
696
|
+
p_drec.add_argument("--state-dir", default=None, dest="state_dir",
|
|
697
|
+
help="State-dir name (default: effective loopRunner.stateDir)")
|
|
698
|
+
p_drec.add_argument("--config", default="./forge.config.json",
|
|
699
|
+
help="forge.config.json path")
|
|
700
|
+
p_drec.add_argument("--json", action="store_true", dest="json_output")
|
|
701
|
+
|
|
702
|
+
p_dlist = sub.add_parser(
|
|
703
|
+
"decision-list", help="Read the decision record (or the unapplied set)"
|
|
704
|
+
)
|
|
705
|
+
p_dlist.add_argument("--backlog-dir", required=True, dest="backlog_dir",
|
|
706
|
+
help="Resolved backlog directory")
|
|
707
|
+
p_dlist.add_argument("--unapplied", action="store_true",
|
|
708
|
+
help="Return only the latest-unapplied-per-item set (REQ-DEC-05)")
|
|
709
|
+
p_dlist.add_argument("--state-dir", default=None, dest="state_dir",
|
|
710
|
+
help="State-dir name (default: effective loopRunner.stateDir)")
|
|
711
|
+
p_dlist.add_argument("--config", default="./forge.config.json",
|
|
712
|
+
help="forge.config.json path")
|
|
713
|
+
p_dlist.add_argument("--json", action="store_true", dest="json_output")
|
|
714
|
+
|
|
715
|
+
p_dapply = sub.add_parser(
|
|
716
|
+
"decision-apply", help="Mark the latest decision for an item applied"
|
|
717
|
+
)
|
|
718
|
+
p_dapply.add_argument("--backlog-dir", required=True, dest="backlog_dir",
|
|
719
|
+
help="Resolved backlog directory")
|
|
720
|
+
p_dapply.add_argument("--item", required=True, dest="item_id", metavar="ID",
|
|
721
|
+
help="Backlog item whose latest decision to stamp applied")
|
|
722
|
+
p_dapply.add_argument("--actor", default=None,
|
|
723
|
+
help="Session/actor label for appliedBy (default forge-5-loop@<host>)")
|
|
724
|
+
p_dapply.add_argument("--state-dir", default=None, dest="state_dir",
|
|
725
|
+
help="State-dir name (default: effective loopRunner.stateDir)")
|
|
726
|
+
p_dapply.add_argument("--config", default="./forge.config.json",
|
|
727
|
+
help="forge.config.json path")
|
|
728
|
+
p_dapply.add_argument("--json", action="store_true", dest="json_output")
|
|
729
|
+
|
|
730
|
+
p_topo = sub.add_parser(
|
|
731
|
+
"backlog-topology",
|
|
732
|
+
help="Dependency-topology metrics + advisory warnings over a runner item array",
|
|
733
|
+
)
|
|
734
|
+
topo_src = p_topo.add_mutually_exclusive_group(required=True)
|
|
735
|
+
topo_src.add_argument(
|
|
736
|
+
"--items-json", help="Path to the loopRunner listCommand JSON output"
|
|
737
|
+
)
|
|
738
|
+
topo_src.add_argument(
|
|
739
|
+
"--items-stdin", action="store_true",
|
|
740
|
+
help="Read the listCommand JSON from stdin",
|
|
741
|
+
)
|
|
742
|
+
p_topo.add_argument(
|
|
743
|
+
"--cluster", action="store_true", dest="with_clusters",
|
|
744
|
+
help="Append blocked-item clusters for consolidated prompts",
|
|
745
|
+
)
|
|
746
|
+
p_topo.add_argument("--json", action="store_true", dest="json_output")
|
|
747
|
+
|
|
748
|
+
args = parser.parse_args()
|
|
749
|
+
|
|
750
|
+
try:
|
|
751
|
+
if args.cmd == "rank-features":
|
|
752
|
+
specs_dir = Path(args.specs_dir)
|
|
753
|
+
config = load_effective_config(Path(args.config))
|
|
754
|
+
rows = build_rows(specs_dir, config)
|
|
755
|
+
counts = _counts(specs_dir)
|
|
756
|
+
invalid_keys = invalid_auto_verify_keys(config)
|
|
757
|
+
if args.json_output:
|
|
758
|
+
payload = {"active": rows, "counts": counts}
|
|
759
|
+
if invalid_keys:
|
|
760
|
+
payload["invalidAutoVerifyKeys"] = invalid_keys
|
|
761
|
+
print(json.dumps(payload, indent=2, ensure_ascii=False))
|
|
762
|
+
else:
|
|
763
|
+
_print_rank_table(rows, counts)
|
|
764
|
+
if invalid_keys:
|
|
765
|
+
print(
|
|
766
|
+
" ! invalid autoVerifyStages keys (ignored): "
|
|
767
|
+
+ ", ".join(invalid_keys)
|
|
768
|
+
)
|
|
769
|
+
return 0
|
|
770
|
+
|
|
771
|
+
if args.cmd == "context-usage":
|
|
772
|
+
usage = context_usage(Path(args.config), args.window, args.threshold)
|
|
773
|
+
if args.json_output:
|
|
774
|
+
print(json.dumps(usage, indent=2, ensure_ascii=False))
|
|
775
|
+
else:
|
|
776
|
+
_print_context(usage)
|
|
777
|
+
return 0
|
|
778
|
+
|
|
779
|
+
if args.cmd == "doctor":
|
|
780
|
+
# Check details carry non-ASCII (em dash, ellipsis); a terminal whose
|
|
781
|
+
# encoding cannot represent them must not turn the diagnostic into a
|
|
782
|
+
# traceback (INV-3). Only the doctor path reconfigures.
|
|
783
|
+
reconfigure = getattr(sys.stdout, "reconfigure", None)
|
|
784
|
+
if reconfigure is not None:
|
|
785
|
+
try:
|
|
786
|
+
reconfigure(errors="backslashreplace")
|
|
787
|
+
except (ValueError, OSError):
|
|
788
|
+
pass
|
|
789
|
+
report = doctor_report(
|
|
790
|
+
Path(args.specs_dir),
|
|
791
|
+
Path(args.config),
|
|
792
|
+
schema_path=Path(args.schema) if args.schema else None,
|
|
793
|
+
only=frozenset(args.checks) if args.checks else None,
|
|
794
|
+
)
|
|
795
|
+
if args.json_output:
|
|
796
|
+
print(json.dumps(report, indent=2, ensure_ascii=False))
|
|
797
|
+
else:
|
|
798
|
+
_print_doctor(report, verbose=args.verbose or bool(args.checks))
|
|
799
|
+
return 0
|
|
800
|
+
|
|
801
|
+
if args.cmd == "discover-feature":
|
|
802
|
+
if args.discover_all:
|
|
803
|
+
payload = discover_all(args.specs_dir)
|
|
804
|
+
printer = _print_discover_all
|
|
805
|
+
elif args.name:
|
|
806
|
+
payload = discover_feature(args.name, args.specs_dir)
|
|
807
|
+
printer = _print_discover
|
|
808
|
+
else:
|
|
809
|
+
parser.error("discover-feature requires a NAME or --all")
|
|
810
|
+
if args.json_output:
|
|
811
|
+
print(json.dumps(payload, indent=2, ensure_ascii=False))
|
|
812
|
+
else:
|
|
813
|
+
printer(payload)
|
|
814
|
+
return 0
|
|
815
|
+
|
|
816
|
+
if args.cmd == "reconcile-branch":
|
|
817
|
+
payload = reconcile_branch(
|
|
818
|
+
args.feature, Path(args.specs_dir), Path(args.config), args.epic
|
|
819
|
+
)
|
|
820
|
+
if args.json_output:
|
|
821
|
+
print(json.dumps(payload, indent=2, ensure_ascii=False))
|
|
822
|
+
else:
|
|
823
|
+
_print_reconcile(payload)
|
|
824
|
+
return 0
|
|
825
|
+
|
|
826
|
+
if args.cmd == "check-epic-base":
|
|
827
|
+
payload = check_epic_base(
|
|
828
|
+
args.feature, Path(args.specs_dir), Path(args.config), args.epic
|
|
829
|
+
)
|
|
830
|
+
if args.json_output:
|
|
831
|
+
print(json.dumps(payload, indent=2, ensure_ascii=False))
|
|
832
|
+
else:
|
|
833
|
+
_print_check_epic_base(payload)
|
|
834
|
+
return 0
|
|
835
|
+
|
|
836
|
+
if args.cmd == "stage-exit":
|
|
837
|
+
payload = stage_exit(
|
|
838
|
+
args.feature,
|
|
839
|
+
args.stage,
|
|
840
|
+
Path(args.specs_dir),
|
|
841
|
+
Path(args.config),
|
|
842
|
+
args.epic,
|
|
843
|
+
args.host,
|
|
844
|
+
args.next_feature,
|
|
845
|
+
args.served_stage,
|
|
846
|
+
args.verify_mode,
|
|
847
|
+
args.outcome,
|
|
848
|
+
args.owner,
|
|
849
|
+
args.verify_capability,
|
|
850
|
+
args.cause,
|
|
851
|
+
)
|
|
852
|
+
if args.json_output:
|
|
853
|
+
print(json.dumps(payload, indent=2, ensure_ascii=False))
|
|
854
|
+
else:
|
|
855
|
+
_print_stage_exit(payload)
|
|
856
|
+
return 0
|
|
857
|
+
|
|
858
|
+
if args.cmd == "select-outcome":
|
|
859
|
+
payload = select_outcome(
|
|
860
|
+
args.feature,
|
|
861
|
+
args.served_stage,
|
|
862
|
+
args.skill,
|
|
863
|
+
Path(args.specs_dir),
|
|
864
|
+
args.epic,
|
|
865
|
+
op_failure=args.op_failure,
|
|
866
|
+
user_deferred=args.user_deferred,
|
|
867
|
+
decisions_open=args.decisions_open,
|
|
868
|
+
)
|
|
869
|
+
if args.json_output:
|
|
870
|
+
print(json.dumps(payload, indent=2, ensure_ascii=False))
|
|
871
|
+
else:
|
|
872
|
+
print(f"{payload['outcome']}: {payload['reason']}")
|
|
873
|
+
for line in payload["evidence"]:
|
|
874
|
+
print(f" - {line}")
|
|
875
|
+
return 0
|
|
876
|
+
|
|
877
|
+
if args.cmd == "verify-state":
|
|
878
|
+
payload = verify_state_for_stage(
|
|
879
|
+
args.feature,
|
|
880
|
+
args.for_stage,
|
|
881
|
+
Path(args.specs_dir),
|
|
882
|
+
args.epic,
|
|
883
|
+
)
|
|
884
|
+
if args.json_output:
|
|
885
|
+
print(json.dumps(payload, indent=2, ensure_ascii=False))
|
|
886
|
+
else:
|
|
887
|
+
flags = []
|
|
888
|
+
if payload["verified"]:
|
|
889
|
+
flags.append("verified")
|
|
890
|
+
if payload["stale"]:
|
|
891
|
+
flags.append("stale")
|
|
892
|
+
suffix = f" [{', '.join(flags)}]" if flags else ""
|
|
893
|
+
print(f"{payload['case']}{suffix}: {payload['message']}")
|
|
894
|
+
if payload["nextCommand"]:
|
|
895
|
+
print(f" next: {payload['nextCommand']}")
|
|
896
|
+
return 0
|
|
897
|
+
|
|
898
|
+
if args.cmd == "effective-config":
|
|
899
|
+
schema_path = Path(args.schema) if args.schema else _default_schema_path()
|
|
900
|
+
layered = resolve_loop_runner_layers(Path(args.config), schema_path)
|
|
901
|
+
resolved = {field: info["value"] for field, info in layered.items()}
|
|
902
|
+
layers = {field: info["layer"] for field, info in layered.items()}
|
|
903
|
+
if args.json_output:
|
|
904
|
+
# --json shape is frozen (spec 04): the flat resolved block, no provenance.
|
|
905
|
+
# The per-key layer lives in the human view here and in `doctor --json` (#324).
|
|
906
|
+
print(json.dumps(resolved, indent=2, ensure_ascii=False))
|
|
907
|
+
else:
|
|
908
|
+
_print_effective_config(resolved, layers)
|
|
909
|
+
return 0
|
|
910
|
+
|
|
911
|
+
if args.cmd == "state-enter":
|
|
912
|
+
payload = cmd_state_enter(
|
|
913
|
+
args.feature, args.stage, Path(args.specs_dir), args.epic
|
|
914
|
+
)
|
|
915
|
+
_emit(payload, args.json_output, _print_state_enter)
|
|
916
|
+
return 0
|
|
917
|
+
|
|
918
|
+
if args.cmd == "state-artifact":
|
|
919
|
+
payload = cmd_state_artifact(
|
|
920
|
+
args.feature, args.stage, args.paths, Path(args.specs_dir), args.epic
|
|
921
|
+
)
|
|
922
|
+
_emit(
|
|
923
|
+
payload,
|
|
924
|
+
args.json_output,
|
|
925
|
+
lambda state: _print_state_artifact(state, args.stage, args.paths),
|
|
926
|
+
)
|
|
927
|
+
return 0
|
|
928
|
+
|
|
929
|
+
if args.cmd == "state-complete":
|
|
930
|
+
payload = cmd_state_complete(
|
|
931
|
+
args.feature,
|
|
932
|
+
args.stage,
|
|
933
|
+
args.version,
|
|
934
|
+
_parse_based_on(args.based_on),
|
|
935
|
+
args.artifacts,
|
|
936
|
+
args.commit_hash,
|
|
937
|
+
Path(args.specs_dir),
|
|
938
|
+
args.epic,
|
|
939
|
+
status=args.status,
|
|
940
|
+
preserve_commit_hash=args.preserve_commit_hash,
|
|
941
|
+
resumable=args.resumable,
|
|
942
|
+
)
|
|
943
|
+
_emit(
|
|
944
|
+
payload,
|
|
945
|
+
args.json_output,
|
|
946
|
+
lambda state: _print_state_complete(
|
|
947
|
+
state, args.stage, args.commit_hash, args.resumable
|
|
948
|
+
),
|
|
949
|
+
)
|
|
950
|
+
return 0
|
|
951
|
+
|
|
952
|
+
if args.cmd == "state-skip":
|
|
953
|
+
payload = cmd_state_skip(
|
|
954
|
+
args.feature, args.stage, Path(args.specs_dir), args.epic
|
|
955
|
+
)
|
|
956
|
+
_emit(
|
|
957
|
+
payload,
|
|
958
|
+
args.json_output,
|
|
959
|
+
lambda state: _print_state_skip(state, args.stage),
|
|
960
|
+
)
|
|
961
|
+
return 0
|
|
962
|
+
|
|
963
|
+
if args.cmd == "state-branch":
|
|
964
|
+
payload = cmd_state_branch(
|
|
965
|
+
args.feature, args.branch, Path(args.specs_dir), args.epic
|
|
966
|
+
)
|
|
967
|
+
_emit(payload, args.json_output, _print_state_branch)
|
|
968
|
+
return 0
|
|
969
|
+
|
|
970
|
+
if args.cmd == "state-note":
|
|
971
|
+
payload = cmd_state_note(
|
|
972
|
+
args.feature, args.note, Path(args.specs_dir), args.epic
|
|
973
|
+
)
|
|
974
|
+
_emit(payload, args.json_output, _print_state_note)
|
|
975
|
+
return 0
|
|
976
|
+
|
|
977
|
+
if args.cmd == "state-decision":
|
|
978
|
+
payload = cmd_state_decision(
|
|
979
|
+
args.feature,
|
|
980
|
+
args.question,
|
|
981
|
+
args.raised_by,
|
|
982
|
+
args.rationale,
|
|
983
|
+
args.target_stage,
|
|
984
|
+
Path(args.specs_dir),
|
|
985
|
+
args.epic,
|
|
986
|
+
)
|
|
987
|
+
_emit(payload, args.json_output, _print_state_decision)
|
|
988
|
+
return 0
|
|
989
|
+
|
|
990
|
+
if args.cmd == "state-ecr":
|
|
991
|
+
payload = cmd_state_ecr(
|
|
992
|
+
args.feature,
|
|
993
|
+
args.kind,
|
|
994
|
+
args.target,
|
|
995
|
+
args.rationale,
|
|
996
|
+
args.raised_by,
|
|
997
|
+
_parse_bool(args.blocks_current, "--blocks-current"),
|
|
998
|
+
Path(args.specs_dir),
|
|
999
|
+
args.epic,
|
|
1000
|
+
)
|
|
1001
|
+
_emit(payload, args.json_output, _print_state_ecr)
|
|
1002
|
+
return 0
|
|
1003
|
+
|
|
1004
|
+
if args.cmd == "state-verify":
|
|
1005
|
+
payload = cmd_state_verify(
|
|
1006
|
+
args.feature,
|
|
1007
|
+
args.stage,
|
|
1008
|
+
Path(args.specs_dir),
|
|
1009
|
+
args.epic,
|
|
1010
|
+
status=args.status,
|
|
1011
|
+
findings_file=args.findings_file,
|
|
1012
|
+
findings_count=args.findings_count,
|
|
1013
|
+
verified_stage_version=args.verified_stage_version,
|
|
1014
|
+
commit_hash=args.commit_hash,
|
|
1015
|
+
)
|
|
1016
|
+
_emit(
|
|
1017
|
+
payload,
|
|
1018
|
+
args.json_output,
|
|
1019
|
+
lambda result: _print_state_verify(result, args.commit_hash),
|
|
1020
|
+
)
|
|
1021
|
+
return 0
|
|
1022
|
+
|
|
1023
|
+
if args.cmd == "decision-record":
|
|
1024
|
+
payload = cmd_decision_record(
|
|
1025
|
+
Path(args.backlog_dir),
|
|
1026
|
+
args.item_ids,
|
|
1027
|
+
args.question,
|
|
1028
|
+
args.answer,
|
|
1029
|
+
args.deferred,
|
|
1030
|
+
args.cluster_id,
|
|
1031
|
+
args.actor or _default_actor(),
|
|
1032
|
+
args.state_dir,
|
|
1033
|
+
Path(args.config),
|
|
1034
|
+
_default_schema_path(),
|
|
1035
|
+
)
|
|
1036
|
+
_emit(payload, args.json_output, _print_decision_record)
|
|
1037
|
+
return 0
|
|
1038
|
+
|
|
1039
|
+
if args.cmd == "decision-list":
|
|
1040
|
+
payload = cmd_decision_list(
|
|
1041
|
+
Path(args.backlog_dir), args.unapplied, args.state_dir,
|
|
1042
|
+
Path(args.config), _default_schema_path(),
|
|
1043
|
+
)
|
|
1044
|
+
_emit(payload, args.json_output, _print_decision_list)
|
|
1045
|
+
return 0
|
|
1046
|
+
|
|
1047
|
+
if args.cmd == "decision-apply":
|
|
1048
|
+
payload = cmd_decision_apply(
|
|
1049
|
+
Path(args.backlog_dir), args.item_id, args.actor or _default_actor(),
|
|
1050
|
+
args.state_dir, Path(args.config), _default_schema_path(),
|
|
1051
|
+
)
|
|
1052
|
+
_emit(payload, args.json_output, _print_decision_apply)
|
|
1053
|
+
return 0
|
|
1054
|
+
|
|
1055
|
+
if args.cmd == "backlog-topology":
|
|
1056
|
+
items = _load_topology_items(args)
|
|
1057
|
+
payload = cmd_backlog_topology(items, with_clusters=args.with_clusters)
|
|
1058
|
+
_emit(payload, args.json_output, _print_topology)
|
|
1059
|
+
return 0
|
|
1060
|
+
|
|
1061
|
+
raise UsageError(f"unknown command: {args.cmd}")
|
|
1062
|
+
except UsageError as exc:
|
|
1063
|
+
print(f"Error: {exc}", file=sys.stderr)
|
|
1064
|
+
return 2
|
|
1065
|
+
except OSError as exc:
|
|
1066
|
+
print(f"Error: {exc}", file=sys.stderr)
|
|
1067
|
+
return 2
|