@opengsd/gsd-path 1.4.0 → 1.6.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/CHANGELOG.md +460 -341
- package/DOCS.md +16 -5
- package/FULL.md +67 -6
- package/HOOKS.md +158 -10
- package/MIGRATE.md +12 -0
- package/QUICK.md +4 -2
- package/README.md +136 -116
- package/RUNTIME.md +24 -6
- package/UPDATE.md +39 -3
- package/WORKFLOW.md +80 -4
- package/package.json +5 -2
- package/platforms/shared-agents/dispatch.md +13 -0
- package/scripts/_common.py +256 -2
- package/scripts/archive_milestone.py +14 -13
- package/scripts/build_recovery.py +155 -58
- package/scripts/build_state.py +274 -8
- package/scripts/check_docs_audit.py +77 -4
- package/scripts/check_handoffs.py +635 -57
- package/scripts/check_task_briefs.py +293 -32
- package/scripts/detect_project.py +260 -20
- package/scripts/discussion_records.py +9 -1
- package/scripts/discussion_validate.py +93 -35
- package/scripts/dispatch_driver.py +549 -53
- package/scripts/git_guard.py +27 -8
- package/scripts/guard_hook.py +2630 -210
- package/scripts/install.mjs +99 -11
- package/scripts/install.py +231 -46
- package/scripts/integration.py +244 -65
- package/scripts/isolation.py +539 -70
- package/scripts/loop_run.py +16 -4
- package/scripts/members.py +77 -32
- package/scripts/migrate_core.py +2 -0
- package/scripts/model_policy.py +5 -1
- package/scripts/path_config.py +3 -3
- package/scripts/pipeline_diagnose.py +17 -2
- package/scripts/pipeline_git.py +131 -42
- package/scripts/pipeline_state.py +139 -39
- package/scripts/pipeline_undo.py +118 -16
- package/scripts/promote_lookahead.py +3 -3
- package/scripts/review_findings.py +180 -44
- package/scripts/roadmap.py +9 -1
- package/scripts/runtime_store.py +21 -2
- package/scripts/skill-resources.json +9 -2
- package/scripts/state_checkpoint.py +39 -36
- package/scripts/state_promote.py +15 -4
- package/scripts/status_runtime.py +22 -4
- package/scripts/task_context.py +14 -3
- package/scripts/wizard.mjs +1 -0
- package/scripts/workflow_run.py +14 -4
- package/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path/DEFINE.md +34 -5
- package/skills/gsd-path/PLAN.md +14 -3
- package/skills/gsd-path/RESEARCH.md +11 -0
- package/skills/gsd-path/ROADMAP.md +16 -6
- package/skills/gsd-path/SHIP.md +32 -5
- package/skills/gsd-path/SKILL.md +52 -24
- package/skills/gsd-path/references/build-native.md +112 -10
- package/skills/gsd-path/references/build-recovery.md +13 -0
- package/skills/gsd-path/references/coder.md +7 -3
- package/skills/gsd-path/references/dispatch.md +13 -0
- package/skills/gsd-path/references/docs-auditor.md +5 -0
- package/skills/gsd-path/references/operating-rules.md +11 -3
- package/skills/gsd-path/references/planner.md +26 -4
- package/skills/gsd-path/references/reviewer-final.md +20 -2
- package/skills/gsd-path/references/reviewer-wave.md +56 -12
- package/skills/gsd-path/references/reviewer.md +3 -1
- package/skills/gsd-path/references/runtime-selection.md +9 -0
- package/skills/gsd-path/references/spec-probes.md +150 -0
- package/skills/gsd-path/scripts/_common.py +256 -2
- package/skills/gsd-path/scripts/archive_milestone.py +14 -13
- package/skills/gsd-path/scripts/build_recovery.py +155 -58
- package/skills/gsd-path/scripts/build_state.py +274 -8
- package/skills/gsd-path/scripts/check_docs_audit.py +77 -4
- package/skills/gsd-path/scripts/check_handoffs.py +635 -57
- package/skills/gsd-path/scripts/check_task_briefs.py +293 -32
- package/skills/gsd-path/scripts/detect_project.py +260 -20
- package/skills/gsd-path/scripts/discussion_records.py +9 -1
- package/skills/gsd-path/scripts/discussion_validate.py +93 -35
- package/skills/gsd-path/scripts/dispatch_driver.py +549 -53
- package/skills/gsd-path/scripts/git_guard.py +27 -8
- package/skills/gsd-path/scripts/integration.py +244 -65
- package/skills/gsd-path/scripts/isolation.py +539 -70
- package/skills/gsd-path/scripts/loop_run.py +16 -4
- package/skills/gsd-path/scripts/members.py +77 -32
- package/skills/gsd-path/scripts/model_policy.py +5 -1
- package/skills/gsd-path/scripts/path_config.py +3 -3
- package/skills/gsd-path/scripts/pipeline_git.py +131 -42
- package/skills/gsd-path/scripts/pipeline_state.py +139 -39
- package/skills/gsd-path/scripts/promote_lookahead.py +3 -3
- package/skills/gsd-path/scripts/review_findings.py +180 -44
- package/skills/gsd-path/scripts/roadmap.py +9 -1
- package/skills/gsd-path/scripts/state_checkpoint.py +39 -36
- package/skills/gsd-path/scripts/state_promote.py +15 -4
- package/skills/gsd-path/scripts/status_runtime.py +22 -4
- package/skills/gsd-path/scripts/task_context.py +14 -3
- package/skills/gsd-path/scripts/workflow_run.py +14 -4
- package/skills/gsd-path/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path/templates/docs-audit.md +5 -1
- package/skills/gsd-path/templates/final-review.md +11 -2
- package/skills/gsd-path/templates/intent.md +30 -0
- package/skills/gsd-path/templates/patch-findings.md +3 -3
- package/skills/gsd-path/templates/plan.md +17 -2
- package/skills/gsd-path/templates/research-handoff.md +14 -3
- package/skills/gsd-path/templates/state.md +2 -1
- package/skills/gsd-path/templates/task.md +1 -0
- package/skills/gsd-path/templates/wave-review.md +28 -9
- package/skills/gsd-path-build/references/build-native.md +112 -10
- package/skills/gsd-path-build/references/build-recovery.md +13 -0
- package/skills/gsd-path-build/references/coder.md +7 -3
- package/skills/gsd-path-build/references/dispatch.md +13 -0
- package/skills/gsd-path-build/references/operating-rules.md +11 -3
- package/skills/gsd-path-build/references/reviewer-final.md +20 -2
- package/skills/gsd-path-build/references/reviewer-wave.md +56 -12
- package/skills/gsd-path-build/references/reviewer.md +3 -1
- package/skills/gsd-path-build/references/runtime-selection.md +9 -0
- package/skills/gsd-path-build/references/spec-probes.md +150 -0
- package/skills/gsd-path-build/scripts/_common.py +256 -2
- package/skills/gsd-path-build/scripts/archive_milestone.py +14 -13
- package/skills/gsd-path-build/scripts/build_recovery.py +155 -58
- package/skills/gsd-path-build/scripts/build_state.py +274 -8
- package/skills/gsd-path-build/scripts/check_handoffs.py +635 -57
- package/skills/gsd-path-build/scripts/check_task_briefs.py +293 -32
- package/skills/gsd-path-build/scripts/detect_project.py +260 -20
- package/skills/gsd-path-build/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-build/scripts/discussion_validate.py +93 -35
- package/skills/gsd-path-build/scripts/dispatch_driver.py +549 -53
- package/skills/gsd-path-build/scripts/integration.py +244 -65
- package/skills/gsd-path-build/scripts/isolation.py +539 -70
- package/skills/gsd-path-build/scripts/loop_run.py +16 -4
- package/skills/gsd-path-build/scripts/members.py +77 -32
- package/skills/gsd-path-build/scripts/model_policy.py +5 -1
- package/skills/gsd-path-build/scripts/path_config.py +3 -3
- package/skills/gsd-path-build/scripts/pipeline_git.py +131 -42
- package/skills/gsd-path-build/scripts/pipeline_state.py +139 -39
- package/skills/gsd-path-build/scripts/promote_lookahead.py +3 -3
- package/skills/gsd-path-build/scripts/review_findings.py +180 -44
- package/skills/gsd-path-build/scripts/roadmap.py +9 -1
- package/skills/gsd-path-build/scripts/state_checkpoint.py +39 -36
- package/skills/gsd-path-build/scripts/state_promote.py +15 -4
- package/skills/gsd-path-build/scripts/task_context.py +14 -3
- package/skills/gsd-path-build/scripts/workflow_run.py +14 -4
- package/skills/gsd-path-build/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path-build/templates/task.md +1 -0
- package/skills/gsd-path-build/templates/wave-review.md +28 -9
- package/skills/gsd-path-decide/references/dispatch.md +13 -0
- package/skills/gsd-path-decide/references/operating-rules.md +11 -3
- package/skills/gsd-path-decide/references/runtime-selection.md +9 -0
- package/skills/gsd-path-decide/scripts/_common.py +256 -2
- package/skills/gsd-path-decide/scripts/archive_milestone.py +14 -13
- package/skills/gsd-path-decide/scripts/build_recovery.py +155 -58
- package/skills/gsd-path-decide/scripts/check_handoffs.py +635 -57
- package/skills/gsd-path-decide/scripts/check_task_briefs.py +293 -32
- package/skills/gsd-path-decide/scripts/detect_project.py +260 -20
- package/skills/gsd-path-decide/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-decide/scripts/discussion_validate.py +93 -35
- package/skills/gsd-path-decide/scripts/integration.py +244 -65
- package/skills/gsd-path-decide/scripts/isolation.py +539 -70
- package/skills/gsd-path-decide/scripts/loop_run.py +16 -4
- package/skills/gsd-path-decide/scripts/members.py +77 -32
- package/skills/gsd-path-decide/scripts/model_policy.py +5 -1
- package/skills/gsd-path-decide/scripts/path_config.py +3 -3
- package/skills/gsd-path-decide/scripts/pipeline_git.py +131 -42
- package/skills/gsd-path-decide/scripts/pipeline_state.py +139 -39
- package/skills/gsd-path-decide/scripts/promote_lookahead.py +3 -3
- package/skills/gsd-path-decide/scripts/roadmap.py +9 -1
- package/skills/gsd-path-decide/scripts/state_checkpoint.py +39 -36
- package/skills/gsd-path-decide/scripts/state_promote.py +15 -4
- package/skills/gsd-path-decide/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path-define/SKILL.md +34 -5
- package/skills/gsd-path-define/references/build-recovery.md +13 -0
- package/skills/gsd-path-define/references/operating-rules.md +11 -3
- package/skills/gsd-path-define/references/runtime-selection.md +9 -0
- package/skills/gsd-path-define/references/spec-probes.md +150 -0
- package/skills/gsd-path-define/scripts/_common.py +256 -2
- package/skills/gsd-path-define/scripts/archive_milestone.py +14 -13
- package/skills/gsd-path-define/scripts/build_recovery.py +155 -58
- package/skills/gsd-path-define/scripts/check_handoffs.py +635 -57
- package/skills/gsd-path-define/scripts/check_task_briefs.py +293 -32
- package/skills/gsd-path-define/scripts/detect_project.py +260 -20
- package/skills/gsd-path-define/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-define/scripts/discussion_validate.py +93 -35
- package/skills/gsd-path-define/scripts/integration.py +244 -65
- package/skills/gsd-path-define/scripts/isolation.py +539 -70
- package/skills/gsd-path-define/scripts/loop_run.py +16 -4
- package/skills/gsd-path-define/scripts/members.py +77 -32
- package/skills/gsd-path-define/scripts/model_policy.py +5 -1
- package/skills/gsd-path-define/scripts/path_config.py +3 -3
- package/skills/gsd-path-define/scripts/pipeline_git.py +131 -42
- package/skills/gsd-path-define/scripts/pipeline_state.py +139 -39
- package/skills/gsd-path-define/scripts/promote_lookahead.py +3 -3
- package/skills/gsd-path-define/scripts/roadmap.py +9 -1
- package/skills/gsd-path-define/scripts/state_checkpoint.py +39 -36
- package/skills/gsd-path-define/scripts/state_promote.py +15 -4
- package/skills/gsd-path-define/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path-define/templates/intent.md +30 -0
- package/skills/gsd-path-define/templates/state.md +2 -1
- package/skills/gsd-path-discuss/references/operating-rules.md +11 -3
- package/skills/gsd-path-discuss/references/runtime-selection.md +9 -0
- package/skills/gsd-path-discuss/scripts/_common.py +256 -2
- package/skills/gsd-path-discuss/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-discuss/scripts/loop_run.py +16 -4
- package/skills/gsd-path-discuss/scripts/model_policy.py +5 -1
- package/skills/gsd-path-discuss/scripts/path_config.py +3 -3
- package/skills/gsd-path-discuss/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path-docs-audit/references/dispatch.md +13 -0
- package/skills/gsd-path-docs-audit/references/docs-auditor.md +5 -0
- package/skills/gsd-path-docs-audit/references/operating-rules.md +11 -3
- package/skills/gsd-path-docs-audit/references/runtime-selection.md +9 -0
- package/skills/gsd-path-docs-audit/scripts/_common.py +256 -2
- package/skills/gsd-path-docs-audit/scripts/archive_milestone.py +14 -13
- package/skills/gsd-path-docs-audit/scripts/build_recovery.py +155 -58
- package/skills/gsd-path-docs-audit/scripts/check_docs_audit.py +77 -4
- package/skills/gsd-path-docs-audit/scripts/check_handoffs.py +635 -57
- package/skills/gsd-path-docs-audit/scripts/check_task_briefs.py +293 -32
- package/skills/gsd-path-docs-audit/scripts/detect_project.py +260 -20
- package/skills/gsd-path-docs-audit/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-docs-audit/scripts/discussion_validate.py +93 -35
- package/skills/gsd-path-docs-audit/scripts/integration.py +244 -65
- package/skills/gsd-path-docs-audit/scripts/isolation.py +539 -70
- package/skills/gsd-path-docs-audit/scripts/loop_run.py +16 -4
- package/skills/gsd-path-docs-audit/scripts/members.py +77 -32
- package/skills/gsd-path-docs-audit/scripts/model_policy.py +5 -1
- package/skills/gsd-path-docs-audit/scripts/path_config.py +3 -3
- package/skills/gsd-path-docs-audit/scripts/pipeline_git.py +131 -42
- package/skills/gsd-path-docs-audit/scripts/pipeline_state.py +139 -39
- package/skills/gsd-path-docs-audit/scripts/promote_lookahead.py +3 -3
- package/skills/gsd-path-docs-audit/scripts/roadmap.py +9 -1
- package/skills/gsd-path-docs-audit/scripts/state_checkpoint.py +39 -36
- package/skills/gsd-path-docs-audit/scripts/state_promote.py +15 -4
- package/skills/gsd-path-docs-audit/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path-docs-audit/templates/docs-audit.md +5 -1
- package/skills/gsd-path-forensics/references/operating-rules.md +11 -3
- package/skills/gsd-path-forensics/references/runtime-selection.md +9 -0
- package/skills/gsd-path-forensics/scripts/_common.py +256 -2
- package/skills/gsd-path-forensics/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-forensics/scripts/loop_run.py +16 -4
- package/skills/gsd-path-forensics/scripts/model_policy.py +5 -1
- package/skills/gsd-path-forensics/scripts/path_config.py +3 -3
- package/skills/gsd-path-forensics/scripts/pipeline_diagnose.py +17 -2
- package/skills/gsd-path-forensics/scripts/pipeline_undo.py +118 -16
- package/skills/gsd-path-forensics/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path-inspect/references/dispatch.md +13 -0
- package/skills/gsd-path-inspect/references/docs-auditor.md +5 -0
- package/skills/gsd-path-inspect/references/operating-rules.md +11 -3
- package/skills/gsd-path-inspect/references/runtime-selection.md +9 -0
- package/skills/gsd-path-inspect/scripts/_common.py +256 -2
- package/skills/gsd-path-inspect/scripts/archive_milestone.py +14 -13
- package/skills/gsd-path-inspect/scripts/build_recovery.py +155 -58
- package/skills/gsd-path-inspect/scripts/check_docs_audit.py +77 -4
- package/skills/gsd-path-inspect/scripts/check_handoffs.py +635 -57
- package/skills/gsd-path-inspect/scripts/check_task_briefs.py +293 -32
- package/skills/gsd-path-inspect/scripts/detect_project.py +260 -20
- package/skills/gsd-path-inspect/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-inspect/scripts/discussion_validate.py +93 -35
- package/skills/gsd-path-inspect/scripts/integration.py +244 -65
- package/skills/gsd-path-inspect/scripts/isolation.py +539 -70
- package/skills/gsd-path-inspect/scripts/loop_run.py +16 -4
- package/skills/gsd-path-inspect/scripts/members.py +77 -32
- package/skills/gsd-path-inspect/scripts/model_policy.py +5 -1
- package/skills/gsd-path-inspect/scripts/path_config.py +3 -3
- package/skills/gsd-path-inspect/scripts/pipeline_git.py +131 -42
- package/skills/gsd-path-inspect/scripts/pipeline_state.py +139 -39
- package/skills/gsd-path-inspect/scripts/promote_lookahead.py +3 -3
- package/skills/gsd-path-inspect/scripts/roadmap.py +9 -1
- package/skills/gsd-path-inspect/scripts/state_checkpoint.py +39 -36
- package/skills/gsd-path-inspect/scripts/state_promote.py +15 -4
- package/skills/gsd-path-inspect/scripts/workflow_run.py +14 -4
- package/skills/gsd-path-inspect/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path-inspect/templates/docs-audit.md +5 -1
- package/skills/gsd-path-inspect/templates/state.md +2 -1
- package/skills/gsd-path-loop/references/operating-rules.md +11 -3
- package/skills/gsd-path-loop/references/runtime-selection.md +9 -0
- package/skills/gsd-path-loop/scripts/_common.py +256 -2
- package/skills/gsd-path-loop/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-loop/scripts/loop_run.py +16 -4
- package/skills/gsd-path-loop/scripts/model_policy.py +5 -1
- package/skills/gsd-path-loop/scripts/path_config.py +3 -3
- package/skills/gsd-path-loop/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path-migrate/SKILL.md +8 -0
- package/skills/gsd-path-migrate/references/operating-rules.md +11 -3
- package/skills/gsd-path-migrate/references/runtime-selection.md +9 -0
- package/skills/gsd-path-migrate/scripts/_common.py +256 -2
- package/skills/gsd-path-migrate/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-migrate/scripts/loop_run.py +16 -4
- package/skills/gsd-path-migrate/scripts/migrate_core.py +2 -0
- package/skills/gsd-path-migrate/scripts/model_policy.py +5 -1
- package/skills/gsd-path-migrate/scripts/path_config.py +3 -3
- package/skills/gsd-path-plan/SKILL.md +14 -3
- package/skills/gsd-path-plan/references/build-recovery.md +13 -0
- package/skills/gsd-path-plan/references/dispatch.md +13 -0
- package/skills/gsd-path-plan/references/operating-rules.md +11 -3
- package/skills/gsd-path-plan/references/planner.md +26 -4
- package/skills/gsd-path-plan/references/runtime-selection.md +9 -0
- package/skills/gsd-path-plan/references/spec-probes.md +150 -0
- package/skills/gsd-path-plan/scripts/_common.py +256 -2
- package/skills/gsd-path-plan/scripts/archive_milestone.py +14 -13
- package/skills/gsd-path-plan/scripts/build_recovery.py +155 -58
- package/skills/gsd-path-plan/scripts/check_handoffs.py +635 -57
- package/skills/gsd-path-plan/scripts/check_task_briefs.py +293 -32
- package/skills/gsd-path-plan/scripts/detect_project.py +260 -20
- package/skills/gsd-path-plan/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-plan/scripts/discussion_validate.py +93 -35
- package/skills/gsd-path-plan/scripts/integration.py +244 -65
- package/skills/gsd-path-plan/scripts/isolation.py +539 -70
- package/skills/gsd-path-plan/scripts/loop_run.py +16 -4
- package/skills/gsd-path-plan/scripts/members.py +77 -32
- package/skills/gsd-path-plan/scripts/model_policy.py +5 -1
- package/skills/gsd-path-plan/scripts/path_config.py +3 -3
- package/skills/gsd-path-plan/scripts/pipeline_git.py +131 -42
- package/skills/gsd-path-plan/scripts/pipeline_state.py +139 -39
- package/skills/gsd-path-plan/scripts/promote_lookahead.py +3 -3
- package/skills/gsd-path-plan/scripts/roadmap.py +9 -1
- package/skills/gsd-path-plan/scripts/state_checkpoint.py +39 -36
- package/skills/gsd-path-plan/scripts/state_promote.py +15 -4
- package/skills/gsd-path-plan/scripts/workflow_run.py +14 -4
- package/skills/gsd-path-plan/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path-plan/templates/patch-findings.md +3 -3
- package/skills/gsd-path-plan/templates/plan.md +17 -2
- package/skills/gsd-path-plan/templates/task.md +1 -0
- package/skills/gsd-path-research/SKILL.md +11 -0
- package/skills/gsd-path-research/references/dispatch.md +13 -0
- package/skills/gsd-path-research/references/operating-rules.md +11 -3
- package/skills/gsd-path-research/references/runtime-selection.md +9 -0
- package/skills/gsd-path-research/scripts/_common.py +256 -2
- package/skills/gsd-path-research/scripts/archive_milestone.py +14 -13
- package/skills/gsd-path-research/scripts/build_recovery.py +155 -58
- package/skills/gsd-path-research/scripts/check_handoffs.py +635 -57
- package/skills/gsd-path-research/scripts/check_task_briefs.py +293 -32
- package/skills/gsd-path-research/scripts/detect_project.py +260 -20
- package/skills/gsd-path-research/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-research/scripts/discussion_validate.py +93 -35
- package/skills/gsd-path-research/scripts/integration.py +244 -65
- package/skills/gsd-path-research/scripts/isolation.py +539 -70
- package/skills/gsd-path-research/scripts/loop_run.py +16 -4
- package/skills/gsd-path-research/scripts/members.py +77 -32
- package/skills/gsd-path-research/scripts/model_policy.py +5 -1
- package/skills/gsd-path-research/scripts/path_config.py +3 -3
- package/skills/gsd-path-research/scripts/pipeline_git.py +131 -42
- package/skills/gsd-path-research/scripts/pipeline_state.py +139 -39
- package/skills/gsd-path-research/scripts/promote_lookahead.py +3 -3
- package/skills/gsd-path-research/scripts/roadmap.py +9 -1
- package/skills/gsd-path-research/scripts/state_checkpoint.py +39 -36
- package/skills/gsd-path-research/scripts/state_promote.py +15 -4
- package/skills/gsd-path-research/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path-research/templates/research-handoff.md +14 -3
- package/skills/gsd-path-roadmap/SKILL.md +16 -6
- package/skills/gsd-path-roadmap/references/dispatch.md +13 -0
- package/skills/gsd-path-roadmap/references/operating-rules.md +11 -3
- package/skills/gsd-path-roadmap/references/runtime-selection.md +9 -0
- package/skills/gsd-path-roadmap/scripts/_common.py +256 -2
- package/skills/gsd-path-roadmap/scripts/archive_milestone.py +14 -13
- package/skills/gsd-path-roadmap/scripts/build_recovery.py +155 -58
- package/skills/gsd-path-roadmap/scripts/check_handoffs.py +635 -57
- package/skills/gsd-path-roadmap/scripts/check_task_briefs.py +293 -32
- package/skills/gsd-path-roadmap/scripts/detect_project.py +260 -20
- package/skills/gsd-path-roadmap/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-roadmap/scripts/discussion_validate.py +93 -35
- package/skills/gsd-path-roadmap/scripts/integration.py +244 -65
- package/skills/gsd-path-roadmap/scripts/isolation.py +539 -70
- package/skills/gsd-path-roadmap/scripts/loop_run.py +16 -4
- package/skills/gsd-path-roadmap/scripts/members.py +77 -32
- package/skills/gsd-path-roadmap/scripts/model_policy.py +5 -1
- package/skills/gsd-path-roadmap/scripts/path_config.py +3 -3
- package/skills/gsd-path-roadmap/scripts/pipeline_git.py +131 -42
- package/skills/gsd-path-roadmap/scripts/pipeline_state.py +139 -39
- package/skills/gsd-path-roadmap/scripts/promote_lookahead.py +3 -3
- package/skills/gsd-path-roadmap/scripts/roadmap.py +9 -1
- package/skills/gsd-path-roadmap/scripts/state_checkpoint.py +39 -36
- package/skills/gsd-path-roadmap/scripts/state_promote.py +15 -4
- package/skills/gsd-path-roadmap/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path-ship/SKILL.md +32 -5
- package/skills/gsd-path-ship/references/dispatch.md +13 -0
- package/skills/gsd-path-ship/references/operating-rules.md +11 -3
- package/skills/gsd-path-ship/references/reviewer-final.md +20 -2
- package/skills/gsd-path-ship/references/reviewer-wave.md +56 -12
- package/skills/gsd-path-ship/references/reviewer.md +3 -1
- package/skills/gsd-path-ship/references/runtime-selection.md +9 -0
- package/skills/gsd-path-ship/references/spec-probes.md +150 -0
- package/skills/gsd-path-ship/scripts/_common.py +256 -2
- package/skills/gsd-path-ship/scripts/archive_milestone.py +14 -13
- package/skills/gsd-path-ship/scripts/build_recovery.py +155 -58
- package/skills/gsd-path-ship/scripts/build_state.py +274 -8
- package/skills/gsd-path-ship/scripts/check_handoffs.py +635 -57
- package/skills/gsd-path-ship/scripts/check_task_briefs.py +293 -32
- package/skills/gsd-path-ship/scripts/detect_project.py +260 -20
- package/skills/gsd-path-ship/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-ship/scripts/discussion_validate.py +93 -35
- package/skills/gsd-path-ship/scripts/integration.py +244 -65
- package/skills/gsd-path-ship/scripts/isolation.py +539 -70
- package/skills/gsd-path-ship/scripts/loop_run.py +16 -4
- package/skills/gsd-path-ship/scripts/members.py +77 -32
- package/skills/gsd-path-ship/scripts/model_policy.py +5 -1
- package/skills/gsd-path-ship/scripts/path_config.py +3 -3
- package/skills/gsd-path-ship/scripts/pipeline_git.py +131 -42
- package/skills/gsd-path-ship/scripts/pipeline_state.py +139 -39
- package/skills/gsd-path-ship/scripts/promote_lookahead.py +3 -3
- package/skills/gsd-path-ship/scripts/roadmap.py +9 -1
- package/skills/gsd-path-ship/scripts/state_checkpoint.py +39 -36
- package/skills/gsd-path-ship/scripts/state_promote.py +15 -4
- package/skills/gsd-path-ship/scripts/workflow_run.py +14 -4
- package/skills/gsd-path-ship/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path-ship/templates/final-review.md +11 -2
- package/skills/gsd-path-ship/templates/patch-findings.md +3 -3
- package/skills/gsd-path-ship/templates/wave-review.md +28 -9
- package/skills/gsd-path-undo/references/operating-rules.md +11 -3
- package/skills/gsd-path-undo/references/runtime-selection.md +9 -0
- package/skills/gsd-path-undo/scripts/_common.py +256 -2
- package/skills/gsd-path-undo/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-undo/scripts/loop_run.py +16 -4
- package/skills/gsd-path-undo/scripts/model_policy.py +5 -1
- package/skills/gsd-path-undo/scripts/path_config.py +3 -3
- package/skills/gsd-path-undo/scripts/pipeline_undo.py +118 -16
- package/skills/gsd-path-undo/scripts/worktree_paths.py +54 -2
- package/skills/path/DEFINE.md +34 -5
- package/skills/path/PLAN.md +14 -3
- package/skills/path/RESEARCH.md +11 -0
- package/skills/path/ROADMAP.md +16 -6
- package/skills/path/SHIP.md +32 -5
- package/skills/path/SKILL.md +52 -24
- package/skills/path/references/build-native.md +112 -10
- package/skills/path/references/build-recovery.md +13 -0
- package/skills/path/references/coder.md +7 -3
- package/skills/path/references/dispatch.md +13 -0
- package/skills/path/references/docs-auditor.md +5 -0
- package/skills/path/references/operating-rules.md +11 -3
- package/skills/path/references/planner.md +26 -4
- package/skills/path/references/reviewer-final.md +20 -2
- package/skills/path/references/reviewer-wave.md +56 -12
- package/skills/path/references/reviewer.md +3 -1
- package/skills/path/references/runtime-selection.md +9 -0
- package/skills/path/references/spec-probes.md +150 -0
- package/skills/path/scripts/_common.py +256 -2
- package/skills/path/scripts/archive_milestone.py +14 -13
- package/skills/path/scripts/build_recovery.py +155 -58
- package/skills/path/scripts/build_state.py +274 -8
- package/skills/path/scripts/check_docs_audit.py +77 -4
- package/skills/path/scripts/check_handoffs.py +635 -57
- package/skills/path/scripts/check_task_briefs.py +293 -32
- package/skills/path/scripts/detect_project.py +260 -20
- package/skills/path/scripts/discussion_records.py +9 -1
- package/skills/path/scripts/discussion_validate.py +93 -35
- package/skills/path/scripts/dispatch_driver.py +549 -53
- package/skills/path/scripts/git_guard.py +27 -8
- package/skills/path/scripts/integration.py +244 -65
- package/skills/path/scripts/isolation.py +539 -70
- package/skills/path/scripts/loop_run.py +16 -4
- package/skills/path/scripts/members.py +77 -32
- package/skills/path/scripts/model_policy.py +5 -1
- package/skills/path/scripts/path_config.py +3 -3
- package/skills/path/scripts/pipeline_git.py +131 -42
- package/skills/path/scripts/pipeline_state.py +139 -39
- package/skills/path/scripts/promote_lookahead.py +3 -3
- package/skills/path/scripts/review_findings.py +180 -44
- package/skills/path/scripts/roadmap.py +9 -1
- package/skills/path/scripts/state_checkpoint.py +39 -36
- package/skills/path/scripts/state_promote.py +15 -4
- package/skills/path/scripts/status_runtime.py +22 -4
- package/skills/path/scripts/task_context.py +14 -3
- package/skills/path/scripts/workflow_run.py +14 -4
- package/skills/path/scripts/worktree_paths.py +54 -2
- package/skills/path/templates/docs-audit.md +5 -1
- package/skills/path/templates/final-review.md +11 -2
- package/skills/path/templates/intent.md +30 -0
- package/skills/path/templates/patch-findings.md +3 -3
- package/skills/path/templates/plan.md +17 -2
- package/skills/path/templates/research-handoff.md +14 -3
- package/skills/path/templates/state.md +2 -1
- package/skills/path/templates/task.md +1 -0
- package/skills/path/templates/wave-review.md +28 -9
- 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-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-inspect/scripts/__pycache__/_common.cpython-312.pyc +0 -0
- package/skills/gsd-path-plan/scripts/__pycache__/_common.cpython-312.pyc +0 -0
- package/skills/gsd-path-ship/scripts/__pycache__/_common.cpython-312.pyc +0 -0
|
@@ -17,10 +17,12 @@ import os
|
|
|
17
17
|
import re
|
|
18
18
|
import shutil
|
|
19
19
|
import sys
|
|
20
|
+
from datetime import date
|
|
20
21
|
|
|
21
22
|
# Runtime helpers must not modify their immutable installation.
|
|
22
23
|
sys.dont_write_bytecode = True
|
|
23
24
|
import tempfile
|
|
25
|
+
import traceback
|
|
24
26
|
from pathlib import Path, PurePosixPath
|
|
25
27
|
from typing import Optional, Sequence
|
|
26
28
|
|
|
@@ -52,7 +54,7 @@ def _load_pipeline_modules():
|
|
|
52
54
|
try:
|
|
53
55
|
from scripts import archive_milestone, isolation, pipeline_git, pipeline_state, state_checkpoint
|
|
54
56
|
return archive_milestone, isolation, pipeline_git, pipeline_state, state_checkpoint
|
|
55
|
-
except
|
|
57
|
+
except ImportError as error: # a foreign `scripts` package
|
|
56
58
|
if error.name not in {
|
|
57
59
|
"scripts",
|
|
58
60
|
"scripts.archive_milestone",
|
|
@@ -62,6 +64,13 @@ def _load_pipeline_modules():
|
|
|
62
64
|
"scripts.state_checkpoint",
|
|
63
65
|
}:
|
|
64
66
|
raise
|
|
67
|
+
# A plain ImportError raised while a `scripts` module loaded is not a
|
|
68
|
+
# foreign package. A missing module falls back, as before.
|
|
69
|
+
if not isinstance(error, ModuleNotFoundError) and any(
|
|
70
|
+
frame.f_globals.get("__name__", "").startswith("scripts.")
|
|
71
|
+
for frame, _ in traceback.walk_tb(error.__traceback__)
|
|
72
|
+
):
|
|
73
|
+
raise
|
|
65
74
|
shared = Path(__file__).resolve().parents[2] / "gsd-path" / "scripts"
|
|
66
75
|
sys.path.insert(0, str(shared))
|
|
67
76
|
import archive_milestone
|
|
@@ -106,6 +115,16 @@ KINDS = ("checkpoint", "task", "member-task", "uncommitted-archive", "lookahead"
|
|
|
106
115
|
PROMOTION_PREFIX = "router: promote lookahead milestone "
|
|
107
116
|
ABANDON_PREFIX = "build: abandon milestone "
|
|
108
117
|
INTEGRATE_PREFIX = "integrate: "
|
|
118
|
+
SHIP_LOG_ONLY_LINE = re.compile(
|
|
119
|
+
r"- (?P<date>\d{4}-\d{2}-\d{2}) — ship — (?P<event>[^\r\n]+)\n\Z"
|
|
120
|
+
)
|
|
121
|
+
SHIPMENT_RECORD_LINE = re.compile(
|
|
122
|
+
r"- (?P<date>\d{4}-\d{2}-\d{2}) — shipped — (?P<event>[^\r\n]+)\n\Z"
|
|
123
|
+
)
|
|
124
|
+
SHIPMENT_EVENTS = {
|
|
125
|
+
"archive preflight passed; shipment recorded",
|
|
126
|
+
"archive preflight passed; shipment recorded; program complete",
|
|
127
|
+
}
|
|
109
128
|
|
|
110
129
|
|
|
111
130
|
class UndoError(RuntimeError):
|
|
@@ -375,6 +394,80 @@ def pending_transaction(repo: Path) -> Optional[dict[str, object]]:
|
|
|
375
394
|
raise UndoError(str(error)) from error
|
|
376
395
|
|
|
377
396
|
|
|
397
|
+
def _valid_state_event_line(line: str, phase: str) -> bool:
|
|
398
|
+
pattern = SHIP_LOG_ONLY_LINE if phase == "ship" else SHIPMENT_RECORD_LINE
|
|
399
|
+
match = pattern.fullmatch(line)
|
|
400
|
+
if match is None:
|
|
401
|
+
return False
|
|
402
|
+
try:
|
|
403
|
+
event_date = date.fromisoformat(match.group("date"))
|
|
404
|
+
except ValueError:
|
|
405
|
+
return False
|
|
406
|
+
event = match.group("event")
|
|
407
|
+
return event_date.isoformat() == match.group("date") and event == " ".join(event.split())
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
def _owned_ship_log_events(
|
|
411
|
+
prepared_state: str,
|
|
412
|
+
current_state: str,
|
|
413
|
+
phase: object,
|
|
414
|
+
status: object,
|
|
415
|
+
) -> Optional[str]:
|
|
416
|
+
"""Return only ship log lines appended around a helper-owned archive event.
|
|
417
|
+
|
|
418
|
+
The prepared text must remain byte-for-byte unchanged. For shipped/done,
|
|
419
|
+
record-shipment changes only phase and status before appending its one
|
|
420
|
+
generated shipment event, so validate that exact prefix and event shape.
|
|
421
|
+
"""
|
|
422
|
+
if (phase, status) == ("ship", "active"):
|
|
423
|
+
if current_state == prepared_state:
|
|
424
|
+
return ""
|
|
425
|
+
if not current_state.startswith(prepared_state):
|
|
426
|
+
return None
|
|
427
|
+
suffix = current_state[len(prepared_state):]
|
|
428
|
+
separator = "" if prepared_state.endswith("\n") else "\n"
|
|
429
|
+
if separator:
|
|
430
|
+
if not suffix.startswith(separator):
|
|
431
|
+
return None
|
|
432
|
+
suffix = suffix[len(separator):]
|
|
433
|
+
lines = suffix.splitlines(keepends=True)
|
|
434
|
+
if not lines or "".join(lines) != suffix:
|
|
435
|
+
return None
|
|
436
|
+
if not all(_valid_state_event_line(line, "ship") for line in lines):
|
|
437
|
+
return None
|
|
438
|
+
return separator + suffix
|
|
439
|
+
|
|
440
|
+
if (phase, status) != ("shipped", "done"):
|
|
441
|
+
return None
|
|
442
|
+
try:
|
|
443
|
+
shipped_prefix = pipeline_state._set_frontmatter(
|
|
444
|
+
prepared_state,
|
|
445
|
+
{"phase": "shipped", "status": "done"},
|
|
446
|
+
)
|
|
447
|
+
except PipelineStateError:
|
|
448
|
+
return None
|
|
449
|
+
if not current_state.startswith(shipped_prefix):
|
|
450
|
+
return None
|
|
451
|
+
suffix = current_state[len(shipped_prefix):]
|
|
452
|
+
separator = "" if shipped_prefix.endswith("\n") else "\n"
|
|
453
|
+
if separator:
|
|
454
|
+
if not suffix.startswith(separator):
|
|
455
|
+
return None
|
|
456
|
+
suffix = suffix[len(separator):]
|
|
457
|
+
lines = suffix.splitlines(keepends=True)
|
|
458
|
+
if not lines or "".join(lines) != suffix:
|
|
459
|
+
return None
|
|
460
|
+
shipment_event = lines[-1]
|
|
461
|
+
if not _valid_state_event_line(shipment_event, "shipped"):
|
|
462
|
+
return None
|
|
463
|
+
if SHIPMENT_RECORD_LINE.fullmatch(shipment_event).group("event") not in SHIPMENT_EVENTS:
|
|
464
|
+
return None
|
|
465
|
+
ship_events = lines[:-1]
|
|
466
|
+
if not all(_valid_state_event_line(line, "ship") for line in ship_events):
|
|
467
|
+
return None
|
|
468
|
+
return separator + "".join(ship_events) if ship_events else ""
|
|
469
|
+
|
|
470
|
+
|
|
378
471
|
def _archive_metadata_error(
|
|
379
472
|
repo: Path,
|
|
380
473
|
state_fields: dict[str, object],
|
|
@@ -420,8 +513,13 @@ def _archive_metadata_error(
|
|
|
420
513
|
if final_review.exists() or gap_reviews:
|
|
421
514
|
reviewed_head, _ = archive_milestone.parse_final_review(archive_path)
|
|
422
515
|
archive_milestone.validate_gap_reviews(archive_path, reviewed_head)
|
|
423
|
-
if
|
|
424
|
-
|
|
516
|
+
if not archive_milestone.reviewed_head_covers(
|
|
517
|
+
repo, reviewed_head, _optional_rev(repo, "HEAD")
|
|
518
|
+
):
|
|
519
|
+
return (
|
|
520
|
+
"archive undo final review does not match current HEAD; "
|
|
521
|
+
f"{archive_milestone._common.RUNTIME_PIN_ALLOWANCE}"
|
|
522
|
+
)
|
|
425
523
|
expected_inventory.add("review/FINAL.md")
|
|
426
524
|
expected_inventory.update(
|
|
427
525
|
path.relative_to(archive_path).as_posix() for path in gap_reviews
|
|
@@ -476,10 +574,14 @@ def _archive_metadata_error(
|
|
|
476
574
|
"archive",
|
|
477
575
|
configured,
|
|
478
576
|
)
|
|
479
|
-
current_state = (repo / ".project" / "STATE.md").
|
|
577
|
+
current_state = (repo / ".project" / "STATE.md").read_bytes().decode("utf-8")
|
|
480
578
|
phase = state_fields.get("phase")
|
|
481
579
|
status = state_fields.get("status")
|
|
580
|
+
ship_events = _owned_ship_log_events(prepared_state, current_state, phase, status)
|
|
482
581
|
if (phase, status) == ("ship", "active"):
|
|
582
|
+
if ship_events is None:
|
|
583
|
+
return "archive undo found unowned STATE.md changes"
|
|
584
|
+
prepared_state += ship_events
|
|
483
585
|
if current_state != prepared_state:
|
|
484
586
|
return "archive undo found unowned STATE.md changes"
|
|
485
587
|
if ".project/ROADMAP.md" in dirty:
|
|
@@ -487,14 +589,13 @@ def _archive_metadata_error(
|
|
|
487
589
|
return None
|
|
488
590
|
if (phase, status) != ("shipped", "done"):
|
|
489
591
|
return "archive undo requires ship/active or shipped/done"
|
|
592
|
+
if ship_events is None:
|
|
593
|
+
return "archive undo found unowned shipment STATE.md changes"
|
|
594
|
+
prepared_state += ship_events
|
|
490
595
|
|
|
491
596
|
prepared = _state_from_text(prepared_state, "prepared archive STATE.md")
|
|
492
|
-
events = (
|
|
493
|
-
"archive preflight passed; shipment recorded",
|
|
494
|
-
"archive preflight passed; shipment recorded; program complete",
|
|
495
|
-
)
|
|
496
597
|
rendered_states = []
|
|
497
|
-
for event in
|
|
598
|
+
for event in SHIPMENT_EVENTS:
|
|
498
599
|
try:
|
|
499
600
|
_, _, rendered = _render_transition(
|
|
500
601
|
prepared,
|
|
@@ -679,14 +780,15 @@ def _member_undo_parent(repo: Path, member: str, landing: str) -> str:
|
|
|
679
780
|
bound = entry["branch"]
|
|
680
781
|
if _run_git(checkout, "rev-parse", f"refs/heads/{bound}").stdout.strip() != landing:
|
|
681
782
|
raise UndoError(f"member {member} {bound} moved past this landing")
|
|
682
|
-
_require_member_unpublished(checkout, member, landing, bound)
|
|
783
|
+
_require_member_unpublished(repo, checkout, member, landing, bound)
|
|
683
784
|
return _run_git(checkout, "rev-parse", f"{landing}^").stdout.strip()
|
|
684
785
|
|
|
685
786
|
|
|
686
|
-
def _require_member_unpublished(checkout: Path, member: str, landing: str, bound: str) -> None:
|
|
687
|
-
for
|
|
787
|
+
def _require_member_unpublished(repo: Path, checkout: Path, member: str, landing: str, bound: str) -> None:
|
|
788
|
+
for branch in (isolation.member_default_branch(repo, member), bound):
|
|
789
|
+
ref = f"refs/remotes/origin/{branch}"
|
|
688
790
|
if _run_git(checkout, "merge-base", "--is-ancestor", landing, ref, check=False).returncode == 0:
|
|
689
|
-
raise UndoError(f"member {member} landing is already on {
|
|
791
|
+
raise UndoError(f"member {member} landing is already on origin/{branch}")
|
|
690
792
|
|
|
691
793
|
|
|
692
794
|
def _require_no_member_landing_journal(repo: Path) -> None:
|
|
@@ -701,7 +803,7 @@ def _undo_member_landing(repo: Path, transaction: dict[str, object]) -> None:
|
|
|
701
803
|
checkout, _, entry = isolation._member_context(repo, member)
|
|
702
804
|
tip = _run_git(checkout, "rev-parse", f"refs/heads/{entry['branch']}").stdout.strip()
|
|
703
805
|
if tip == transaction["member_parent"]:
|
|
704
|
-
_require_member_unpublished(checkout, member, str(transaction["landing"]), entry["branch"])
|
|
806
|
+
_require_member_unpublished(repo, checkout, member, str(transaction["landing"]), entry["branch"])
|
|
705
807
|
return
|
|
706
808
|
if tip != transaction["landing"]:
|
|
707
809
|
raise UndoError(f"member {member} bound branch moved during undo")
|
|
@@ -768,7 +870,7 @@ def classify_undo(repo: Path) -> dict[str, object]:
|
|
|
768
870
|
[f"an in-progress helper journal exists ({names}); resume that transaction first"]
|
|
769
871
|
)
|
|
770
872
|
if git.get("ancestor_of_origin_main"):
|
|
771
|
-
return _blocked(["HEAD is an ancestor of origin
|
|
873
|
+
return _blocked(["HEAD is an ancestor of the origin default branch; undo would rewrite shipped history"])
|
|
772
874
|
|
|
773
875
|
product = _product_dirty(dirty)
|
|
774
876
|
if product:
|
|
@@ -988,7 +1090,7 @@ def _require_unpublished_reset(repo: Path, expected_branch: str) -> None:
|
|
|
988
1090
|
if git.get("published"):
|
|
989
1091
|
raise UndoError("HEAD became published on its recorded remote branch")
|
|
990
1092
|
if git.get("ancestor_of_origin_main"):
|
|
991
|
-
raise UndoError("HEAD became published through origin
|
|
1093
|
+
raise UndoError("HEAD became published through the origin default branch")
|
|
992
1094
|
|
|
993
1095
|
|
|
994
1096
|
def _remove_untracked_tree(repo: Path, relative: str) -> None:
|
|
@@ -22,6 +22,27 @@ else:
|
|
|
22
22
|
from scripts import _common
|
|
23
23
|
|
|
24
24
|
|
|
25
|
+
def _worktree_list_porcelain(primary: Path) -> tuple[str, bool]:
|
|
26
|
+
try:
|
|
27
|
+
if __package__:
|
|
28
|
+
from . import pipeline_git as pg
|
|
29
|
+
else:
|
|
30
|
+
from scripts import pipeline_git as pg
|
|
31
|
+
except ImportError:
|
|
32
|
+
try:
|
|
33
|
+
import pipeline_git as pg
|
|
34
|
+
except ImportError:
|
|
35
|
+
pg = None
|
|
36
|
+
if pg is not None:
|
|
37
|
+
return pg.worktree_list_porcelain(primary)
|
|
38
|
+
try:
|
|
39
|
+
output = _git(primary, "worktree", "list", "--porcelain", "-z")
|
|
40
|
+
return output, True
|
|
41
|
+
except ValueError:
|
|
42
|
+
output = _git(primary, "worktree", "list", "--porcelain")
|
|
43
|
+
return output, False
|
|
44
|
+
|
|
45
|
+
|
|
25
46
|
def _git(primary: Path, *args: str) -> str:
|
|
26
47
|
result = _common.run_git(primary, *args)
|
|
27
48
|
if result.returncode:
|
|
@@ -82,6 +103,33 @@ def _workspace(primary: Path, pin: bool) -> Path:
|
|
|
82
103
|
return workspace
|
|
83
104
|
|
|
84
105
|
|
|
106
|
+
def release_workspace(primary: Path) -> bool:
|
|
107
|
+
"""Forget the pinned placement receipt once no linked worktrees remain.
|
|
108
|
+
|
|
109
|
+
Lets GSD_PATH_WORKTREE_ROOT (or a new default) apply again at the next
|
|
110
|
+
milestone's first allocation. Returns True when a receipt was removed;
|
|
111
|
+
any remaining linked worktree (including one only still registered) keeps
|
|
112
|
+
the pin.
|
|
113
|
+
"""
|
|
114
|
+
primary = primary.resolve()
|
|
115
|
+
common = Path(_git(primary, "rev-parse", "--git-common-dir"))
|
|
116
|
+
common = (primary / common).resolve()
|
|
117
|
+
receipt = common / "gsd-path" / "workspaces" / f"{_identity(primary)}.json"
|
|
118
|
+
if not receipt.is_file():
|
|
119
|
+
return False
|
|
120
|
+
output, nul_separated = _worktree_list_porcelain(primary)
|
|
121
|
+
records = output.split("\0\0") if nul_separated else [
|
|
122
|
+
block for block in output.strip().split("\n\n") if block.strip()
|
|
123
|
+
]
|
|
124
|
+
for record in records:
|
|
125
|
+
fields = record.split("\0") if nul_separated else record.splitlines()
|
|
126
|
+
for field in fields:
|
|
127
|
+
if field.startswith("worktree ") and Path(field[len("worktree "):]).resolve() != primary:
|
|
128
|
+
return False
|
|
129
|
+
receipt.unlink()
|
|
130
|
+
return True
|
|
131
|
+
|
|
132
|
+
|
|
85
133
|
def worktree_path(primary: Path, kind: str, name: str, *, pin: bool = False) -> Path:
|
|
86
134
|
primary = primary.resolve()
|
|
87
135
|
if kind not in {"task", "verify", "integrate", "bound"} or not name or Path(name).name != name or name in {".", ".."}:
|
|
@@ -91,9 +139,13 @@ def worktree_path(primary: Path, kind: str, name: str, *, pin: bool = False) ->
|
|
|
91
139
|
legacy = (primary.parent / f".{primary.name}-gsd-path-integrate-{name}"
|
|
92
140
|
if kind == "integrate" else primary.parent / f"{primary.name}.gsd-path" / kind / name)
|
|
93
141
|
branch = f"refs/heads/gsd-path-{kind}/{name}"
|
|
94
|
-
|
|
142
|
+
output, nul_separated = _worktree_list_porcelain(primary)
|
|
143
|
+
if nul_separated:
|
|
144
|
+
records = output.split("\0\0")
|
|
145
|
+
else:
|
|
146
|
+
records = [block for block in output.strip().split("\n\n") if block.strip()]
|
|
95
147
|
for record in records:
|
|
96
|
-
fields = record.split("\0")
|
|
148
|
+
fields = record.split("\0") if nul_separated else record.splitlines()
|
|
97
149
|
# Compare as paths: git prints forward slashes on Windows.
|
|
98
150
|
worktrees = [Path(field[len("worktree "):]) for field in fields if field.startswith("worktree ")]
|
|
99
151
|
if legacy in worktrees and f"branch {branch}" in fields:
|
package/skills/path/DEFINE.md
CHANGED
|
@@ -100,6 +100,10 @@ Obtain a confident answer in every area before finishing:
|
|
|
100
100
|
give every named surface at least one success criterion observable
|
|
101
101
|
there. A criterion satisfied by a passing test alone does not cover a
|
|
102
102
|
surface.
|
|
103
|
+
9. **Edges and prohibitions** — once the success criteria are drafted, run
|
|
104
|
+
the [spec-reach probes](references/spec-probes.md): every applicable edge
|
|
105
|
+
and every kept prohibition gets the user's ruling in INTENT.md
|
|
106
|
+
`## Edge coverage` and `## Prohibitions`.
|
|
103
107
|
|
|
104
108
|
## Program mode
|
|
105
109
|
|
|
@@ -149,7 +153,10 @@ State ownership. There is no re-interview of charter or roadmap scope:
|
|
|
149
153
|
`Lane: milestone`, `Surfaces:` copied verbatim from the entry, and
|
|
150
154
|
`Review panel:` copied from CHARTER.md (default
|
|
151
155
|
the configured preference when CHARTER omits it). The confirmation may override the copied
|
|
152
|
-
panel value; do not invent `detected` or a named list.
|
|
156
|
+
panel value; do not invent `detected` or a named list. Run the
|
|
157
|
+
[spec-reach probes](references/spec-probes.md) over the derived criteria
|
|
158
|
+
and draft `## Edge coverage` and `## Prohibitions` with recommended
|
|
159
|
+
rulings. When brownfield,
|
|
153
160
|
fill `## Current state` from the map, record doc-vs-code rulings as in
|
|
154
161
|
Brownfield mode, and add protected existing behavior under Scope out.
|
|
155
162
|
Write Ground truth paths from the track root: `.project` normally, or
|
|
@@ -157,10 +164,16 @@ State ownership. There is no re-interview of charter or roadmap scope:
|
|
|
157
164
|
active `research/` paths.
|
|
158
165
|
3. Present one confirmation, not an interview: playback the derivation (and
|
|
159
166
|
brownfield ground truth when present), link the resolved absolute INTENT.md
|
|
160
|
-
path, and ask approve or adjust.
|
|
167
|
+
path, and ask approve or adjust. The confirmation lists each proposed edge
|
|
168
|
+
and prohibition ruling for the user to accept or change; it never rules on
|
|
169
|
+
them silently. A requested change that contradicts the
|
|
161
170
|
charter or the resolved roadmap entry is a scope change — this phase never
|
|
162
|
-
edits the roadmap; surface it to the user for a `$gsd-path-roadmap`
|
|
163
|
-
|
|
171
|
+
edits the roadmap; surface it to the user for a `$gsd-path-roadmap`
|
|
172
|
+
re-slice. Before intent approval, that re-slice keeps `define/active` and
|
|
173
|
+
can change the scope of this milestone's `active` entry; after its
|
|
174
|
+
approval, draft INTENT.md again from the changed entry. In `corrections`
|
|
175
|
+
mode the intent is already approved, so the re-slice waits for the next
|
|
176
|
+
milestone boundary.
|
|
164
177
|
4. On approval, finalize per the Output contract, setting `milestone` to the
|
|
165
178
|
resolved entry's slug. The router continues with milestone-scoped research
|
|
166
179
|
when the entry lists open questions, otherwise planning.
|
|
@@ -254,7 +267,15 @@ question. The rules change for every primary mode:
|
|
|
254
267
|
the brownfield map already established. Milestone mode skips this step.
|
|
255
268
|
5. Stop when coverage is complete or the user says `enough`. Record remaining
|
|
256
269
|
uncertainty under `## Open questions` with `RESEARCH` or `NEEDS-USER`.
|
|
257
|
-
|
|
270
|
+
`enough` does not skip the next step.
|
|
271
|
+
6. In standard mode, run the [spec-reach probes](references/spec-probes.md)
|
|
272
|
+
over the drafted success criteria: one question round for edges, then one
|
|
273
|
+
for kept prohibitions, each with a recommended ruling first. A ruling
|
|
274
|
+
observable where the user sees the work becomes or amends a success
|
|
275
|
+
criterion; write every ruling into `## Edge coverage` and
|
|
276
|
+
`## Prohibitions`. Program mode skips this step (each milestone runs it
|
|
277
|
+
in milestone mode); milestone mode runs it inside its confirmation.
|
|
278
|
+
7. Classify the proposed milestone lane before writing the approval draft.
|
|
258
279
|
Milestone mode keeps `Lane: milestone` and skips this classification.
|
|
259
280
|
Program mode writes CHARTER.md instead of INTENT.md. Otherwise choose
|
|
260
281
|
`quick` when scope fits at most two deliverable-sized tasks (project
|
|
@@ -275,6 +296,11 @@ question. The rules change for every primary mode:
|
|
|
275
296
|
## Output contract
|
|
276
297
|
|
|
277
298
|
At approval, retain the already reviewed `Lane:` value and its one-line reason.
|
|
299
|
+
Before every approval question on INTENT.md, run the bundled `python3
|
|
300
|
+
<absolute-bundled-script> intent --repo <absolute-root>` helper
|
|
301
|
+
(`scripts/check_handoffs.py`, plus `--project-dir .project/next` in
|
|
302
|
+
lookahead). It checks the success criteria, Surfaces, and both probe tables;
|
|
303
|
+
fix a failure in the draft before asking. It approves nothing.
|
|
278
304
|
Before presenting an approval draft without a CHARTER or explicit panel choice,
|
|
279
305
|
read `settings.review_panel.value` from the selected runtime's `path_config.py
|
|
280
306
|
show --repo <absolute-root>` (bundle for legacy projects; off for older selected
|
|
@@ -302,5 +328,8 @@ Use the executable phase handoff in AGENTS.md for the next action.
|
|
|
302
328
|
- In brownfield mode, state mapped facts for correction; never re-ask them.
|
|
303
329
|
- Treat solution-shaped problems as hypotheses and uncover the underlying pain.
|
|
304
330
|
- Preserve vetoes and corrections verbatim.
|
|
331
|
+
- Never rule on an edge's behavior or a prohibition yourself; recommend,
|
|
332
|
+
then record the user's ruling. An edge the user has not ruled on is a
|
|
333
|
+
required answer, including under pre-approval.
|
|
305
334
|
- Wrap up when every coverage-checklist area is answered or the user signals
|
|
306
335
|
done, and tag remaining gaps.
|
package/skills/path/PLAN.md
CHANGED
|
@@ -115,9 +115,13 @@ as stated in Lookahead mode.
|
|
|
115
115
|
In patch mode, tasks already `done` keep their landed metadata; only
|
|
116
116
|
the appended patch tasks must start clean.
|
|
117
117
|
- Require every dependency id to exist, forbid later-wave dependencies,
|
|
118
|
-
detect cycles, and forbid file overlap between planned tasks
|
|
119
|
-
wave. Same-wave
|
|
120
|
-
|
|
118
|
+
detect cycles, and forbid unordered file overlap between planned tasks
|
|
119
|
+
in the same wave. Same-wave tasks may share files only when one
|
|
120
|
+
transitively depends on the other through `deps`; the build executes
|
|
121
|
+
them in dependency layers.
|
|
122
|
+
- Require an optional `supersedes` field to be a list of different task
|
|
123
|
+
ids; each one names an existing task of an earlier wave, in the same
|
|
124
|
+
repo, that shares a declared file with the task.
|
|
121
125
|
- Reject a declared dependency that carries neither data nor a prerequisite
|
|
122
126
|
effect. A `deps` edge is valid only when the dependent consumes a symbol,
|
|
123
127
|
signature, schema, endpoint, file format, or path named in that
|
|
@@ -157,6 +161,13 @@ as stated in Lookahead mode.
|
|
|
157
161
|
command's output — not an internal unit test.
|
|
158
162
|
Require the surface to land in the same wave as the capability behind
|
|
159
163
|
it, never in a later polish wave.
|
|
164
|
+
- When INTENT.md has `## Edge coverage`, require a PLAN.md
|
|
165
|
+
`## Held-out checks` row for every `held-out` edge and for no other
|
|
166
|
+
edge. The named test is in that task's `files`, the task's Verify runs
|
|
167
|
+
it, and the task's Acceptance criteria state the edge id and its ruling
|
|
168
|
+
(see [spec-reach probes](references/spec-probes.md)). An edge or
|
|
169
|
+
prohibition ruled `criterion SCn` needs no extra row; it is covered as
|
|
170
|
+
SCn. Put each `judgment` prohibition in its owning task's Approach.
|
|
160
171
|
- Prove every intent constraint and synthesis decision is covered, that no
|
|
161
172
|
scope-out veto appears in a task, and that `Project verify` is a real,
|
|
162
173
|
non-placeholder command in PLAN.md. Every Verify — task and project —
|
package/skills/path/RESEARCH.md
CHANGED
|
@@ -84,6 +84,17 @@ settled brownfield input.
|
|
|
84
84
|
template before dispatch. Record every standard dimension exactly once as
|
|
85
85
|
`dispatched` or `skipped` with a reason, and assign every research question
|
|
86
86
|
to at least one dispatched dimension. No question may remain unassigned.
|
|
87
|
+
Copy each question to exactly one `Question assignments` row. Assign one or
|
|
88
|
+
more dispatched dimension slugs there, each in its own code span and
|
|
89
|
+
separated by commas, as in:
|
|
90
|
+
|
|
91
|
+
```md
|
|
92
|
+
- `[RESEARCH] Which approach is viable?` → `stack`, `pitfalls`
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
List a dimension only once per row. Every dispatched dimension must own at
|
|
96
|
+
least one question, and its evidence file must answer every question
|
|
97
|
+
assigned to it. Use `- none` only when there are no research questions.
|
|
87
98
|
2. Decide which standard dimensions have work: dispatch a dimension only when
|
|
88
99
|
it has at least one assigned `RESEARCH` question from INTENT.md or
|
|
89
100
|
CHARTER.md. Unsettled choices and risks need that source question before
|
package/skills/path/ROADMAP.md
CHANGED
|
@@ -27,7 +27,8 @@ return to `$gsd-path` for ownership checking. Legal entry is
|
|
|
27
27
|
yet, `roadmap/active|blocked`, or a
|
|
28
28
|
milestone-boundary re-slice: `inspect/active` or `define/active` with no
|
|
29
29
|
approved INTENT.md for the next milestone and a user request to re-scope the
|
|
30
|
-
remaining `pending` entries,
|
|
30
|
+
remaining `pending` entries or, at `define/active` only, to change the scope
|
|
31
|
+
of the `active` entry,
|
|
31
32
|
or `roadmap/active` with STATE.milestone null and an `abandoned` entry in
|
|
32
33
|
ROADMAP.md (the post-abandon re-slice the build orchestrator hands off).
|
|
33
34
|
Enter from `decide/done` only with `pipeline_state.py transition`, exact
|
|
@@ -35,6 +36,8 @@ expected phase/status/milestone/branch/archive fields, event `roadmap started`,
|
|
|
35
36
|
and `--set-phase roadmap --set-status active`; never edit STATE directly. In a
|
|
36
37
|
milestone-boundary re-slice, preserve the entering `inspect/active` or
|
|
37
38
|
`define/active` state throughout the re-slice.
|
|
39
|
+
A `define/active` state that the router reports in `corrections` mode already
|
|
40
|
+
has an approved INTENT.md; it blocks.
|
|
38
41
|
Any later phase blocks; mid-milestone
|
|
39
42
|
re-scope is never legal — finish or ship the active milestone first. A
|
|
40
43
|
`decide/done` state with ROADMAP.md already present is milestone-scope decide;
|
|
@@ -71,8 +74,11 @@ precondition fails.
|
|
|
71
74
|
give `.project/ROADMAP.before-reslice.md` with the instruction to preserve
|
|
72
75
|
`shipped` entries byte-for-byte except Status/Archive/Integrated fields and
|
|
73
76
|
to never modify `abandoned` entries at all. For a milestone-boundary
|
|
74
|
-
re-slice
|
|
75
|
-
`pending` entries are in scope.
|
|
77
|
+
re-slice entered at `inspect/active`, also preserve the existing `active`
|
|
78
|
+
entry byte-for-byte; only `pending` entries are in scope. Entered at
|
|
79
|
+
`define/active`, the `active` entry may also change as the user ruled, but
|
|
80
|
+
its heading (id and slug) and its Status, Depends on, Archive, and
|
|
81
|
+
Integrated fields stay unchanged.
|
|
76
82
|
The output is exactly `.project/ROADMAP.md` — no other location is
|
|
77
83
|
canonical.
|
|
78
84
|
3. Gate ROADMAP.md:
|
|
@@ -96,8 +102,11 @@ precondition fails.
|
|
|
96
102
|
- On a re-slice, `shipped` entries differ from
|
|
97
103
|
`.project/ROADMAP.before-reslice.md` only in Status/Archive/Integrated;
|
|
98
104
|
`abandoned` entries are byte-for-byte identical.
|
|
99
|
-
- On a milestone-boundary re-slice
|
|
100
|
-
identical to
|
|
105
|
+
- On a milestone-boundary re-slice entered at `inspect/active`, the prior
|
|
106
|
+
`active` entry is byte-for-byte identical to
|
|
107
|
+
`.project/ROADMAP.before-reslice.md`. Entered at `define/active`, it
|
|
108
|
+
stays the only `active` entry and keeps its heading and its Status,
|
|
109
|
+
Depends on, Archive, and Integrated fields.
|
|
101
110
|
4. Redispatch one complete corrected brief under logical task name `roadmap`,
|
|
102
111
|
following the runtime dispatch contract and including all gate failures.
|
|
103
112
|
Allow one revision round. If it still fails, keep the entering
|
|
@@ -160,7 +169,8 @@ precondition fails.
|
|
|
160
169
|
|
|
161
170
|
The helper owns roadmap selection, expected state, baseline cleanup and
|
|
162
171
|
the approval checkpoint. It journals before mutation, retains the baseline
|
|
163
|
-
bytes for recovery, and refuses changes to settled
|
|
172
|
+
bytes for recovery, and refuses changes to settled entries and every
|
|
173
|
+
`active` entry change that step 2 does not permit.
|
|
164
174
|
A milestone-boundary re-slice retains Inspect or Define; a post-abandon
|
|
165
175
|
re-slice enters Inspect. Require its typed result to report `status:
|
|
166
176
|
approved`, the requested kind, milestone and returned commit. After an
|
package/skills/path/SHIP.md
CHANGED
|
@@ -159,7 +159,12 @@ so the position is unchanged. Then:
|
|
|
159
159
|
then stop and do not invent a patch finding. A `not-met`,
|
|
160
160
|
`unverifiable`, or blocked gap with valid evidence sets `ship/blocked`,
|
|
161
161
|
writes `.project/review/PATCH-FINDINGS.md` from the patch-findings template,
|
|
162
|
-
|
|
162
|
+
copying the full `Risk: ...` line into each gap finding's Locator, its
|
|
163
|
+
`Found` field into Evidence, and its `Fix direction` field verbatim. For a
|
|
164
|
+
`FINAL.md` finding, use its `SC<n>` id as Locator and copy its `Finding` and
|
|
165
|
+
`Fix direction` fields verbatim. The patch validator requires these source
|
|
166
|
+
field values to match exactly; do not shorten or paraphrase them. Run
|
|
167
|
+
`python3 <absolute check_handoffs.py> patch --repo <absolute repo
|
|
163
168
|
root>`. Present the blocked outcome, link the resolved absolute
|
|
164
169
|
PATCH-FINDINGS.md path, and state that patch planning is next. The manifest
|
|
165
170
|
contains exactly those FINAL.md and gap rows. When routed by an active
|
|
@@ -262,7 +267,11 @@ The persisted `STATE.archive` field is the transaction identity.
|
|
|
262
267
|
`python3 <absolute archive_milestone.py> close-members --repo <root>`
|
|
263
268
|
after preflight passes and before recording shipment. It closes each
|
|
264
269
|
locked member in lock order in that member's integration mode and
|
|
265
|
-
journals each one.
|
|
270
|
+
journals each one. Each member closes onto the default branch that
|
|
271
|
+
MEMBERS.md records for it (`main` when its section has no
|
|
272
|
+
`Default branch`); when the command reports
|
|
273
|
+
`remote default must be <recorded>`, stop and report it. When it returns
|
|
274
|
+
`awaiting-merge`, report the member PR
|
|
266
275
|
link, stop, and rerun the same command after the user merges it; never
|
|
267
276
|
merge a member PR yourself. When it returns `integrated`, keep its `body`
|
|
268
277
|
for the ship commit below.
|
|
@@ -305,8 +314,10 @@ The persisted `STATE.archive` field is the transaction identity.
|
|
|
305
314
|
milestone is not shipped until integration below passes.
|
|
306
315
|
7. Integrate only after the postcommit `validate` passes, with the recorded
|
|
307
316
|
ship commit and exact reviewed HEAD unchanged. Run `python3 <absolute archive_milestone.py> integrate --repo <root> --slug <STATE.milestone>`.
|
|
308
|
-
This helper validates the ship commit, fetches origin, requires remote
|
|
309
|
-
default `main
|
|
317
|
+
This helper validates the ship commit, fetches origin, requires the remote
|
|
318
|
+
default to equal STATE `default_branch` (`main` when the field is absent),
|
|
319
|
+
and follows the locked `STATE.integration` mode. `main` and `origin/main`
|
|
320
|
+
below mean that recorded branch:
|
|
310
321
|
|
|
311
322
|
- `direct` owns the resumable merge transaction. It creates the canonical
|
|
312
323
|
named integration worktree, performs the hook-verified `--no-ff` merge,
|
|
@@ -339,6 +350,22 @@ The persisted `STATE.archive` field is the transaction identity.
|
|
|
339
350
|
landing SHA. A closed unmerged PR, squash, rebase, merge queue, moved
|
|
340
351
|
head, duplicate PR, or non-GitHub.com origin blocks. The remote bound
|
|
341
352
|
branch may be absent after a valid merge because GitHub may auto-delete it.
|
|
353
|
+
- `external-landing` is for an origin where Path cannot open the review
|
|
354
|
+
itself, such as GitLab, Gitea, or GitHub Enterprise Server. It needs no
|
|
355
|
+
forge CLI. The helper publishes the bound branch at the exact ship commit,
|
|
356
|
+
never pushes `main`, and returns `status: awaiting-merge` with `branch`,
|
|
357
|
+
`merge_subject`, and `merge_body`. Present **Outcome**, and state in
|
|
358
|
+
**Next** that the user must open a merge request from `branch` to `main`
|
|
359
|
+
in their own forge and merge it with a merge commit. The merge commit
|
|
360
|
+
message must be exactly `merge_subject`, a blank line, then `merge_body`;
|
|
361
|
+
show both values verbatim in a code block. Stop this ship invocation;
|
|
362
|
+
Path never opens or merges the request. The forge may delete the source
|
|
363
|
+
branch after the merge. On rerun after the merge, the helper requires exactly
|
|
364
|
+
one commit with that subject on `origin/main` first-parent history, that
|
|
365
|
+
exact body, and two parents with the ship commit as second parent. It
|
|
366
|
+
then writes and pushes the annotated milestone tag containing the ship
|
|
367
|
+
SHA and landing SHA. A squash, rebase, fast-forward, or different merge
|
|
368
|
+
message blocks.
|
|
342
369
|
|
|
343
370
|
A passing run returns the same proof exposed by `validate-integrated`.
|
|
344
371
|
A non-zero result blocks; rerun the exact `integrate` command to resume a
|
|
@@ -349,7 +376,7 @@ The persisted `STATE.archive` field is the transaction identity.
|
|
|
349
376
|
continuing. Never merge into or re-ship the closed branch.
|
|
350
377
|
For a later validation recheck with origin network access, run
|
|
351
378
|
`python3 <absolute archive_milestone.py> validate-integrated --repo <root> --slug <STATE.milestone>`.
|
|
352
|
-
|
|
379
|
+
All integration modes refresh the remote-default and mirrored milestone-tag
|
|
353
380
|
refs when an `origin` remote exists. Without that remote, validation resolves
|
|
354
381
|
the existing remote-default refs locally, preserving offline direct-mode
|
|
355
382
|
fixtures. PR mode also revalidates the PR identity, state, merge provenance,
|