@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
package/scripts/install.py
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
import argparse
|
|
5
5
|
import errno
|
|
6
|
+
import hashlib
|
|
6
7
|
import json
|
|
7
8
|
import os
|
|
8
9
|
import re
|
|
@@ -17,9 +18,11 @@ from typing import Callable, Iterable, List, Mapping, Optional, Sequence, Tuple,
|
|
|
17
18
|
sys.dont_write_bytecode = True
|
|
18
19
|
|
|
19
20
|
try:
|
|
20
|
-
from . import sync_skill_resources
|
|
21
|
+
from . import sync_skill_resources, runtime_store, status_runtime
|
|
21
22
|
except ImportError: # Direct execution from scripts/.
|
|
22
23
|
import sync_skill_resources # type: ignore
|
|
24
|
+
import runtime_store
|
|
25
|
+
import status_runtime
|
|
23
26
|
|
|
24
27
|
|
|
25
28
|
def skill_names_for_manifest(manifest: Mapping) -> Tuple[str, ...]:
|
|
@@ -46,25 +49,7 @@ CLAUDE_BRIDGE = "@../AGENTS.md\n@../WORKFLOW.md\n"
|
|
|
46
49
|
HOOKS_DIRECTORY = ".gsd-path"
|
|
47
50
|
GUARD_SCRIPTS = ("guard_hook.py", "git_guard.py")
|
|
48
51
|
GUARD_MARKER = "gsd-path guard"
|
|
49
|
-
PROJECT_RUNTIME_SCRIPTS =
|
|
50
|
-
"pipeline_state.py",
|
|
51
|
-
"check_handoffs.py",
|
|
52
|
-
"check_task_briefs.py",
|
|
53
|
-
"isolation.py",
|
|
54
|
-
"discussion_records.py",
|
|
55
|
-
"pipeline_git.py",
|
|
56
|
-
"promote_lookahead.py",
|
|
57
|
-
"detect_project.py",
|
|
58
|
-
"pipeline_diagnose.py",
|
|
59
|
-
"pipeline_undo.py",
|
|
60
|
-
"archive_milestone.py",
|
|
61
|
-
"review_panel.py",
|
|
62
|
-
"_common.py",
|
|
63
|
-
"state_checkpoint.py",
|
|
64
|
-
"state_promote.py",
|
|
65
|
-
"discussion_validate.py",
|
|
66
|
-
"integration.py",
|
|
67
|
-
)
|
|
52
|
+
PROJECT_RUNTIME_SCRIPTS = runtime_store.RUNTIME_FILES
|
|
68
53
|
PROJECT_RUNTIME_MARKER = "gsd-path project runtime"
|
|
69
54
|
PROJECT_STATUS_LAUNCHER = "status_runtime.py"
|
|
70
55
|
PROJECT_STATUS_MARKER = "gsd-path project status launcher"
|
|
@@ -886,10 +871,15 @@ def _create_install_lock(lock: Path) -> None:
|
|
|
886
871
|
raise
|
|
887
872
|
|
|
888
873
|
|
|
874
|
+
def _install_lock_path(root: Path) -> Path:
|
|
875
|
+
identity = hashlib.sha256(os.fsencode(root.resolve())).hexdigest()
|
|
876
|
+
return Path.home() / ".gsd-path" / "install-locks" / identity / INSTALL_LOCK_NAME
|
|
877
|
+
|
|
878
|
+
|
|
889
879
|
def _acquire_install_locks(roots: Iterable[Path]) -> Tuple[List[Path], List[Path]]:
|
|
890
880
|
locks: List[Path] = []
|
|
891
881
|
for root in roots:
|
|
892
|
-
candidate = root
|
|
882
|
+
candidate = _install_lock_path(root)
|
|
893
883
|
if not any(_same_path(candidate, existing) for existing in locks):
|
|
894
884
|
locks.append(candidate)
|
|
895
885
|
locks.sort(key=lambda candidate: os.path.normcase(os.fspath(candidate)))
|
|
@@ -1028,15 +1018,7 @@ def _project_destinations(
|
|
|
1028
1018
|
False,
|
|
1029
1019
|
),
|
|
1030
1020
|
]
|
|
1031
|
-
destinations.
|
|
1032
|
-
(
|
|
1033
|
-
project / HOOKS_DIRECTORY / "runtime" / name,
|
|
1034
|
-
f"scripts/{name}",
|
|
1035
|
-
None,
|
|
1036
|
-
False,
|
|
1037
|
-
)
|
|
1038
|
-
for name in PROJECT_RUNTIME_SCRIPTS
|
|
1039
|
-
)
|
|
1021
|
+
destinations.append((project / HOOKS_DIRECTORY / "runtime.json", None, "", False))
|
|
1040
1022
|
if "claude" in selected:
|
|
1041
1023
|
destinations.append(
|
|
1042
1024
|
(project / ".claude" / "CLAUDE.md", None, CLAUDE_BRIDGE, False)
|
|
@@ -1044,7 +1026,7 @@ def _project_destinations(
|
|
|
1044
1026
|
if hooks:
|
|
1045
1027
|
for name in GUARD_SCRIPTS:
|
|
1046
1028
|
destinations.append(
|
|
1047
|
-
(project / HOOKS_DIRECTORY / name,
|
|
1029
|
+
(project / HOOKS_DIRECTORY / name, None, runtime_store.guard_launcher(name), False)
|
|
1048
1030
|
)
|
|
1049
1031
|
if "claude" in selected:
|
|
1050
1032
|
destinations.append(
|
|
@@ -1104,6 +1086,8 @@ def _update_replacement(
|
|
|
1104
1086
|
the managed-file check for a replaceable destination, or None for a
|
|
1105
1087
|
kept one."""
|
|
1106
1088
|
parent = project / HOOKS_DIRECTORY
|
|
1089
|
+
if (parent / "runtime.json").is_file() and destination.parent == parent:
|
|
1090
|
+
return None # Stable wiring and selection change only through explicit operations.
|
|
1107
1091
|
directory = destination.parent
|
|
1108
1092
|
if _same_path(directory, parent / "runtime"):
|
|
1109
1093
|
return _is_managed_project_runtime
|
|
@@ -1244,6 +1228,10 @@ def _validate_project(
|
|
|
1244
1228
|
source = source_root / source_name
|
|
1245
1229
|
if source.is_symlink() or not source.is_file():
|
|
1246
1230
|
raise InstallerError(f"missing project contract: {source}")
|
|
1231
|
+
try:
|
|
1232
|
+
runtime_store.prepare(source_root, project, dry_run=True)
|
|
1233
|
+
except (OSError, ValueError) as error:
|
|
1234
|
+
raise InstallerError(str(error)) from error
|
|
1247
1235
|
mergers = _native_settings_mergers(project, selected, hooks)
|
|
1248
1236
|
for destination, _, _, _ in _project_destinations(
|
|
1249
1237
|
project, selected, hooks, interpreter, hooks_dir
|
|
@@ -1278,11 +1266,17 @@ def _apply_project(
|
|
|
1278
1266
|
hooks_dir: Optional[Path],
|
|
1279
1267
|
update: bool = False,
|
|
1280
1268
|
) -> None:
|
|
1269
|
+
try:
|
|
1270
|
+
pin = runtime_store.prepare(source_root, project)
|
|
1271
|
+
except (OSError, ValueError) as error:
|
|
1272
|
+
raise InstallerError(str(error)) from error
|
|
1281
1273
|
_create_directory(project, transaction.created_directories)
|
|
1282
1274
|
mergers = _native_settings_mergers(project, selected, hooks)
|
|
1283
1275
|
for destination, source_name, content, executable in _project_destinations(
|
|
1284
1276
|
project, selected, hooks, interpreter, hooks_dir
|
|
1285
1277
|
):
|
|
1278
|
+
if destination.name == "runtime.json" and destination.parent == project / HOOKS_DIRECTORY:
|
|
1279
|
+
content = runtime_store.pin_text(pin)
|
|
1286
1280
|
_create_directory(destination.parent, transaction.created_directories)
|
|
1287
1281
|
merge = mergers.get(destination)
|
|
1288
1282
|
if _lexists(destination) and not destination.is_symlink():
|
|
@@ -1298,7 +1292,7 @@ def _apply_project(
|
|
|
1298
1292
|
elif source_name:
|
|
1299
1293
|
replacement = (source_root / source_name).read_bytes()
|
|
1300
1294
|
else:
|
|
1301
|
-
replacement = content or ""
|
|
1295
|
+
replacement = (content or "").encode("utf-8")
|
|
1302
1296
|
_atomic_write(
|
|
1303
1297
|
destination, replacement, 0o755 if executable else mode
|
|
1304
1298
|
)
|
|
@@ -1314,9 +1308,9 @@ def _apply_project(
|
|
|
1314
1308
|
created = True
|
|
1315
1309
|
shutil.copyfileobj(source, output)
|
|
1316
1310
|
else:
|
|
1317
|
-
with destination.open("
|
|
1311
|
+
with destination.open("xb") as output:
|
|
1318
1312
|
created = True
|
|
1319
|
-
output.write(content)
|
|
1313
|
+
output.write(content.encode("utf-8"))
|
|
1320
1314
|
if executable:
|
|
1321
1315
|
destination.chmod(0o755)
|
|
1322
1316
|
transaction.copied.append(destination)
|
|
@@ -1640,7 +1634,7 @@ def _validate_hooks_refresh(
|
|
|
1640
1634
|
project / HOOKS_DIRECTORY / "runtime", "project runtime directory"
|
|
1641
1635
|
)
|
|
1642
1636
|
refresh_guards = _refreshes_guards(project, full, initialize)
|
|
1643
|
-
runtime_exists = any(
|
|
1637
|
+
runtime_exists = (project / HOOKS_DIRECTORY / "runtime.json").is_file() or any(
|
|
1644
1638
|
_lexists(project / HOOKS_DIRECTORY / "runtime" / name)
|
|
1645
1639
|
for name in PROJECT_RUNTIME_SCRIPTS
|
|
1646
1640
|
)
|
|
@@ -1731,162 +1725,63 @@ def _validate_hooks_refresh(
|
|
|
1731
1725
|
)
|
|
1732
1726
|
|
|
1733
1727
|
|
|
1734
|
-
def _refresh_hooks_unlocked(
|
|
1735
|
-
source_root: Path,
|
|
1736
|
-
project: Path,
|
|
1737
|
-
full: bool,
|
|
1738
|
-
dry_run: bool = False,
|
|
1739
|
-
selected: Sequence[str] = (),
|
|
1740
|
-
initialize: bool = False,
|
|
1741
|
-
) -> List[str]:
|
|
1742
|
-
"""Refreshed project-relative paths; "note:"-prefixed entries are
|
|
1743
|
-
user-facing notes rather than refreshed files."""
|
|
1744
|
-
hooks_dir = _git_hooks_directory(project) if full else None
|
|
1745
|
-
interpreter: Optional[str] = None
|
|
1746
|
-
if not dry_run:
|
|
1747
|
-
if full:
|
|
1748
|
-
interpreter, hooks_dir = _required_hook_runtime(
|
|
1749
|
-
project,
|
|
1750
|
-
"--hooks-init" if initialize else "--hooks-refresh-full",
|
|
1751
|
-
selected,
|
|
1752
|
-
)
|
|
1753
|
-
else:
|
|
1754
|
-
interpreter = _required_python_runtime("--hooks-refresh", selected)
|
|
1755
|
-
_validate_hooks_refresh(
|
|
1756
|
-
source_root, project, full, hooks_dir, selected, initialize
|
|
1757
|
-
)
|
|
1758
|
-
refreshed: List[str] = []
|
|
1759
|
-
refresh_guards = _refreshes_guards(project, full, initialize)
|
|
1760
|
-
runtime = project / HOOKS_DIRECTORY / "runtime"
|
|
1761
|
-
if not dry_run:
|
|
1762
|
-
runtime.parent.mkdir(parents=True, exist_ok=True)
|
|
1763
|
-
staging = Path(tempfile.mkdtemp(prefix=".runtime-stage-", dir=runtime.parent))
|
|
1764
|
-
previous = staging.with_name(staging.name + "-previous")
|
|
1765
|
-
moved_previous = False
|
|
1766
|
-
published_runtime = False
|
|
1767
|
-
launcher = runtime.parent / PROJECT_STATUS_LAUNCHER
|
|
1768
|
-
launcher_original = launcher.read_bytes() if _lexists(launcher) else None
|
|
1769
|
-
launcher_mode = (
|
|
1770
|
-
launcher.stat().st_mode & 0o777 if launcher_original is not None else None
|
|
1771
|
-
)
|
|
1772
|
-
guard_originals: List[Tuple[Path, Optional[bytes], Optional[int]]] = []
|
|
1773
|
-
try:
|
|
1774
|
-
for name in PROJECT_RUNTIME_SCRIPTS:
|
|
1775
|
-
shutil.copy2(source_root / "scripts" / name, staging / name)
|
|
1776
|
-
_atomic_copy(source_root / "scripts" / PROJECT_STATUS_LAUNCHER, launcher)
|
|
1777
|
-
if _lexists(runtime):
|
|
1778
|
-
os.replace(runtime, previous)
|
|
1779
|
-
moved_previous = True
|
|
1780
|
-
os.replace(staging, runtime)
|
|
1781
|
-
published_runtime = True
|
|
1782
|
-
if refresh_guards:
|
|
1783
|
-
for name in GUARD_SCRIPTS:
|
|
1784
|
-
destination = project / HOOKS_DIRECTORY / name
|
|
1785
|
-
original = destination.read_bytes() if _lexists(destination) else None
|
|
1786
|
-
mode = (
|
|
1787
|
-
destination.stat().st_mode & 0o777
|
|
1788
|
-
if original is not None
|
|
1789
|
-
else None
|
|
1790
|
-
)
|
|
1791
|
-
guard_originals.append((destination, original, mode))
|
|
1792
|
-
_atomic_copy(source_root / "scripts" / name, destination)
|
|
1793
|
-
if moved_previous:
|
|
1794
|
-
_remove_path(previous)
|
|
1795
|
-
except BaseException as error:
|
|
1796
|
-
for destination, original, mode in reversed(guard_originals):
|
|
1797
|
-
if original is None:
|
|
1798
|
-
_remove_path(destination)
|
|
1799
|
-
else:
|
|
1800
|
-
_atomic_write(destination, original, mode)
|
|
1801
|
-
if launcher_original is None:
|
|
1802
|
-
_remove_path(launcher)
|
|
1803
|
-
else:
|
|
1804
|
-
_atomic_write(launcher, launcher_original, launcher_mode)
|
|
1805
|
-
if published_runtime and _lexists(runtime):
|
|
1806
|
-
_remove_path(runtime)
|
|
1807
|
-
if not _lexists(runtime) and moved_previous and _lexists(previous):
|
|
1808
|
-
os.replace(previous, runtime)
|
|
1809
|
-
if isinstance(error, Exception):
|
|
1810
|
-
raise InstallerError(
|
|
1811
|
-
f"project runtime refresh failed: {error}"
|
|
1812
|
-
) from error
|
|
1813
|
-
raise
|
|
1814
|
-
finally:
|
|
1815
|
-
_remove_path(staging)
|
|
1816
|
-
for name in PROJECT_RUNTIME_SCRIPTS:
|
|
1817
|
-
refreshed.append(_describe_project_path(project, runtime / name))
|
|
1818
|
-
refreshed.append(
|
|
1819
|
-
_describe_project_path(
|
|
1820
|
-
project, project / HOOKS_DIRECTORY / PROJECT_STATUS_LAUNCHER
|
|
1821
|
-
)
|
|
1822
|
-
)
|
|
1823
|
-
if refresh_guards:
|
|
1824
|
-
for name in GUARD_SCRIPTS:
|
|
1825
|
-
destination = project / HOOKS_DIRECTORY / name
|
|
1826
|
-
refreshed.append(_describe_project_path(project, destination))
|
|
1827
|
-
if full:
|
|
1828
|
-
for target, settings, merge, generated in (
|
|
1829
|
-
(
|
|
1830
|
-
"claude",
|
|
1831
|
-
project / ".claude" / "settings.json",
|
|
1832
|
-
_merged_claude_settings,
|
|
1833
|
-
claude_hooks_settings,
|
|
1834
|
-
),
|
|
1835
|
-
(
|
|
1836
|
-
"codex",
|
|
1837
|
-
project / ".codex" / "hooks.json",
|
|
1838
|
-
_merged_codex_settings,
|
|
1839
|
-
codex_hooks_settings,
|
|
1840
|
-
),
|
|
1841
|
-
(
|
|
1842
|
-
"cursor",
|
|
1843
|
-
project / ".cursor" / "hooks.json",
|
|
1844
|
-
_merged_cursor_settings,
|
|
1845
|
-
cursor_hooks_settings,
|
|
1846
|
-
),
|
|
1847
|
-
):
|
|
1848
|
-
if initialize and target not in selected:
|
|
1849
|
-
continue
|
|
1850
|
-
exists = _lexists(settings)
|
|
1851
|
-
if exists or target in selected:
|
|
1852
|
-
if not dry_run:
|
|
1853
|
-
settings.parent.mkdir(parents=True, exist_ok=True)
|
|
1854
|
-
content = (
|
|
1855
|
-
merge(settings, interpreter)
|
|
1856
|
-
if exists
|
|
1857
|
-
else generated(interpreter)
|
|
1858
|
-
)
|
|
1859
|
-
_atomic_write(settings, content)
|
|
1860
|
-
refreshed.append(_describe_project_path(project, settings))
|
|
1861
|
-
if hooks_dir is not None:
|
|
1862
|
-
for hook_name, generator in GIT_HOOKS:
|
|
1863
|
-
hook_path = hooks_dir / hook_name
|
|
1864
|
-
if not dry_run:
|
|
1865
|
-
content = generator(interpreter)
|
|
1866
|
-
hook_path.parent.mkdir(parents=True, exist_ok=True)
|
|
1867
|
-
_atomic_write(hook_path, content, mode=0o755)
|
|
1868
|
-
refreshed.append(_describe_project_path(project, hook_path))
|
|
1869
|
-
return refreshed
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
1728
|
def refresh_hooks(
|
|
1873
|
-
source_root: Path,
|
|
1874
|
-
|
|
1875
|
-
full: bool,
|
|
1876
|
-
dry_run: bool = False,
|
|
1877
|
-
selected: Sequence[str] = (),
|
|
1878
|
-
initialize: bool = False,
|
|
1729
|
+
source_root: Path, project: Path, full: bool, dry_run: bool = False,
|
|
1730
|
+
selected: Sequence[str] = (), initialize: bool = False,
|
|
1879
1731
|
) -> List[str]:
|
|
1880
|
-
if dry_run:
|
|
1881
|
-
return _refresh_hooks_unlocked(
|
|
1882
|
-
source_root, project, full, True, selected, initialize
|
|
1883
|
-
)
|
|
1884
1732
|
_validate_directory_destination(project, "project path")
|
|
1733
|
+
if full and not dry_run:
|
|
1734
|
+
_required_hook_runtime(project, "--hooks-init" if initialize else "--hooks-refresh-full", selected)
|
|
1735
|
+
pinned = os.path.lexists(project / HOOKS_DIRECTORY / "runtime.json")
|
|
1736
|
+
if os.path.lexists(project / HOOKS_DIRECTORY / "runtime"):
|
|
1737
|
+
raise InstallerError("legacy runtime requires --runtime-migrate before refresh")
|
|
1738
|
+
if pinned:
|
|
1739
|
+
try:
|
|
1740
|
+
status_runtime.resolve_runtime(project)
|
|
1741
|
+
except (OSError, ValueError) as error:
|
|
1742
|
+
raise InstallerError(str(error)) from error
|
|
1743
|
+
_validate_hooks_refresh(source_root, project, full, _git_hooks_directory(project) if full else None, selected, initialize)
|
|
1744
|
+
if not dry_run:
|
|
1745
|
+
_required_python_runtime("--hooks-refresh", selected)
|
|
1746
|
+
elif not initialize and not _has_legacy_project_contracts(source_root, project):
|
|
1747
|
+
_validate_hooks_refresh(source_root, project, full, _git_hooks_directory(project) if full else None, selected, initialize)
|
|
1748
|
+
raise InstallerError(f"no managed GSD Path hooks or runtime found in project: {project}")
|
|
1749
|
+
if dry_run:
|
|
1750
|
+
if pinned:
|
|
1751
|
+
return ["note: selected runtime retained; use --runtime-upgrade for an explicit upgrade"]
|
|
1752
|
+
_validate_hooks_refresh(source_root, project, full,
|
|
1753
|
+
_git_hooks_directory(project) if full else None, selected, True)
|
|
1754
|
+
runtime_store.prepare(source_root, project, dry_run=True)
|
|
1755
|
+
return [".gsd-path/runtime.json", ".gsd-path/status_runtime.py"]
|
|
1885
1756
|
locks, created = _acquire_install_locks([project / HOOKS_DIRECTORY])
|
|
1886
1757
|
try:
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1758
|
+
if not pinned:
|
|
1759
|
+
interpreter = _required_python_runtime("--hooks-init", selected)
|
|
1760
|
+
hooks_dir = _git_hooks_directory(project) if full else None
|
|
1761
|
+
_validate_hooks_refresh(source_root, project, full, hooks_dir, selected, True)
|
|
1762
|
+
transaction = ProjectTransaction()
|
|
1763
|
+
try:
|
|
1764
|
+
_apply_project(source_root, project, selected, full, transaction, interpreter, hooks_dir, update=True)
|
|
1765
|
+
except BaseException:
|
|
1766
|
+
_rollback_project(transaction)
|
|
1767
|
+
raise
|
|
1768
|
+
return [".gsd-path/runtime.json", ".gsd-path/status_runtime.py"]
|
|
1769
|
+
if not full and not _has_managed_guard_wiring(project):
|
|
1770
|
+
return ["note: selected runtime retained; use --runtime-upgrade for an explicit upgrade"]
|
|
1771
|
+
interpreter = _required_python_runtime("--hooks-refresh", selected)
|
|
1772
|
+
hooks_dir = _git_hooks_directory(project) if full else None
|
|
1773
|
+
refresh_targets = list(selected)
|
|
1774
|
+
if full and not initialize:
|
|
1775
|
+
for target, relative in (("claude", ".claude/settings.json"), ("codex", ".codex/hooks.json"), ("cursor", ".cursor/hooks.json")):
|
|
1776
|
+
if (project / relative).exists() and target not in refresh_targets:
|
|
1777
|
+
refresh_targets.append(target)
|
|
1778
|
+
transaction = ProjectTransaction()
|
|
1779
|
+
try:
|
|
1780
|
+
_apply_project(source_root, project, refresh_targets, True, transaction, interpreter, hooks_dir, update=True)
|
|
1781
|
+
except BaseException:
|
|
1782
|
+
_rollback_project(transaction)
|
|
1783
|
+
raise
|
|
1784
|
+
return ["note: selected runtime retained; stable hooks initialized/refreshed"]
|
|
1890
1785
|
finally:
|
|
1891
1786
|
_release_install_locks(locks, created)
|
|
1892
1787
|
|
|
@@ -2035,6 +1930,11 @@ def _read_package_version(manifest: Path) -> Optional[str]:
|
|
|
2035
1930
|
|
|
2036
1931
|
def _validated_project_state(source_root: Path, project: Path) -> dict:
|
|
2037
1932
|
validator = source_root / "scripts" / "pipeline_state.py"
|
|
1933
|
+
if (project / HOOKS_DIRECTORY / "runtime.json").exists():
|
|
1934
|
+
try:
|
|
1935
|
+
validator = status_runtime.resolve_runtime(project) / "pipeline_state.py"
|
|
1936
|
+
except (OSError, ValueError) as error:
|
|
1937
|
+
raise InstallerError(str(error)) from error
|
|
2038
1938
|
if validator.is_symlink() or not validator.is_file():
|
|
2039
1939
|
raise InstallerError(f"canonical state validator is unavailable: {validator}")
|
|
2040
1940
|
interpreter = _required_python_runtime("--doctor")
|
|
@@ -2072,6 +1972,11 @@ def _validated_project_state(source_root: Path, project: Path) -> dict:
|
|
|
2072
1972
|
def _validate_project_runtime_status(source_root: Path, project: Path) -> None:
|
|
2073
1973
|
interpreter = _required_python_runtime("--doctor")
|
|
2074
1974
|
runtime = source_root / "scripts" / "pipeline_state.py"
|
|
1975
|
+
if (project / HOOKS_DIRECTORY / "runtime.json").exists():
|
|
1976
|
+
try:
|
|
1977
|
+
runtime = status_runtime.resolve_runtime(project) / "pipeline_state.py"
|
|
1978
|
+
except (OSError, ValueError) as error:
|
|
1979
|
+
raise InstallerError(f"runtime changed during doctor validation: {error}") from error
|
|
2075
1980
|
environment = os.environ.copy()
|
|
2076
1981
|
environment["GIT_OPTIONAL_LOCKS"] = "0"
|
|
2077
1982
|
try:
|
|
@@ -2097,6 +2002,13 @@ def _validate_project_runtime_status(source_root: Path, project: Path) -> None:
|
|
|
2097
2002
|
|
|
2098
2003
|
|
|
2099
2004
|
def _project_runtime_matches(source_root: Path, project: Path) -> bool:
|
|
2005
|
+
if (project / HOOKS_DIRECTORY / "runtime.json").exists():
|
|
2006
|
+
try:
|
|
2007
|
+
root = status_runtime.resolve_runtime(project)
|
|
2008
|
+
launcher = project / HOOKS_DIRECTORY / PROJECT_STATUS_LAUNCHER
|
|
2009
|
+
return not launcher.is_symlink() and launcher.read_bytes() == (root / PROJECT_STATUS_LAUNCHER).read_bytes()
|
|
2010
|
+
except (OSError, ValueError):
|
|
2011
|
+
return False
|
|
2100
2012
|
pairs = [
|
|
2101
2013
|
(
|
|
2102
2014
|
project / HOOKS_DIRECTORY / PROJECT_STATUS_LAUNCHER,
|
|
@@ -2368,7 +2280,15 @@ def doctor(
|
|
|
2368
2280
|
"project: .claude/CLAUDE.md exists but is not the managed bridge",
|
|
2369
2281
|
)
|
|
2370
2282
|
|
|
2283
|
+
pinned = os.path.lexists(project / HOOKS_DIRECTORY / "runtime.json")
|
|
2371
2284
|
runtime = project / HOOKS_DIRECTORY / "runtime"
|
|
2285
|
+
if pinned:
|
|
2286
|
+
try:
|
|
2287
|
+
runtime = status_runtime.resolve_runtime(project)
|
|
2288
|
+
push("ok", f"project: selected runtime {status_runtime.declaration(project)['version']}")
|
|
2289
|
+
except (OSError, ValueError) as error:
|
|
2290
|
+
push("fail", str(error))
|
|
2291
|
+
return findings
|
|
2372
2292
|
launcher = project / HOOKS_DIRECTORY / PROJECT_STATUS_LAUNCHER
|
|
2373
2293
|
runtime_current = True
|
|
2374
2294
|
if launcher.is_symlink():
|
|
@@ -2380,7 +2300,7 @@ def doctor(
|
|
|
2380
2300
|
else:
|
|
2381
2301
|
launcher_content = read_project_file(launcher, "project: status launcher")
|
|
2382
2302
|
launcher_source = read_project_file(
|
|
2383
|
-
source_root / "scripts" / PROJECT_STATUS_LAUNCHER,
|
|
2303
|
+
(runtime if pinned else source_root / "scripts") / PROJECT_STATUS_LAUNCHER,
|
|
2384
2304
|
"package: status launcher",
|
|
2385
2305
|
)
|
|
2386
2306
|
if launcher_content is None or launcher_source is None:
|
|
@@ -2421,7 +2341,7 @@ def doctor(
|
|
|
2421
2341
|
runtime_current = False
|
|
2422
2342
|
continue
|
|
2423
2343
|
source = read_project_file(
|
|
2424
|
-
source_root / "scripts" / name, f"package: runtime {name}"
|
|
2344
|
+
(runtime if pinned else source_root / "scripts") / name, f"package: runtime {name}"
|
|
2425
2345
|
)
|
|
2426
2346
|
if source is None:
|
|
2427
2347
|
runtime_current = False
|
|
@@ -2492,6 +2412,8 @@ def doctor(
|
|
|
2492
2412
|
source = read_project_file(
|
|
2493
2413
|
source_root / "scripts" / name, f"package: guard {name}"
|
|
2494
2414
|
)
|
|
2415
|
+
if pinned:
|
|
2416
|
+
source = runtime_store.guard_launcher(name).encode()
|
|
2495
2417
|
if source is None:
|
|
2496
2418
|
continue
|
|
2497
2419
|
if GUARD_MARKER.encode() not in content:
|
|
@@ -2851,12 +2773,16 @@ def parser() -> argparse.ArgumentParser:
|
|
|
2851
2773
|
for target in TARGETS:
|
|
2852
2774
|
argument_parser.add_argument(f"--{target}", action="store_true")
|
|
2853
2775
|
argument_parser.add_argument(f"--{target}-root", type=Path)
|
|
2776
|
+
argument_parser.add_argument("--adapter-request", action="store_true", help=argparse.SUPPRESS)
|
|
2854
2777
|
argument_parser.add_argument("--all", action="store_true", dest="all_targets")
|
|
2855
2778
|
argument_parser.add_argument("--update", action="store_true")
|
|
2856
2779
|
argument_parser.add_argument("--local", action="store_true")
|
|
2857
2780
|
argument_parser.add_argument("--dry-run", action="store_true")
|
|
2858
2781
|
argument_parser.add_argument("--project", type=Path)
|
|
2859
2782
|
argument_parser.add_argument("--doctor", action="store_true")
|
|
2783
|
+
runtime_actions = argument_parser.add_mutually_exclusive_group()
|
|
2784
|
+
for action in ("restore", "upgrade", "migrate"):
|
|
2785
|
+
runtime_actions.add_argument(f"--runtime-{action}", action="store_true")
|
|
2860
2786
|
argument_parser.add_argument("--hooks", action="store_true")
|
|
2861
2787
|
argument_parser.add_argument("--hooks-init", action="store_true")
|
|
2862
2788
|
argument_parser.add_argument("--hooks-refresh", action="store_true")
|
|
@@ -2873,10 +2799,51 @@ def parser() -> argparse.ArgumentParser:
|
|
|
2873
2799
|
def main(argv: Optional[Sequence[str]] = None) -> int:
|
|
2874
2800
|
argument_parser = parser()
|
|
2875
2801
|
arguments = argument_parser.parse_args(argv)
|
|
2802
|
+
if arguments.adapter_request:
|
|
2803
|
+
try:
|
|
2804
|
+
request = json.load(sys.stdin)
|
|
2805
|
+
source = Path(request["source"])
|
|
2806
|
+
project = Path(request["project"])
|
|
2807
|
+
action = request["action"]
|
|
2808
|
+
if action == "install":
|
|
2809
|
+
plans = [TargetPlan(p["name"], Path(p["root"])) for p in request["plans"]]
|
|
2810
|
+
result = install(source, plans, project=project, dry_run=request["dryRun"],
|
|
2811
|
+
hooks=request["hooks"], migrate_legacy=request["migrateLegacy"],
|
|
2812
|
+
update=request["update"])
|
|
2813
|
+
elif action == "refresh":
|
|
2814
|
+
result = refresh_hooks(source, project, request["full"], request["dryRun"],
|
|
2815
|
+
request["selected"], request["initialize"])
|
|
2816
|
+
elif action == "doctor":
|
|
2817
|
+
result = doctor(source, request["targets"], lambda target: Path(request["roots"][target]), project)
|
|
2818
|
+
else:
|
|
2819
|
+
raise InstallerError("unknown installer adapter action")
|
|
2820
|
+
print(json.dumps(result))
|
|
2821
|
+
return 0
|
|
2822
|
+
except (InstallerError, OSError, ValueError, KeyError) as error:
|
|
2823
|
+
print(str(error), file=sys.stderr)
|
|
2824
|
+
return 1
|
|
2876
2825
|
source_root = absolute_path(arguments.source_root)
|
|
2877
2826
|
project = (
|
|
2878
2827
|
absolute_path(arguments.project) if arguments.project is not None else None
|
|
2879
2828
|
)
|
|
2829
|
+
runtime_action = next((action for action in ("restore", "upgrade", "migrate")
|
|
2830
|
+
if getattr(arguments, "runtime_" + action)), None)
|
|
2831
|
+
if runtime_action:
|
|
2832
|
+
if project is None:
|
|
2833
|
+
argument_parser.error(f"--runtime-{runtime_action} requires --project")
|
|
2834
|
+
try:
|
|
2835
|
+
_validate_project_git_root(project)
|
|
2836
|
+
locks, created = ([], []) if arguments.dry_run else _acquire_install_locks([project / HOOKS_DIRECTORY])
|
|
2837
|
+
try:
|
|
2838
|
+
pin = runtime_store.operate(source_root, project, runtime_action, dry_run=arguments.dry_run)
|
|
2839
|
+
finally:
|
|
2840
|
+
_release_install_locks(locks, created)
|
|
2841
|
+
print(f"runtime: {runtime_action} {pin['version']} ({pin['digest']})"
|
|
2842
|
+
+ (" (dry run)" if arguments.dry_run else ""))
|
|
2843
|
+
return 0
|
|
2844
|
+
except (InstallerError, OSError, ValueError) as error:
|
|
2845
|
+
print(f"error: {error}", file=sys.stderr)
|
|
2846
|
+
return 1
|
|
2880
2847
|
if arguments.doctor:
|
|
2881
2848
|
named = [target for target in TARGETS if getattr(arguments, target)]
|
|
2882
2849
|
selected = named if named and not arguments.all_targets else list(TARGETS)
|