@opengsd/gsd-path 1.0.0 → 1.2.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 +33 -13
- package/CHANGELOG.md +68 -0
- package/DOCS.md +75 -6
- package/FULL.md +12 -15
- package/HOOKS.md +18 -9
- package/QUICK.md +8 -6
- package/README.md +218 -14
- package/RUNTIME.md +16 -5
- package/UPDATE.md +30 -11
- package/WORKFLOW.md +35 -16
- package/package.json +23 -1
- package/platforms/claude/dispatch.md +4 -4
- package/platforms/copilot/dispatch.md +4 -4
- package/platforms/cursor/dispatch.md +5 -10
- package/platforms/grok/dispatch.md +4 -6
- package/platforms/kimi/dispatch.md +4 -4
- package/platforms/kiro/dispatch.md +4 -6
- package/platforms/opencode/dispatch.md +4 -4
- package/platforms/qwen/dispatch.md +4 -4
- package/platforms/shared-agents/dispatch.md +12 -19
- package/scripts/_common.py +5 -0
- package/scripts/archive_milestone.py +30 -124
- package/scripts/bootstrap_repository.py +33 -4
- package/scripts/build_recovery.py +292 -0
- package/scripts/build_state.py +2 -0
- package/scripts/check_docs_audit.py +7 -3
- package/scripts/check_handoffs.py +7 -1
- package/scripts/check_task_briefs.py +3 -0
- package/scripts/detect_project.py +22 -3
- package/scripts/discussion_records.py +3 -0
- package/scripts/discussion_validate.py +8 -3
- package/scripts/dispatch_driver.py +233 -22
- package/scripts/git_guard.py +14 -5
- package/scripts/guard_hook.py +11 -1
- package/scripts/install.mjs +54 -1448
- package/scripts/install.py +155 -188
- package/scripts/integration.py +54 -28
- package/scripts/isolation.py +24 -6
- package/scripts/jev_review.py +138 -0
- package/scripts/lean_verification.py +3 -1
- package/scripts/loop_run.py +2 -0
- package/scripts/model_policy.py +279 -0
- package/scripts/path_config.py +248 -0
- package/scripts/pipeline_diagnose.py +15 -3
- package/scripts/pipeline_git.py +3 -0
- package/scripts/pipeline_state.py +117 -186
- package/scripts/pipeline_undo.py +14 -7
- package/scripts/promote_lookahead.py +33 -162
- package/scripts/review_panel.py +11 -0
- package/scripts/roadmap.py +326 -0
- package/scripts/runtime_store.py +278 -0
- package/scripts/skill-resources.json +182 -4
- package/scripts/state_checkpoint.py +114 -72
- package/scripts/state_promote.py +47 -44
- package/scripts/status_runtime.py +92 -6
- package/scripts/task_context.py +73 -0
- package/scripts/token_budget.py +40 -1
- package/scripts/workflow_run.py +128 -8
- package/scripts/worktree_paths.py +94 -0
- package/skills/gsd-path/BUILD.md +54 -575
- package/skills/gsd-path/DECIDE.md +4 -6
- package/skills/gsd-path/DEFINE.md +23 -21
- package/skills/gsd-path/DOCS-AUDIT.md +2 -0
- package/skills/gsd-path/INSPECT.md +32 -8
- package/skills/gsd-path/PLAN.md +29 -19
- package/skills/gsd-path/RESEARCH.md +5 -6
- package/skills/gsd-path/ROADMAP.md +24 -58
- package/skills/gsd-path/SHIP.md +29 -17
- package/skills/gsd-path/SKILL.md +46 -22
- package/skills/gsd-path/references/build-abandon.md +33 -0
- package/skills/gsd-path/references/build-native.md +502 -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/config.md +57 -0
- package/skills/gsd-path/references/dispatch.md +12 -19
- package/skills/gsd-path/references/docs-auditor.md +14 -0
- package/skills/gsd-path/references/jev-review.md +82 -0
- package/skills/gsd-path/references/model-policy.md +139 -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 -148
- package/skills/gsd-path/references/runtime-selection.md +25 -0
- package/skills/gsd-path/scripts/__pycache__/_common.cpython-312.pyc +0 -0
- package/skills/gsd-path/scripts/__pycache__/check_handoffs.cpython-312.pyc +0 -0
- package/skills/gsd-path/scripts/_common.py +5 -0
- package/skills/gsd-path/scripts/archive_milestone.py +30 -124
- package/skills/gsd-path/scripts/bootstrap_repository.py +33 -4
- package/skills/gsd-path/scripts/build_recovery.py +292 -0
- package/skills/gsd-path/scripts/build_state.py +2 -0
- package/skills/gsd-path/scripts/check_docs_audit.py +7 -3
- package/skills/gsd-path/scripts/check_handoffs.py +7 -1
- package/skills/gsd-path/scripts/check_task_briefs.py +3 -0
- package/skills/gsd-path/scripts/detect_project.py +22 -3
- package/skills/gsd-path/scripts/discussion_records.py +3 -0
- package/skills/gsd-path/scripts/discussion_validate.py +8 -3
- package/skills/gsd-path/scripts/dispatch_driver.py +233 -22
- package/skills/gsd-path/scripts/git_guard.py +768 -0
- package/skills/gsd-path/scripts/integration.py +54 -28
- package/skills/gsd-path/scripts/isolation.py +24 -6
- package/skills/gsd-path/scripts/jev_review.py +138 -0
- package/skills/gsd-path/scripts/lean_verification.py +3 -1
- package/skills/gsd-path/scripts/loop_run.py +2 -0
- package/skills/gsd-path/scripts/model_policy.py +279 -0
- package/skills/gsd-path/scripts/path_config.py +248 -0
- package/skills/gsd-path/scripts/pipeline_git.py +3 -0
- package/skills/gsd-path/scripts/pipeline_state.py +117 -186
- package/skills/gsd-path/scripts/promote_lookahead.py +33 -162
- package/skills/gsd-path/scripts/review_panel.py +11 -0
- package/skills/gsd-path/scripts/roadmap.py +326 -0
- package/skills/gsd-path/scripts/state_checkpoint.py +114 -72
- package/skills/gsd-path/scripts/state_promote.py +47 -44
- package/skills/gsd-path/scripts/status_runtime.py +208 -0
- 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 +128 -8
- package/skills/gsd-path/scripts/worktree_paths.py +94 -0
- package/skills/gsd-path/templates/skeptic.md +1 -1
- package/skills/gsd-path/templates/task.md +2 -0
- package/skills/gsd-path/templates/wave-panel.md +1 -1
- package/skills/gsd-path/templates/wave-review.md +1 -1
- package/skills/gsd-path-build/SKILL.md +54 -575
- package/skills/gsd-path-build/references/build-abandon.md +33 -0
- package/skills/gsd-path-build/references/build-native.md +502 -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 +12 -19
- package/skills/gsd-path-build/references/jev-review.md +82 -0
- package/skills/gsd-path-build/references/model-policy.md +139 -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 -148
- package/skills/gsd-path-build/references/runtime-selection.md +25 -0
- package/skills/gsd-path-build/scripts/__pycache__/_common.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/_common.py +5 -0
- package/skills/gsd-path-build/scripts/archive_milestone.py +30 -124
- package/skills/gsd-path-build/scripts/build_recovery.py +292 -0
- package/skills/gsd-path-build/scripts/build_state.py +2 -0
- package/skills/gsd-path-build/scripts/check_handoffs.py +7 -1
- package/skills/gsd-path-build/scripts/check_task_briefs.py +3 -0
- package/skills/gsd-path-build/scripts/detect_project.py +1536 -0
- package/skills/gsd-path-build/scripts/discussion_records.py +3 -0
- package/skills/gsd-path-build/scripts/discussion_validate.py +8 -3
- package/skills/gsd-path-build/scripts/dispatch_driver.py +233 -22
- package/skills/gsd-path-build/scripts/integration.py +54 -28
- package/skills/gsd-path-build/scripts/isolation.py +24 -6
- package/skills/gsd-path-build/scripts/jev_review.py +138 -0
- package/skills/gsd-path-build/scripts/loop_run.py +2 -0
- package/skills/gsd-path-build/scripts/model_policy.py +279 -0
- package/skills/gsd-path-build/scripts/path_config.py +248 -0
- package/skills/gsd-path-build/scripts/pipeline_git.py +3 -0
- package/skills/gsd-path-build/scripts/pipeline_state.py +117 -186
- package/skills/gsd-path-build/scripts/promote_lookahead.py +286 -0
- package/skills/gsd-path-build/scripts/review_panel.py +11 -0
- package/skills/gsd-path-build/scripts/roadmap.py +326 -0
- package/skills/gsd-path-build/scripts/state_checkpoint.py +114 -72
- package/skills/gsd-path-build/scripts/state_promote.py +47 -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 +128 -8
- package/skills/gsd-path-build/scripts/worktree_paths.py +94 -0
- package/skills/gsd-path-build/templates/skeptic.md +1 -1
- package/skills/gsd-path-build/templates/task.md +2 -0
- package/skills/gsd-path-build/templates/wave-panel.md +1 -1
- package/skills/gsd-path-build/templates/wave-review.md +1 -1
- package/skills/gsd-path-decide/SKILL.md +4 -6
- package/skills/gsd-path-decide/references/dispatch.md +12 -19
- package/skills/gsd-path-decide/references/model-policy.md +139 -0
- package/skills/gsd-path-decide/references/runtime-selection.md +25 -0
- package/skills/gsd-path-decide/scripts/_common.py +5 -0
- package/skills/gsd-path-decide/scripts/archive_milestone.py +2171 -0
- package/skills/gsd-path-decide/scripts/build_recovery.py +292 -0
- package/skills/gsd-path-decide/scripts/check_handoffs.py +7 -1
- package/skills/gsd-path-decide/scripts/check_task_briefs.py +3 -0
- package/skills/gsd-path-decide/scripts/detect_project.py +1536 -0
- package/skills/gsd-path-decide/scripts/discussion_records.py +3 -0
- package/skills/gsd-path-decide/scripts/discussion_validate.py +1326 -0
- package/skills/gsd-path-decide/scripts/integration.py +1459 -0
- package/skills/gsd-path-decide/scripts/isolation.py +24 -6
- package/skills/gsd-path-decide/scripts/loop_run.py +839 -0
- package/skills/gsd-path-decide/scripts/model_policy.py +279 -0
- package/skills/gsd-path-decide/scripts/path_config.py +248 -0
- package/skills/gsd-path-decide/scripts/pipeline_git.py +3 -0
- package/skills/gsd-path-decide/scripts/pipeline_state.py +117 -186
- package/skills/gsd-path-decide/scripts/promote_lookahead.py +286 -0
- package/skills/gsd-path-decide/scripts/review_panel.py +564 -0
- package/skills/gsd-path-decide/scripts/roadmap.py +326 -0
- package/skills/gsd-path-decide/scripts/state_checkpoint.py +114 -72
- package/skills/gsd-path-decide/scripts/state_promote.py +47 -44
- package/skills/gsd-path-decide/scripts/worktree_paths.py +94 -0
- package/skills/gsd-path-define/SKILL.md +23 -21
- package/skills/gsd-path-define/references/build-recovery.md +78 -0
- package/skills/gsd-path-define/references/runtime-selection.md +25 -0
- package/skills/gsd-path-define/scripts/_common.py +5 -0
- package/skills/gsd-path-define/scripts/archive_milestone.py +2171 -0
- package/skills/gsd-path-define/scripts/build_recovery.py +292 -0
- package/skills/gsd-path-define/scripts/check_handoffs.py +7 -1
- package/skills/gsd-path-define/scripts/check_task_briefs.py +3 -0
- package/skills/gsd-path-define/scripts/detect_project.py +22 -3
- package/skills/gsd-path-define/scripts/discussion_records.py +3 -0
- package/skills/gsd-path-define/scripts/discussion_validate.py +1326 -0
- package/skills/gsd-path-define/scripts/integration.py +1459 -0
- package/skills/gsd-path-define/scripts/isolation.py +24 -6
- package/skills/gsd-path-define/scripts/loop_run.py +839 -0
- package/skills/gsd-path-define/scripts/model_policy.py +279 -0
- package/skills/gsd-path-define/scripts/path_config.py +248 -0
- package/skills/gsd-path-define/scripts/pipeline_git.py +3 -0
- package/skills/gsd-path-define/scripts/pipeline_state.py +117 -186
- package/skills/gsd-path-define/scripts/promote_lookahead.py +286 -0
- package/skills/gsd-path-define/scripts/review_panel.py +564 -0
- package/skills/gsd-path-define/scripts/roadmap.py +326 -0
- package/skills/gsd-path-define/scripts/state_checkpoint.py +114 -72
- package/skills/gsd-path-define/scripts/state_promote.py +47 -44
- package/skills/gsd-path-define/scripts/worktree_paths.py +94 -0
- package/skills/gsd-path-discuss/SKILL.md +2 -0
- package/skills/gsd-path-discuss/references/runtime-selection.md +25 -0
- package/skills/gsd-path-discuss/scripts/_common.py +5 -0
- package/skills/gsd-path-discuss/scripts/discussion_records.py +3 -0
- package/skills/gsd-path-discuss/scripts/loop_run.py +839 -0
- package/skills/gsd-path-discuss/scripts/model_policy.py +279 -0
- package/skills/gsd-path-discuss/scripts/path_config.py +248 -0
- package/skills/gsd-path-discuss/scripts/review_panel.py +564 -0
- package/skills/gsd-path-discuss/scripts/worktree_paths.py +94 -0
- package/skills/gsd-path-docs-audit/SKILL.md +2 -0
- package/skills/gsd-path-docs-audit/references/dispatch.md +12 -19
- package/skills/gsd-path-docs-audit/references/docs-auditor.md +14 -0
- package/skills/gsd-path-docs-audit/references/model-policy.md +139 -0
- package/skills/gsd-path-docs-audit/references/runtime-selection.md +25 -0
- package/skills/gsd-path-docs-audit/scripts/_common.py +5 -0
- package/skills/gsd-path-docs-audit/scripts/archive_milestone.py +2171 -0
- package/skills/gsd-path-docs-audit/scripts/build_recovery.py +292 -0
- package/skills/gsd-path-docs-audit/scripts/check_docs_audit.py +7 -3
- package/skills/gsd-path-docs-audit/scripts/check_handoffs.py +7 -1
- package/skills/gsd-path-docs-audit/scripts/check_task_briefs.py +3 -0
- package/skills/gsd-path-docs-audit/scripts/detect_project.py +1536 -0
- package/skills/gsd-path-docs-audit/scripts/discussion_records.py +3 -0
- package/skills/gsd-path-docs-audit/scripts/discussion_validate.py +1326 -0
- package/skills/gsd-path-docs-audit/scripts/integration.py +1459 -0
- package/skills/gsd-path-docs-audit/scripts/isolation.py +24 -6
- package/skills/gsd-path-docs-audit/scripts/loop_run.py +839 -0
- package/skills/gsd-path-docs-audit/scripts/model_policy.py +279 -0
- package/skills/gsd-path-docs-audit/scripts/path_config.py +248 -0
- package/skills/gsd-path-docs-audit/scripts/pipeline_git.py +3 -0
- package/skills/gsd-path-docs-audit/scripts/pipeline_state.py +117 -186
- package/skills/gsd-path-docs-audit/scripts/promote_lookahead.py +286 -0
- package/skills/gsd-path-docs-audit/scripts/review_panel.py +564 -0
- package/skills/gsd-path-docs-audit/scripts/roadmap.py +326 -0
- package/skills/gsd-path-docs-audit/scripts/state_checkpoint.py +114 -72
- package/skills/gsd-path-docs-audit/scripts/state_promote.py +47 -44
- package/skills/gsd-path-docs-audit/scripts/worktree_paths.py +94 -0
- package/skills/gsd-path-forensics/SKILL.md +9 -5
- package/skills/gsd-path-forensics/references/runtime-selection.md +25 -0
- package/skills/gsd-path-forensics/scripts/_common.py +5 -0
- package/skills/gsd-path-forensics/scripts/discussion_records.py +3 -0
- package/skills/gsd-path-forensics/scripts/loop_run.py +839 -0
- package/skills/gsd-path-forensics/scripts/model_policy.py +279 -0
- package/skills/gsd-path-forensics/scripts/path_config.py +248 -0
- package/skills/gsd-path-forensics/scripts/pipeline_diagnose.py +15 -3
- package/skills/gsd-path-forensics/scripts/pipeline_undo.py +14 -7
- package/skills/gsd-path-forensics/scripts/review_panel.py +564 -0
- package/skills/gsd-path-forensics/scripts/worktree_paths.py +94 -0
- package/skills/gsd-path-inspect/SKILL.md +32 -8
- package/skills/gsd-path-inspect/references/dispatch.md +12 -19
- package/skills/gsd-path-inspect/references/docs-auditor.md +14 -0
- package/skills/gsd-path-inspect/references/model-policy.md +139 -0
- package/skills/gsd-path-inspect/references/runtime-selection.md +25 -0
- package/skills/gsd-path-inspect/scripts/__pycache__/_common.cpython-312.pyc +0 -0
- package/skills/gsd-path-inspect/scripts/_common.py +5 -0
- package/skills/gsd-path-inspect/scripts/archive_milestone.py +2171 -0
- package/skills/gsd-path-inspect/scripts/build_recovery.py +292 -0
- package/skills/gsd-path-inspect/scripts/check_docs_audit.py +7 -3
- package/skills/gsd-path-inspect/scripts/check_handoffs.py +7 -1
- package/skills/gsd-path-inspect/scripts/check_task_briefs.py +3 -0
- package/skills/gsd-path-inspect/scripts/detect_project.py +22 -3
- package/skills/gsd-path-inspect/scripts/discussion_records.py +3 -0
- package/skills/gsd-path-inspect/scripts/discussion_validate.py +1326 -0
- package/skills/gsd-path-inspect/scripts/integration.py +1459 -0
- package/skills/gsd-path-inspect/scripts/isolation.py +24 -6
- package/skills/gsd-path-inspect/scripts/loop_run.py +839 -0
- package/skills/gsd-path-inspect/scripts/model_policy.py +279 -0
- package/skills/gsd-path-inspect/scripts/path_config.py +248 -0
- package/skills/gsd-path-inspect/scripts/pipeline_git.py +3 -0
- package/skills/gsd-path-inspect/scripts/pipeline_state.py +117 -186
- package/skills/gsd-path-inspect/scripts/promote_lookahead.py +286 -0
- package/skills/gsd-path-inspect/scripts/review_panel.py +564 -0
- package/skills/gsd-path-inspect/scripts/roadmap.py +326 -0
- package/skills/gsd-path-inspect/scripts/state_checkpoint.py +114 -72
- package/skills/gsd-path-inspect/scripts/state_promote.py +47 -44
- package/skills/gsd-path-inspect/scripts/workflow_run.py +237 -0
- package/skills/gsd-path-inspect/scripts/worktree_paths.py +94 -0
- package/skills/gsd-path-loop/SKILL.md +2 -0
- package/skills/gsd-path-loop/references/runtime-selection.md +25 -0
- package/skills/gsd-path-loop/scripts/_common.py +5 -0
- package/skills/gsd-path-loop/scripts/discussion_records.py +3 -0
- package/skills/gsd-path-loop/scripts/loop_run.py +2 -0
- package/skills/gsd-path-loop/scripts/model_policy.py +279 -0
- package/skills/gsd-path-loop/scripts/path_config.py +248 -0
- package/skills/gsd-path-loop/scripts/review_panel.py +564 -0
- package/skills/gsd-path-loop/scripts/worktree_paths.py +94 -0
- package/skills/gsd-path-migrate/SKILL.md +2 -0
- package/skills/gsd-path-migrate/references/runtime-selection.md +25 -0
- package/skills/gsd-path-migrate/scripts/_common.py +185 -0
- package/skills/gsd-path-migrate/scripts/discussion_records.py +3 -0
- package/skills/gsd-path-migrate/scripts/loop_run.py +839 -0
- package/skills/gsd-path-migrate/scripts/model_policy.py +279 -0
- package/skills/gsd-path-migrate/scripts/path_config.py +248 -0
- package/skills/gsd-path-migrate/scripts/review_panel.py +564 -0
- package/skills/gsd-path-plan/SKILL.md +29 -19
- package/skills/gsd-path-plan/references/build-recovery.md +78 -0
- package/skills/gsd-path-plan/references/dispatch.md +12 -19
- package/skills/gsd-path-plan/references/model-policy.md +139 -0
- package/skills/gsd-path-plan/references/runtime-selection.md +25 -0
- package/skills/gsd-path-plan/scripts/__pycache__/_common.cpython-312.pyc +0 -0
- package/skills/gsd-path-plan/scripts/_common.py +5 -0
- package/skills/gsd-path-plan/scripts/archive_milestone.py +2171 -0
- package/skills/gsd-path-plan/scripts/build_recovery.py +292 -0
- package/skills/gsd-path-plan/scripts/check_handoffs.py +7 -1
- package/skills/gsd-path-plan/scripts/check_task_briefs.py +3 -0
- package/skills/gsd-path-plan/scripts/detect_project.py +1536 -0
- package/skills/gsd-path-plan/scripts/discussion_records.py +3 -0
- package/skills/gsd-path-plan/scripts/discussion_validate.py +1326 -0
- package/skills/gsd-path-plan/scripts/integration.py +1459 -0
- package/skills/gsd-path-plan/scripts/isolation.py +24 -6
- package/skills/gsd-path-plan/scripts/loop_run.py +839 -0
- package/skills/gsd-path-plan/scripts/model_policy.py +279 -0
- package/skills/gsd-path-plan/scripts/path_config.py +248 -0
- package/skills/gsd-path-plan/scripts/pipeline_git.py +3 -0
- package/skills/gsd-path-plan/scripts/pipeline_state.py +117 -186
- package/skills/gsd-path-plan/scripts/promote_lookahead.py +286 -0
- package/skills/gsd-path-plan/scripts/review_panel.py +11 -0
- package/skills/gsd-path-plan/scripts/roadmap.py +326 -0
- package/skills/gsd-path-plan/scripts/state_checkpoint.py +114 -72
- package/skills/gsd-path-plan/scripts/state_promote.py +47 -44
- package/skills/gsd-path-plan/scripts/workflow_run.py +128 -8
- package/skills/gsd-path-plan/scripts/worktree_paths.py +94 -0
- package/skills/gsd-path-plan/templates/task.md +2 -0
- package/skills/gsd-path-research/SKILL.md +5 -6
- package/skills/gsd-path-research/references/dispatch.md +12 -19
- package/skills/gsd-path-research/references/model-policy.md +139 -0
- package/skills/gsd-path-research/references/runtime-selection.md +25 -0
- package/skills/gsd-path-research/scripts/_common.py +5 -0
- package/skills/gsd-path-research/scripts/archive_milestone.py +2171 -0
- package/skills/gsd-path-research/scripts/build_recovery.py +292 -0
- package/skills/gsd-path-research/scripts/check_handoffs.py +7 -1
- package/skills/gsd-path-research/scripts/check_task_briefs.py +3 -0
- package/skills/gsd-path-research/scripts/detect_project.py +1536 -0
- package/skills/gsd-path-research/scripts/discussion_records.py +3 -0
- package/skills/gsd-path-research/scripts/discussion_validate.py +1326 -0
- package/skills/gsd-path-research/scripts/integration.py +1459 -0
- package/skills/gsd-path-research/scripts/isolation.py +24 -6
- package/skills/gsd-path-research/scripts/loop_run.py +839 -0
- package/skills/gsd-path-research/scripts/model_policy.py +279 -0
- package/skills/gsd-path-research/scripts/path_config.py +248 -0
- package/skills/gsd-path-research/scripts/pipeline_git.py +3 -0
- package/skills/gsd-path-research/scripts/pipeline_state.py +117 -186
- package/skills/gsd-path-research/scripts/promote_lookahead.py +286 -0
- package/skills/gsd-path-research/scripts/review_panel.py +564 -0
- package/skills/gsd-path-research/scripts/roadmap.py +326 -0
- package/skills/gsd-path-research/scripts/state_checkpoint.py +114 -72
- package/skills/gsd-path-research/scripts/state_promote.py +47 -44
- package/skills/gsd-path-research/scripts/worktree_paths.py +94 -0
- package/skills/gsd-path-roadmap/SKILL.md +24 -58
- package/skills/gsd-path-roadmap/references/dispatch.md +12 -19
- package/skills/gsd-path-roadmap/references/model-policy.md +139 -0
- package/skills/gsd-path-roadmap/references/runtime-selection.md +25 -0
- package/skills/gsd-path-roadmap/scripts/_common.py +5 -0
- package/skills/gsd-path-roadmap/scripts/archive_milestone.py +30 -124
- package/skills/gsd-path-roadmap/scripts/build_recovery.py +292 -0
- package/skills/gsd-path-roadmap/scripts/check_handoffs.py +7 -1
- package/skills/gsd-path-roadmap/scripts/check_task_briefs.py +3 -0
- package/skills/gsd-path-roadmap/scripts/detect_project.py +22 -3
- package/skills/gsd-path-roadmap/scripts/discussion_records.py +3 -0
- package/skills/gsd-path-roadmap/scripts/discussion_validate.py +8 -3
- package/skills/gsd-path-roadmap/scripts/integration.py +54 -28
- package/skills/gsd-path-roadmap/scripts/isolation.py +24 -6
- package/skills/gsd-path-roadmap/scripts/loop_run.py +839 -0
- package/skills/gsd-path-roadmap/scripts/model_policy.py +279 -0
- package/skills/gsd-path-roadmap/scripts/path_config.py +248 -0
- package/skills/gsd-path-roadmap/scripts/pipeline_git.py +3 -0
- package/skills/gsd-path-roadmap/scripts/pipeline_state.py +117 -186
- package/skills/gsd-path-roadmap/scripts/promote_lookahead.py +33 -162
- package/skills/gsd-path-roadmap/scripts/review_panel.py +11 -0
- package/skills/gsd-path-roadmap/scripts/roadmap.py +326 -0
- package/skills/gsd-path-roadmap/scripts/state_checkpoint.py +114 -72
- package/skills/gsd-path-roadmap/scripts/state_promote.py +47 -44
- package/skills/gsd-path-roadmap/scripts/worktree_paths.py +94 -0
- package/skills/gsd-path-ship/SKILL.md +29 -17
- package/skills/gsd-path-ship/references/dispatch.md +12 -19
- package/skills/gsd-path-ship/references/jev-review.md +82 -0
- package/skills/gsd-path-ship/references/model-policy.md +139 -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 -148
- package/skills/gsd-path-ship/references/runtime-selection.md +25 -0
- package/skills/gsd-path-ship/scripts/__pycache__/_common.cpython-312.pyc +0 -0
- package/skills/gsd-path-ship/scripts/_common.py +5 -0
- package/skills/gsd-path-ship/scripts/archive_milestone.py +30 -124
- package/skills/gsd-path-ship/scripts/build_recovery.py +292 -0
- package/skills/gsd-path-ship/scripts/build_state.py +2 -0
- package/skills/gsd-path-ship/scripts/check_handoffs.py +7 -1
- package/skills/gsd-path-ship/scripts/check_task_briefs.py +3 -0
- package/skills/gsd-path-ship/scripts/detect_project.py +1536 -0
- package/skills/gsd-path-ship/scripts/discussion_records.py +3 -0
- package/skills/gsd-path-ship/scripts/discussion_validate.py +8 -3
- package/skills/gsd-path-ship/scripts/integration.py +54 -28
- package/skills/gsd-path-ship/scripts/isolation.py +24 -6
- package/skills/gsd-path-ship/scripts/jev_review.py +138 -0
- package/skills/gsd-path-ship/scripts/lean_verification.py +3 -1
- package/skills/gsd-path-ship/scripts/loop_run.py +839 -0
- package/skills/gsd-path-ship/scripts/model_policy.py +279 -0
- package/skills/gsd-path-ship/scripts/path_config.py +248 -0
- package/skills/gsd-path-ship/scripts/pipeline_git.py +3 -0
- package/skills/gsd-path-ship/scripts/pipeline_state.py +117 -186
- package/skills/gsd-path-ship/scripts/promote_lookahead.py +286 -0
- package/skills/gsd-path-ship/scripts/review_panel.py +11 -0
- package/skills/gsd-path-ship/scripts/roadmap.py +326 -0
- package/skills/gsd-path-ship/scripts/state_checkpoint.py +114 -72
- package/skills/gsd-path-ship/scripts/state_promote.py +47 -44
- package/skills/gsd-path-ship/scripts/workflow_run.py +128 -8
- package/skills/gsd-path-ship/scripts/worktree_paths.py +94 -0
- package/skills/gsd-path-ship/templates/wave-review.md +1 -1
- package/skills/gsd-path-undo/SKILL.md +2 -0
- package/skills/gsd-path-undo/references/runtime-selection.md +25 -0
- package/skills/gsd-path-undo/scripts/_common.py +5 -0
- package/skills/gsd-path-undo/scripts/discussion_records.py +3 -0
- package/skills/gsd-path-undo/scripts/loop_run.py +839 -0
- package/skills/gsd-path-undo/scripts/model_policy.py +279 -0
- package/skills/gsd-path-undo/scripts/path_config.py +248 -0
- package/skills/gsd-path-undo/scripts/pipeline_undo.py +14 -7
- package/skills/gsd-path-undo/scripts/review_panel.py +564 -0
- package/skills/gsd-path-undo/scripts/worktree_paths.py +94 -0
- package/skills/path/BUILD.md +54 -575
- package/skills/path/DECIDE.md +4 -6
- package/skills/path/DEFINE.md +23 -21
- package/skills/path/DOCS-AUDIT.md +2 -0
- package/skills/path/INSPECT.md +32 -8
- package/skills/path/PLAN.md +29 -19
- package/skills/path/RESEARCH.md +5 -6
- package/skills/path/ROADMAP.md +24 -58
- package/skills/path/SHIP.md +29 -17
- package/skills/path/SKILL.md +46 -22
- package/skills/path/references/build-abandon.md +33 -0
- package/skills/path/references/build-native.md +502 -0
- package/skills/path/references/build-recovery.md +78 -0
- package/skills/path/references/coder.md +8 -3
- package/skills/path/references/config.md +57 -0
- package/skills/path/references/dispatch.md +12 -19
- package/skills/path/references/docs-auditor.md +14 -0
- package/skills/path/references/jev-review.md +82 -0
- package/skills/path/references/model-policy.md +139 -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 -148
- package/skills/path/references/runtime-selection.md +25 -0
- package/skills/path/scripts/_common.py +5 -0
- package/skills/path/scripts/archive_milestone.py +30 -124
- package/skills/path/scripts/bootstrap_repository.py +33 -4
- package/skills/path/scripts/build_recovery.py +292 -0
- package/skills/path/scripts/build_state.py +2 -0
- package/skills/path/scripts/check_docs_audit.py +7 -3
- package/skills/path/scripts/check_handoffs.py +7 -1
- package/skills/path/scripts/check_task_briefs.py +3 -0
- package/skills/path/scripts/detect_project.py +22 -3
- package/skills/path/scripts/discussion_records.py +3 -0
- package/skills/path/scripts/discussion_validate.py +8 -3
- package/skills/path/scripts/dispatch_driver.py +233 -22
- package/skills/path/scripts/git_guard.py +768 -0
- package/skills/path/scripts/integration.py +54 -28
- package/skills/path/scripts/isolation.py +24 -6
- package/skills/path/scripts/jev_review.py +138 -0
- package/skills/path/scripts/lean_verification.py +3 -1
- package/skills/path/scripts/loop_run.py +2 -0
- package/skills/path/scripts/model_policy.py +279 -0
- package/skills/path/scripts/path_config.py +248 -0
- package/skills/path/scripts/pipeline_git.py +3 -0
- package/skills/path/scripts/pipeline_state.py +117 -186
- package/skills/path/scripts/promote_lookahead.py +33 -162
- package/skills/path/scripts/review_panel.py +11 -0
- package/skills/path/scripts/roadmap.py +326 -0
- package/skills/path/scripts/state_checkpoint.py +114 -72
- package/skills/path/scripts/state_promote.py +47 -44
- package/skills/path/scripts/status_runtime.py +208 -0
- 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 +128 -8
- package/skills/path/scripts/worktree_paths.py +94 -0
- package/skills/path/templates/skeptic.md +1 -1
- package/skills/path/templates/task.md +2 -0
- package/skills/path/templates/wave-panel.md +1 -1
- package/skills/path/templates/wave-review.md +1 -1
|
@@ -4,6 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
from __future__ import annotations
|
|
6
6
|
|
|
7
|
+
import sys
|
|
8
|
+
|
|
9
|
+
# Runtime helpers must not modify their immutable installation.
|
|
10
|
+
sys.dont_write_bytecode = True
|
|
11
|
+
|
|
7
12
|
import json
|
|
8
13
|
import re
|
|
9
14
|
import shutil
|
|
@@ -11,6 +16,31 @@ from pathlib import Path, PurePosixPath
|
|
|
11
16
|
from typing import Mapping, Optional
|
|
12
17
|
|
|
13
18
|
|
|
19
|
+
if __package__: # imported as scripts.state_promote
|
|
20
|
+
from . import pipeline_state, state_checkpoint
|
|
21
|
+
from .pipeline_state import (
|
|
22
|
+
NULL,
|
|
23
|
+
PROMOTION_RESIDUAL,
|
|
24
|
+
PROMOTION_SCHEMA,
|
|
25
|
+
PROMOTION_TRACKS,
|
|
26
|
+
SLUG_RE,
|
|
27
|
+
PipelineState,
|
|
28
|
+
PipelineStateError,
|
|
29
|
+
)
|
|
30
|
+
else: # standalone script or sibling import
|
|
31
|
+
import pipeline_state
|
|
32
|
+
import state_checkpoint
|
|
33
|
+
from pipeline_state import (
|
|
34
|
+
NULL,
|
|
35
|
+
PROMOTION_RESIDUAL,
|
|
36
|
+
PROMOTION_SCHEMA,
|
|
37
|
+
PROMOTION_TRACKS,
|
|
38
|
+
SLUG_RE,
|
|
39
|
+
PipelineState,
|
|
40
|
+
PipelineStateError,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
14
44
|
def _render_roadmap(
|
|
15
45
|
text: str,
|
|
16
46
|
previous_milestone: str,
|
|
@@ -243,9 +273,9 @@ def _completed_promotion(
|
|
|
243
273
|
if _head_with_exact_message(repo, subject, fields) != head:
|
|
244
274
|
raise PipelineStateError("completed promotion has the wrong commit message")
|
|
245
275
|
|
|
246
|
-
active_text =
|
|
247
|
-
next_text =
|
|
248
|
-
roadmap_text =
|
|
276
|
+
active_text = state_checkpoint._git_text_at(repo, base, ".project/STATE.md")
|
|
277
|
+
next_text = state_checkpoint._git_text_at(repo, base, ".project/next/STATE.md")
|
|
278
|
+
roadmap_text = state_checkpoint._git_text_at(repo, base, ".project/ROADMAP.md")
|
|
249
279
|
if active_text is None or next_text is None or roadmap_text is None:
|
|
250
280
|
raise PipelineStateError("promotion parent is missing required metadata")
|
|
251
281
|
active_state = pipeline_state._state_from_text(active_text, "promotion parent STATE.md")
|
|
@@ -265,7 +295,7 @@ def _completed_promotion(
|
|
|
265
295
|
)
|
|
266
296
|
|
|
267
297
|
_promotion_tree_mapping(repo, base, head)
|
|
268
|
-
drift =
|
|
298
|
+
drift = state_checkpoint._classify_plan_drift(repo, next_state, base, landing)
|
|
269
299
|
expected_roadmap = _render_roadmap(
|
|
270
300
|
roadmap_text,
|
|
271
301
|
active_state.milestone,
|
|
@@ -273,11 +303,11 @@ def _completed_promotion(
|
|
|
273
303
|
branch,
|
|
274
304
|
landing,
|
|
275
305
|
)
|
|
276
|
-
current_roadmap =
|
|
306
|
+
current_roadmap = state_checkpoint._git_text_at(repo, head, ".project/ROADMAP.md")
|
|
277
307
|
if current_roadmap != expected_roadmap:
|
|
278
308
|
raise PipelineStateError("completed promotion has invalid ROADMAP.md")
|
|
279
309
|
|
|
280
|
-
current_state =
|
|
310
|
+
current_state = state_checkpoint._git_text_at(repo, head, ".project/STATE.md")
|
|
281
311
|
if current_state is None:
|
|
282
312
|
raise PipelineStateError("completed promotion has no STATE.md")
|
|
283
313
|
event = re.escape(_promotion_event(drift, branch, landing, base))
|
|
@@ -438,10 +468,10 @@ def _prepare_promotion(
|
|
|
438
468
|
if source.exists() or source.is_symlink():
|
|
439
469
|
if destination.exists() or destination.is_symlink():
|
|
440
470
|
raise PipelineStateError(f"promotion destination already exists: {destination}")
|
|
441
|
-
tracks[name] =
|
|
471
|
+
tracks[name] = state_checkpoint._tree_digest(source)
|
|
442
472
|
if not tracks:
|
|
443
473
|
raise PipelineStateError("lookahead track has no promotable artifacts")
|
|
444
|
-
drift =
|
|
474
|
+
drift = state_checkpoint._classify_plan_drift(repo, next_state, base, landing)
|
|
445
475
|
roadmap_path = project / "ROADMAP.md"
|
|
446
476
|
roadmap_text = pipeline_state._read_real_file(roadmap_path, "ROADMAP.md")
|
|
447
477
|
target_state = _promotion_state(
|
|
@@ -464,10 +494,10 @@ def _prepare_promotion(
|
|
|
464
494
|
"landing": landing,
|
|
465
495
|
"base": base,
|
|
466
496
|
"tracks": tracks,
|
|
467
|
-
"residual_sha256":
|
|
468
|
-
"next_state_sha256":
|
|
469
|
-
"active_state_sha256":
|
|
470
|
-
"roadmap_sha256":
|
|
497
|
+
"residual_sha256": state_checkpoint._tree_digest(next_root, tuple(tracks)),
|
|
498
|
+
"next_state_sha256": state_checkpoint._sha256(next_text),
|
|
499
|
+
"active_state_sha256": state_checkpoint._sha256(active_text),
|
|
500
|
+
"roadmap_sha256": state_checkpoint._sha256(roadmap_text),
|
|
471
501
|
"target_state": target_state,
|
|
472
502
|
"target_roadmap": target_roadmap,
|
|
473
503
|
"drift": drift,
|
|
@@ -521,7 +551,7 @@ def _resume_track_moves(project: Path, journal: dict[str, object], path: Path) -
|
|
|
521
551
|
if not source_exists and not destination_exists:
|
|
522
552
|
raise PipelineStateError(f"promotion lost both source and destination: {name}")
|
|
523
553
|
candidate = source if source_exists else destination
|
|
524
|
-
if
|
|
554
|
+
if state_checkpoint._tree_digest(candidate) != expected_digest:
|
|
525
555
|
raise PipelineStateError(f"promotion track drifted: {name}")
|
|
526
556
|
if source_exists:
|
|
527
557
|
source.rename(destination)
|
|
@@ -542,7 +572,7 @@ def _resume_metadata(project: Path, journal: dict[str, object], path: Path) -> N
|
|
|
542
572
|
raise PipelineStateError("promotion journal has invalid metadata")
|
|
543
573
|
if current == desired:
|
|
544
574
|
continue
|
|
545
|
-
if
|
|
575
|
+
if state_checkpoint._sha256(current) != expected_original:
|
|
546
576
|
raise PipelineStateError(f"promotion metadata drifted: {target}")
|
|
547
577
|
pipeline_state._atomic_write(target, desired)
|
|
548
578
|
journal["stage"] = f"updated:{target.name}"
|
|
@@ -560,9 +590,9 @@ def _resume_next_removal(
|
|
|
560
590
|
if residual.exists() or residual.is_symlink():
|
|
561
591
|
raise PipelineStateError("promotion has both next track and residual staging")
|
|
562
592
|
next_text = pipeline_state._read_real_file(next_root / "STATE.md", "next/STATE.md")
|
|
563
|
-
if
|
|
593
|
+
if state_checkpoint._sha256(next_text) != journal.get("next_state_sha256"):
|
|
564
594
|
raise PipelineStateError("lookahead STATE drifted during promotion")
|
|
565
|
-
if
|
|
595
|
+
if state_checkpoint._tree_digest(next_root) != journal.get("residual_sha256"):
|
|
566
596
|
raise PipelineStateError("lookahead residual drifted during promotion")
|
|
567
597
|
next_root.rename(residual)
|
|
568
598
|
journal["stage"] = "next-staged"
|
|
@@ -574,7 +604,7 @@ def _resume_next_removal(
|
|
|
574
604
|
raise PipelineStateError("promotion lost next track and residual staging")
|
|
575
605
|
if residual.is_symlink() or not residual.is_dir():
|
|
576
606
|
raise PipelineStateError(f"promotion residual must be a real directory: {residual}")
|
|
577
|
-
if
|
|
607
|
+
if state_checkpoint._tree_digest(residual) != journal.get("residual_sha256"):
|
|
578
608
|
raise PipelineStateError("staged lookahead residual drifted during promotion")
|
|
579
609
|
|
|
580
610
|
|
|
@@ -714,30 +744,3 @@ def promote_next(
|
|
|
714
744
|
"commit": commit,
|
|
715
745
|
"drift": journal["drift"],
|
|
716
746
|
}
|
|
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,237 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Run canonical workflow helpers with fixed arguments and fail-stop receipts."""
|
|
3
|
+
|
|
4
|
+
import argparse
|
|
5
|
+
import hashlib
|
|
6
|
+
import json
|
|
7
|
+
import os
|
|
8
|
+
import subprocess
|
|
9
|
+
import sys
|
|
10
|
+
import tempfile
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
try:
|
|
14
|
+
from scripts import _common
|
|
15
|
+
except ImportError: # bundled copy inside a skill's scripts directory
|
|
16
|
+
import _common
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class StepFailed(RuntimeError):
|
|
20
|
+
pass
|
|
21
|
+
|
|
22
|
+
INSPECTION_SPECS = (("inspect_codebase", "codebase-mapper", "codebase", "evidence-codebase.md"),
|
|
23
|
+
("inspect_docs", "docs-auditor", "docs-audit", "DOCS-AUDIT.md"))
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def run_workflow(repo: Path, action: str, project_dir: str, expected_head: str = None,
|
|
27
|
+
task_id: str = None, round_size: int = None, inspection: Path = None,
|
|
28
|
+
mapper_reviewed: bool = False) -> dict:
|
|
29
|
+
steps = []
|
|
30
|
+
outputs = {}
|
|
31
|
+
scripts = Path(__file__).resolve().parent
|
|
32
|
+
helpers = scripts
|
|
33
|
+
|
|
34
|
+
def step(script, *arguments, raw=False):
|
|
35
|
+
command = [sys.executable, "-B", str(helpers / script), *arguments]
|
|
36
|
+
completed = subprocess.run(command, cwd=repo, capture_output=True, text=True)
|
|
37
|
+
receipt = {"script": script, "command": command, "exit_code": completed.returncode,
|
|
38
|
+
"stdout": completed.stdout, "stderr": completed.stderr}
|
|
39
|
+
steps.append(receipt)
|
|
40
|
+
if completed.stderr:
|
|
41
|
+
sys.stderr.write(completed.stderr)
|
|
42
|
+
if completed.returncode:
|
|
43
|
+
raise StepFailed(script)
|
|
44
|
+
if raw:
|
|
45
|
+
return completed.stdout
|
|
46
|
+
try:
|
|
47
|
+
receipt["result"] = json.loads(completed.stdout)
|
|
48
|
+
except json.JSONDecodeError as error:
|
|
49
|
+
raise StepFailed(f"{script} did not return JSON") from error
|
|
50
|
+
return receipt["result"]
|
|
51
|
+
|
|
52
|
+
common = ["--repo", str(repo), "--project-dir", project_dir]
|
|
53
|
+
try:
|
|
54
|
+
if os.path.lexists(repo / ".gsd-path/runtime.json"):
|
|
55
|
+
resolved = subprocess.run(
|
|
56
|
+
[sys.executable, "-B", str(repo / ".gsd-path/status_runtime.py"),
|
|
57
|
+
"--repo", str(repo), "--runtime-path"],
|
|
58
|
+
cwd=repo, capture_output=True, text=True)
|
|
59
|
+
if resolved.returncode:
|
|
60
|
+
sys.stderr.write(resolved.stderr)
|
|
61
|
+
raise StepFailed(resolved.stderr.strip())
|
|
62
|
+
helpers = Path(resolved.stdout.strip())
|
|
63
|
+
if action == "route":
|
|
64
|
+
step("pipeline_state.py", "route", *common)
|
|
65
|
+
elif action == "prepare-inspect":
|
|
66
|
+
state = step("pipeline_state.py", "validate", *common)["state"]
|
|
67
|
+
if project_dir != ".project" or state["phase"] != "inspect" or state["status"] != "active":
|
|
68
|
+
raise StepFailed("initial inspection requires the active inspect track")
|
|
69
|
+
specs = INSPECTION_SPECS
|
|
70
|
+
if any((repo / project_dir / "research" / spec[3]).exists() or
|
|
71
|
+
(repo / project_dir / "research" / spec[3]).is_symlink() for spec in specs):
|
|
72
|
+
raise StepFailed("prior inspection evidence requires the re-inspection contract")
|
|
73
|
+
branch = subprocess.run(["git", "branch", "--show-current"], cwd=repo,
|
|
74
|
+
capture_output=True, text=True, check=True).stdout.strip()
|
|
75
|
+
if branch != state["branch"]:
|
|
76
|
+
raise StepFailed("current branch differs from the recorded inspection branch")
|
|
77
|
+
pending = step("discussion_records.py", "pending", "--repo", str(repo))
|
|
78
|
+
if pending["pending"]:
|
|
79
|
+
raise StepFailed("pending discussion requires its owner disposition")
|
|
80
|
+
inventory = step("check_docs_audit.py", "--repo", str(repo), "--emit-inventory", raw=True)
|
|
81
|
+
resources = scripts.parent
|
|
82
|
+
if not (resources / "references").is_dir():
|
|
83
|
+
resources = resources / "skills/gsd-path"
|
|
84
|
+
for _, role, template, _ in specs:
|
|
85
|
+
for path in (resources / "references" / f"{role}.md", resources / "templates" / f"{template}.md"):
|
|
86
|
+
if not path.is_file():
|
|
87
|
+
raise StepFailed(f"missing inspection resource: {path}")
|
|
88
|
+
staging = Path(tempfile.mkdtemp(prefix="gsd-path-inspect-"))
|
|
89
|
+
inventory_file = staging / "inventory.txt"
|
|
90
|
+
inventory_file.write_text(inventory, encoding="utf-8")
|
|
91
|
+
assignments = []
|
|
92
|
+
for task_name, role, template, filename in specs:
|
|
93
|
+
isolated = step("isolation.py", "isolate-verify", "--repo", str(repo),
|
|
94
|
+
"--base", expected_head, "--name", task_name.replace("_", "-"))
|
|
95
|
+
role_path = resources / "references" / f"{role}.md"
|
|
96
|
+
template_path = resources / "templates" / f"{template}.md"
|
|
97
|
+
output = f"{project_dir}/research/{filename}"
|
|
98
|
+
brief_file = staging / f"{task_name}.md"
|
|
99
|
+
brief = (f"Logical task: {task_name}\nRead and follow role: {role_path}\n"
|
|
100
|
+
f"Template: {template_path}\nRepository and command cwd: {isolated['worktree']}\n"
|
|
101
|
+
f"Recorded baseline and Audited HEAD: {isolated['base']}\n"
|
|
102
|
+
f"Write only: {Path(isolated['worktree']) / output}\n"
|
|
103
|
+
"Use only this supplied sidecar for project commands; do not create worktrees.\n"
|
|
104
|
+
"The parent owns gates, collection, retirement, and phase state.\n"
|
|
105
|
+
"Exclude .git, node_modules, .project/archive, and installed GSD Path and path skill bundles.\n")
|
|
106
|
+
if task_name == "inspect_docs":
|
|
107
|
+
brief += ("Alignment mode: false. No prior audit or changed set.\n"
|
|
108
|
+
"Frozen inventory follows; use it exactly, without rediscovery:\n" + inventory)
|
|
109
|
+
brief_file.write_text(brief, encoding="utf-8")
|
|
110
|
+
assignments.append({**isolated, "task_name": task_name, "role": str(role_path),
|
|
111
|
+
"template": str(template_path), "output": output,
|
|
112
|
+
"brief_file": str(brief_file)})
|
|
113
|
+
receipt_file = staging / "inspection.json"
|
|
114
|
+
outputs["inspection"] = {"repo": str(repo), "base": expected_head,
|
|
115
|
+
"inventory_file": str(inventory_file),
|
|
116
|
+
"inventory_sha256": hashlib.sha256(inventory_file.read_bytes()).hexdigest(),
|
|
117
|
+
"assignments": assignments, "receipt_file": str(receipt_file)}
|
|
118
|
+
_common.atomic_write(receipt_file, json.dumps(outputs["inspection"], sort_keys=True) + "\n")
|
|
119
|
+
elif action == "finish-inspect":
|
|
120
|
+
if not mapper_reviewed or inspection is None or project_dir != ".project":
|
|
121
|
+
raise StepFailed("finish-inspect requires the prepared active track and mapper review")
|
|
122
|
+
prepared = json.loads(inspection.read_text(encoding="utf-8"))
|
|
123
|
+
if prepared["repo"] != str(repo) or prepared["base"] != expected_head:
|
|
124
|
+
raise StepFailed("inspection receipt does not match repository and expected HEAD")
|
|
125
|
+
assignments = {a["task_name"]: a for a in prepared["assignments"]}
|
|
126
|
+
if len(prepared["assignments"]) != len(INSPECTION_SPECS) or set(assignments) != {s[0] for s in INSPECTION_SPECS}:
|
|
127
|
+
raise StepFailed("inspection receipt must name both original assignments")
|
|
128
|
+
for task_name, _, _, filename in INSPECTION_SPECS:
|
|
129
|
+
assignment = assignments[task_name]
|
|
130
|
+
if assignment["base"] != expected_head or assignment["output"] != f".project/research/{filename}":
|
|
131
|
+
raise StepFailed("inspection assignment changed its baseline or output")
|
|
132
|
+
inventory_file = Path(prepared["inventory_file"])
|
|
133
|
+
if hashlib.sha256(inventory_file.read_bytes()).hexdigest() != prepared["inventory_sha256"]:
|
|
134
|
+
raise StepFailed("frozen inspection inventory changed")
|
|
135
|
+
state = step("pipeline_state.py", "validate", *common)["state"]
|
|
136
|
+
if state["phase"] != "inspect" or state["status"] != "active":
|
|
137
|
+
raise StepFailed("inspection completion requires inspect/active")
|
|
138
|
+
branch = subprocess.run(["git", "branch", "--show-current"], cwd=repo,
|
|
139
|
+
capture_output=True, text=True, check=True).stdout.strip()
|
|
140
|
+
if state["branch"] != branch:
|
|
141
|
+
raise StepFailed("current branch differs from the recorded inspection branch")
|
|
142
|
+
pending = step("discussion_records.py", "pending", "--repo", str(repo))
|
|
143
|
+
if pending["pending"]:
|
|
144
|
+
raise StepFailed("pending discussion requires its owner disposition")
|
|
145
|
+
docs = assignments["inspect_docs"]
|
|
146
|
+
step("check_docs_audit.py", "--repo", docs["worktree"], "--audit", docs["output"],
|
|
147
|
+
"--inventory", str(inventory_file))
|
|
148
|
+
if f"Audited HEAD: {expected_head}" not in (Path(docs["worktree"]) / docs["output"]).read_text().splitlines():
|
|
149
|
+
raise StepFailed("audit does not name the supplied inspection baseline")
|
|
150
|
+
for task_name, _, _, _ in INSPECTION_SPECS:
|
|
151
|
+
assignment = assignments[task_name]
|
|
152
|
+
step("isolation.py", "collect-artifact", "--repo", str(repo),
|
|
153
|
+
"--source", assignment["worktree"], "--base", expected_head,
|
|
154
|
+
"--branch", assignment["branch"], "--source-path", assignment["output"],
|
|
155
|
+
"--destination-path", assignment["output"])
|
|
156
|
+
step("isolation.py", "retire", "--repo", str(repo), "--worktree", assignment["worktree"],
|
|
157
|
+
"--branch", assignment["branch"])
|
|
158
|
+
expected = [part for key, value in state.items()
|
|
159
|
+
for part in (f"--expect-{key}", "null" if value is None else str(value))]
|
|
160
|
+
step("pipeline_state.py", "transition", *common, *expected,
|
|
161
|
+
"--set-phase", "inspect", "--set-status", "done", "--event", "inspection artifacts passed")
|
|
162
|
+
elif action == "lint-round":
|
|
163
|
+
head = subprocess.run(["git", "rev-parse", "--verify", "HEAD"],
|
|
164
|
+
cwd=repo, capture_output=True, text=True, check=True).stdout.strip()
|
|
165
|
+
step("check_task_briefs.py", "--repo", str(repo), "--base", head,
|
|
166
|
+
"--tasks-dir", f"{project_dir}/tasks")
|
|
167
|
+
step("check_handoffs.py", "plan", *common)
|
|
168
|
+
elif action == "prepare-task":
|
|
169
|
+
task = step("isolation.py", "isolate-task", "--repo", str(repo),
|
|
170
|
+
"--base", expected_head, "--task-id", task_id,
|
|
171
|
+
"--round-size", str(round_size))
|
|
172
|
+
if task["mode"] == "serial":
|
|
173
|
+
step("isolation.py", "isolate-verify", "--repo", str(repo),
|
|
174
|
+
"--base", expected_head, "--name", f"task-{task_id.lower()}-verify")
|
|
175
|
+
elif action == "build-evidence":
|
|
176
|
+
proof = step("build_state.py", "verify-landed", *common, "--head", expected_head)
|
|
177
|
+
# The landing proof has one canonical home; lean final-review reuse allows only this path.
|
|
178
|
+
evidence = repo / project_dir / "build" / "evidence.json"
|
|
179
|
+
_common.atomic_write(evidence, json.dumps(proof, indent=2, sort_keys=True) + "\n")
|
|
180
|
+
steps.append({"script": "workflow_run.py", "evidence": str(evidence)})
|
|
181
|
+
elif action == "prepare-final":
|
|
182
|
+
if project_dir != ".project":
|
|
183
|
+
raise StepFailed("final review requires the active milestone")
|
|
184
|
+
pending = step("discussion_records.py", "pending", "--repo", str(repo))
|
|
185
|
+
if pending["pending"]:
|
|
186
|
+
raise StepFailed("pending discussion requires its owner disposition")
|
|
187
|
+
step("build_state.py", "verify-landed", *common, "--head", expected_head)
|
|
188
|
+
step("lean_verification.py", "--repo", str(repo), "--expected-head", expected_head)
|
|
189
|
+
else:
|
|
190
|
+
pending = step("discussion_records.py", "pending", "--repo", str(repo))
|
|
191
|
+
if pending["pending"]:
|
|
192
|
+
raise StepFailed("pending discussion requires its owner disposition")
|
|
193
|
+
step("check_handoffs.py", "plan", *common)
|
|
194
|
+
head = subprocess.run(["git", "rev-parse", "--verify", "HEAD"],
|
|
195
|
+
cwd=repo, capture_output=True, text=True, check=True).stdout.strip()
|
|
196
|
+
step("check_task_briefs.py", "--repo", str(repo), "--base", head,
|
|
197
|
+
"--tasks-dir", f"{project_dir}/tasks")
|
|
198
|
+
panel = ["validate-plan", "--plan", str(repo / project_dir / "plan/PLAN.md"),
|
|
199
|
+
"--intent", str(repo / project_dir / "intent/INTENT.md")]
|
|
200
|
+
charter = repo / ".project/CHARTER.md"
|
|
201
|
+
if charter.exists():
|
|
202
|
+
panel += ["--charter", str(charter)]
|
|
203
|
+
step("review_panel.py", *panel)
|
|
204
|
+
if action == "approve-plan":
|
|
205
|
+
step("pipeline_state.py", "approve", *common, "--kind", "plan",
|
|
206
|
+
"--expected-head", expected_head)
|
|
207
|
+
except (StepFailed, OSError, subprocess.CalledProcessError, ValueError, KeyError, TypeError) as error:
|
|
208
|
+
return {"status": "blocked", "reason": str(error), "steps": steps,
|
|
209
|
+
"next": "$gsd-path-forensics"}
|
|
210
|
+
return {"status": "complete", "steps": steps, **outputs}
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def main(argv=None):
|
|
214
|
+
parser = argparse.ArgumentParser(description=__doc__)
|
|
215
|
+
parser.add_argument("action", choices=("route", "gate-plan", "approve-plan", "build-evidence", "lint-round", "prepare-task", "prepare-final", "prepare-inspect", "finish-inspect"))
|
|
216
|
+
parser.add_argument("--repo", type=Path, required=True)
|
|
217
|
+
parser.add_argument("--project-dir", choices=(".project", ".project/next"), default=".project")
|
|
218
|
+
parser.add_argument("--expected-head")
|
|
219
|
+
parser.add_argument("--task-id")
|
|
220
|
+
parser.add_argument("--round-size", type=int)
|
|
221
|
+
parser.add_argument("--inspection", type=Path)
|
|
222
|
+
parser.add_argument("--mapper-reviewed", action="store_true")
|
|
223
|
+
arguments = parser.parse_args(argv)
|
|
224
|
+
if arguments.action in {"approve-plan", "build-evidence", "prepare-task", "prepare-final", "prepare-inspect", "finish-inspect"} and not arguments.expected_head:
|
|
225
|
+
parser.error(f"{arguments.action} requires --expected-head")
|
|
226
|
+
if arguments.action == "prepare-task" and (not arguments.task_id or arguments.round_size is None):
|
|
227
|
+
parser.error("prepare-task requires --task-id and --round-size")
|
|
228
|
+
result = run_workflow(arguments.repo.resolve(), arguments.action,
|
|
229
|
+
arguments.project_dir, arguments.expected_head,
|
|
230
|
+
arguments.task_id, arguments.round_size, arguments.inspection,
|
|
231
|
+
arguments.mapper_reviewed)
|
|
232
|
+
print(json.dumps(result, sort_keys=True))
|
|
233
|
+
return 0 if result["status"] == "complete" else 1
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
if __name__ == "__main__":
|
|
237
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# gsd-path project runtime
|
|
3
|
+
"""Placement shared by task isolation, verification, and integration."""
|
|
4
|
+
|
|
5
|
+
import sys
|
|
6
|
+
|
|
7
|
+
# Runtime helpers must not modify their immutable installation.
|
|
8
|
+
sys.dont_write_bytecode = True
|
|
9
|
+
|
|
10
|
+
import hashlib
|
|
11
|
+
import json
|
|
12
|
+
import os
|
|
13
|
+
import tempfile
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
try:
|
|
17
|
+
import _common
|
|
18
|
+
except ImportError:
|
|
19
|
+
from scripts import _common
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _git(primary: Path, *args: str) -> str:
|
|
23
|
+
result = _common.run_git(primary, *args)
|
|
24
|
+
if result.returncode:
|
|
25
|
+
raise ValueError(result.stderr.strip() or "cannot inspect worktree placement")
|
|
26
|
+
return result.stdout.rstrip("\n")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _identity(path: Path) -> str:
|
|
30
|
+
return hashlib.sha256(os.fsencode(path)).hexdigest()
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _workspace(primary: Path, pin: bool) -> Path:
|
|
34
|
+
common = Path(_git(primary, "rev-parse", "--git-common-dir"))
|
|
35
|
+
common = (primary / common).resolve()
|
|
36
|
+
identity = _identity(primary)
|
|
37
|
+
receipt = common / "gsd-path" / "workspaces" / f"{identity}.json"
|
|
38
|
+
try:
|
|
39
|
+
data = json.loads(receipt.read_text(encoding="utf-8"))
|
|
40
|
+
except FileNotFoundError:
|
|
41
|
+
pass
|
|
42
|
+
else:
|
|
43
|
+
if (not isinstance(data, dict) or data.get("primary") != str(primary)
|
|
44
|
+
or not isinstance(data.get("root"), str)
|
|
45
|
+
or not Path(data["root"]).is_absolute()):
|
|
46
|
+
raise ValueError(f"invalid worktree placement receipt: {receipt}")
|
|
47
|
+
return Path(data["root"])
|
|
48
|
+
|
|
49
|
+
root = Path(os.environ.get("GSD_PATH_WORKTREE_ROOT") or Path.home() / ".gsd-path" / "projects").expanduser()
|
|
50
|
+
if not root.is_absolute():
|
|
51
|
+
raise ValueError("GSD_PATH_WORKTREE_ROOT must be absolute")
|
|
52
|
+
root = root.resolve()
|
|
53
|
+
parent = root
|
|
54
|
+
while not parent.exists():
|
|
55
|
+
parent = parent.parent
|
|
56
|
+
ancestor = _common.run_git(parent, "rev-parse", "--git-common-dir")
|
|
57
|
+
same_repository = (
|
|
58
|
+
ancestor.returncode == 0
|
|
59
|
+
and (parent / ancestor.stdout.strip()).resolve() == common
|
|
60
|
+
)
|
|
61
|
+
if root.is_relative_to(primary) or same_repository:
|
|
62
|
+
raise ValueError(f"managed worktree root must be outside this repository's worktrees: {root}")
|
|
63
|
+
workspace = root / _identity(common) / identity
|
|
64
|
+
if pin:
|
|
65
|
+
receipt.parent.mkdir(parents=True, exist_ok=True)
|
|
66
|
+
fd, temporary = tempfile.mkstemp(dir=receipt.parent)
|
|
67
|
+
try:
|
|
68
|
+
with os.fdopen(fd, "w", encoding="utf-8") as handle:
|
|
69
|
+
json.dump({"primary": str(primary), "root": str(workspace)}, handle)
|
|
70
|
+
try:
|
|
71
|
+
os.link(temporary, receipt)
|
|
72
|
+
except FileExistsError:
|
|
73
|
+
return _workspace(primary, False)
|
|
74
|
+
finally:
|
|
75
|
+
os.unlink(temporary)
|
|
76
|
+
return workspace
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def worktree_path(primary: Path, kind: str, name: str, *, pin: bool = False) -> Path:
|
|
80
|
+
primary = primary.resolve()
|
|
81
|
+
if kind not in {"task", "verify", "integrate"} or not name or Path(name).name != name or name in {".", ".."}:
|
|
82
|
+
raise ValueError("invalid managed worktree kind or name")
|
|
83
|
+
legacy = (primary.parent / f".{primary.name}-gsd-path-integrate-{name}"
|
|
84
|
+
if kind == "integrate" else primary.parent / f"{primary.name}.gsd-path" / kind / name)
|
|
85
|
+
branch = f"refs/heads/gsd-path-{kind}/{name}"
|
|
86
|
+
records = _git(primary, "worktree", "list", "--porcelain", "-z").split("\0\0")
|
|
87
|
+
for record in records:
|
|
88
|
+
fields = record.split("\0")
|
|
89
|
+
if f"worktree {legacy}" in fields and f"branch {branch}" in fields:
|
|
90
|
+
return legacy
|
|
91
|
+
# Keep collision checks and missing-directory recovery at the old location.
|
|
92
|
+
if os.path.lexists(legacy):
|
|
93
|
+
return legacy
|
|
94
|
+
return _workspace(primary, pin) / kind / name
|
|
@@ -3,6 +3,8 @@ name: gsd-path-loop
|
|
|
3
3
|
description: Use only when the user explicitly invokes $gsd-path-loop. Runs one bounded loop pass from a LOOP.md spec — gate checks, independent verification, one fix worker, telemetry. Autonomy lives in the external scheduler that invokes this skill; the skill never schedules itself.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
+
Before executing project helpers, read [runtime selection](references/runtime-selection.md).
|
|
7
|
+
|
|
6
8
|
# GSD Path Loop
|
|
7
9
|
|
|
8
10
|
One invocation = one bounded pass. The bundled deterministic helper
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Project runtime selection
|
|
2
|
+
|
|
3
|
+
Before running a project runtime helper, check for
|
|
4
|
+
`<absolute-project>/.gsd-path/runtime.json`. When present, run the stable launcher:
|
|
5
|
+
|
|
6
|
+
```sh
|
|
7
|
+
python3 -B <absolute-project>/.gsd-path/status_runtime.py --repo <absolute-project> --runtime-path
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
Use `python` only when it is the compatible Python 3.9+ interpreter. A failure
|
|
11
|
+
stops helper execution: follow the exact-version restore action in the error.
|
|
12
|
+
Do not install, upgrade, or fall back to the current plugin's runtime implicitly.
|
|
13
|
+
|
|
14
|
+
The returned directory is the verified Project runtime. Resolve helper names
|
|
15
|
+
present in its `manifest.json` from that directory, including status, state,
|
|
16
|
+
isolation, integration, archive, recovery, build-state, final-verification, and guard helpers.
|
|
17
|
+
The workflow runner resolves its subprocess helpers from this same directory;
|
|
18
|
+
helper imports stay within the selected runtime. This rule overrides
|
|
19
|
+
references to bundled copies of those helpers. Other skill helpers, templates,
|
|
20
|
+
and role briefs remain in the installed skill bundle. Pass `-B` to Python helper
|
|
21
|
+
invocations so execution does not create bytecode in the runtime store.
|
|
22
|
+
|
|
23
|
+
With no declaration, retain the legacy helper lookup. An existing
|
|
24
|
+
`.gsd-path/runtime/` requires the explicit `--runtime-migrate --project PATH`
|
|
25
|
+
operation before adopting external storage; review the resulting Git diff.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
+
# gsd-path project runtime
|
|
2
3
|
"""Deterministic gates for a GSD Path LOOP.md loop spec.
|
|
3
4
|
|
|
4
5
|
The loop skill (a model) reads the prose sections of a LOOP.md; this helper
|
|
@@ -23,6 +24,7 @@ import os
|
|
|
23
24
|
import re
|
|
24
25
|
import subprocess
|
|
25
26
|
import sys
|
|
27
|
+
sys.dont_write_bytecode = True
|
|
26
28
|
import time
|
|
27
29
|
import uuid
|
|
28
30
|
from contextlib import contextmanager
|