@opengsd/gsd-path 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +28 -11
- package/DOCS.md +6 -5
- package/FULL.md +9 -13
- package/QUICK.md +3 -3
- package/README.md +151 -14
- package/RUNTIME.md +7 -1
- package/WORKFLOW.md +30 -14
- package/package.json +15 -1
- package/platforms/shared-agents/dispatch.md +6 -0
- package/scripts/archive_milestone.py +10 -118
- package/scripts/bootstrap_repository.py +25 -3
- package/scripts/build_recovery.py +287 -0
- package/scripts/check_docs_audit.py +5 -3
- package/scripts/check_handoffs.py +1 -1
- package/scripts/detect_project.py +11 -2
- package/scripts/dispatch_driver.py +4 -2
- package/scripts/git_guard.py +2 -1
- package/scripts/install.mjs +2 -0
- package/scripts/install.py +2 -0
- package/scripts/integration.py +28 -22
- package/scripts/isolation.py +9 -1
- package/scripts/lean_verification.py +1 -1
- package/scripts/pipeline_diagnose.py +12 -3
- package/scripts/pipeline_state.py +114 -186
- package/scripts/pipeline_undo.py +11 -7
- package/scripts/promote_lookahead.py +30 -162
- package/scripts/roadmap.py +321 -0
- package/scripts/skill-resources.json +79 -1
- package/scripts/state_checkpoint.py +109 -72
- package/scripts/state_promote.py +42 -44
- package/scripts/task_context.py +73 -0
- package/scripts/token_budget.py +40 -1
- package/scripts/workflow_run.py +116 -7
- package/skills/gsd-path/BUILD.md +47 -575
- package/skills/gsd-path/DECIDE.md +2 -6
- package/skills/gsd-path/DEFINE.md +10 -14
- package/skills/gsd-path/INSPECT.md +30 -8
- package/skills/gsd-path/PLAN.md +25 -17
- package/skills/gsd-path/RESEARCH.md +3 -6
- package/skills/gsd-path/ROADMAP.md +22 -58
- package/skills/gsd-path/SHIP.md +5 -4
- package/skills/gsd-path/SKILL.md +24 -14
- package/skills/gsd-path/references/build-abandon.md +33 -0
- package/skills/gsd-path/references/build-native.md +494 -0
- package/skills/gsd-path/references/build-recovery.md +78 -0
- package/skills/gsd-path/references/coder.md +8 -3
- package/skills/gsd-path/references/dispatch.md +6 -0
- package/skills/gsd-path/references/docs-auditor.md +14 -0
- package/skills/gsd-path/references/reviewer-final.md +21 -0
- package/skills/gsd-path/references/reviewer-panel.md +17 -0
- package/skills/gsd-path/references/reviewer-skeptic.md +20 -0
- package/skills/gsd-path/references/reviewer-wave.md +89 -0
- package/skills/gsd-path/references/reviewer.md +12 -150
- package/skills/gsd-path/scripts/__pycache__/_common.cpython-312.pyc +0 -0
- package/skills/gsd-path/scripts/__pycache__/archive_milestone.cpython-312.pyc +0 -0
- package/skills/gsd-path/scripts/__pycache__/build_recovery.cpython-312.pyc +0 -0
- package/skills/gsd-path/scripts/__pycache__/build_state.cpython-312.pyc +0 -0
- package/skills/gsd-path/scripts/__pycache__/check_handoffs.cpython-312.pyc +0 -0
- package/skills/gsd-path/scripts/__pycache__/check_task_briefs.cpython-312.pyc +0 -0
- package/skills/gsd-path/scripts/__pycache__/detect_project.cpython-312.pyc +0 -0
- package/skills/gsd-path/scripts/__pycache__/discussion_records.cpython-312.pyc +0 -0
- package/skills/gsd-path/scripts/__pycache__/discussion_validate.cpython-312.pyc +0 -0
- package/skills/gsd-path/scripts/__pycache__/integration.cpython-312.pyc +0 -0
- package/skills/gsd-path/scripts/__pycache__/isolation.cpython-312.pyc +0 -0
- package/skills/gsd-path/scripts/__pycache__/loop_run.cpython-312.pyc +0 -0
- package/skills/gsd-path/scripts/__pycache__/pipeline_git.cpython-312.pyc +0 -0
- package/skills/gsd-path/scripts/__pycache__/pipeline_state.cpython-312.pyc +0 -0
- package/skills/gsd-path/scripts/__pycache__/review_findings.cpython-312.pyc +0 -0
- package/skills/gsd-path/scripts/__pycache__/review_panel.cpython-312.pyc +0 -0
- package/skills/gsd-path/scripts/__pycache__/roadmap.cpython-312.pyc +0 -0
- package/skills/gsd-path/scripts/__pycache__/state_checkpoint.cpython-312.pyc +0 -0
- package/skills/gsd-path/scripts/__pycache__/task_context.cpython-312.pyc +0 -0
- package/skills/gsd-path/scripts/__pycache__/workflow_run.cpython-312.pyc +0 -0
- package/skills/gsd-path/scripts/archive_milestone.py +10 -118
- package/skills/gsd-path/scripts/bootstrap_repository.py +25 -3
- package/skills/gsd-path/scripts/build_recovery.py +287 -0
- package/skills/gsd-path/scripts/check_docs_audit.py +5 -3
- package/skills/gsd-path/scripts/check_handoffs.py +1 -1
- package/skills/gsd-path/scripts/detect_project.py +11 -2
- package/skills/gsd-path/scripts/dispatch_driver.py +4 -2
- package/skills/gsd-path/scripts/integration.py +28 -22
- package/skills/gsd-path/scripts/isolation.py +9 -1
- package/skills/gsd-path/scripts/lean_verification.py +1 -1
- package/skills/gsd-path/scripts/pipeline_state.py +114 -186
- package/skills/gsd-path/scripts/promote_lookahead.py +30 -162
- package/skills/gsd-path/scripts/roadmap.py +321 -0
- package/skills/gsd-path/scripts/state_checkpoint.py +109 -72
- package/skills/gsd-path/scripts/state_promote.py +42 -44
- package/skills/gsd-path/scripts/task_context.py +73 -0
- package/skills/gsd-path/scripts/token_budget.py +40 -1
- package/skills/gsd-path/scripts/workflow_run.py +116 -7
- package/skills/gsd-path/templates/wave-review.md +1 -1
- package/skills/gsd-path-build/SKILL.md +47 -575
- package/skills/gsd-path-build/references/build-abandon.md +33 -0
- package/skills/gsd-path-build/references/build-native.md +494 -0
- package/skills/gsd-path-build/references/build-recovery.md +78 -0
- package/skills/gsd-path-build/references/coder.md +8 -3
- package/skills/gsd-path-build/references/dispatch.md +6 -0
- package/skills/gsd-path-build/references/reviewer-final.md +21 -0
- package/skills/gsd-path-build/references/reviewer-panel.md +17 -0
- package/skills/gsd-path-build/references/reviewer-skeptic.md +20 -0
- package/skills/gsd-path-build/references/reviewer-wave.md +89 -0
- package/skills/gsd-path-build/references/reviewer.md +12 -150
- package/skills/gsd-path-build/scripts/__pycache__/_common.cpython-312.pyc +0 -0
- package/skills/gsd-path-build/scripts/__pycache__/archive_milestone.cpython-312.pyc +0 -0
- package/skills/gsd-path-build/scripts/__pycache__/build_recovery.cpython-312.pyc +0 -0
- package/skills/gsd-path-build/scripts/__pycache__/build_state.cpython-312.pyc +0 -0
- package/skills/gsd-path-build/scripts/__pycache__/check_handoffs.cpython-312.pyc +0 -0
- package/skills/gsd-path-build/scripts/__pycache__/check_task_briefs.cpython-312.pyc +0 -0
- package/skills/gsd-path-build/scripts/__pycache__/detect_project.cpython-312.pyc +0 -0
- package/skills/gsd-path-build/scripts/__pycache__/discussion_validate.cpython-312.pyc +0 -0
- package/skills/gsd-path-build/scripts/__pycache__/isolation.cpython-312.pyc +0 -0
- package/skills/gsd-path-build/scripts/__pycache__/loop_run.cpython-312.pyc +0 -0
- package/skills/gsd-path-build/scripts/__pycache__/pipeline_git.cpython-312.pyc +0 -0
- package/skills/gsd-path-build/scripts/__pycache__/pipeline_state.cpython-312.pyc +0 -0
- package/skills/gsd-path-build/scripts/__pycache__/review_findings.cpython-312.pyc +0 -0
- package/skills/gsd-path-build/scripts/__pycache__/review_panel.cpython-312.pyc +0 -0
- package/skills/gsd-path-build/scripts/__pycache__/roadmap.cpython-312.pyc +0 -0
- package/skills/gsd-path-build/scripts/__pycache__/state_checkpoint.cpython-312.pyc +0 -0
- package/skills/gsd-path-build/scripts/__pycache__/task_context.cpython-312.pyc +0 -0
- package/skills/gsd-path-build/scripts/__pycache__/workflow_run.cpython-312.pyc +0 -0
- package/skills/gsd-path-build/scripts/archive_milestone.py +10 -118
- package/skills/gsd-path-build/scripts/build_recovery.py +287 -0
- package/skills/gsd-path-build/scripts/check_handoffs.py +1 -1
- package/skills/gsd-path-build/scripts/detect_project.py +1526 -0
- package/skills/gsd-path-build/scripts/dispatch_driver.py +4 -2
- package/skills/gsd-path-build/scripts/integration.py +28 -22
- package/skills/gsd-path-build/scripts/isolation.py +9 -1
- package/skills/gsd-path-build/scripts/pipeline_state.py +114 -186
- package/skills/gsd-path-build/scripts/promote_lookahead.py +283 -0
- package/skills/gsd-path-build/scripts/roadmap.py +321 -0
- package/skills/gsd-path-build/scripts/state_checkpoint.py +109 -72
- package/skills/gsd-path-build/scripts/state_promote.py +42 -44
- package/skills/gsd-path-build/scripts/task_context.py +73 -0
- package/skills/gsd-path-build/scripts/token_budget.py +40 -1
- package/skills/gsd-path-build/scripts/workflow_run.py +116 -7
- package/skills/gsd-path-build/templates/wave-review.md +1 -1
- package/skills/gsd-path-decide/SKILL.md +2 -6
- package/skills/gsd-path-decide/references/dispatch.md +6 -0
- package/skills/gsd-path-decide/scripts/__pycache__/_common.cpython-312.pyc +0 -0
- package/skills/gsd-path-decide/scripts/__pycache__/archive_milestone.cpython-312.pyc +0 -0
- package/skills/gsd-path-decide/scripts/__pycache__/detect_project.cpython-312.pyc +0 -0
- package/skills/gsd-path-decide/scripts/__pycache__/discussion_validate.cpython-312.pyc +0 -0
- package/skills/gsd-path-decide/scripts/__pycache__/isolation.cpython-312.pyc +0 -0
- package/skills/gsd-path-decide/scripts/__pycache__/pipeline_git.cpython-312.pyc +0 -0
- package/skills/gsd-path-decide/scripts/__pycache__/pipeline_state.cpython-312.pyc +0 -0
- package/skills/gsd-path-decide/scripts/__pycache__/review_panel.cpython-312.pyc +0 -0
- package/skills/gsd-path-decide/scripts/__pycache__/roadmap.cpython-312.pyc +0 -0
- package/skills/gsd-path-decide/scripts/__pycache__/state_checkpoint.cpython-312.pyc +0 -0
- package/skills/gsd-path-decide/scripts/archive_milestone.py +2157 -0
- package/skills/gsd-path-decide/scripts/build_recovery.py +287 -0
- package/skills/gsd-path-decide/scripts/check_handoffs.py +1 -1
- package/skills/gsd-path-decide/scripts/detect_project.py +1526 -0
- package/skills/gsd-path-decide/scripts/discussion_validate.py +1321 -0
- package/skills/gsd-path-decide/scripts/integration.py +1439 -0
- package/skills/gsd-path-decide/scripts/isolation.py +9 -1
- package/skills/gsd-path-decide/scripts/pipeline_state.py +114 -186
- package/skills/gsd-path-decide/scripts/promote_lookahead.py +283 -0
- package/skills/gsd-path-decide/scripts/review_panel.py +553 -0
- package/skills/gsd-path-decide/scripts/roadmap.py +321 -0
- package/skills/gsd-path-decide/scripts/state_checkpoint.py +109 -72
- package/skills/gsd-path-decide/scripts/state_promote.py +42 -44
- package/skills/gsd-path-define/SKILL.md +10 -14
- package/skills/gsd-path-define/references/build-recovery.md +78 -0
- package/skills/gsd-path-define/scripts/__pycache__/_common.cpython-312.pyc +0 -0
- package/skills/gsd-path-define/scripts/__pycache__/archive_milestone.cpython-312.pyc +0 -0
- package/skills/gsd-path-define/scripts/__pycache__/detect_project.cpython-312.pyc +0 -0
- package/skills/gsd-path-define/scripts/__pycache__/discussion_validate.cpython-312.pyc +0 -0
- package/skills/gsd-path-define/scripts/__pycache__/isolation.cpython-312.pyc +0 -0
- package/skills/gsd-path-define/scripts/__pycache__/pipeline_git.cpython-312.pyc +0 -0
- package/skills/gsd-path-define/scripts/__pycache__/pipeline_state.cpython-312.pyc +0 -0
- package/skills/gsd-path-define/scripts/__pycache__/review_panel.cpython-312.pyc +0 -0
- package/skills/gsd-path-define/scripts/__pycache__/roadmap.cpython-312.pyc +0 -0
- package/skills/gsd-path-define/scripts/__pycache__/state_checkpoint.cpython-312.pyc +0 -0
- package/skills/gsd-path-define/scripts/archive_milestone.py +2157 -0
- package/skills/gsd-path-define/scripts/build_recovery.py +287 -0
- package/skills/gsd-path-define/scripts/check_handoffs.py +1 -1
- package/skills/gsd-path-define/scripts/detect_project.py +11 -2
- package/skills/gsd-path-define/scripts/discussion_validate.py +1321 -0
- package/skills/gsd-path-define/scripts/integration.py +1439 -0
- package/skills/gsd-path-define/scripts/isolation.py +9 -1
- package/skills/gsd-path-define/scripts/pipeline_state.py +114 -186
- package/skills/gsd-path-define/scripts/promote_lookahead.py +283 -0
- package/skills/gsd-path-define/scripts/review_panel.py +553 -0
- package/skills/gsd-path-define/scripts/roadmap.py +321 -0
- package/skills/gsd-path-define/scripts/state_checkpoint.py +109 -72
- package/skills/gsd-path-define/scripts/state_promote.py +42 -44
- package/skills/gsd-path-docs-audit/references/dispatch.md +6 -0
- package/skills/gsd-path-docs-audit/references/docs-auditor.md +14 -0
- package/skills/gsd-path-docs-audit/scripts/__pycache__/_common.cpython-312.pyc +0 -0
- package/skills/gsd-path-docs-audit/scripts/__pycache__/archive_milestone.cpython-312.pyc +0 -0
- package/skills/gsd-path-docs-audit/scripts/__pycache__/build_recovery.cpython-312.pyc +0 -0
- package/skills/gsd-path-docs-audit/scripts/__pycache__/detect_project.cpython-312.pyc +0 -0
- package/skills/gsd-path-docs-audit/scripts/__pycache__/discussion_validate.cpython-312.pyc +0 -0
- package/skills/gsd-path-docs-audit/scripts/__pycache__/isolation.cpython-312.pyc +0 -0
- package/skills/gsd-path-docs-audit/scripts/__pycache__/pipeline_git.cpython-312.pyc +0 -0
- package/skills/gsd-path-docs-audit/scripts/__pycache__/pipeline_state.cpython-312.pyc +0 -0
- package/skills/gsd-path-docs-audit/scripts/__pycache__/review_panel.cpython-312.pyc +0 -0
- package/skills/gsd-path-docs-audit/scripts/__pycache__/roadmap.cpython-312.pyc +0 -0
- package/skills/gsd-path-docs-audit/scripts/__pycache__/state_checkpoint.cpython-312.pyc +0 -0
- package/skills/gsd-path-docs-audit/scripts/archive_milestone.py +2157 -0
- package/skills/gsd-path-docs-audit/scripts/build_recovery.py +287 -0
- package/skills/gsd-path-docs-audit/scripts/check_docs_audit.py +5 -3
- package/skills/gsd-path-docs-audit/scripts/check_handoffs.py +1 -1
- package/skills/gsd-path-docs-audit/scripts/detect_project.py +1526 -0
- package/skills/gsd-path-docs-audit/scripts/discussion_validate.py +1321 -0
- package/skills/gsd-path-docs-audit/scripts/integration.py +1439 -0
- package/skills/gsd-path-docs-audit/scripts/isolation.py +9 -1
- package/skills/gsd-path-docs-audit/scripts/pipeline_state.py +114 -186
- package/skills/gsd-path-docs-audit/scripts/promote_lookahead.py +283 -0
- package/skills/gsd-path-docs-audit/scripts/review_panel.py +553 -0
- package/skills/gsd-path-docs-audit/scripts/roadmap.py +321 -0
- package/skills/gsd-path-docs-audit/scripts/state_checkpoint.py +109 -72
- package/skills/gsd-path-docs-audit/scripts/state_promote.py +42 -44
- package/skills/gsd-path-forensics/scripts/__pycache__/pipeline_undo.cpython-312.pyc +0 -0
- package/skills/gsd-path-forensics/scripts/pipeline_diagnose.py +12 -3
- package/skills/gsd-path-forensics/scripts/pipeline_undo.py +11 -7
- package/skills/gsd-path-inspect/SKILL.md +30 -8
- package/skills/gsd-path-inspect/references/dispatch.md +6 -0
- package/skills/gsd-path-inspect/references/docs-auditor.md +14 -0
- package/skills/gsd-path-inspect/scripts/__pycache__/_common.cpython-312.pyc +0 -0
- package/skills/gsd-path-inspect/scripts/__pycache__/archive_milestone.cpython-312.pyc +0 -0
- package/skills/gsd-path-inspect/scripts/__pycache__/build_recovery.cpython-312.pyc +0 -0
- package/skills/gsd-path-inspect/scripts/__pycache__/detect_project.cpython-312.pyc +0 -0
- package/skills/gsd-path-inspect/scripts/__pycache__/discussion_validate.cpython-312.pyc +0 -0
- package/skills/gsd-path-inspect/scripts/__pycache__/isolation.cpython-312.pyc +0 -0
- package/skills/gsd-path-inspect/scripts/__pycache__/pipeline_git.cpython-312.pyc +0 -0
- package/skills/gsd-path-inspect/scripts/__pycache__/pipeline_state.cpython-312.pyc +0 -0
- package/skills/gsd-path-inspect/scripts/__pycache__/review_panel.cpython-312.pyc +0 -0
- package/skills/gsd-path-inspect/scripts/__pycache__/roadmap.cpython-312.pyc +0 -0
- package/skills/gsd-path-inspect/scripts/__pycache__/state_checkpoint.cpython-312.pyc +0 -0
- package/skills/gsd-path-inspect/scripts/archive_milestone.py +2157 -0
- package/skills/gsd-path-inspect/scripts/build_recovery.py +287 -0
- package/skills/gsd-path-inspect/scripts/check_docs_audit.py +5 -3
- package/skills/gsd-path-inspect/scripts/check_handoffs.py +1 -1
- package/skills/gsd-path-inspect/scripts/detect_project.py +11 -2
- package/skills/gsd-path-inspect/scripts/discussion_validate.py +1321 -0
- package/skills/gsd-path-inspect/scripts/integration.py +1439 -0
- package/skills/gsd-path-inspect/scripts/isolation.py +9 -1
- package/skills/gsd-path-inspect/scripts/pipeline_state.py +114 -186
- package/skills/gsd-path-inspect/scripts/promote_lookahead.py +283 -0
- package/skills/gsd-path-inspect/scripts/review_panel.py +553 -0
- package/skills/gsd-path-inspect/scripts/roadmap.py +321 -0
- package/skills/gsd-path-inspect/scripts/state_checkpoint.py +109 -72
- package/skills/gsd-path-inspect/scripts/state_promote.py +42 -44
- package/skills/gsd-path-inspect/scripts/workflow_run.py +226 -0
- package/skills/gsd-path-plan/SKILL.md +25 -17
- package/skills/gsd-path-plan/references/build-recovery.md +78 -0
- package/skills/gsd-path-plan/references/dispatch.md +6 -0
- package/skills/gsd-path-plan/scripts/__pycache__/_common.cpython-312.pyc +0 -0
- package/skills/gsd-path-plan/scripts/__pycache__/archive_milestone.cpython-312.pyc +0 -0
- package/skills/gsd-path-plan/scripts/__pycache__/detect_project.cpython-312.pyc +0 -0
- package/skills/gsd-path-plan/scripts/__pycache__/discussion_validate.cpython-312.pyc +0 -0
- package/skills/gsd-path-plan/scripts/__pycache__/isolation.cpython-312.pyc +0 -0
- package/skills/gsd-path-plan/scripts/__pycache__/pipeline_git.cpython-312.pyc +0 -0
- package/skills/gsd-path-plan/scripts/__pycache__/pipeline_state.cpython-312.pyc +0 -0
- package/skills/gsd-path-plan/scripts/__pycache__/review_panel.cpython-312.pyc +0 -0
- package/skills/gsd-path-plan/scripts/__pycache__/roadmap.cpython-312.pyc +0 -0
- package/skills/gsd-path-plan/scripts/__pycache__/state_checkpoint.cpython-312.pyc +0 -0
- package/skills/gsd-path-plan/scripts/archive_milestone.py +2157 -0
- package/skills/gsd-path-plan/scripts/build_recovery.py +287 -0
- package/skills/gsd-path-plan/scripts/check_handoffs.py +1 -1
- package/skills/gsd-path-plan/scripts/detect_project.py +1526 -0
- package/skills/gsd-path-plan/scripts/discussion_validate.py +1321 -0
- package/skills/gsd-path-plan/scripts/integration.py +1439 -0
- package/skills/gsd-path-plan/scripts/isolation.py +9 -1
- package/skills/gsd-path-plan/scripts/pipeline_state.py +114 -186
- package/skills/gsd-path-plan/scripts/promote_lookahead.py +283 -0
- package/skills/gsd-path-plan/scripts/roadmap.py +321 -0
- package/skills/gsd-path-plan/scripts/state_checkpoint.py +109 -72
- package/skills/gsd-path-plan/scripts/state_promote.py +42 -44
- package/skills/gsd-path-plan/scripts/workflow_run.py +116 -7
- package/skills/gsd-path-research/SKILL.md +3 -6
- package/skills/gsd-path-research/references/dispatch.md +6 -0
- package/skills/gsd-path-research/scripts/__pycache__/_common.cpython-312.pyc +0 -0
- package/skills/gsd-path-research/scripts/__pycache__/archive_milestone.cpython-312.pyc +0 -0
- package/skills/gsd-path-research/scripts/__pycache__/detect_project.cpython-312.pyc +0 -0
- package/skills/gsd-path-research/scripts/__pycache__/discussion_validate.cpython-312.pyc +0 -0
- package/skills/gsd-path-research/scripts/__pycache__/isolation.cpython-312.pyc +0 -0
- package/skills/gsd-path-research/scripts/__pycache__/pipeline_git.cpython-312.pyc +0 -0
- package/skills/gsd-path-research/scripts/__pycache__/pipeline_state.cpython-312.pyc +0 -0
- package/skills/gsd-path-research/scripts/__pycache__/review_panel.cpython-312.pyc +0 -0
- package/skills/gsd-path-research/scripts/__pycache__/roadmap.cpython-312.pyc +0 -0
- package/skills/gsd-path-research/scripts/__pycache__/state_checkpoint.cpython-312.pyc +0 -0
- package/skills/gsd-path-research/scripts/archive_milestone.py +2157 -0
- package/skills/gsd-path-research/scripts/build_recovery.py +287 -0
- package/skills/gsd-path-research/scripts/check_handoffs.py +1 -1
- package/skills/gsd-path-research/scripts/detect_project.py +1526 -0
- package/skills/gsd-path-research/scripts/discussion_validate.py +1321 -0
- package/skills/gsd-path-research/scripts/integration.py +1439 -0
- package/skills/gsd-path-research/scripts/isolation.py +9 -1
- package/skills/gsd-path-research/scripts/pipeline_state.py +114 -186
- package/skills/gsd-path-research/scripts/promote_lookahead.py +283 -0
- package/skills/gsd-path-research/scripts/review_panel.py +553 -0
- package/skills/gsd-path-research/scripts/roadmap.py +321 -0
- package/skills/gsd-path-research/scripts/state_checkpoint.py +109 -72
- package/skills/gsd-path-research/scripts/state_promote.py +42 -44
- package/skills/gsd-path-roadmap/SKILL.md +22 -58
- package/skills/gsd-path-roadmap/references/dispatch.md +6 -0
- package/skills/gsd-path-roadmap/scripts/__pycache__/_common.cpython-312.pyc +0 -0
- package/skills/gsd-path-roadmap/scripts/__pycache__/archive_milestone.cpython-312.pyc +0 -0
- package/skills/gsd-path-roadmap/scripts/__pycache__/detect_project.cpython-312.pyc +0 -0
- package/skills/gsd-path-roadmap/scripts/__pycache__/discussion_validate.cpython-312.pyc +0 -0
- package/skills/gsd-path-roadmap/scripts/__pycache__/isolation.cpython-312.pyc +0 -0
- package/skills/gsd-path-roadmap/scripts/__pycache__/pipeline_git.cpython-312.pyc +0 -0
- package/skills/gsd-path-roadmap/scripts/__pycache__/pipeline_state.cpython-312.pyc +0 -0
- package/skills/gsd-path-roadmap/scripts/__pycache__/review_panel.cpython-312.pyc +0 -0
- package/skills/gsd-path-roadmap/scripts/__pycache__/roadmap.cpython-312.pyc +0 -0
- package/skills/gsd-path-roadmap/scripts/__pycache__/state_checkpoint.cpython-312.pyc +0 -0
- package/skills/gsd-path-roadmap/scripts/archive_milestone.py +10 -118
- package/skills/gsd-path-roadmap/scripts/build_recovery.py +287 -0
- package/skills/gsd-path-roadmap/scripts/check_handoffs.py +1 -1
- package/skills/gsd-path-roadmap/scripts/detect_project.py +11 -2
- package/skills/gsd-path-roadmap/scripts/integration.py +28 -22
- package/skills/gsd-path-roadmap/scripts/isolation.py +9 -1
- package/skills/gsd-path-roadmap/scripts/pipeline_state.py +114 -186
- package/skills/gsd-path-roadmap/scripts/promote_lookahead.py +30 -162
- package/skills/gsd-path-roadmap/scripts/roadmap.py +321 -0
- package/skills/gsd-path-roadmap/scripts/state_checkpoint.py +109 -72
- package/skills/gsd-path-roadmap/scripts/state_promote.py +42 -44
- package/skills/gsd-path-ship/SKILL.md +5 -4
- package/skills/gsd-path-ship/references/dispatch.md +6 -0
- package/skills/gsd-path-ship/references/reviewer-final.md +21 -0
- package/skills/gsd-path-ship/references/reviewer-panel.md +17 -0
- package/skills/gsd-path-ship/references/reviewer-skeptic.md +20 -0
- package/skills/gsd-path-ship/references/reviewer-wave.md +89 -0
- package/skills/gsd-path-ship/references/reviewer.md +12 -150
- package/skills/gsd-path-ship/scripts/__pycache__/_common.cpython-312.pyc +0 -0
- package/skills/gsd-path-ship/scripts/__pycache__/archive_milestone.cpython-312.pyc +0 -0
- package/skills/gsd-path-ship/scripts/__pycache__/build_recovery.cpython-312.pyc +0 -0
- package/skills/gsd-path-ship/scripts/__pycache__/build_state.cpython-312.pyc +0 -0
- package/skills/gsd-path-ship/scripts/__pycache__/check_handoffs.cpython-312.pyc +0 -0
- package/skills/gsd-path-ship/scripts/__pycache__/check_task_briefs.cpython-312.pyc +0 -0
- package/skills/gsd-path-ship/scripts/__pycache__/detect_project.cpython-312.pyc +0 -0
- package/skills/gsd-path-ship/scripts/__pycache__/discussion_validate.cpython-312.pyc +0 -0
- package/skills/gsd-path-ship/scripts/__pycache__/isolation.cpython-312.pyc +0 -0
- package/skills/gsd-path-ship/scripts/__pycache__/pipeline_git.cpython-312.pyc +0 -0
- package/skills/gsd-path-ship/scripts/__pycache__/pipeline_state.cpython-312.pyc +0 -0
- package/skills/gsd-path-ship/scripts/__pycache__/review_panel.cpython-312.pyc +0 -0
- package/skills/gsd-path-ship/scripts/__pycache__/roadmap.cpython-312.pyc +0 -0
- package/skills/gsd-path-ship/scripts/__pycache__/state_checkpoint.cpython-312.pyc +0 -0
- package/skills/gsd-path-ship/scripts/archive_milestone.py +10 -118
- package/skills/gsd-path-ship/scripts/build_recovery.py +287 -0
- package/skills/gsd-path-ship/scripts/check_handoffs.py +1 -1
- package/skills/gsd-path-ship/scripts/detect_project.py +1526 -0
- package/skills/gsd-path-ship/scripts/integration.py +28 -22
- package/skills/gsd-path-ship/scripts/isolation.py +9 -1
- package/skills/gsd-path-ship/scripts/lean_verification.py +1 -1
- package/skills/gsd-path-ship/scripts/pipeline_state.py +114 -186
- package/skills/gsd-path-ship/scripts/promote_lookahead.py +283 -0
- package/skills/gsd-path-ship/scripts/roadmap.py +321 -0
- package/skills/gsd-path-ship/scripts/state_checkpoint.py +109 -72
- package/skills/gsd-path-ship/scripts/state_promote.py +42 -44
- package/skills/gsd-path-ship/scripts/workflow_run.py +116 -7
- package/skills/gsd-path-ship/templates/wave-review.md +1 -1
- package/skills/gsd-path-undo/scripts/pipeline_undo.py +11 -7
- package/skills/path/BUILD.md +47 -575
- package/skills/path/DECIDE.md +2 -6
- package/skills/path/DEFINE.md +10 -14
- package/skills/path/INSPECT.md +30 -8
- package/skills/path/PLAN.md +25 -17
- package/skills/path/RESEARCH.md +3 -6
- package/skills/path/ROADMAP.md +22 -58
- package/skills/path/SHIP.md +5 -4
- package/skills/path/SKILL.md +24 -14
- package/skills/path/references/build-abandon.md +33 -0
- package/skills/path/references/build-native.md +494 -0
- package/skills/path/references/build-recovery.md +78 -0
- package/skills/path/references/coder.md +8 -3
- package/skills/path/references/dispatch.md +6 -0
- package/skills/path/references/docs-auditor.md +14 -0
- package/skills/path/references/reviewer-final.md +21 -0
- package/skills/path/references/reviewer-panel.md +17 -0
- package/skills/path/references/reviewer-skeptic.md +20 -0
- package/skills/path/references/reviewer-wave.md +89 -0
- package/skills/path/references/reviewer.md +12 -150
- package/skills/path/scripts/archive_milestone.py +10 -118
- package/skills/path/scripts/bootstrap_repository.py +25 -3
- package/skills/path/scripts/build_recovery.py +287 -0
- package/skills/path/scripts/check_docs_audit.py +5 -3
- package/skills/path/scripts/check_handoffs.py +1 -1
- package/skills/path/scripts/detect_project.py +11 -2
- package/skills/path/scripts/dispatch_driver.py +4 -2
- package/skills/path/scripts/integration.py +28 -22
- package/skills/path/scripts/isolation.py +9 -1
- package/skills/path/scripts/lean_verification.py +1 -1
- package/skills/path/scripts/pipeline_state.py +114 -186
- package/skills/path/scripts/promote_lookahead.py +30 -162
- package/skills/path/scripts/roadmap.py +321 -0
- package/skills/path/scripts/state_checkpoint.py +109 -72
- package/skills/path/scripts/state_promote.py +42 -44
- package/skills/path/scripts/task_context.py +73 -0
- package/skills/path/scripts/token_budget.py +40 -1
- package/skills/path/scripts/workflow_run.py +116 -7
- package/skills/path/templates/wave-review.md +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
# gsd-path project runtime
|
|
3
|
-
"""
|
|
3
|
+
"""Own milestone integration, publication, tags, and completion proof."""
|
|
4
4
|
|
|
5
5
|
import json
|
|
6
6
|
import re
|
|
@@ -37,6 +37,20 @@ except ImportError: # pragma: no cover - package import used by tests
|
|
|
37
37
|
from scripts import _common
|
|
38
38
|
|
|
39
39
|
|
|
40
|
+
if __package__:
|
|
41
|
+
from . import archive_milestone
|
|
42
|
+
from .archive_milestone import ArchiveError
|
|
43
|
+
else:
|
|
44
|
+
import archive_milestone
|
|
45
|
+
from archive_milestone import ArchiveError
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
PR_CREDIT_LINE = (
|
|
49
|
+
"PR prepared with [GSD Path](https://github.com/open-gsd/gsd-path)."
|
|
50
|
+
)
|
|
51
|
+
GITHUB_HOST = "github.com"
|
|
52
|
+
|
|
53
|
+
|
|
40
54
|
run_git = _common.run_git
|
|
41
55
|
run_command = _common.run_command
|
|
42
56
|
|
|
@@ -1208,7 +1222,7 @@ def find_integrate_commit(
|
|
|
1208
1222
|
return merge_commit
|
|
1209
1223
|
|
|
1210
1224
|
|
|
1211
|
-
def validate_integrated(repo: Path, slug: str) -> dict:
|
|
1225
|
+
def validate_integrated(repo: Path, slug: str, *, refresh: bool = True) -> dict:
|
|
1212
1226
|
project = repo.resolve()
|
|
1213
1227
|
active_root = archive_milestone.require_project_layout(project)
|
|
1214
1228
|
state, _, loaded_state_path = archive_milestone.strict_state(project)
|
|
@@ -1228,7 +1242,8 @@ def validate_integrated(repo: Path, slug: str) -> dict:
|
|
|
1228
1242
|
|
|
1229
1243
|
# Refresh whenever origin exists so direct mode cannot miss a published tag.
|
|
1230
1244
|
# Fixtures that only plant refs/remotes/origin/* keep resolve_remote_default.
|
|
1231
|
-
|
|
1245
|
+
has_origin = run_git(project, "remote", "get-url", "origin").returncode == 0
|
|
1246
|
+
if has_origin and refresh:
|
|
1232
1247
|
remote_default = refresh_origin(project)["remote_default"]
|
|
1233
1248
|
else:
|
|
1234
1249
|
remote_default = resolve_remote_default(project)
|
|
@@ -1348,6 +1363,16 @@ def validate_integrated(repo: Path, slug: str) -> dict:
|
|
|
1348
1363
|
"mode": state.integration,
|
|
1349
1364
|
"tag": tag_name,
|
|
1350
1365
|
}
|
|
1366
|
+
if has_origin and not refresh:
|
|
1367
|
+
# Status must not fetch or write refs. Missing/stale local evidence is
|
|
1368
|
+
# unverified; the normal ship validator remains the refresh owner.
|
|
1369
|
+
refs = [(f"refs/heads/{default_name}", result["base"]),
|
|
1370
|
+
(f"refs/tags/{tag_name}", optional_ref(project, tag_ref))]
|
|
1371
|
+
if state.integration == "direct":
|
|
1372
|
+
refs.append((f"refs/heads/{bound_branch}", ship_commit))
|
|
1373
|
+
for ref, expected in refs:
|
|
1374
|
+
if live_remote_ref(project, ref) != expected:
|
|
1375
|
+
raise ArchiveError(f"published {ref} differs from local integration evidence")
|
|
1351
1376
|
if pull_request is not None:
|
|
1352
1377
|
result["pull_request"] = pull_request
|
|
1353
1378
|
return result
|
|
@@ -1412,22 +1437,3 @@ def require_published_integration(
|
|
|
1412
1437
|
raise ArchiveError(
|
|
1413
1438
|
f"published milestone tag {tag_name} does not point at the integration merge"
|
|
1414
1439
|
)
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
# archive_milestone imports this module, so the parent is resolved after the
|
|
1418
|
-
# definitions above. Parent functions are looked up on the module at call time
|
|
1419
|
-
# so patches applied to archive_milestone stay visible here.
|
|
1420
|
-
if __package__: # imported as scripts.integration
|
|
1421
|
-
from . import archive_milestone
|
|
1422
|
-
from .archive_milestone import (
|
|
1423
|
-
GITHUB_HOST,
|
|
1424
|
-
PR_CREDIT_LINE,
|
|
1425
|
-
ArchiveError,
|
|
1426
|
-
)
|
|
1427
|
-
else: # standalone script or sibling import
|
|
1428
|
-
import archive_milestone
|
|
1429
|
-
from archive_milestone import (
|
|
1430
|
-
GITHUB_HOST,
|
|
1431
|
-
PR_CREDIT_LINE,
|
|
1432
|
-
ArchiveError,
|
|
1433
|
-
)
|
|
@@ -2016,7 +2016,15 @@ def _recovery_task_inventory(
|
|
|
2016
2016
|
relative_posix_dir = PurePosixPath(relative_dir.as_posix())
|
|
2017
2017
|
revisions = [head]
|
|
2018
2018
|
parents = git_output(primary, "show", "-s", "--format=%P", head).split()
|
|
2019
|
-
|
|
2019
|
+
# A recovery plan checkpoint owns replacement of unstarted task briefs.
|
|
2020
|
+
# Ordinary commits still require the parent inventory so a deletion cannot
|
|
2021
|
+
# silently hide a task from recovery.
|
|
2022
|
+
if __package__:
|
|
2023
|
+
from scripts import build_recovery
|
|
2024
|
+
else:
|
|
2025
|
+
import build_recovery
|
|
2026
|
+
replaced = build_recovery.inventory_checkpoint(primary, head)
|
|
2027
|
+
if parents and not replaced:
|
|
2020
2028
|
revisions.append(parents[0])
|
|
2021
2029
|
tracked = set()
|
|
2022
2030
|
for revision in revisions:
|
|
@@ -94,7 +94,7 @@ def _final_view(relative, text, criteria, reviewed, head):
|
|
|
94
94
|
f"- **Reference**: {relative} — {criterion}",
|
|
95
95
|
"- **Finding**: none", "- **Fix direction**: none"]
|
|
96
96
|
if "Surface" in fields:
|
|
97
|
-
lines.append(f"- **Surface**: {fields['Surface']}")
|
|
97
|
+
lines.append(f"- **Surface**: {contracts._unquoted(fields['Surface']).partition(',')[0]}")
|
|
98
98
|
lines.append("")
|
|
99
99
|
return "\n".join(lines)
|
|
100
100
|
|
|
@@ -32,8 +32,9 @@ try:
|
|
|
32
32
|
collect_artifact_recoveries,
|
|
33
33
|
)
|
|
34
34
|
import _common
|
|
35
|
+
import roadmap
|
|
35
36
|
except ModuleNotFoundError as error: # pragma: no cover - package imports used by tests
|
|
36
|
-
if error.name not in {"isolation", "_common"}:
|
|
37
|
+
if error.name not in {"isolation", "_common", "roadmap"}:
|
|
37
38
|
raise
|
|
38
39
|
from scripts.isolation import (
|
|
39
40
|
IsolationError,
|
|
@@ -41,7 +42,7 @@ except ModuleNotFoundError as error: # pragma: no cover - package imports used
|
|
|
41
42
|
checkpoint as isolation_checkpoint,
|
|
42
43
|
collect_artifact_recoveries,
|
|
43
44
|
)
|
|
44
|
-
from scripts import _common
|
|
45
|
+
from scripts import _common, roadmap
|
|
45
46
|
|
|
46
47
|
try: # pragma: no cover - exercised only on Windows
|
|
47
48
|
import fcntl
|
|
@@ -82,7 +83,6 @@ SLUG_RE = re.compile(r"^[a-z0-9][a-z0-9-]*$")
|
|
|
82
83
|
BOUND_BRANCH_RE = _common.BOUND_BRANCH_RE
|
|
83
84
|
ARCHIVE_RE = re.compile(r"^\.project/archive/(\d{3,})-([a-z0-9][a-z0-9-]*)/?$")
|
|
84
85
|
FRONTMATTER_RE = re.compile(r"^([a-z_]+):\s*([^#]*?)(?:\s+#.*)?$")
|
|
85
|
-
ROADMAP_HEADING_RE = re.compile(r"^### (M\d{3,}) — ([a-z0-9][a-z0-9-]*)\s*$")
|
|
86
86
|
TASK_ID_RE = re.compile(r"^T\d{3,}$")
|
|
87
87
|
TASK_FILE_RE = re.compile(r"^(T\d{3,})-[a-z0-9][a-z0-9-]*\.md$")
|
|
88
88
|
PLAN_APPROVAL_SUBJECT = "plan: build plan approved"
|
|
@@ -110,7 +110,7 @@ LOOKAHEAD_EVIDENCE_RE = re.compile(r"^research/evidence-[a-z0-9][a-z0-9-]*\.md$"
|
|
|
110
110
|
PROMOTION_RESIDUAL = ".gsd-path-promote-next-residual"
|
|
111
111
|
CHECKPOINT_SCHEMA = "gsd-path/state-checkpoint/v1"
|
|
112
112
|
CHECKPOINT_JOURNAL_NAME = "gsd-path-state-checkpoint.json"
|
|
113
|
-
CHECKPOINT_KINDS = ("plan", "roadmap")
|
|
113
|
+
CHECKPOINT_KINDS = ("plan", "roadmap", "roadmap-reslice")
|
|
114
114
|
SHIPMENT_SCHEMA = "gsd-path/shipment/v1"
|
|
115
115
|
SHIPMENT_JOURNAL_NAME = "gsd-path-shipment.json"
|
|
116
116
|
UNDO_TRANSACTION_SCHEMA = "gsd-path/undo-transaction/v2"
|
|
@@ -126,6 +126,8 @@ CROSS_PHASE_TRANSITIONS = {
|
|
|
126
126
|
("decide", "done", "plan", "active"),
|
|
127
127
|
("roadmap", "done", "define", "active"),
|
|
128
128
|
("plan", "done", "build", "active"),
|
|
129
|
+
("build", "blocked", "define", "active"),
|
|
130
|
+
("build", "blocked", "plan", "active"),
|
|
129
131
|
("build", "active", "ship", "active"),
|
|
130
132
|
("build", "done", "ship", "active"),
|
|
131
133
|
("ship", "active", "shipped", "done"),
|
|
@@ -166,99 +168,10 @@ class ApprovedTaskContract:
|
|
|
166
168
|
files: tuple[str, ...]
|
|
167
169
|
|
|
168
170
|
|
|
169
|
-
#
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
from .state_checkpoint import (
|
|
174
|
-
_sha256,
|
|
175
|
-
_tree_digest,
|
|
176
|
-
_checkpoint_artifact_digest,
|
|
177
|
-
_roadmap_status,
|
|
178
|
-
_activate_roadmap_milestone,
|
|
179
|
-
_approval_details,
|
|
180
|
-
_checkpoint_request_fields,
|
|
181
|
-
_checkpoint_file,
|
|
182
|
-
_approval_journal,
|
|
183
|
-
_remove_checkpoint_temporary,
|
|
184
|
-
_converge_checkpoint_file,
|
|
185
|
-
_unlink_checkpoint_journal,
|
|
186
|
-
_resume_checkpoint_locked,
|
|
187
|
-
checkpoint_approval,
|
|
188
|
-
_checkpoint_deferral_error,
|
|
189
|
-
defer_approval,
|
|
190
|
-
resume_checkpoint,
|
|
191
|
-
_task_files,
|
|
192
|
-
_approval_checkpoint,
|
|
193
|
-
_validate_approval_track,
|
|
194
|
-
_safe_declared_paths,
|
|
195
|
-
_git_text_at,
|
|
196
|
-
_approved_task_contracts,
|
|
197
|
-
_task_contracts_at,
|
|
198
|
-
_classify_plan_drift,
|
|
199
|
-
)
|
|
200
|
-
from .state_promote import (
|
|
201
|
-
_render_roadmap,
|
|
202
|
-
_promotion_event,
|
|
203
|
-
_promotion_state,
|
|
204
|
-
_head_with_exact_message,
|
|
205
|
-
_tree_entries,
|
|
206
|
-
_promotion_tree_mapping,
|
|
207
|
-
_completed_promotion,
|
|
208
|
-
_prepare_promotion,
|
|
209
|
-
_require_journal_request,
|
|
210
|
-
_resume_track_moves,
|
|
211
|
-
_resume_metadata,
|
|
212
|
-
_resume_next_removal,
|
|
213
|
-
_commit_promotion,
|
|
214
|
-
promote_next,
|
|
215
|
-
)
|
|
216
|
-
else: # standalone script or sibling import
|
|
217
|
-
if __name__ == "__main__":
|
|
218
|
-
sys.modules.setdefault("pipeline_state", sys.modules[__name__])
|
|
219
|
-
from state_checkpoint import (
|
|
220
|
-
_sha256,
|
|
221
|
-
_tree_digest,
|
|
222
|
-
_checkpoint_artifact_digest,
|
|
223
|
-
_roadmap_status,
|
|
224
|
-
_activate_roadmap_milestone,
|
|
225
|
-
_approval_details,
|
|
226
|
-
_checkpoint_request_fields,
|
|
227
|
-
_checkpoint_file,
|
|
228
|
-
_approval_journal,
|
|
229
|
-
_remove_checkpoint_temporary,
|
|
230
|
-
_converge_checkpoint_file,
|
|
231
|
-
_unlink_checkpoint_journal,
|
|
232
|
-
_resume_checkpoint_locked,
|
|
233
|
-
checkpoint_approval,
|
|
234
|
-
_checkpoint_deferral_error,
|
|
235
|
-
defer_approval,
|
|
236
|
-
resume_checkpoint,
|
|
237
|
-
_task_files,
|
|
238
|
-
_approval_checkpoint,
|
|
239
|
-
_validate_approval_track,
|
|
240
|
-
_safe_declared_paths,
|
|
241
|
-
_git_text_at,
|
|
242
|
-
_approved_task_contracts,
|
|
243
|
-
_task_contracts_at,
|
|
244
|
-
_classify_plan_drift,
|
|
245
|
-
)
|
|
246
|
-
from state_promote import (
|
|
247
|
-
_render_roadmap,
|
|
248
|
-
_promotion_event,
|
|
249
|
-
_promotion_state,
|
|
250
|
-
_head_with_exact_message,
|
|
251
|
-
_tree_entries,
|
|
252
|
-
_promotion_tree_mapping,
|
|
253
|
-
_completed_promotion,
|
|
254
|
-
_prepare_promotion,
|
|
255
|
-
_require_journal_request,
|
|
256
|
-
_resume_track_moves,
|
|
257
|
-
_resume_metadata,
|
|
258
|
-
_resume_next_removal,
|
|
259
|
-
_commit_promotion,
|
|
260
|
-
promote_next,
|
|
261
|
-
)
|
|
171
|
+
# Standalone transaction imports must reuse this state module and its types.
|
|
172
|
+
if __name__ == "__main__":
|
|
173
|
+
sys.modules.setdefault("pipeline_state", sys.modules[__name__])
|
|
174
|
+
|
|
262
175
|
|
|
263
176
|
def _run_git(
|
|
264
177
|
repo: Path,
|
|
@@ -693,6 +606,21 @@ def _next_skill(route: Mapping[str, object]) -> Optional[str]:
|
|
|
693
606
|
return None
|
|
694
607
|
|
|
695
608
|
|
|
609
|
+
def _completion_status(repo: Path, state: Mapping[str, object], project_dir: str) -> dict:
|
|
610
|
+
if project_dir != ".project" or state.get("phase") != "shipped":
|
|
611
|
+
return {"status": "not-shipped"}
|
|
612
|
+
if __package__:
|
|
613
|
+
from . import integration
|
|
614
|
+
else:
|
|
615
|
+
import integration
|
|
616
|
+
try:
|
|
617
|
+
proof = integration.validate_integrated(
|
|
618
|
+
repo, str(state.get("milestone") or ""), refresh=False)
|
|
619
|
+
except (integration.ArchiveError, OSError) as error:
|
|
620
|
+
return {"status": "unverified", "reason": str(error)}
|
|
621
|
+
return {"status": "verified", "proof": proof}
|
|
622
|
+
|
|
623
|
+
|
|
696
624
|
def status_state(repo: Path, project_dir: str = ".project") -> dict[str, object]:
|
|
697
625
|
"""Report owned state, route, and git facts without advancing a phase."""
|
|
698
626
|
resolved = _repo_root(repo)
|
|
@@ -726,9 +654,11 @@ def status_state(repo: Path, project_dir: str = ".project") -> dict[str, object]
|
|
|
726
654
|
"undo": None,
|
|
727
655
|
"collect_artifact": None,
|
|
728
656
|
}
|
|
657
|
+
completion = _completion_status(resolved, state, project_dir)
|
|
729
658
|
return {
|
|
730
659
|
"schema": STATUS_SCHEMA,
|
|
731
660
|
"advance": False,
|
|
661
|
+
"completion": completion,
|
|
732
662
|
"state": state,
|
|
733
663
|
"route": route,
|
|
734
664
|
"path": str(_track_root(resolved, project_dir) / "STATE.md"),
|
|
@@ -753,6 +683,28 @@ def status_state(repo: Path, project_dir: str = ".project") -> dict[str, object]
|
|
|
753
683
|
"lookahead": lookahead.exists() or lookahead.is_symlink(),
|
|
754
684
|
"journals": journals,
|
|
755
685
|
"next_skill": _next_skill(route if isinstance(route, dict) else {}),
|
|
686
|
+
"handoff": phase_handoff(state, route, _track_root(resolved, project_dir) / "STATE.md", completion),
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
|
|
690
|
+
def phase_handoff(state: Mapping[str, object], route: Mapping[str, object], path: Path,
|
|
691
|
+
completion: Mapping[str, object]) -> dict[str, str]:
|
|
692
|
+
"""Present the authoritative route without granting continuation authority."""
|
|
693
|
+
action = route["action"]
|
|
694
|
+
if action == "run-phase":
|
|
695
|
+
next_action = f"Invoke $gsd-path to continue with {route['phase']}."
|
|
696
|
+
router_next = f"Continue with {route['phase']}; honor its input and approval gates."
|
|
697
|
+
else:
|
|
698
|
+
next_action = router_next = f"{action}: {route['reason']}"
|
|
699
|
+
outcome = f"{state['phase']}/{state['status']}"
|
|
700
|
+
if completion["status"] == "unverified":
|
|
701
|
+
outcome = f"Unverified: {outcome}"
|
|
702
|
+
return {
|
|
703
|
+
"outcome": outcome,
|
|
704
|
+
"review": str(path),
|
|
705
|
+
"next": next_action,
|
|
706
|
+
"phase_next": next_action,
|
|
707
|
+
"router_next": router_next,
|
|
756
708
|
}
|
|
757
709
|
|
|
758
710
|
|
|
@@ -784,50 +736,11 @@ def _intent_lane(track: Path) -> Optional[str]:
|
|
|
784
736
|
|
|
785
737
|
|
|
786
738
|
def _active_roadmap_has_questions(project: Path, milestone: Optional[str] = None) -> bool:
|
|
787
|
-
"""Report open questions for the active entry, or for ``milestone`` when given."""
|
|
788
739
|
text = _read_real_file(project / "ROADMAP.md", "ROADMAP.md")
|
|
789
|
-
lines = text.splitlines()
|
|
790
|
-
active_section: Optional[list[str]] = None
|
|
791
|
-
for index, line in enumerate(lines):
|
|
792
|
-
heading = ROADMAP_HEADING_RE.fullmatch(line)
|
|
793
|
-
if heading is None:
|
|
794
|
-
continue
|
|
795
|
-
if int(heading.group(1).removeprefix("M")) < 1:
|
|
796
|
-
raise PipelineStateError(
|
|
797
|
-
f"ROADMAP.md has invalid milestone id: {heading.group(1)}"
|
|
798
|
-
)
|
|
799
|
-
end = next(
|
|
800
|
-
(
|
|
801
|
-
cursor
|
|
802
|
-
for cursor in range(index + 1, len(lines))
|
|
803
|
-
if ROADMAP_HEADING_RE.fullmatch(lines[cursor]) is not None
|
|
804
|
-
),
|
|
805
|
-
len(lines),
|
|
806
|
-
)
|
|
807
|
-
section = lines[index:end]
|
|
808
|
-
if milestone is not None:
|
|
809
|
-
if heading.group(2) == milestone:
|
|
810
|
-
active_section = section
|
|
811
|
-
continue
|
|
812
|
-
if any(re.fullmatch(r"Status:\s*active(?:\s+#.*)?", item) for item in section):
|
|
813
|
-
if active_section is not None:
|
|
814
|
-
raise PipelineStateError("ROADMAP.md has more than one active milestone")
|
|
815
|
-
active_section = section
|
|
816
|
-
if active_section is None:
|
|
817
|
-
if milestone is not None:
|
|
818
|
-
raise PipelineStateError(f"ROADMAP.md is missing lookahead milestone: {milestone}")
|
|
819
|
-
raise PipelineStateError("ROADMAP.md has no active milestone")
|
|
820
740
|
try:
|
|
821
|
-
|
|
822
|
-
except
|
|
823
|
-
raise PipelineStateError(
|
|
824
|
-
questions = [
|
|
825
|
-
line[2:].strip()
|
|
826
|
-
for line in active_section[start:]
|
|
827
|
-
if line.startswith("- ")
|
|
828
|
-
]
|
|
829
|
-
return any(question.lower() != "none" for question in questions)
|
|
830
|
-
|
|
741
|
+
return roadmap.has_questions(text, milestone)
|
|
742
|
+
except roadmap.RoadmapError as error:
|
|
743
|
+
raise PipelineStateError(str(error)) from error
|
|
831
744
|
|
|
832
745
|
def _valid_patch_findings(repo: Path) -> bool:
|
|
833
746
|
validator = Path(__file__).resolve().with_name("check_handoffs.py")
|
|
@@ -1106,6 +1019,14 @@ def route_state(repo: Path, project_dir: str = ".project") -> dict[str, object]:
|
|
|
1106
1019
|
"""Route ordinary phase work only when its pending discussion owner can enter."""
|
|
1107
1020
|
result = _route_state(repo, project_dir)
|
|
1108
1021
|
route = result["route"]
|
|
1022
|
+
if project_dir == ".project" and route["action"] == "run-phase":
|
|
1023
|
+
recovery = _build_recovery().context(_repo_root(repo))
|
|
1024
|
+
if recovery and recovery["active"]:
|
|
1025
|
+
result["recovery"] = recovery
|
|
1026
|
+
if route.get("phase") == "define":
|
|
1027
|
+
route["mode"] = "corrections"
|
|
1028
|
+
elif route.get("phase") == "plan":
|
|
1029
|
+
route["mode"] = "build-repair"
|
|
1109
1030
|
if route["action"] == "run-phase" and result["state"]["archive"] is None:
|
|
1110
1031
|
reason = _pending_discussion_block(_repo_root(repo), route.get("phase"))
|
|
1111
1032
|
if reason:
|
|
@@ -1159,7 +1080,11 @@ def _route_state(repo: Path, project_dir: str = ".project") -> dict[str, object]
|
|
|
1159
1080
|
return result
|
|
1160
1081
|
checkpoint_journal = _git_path(resolved, CHECKPOINT_JOURNAL_NAME)
|
|
1161
1082
|
if checkpoint_journal.exists() or checkpoint_journal.is_symlink():
|
|
1162
|
-
|
|
1083
|
+
if __package__:
|
|
1084
|
+
from . import state_checkpoint
|
|
1085
|
+
else:
|
|
1086
|
+
import state_checkpoint
|
|
1087
|
+
transaction = state_checkpoint._approval_journal(
|
|
1163
1088
|
resolved,
|
|
1164
1089
|
_read_json(checkpoint_journal),
|
|
1165
1090
|
)
|
|
@@ -1736,6 +1661,16 @@ def transition_state(
|
|
|
1736
1661
|
event,
|
|
1737
1662
|
project_dir,
|
|
1738
1663
|
)
|
|
1664
|
+
recovery_context = _build_recovery().context(resolved, text) if project_dir == ".project" else None
|
|
1665
|
+
if recovery_context and recovery_context["active"]:
|
|
1666
|
+
if (state.milestone, state.branch, state.archive) != (after.milestone, after.branch, after.archive):
|
|
1667
|
+
raise PipelineStateError("build recovery must preserve milestone identity")
|
|
1668
|
+
if state.phase == "build" and after.phase in {"define", "plan"}:
|
|
1669
|
+
recovery = _build_recovery().begin(resolved, state, after, event)
|
|
1670
|
+
rendered = _append_event(
|
|
1671
|
+
rendered, after.phase,
|
|
1672
|
+
_build_recovery().MARKER + json.dumps(recovery, sort_keys=True),
|
|
1673
|
+
)
|
|
1739
1674
|
if after.status != "blocked":
|
|
1740
1675
|
reason = _pending_discussion_block(
|
|
1741
1676
|
resolved, after.phase if after.status == "active" else None
|
|
@@ -1767,6 +1702,14 @@ def transition_state(
|
|
|
1767
1702
|
}
|
|
1768
1703
|
|
|
1769
1704
|
|
|
1705
|
+
def _build_recovery():
|
|
1706
|
+
if __package__:
|
|
1707
|
+
from scripts import build_recovery
|
|
1708
|
+
else:
|
|
1709
|
+
import build_recovery
|
|
1710
|
+
return build_recovery
|
|
1711
|
+
|
|
1712
|
+
|
|
1770
1713
|
def configure_integration(
|
|
1771
1714
|
repo: Path,
|
|
1772
1715
|
scope: str,
|
|
@@ -1786,7 +1729,9 @@ def configure_integration(
|
|
|
1786
1729
|
project = _track_root(resolved, project_dir)
|
|
1787
1730
|
with _state_lock(project):
|
|
1788
1731
|
state, text, path = load_state(resolved, project_dir)
|
|
1789
|
-
if state.phase in {"build", "ship", "shipped"}
|
|
1732
|
+
if state.phase in {"build", "ship", "shipped"} or (
|
|
1733
|
+
project_dir == ".project" and _build_recovery().context(resolved, text)
|
|
1734
|
+
):
|
|
1790
1735
|
raise PipelineStateError("integration mode is locked when build starts")
|
|
1791
1736
|
if scope == "default":
|
|
1792
1737
|
integration = (
|
|
@@ -2022,49 +1967,18 @@ def _render_transition(
|
|
|
2022
1967
|
|
|
2023
1968
|
|
|
2024
1969
|
def _roadmap_sections(text: str) -> dict[str, tuple[str, int, int]]:
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
if match:
|
|
2030
|
-
if int(match.group(1).removeprefix("M")) < 1:
|
|
2031
|
-
raise PipelineStateError(f"ROADMAP.md has invalid milestone id: {match.group(1)}")
|
|
2032
|
-
headings.append((match.group(1), match.group(2), index))
|
|
2033
|
-
sections: dict[str, tuple[str, int, int]] = {}
|
|
2034
|
-
for position, (milestone_id, slug, start) in enumerate(headings):
|
|
2035
|
-
end = headings[position + 1][2] if position + 1 < len(headings) else len(lines)
|
|
2036
|
-
if slug in sections:
|
|
2037
|
-
raise PipelineStateError(f"ROADMAP.md repeats milestone slug: {slug}")
|
|
2038
|
-
sections[slug] = (milestone_id, start, end)
|
|
2039
|
-
return sections
|
|
2040
|
-
|
|
1970
|
+
try:
|
|
1971
|
+
return roadmap.strict_sections(text)
|
|
1972
|
+
except roadmap.RoadmapError as error:
|
|
1973
|
+
raise PipelineStateError(str(error)) from error
|
|
2041
1974
|
|
|
2042
1975
|
def _replace_roadmap_field(
|
|
2043
|
-
lines: list[str],
|
|
2044
|
-
start: int,
|
|
2045
|
-
end: int,
|
|
2046
|
-
field: str,
|
|
2047
|
-
expected: set[str],
|
|
2048
|
-
value: str,
|
|
1976
|
+
lines: list[str], start: int, end: int, field: str, expected: set[str], value: str,
|
|
2049
1977
|
) -> None:
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
match = re.match(rf"^({re.escape(field)}:\s*)(\S+)(.*)$", raw)
|
|
2055
|
-
if match is None:
|
|
2056
|
-
continue
|
|
2057
|
-
if found is not None:
|
|
2058
|
-
raise PipelineStateError(f"ROADMAP.md repeats {field} in one milestone")
|
|
2059
|
-
if match.group(2) not in expected:
|
|
2060
|
-
raise PipelineStateError(
|
|
2061
|
-
f"ROADMAP.md {field} is {match.group(2)}, expected {sorted(expected)}"
|
|
2062
|
-
)
|
|
2063
|
-
lines[index] = f"{match.group(1)}{value}{match.group(3)}{ending}"
|
|
2064
|
-
found = index
|
|
2065
|
-
if found is None:
|
|
2066
|
-
raise PipelineStateError(f"ROADMAP.md milestone is missing {field}")
|
|
2067
|
-
|
|
1978
|
+
try:
|
|
1979
|
+
return roadmap.replace_field(lines, start, end, field, expected, value)
|
|
1980
|
+
except roadmap.RoadmapError as error:
|
|
1981
|
+
raise PipelineStateError(str(error)) from error
|
|
2068
1982
|
|
|
2069
1983
|
def _git_path(repo: Path, name: str) -> Path:
|
|
2070
1984
|
value = _run_git(repo, "rev-parse", "--git-path", name).stdout.strip()
|
|
@@ -2163,7 +2077,7 @@ def _specified_fields(arguments: argparse.Namespace, prefix: str) -> dict[str, O
|
|
|
2163
2077
|
def parse_args(argv: Optional[Sequence[str]] = None) -> argparse.Namespace:
|
|
2164
2078
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
2165
2079
|
subparsers = parser.add_subparsers(dest="command", required=True)
|
|
2166
|
-
for command in ("validate", "route", "status"):
|
|
2080
|
+
for command in ("validate", "route", "status", "prepare-build-recovery"):
|
|
2167
2081
|
subparser = subparsers.add_parser(command)
|
|
2168
2082
|
subparser.add_argument("--repo", required=True, type=Path)
|
|
2169
2083
|
subparser.add_argument("--project-dir", default=".project")
|
|
@@ -2204,6 +2118,16 @@ def parse_args(argv: Optional[Sequence[str]] = None) -> argparse.Namespace:
|
|
|
2204
2118
|
|
|
2205
2119
|
def main(argv: Optional[Sequence[str]] = None) -> int:
|
|
2206
2120
|
args = parse_args(argv)
|
|
2121
|
+
if args.command in {"approve", "resume-checkpoint"}:
|
|
2122
|
+
if __package__:
|
|
2123
|
+
from . import state_checkpoint
|
|
2124
|
+
else:
|
|
2125
|
+
import state_checkpoint
|
|
2126
|
+
elif args.command == "promote-next":
|
|
2127
|
+
if __package__:
|
|
2128
|
+
from . import state_promote
|
|
2129
|
+
else:
|
|
2130
|
+
import state_promote
|
|
2207
2131
|
try:
|
|
2208
2132
|
if args.command == "validate":
|
|
2209
2133
|
result = validate_state(args.repo, args.project_dir)
|
|
@@ -2211,6 +2135,10 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
|
|
|
2211
2135
|
result = route_state(args.repo, args.project_dir)
|
|
2212
2136
|
elif args.command == "status":
|
|
2213
2137
|
result = status_state(args.repo, args.project_dir)
|
|
2138
|
+
elif args.command == "prepare-build-recovery":
|
|
2139
|
+
if args.project_dir != ".project":
|
|
2140
|
+
raise PipelineStateError("build recovery requires the active track")
|
|
2141
|
+
result = _build_recovery().prepare(args.repo)
|
|
2214
2142
|
elif args.command == "transition":
|
|
2215
2143
|
result = transition_state(
|
|
2216
2144
|
args.repo,
|
|
@@ -2224,7 +2152,7 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
|
|
|
2224
2152
|
raise PipelineStateError(
|
|
2225
2153
|
"--expected-head is not accepted with --defer-checkpoint or --patch"
|
|
2226
2154
|
)
|
|
2227
|
-
result = defer_approval(
|
|
2155
|
+
result = state_checkpoint.defer_approval(
|
|
2228
2156
|
args.repo,
|
|
2229
2157
|
args.kind,
|
|
2230
2158
|
args.project_dir,
|
|
@@ -2236,7 +2164,7 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
|
|
|
2236
2164
|
raise PipelineStateError(
|
|
2237
2165
|
"approve requires --expected-head unless --defer-checkpoint or --patch"
|
|
2238
2166
|
)
|
|
2239
|
-
result = checkpoint_approval(
|
|
2167
|
+
result = state_checkpoint.checkpoint_approval(
|
|
2240
2168
|
args.repo,
|
|
2241
2169
|
args.kind,
|
|
2242
2170
|
args.expected_head,
|
|
@@ -2244,7 +2172,7 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
|
|
|
2244
2172
|
args.milestone,
|
|
2245
2173
|
)
|
|
2246
2174
|
elif args.command == "resume-checkpoint":
|
|
2247
|
-
result = resume_checkpoint(args.repo)
|
|
2175
|
+
result = state_checkpoint.resume_checkpoint(args.repo)
|
|
2248
2176
|
elif args.command == "promote-next":
|
|
2249
2177
|
if args.integrate is not None and (
|
|
2250
2178
|
args.base is not None or args.landing is not None
|
|
@@ -2262,7 +2190,7 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
|
|
|
2262
2190
|
raise PipelineStateError(
|
|
2263
2191
|
"promote-next requires --base or legacy --integrate"
|
|
2264
2192
|
)
|
|
2265
|
-
result = promote_next(
|
|
2193
|
+
result = state_promote.promote_next(
|
|
2266
2194
|
args.repo,
|
|
2267
2195
|
args.milestone,
|
|
2268
2196
|
args.branch,
|