@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
|
@@ -11,6 +11,31 @@ from pathlib import Path, PurePosixPath
|
|
|
11
11
|
from typing import Mapping, Optional
|
|
12
12
|
|
|
13
13
|
|
|
14
|
+
if __package__: # imported as scripts.state_promote
|
|
15
|
+
from . import pipeline_state, state_checkpoint
|
|
16
|
+
from .pipeline_state import (
|
|
17
|
+
NULL,
|
|
18
|
+
PROMOTION_RESIDUAL,
|
|
19
|
+
PROMOTION_SCHEMA,
|
|
20
|
+
PROMOTION_TRACKS,
|
|
21
|
+
SLUG_RE,
|
|
22
|
+
PipelineState,
|
|
23
|
+
PipelineStateError,
|
|
24
|
+
)
|
|
25
|
+
else: # standalone script or sibling import
|
|
26
|
+
import pipeline_state
|
|
27
|
+
import state_checkpoint
|
|
28
|
+
from pipeline_state import (
|
|
29
|
+
NULL,
|
|
30
|
+
PROMOTION_RESIDUAL,
|
|
31
|
+
PROMOTION_SCHEMA,
|
|
32
|
+
PROMOTION_TRACKS,
|
|
33
|
+
SLUG_RE,
|
|
34
|
+
PipelineState,
|
|
35
|
+
PipelineStateError,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
|
|
14
39
|
def _render_roadmap(
|
|
15
40
|
text: str,
|
|
16
41
|
previous_milestone: str,
|
|
@@ -243,9 +268,9 @@ def _completed_promotion(
|
|
|
243
268
|
if _head_with_exact_message(repo, subject, fields) != head:
|
|
244
269
|
raise PipelineStateError("completed promotion has the wrong commit message")
|
|
245
270
|
|
|
246
|
-
active_text =
|
|
247
|
-
next_text =
|
|
248
|
-
roadmap_text =
|
|
271
|
+
active_text = state_checkpoint._git_text_at(repo, base, ".project/STATE.md")
|
|
272
|
+
next_text = state_checkpoint._git_text_at(repo, base, ".project/next/STATE.md")
|
|
273
|
+
roadmap_text = state_checkpoint._git_text_at(repo, base, ".project/ROADMAP.md")
|
|
249
274
|
if active_text is None or next_text is None or roadmap_text is None:
|
|
250
275
|
raise PipelineStateError("promotion parent is missing required metadata")
|
|
251
276
|
active_state = pipeline_state._state_from_text(active_text, "promotion parent STATE.md")
|
|
@@ -265,7 +290,7 @@ def _completed_promotion(
|
|
|
265
290
|
)
|
|
266
291
|
|
|
267
292
|
_promotion_tree_mapping(repo, base, head)
|
|
268
|
-
drift =
|
|
293
|
+
drift = state_checkpoint._classify_plan_drift(repo, next_state, base, landing)
|
|
269
294
|
expected_roadmap = _render_roadmap(
|
|
270
295
|
roadmap_text,
|
|
271
296
|
active_state.milestone,
|
|
@@ -273,11 +298,11 @@ def _completed_promotion(
|
|
|
273
298
|
branch,
|
|
274
299
|
landing,
|
|
275
300
|
)
|
|
276
|
-
current_roadmap =
|
|
301
|
+
current_roadmap = state_checkpoint._git_text_at(repo, head, ".project/ROADMAP.md")
|
|
277
302
|
if current_roadmap != expected_roadmap:
|
|
278
303
|
raise PipelineStateError("completed promotion has invalid ROADMAP.md")
|
|
279
304
|
|
|
280
|
-
current_state =
|
|
305
|
+
current_state = state_checkpoint._git_text_at(repo, head, ".project/STATE.md")
|
|
281
306
|
if current_state is None:
|
|
282
307
|
raise PipelineStateError("completed promotion has no STATE.md")
|
|
283
308
|
event = re.escape(_promotion_event(drift, branch, landing, base))
|
|
@@ -438,10 +463,10 @@ def _prepare_promotion(
|
|
|
438
463
|
if source.exists() or source.is_symlink():
|
|
439
464
|
if destination.exists() or destination.is_symlink():
|
|
440
465
|
raise PipelineStateError(f"promotion destination already exists: {destination}")
|
|
441
|
-
tracks[name] =
|
|
466
|
+
tracks[name] = state_checkpoint._tree_digest(source)
|
|
442
467
|
if not tracks:
|
|
443
468
|
raise PipelineStateError("lookahead track has no promotable artifacts")
|
|
444
|
-
drift =
|
|
469
|
+
drift = state_checkpoint._classify_plan_drift(repo, next_state, base, landing)
|
|
445
470
|
roadmap_path = project / "ROADMAP.md"
|
|
446
471
|
roadmap_text = pipeline_state._read_real_file(roadmap_path, "ROADMAP.md")
|
|
447
472
|
target_state = _promotion_state(
|
|
@@ -464,10 +489,10 @@ def _prepare_promotion(
|
|
|
464
489
|
"landing": landing,
|
|
465
490
|
"base": base,
|
|
466
491
|
"tracks": tracks,
|
|
467
|
-
"residual_sha256":
|
|
468
|
-
"next_state_sha256":
|
|
469
|
-
"active_state_sha256":
|
|
470
|
-
"roadmap_sha256":
|
|
492
|
+
"residual_sha256": state_checkpoint._tree_digest(next_root, tuple(tracks)),
|
|
493
|
+
"next_state_sha256": state_checkpoint._sha256(next_text),
|
|
494
|
+
"active_state_sha256": state_checkpoint._sha256(active_text),
|
|
495
|
+
"roadmap_sha256": state_checkpoint._sha256(roadmap_text),
|
|
471
496
|
"target_state": target_state,
|
|
472
497
|
"target_roadmap": target_roadmap,
|
|
473
498
|
"drift": drift,
|
|
@@ -521,7 +546,7 @@ def _resume_track_moves(project: Path, journal: dict[str, object], path: Path) -
|
|
|
521
546
|
if not source_exists and not destination_exists:
|
|
522
547
|
raise PipelineStateError(f"promotion lost both source and destination: {name}")
|
|
523
548
|
candidate = source if source_exists else destination
|
|
524
|
-
if
|
|
549
|
+
if state_checkpoint._tree_digest(candidate) != expected_digest:
|
|
525
550
|
raise PipelineStateError(f"promotion track drifted: {name}")
|
|
526
551
|
if source_exists:
|
|
527
552
|
source.rename(destination)
|
|
@@ -542,7 +567,7 @@ def _resume_metadata(project: Path, journal: dict[str, object], path: Path) -> N
|
|
|
542
567
|
raise PipelineStateError("promotion journal has invalid metadata")
|
|
543
568
|
if current == desired:
|
|
544
569
|
continue
|
|
545
|
-
if
|
|
570
|
+
if state_checkpoint._sha256(current) != expected_original:
|
|
546
571
|
raise PipelineStateError(f"promotion metadata drifted: {target}")
|
|
547
572
|
pipeline_state._atomic_write(target, desired)
|
|
548
573
|
journal["stage"] = f"updated:{target.name}"
|
|
@@ -560,9 +585,9 @@ def _resume_next_removal(
|
|
|
560
585
|
if residual.exists() or residual.is_symlink():
|
|
561
586
|
raise PipelineStateError("promotion has both next track and residual staging")
|
|
562
587
|
next_text = pipeline_state._read_real_file(next_root / "STATE.md", "next/STATE.md")
|
|
563
|
-
if
|
|
588
|
+
if state_checkpoint._sha256(next_text) != journal.get("next_state_sha256"):
|
|
564
589
|
raise PipelineStateError("lookahead STATE drifted during promotion")
|
|
565
|
-
if
|
|
590
|
+
if state_checkpoint._tree_digest(next_root) != journal.get("residual_sha256"):
|
|
566
591
|
raise PipelineStateError("lookahead residual drifted during promotion")
|
|
567
592
|
next_root.rename(residual)
|
|
568
593
|
journal["stage"] = "next-staged"
|
|
@@ -574,7 +599,7 @@ def _resume_next_removal(
|
|
|
574
599
|
raise PipelineStateError("promotion lost next track and residual staging")
|
|
575
600
|
if residual.is_symlink() or not residual.is_dir():
|
|
576
601
|
raise PipelineStateError(f"promotion residual must be a real directory: {residual}")
|
|
577
|
-
if
|
|
602
|
+
if state_checkpoint._tree_digest(residual) != journal.get("residual_sha256"):
|
|
578
603
|
raise PipelineStateError("staged lookahead residual drifted during promotion")
|
|
579
604
|
|
|
580
605
|
|
|
@@ -714,30 +739,3 @@ def promote_next(
|
|
|
714
739
|
"commit": commit,
|
|
715
740
|
"drift": journal["drift"],
|
|
716
741
|
}
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
# pipeline_state imports this module, so the parent is resolved after the
|
|
720
|
-
# definitions above. Parent functions are looked up on the module at call time
|
|
721
|
-
# so patches applied to pipeline_state stay visible here.
|
|
722
|
-
if __package__: # imported as scripts.state_promote
|
|
723
|
-
from . import pipeline_state
|
|
724
|
-
from .pipeline_state import (
|
|
725
|
-
NULL,
|
|
726
|
-
PROMOTION_RESIDUAL,
|
|
727
|
-
PROMOTION_SCHEMA,
|
|
728
|
-
PROMOTION_TRACKS,
|
|
729
|
-
SLUG_RE,
|
|
730
|
-
PipelineState,
|
|
731
|
-
PipelineStateError,
|
|
732
|
-
)
|
|
733
|
-
else: # standalone script or sibling import
|
|
734
|
-
import pipeline_state
|
|
735
|
-
from pipeline_state import (
|
|
736
|
-
NULL,
|
|
737
|
-
PROMOTION_RESIDUAL,
|
|
738
|
-
PROMOTION_SCHEMA,
|
|
739
|
-
PROMOTION_TRACKS,
|
|
740
|
-
SLUG_RE,
|
|
741
|
-
PipelineState,
|
|
742
|
-
PipelineStateError,
|
|
743
|
-
)
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Render a read-only coder intent view from the approved task and intent."""
|
|
3
|
+
|
|
4
|
+
import argparse
|
|
5
|
+
import hashlib
|
|
6
|
+
import re
|
|
7
|
+
import sys
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
try:
|
|
11
|
+
from scripts import check_handoffs as contracts
|
|
12
|
+
except ImportError:
|
|
13
|
+
import check_handoffs as contracts
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def render(repo: Path, task: Path) -> str:
|
|
17
|
+
intent_path = repo.resolve() / '.project/intent/INTENT.md'
|
|
18
|
+
task = task.resolve()
|
|
19
|
+
intent = intent_path.read_bytes().decode('utf-8')
|
|
20
|
+
task_text = task.read_bytes().decode('utf-8')
|
|
21
|
+
owned = contracts._owned_criteria(task_text, task.stem)
|
|
22
|
+
criteria = contracts._success_criteria(intent)
|
|
23
|
+
unknown = set(owned) - set(criteria)
|
|
24
|
+
if unknown:
|
|
25
|
+
raise contracts.HandoffError('unknown owned criteria: ' + ', '.join(sorted(unknown)))
|
|
26
|
+
projected, mode = intent, 'full-intent'
|
|
27
|
+
sections = list(re.finditer(r'(?ms)^## Success criteria[ \t]*\n(?P<body>.*?)(?=^## |\Z)', intent))
|
|
28
|
+
if len(sections) == 1:
|
|
29
|
+
section = sections[0]
|
|
30
|
+
body = section['body']
|
|
31
|
+
items = list(re.finditer(r'(?m)^(\d+)\. .+\n?', body))
|
|
32
|
+
# Project only simple numbered prose. Preserve unfamiliar Markdown in full.
|
|
33
|
+
simple = (items and not body[:items[0].start()].strip()
|
|
34
|
+
and '```' not in body and '~~~' not in body and '<!--' not in body
|
|
35
|
+
and [f'SC{item[1]}' for item in items] == list(criteria))
|
|
36
|
+
chunks = [body[item.start():items[n + 1].start() if n + 1 < len(items) else len(body)]
|
|
37
|
+
for n, item in enumerate(items)]
|
|
38
|
+
simple = simple and all(not line.strip() or line[:1].isspace()
|
|
39
|
+
for chunk in chunks for line in chunk.splitlines()[1:])
|
|
40
|
+
if simple:
|
|
41
|
+
before, after = intent[:section.start('body')], intent[section.end('body'):]
|
|
42
|
+
# Corrections and task interfaces can explicitly refer to another SC.
|
|
43
|
+
required = set(owned) | set(re.findall(r'\bSC\d+\b', before + after + task_text))
|
|
44
|
+
selected = ''.join(chunk for item, chunk in zip(items, chunks) if f'SC{item[1]}' in required)
|
|
45
|
+
projected = before + '\n' + (selected or '- No criteria assigned.\n\n') + after
|
|
46
|
+
mode = 'owned-criteria'
|
|
47
|
+
return ('## Generated intent context\n\n'
|
|
48
|
+
f'Source: {intent_path}\n'
|
|
49
|
+
f'Intent SHA256: {hashlib.sha256(intent.encode()).hexdigest()}\n'
|
|
50
|
+
f'Task: {task}\n'
|
|
51
|
+
f'Task SHA256: {hashlib.sha256(task_text.encode()).hexdigest()}\n'
|
|
52
|
+
f'Mode: {mode}\n\n'
|
|
53
|
+
'Use this view for intent. All non-criterion text is verbatim; selected criteria retain '
|
|
54
|
+
'their original numbers. The source remains authoritative. Read it if a dependency '
|
|
55
|
+
'or ambiguity requires omitted criteria.\n\n' + projected)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def main() -> int:
|
|
59
|
+
parser = argparse.ArgumentParser(description=__doc__)
|
|
60
|
+
parser.add_argument('--repo', type=Path, required=True)
|
|
61
|
+
parser.add_argument('--task', type=Path, required=True)
|
|
62
|
+
args = parser.parse_args()
|
|
63
|
+
try:
|
|
64
|
+
output = render(args.repo, args.task)
|
|
65
|
+
except (OSError, contracts.HandoffError) as error:
|
|
66
|
+
print(str(error), file=sys.stderr)
|
|
67
|
+
return 1
|
|
68
|
+
print(output, end='')
|
|
69
|
+
return 0
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
if __name__ == '__main__':
|
|
73
|
+
raise SystemExit(main())
|
|
@@ -69,6 +69,24 @@ def output_usage(path: Path) -> int:
|
|
|
69
69
|
return sum(usages)
|
|
70
70
|
|
|
71
71
|
|
|
72
|
+
def cumulative_counter(path: Path):
|
|
73
|
+
"""One completed CLI invocation, with the thread identity needed for resume."""
|
|
74
|
+
identities, counters = set(), []
|
|
75
|
+
for line in path.read_text(encoding="utf-8").splitlines():
|
|
76
|
+
event = json.loads(line)
|
|
77
|
+
if "raw" in event:
|
|
78
|
+
event = json.loads(event["raw"])
|
|
79
|
+
if event.get("type") == "thread.started":
|
|
80
|
+
identities.add(event["thread_id"])
|
|
81
|
+
if event.get("type") == "turn.completed":
|
|
82
|
+
counters.append(event["usage"]["output_tokens"])
|
|
83
|
+
if len(identities) != 1 or len(counters) != 1:
|
|
84
|
+
raise ValueError("cumulative usage requires one identified, completed CLI invocation")
|
|
85
|
+
if type(counters[0]) is not int or counters[0] < 0:
|
|
86
|
+
raise ValueError("invalid cumulative output counter")
|
|
87
|
+
return identities.pop(), counters[0]
|
|
88
|
+
|
|
89
|
+
|
|
72
90
|
def operate(args):
|
|
73
91
|
ledger = args.ledger.absolute()
|
|
74
92
|
if ledger.is_symlink():
|
|
@@ -92,9 +110,28 @@ def operate(args):
|
|
|
92
110
|
if args.action == "record":
|
|
93
111
|
source = str(args.events.resolve())
|
|
94
112
|
observation = {"task": args.task, "output_tokens": output_usage(args.events)}
|
|
113
|
+
prior_events = getattr(args, "previous_events", None)
|
|
114
|
+
if prior_events is not None:
|
|
115
|
+
prior_source = str(prior_events.resolve())
|
|
116
|
+
prior = data["observations"].get(prior_source)
|
|
117
|
+
identity, total = cumulative_counter(args.events)
|
|
118
|
+
prior_identity, prior_total = cumulative_counter(prior_events)
|
|
119
|
+
if source == prior_source or identity != prior_identity or total < prior_total:
|
|
120
|
+
raise ValueError("cumulative resume has a different thread or a reset counter")
|
|
121
|
+
if prior is None or prior.get("reported_output_tokens", prior["output_tokens"]) != prior_total:
|
|
122
|
+
raise ValueError("previous cumulative invocation must be recorded unchanged first")
|
|
123
|
+
if any(key != source and row.get("previous_events") == prior_source
|
|
124
|
+
for key, row in data["observations"].items()):
|
|
125
|
+
raise ValueError("previous cumulative invocation already has a recorded successor")
|
|
126
|
+
observation.update(output_tokens=total - prior_total, reported_output_tokens=total,
|
|
127
|
+
previous_events=prior_source, session_id=identity)
|
|
95
128
|
previous = data["observations"].get(source)
|
|
129
|
+
if previous and previous != observation and any(
|
|
130
|
+
row.get("previous_events") == source for row in data["observations"].values()):
|
|
131
|
+
raise ValueError("a cumulative predecessor cannot change after its successor is recorded")
|
|
96
132
|
if previous and (previous["task"] != args.task or
|
|
97
|
-
previous["output_tokens"] > observation["output_tokens"]
|
|
133
|
+
previous["output_tokens"] > observation["output_tokens"] or
|
|
134
|
+
previous.get("previous_events") != observation.get("previous_events")):
|
|
98
135
|
raise ValueError("observation cannot change task or reduce recorded usage")
|
|
99
136
|
data["observations"][source] = observation
|
|
100
137
|
atomic_write(ledger, json.dumps(data, indent=2) + "\n")
|
|
@@ -131,6 +168,8 @@ def main(argv=None):
|
|
|
131
168
|
command.add_argument("--task", required=True)
|
|
132
169
|
if name == "record":
|
|
133
170
|
command.add_argument("--events", type=Path, required=True)
|
|
171
|
+
command.add_argument("--previous-events", type=Path,
|
|
172
|
+
help="previous recorded invocation when this CLI reports cumulative resume counters")
|
|
134
173
|
if name == "admit":
|
|
135
174
|
command.add_argument("--require-hard-cap", action="store_true")
|
|
136
175
|
try:
|
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
"""Run canonical workflow helpers with fixed arguments and fail-stop receipts."""
|
|
3
3
|
|
|
4
4
|
import argparse
|
|
5
|
+
import hashlib
|
|
5
6
|
import json
|
|
6
7
|
import subprocess
|
|
7
8
|
import sys
|
|
9
|
+
import tempfile
|
|
8
10
|
from pathlib import Path
|
|
9
11
|
|
|
10
12
|
try:
|
|
@@ -16,13 +18,18 @@ except ImportError: # bundled copy inside a skill's scripts directory
|
|
|
16
18
|
class StepFailed(RuntimeError):
|
|
17
19
|
pass
|
|
18
20
|
|
|
21
|
+
INSPECTION_SPECS = (("inspect_codebase", "codebase-mapper", "codebase", "evidence-codebase.md"),
|
|
22
|
+
("inspect_docs", "docs-auditor", "docs-audit", "DOCS-AUDIT.md"))
|
|
23
|
+
|
|
19
24
|
|
|
20
25
|
def run_workflow(repo: Path, action: str, project_dir: str, expected_head: str = None,
|
|
21
|
-
task_id: str = None, round_size: int = None
|
|
26
|
+
task_id: str = None, round_size: int = None, inspection: Path = None,
|
|
27
|
+
mapper_reviewed: bool = False) -> dict:
|
|
22
28
|
steps = []
|
|
29
|
+
outputs = {}
|
|
23
30
|
scripts = Path(__file__).resolve().parent
|
|
24
31
|
|
|
25
|
-
def step(script, *arguments):
|
|
32
|
+
def step(script, *arguments, raw=False):
|
|
26
33
|
command = [sys.executable, "-B", str(scripts / script), *arguments]
|
|
27
34
|
completed = subprocess.run(command, cwd=repo, capture_output=True, text=True)
|
|
28
35
|
receipt = {"script": script, "command": command, "exit_code": completed.returncode,
|
|
@@ -32,6 +39,8 @@ def run_workflow(repo: Path, action: str, project_dir: str, expected_head: str =
|
|
|
32
39
|
sys.stderr.write(completed.stderr)
|
|
33
40
|
if completed.returncode:
|
|
34
41
|
raise StepFailed(script)
|
|
42
|
+
if raw:
|
|
43
|
+
return completed.stdout
|
|
35
44
|
try:
|
|
36
45
|
receipt["result"] = json.loads(completed.stdout)
|
|
37
46
|
except json.JSONDecodeError as error:
|
|
@@ -42,6 +51,103 @@ def run_workflow(repo: Path, action: str, project_dir: str, expected_head: str =
|
|
|
42
51
|
try:
|
|
43
52
|
if action == "route":
|
|
44
53
|
step("pipeline_state.py", "route", *common)
|
|
54
|
+
elif action == "prepare-inspect":
|
|
55
|
+
state = step("pipeline_state.py", "validate", *common)["state"]
|
|
56
|
+
if project_dir != ".project" or state["phase"] != "inspect" or state["status"] != "active":
|
|
57
|
+
raise StepFailed("initial inspection requires the active inspect track")
|
|
58
|
+
specs = INSPECTION_SPECS
|
|
59
|
+
if any((repo / project_dir / "research" / spec[3]).exists() or
|
|
60
|
+
(repo / project_dir / "research" / spec[3]).is_symlink() for spec in specs):
|
|
61
|
+
raise StepFailed("prior inspection evidence requires the re-inspection contract")
|
|
62
|
+
branch = subprocess.run(["git", "branch", "--show-current"], cwd=repo,
|
|
63
|
+
capture_output=True, text=True, check=True).stdout.strip()
|
|
64
|
+
if branch != state["branch"]:
|
|
65
|
+
raise StepFailed("current branch differs from the recorded inspection branch")
|
|
66
|
+
pending = step("discussion_records.py", "pending", "--repo", str(repo))
|
|
67
|
+
if pending["pending"]:
|
|
68
|
+
raise StepFailed("pending discussion requires its owner disposition")
|
|
69
|
+
inventory = step("check_docs_audit.py", "--repo", str(repo), "--emit-inventory", raw=True)
|
|
70
|
+
resources = scripts.parent
|
|
71
|
+
if not (resources / "references").is_dir():
|
|
72
|
+
resources = resources / "skills/gsd-path"
|
|
73
|
+
for _, role, template, _ in specs:
|
|
74
|
+
for path in (resources / "references" / f"{role}.md", resources / "templates" / f"{template}.md"):
|
|
75
|
+
if not path.is_file():
|
|
76
|
+
raise StepFailed(f"missing inspection resource: {path}")
|
|
77
|
+
staging = Path(tempfile.mkdtemp(prefix="gsd-path-inspect-"))
|
|
78
|
+
inventory_file = staging / "inventory.txt"
|
|
79
|
+
inventory_file.write_text(inventory, encoding="utf-8")
|
|
80
|
+
assignments = []
|
|
81
|
+
for task_name, role, template, filename in specs:
|
|
82
|
+
isolated = step("isolation.py", "isolate-verify", "--repo", str(repo),
|
|
83
|
+
"--base", expected_head, "--name", task_name.replace("_", "-"))
|
|
84
|
+
role_path = resources / "references" / f"{role}.md"
|
|
85
|
+
template_path = resources / "templates" / f"{template}.md"
|
|
86
|
+
output = f"{project_dir}/research/{filename}"
|
|
87
|
+
brief_file = staging / f"{task_name}.md"
|
|
88
|
+
brief = (f"Logical task: {task_name}\nRead and follow role: {role_path}\n"
|
|
89
|
+
f"Template: {template_path}\nRepository and command cwd: {isolated['worktree']}\n"
|
|
90
|
+
f"Recorded baseline and Audited HEAD: {isolated['base']}\n"
|
|
91
|
+
f"Write only: {Path(isolated['worktree']) / output}\n"
|
|
92
|
+
"Use only this supplied sidecar for project commands; do not create worktrees.\n"
|
|
93
|
+
"The parent owns gates, collection, retirement, and phase state.\n"
|
|
94
|
+
"Exclude .git, node_modules, .project/archive, and installed GSD Path and path skill bundles.\n")
|
|
95
|
+
if task_name == "inspect_docs":
|
|
96
|
+
brief += ("Alignment mode: false. No prior audit or changed set.\n"
|
|
97
|
+
"Frozen inventory follows; use it exactly, without rediscovery:\n" + inventory)
|
|
98
|
+
brief_file.write_text(brief, encoding="utf-8")
|
|
99
|
+
assignments.append({**isolated, "task_name": task_name, "role": str(role_path),
|
|
100
|
+
"template": str(template_path), "output": output,
|
|
101
|
+
"brief_file": str(brief_file)})
|
|
102
|
+
receipt_file = staging / "inspection.json"
|
|
103
|
+
outputs["inspection"] = {"repo": str(repo), "base": expected_head,
|
|
104
|
+
"inventory_file": str(inventory_file),
|
|
105
|
+
"inventory_sha256": hashlib.sha256(inventory_file.read_bytes()).hexdigest(),
|
|
106
|
+
"assignments": assignments, "receipt_file": str(receipt_file)}
|
|
107
|
+
_common.atomic_write(receipt_file, json.dumps(outputs["inspection"], sort_keys=True) + "\n")
|
|
108
|
+
elif action == "finish-inspect":
|
|
109
|
+
if not mapper_reviewed or inspection is None or project_dir != ".project":
|
|
110
|
+
raise StepFailed("finish-inspect requires the prepared active track and mapper review")
|
|
111
|
+
prepared = json.loads(inspection.read_text(encoding="utf-8"))
|
|
112
|
+
if prepared["repo"] != str(repo) or prepared["base"] != expected_head:
|
|
113
|
+
raise StepFailed("inspection receipt does not match repository and expected HEAD")
|
|
114
|
+
assignments = {a["task_name"]: a for a in prepared["assignments"]}
|
|
115
|
+
if len(prepared["assignments"]) != len(INSPECTION_SPECS) or set(assignments) != {s[0] for s in INSPECTION_SPECS}:
|
|
116
|
+
raise StepFailed("inspection receipt must name both original assignments")
|
|
117
|
+
for task_name, _, _, filename in INSPECTION_SPECS:
|
|
118
|
+
assignment = assignments[task_name]
|
|
119
|
+
if assignment["base"] != expected_head or assignment["output"] != f".project/research/{filename}":
|
|
120
|
+
raise StepFailed("inspection assignment changed its baseline or output")
|
|
121
|
+
inventory_file = Path(prepared["inventory_file"])
|
|
122
|
+
if hashlib.sha256(inventory_file.read_bytes()).hexdigest() != prepared["inventory_sha256"]:
|
|
123
|
+
raise StepFailed("frozen inspection inventory changed")
|
|
124
|
+
state = step("pipeline_state.py", "validate", *common)["state"]
|
|
125
|
+
if state["phase"] != "inspect" or state["status"] != "active":
|
|
126
|
+
raise StepFailed("inspection completion requires inspect/active")
|
|
127
|
+
branch = subprocess.run(["git", "branch", "--show-current"], cwd=repo,
|
|
128
|
+
capture_output=True, text=True, check=True).stdout.strip()
|
|
129
|
+
if state["branch"] != branch:
|
|
130
|
+
raise StepFailed("current branch differs from the recorded inspection branch")
|
|
131
|
+
pending = step("discussion_records.py", "pending", "--repo", str(repo))
|
|
132
|
+
if pending["pending"]:
|
|
133
|
+
raise StepFailed("pending discussion requires its owner disposition")
|
|
134
|
+
docs = assignments["inspect_docs"]
|
|
135
|
+
step("check_docs_audit.py", "--repo", docs["worktree"], "--audit", docs["output"],
|
|
136
|
+
"--inventory", str(inventory_file))
|
|
137
|
+
if f"Audited HEAD: {expected_head}" not in (Path(docs["worktree"]) / docs["output"]).read_text().splitlines():
|
|
138
|
+
raise StepFailed("audit does not name the supplied inspection baseline")
|
|
139
|
+
for task_name, _, _, _ in INSPECTION_SPECS:
|
|
140
|
+
assignment = assignments[task_name]
|
|
141
|
+
step("isolation.py", "collect-artifact", "--repo", str(repo),
|
|
142
|
+
"--source", assignment["worktree"], "--base", expected_head,
|
|
143
|
+
"--branch", assignment["branch"], "--source-path", assignment["output"],
|
|
144
|
+
"--destination-path", assignment["output"])
|
|
145
|
+
step("isolation.py", "retire", "--repo", str(repo), "--worktree", assignment["worktree"],
|
|
146
|
+
"--branch", assignment["branch"])
|
|
147
|
+
expected = [part for key, value in state.items()
|
|
148
|
+
for part in (f"--expect-{key}", "null" if value is None else str(value))]
|
|
149
|
+
step("pipeline_state.py", "transition", *common, *expected,
|
|
150
|
+
"--set-phase", "inspect", "--set-status", "done", "--event", "inspection artifacts passed")
|
|
45
151
|
elif action == "lint-round":
|
|
46
152
|
head = subprocess.run(["git", "rev-parse", "--verify", "HEAD"],
|
|
47
153
|
cwd=repo, capture_output=True, text=True, check=True).stdout.strip()
|
|
@@ -87,28 +193,31 @@ def run_workflow(repo: Path, action: str, project_dir: str, expected_head: str =
|
|
|
87
193
|
if action == "approve-plan":
|
|
88
194
|
step("pipeline_state.py", "approve", *common, "--kind", "plan",
|
|
89
195
|
"--expected-head", expected_head)
|
|
90
|
-
except (StepFailed, OSError, subprocess.CalledProcessError) as error:
|
|
196
|
+
except (StepFailed, OSError, subprocess.CalledProcessError, ValueError, KeyError, TypeError) as error:
|
|
91
197
|
return {"status": "blocked", "reason": str(error), "steps": steps,
|
|
92
198
|
"next": "$gsd-path-forensics"}
|
|
93
|
-
return {"status": "complete", "steps": steps}
|
|
199
|
+
return {"status": "complete", "steps": steps, **outputs}
|
|
94
200
|
|
|
95
201
|
|
|
96
202
|
def main(argv=None):
|
|
97
203
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
98
|
-
parser.add_argument("action", choices=("route", "gate-plan", "approve-plan", "build-evidence", "lint-round", "prepare-task", "prepare-final"))
|
|
204
|
+
parser.add_argument("action", choices=("route", "gate-plan", "approve-plan", "build-evidence", "lint-round", "prepare-task", "prepare-final", "prepare-inspect", "finish-inspect"))
|
|
99
205
|
parser.add_argument("--repo", type=Path, required=True)
|
|
100
206
|
parser.add_argument("--project-dir", choices=(".project", ".project/next"), default=".project")
|
|
101
207
|
parser.add_argument("--expected-head")
|
|
102
208
|
parser.add_argument("--task-id")
|
|
103
209
|
parser.add_argument("--round-size", type=int)
|
|
210
|
+
parser.add_argument("--inspection", type=Path)
|
|
211
|
+
parser.add_argument("--mapper-reviewed", action="store_true")
|
|
104
212
|
arguments = parser.parse_args(argv)
|
|
105
|
-
if arguments.action in {"approve-plan", "build-evidence", "prepare-task", "prepare-final"} and not arguments.expected_head:
|
|
213
|
+
if arguments.action in {"approve-plan", "build-evidence", "prepare-task", "prepare-final", "prepare-inspect", "finish-inspect"} and not arguments.expected_head:
|
|
106
214
|
parser.error(f"{arguments.action} requires --expected-head")
|
|
107
215
|
if arguments.action == "prepare-task" and (not arguments.task_id or arguments.round_size is None):
|
|
108
216
|
parser.error("prepare-task requires --task-id and --round-size")
|
|
109
217
|
result = run_workflow(arguments.repo.resolve(), arguments.action,
|
|
110
218
|
arguments.project_dir, arguments.expected_head,
|
|
111
|
-
arguments.task_id, arguments.round_size
|
|
219
|
+
arguments.task_id, arguments.round_size, arguments.inspection,
|
|
220
|
+
arguments.mapper_reviewed)
|
|
112
221
|
print(json.dumps(result, sort_keys=True))
|
|
113
222
|
return 0 if result["status"] == "complete" else 1
|
|
114
223
|
|
|
@@ -17,7 +17,7 @@ Wave verdict: <pass | blocked — blocked if any task fails>
|
|
|
17
17
|
Cycle: <C>
|
|
18
18
|
Depth: <full | deep | verify-only — verify-only is orchestrator-written from
|
|
19
19
|
its isolated Verify evidence; no independent reviewer ran>
|
|
20
|
-
Lens: <contract | adversarial — deep reviews only; empty or
|
|
20
|
+
Lens: <contract | adversarial — deep reviews only; leave this value empty or omit the line
|
|
21
21
|
otherwise>
|
|
22
22
|
Tasks reviewed: <count>
|
|
23
23
|
|