@opengsd/gsd-path 1.5.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 +138 -0
- package/DOCS.md +4 -3
- package/FULL.md +64 -4
- package/HOOKS.md +63 -2
- package/MIGRATE.md +12 -0
- package/QUICK.md +4 -2
- package/README.md +67 -15
- package/RUNTIME.md +23 -5
- package/UPDATE.md +35 -0
- package/WORKFLOW.md +58 -3
- package/package.json +1 -1
- package/scripts/_common.py +107 -1
- package/scripts/build_recovery.py +62 -30
- package/scripts/build_state.py +195 -5
- package/scripts/check_handoffs.py +92 -30
- package/scripts/check_task_briefs.py +19 -14
- package/scripts/detect_project.py +17 -2
- package/scripts/discussion_records.py +9 -1
- package/scripts/discussion_validate.py +7 -6
- package/scripts/dispatch_driver.py +157 -31
- package/scripts/git_guard.py +24 -5
- package/scripts/guard_hook.py +1216 -47
- package/scripts/install.mjs +76 -3
- package/scripts/install.py +182 -37
- package/scripts/integration.py +98 -64
- package/scripts/isolation.py +148 -11
- package/scripts/members.py +68 -25
- package/scripts/migrate_core.py +2 -0
- package/scripts/model_policy.py +5 -1
- package/scripts/pipeline_diagnose.py +17 -2
- package/scripts/pipeline_git.py +68 -30
- package/scripts/pipeline_state.py +28 -6
- package/scripts/pipeline_undo.py +17 -8
- 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 +1 -0
- package/scripts/state_checkpoint.py +30 -9
- package/scripts/state_promote.py +15 -4
- package/scripts/task_context.py +2 -0
- package/scripts/workflow_run.py +9 -2
- package/skills/gsd-path/DEFINE.md +6 -2
- package/skills/gsd-path/PLAN.md +3 -0
- package/skills/gsd-path/ROADMAP.md +16 -6
- package/skills/gsd-path/SHIP.md +26 -4
- package/skills/gsd-path/SKILL.md +52 -24
- package/skills/gsd-path/references/build-native.md +96 -9
- package/skills/gsd-path/references/build-recovery.md +13 -0
- package/skills/gsd-path/references/coder.md +7 -3
- package/skills/gsd-path/references/operating-rules.md +11 -3
- package/skills/gsd-path/references/planner.md +13 -1
- package/skills/gsd-path/references/reviewer-final.md +5 -5
- package/skills/gsd-path/references/reviewer-wave.md +46 -13
- package/skills/gsd-path/references/runtime-selection.md +9 -0
- package/skills/gsd-path/scripts/_common.py +107 -1
- package/skills/gsd-path/scripts/build_recovery.py +62 -30
- package/skills/gsd-path/scripts/build_state.py +195 -5
- package/skills/gsd-path/scripts/check_handoffs.py +92 -30
- package/skills/gsd-path/scripts/check_task_briefs.py +19 -14
- package/skills/gsd-path/scripts/detect_project.py +17 -2
- package/skills/gsd-path/scripts/discussion_records.py +9 -1
- package/skills/gsd-path/scripts/discussion_validate.py +7 -6
- package/skills/gsd-path/scripts/dispatch_driver.py +157 -31
- package/skills/gsd-path/scripts/git_guard.py +24 -5
- package/skills/gsd-path/scripts/integration.py +98 -64
- package/skills/gsd-path/scripts/isolation.py +148 -11
- package/skills/gsd-path/scripts/members.py +68 -25
- package/skills/gsd-path/scripts/model_policy.py +5 -1
- package/skills/gsd-path/scripts/pipeline_git.py +68 -30
- package/skills/gsd-path/scripts/pipeline_state.py +28 -6
- 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 +30 -9
- package/skills/gsd-path/scripts/state_promote.py +15 -4
- package/skills/gsd-path/scripts/task_context.py +2 -0
- package/skills/gsd-path/scripts/workflow_run.py +9 -2
- package/skills/gsd-path/templates/final-review.md +5 -5
- package/skills/gsd-path/templates/state.md +1 -0
- package/skills/gsd-path/templates/task.md +1 -0
- package/skills/gsd-path/templates/wave-review.md +18 -9
- package/skills/gsd-path-build/references/build-native.md +96 -9
- 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/operating-rules.md +11 -3
- package/skills/gsd-path-build/references/reviewer-final.md +5 -5
- package/skills/gsd-path-build/references/reviewer-wave.md +46 -13
- package/skills/gsd-path-build/references/runtime-selection.md +9 -0
- package/skills/gsd-path-build/scripts/_common.py +107 -1
- package/skills/gsd-path-build/scripts/build_recovery.py +62 -30
- package/skills/gsd-path-build/scripts/build_state.py +195 -5
- package/skills/gsd-path-build/scripts/check_handoffs.py +92 -30
- package/skills/gsd-path-build/scripts/check_task_briefs.py +19 -14
- package/skills/gsd-path-build/scripts/detect_project.py +17 -2
- package/skills/gsd-path-build/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-build/scripts/discussion_validate.py +7 -6
- package/skills/gsd-path-build/scripts/dispatch_driver.py +157 -31
- package/skills/gsd-path-build/scripts/integration.py +98 -64
- package/skills/gsd-path-build/scripts/isolation.py +148 -11
- package/skills/gsd-path-build/scripts/members.py +68 -25
- package/skills/gsd-path-build/scripts/model_policy.py +5 -1
- package/skills/gsd-path-build/scripts/pipeline_git.py +68 -30
- package/skills/gsd-path-build/scripts/pipeline_state.py +28 -6
- 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 +30 -9
- package/skills/gsd-path-build/scripts/state_promote.py +15 -4
- package/skills/gsd-path-build/scripts/task_context.py +2 -0
- package/skills/gsd-path-build/scripts/workflow_run.py +9 -2
- package/skills/gsd-path-build/templates/task.md +1 -0
- package/skills/gsd-path-build/templates/wave-review.md +18 -9
- 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 +107 -1
- package/skills/gsd-path-decide/scripts/build_recovery.py +62 -30
- package/skills/gsd-path-decide/scripts/check_handoffs.py +92 -30
- package/skills/gsd-path-decide/scripts/check_task_briefs.py +19 -14
- package/skills/gsd-path-decide/scripts/detect_project.py +17 -2
- package/skills/gsd-path-decide/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-decide/scripts/discussion_validate.py +7 -6
- package/skills/gsd-path-decide/scripts/integration.py +98 -64
- package/skills/gsd-path-decide/scripts/isolation.py +148 -11
- package/skills/gsd-path-decide/scripts/members.py +68 -25
- package/skills/gsd-path-decide/scripts/model_policy.py +5 -1
- package/skills/gsd-path-decide/scripts/pipeline_git.py +68 -30
- package/skills/gsd-path-decide/scripts/pipeline_state.py +28 -6
- 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 +30 -9
- package/skills/gsd-path-decide/scripts/state_promote.py +15 -4
- package/skills/gsd-path-define/SKILL.md +6 -2
- 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/scripts/_common.py +107 -1
- package/skills/gsd-path-define/scripts/build_recovery.py +62 -30
- package/skills/gsd-path-define/scripts/check_handoffs.py +92 -30
- package/skills/gsd-path-define/scripts/check_task_briefs.py +19 -14
- package/skills/gsd-path-define/scripts/detect_project.py +17 -2
- package/skills/gsd-path-define/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-define/scripts/discussion_validate.py +7 -6
- package/skills/gsd-path-define/scripts/integration.py +98 -64
- package/skills/gsd-path-define/scripts/isolation.py +148 -11
- package/skills/gsd-path-define/scripts/members.py +68 -25
- package/skills/gsd-path-define/scripts/model_policy.py +5 -1
- package/skills/gsd-path-define/scripts/pipeline_git.py +68 -30
- package/skills/gsd-path-define/scripts/pipeline_state.py +28 -6
- 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 +30 -9
- package/skills/gsd-path-define/scripts/state_promote.py +15 -4
- package/skills/gsd-path-define/templates/state.md +1 -0
- 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 +107 -1
- package/skills/gsd-path-discuss/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-discuss/scripts/model_policy.py +5 -1
- 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 +107 -1
- package/skills/gsd-path-docs-audit/scripts/build_recovery.py +62 -30
- package/skills/gsd-path-docs-audit/scripts/check_handoffs.py +92 -30
- package/skills/gsd-path-docs-audit/scripts/check_task_briefs.py +19 -14
- package/skills/gsd-path-docs-audit/scripts/detect_project.py +17 -2
- package/skills/gsd-path-docs-audit/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-docs-audit/scripts/discussion_validate.py +7 -6
- package/skills/gsd-path-docs-audit/scripts/integration.py +98 -64
- package/skills/gsd-path-docs-audit/scripts/isolation.py +148 -11
- package/skills/gsd-path-docs-audit/scripts/members.py +68 -25
- package/skills/gsd-path-docs-audit/scripts/model_policy.py +5 -1
- package/skills/gsd-path-docs-audit/scripts/pipeline_git.py +68 -30
- package/skills/gsd-path-docs-audit/scripts/pipeline_state.py +28 -6
- 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 +30 -9
- package/skills/gsd-path-docs-audit/scripts/state_promote.py +15 -4
- 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 +107 -1
- package/skills/gsd-path-forensics/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-forensics/scripts/model_policy.py +5 -1
- package/skills/gsd-path-forensics/scripts/pipeline_diagnose.py +17 -2
- package/skills/gsd-path-forensics/scripts/pipeline_undo.py +17 -8
- 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 +107 -1
- package/skills/gsd-path-inspect/scripts/build_recovery.py +62 -30
- package/skills/gsd-path-inspect/scripts/check_handoffs.py +92 -30
- package/skills/gsd-path-inspect/scripts/check_task_briefs.py +19 -14
- package/skills/gsd-path-inspect/scripts/detect_project.py +17 -2
- package/skills/gsd-path-inspect/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-inspect/scripts/discussion_validate.py +7 -6
- package/skills/gsd-path-inspect/scripts/integration.py +98 -64
- package/skills/gsd-path-inspect/scripts/isolation.py +148 -11
- package/skills/gsd-path-inspect/scripts/members.py +68 -25
- package/skills/gsd-path-inspect/scripts/model_policy.py +5 -1
- package/skills/gsd-path-inspect/scripts/pipeline_git.py +68 -30
- package/skills/gsd-path-inspect/scripts/pipeline_state.py +28 -6
- 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 +30 -9
- package/skills/gsd-path-inspect/scripts/state_promote.py +15 -4
- package/skills/gsd-path-inspect/scripts/workflow_run.py +9 -2
- package/skills/gsd-path-inspect/templates/state.md +1 -0
- 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 +107 -1
- package/skills/gsd-path-loop/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-loop/scripts/model_policy.py +5 -1
- 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 +107 -1
- package/skills/gsd-path-migrate/scripts/discussion_records.py +9 -1
- 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-plan/SKILL.md +3 -0
- package/skills/gsd-path-plan/references/build-recovery.md +13 -0
- package/skills/gsd-path-plan/references/operating-rules.md +11 -3
- package/skills/gsd-path-plan/references/planner.md +13 -1
- package/skills/gsd-path-plan/references/runtime-selection.md +9 -0
- package/skills/gsd-path-plan/scripts/_common.py +107 -1
- package/skills/gsd-path-plan/scripts/build_recovery.py +62 -30
- package/skills/gsd-path-plan/scripts/check_handoffs.py +92 -30
- package/skills/gsd-path-plan/scripts/check_task_briefs.py +19 -14
- package/skills/gsd-path-plan/scripts/detect_project.py +17 -2
- package/skills/gsd-path-plan/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-plan/scripts/discussion_validate.py +7 -6
- package/skills/gsd-path-plan/scripts/integration.py +98 -64
- package/skills/gsd-path-plan/scripts/isolation.py +148 -11
- package/skills/gsd-path-plan/scripts/members.py +68 -25
- package/skills/gsd-path-plan/scripts/model_policy.py +5 -1
- package/skills/gsd-path-plan/scripts/pipeline_git.py +68 -30
- package/skills/gsd-path-plan/scripts/pipeline_state.py +28 -6
- 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 +30 -9
- package/skills/gsd-path-plan/scripts/state_promote.py +15 -4
- package/skills/gsd-path-plan/scripts/workflow_run.py +9 -2
- package/skills/gsd-path-plan/templates/task.md +1 -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 +107 -1
- package/skills/gsd-path-research/scripts/build_recovery.py +62 -30
- package/skills/gsd-path-research/scripts/check_handoffs.py +92 -30
- package/skills/gsd-path-research/scripts/check_task_briefs.py +19 -14
- package/skills/gsd-path-research/scripts/detect_project.py +17 -2
- package/skills/gsd-path-research/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-research/scripts/discussion_validate.py +7 -6
- package/skills/gsd-path-research/scripts/integration.py +98 -64
- package/skills/gsd-path-research/scripts/isolation.py +148 -11
- package/skills/gsd-path-research/scripts/members.py +68 -25
- package/skills/gsd-path-research/scripts/model_policy.py +5 -1
- package/skills/gsd-path-research/scripts/pipeline_git.py +68 -30
- package/skills/gsd-path-research/scripts/pipeline_state.py +28 -6
- 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 +30 -9
- package/skills/gsd-path-research/scripts/state_promote.py +15 -4
- package/skills/gsd-path-roadmap/SKILL.md +16 -6
- 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 +107 -1
- package/skills/gsd-path-roadmap/scripts/build_recovery.py +62 -30
- package/skills/gsd-path-roadmap/scripts/check_handoffs.py +92 -30
- package/skills/gsd-path-roadmap/scripts/check_task_briefs.py +19 -14
- package/skills/gsd-path-roadmap/scripts/detect_project.py +17 -2
- package/skills/gsd-path-roadmap/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-roadmap/scripts/discussion_validate.py +7 -6
- package/skills/gsd-path-roadmap/scripts/integration.py +98 -64
- package/skills/gsd-path-roadmap/scripts/isolation.py +148 -11
- package/skills/gsd-path-roadmap/scripts/members.py +68 -25
- package/skills/gsd-path-roadmap/scripts/model_policy.py +5 -1
- package/skills/gsd-path-roadmap/scripts/pipeline_git.py +68 -30
- package/skills/gsd-path-roadmap/scripts/pipeline_state.py +28 -6
- 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 +30 -9
- package/skills/gsd-path-roadmap/scripts/state_promote.py +15 -4
- package/skills/gsd-path-ship/SKILL.md +26 -4
- package/skills/gsd-path-ship/references/operating-rules.md +11 -3
- package/skills/gsd-path-ship/references/reviewer-final.md +5 -5
- package/skills/gsd-path-ship/references/reviewer-wave.md +46 -13
- package/skills/gsd-path-ship/references/runtime-selection.md +9 -0
- package/skills/gsd-path-ship/scripts/_common.py +107 -1
- package/skills/gsd-path-ship/scripts/build_recovery.py +62 -30
- package/skills/gsd-path-ship/scripts/build_state.py +195 -5
- package/skills/gsd-path-ship/scripts/check_handoffs.py +92 -30
- package/skills/gsd-path-ship/scripts/check_task_briefs.py +19 -14
- package/skills/gsd-path-ship/scripts/detect_project.py +17 -2
- package/skills/gsd-path-ship/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-ship/scripts/discussion_validate.py +7 -6
- package/skills/gsd-path-ship/scripts/integration.py +98 -64
- package/skills/gsd-path-ship/scripts/isolation.py +148 -11
- package/skills/gsd-path-ship/scripts/members.py +68 -25
- package/skills/gsd-path-ship/scripts/model_policy.py +5 -1
- package/skills/gsd-path-ship/scripts/pipeline_git.py +68 -30
- package/skills/gsd-path-ship/scripts/pipeline_state.py +28 -6
- 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 +30 -9
- package/skills/gsd-path-ship/scripts/state_promote.py +15 -4
- package/skills/gsd-path-ship/scripts/workflow_run.py +9 -2
- package/skills/gsd-path-ship/templates/final-review.md +5 -5
- package/skills/gsd-path-ship/templates/wave-review.md +18 -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 +107 -1
- package/skills/gsd-path-undo/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-undo/scripts/model_policy.py +5 -1
- package/skills/gsd-path-undo/scripts/pipeline_undo.py +17 -8
- package/skills/path/DEFINE.md +6 -2
- package/skills/path/PLAN.md +3 -0
- package/skills/path/ROADMAP.md +16 -6
- package/skills/path/SHIP.md +26 -4
- package/skills/path/SKILL.md +52 -24
- package/skills/path/references/build-native.md +96 -9
- package/skills/path/references/build-recovery.md +13 -0
- package/skills/path/references/coder.md +7 -3
- package/skills/path/references/operating-rules.md +11 -3
- package/skills/path/references/planner.md +13 -1
- package/skills/path/references/reviewer-final.md +5 -5
- package/skills/path/references/reviewer-wave.md +46 -13
- package/skills/path/references/runtime-selection.md +9 -0
- package/skills/path/scripts/_common.py +107 -1
- package/skills/path/scripts/build_recovery.py +62 -30
- package/skills/path/scripts/build_state.py +195 -5
- package/skills/path/scripts/check_handoffs.py +92 -30
- package/skills/path/scripts/check_task_briefs.py +19 -14
- package/skills/path/scripts/detect_project.py +17 -2
- package/skills/path/scripts/discussion_records.py +9 -1
- package/skills/path/scripts/discussion_validate.py +7 -6
- package/skills/path/scripts/dispatch_driver.py +157 -31
- package/skills/path/scripts/git_guard.py +24 -5
- package/skills/path/scripts/integration.py +98 -64
- package/skills/path/scripts/isolation.py +148 -11
- package/skills/path/scripts/members.py +68 -25
- package/skills/path/scripts/model_policy.py +5 -1
- package/skills/path/scripts/pipeline_git.py +68 -30
- package/skills/path/scripts/pipeline_state.py +28 -6
- 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 +30 -9
- package/skills/path/scripts/state_promote.py +15 -4
- package/skills/path/scripts/task_context.py +2 -0
- package/skills/path/scripts/workflow_run.py +9 -2
- package/skills/path/templates/final-review.md +5 -5
- package/skills/path/templates/state.md +1 -0
- package/skills/path/templates/task.md +1 -0
- package/skills/path/templates/wave-review.md +18 -9
|
@@ -20,6 +20,15 @@ references to bundled copies of those helpers. Other skill helpers, templates,
|
|
|
20
20
|
and role briefs remain in the installed skill bundle. Pass `-B` to Python helper
|
|
21
21
|
invocations so execution does not create bytecode in the runtime store.
|
|
22
22
|
|
|
23
|
+
The selected runtime is authoritative for each helper in its `manifest.json`;
|
|
24
|
+
this includes `review_findings.py` and `task_context.py`. A selected runtime
|
|
25
|
+
that was published before a helper became a runtime file does not list that
|
|
26
|
+
helper: run the bundled copy until the project runtime is upgraded.
|
|
27
|
+
`dispatch_driver.py` and `workflow_run.py` always run from the installed skill
|
|
28
|
+
bundle, because they read role briefs and templates from it; a skill update
|
|
29
|
+
replaces them, a runtime upgrade does not. The driver reloads the helper modules
|
|
30
|
+
that it imports from the selected runtime.
|
|
31
|
+
|
|
23
32
|
With no declaration, retain the legacy helper lookup. An existing
|
|
24
33
|
`.gsd-path/runtime/` requires the explicit `--runtime-migrate --project PATH`
|
|
25
34
|
operation before adopting external storage; review the resulting Git diff.
|
|
@@ -25,7 +25,8 @@ import signal
|
|
|
25
25
|
import subprocess
|
|
26
26
|
import time
|
|
27
27
|
from pathlib import Path
|
|
28
|
-
from typing import BinaryIO, Iterator, List, Optional, Sequence
|
|
28
|
+
from typing import BinaryIO, Iterable, Iterator, List, Optional, Sequence, Tuple
|
|
29
|
+
|
|
29
30
|
|
|
30
31
|
# Chosen by what imports, not os.name, so tests can emulate Windows on POSIX.
|
|
31
32
|
try:
|
|
@@ -161,6 +162,33 @@ def project_ignore_error(repo: Path) -> Optional[str]:
|
|
|
161
162
|
+ ". Anchor the product rule (for example `/build/`) in a task that owns it.")
|
|
162
163
|
|
|
163
164
|
|
|
165
|
+
_DEFAULT_BRANCH_RE = re.compile(
|
|
166
|
+
r"[^\s#\"'\\~^:?*\[\x00-\x1f\x7f-][^\s#\"'\\~^:?*\[\x00-\x1f\x7f]*"
|
|
167
|
+
)
|
|
168
|
+
_RESERVED_BRANCH_PREFIXES = ("gsd-path/", "gsd-path-integrate/", "gsd-path-task/")
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def valid_default_branch(name: str) -> bool:
|
|
172
|
+
"""A git branch name that STATE frontmatter can hold and Path does not reserve."""
|
|
173
|
+
return (
|
|
174
|
+
bool(_DEFAULT_BRANCH_RE.fullmatch(name))
|
|
175
|
+
and name != "null"
|
|
176
|
+
and not name.startswith(_RESERVED_BRANCH_PREFIXES)
|
|
177
|
+
and not name.endswith(("/", ".", ".lock"))
|
|
178
|
+
and not any(part in name for part in ("..", "//", "/.", "@{"))
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def origin_default_branch(repo: Path) -> str:
|
|
183
|
+
"""The origin default branch that initialization records; an unset origin/HEAD means main."""
|
|
184
|
+
result = run_git(repo, "symbolic-ref", "--quiet", "refs/remotes/origin/HEAD")
|
|
185
|
+
prefix = "refs/remotes/origin/"
|
|
186
|
+
remote_ref = result.stdout.strip()
|
|
187
|
+
if result.returncode != 0 or not remote_ref.startswith(prefix):
|
|
188
|
+
return "main"
|
|
189
|
+
return remote_ref.removeprefix(prefix)
|
|
190
|
+
|
|
191
|
+
|
|
164
192
|
def section_body(text: str, heading: str) -> Optional[str]:
|
|
165
193
|
"""The text under `## <heading>` up to the next `## `, or None when absent."""
|
|
166
194
|
match = re.search(
|
|
@@ -169,6 +197,79 @@ def section_body(text: str, heading: str) -> Optional[str]:
|
|
|
169
197
|
return match.group("body") if match else None
|
|
170
198
|
|
|
171
199
|
|
|
200
|
+
def overlapping_paths(left: Sequence[str], right: Sequence[str]) -> List[str]:
|
|
201
|
+
"""Return the sorted paths that two task `files` lists both cover.
|
|
202
|
+
|
|
203
|
+
An entry covers itself and the paths below it. For a declared directory
|
|
204
|
+
and a path below it, the result names the lower path. The callers have no
|
|
205
|
+
task base, so this does not ask if an entry is a file: the task-brief
|
|
206
|
+
lint rejects a path below a file at the base.
|
|
207
|
+
"""
|
|
208
|
+
return sorted(
|
|
209
|
+
{
|
|
210
|
+
max(one, other, key=len)
|
|
211
|
+
for one in left
|
|
212
|
+
for other in right
|
|
213
|
+
if one == other or one.startswith(other + "/") or other.startswith(one + "/")
|
|
214
|
+
}
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
# The `- ` of an indented sub-bullet line. A line that would then read as a
|
|
219
|
+
# numbered item (`- 2. text`) keeps its marker, so both readings of a source
|
|
220
|
+
# have the same criteria.
|
|
221
|
+
SUB_BULLET_MARKER = re.compile(r"(?m)^([ \t]+)-[ \t]+(?![ \t]*\d+\.\s)")
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
def without_sub_bullet_markers(source: str) -> str:
|
|
225
|
+
"""`source` with the `- ` marker of each indented sub-bullet line removed."""
|
|
226
|
+
return SUB_BULLET_MARKER.sub(r"\1", source)
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
class Criterion(str):
|
|
230
|
+
"""A criterion as its parser joins it, with the `- ` markers of its sub-bullet lines.
|
|
231
|
+
|
|
232
|
+
`bare` is the same criterion parsed from `without_sub_bullet_markers(source)`.
|
|
233
|
+
The joined text cannot tell a marker from a minus sign; the source lines can.
|
|
234
|
+
"""
|
|
235
|
+
|
|
236
|
+
bare: str
|
|
237
|
+
|
|
238
|
+
def __new__(cls, text: str, bare: str) -> "Criterion":
|
|
239
|
+
criterion = super().__new__(cls, text)
|
|
240
|
+
criterion.bare = bare
|
|
241
|
+
return criterion
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def quotes_criterion(quote: str, criterion: str) -> bool:
|
|
245
|
+
"""Whether a review quote is `criterion`, for every reader.
|
|
246
|
+
|
|
247
|
+
Only whitespace is collapsed. The quote must equal the criterion with all
|
|
248
|
+
the markers of its sub-bullet lines or with none of them; every other
|
|
249
|
+
character, a hyphen inside a line too, is compared.
|
|
250
|
+
"""
|
|
251
|
+
forms = (criterion, getattr(criterion, "bare", criterion))
|
|
252
|
+
return " ".join(quote.split()) in {" ".join(form.split()) for form in forms}
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def quoted_criterion(item: str, criteria: Sequence[str]) -> Optional[Tuple[int, int]]:
|
|
256
|
+
"""Index of the criterion quoted at the start of `item`, and where the quote ends.
|
|
257
|
+
|
|
258
|
+
A criterion can contain ` — ` itself, so each separator and the end of
|
|
259
|
+
`item` is a candidate, the longest quote first. A criterion as written
|
|
260
|
+
wins over any criterion read without its sub-bullet markers.
|
|
261
|
+
"""
|
|
262
|
+
ends = [match.start() for match in re.finditer("(?= —(?: |$))|$", item)][::-1]
|
|
263
|
+
for bare in (False, True):
|
|
264
|
+
for end in ends:
|
|
265
|
+
quote = " ".join(item[:end].split())
|
|
266
|
+
for index, criterion in enumerate(criteria):
|
|
267
|
+
form = getattr(criterion, "bare", criterion) if bare else criterion
|
|
268
|
+
if quote == " ".join(form.split()):
|
|
269
|
+
return index, end
|
|
270
|
+
return None
|
|
271
|
+
|
|
272
|
+
|
|
172
273
|
def task_verify_command(task_text: str) -> str:
|
|
173
274
|
"""The Verify shell text, excluding the closing fence's separator newline."""
|
|
174
275
|
body = section_body(task_text, "Verify")
|
|
@@ -176,6 +277,11 @@ def task_verify_command(task_text: str) -> str:
|
|
|
176
277
|
return block.group("block").removesuffix("\n") if block else ""
|
|
177
278
|
|
|
178
279
|
|
|
280
|
+
def fix_verify(commands: Iterable[str]) -> str:
|
|
281
|
+
"""The Verify of a fix task: each distinct source Verify in its own subshell, under `set -e`."""
|
|
282
|
+
return "set -e\n" + "\n".join(f"(\n{command}\n)" for command in dict.fromkeys(commands))
|
|
283
|
+
|
|
284
|
+
|
|
179
285
|
def latest_verify_entry(entries: list, command: str, commit: str,
|
|
180
286
|
repo: Optional[str] = None) -> Optional[dict]:
|
|
181
287
|
"""Rows are keyed by (command, repo, commit); a row without `repo` is a coordinator row."""
|
|
@@ -7,6 +7,7 @@ import json
|
|
|
7
7
|
import os
|
|
8
8
|
import shutil
|
|
9
9
|
import sys
|
|
10
|
+
import traceback
|
|
10
11
|
|
|
11
12
|
# Runtime helpers must not modify their immutable installation.
|
|
12
13
|
sys.dont_write_bytecode = True
|
|
@@ -33,7 +34,7 @@ def _load_pipeline_modules():
|
|
|
33
34
|
try:
|
|
34
35
|
from scripts import archive_milestone, pipeline_state, _common
|
|
35
36
|
return _common, archive_milestone, pipeline_state
|
|
36
|
-
except
|
|
37
|
+
except ImportError as error: # a foreign `scripts` package
|
|
37
38
|
if error.name not in {
|
|
38
39
|
"scripts",
|
|
39
40
|
"scripts.archive_milestone",
|
|
@@ -41,6 +42,13 @@ def _load_pipeline_modules():
|
|
|
41
42
|
"scripts._common",
|
|
42
43
|
}:
|
|
43
44
|
raise
|
|
45
|
+
# A plain ImportError raised while a `scripts` module loaded is not a
|
|
46
|
+
# foreign package. A missing module falls back, as before.
|
|
47
|
+
if not isinstance(error, ModuleNotFoundError) and any(
|
|
48
|
+
frame.f_globals.get("__name__", "").startswith("scripts.")
|
|
49
|
+
for frame, _ in traceback.walk_tb(error.__traceback__)
|
|
50
|
+
):
|
|
51
|
+
raise
|
|
44
52
|
shared_scripts = Path(__file__).resolve().parents[2] / "gsd-path" / "scripts"
|
|
45
53
|
sys.path.insert(0, str(shared_scripts))
|
|
46
54
|
import archive_milestone
|
|
@@ -202,7 +202,11 @@ def native_record(args):
|
|
|
202
202
|
identity = {'repo': str(args.repo.resolve()), 'project_dir': args.project_dir,
|
|
203
203
|
'scope': args.scope, 'assignment': args.assignment, 'role': args.role}
|
|
204
204
|
if data is not None and data.get('identity') != identity:
|
|
205
|
-
|
|
205
|
+
recorded = data.get('identity')
|
|
206
|
+
recorded = recorded if isinstance(recorded, dict) else {}
|
|
207
|
+
differing = ', '.join(f'{field}: {value}, record has {recorded.get(field)}'
|
|
208
|
+
for field, value in identity.items() if recorded.get(field) != value)
|
|
209
|
+
raise PolicyError(f'record belongs to another assignment or milestone/track/cycle ({differing})')
|
|
206
210
|
if args.action == 'release':
|
|
207
211
|
if data is None or not args.terminal_result:
|
|
208
212
|
raise PolicyError('release requires an existing record and terminal-result evidence')
|
|
@@ -22,6 +22,7 @@ from datetime import date
|
|
|
22
22
|
# Runtime helpers must not modify their immutable installation.
|
|
23
23
|
sys.dont_write_bytecode = True
|
|
24
24
|
import tempfile
|
|
25
|
+
import traceback
|
|
25
26
|
from pathlib import Path, PurePosixPath
|
|
26
27
|
from typing import Optional, Sequence
|
|
27
28
|
|
|
@@ -53,7 +54,7 @@ def _load_pipeline_modules():
|
|
|
53
54
|
try:
|
|
54
55
|
from scripts import archive_milestone, isolation, pipeline_git, pipeline_state, state_checkpoint
|
|
55
56
|
return archive_milestone, isolation, pipeline_git, pipeline_state, state_checkpoint
|
|
56
|
-
except
|
|
57
|
+
except ImportError as error: # a foreign `scripts` package
|
|
57
58
|
if error.name not in {
|
|
58
59
|
"scripts",
|
|
59
60
|
"scripts.archive_milestone",
|
|
@@ -63,6 +64,13 @@ def _load_pipeline_modules():
|
|
|
63
64
|
"scripts.state_checkpoint",
|
|
64
65
|
}:
|
|
65
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
|
|
66
74
|
shared = Path(__file__).resolve().parents[2] / "gsd-path" / "scripts"
|
|
67
75
|
sys.path.insert(0, str(shared))
|
|
68
76
|
import archive_milestone
|
|
@@ -772,14 +780,15 @@ def _member_undo_parent(repo: Path, member: str, landing: str) -> str:
|
|
|
772
780
|
bound = entry["branch"]
|
|
773
781
|
if _run_git(checkout, "rev-parse", f"refs/heads/{bound}").stdout.strip() != landing:
|
|
774
782
|
raise UndoError(f"member {member} {bound} moved past this landing")
|
|
775
|
-
_require_member_unpublished(checkout, member, landing, bound)
|
|
783
|
+
_require_member_unpublished(repo, checkout, member, landing, bound)
|
|
776
784
|
return _run_git(checkout, "rev-parse", f"{landing}^").stdout.strip()
|
|
777
785
|
|
|
778
786
|
|
|
779
|
-
def _require_member_unpublished(checkout: Path, member: str, landing: str, bound: str) -> None:
|
|
780
|
-
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}"
|
|
781
790
|
if _run_git(checkout, "merge-base", "--is-ancestor", landing, ref, check=False).returncode == 0:
|
|
782
|
-
raise UndoError(f"member {member} landing is already on {
|
|
791
|
+
raise UndoError(f"member {member} landing is already on origin/{branch}")
|
|
783
792
|
|
|
784
793
|
|
|
785
794
|
def _require_no_member_landing_journal(repo: Path) -> None:
|
|
@@ -794,7 +803,7 @@ def _undo_member_landing(repo: Path, transaction: dict[str, object]) -> None:
|
|
|
794
803
|
checkout, _, entry = isolation._member_context(repo, member)
|
|
795
804
|
tip = _run_git(checkout, "rev-parse", f"refs/heads/{entry['branch']}").stdout.strip()
|
|
796
805
|
if tip == transaction["member_parent"]:
|
|
797
|
-
_require_member_unpublished(checkout, member, str(transaction["landing"]), entry["branch"])
|
|
806
|
+
_require_member_unpublished(repo, checkout, member, str(transaction["landing"]), entry["branch"])
|
|
798
807
|
return
|
|
799
808
|
if tip != transaction["landing"]:
|
|
800
809
|
raise UndoError(f"member {member} bound branch moved during undo")
|
|
@@ -861,7 +870,7 @@ def classify_undo(repo: Path) -> dict[str, object]:
|
|
|
861
870
|
[f"an in-progress helper journal exists ({names}); resume that transaction first"]
|
|
862
871
|
)
|
|
863
872
|
if git.get("ancestor_of_origin_main"):
|
|
864
|
-
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"])
|
|
865
874
|
|
|
866
875
|
product = _product_dirty(dirty)
|
|
867
876
|
if product:
|
|
@@ -1081,7 +1090,7 @@ def _require_unpublished_reset(repo: Path, expected_branch: str) -> None:
|
|
|
1081
1090
|
if git.get("published"):
|
|
1082
1091
|
raise UndoError("HEAD became published on its recorded remote branch")
|
|
1083
1092
|
if git.get("ancestor_of_origin_main"):
|
|
1084
|
-
raise UndoError("HEAD became published through origin
|
|
1093
|
+
raise UndoError("HEAD became published through the origin default branch")
|
|
1085
1094
|
|
|
1086
1095
|
|
|
1087
1096
|
def _remove_untracked_tree(repo: Path, relative: str) -> None:
|
package/skills/path/DEFINE.md
CHANGED
|
@@ -168,8 +168,12 @@ State ownership. There is no re-interview of charter or roadmap scope:
|
|
|
168
168
|
and prohibition ruling for the user to accept or change; it never rules on
|
|
169
169
|
them silently. A requested change that contradicts the
|
|
170
170
|
charter or the resolved roadmap entry is a scope change — this phase never
|
|
171
|
-
edits the roadmap; surface it to the user for a `$gsd-path-roadmap`
|
|
172
|
-
|
|
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.
|
|
173
177
|
4. On approval, finalize per the Output contract, setting `milestone` to the
|
|
174
178
|
resolved entry's slug. The router continues with milestone-scoped research
|
|
175
179
|
when the entry lists open questions, otherwise planning.
|
package/skills/path/PLAN.md
CHANGED
|
@@ -119,6 +119,9 @@ as stated in Lookahead mode.
|
|
|
119
119
|
in the same wave. Same-wave tasks may share files only when one
|
|
120
120
|
transitively depends on the other through `deps`; the build executes
|
|
121
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.
|
|
122
125
|
- Reject a declared dependency that carries neither data nor a prerequisite
|
|
123
126
|
effect. A `deps` edge is valid only when the dependent consumes a symbol,
|
|
124
127
|
signature, schema, endpoint, file format, or path named in that
|
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
|
@@ -267,7 +267,11 @@ The persisted `STATE.archive` field is the transaction identity.
|
|
|
267
267
|
`python3 <absolute archive_milestone.py> close-members --repo <root>`
|
|
268
268
|
after preflight passes and before recording shipment. It closes each
|
|
269
269
|
locked member in lock order in that member's integration mode and
|
|
270
|
-
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
|
|
271
275
|
link, stop, and rerun the same command after the user merges it; never
|
|
272
276
|
merge a member PR yourself. When it returns `integrated`, keep its `body`
|
|
273
277
|
for the ship commit below.
|
|
@@ -310,8 +314,10 @@ The persisted `STATE.archive` field is the transaction identity.
|
|
|
310
314
|
milestone is not shipped until integration below passes.
|
|
311
315
|
7. Integrate only after the postcommit `validate` passes, with the recorded
|
|
312
316
|
ship commit and exact reviewed HEAD unchanged. Run `python3 <absolute archive_milestone.py> integrate --repo <root> --slug <STATE.milestone>`.
|
|
313
|
-
This helper validates the ship commit, fetches origin, requires remote
|
|
314
|
-
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:
|
|
315
321
|
|
|
316
322
|
- `direct` owns the resumable merge transaction. It creates the canonical
|
|
317
323
|
named integration worktree, performs the hook-verified `--no-ff` merge,
|
|
@@ -344,6 +350,22 @@ The persisted `STATE.archive` field is the transaction identity.
|
|
|
344
350
|
landing SHA. A closed unmerged PR, squash, rebase, merge queue, moved
|
|
345
351
|
head, duplicate PR, or non-GitHub.com origin blocks. The remote bound
|
|
346
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.
|
|
347
369
|
|
|
348
370
|
A passing run returns the same proof exposed by `validate-integrated`.
|
|
349
371
|
A non-zero result blocks; rerun the exact `integrate` command to resume a
|
|
@@ -354,7 +376,7 @@ The persisted `STATE.archive` field is the transaction identity.
|
|
|
354
376
|
continuing. Never merge into or re-ship the closed branch.
|
|
355
377
|
For a later validation recheck with origin network access, run
|
|
356
378
|
`python3 <absolute archive_milestone.py> validate-integrated --repo <root> --slug <STATE.milestone>`.
|
|
357
|
-
|
|
379
|
+
All integration modes refresh the remote-default and mirrored milestone-tag
|
|
358
380
|
refs when an `origin` remote exists. Without that remote, validation resolves
|
|
359
381
|
the existing remote-default refs locally, preserving offline direct-mode
|
|
360
382
|
fixtures. PR mode also revalidates the PR identity, state, merge provenance,
|
package/skills/path/SKILL.md
CHANGED
|
@@ -179,6 +179,23 @@ selects a milestone branch.
|
|
|
179
179
|
`define/active`; report that no brownfield signal fired, and route to
|
|
180
180
|
the bundled [define contract](DEFINE.md).
|
|
181
181
|
|
|
182
|
+
## Default branch
|
|
183
|
+
|
|
184
|
+
`initialize` records the default branch of `origin` one time, as STATE
|
|
185
|
+
`default_branch`. It reads the local `refs/remotes/origin/HEAD`; when that ref
|
|
186
|
+
is unset it records `main`. When the repository has an `origin`, run
|
|
187
|
+
`git remote set-head origin --auto` before `initialize`, so that the record is
|
|
188
|
+
the default branch of the forge. A STATE file without the field means `main`.
|
|
189
|
+
|
|
190
|
+
`<default_branch>` in the commands below is the `default_branch` value in the
|
|
191
|
+
`validate`, `route`, and `status` JSON, beside `state`. Never edit the field,
|
|
192
|
+
and never take the name from a later `origin/HEAD` lookup. When a helper
|
|
193
|
+
reports that the remote default differs from the recorded one, stop and report
|
|
194
|
+
it. In a project with members, STATE `default_branch` is the default branch of
|
|
195
|
+
the coordinator only. `members.py add` records the default branch of each
|
|
196
|
+
member in `.project/MEMBERS.md`; the member helpers read that record. The
|
|
197
|
+
names can differ.
|
|
198
|
+
|
|
182
199
|
## Integration choice
|
|
183
200
|
|
|
184
201
|
New state uses the user shipping default (built-in: `direct`) for
|
|
@@ -190,7 +207,7 @@ helper; never edit these fields by hand:
|
|
|
190
207
|
python3 <absolute-bundled-pipeline-state.py> configure-integration \
|
|
191
208
|
--repo <absolute-root> \
|
|
192
209
|
--scope <default-or-milestone> \
|
|
193
|
-
--mode <direct
|
|
210
|
+
--mode <direct|pull-request|external-landing>
|
|
194
211
|
```
|
|
195
212
|
|
|
196
213
|
`default` changes the project setting and changes the current milestone only
|
|
@@ -212,16 +229,23 @@ milestone boundary, never during build or ship. Resolve the bundled
|
|
|
212
229
|
`scripts/members.py` to an absolute path and use it; never edit MEMBERS.md
|
|
213
230
|
or a member marker by hand.
|
|
214
231
|
|
|
215
|
-
- To add an existing repository, it needs a GitHub.com `origin
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
232
|
+
- To add an existing repository, it needs a GitHub.com `origin`, a clean
|
|
233
|
+
worktree, and no active milestone of its own. Its default branch can have
|
|
234
|
+
any name. Run `git remote set-head origin --auto` in the member first: `add`
|
|
235
|
+
reads the member's local `origin/HEAD` one time and records the name in
|
|
236
|
+
MEMBERS.md as `Default branch`; an unset `origin/HEAD` records `main`. Ask
|
|
237
|
+
for the member name, checkout path, and integration (`direct`,
|
|
238
|
+
`pull-request`, or `default`, which follows the milestone's choice), then run
|
|
219
239
|
`python3 <members.py> add --repo <absolute-root> --name <name> --checkout <path> --integration <mode>`.
|
|
240
|
+
When `validate` or member close later reports
|
|
241
|
+
`remote default must be <recorded>`, stop and report it; never edit the
|
|
242
|
+
record.
|
|
220
243
|
- To create a new member repository, present the exact `owner/name`,
|
|
221
244
|
visibility, and checkout path as the **Review** surface and get approval
|
|
222
245
|
first, as for a new GitHub repository. Then run the same command with
|
|
223
246
|
`--create <owner/name> --visibility <visibility>`. It journals the approved
|
|
224
|
-
target before creating anything; rerun the identical command to resume.
|
|
247
|
+
target before creating anything; rerun the identical command to resume. A
|
|
248
|
+
new member repository uses `main`.
|
|
225
249
|
- After adding a member, tell the user to install its guard hooks:
|
|
226
250
|
`npx @opengsd/gsd-path@latest --member-of <absolute-root> --project <member checkout>`.
|
|
227
251
|
- `python3 <members.py> validate --repo <absolute-root>` checks every member;
|
|
@@ -269,8 +293,8 @@ integration ancestry, cleanliness, and journal ownership before continuing.
|
|
|
269
293
|
After it returns, continue the state transition or lookahead promotion below.
|
|
270
294
|
Do not reconstruct this classification from Git output or Log prose.
|
|
271
295
|
When the route returns `allow_remote_absent: true`, also pass
|
|
272
|
-
`--allow-missing-previous`; this is valid only because
|
|
273
|
-
auto-deleted the published bound branch.
|
|
296
|
+
`--allow-missing-previous`; this is valid only because the forge may have
|
|
297
|
+
auto-deleted the published bound branch after the merge.
|
|
274
298
|
|
|
275
299
|
Before ordinary routing, inspect `STATE.archive`.
|
|
276
300
|
|
|
@@ -328,7 +352,7 @@ promotion, `resume-next-handoff` resumes the verified `bind-next` transaction,
|
|
|
328
352
|
`resume-undo` invokes `$gsd-path-undo` with the returned kind and expected HEAD,
|
|
329
353
|
`block` stops with the returned reason. `bind-initial`
|
|
330
354
|
means initialization is complete and phase work must wait for the initial
|
|
331
|
-
router binding: resolve the exact fetched `origin
|
|
355
|
+
router binding: resolve the exact fetched `origin/<default_branch>` SHA, call `bind-initial` as
|
|
332
356
|
above with `route.branch`, then persist its returned branch with
|
|
333
357
|
`pipeline_state.py transition` using the route result's `state` phase and status plus its
|
|
334
358
|
null branch and archive as expected fields. Set `--set-branch` to the helper's
|
|
@@ -371,7 +395,8 @@ on `NEEDS-USER`. Planning owns the single build-approval gate; never ask a
|
|
|
371
395
|
second time. One user-driven exception to normal routing: at a program milestone
|
|
372
396
|
boundary — `inspect/active` or `define/active` with no approved INTENT.md for
|
|
373
397
|
the next milestone — a user request to re-scope the remaining `pending`
|
|
374
|
-
entries
|
|
398
|
+
entries, or at `define/active` the `active` entry, routes to the bundled
|
|
399
|
+
[roadmap contract](ROADMAP.md) in re-slice mode.
|
|
375
400
|
|
|
376
401
|
## Lookahead planning (program flow)
|
|
377
402
|
|
|
@@ -400,7 +425,9 @@ template](templates/state.md) with `pipeline: gsd-path/v2`, `phase:
|
|
|
400
425
|
inspect`, `status: active`, the selector's exact returned `milestone` slug as
|
|
401
426
|
`milestone`, `branch: null`, and `archive: null`. Copy the active project's
|
|
402
427
|
`integration_default` into both integration mode fields and set
|
|
403
|
-
`integration_source: default`.
|
|
428
|
+
`integration_source: default`. Set `default_branch` to the active project's
|
|
429
|
+
value; when the active STATE.md has no `default_branch` line, delete that line
|
|
430
|
+
from the new file. Then follow the bundled
|
|
404
431
|
phase contracts in their Lookahead mode — inspect, define (milestone +
|
|
405
432
|
brownfield), research (only when the entry lists open questions), decide, and
|
|
406
433
|
plan — rooted at `.project/next/`.
|
|
@@ -424,14 +451,14 @@ bundled integration check (`validate-integrated`); pending integration routes
|
|
|
424
451
|
back to ship, never here. Preserve the previous archive path, ship SHA,
|
|
425
452
|
integration SHA, and build branch in the state Log. Before fetching or binding
|
|
426
453
|
the next program branch, fetch origin and resolve the exact current
|
|
427
|
-
`origin
|
|
454
|
+
`origin/<default_branch>` SHA. For a program roadmap, resolve the branch from that exact
|
|
428
455
|
fetched commit through the bundled helper. With a saved lookahead track, run:
|
|
429
456
|
|
|
430
457
|
```text
|
|
431
458
|
python3 <absolute-bundled-promote-lookahead.py> select-base \
|
|
432
459
|
--repo <absolute-primary-root> \
|
|
433
|
-
--base <exact-
|
|
434
|
-
--remote-default origin
|
|
460
|
+
--base <exact-remote-default-sha> \
|
|
461
|
+
--remote-default origin/<default_branch> \
|
|
435
462
|
--lookahead
|
|
436
463
|
```
|
|
437
464
|
|
|
@@ -440,8 +467,8 @@ Without a saved lookahead track, run:
|
|
|
440
467
|
```text
|
|
441
468
|
python3 <absolute-bundled-promote-lookahead.py> select-base \
|
|
442
469
|
--repo <absolute-primary-root> \
|
|
443
|
-
--base <exact-
|
|
444
|
-
--remote-default origin
|
|
470
|
+
--base <exact-remote-default-sha> \
|
|
471
|
+
--remote-default origin/<default_branch>
|
|
445
472
|
```
|
|
446
473
|
|
|
447
474
|
When the helper returns `status: complete`, report program completion and stop;
|
|
@@ -457,21 +484,22 @@ python3 <absolute-bundled-pipeline-git.py> bind-next \
|
|
|
457
484
|
--branch <selected-branch> \
|
|
458
485
|
--previous-branch <STATE.branch> \
|
|
459
486
|
--ship <exact-ship-sha> \
|
|
460
|
-
--remote-default origin
|
|
461
|
-
--base <exact-
|
|
487
|
+
--remote-default origin/<default_branch> \
|
|
488
|
+
--base <exact-remote-default-sha> \
|
|
462
489
|
--landing <validate-integrated-landing-sha>
|
|
463
490
|
```
|
|
464
491
|
|
|
465
492
|
Add `--allow-missing-previous` when `validate-integrated` returned
|
|
466
|
-
`mode: pull-request` and `origin/<STATE.branch>`
|
|
467
|
-
that
|
|
468
|
-
the handoff. The helper independently
|
|
469
|
-
milestone tag
|
|
493
|
+
`mode: pull-request` or `mode: external-landing` and `origin/<STATE.branch>`
|
|
494
|
+
is absent. The forge may delete that source branch after merge; the local
|
|
495
|
+
branch and exact ship SHA still bind the handoff. The helper independently
|
|
496
|
+
verifies the published milestone tag for `STATE.integration` and the merge
|
|
497
|
+
topology before accepting the missing branch.
|
|
470
498
|
|
|
471
499
|
The helper requires the previous branch, while it still exists locally, to
|
|
472
500
|
remain at the ship SHA, proves the ship commit is integrated into the exact
|
|
473
501
|
base, rejects local or remote branch collisions,
|
|
474
|
-
and switches the clean primary worktree without tracking
|
|
502
|
+
and switches the clean primary worktree without tracking the default branch. It then
|
|
475
503
|
retires the integrated previous branch — deleted locally and on origin; the
|
|
476
504
|
ship commit stays reachable from the integration merge and its tag. Repeating the
|
|
477
505
|
same command while the new branch is current at the unchanged base is the
|
|
@@ -488,7 +516,7 @@ Log, then:
|
|
|
488
516
|
--repo <absolute-primary-root> \
|
|
489
517
|
--milestone <next-slug> \
|
|
490
518
|
--branch gsd-path/M00N \
|
|
491
|
-
--base <exact-current-
|
|
519
|
+
--base <exact-current-remote-default-sha> \
|
|
492
520
|
--landing <exact-milestone-merge-sha>
|
|
493
521
|
```
|
|
494
522
|
|