@opengsd/gsd-path 1.3.1 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +2 -207
- package/CHANGELOG.md +331 -69
- package/DOCS.md +25 -9
- package/FULL.md +12 -5
- package/GUIDE.md +1 -1
- package/HOOKS.md +104 -14
- package/QUICK.md +5 -2
- package/README.md +131 -111
- package/RUNTIME.md +2 -2
- package/UPDATE.md +61 -11
- package/WORKFLOW.md +44 -7
- package/package.json +13 -9
- package/platforms/shared-agents/dispatch.md +13 -0
- package/scripts/_common.py +619 -18
- package/scripts/archive_milestone.py +160 -86
- package/scripts/bootstrap_repository.py +8 -5
- package/scripts/build_recovery.py +100 -32
- package/scripts/build_state.py +143 -24
- package/scripts/check_docs_audit.py +91 -7
- package/scripts/check_handoffs.py +662 -50
- package/scripts/check_task_briefs.py +338 -30
- package/scripts/check_update.py +2 -2
- package/scripts/core_hook_gate.py +10 -1
- package/scripts/core_hook_settings.py +11 -4
- package/scripts/detect_project.py +587 -32
- package/scripts/discussion_records.py +19 -13
- package/scripts/discussion_validate.py +152 -50
- package/scripts/dispatch_driver.py +501 -46
- package/scripts/git_guard.py +118 -31
- package/scripts/guard_hook.py +1567 -194
- package/scripts/install.mjs +77 -46
- package/scripts/install.py +611 -50
- package/scripts/integration.py +580 -25
- package/scripts/isolation.py +1438 -57
- package/scripts/lean_verification.py +99 -19
- package/scripts/loop_run.py +31 -29
- package/scripts/members.py +706 -0
- package/scripts/migrate_core.py +2 -2
- package/scripts/path_config.py +5 -5
- package/scripts/pipeline_diagnose.py +82 -31
- package/scripts/pipeline_git.py +124 -34
- package/scripts/pipeline_state.py +287 -87
- package/scripts/pipeline_undo.py +218 -30
- package/scripts/promote_lookahead.py +1 -1
- package/scripts/review_panel.py +1 -1
- package/scripts/runtime_store.py +55 -11
- package/scripts/skill-resources.json +37 -5
- package/scripts/state_checkpoint.py +135 -44
- package/scripts/state_promote.py +2 -0
- package/scripts/status_runtime.py +58 -10
- package/scripts/sync_skill_resources.py +8 -7
- package/scripts/task_context.py +12 -3
- package/scripts/token_budget.py +12 -8
- package/scripts/wizard.mjs +1 -0
- package/scripts/workflow_run.py +107 -30
- package/scripts/worktree_paths.py +72 -10
- package/skills/gsd-path/BUILD.md +7 -1
- package/skills/gsd-path/DECIDE.md +11 -4
- package/skills/gsd-path/DEFINE.md +36 -4
- package/skills/gsd-path/DOCS-AUDIT.md +6 -4
- package/skills/gsd-path/INSPECT.md +5 -4
- package/skills/gsd-path/PLAN.md +18 -4
- package/skills/gsd-path/RESEARCH.md +13 -1
- package/skills/gsd-path/ROADMAP.md +2 -1
- package/skills/gsd-path/SHIP.md +33 -11
- package/skills/gsd-path/SKILL.md +45 -1
- package/skills/gsd-path/references/build-native.md +63 -15
- package/skills/gsd-path/references/codebase-mapper.md +2 -1
- package/skills/gsd-path/references/dispatch.md +13 -0
- package/skills/gsd-path/references/docs-auditor.md +7 -1
- package/skills/gsd-path/references/operating-rules.md +214 -0
- package/skills/gsd-path/references/planner.md +22 -4
- package/skills/gsd-path/references/reviewer-final.md +20 -2
- package/skills/gsd-path/references/reviewer-wave.md +18 -5
- package/skills/gsd-path/references/reviewer.md +3 -1
- package/skills/gsd-path/references/spec-probes.md +150 -0
- package/skills/gsd-path/scripts/_common.py +619 -18
- package/skills/gsd-path/scripts/archive_milestone.py +160 -86
- package/skills/gsd-path/scripts/bootstrap_repository.py +8 -5
- package/skills/gsd-path/scripts/build_recovery.py +100 -32
- package/skills/gsd-path/scripts/build_state.py +143 -24
- package/skills/gsd-path/scripts/check_docs_audit.py +91 -7
- package/skills/gsd-path/scripts/check_handoffs.py +662 -50
- package/skills/gsd-path/scripts/check_task_briefs.py +338 -30
- package/skills/gsd-path/scripts/check_update.py +2 -2
- package/skills/gsd-path/scripts/detect_project.py +587 -32
- package/skills/gsd-path/scripts/discussion_records.py +19 -13
- package/skills/gsd-path/scripts/discussion_validate.py +152 -50
- package/skills/gsd-path/scripts/dispatch_driver.py +501 -46
- package/skills/gsd-path/scripts/git_guard.py +118 -31
- package/skills/gsd-path/scripts/integration.py +580 -25
- package/skills/gsd-path/scripts/isolation.py +1438 -57
- package/skills/gsd-path/scripts/lean_verification.py +99 -19
- package/skills/gsd-path/scripts/loop_run.py +31 -29
- package/skills/gsd-path/scripts/members.py +706 -0
- package/skills/gsd-path/scripts/path_config.py +5 -5
- package/skills/gsd-path/scripts/pipeline_git.py +124 -34
- package/skills/gsd-path/scripts/pipeline_state.py +287 -87
- package/skills/gsd-path/scripts/promote_lookahead.py +1 -1
- package/skills/gsd-path/scripts/review_panel.py +1 -1
- package/skills/gsd-path/scripts/state_checkpoint.py +135 -44
- package/skills/gsd-path/scripts/state_promote.py +2 -0
- package/skills/gsd-path/scripts/status_runtime.py +58 -10
- package/skills/gsd-path/scripts/task_context.py +12 -3
- package/skills/gsd-path/scripts/token_budget.py +12 -8
- package/skills/gsd-path/scripts/workflow_run.py +107 -30
- package/skills/gsd-path/scripts/worktree_paths.py +72 -10
- package/skills/gsd-path/templates/codebase.md +1 -1
- package/skills/gsd-path/templates/docs-audit.md +6 -2
- package/skills/gsd-path/templates/final-review.md +16 -4
- package/skills/gsd-path/templates/gap-review.md +2 -1
- 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 +1 -1
- package/skills/gsd-path/templates/task.md +1 -0
- package/skills/gsd-path/templates/wave-review.md +16 -4
- package/skills/gsd-path-build/SKILL.md +7 -1
- package/skills/gsd-path-build/references/build-native.md +63 -15
- package/skills/gsd-path-build/references/dispatch.md +13 -0
- package/skills/gsd-path-build/references/operating-rules.md +214 -0
- package/skills/gsd-path-build/references/reviewer-final.md +20 -2
- package/skills/gsd-path-build/references/reviewer-wave.md +18 -5
- package/skills/gsd-path-build/references/reviewer.md +3 -1
- package/skills/gsd-path-build/references/spec-probes.md +150 -0
- package/skills/gsd-path-build/scripts/_common.py +619 -18
- package/skills/gsd-path-build/scripts/archive_milestone.py +160 -86
- package/skills/gsd-path-build/scripts/build_recovery.py +100 -32
- package/skills/gsd-path-build/scripts/build_state.py +143 -24
- package/skills/gsd-path-build/scripts/check_handoffs.py +662 -50
- package/skills/gsd-path-build/scripts/check_task_briefs.py +338 -30
- package/skills/gsd-path-build/scripts/detect_project.py +587 -32
- package/skills/gsd-path-build/scripts/discussion_records.py +19 -13
- package/skills/gsd-path-build/scripts/discussion_validate.py +152 -50
- package/skills/gsd-path-build/scripts/dispatch_driver.py +501 -46
- package/skills/gsd-path-build/scripts/integration.py +580 -25
- package/skills/gsd-path-build/scripts/isolation.py +1438 -57
- package/skills/gsd-path-build/scripts/loop_run.py +31 -29
- package/skills/gsd-path-build/scripts/members.py +706 -0
- package/skills/gsd-path-build/scripts/path_config.py +5 -5
- package/skills/gsd-path-build/scripts/pipeline_git.py +124 -34
- package/skills/gsd-path-build/scripts/pipeline_state.py +287 -87
- package/skills/gsd-path-build/scripts/promote_lookahead.py +1 -1
- package/skills/gsd-path-build/scripts/review_panel.py +1 -1
- package/skills/gsd-path-build/scripts/state_checkpoint.py +135 -44
- package/skills/gsd-path-build/scripts/state_promote.py +2 -0
- package/skills/gsd-path-build/scripts/task_context.py +12 -3
- package/skills/gsd-path-build/scripts/token_budget.py +12 -8
- package/skills/gsd-path-build/scripts/workflow_run.py +107 -30
- package/skills/gsd-path-build/scripts/worktree_paths.py +72 -10
- package/skills/gsd-path-build/templates/task.md +1 -0
- package/skills/gsd-path-build/templates/wave-review.md +16 -4
- package/skills/gsd-path-decide/SKILL.md +11 -4
- package/skills/gsd-path-decide/references/dispatch.md +13 -0
- package/skills/gsd-path-decide/references/operating-rules.md +214 -0
- package/skills/gsd-path-decide/scripts/_common.py +619 -18
- package/skills/gsd-path-decide/scripts/archive_milestone.py +160 -86
- package/skills/gsd-path-decide/scripts/build_recovery.py +100 -32
- package/skills/gsd-path-decide/scripts/check_handoffs.py +662 -50
- package/skills/gsd-path-decide/scripts/check_task_briefs.py +338 -30
- package/skills/gsd-path-decide/scripts/detect_project.py +587 -32
- package/skills/gsd-path-decide/scripts/discussion_records.py +19 -13
- package/skills/gsd-path-decide/scripts/discussion_validate.py +152 -50
- package/skills/gsd-path-decide/scripts/integration.py +580 -25
- package/skills/gsd-path-decide/scripts/isolation.py +1438 -57
- package/skills/gsd-path-decide/scripts/loop_run.py +31 -29
- package/skills/gsd-path-decide/scripts/members.py +706 -0
- package/skills/gsd-path-decide/scripts/path_config.py +5 -5
- package/skills/gsd-path-decide/scripts/pipeline_git.py +124 -34
- package/skills/gsd-path-decide/scripts/pipeline_state.py +287 -87
- package/skills/gsd-path-decide/scripts/promote_lookahead.py +1 -1
- package/skills/gsd-path-decide/scripts/review_panel.py +1 -1
- package/skills/gsd-path-decide/scripts/state_checkpoint.py +135 -44
- package/skills/gsd-path-decide/scripts/state_promote.py +2 -0
- package/skills/gsd-path-decide/scripts/worktree_paths.py +72 -10
- package/skills/gsd-path-define/SKILL.md +36 -4
- package/skills/gsd-path-define/references/operating-rules.md +214 -0
- package/skills/gsd-path-define/references/spec-probes.md +150 -0
- package/skills/gsd-path-define/scripts/_common.py +619 -18
- package/skills/gsd-path-define/scripts/archive_milestone.py +160 -86
- package/skills/gsd-path-define/scripts/build_recovery.py +100 -32
- package/skills/gsd-path-define/scripts/check_handoffs.py +662 -50
- package/skills/gsd-path-define/scripts/check_task_briefs.py +338 -30
- package/skills/gsd-path-define/scripts/detect_project.py +587 -32
- package/skills/gsd-path-define/scripts/discussion_records.py +19 -13
- package/skills/gsd-path-define/scripts/discussion_validate.py +152 -50
- package/skills/gsd-path-define/scripts/integration.py +580 -25
- package/skills/gsd-path-define/scripts/isolation.py +1438 -57
- package/skills/gsd-path-define/scripts/loop_run.py +31 -29
- package/skills/gsd-path-define/scripts/members.py +706 -0
- package/skills/gsd-path-define/scripts/path_config.py +5 -5
- package/skills/gsd-path-define/scripts/pipeline_git.py +124 -34
- package/skills/gsd-path-define/scripts/pipeline_state.py +287 -87
- package/skills/gsd-path-define/scripts/promote_lookahead.py +1 -1
- package/skills/gsd-path-define/scripts/review_panel.py +1 -1
- package/skills/gsd-path-define/scripts/state_checkpoint.py +135 -44
- package/skills/gsd-path-define/scripts/state_promote.py +2 -0
- package/skills/gsd-path-define/scripts/worktree_paths.py +72 -10
- package/skills/gsd-path-define/templates/intent.md +30 -0
- package/skills/gsd-path-define/templates/state.md +1 -1
- package/skills/gsd-path-discuss/SKILL.md +2 -1
- package/skills/gsd-path-discuss/references/operating-rules.md +214 -0
- package/skills/gsd-path-discuss/scripts/_common.py +619 -18
- package/skills/gsd-path-discuss/scripts/discussion_records.py +19 -13
- package/skills/gsd-path-discuss/scripts/loop_run.py +31 -29
- package/skills/gsd-path-discuss/scripts/path_config.py +5 -5
- package/skills/gsd-path-discuss/scripts/review_panel.py +1 -1
- package/skills/gsd-path-discuss/scripts/worktree_paths.py +72 -10
- package/skills/gsd-path-docs-audit/SKILL.md +6 -4
- package/skills/gsd-path-docs-audit/references/dispatch.md +13 -0
- package/skills/gsd-path-docs-audit/references/docs-auditor.md +7 -1
- package/skills/gsd-path-docs-audit/references/operating-rules.md +214 -0
- package/skills/gsd-path-docs-audit/scripts/_common.py +619 -18
- package/skills/gsd-path-docs-audit/scripts/archive_milestone.py +160 -86
- package/skills/gsd-path-docs-audit/scripts/build_recovery.py +100 -32
- package/skills/gsd-path-docs-audit/scripts/check_docs_audit.py +91 -7
- package/skills/gsd-path-docs-audit/scripts/check_handoffs.py +662 -50
- package/skills/gsd-path-docs-audit/scripts/check_task_briefs.py +338 -30
- package/skills/gsd-path-docs-audit/scripts/detect_project.py +587 -32
- package/skills/gsd-path-docs-audit/scripts/discussion_records.py +19 -13
- package/skills/gsd-path-docs-audit/scripts/discussion_validate.py +152 -50
- package/skills/gsd-path-docs-audit/scripts/integration.py +580 -25
- package/skills/gsd-path-docs-audit/scripts/isolation.py +1438 -57
- package/skills/gsd-path-docs-audit/scripts/loop_run.py +31 -29
- package/skills/gsd-path-docs-audit/scripts/members.py +706 -0
- package/skills/gsd-path-docs-audit/scripts/path_config.py +5 -5
- package/skills/gsd-path-docs-audit/scripts/pipeline_git.py +124 -34
- package/skills/gsd-path-docs-audit/scripts/pipeline_state.py +287 -87
- package/skills/gsd-path-docs-audit/scripts/promote_lookahead.py +1 -1
- package/skills/gsd-path-docs-audit/scripts/review_panel.py +1 -1
- package/skills/gsd-path-docs-audit/scripts/state_checkpoint.py +135 -44
- package/skills/gsd-path-docs-audit/scripts/state_promote.py +2 -0
- package/skills/gsd-path-docs-audit/scripts/worktree_paths.py +72 -10
- package/skills/gsd-path-docs-audit/templates/docs-audit.md +6 -2
- package/skills/gsd-path-forensics/SKILL.md +2 -1
- package/skills/gsd-path-forensics/references/operating-rules.md +214 -0
- package/skills/gsd-path-forensics/scripts/_common.py +619 -18
- package/skills/gsd-path-forensics/scripts/discussion_records.py +19 -13
- package/skills/gsd-path-forensics/scripts/loop_run.py +31 -29
- package/skills/gsd-path-forensics/scripts/path_config.py +5 -5
- package/skills/gsd-path-forensics/scripts/pipeline_diagnose.py +82 -31
- package/skills/gsd-path-forensics/scripts/pipeline_undo.py +218 -30
- package/skills/gsd-path-forensics/scripts/review_panel.py +1 -1
- package/skills/gsd-path-forensics/scripts/worktree_paths.py +72 -10
- package/skills/gsd-path-inspect/SKILL.md +5 -4
- package/skills/gsd-path-inspect/references/codebase-mapper.md +2 -1
- package/skills/gsd-path-inspect/references/dispatch.md +13 -0
- package/skills/gsd-path-inspect/references/docs-auditor.md +7 -1
- package/skills/gsd-path-inspect/references/operating-rules.md +214 -0
- package/skills/gsd-path-inspect/scripts/_common.py +619 -18
- package/skills/gsd-path-inspect/scripts/archive_milestone.py +160 -86
- package/skills/gsd-path-inspect/scripts/build_recovery.py +100 -32
- package/skills/gsd-path-inspect/scripts/check_docs_audit.py +91 -7
- package/skills/gsd-path-inspect/scripts/check_handoffs.py +662 -50
- package/skills/gsd-path-inspect/scripts/check_task_briefs.py +338 -30
- package/skills/gsd-path-inspect/scripts/detect_project.py +587 -32
- package/skills/gsd-path-inspect/scripts/discussion_records.py +19 -13
- package/skills/gsd-path-inspect/scripts/discussion_validate.py +152 -50
- package/skills/gsd-path-inspect/scripts/integration.py +580 -25
- package/skills/gsd-path-inspect/scripts/isolation.py +1438 -57
- package/skills/gsd-path-inspect/scripts/loop_run.py +31 -29
- package/skills/gsd-path-inspect/scripts/members.py +706 -0
- package/skills/gsd-path-inspect/scripts/path_config.py +5 -5
- package/skills/gsd-path-inspect/scripts/pipeline_git.py +124 -34
- package/skills/gsd-path-inspect/scripts/pipeline_state.py +287 -87
- package/skills/gsd-path-inspect/scripts/promote_lookahead.py +1 -1
- package/skills/gsd-path-inspect/scripts/review_panel.py +1 -1
- package/skills/gsd-path-inspect/scripts/state_checkpoint.py +135 -44
- package/skills/gsd-path-inspect/scripts/state_promote.py +2 -0
- package/skills/gsd-path-inspect/scripts/workflow_run.py +107 -30
- package/skills/gsd-path-inspect/scripts/worktree_paths.py +72 -10
- package/skills/gsd-path-inspect/templates/codebase.md +1 -1
- package/skills/gsd-path-inspect/templates/docs-audit.md +6 -2
- package/skills/gsd-path-inspect/templates/state.md +1 -1
- package/skills/gsd-path-loop/SKILL.md +2 -1
- package/skills/gsd-path-loop/references/operating-rules.md +214 -0
- package/skills/gsd-path-loop/scripts/_common.py +619 -18
- package/skills/gsd-path-loop/scripts/discussion_records.py +19 -13
- package/skills/gsd-path-loop/scripts/loop_run.py +31 -29
- package/skills/gsd-path-loop/scripts/path_config.py +5 -5
- package/skills/gsd-path-loop/scripts/review_panel.py +1 -1
- package/skills/gsd-path-loop/scripts/worktree_paths.py +72 -10
- package/skills/gsd-path-migrate/SKILL.md +2 -1
- package/skills/gsd-path-migrate/references/operating-rules.md +214 -0
- package/skills/gsd-path-migrate/scripts/_common.py +619 -18
- package/skills/gsd-path-migrate/scripts/core_hook_gate.py +10 -1
- package/skills/gsd-path-migrate/scripts/core_hook_settings.py +11 -4
- package/skills/gsd-path-migrate/scripts/discussion_records.py +19 -13
- package/skills/gsd-path-migrate/scripts/loop_run.py +31 -29
- package/skills/gsd-path-migrate/scripts/migrate_core.py +2 -2
- package/skills/gsd-path-migrate/scripts/path_config.py +5 -5
- package/skills/gsd-path-migrate/scripts/review_panel.py +1 -1
- package/skills/gsd-path-plan/SKILL.md +18 -4
- package/skills/gsd-path-plan/references/dispatch.md +13 -0
- package/skills/gsd-path-plan/references/operating-rules.md +214 -0
- package/skills/gsd-path-plan/references/planner.md +22 -4
- package/skills/gsd-path-plan/references/spec-probes.md +150 -0
- package/skills/gsd-path-plan/scripts/_common.py +619 -18
- package/skills/gsd-path-plan/scripts/archive_milestone.py +160 -86
- package/skills/gsd-path-plan/scripts/build_recovery.py +100 -32
- package/skills/gsd-path-plan/scripts/check_handoffs.py +662 -50
- package/skills/gsd-path-plan/scripts/check_task_briefs.py +338 -30
- package/skills/gsd-path-plan/scripts/detect_project.py +587 -32
- package/skills/gsd-path-plan/scripts/discussion_records.py +19 -13
- package/skills/gsd-path-plan/scripts/discussion_validate.py +152 -50
- package/skills/gsd-path-plan/scripts/integration.py +580 -25
- package/skills/gsd-path-plan/scripts/isolation.py +1438 -57
- package/skills/gsd-path-plan/scripts/loop_run.py +31 -29
- package/skills/gsd-path-plan/scripts/members.py +706 -0
- package/skills/gsd-path-plan/scripts/path_config.py +5 -5
- package/skills/gsd-path-plan/scripts/pipeline_git.py +124 -34
- package/skills/gsd-path-plan/scripts/pipeline_state.py +287 -87
- package/skills/gsd-path-plan/scripts/promote_lookahead.py +1 -1
- package/skills/gsd-path-plan/scripts/review_panel.py +1 -1
- package/skills/gsd-path-plan/scripts/state_checkpoint.py +135 -44
- package/skills/gsd-path-plan/scripts/state_promote.py +2 -0
- package/skills/gsd-path-plan/scripts/workflow_run.py +107 -30
- package/skills/gsd-path-plan/scripts/worktree_paths.py +72 -10
- 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 +13 -1
- package/skills/gsd-path-research/references/dispatch.md +13 -0
- package/skills/gsd-path-research/references/operating-rules.md +214 -0
- package/skills/gsd-path-research/scripts/_common.py +619 -18
- package/skills/gsd-path-research/scripts/archive_milestone.py +160 -86
- package/skills/gsd-path-research/scripts/build_recovery.py +100 -32
- package/skills/gsd-path-research/scripts/check_handoffs.py +662 -50
- package/skills/gsd-path-research/scripts/check_task_briefs.py +338 -30
- package/skills/gsd-path-research/scripts/detect_project.py +587 -32
- package/skills/gsd-path-research/scripts/discussion_records.py +19 -13
- package/skills/gsd-path-research/scripts/discussion_validate.py +152 -50
- package/skills/gsd-path-research/scripts/integration.py +580 -25
- package/skills/gsd-path-research/scripts/isolation.py +1438 -57
- package/skills/gsd-path-research/scripts/loop_run.py +31 -29
- package/skills/gsd-path-research/scripts/members.py +706 -0
- package/skills/gsd-path-research/scripts/path_config.py +5 -5
- package/skills/gsd-path-research/scripts/pipeline_git.py +124 -34
- package/skills/gsd-path-research/scripts/pipeline_state.py +287 -87
- package/skills/gsd-path-research/scripts/promote_lookahead.py +1 -1
- package/skills/gsd-path-research/scripts/review_panel.py +1 -1
- package/skills/gsd-path-research/scripts/state_checkpoint.py +135 -44
- package/skills/gsd-path-research/scripts/state_promote.py +2 -0
- package/skills/gsd-path-research/scripts/worktree_paths.py +72 -10
- package/skills/gsd-path-research/templates/research-handoff.md +14 -3
- package/skills/gsd-path-roadmap/SKILL.md +2 -1
- package/skills/gsd-path-roadmap/references/dispatch.md +13 -0
- package/skills/gsd-path-roadmap/references/operating-rules.md +214 -0
- package/skills/gsd-path-roadmap/scripts/_common.py +619 -18
- package/skills/gsd-path-roadmap/scripts/archive_milestone.py +160 -86
- package/skills/gsd-path-roadmap/scripts/build_recovery.py +100 -32
- package/skills/gsd-path-roadmap/scripts/check_handoffs.py +662 -50
- package/skills/gsd-path-roadmap/scripts/check_task_briefs.py +338 -30
- package/skills/gsd-path-roadmap/scripts/detect_project.py +587 -32
- package/skills/gsd-path-roadmap/scripts/discussion_records.py +19 -13
- package/skills/gsd-path-roadmap/scripts/discussion_validate.py +152 -50
- package/skills/gsd-path-roadmap/scripts/integration.py +580 -25
- package/skills/gsd-path-roadmap/scripts/isolation.py +1438 -57
- package/skills/gsd-path-roadmap/scripts/loop_run.py +31 -29
- package/skills/gsd-path-roadmap/scripts/members.py +706 -0
- package/skills/gsd-path-roadmap/scripts/path_config.py +5 -5
- package/skills/gsd-path-roadmap/scripts/pipeline_git.py +124 -34
- package/skills/gsd-path-roadmap/scripts/pipeline_state.py +287 -87
- package/skills/gsd-path-roadmap/scripts/promote_lookahead.py +1 -1
- package/skills/gsd-path-roadmap/scripts/review_panel.py +1 -1
- package/skills/gsd-path-roadmap/scripts/state_checkpoint.py +135 -44
- package/skills/gsd-path-roadmap/scripts/state_promote.py +2 -0
- package/skills/gsd-path-roadmap/scripts/worktree_paths.py +72 -10
- package/skills/gsd-path-ship/SKILL.md +33 -11
- package/skills/gsd-path-ship/references/dispatch.md +13 -0
- package/skills/gsd-path-ship/references/operating-rules.md +214 -0
- package/skills/gsd-path-ship/references/reviewer-final.md +20 -2
- package/skills/gsd-path-ship/references/reviewer-wave.md +18 -5
- package/skills/gsd-path-ship/references/reviewer.md +3 -1
- package/skills/gsd-path-ship/references/spec-probes.md +150 -0
- package/skills/gsd-path-ship/scripts/_common.py +619 -18
- package/skills/gsd-path-ship/scripts/archive_milestone.py +160 -86
- package/skills/gsd-path-ship/scripts/build_recovery.py +100 -32
- package/skills/gsd-path-ship/scripts/build_state.py +143 -24
- package/skills/gsd-path-ship/scripts/check_handoffs.py +662 -50
- package/skills/gsd-path-ship/scripts/check_task_briefs.py +338 -30
- package/skills/gsd-path-ship/scripts/detect_project.py +587 -32
- package/skills/gsd-path-ship/scripts/discussion_records.py +19 -13
- package/skills/gsd-path-ship/scripts/discussion_validate.py +152 -50
- package/skills/gsd-path-ship/scripts/integration.py +580 -25
- package/skills/gsd-path-ship/scripts/isolation.py +1438 -57
- package/skills/gsd-path-ship/scripts/lean_verification.py +99 -19
- package/skills/gsd-path-ship/scripts/loop_run.py +31 -29
- package/skills/gsd-path-ship/scripts/members.py +706 -0
- package/skills/gsd-path-ship/scripts/path_config.py +5 -5
- package/skills/gsd-path-ship/scripts/pipeline_git.py +124 -34
- package/skills/gsd-path-ship/scripts/pipeline_state.py +287 -87
- package/skills/gsd-path-ship/scripts/promote_lookahead.py +1 -1
- package/skills/gsd-path-ship/scripts/review_panel.py +1 -1
- package/skills/gsd-path-ship/scripts/state_checkpoint.py +135 -44
- package/skills/gsd-path-ship/scripts/state_promote.py +2 -0
- package/skills/gsd-path-ship/scripts/workflow_run.py +107 -30
- package/skills/gsd-path-ship/scripts/worktree_paths.py +72 -10
- package/skills/gsd-path-ship/templates/final-review.md +16 -4
- package/skills/gsd-path-ship/templates/gap-review.md +2 -1
- package/skills/gsd-path-ship/templates/patch-findings.md +3 -3
- package/skills/gsd-path-ship/templates/wave-review.md +16 -4
- package/skills/gsd-path-undo/SKILL.md +2 -1
- package/skills/gsd-path-undo/references/operating-rules.md +214 -0
- package/skills/gsd-path-undo/scripts/_common.py +619 -18
- package/skills/gsd-path-undo/scripts/discussion_records.py +19 -13
- package/skills/gsd-path-undo/scripts/loop_run.py +31 -29
- package/skills/gsd-path-undo/scripts/path_config.py +5 -5
- package/skills/gsd-path-undo/scripts/pipeline_undo.py +218 -30
- package/skills/gsd-path-undo/scripts/review_panel.py +1 -1
- package/skills/gsd-path-undo/scripts/worktree_paths.py +72 -10
- package/skills/path/BUILD.md +7 -1
- package/skills/path/DECIDE.md +11 -4
- package/skills/path/DEFINE.md +36 -4
- package/skills/path/DOCS-AUDIT.md +6 -4
- package/skills/path/INSPECT.md +5 -4
- package/skills/path/PLAN.md +18 -4
- package/skills/path/RESEARCH.md +13 -1
- package/skills/path/ROADMAP.md +2 -1
- package/skills/path/SHIP.md +33 -11
- package/skills/path/SKILL.md +45 -1
- package/skills/path/references/build-native.md +63 -15
- package/skills/path/references/codebase-mapper.md +2 -1
- package/skills/path/references/dispatch.md +13 -0
- package/skills/path/references/docs-auditor.md +7 -1
- package/skills/path/references/operating-rules.md +214 -0
- package/skills/path/references/planner.md +22 -4
- package/skills/path/references/reviewer-final.md +20 -2
- package/skills/path/references/reviewer-wave.md +18 -5
- package/skills/path/references/reviewer.md +3 -1
- package/skills/path/references/spec-probes.md +150 -0
- package/skills/path/scripts/_common.py +619 -18
- package/skills/path/scripts/archive_milestone.py +160 -86
- package/skills/path/scripts/bootstrap_repository.py +8 -5
- package/skills/path/scripts/build_recovery.py +100 -32
- package/skills/path/scripts/build_state.py +143 -24
- package/skills/path/scripts/check_docs_audit.py +91 -7
- package/skills/path/scripts/check_handoffs.py +662 -50
- package/skills/path/scripts/check_task_briefs.py +338 -30
- package/skills/path/scripts/check_update.py +2 -2
- package/skills/path/scripts/detect_project.py +587 -32
- package/skills/path/scripts/discussion_records.py +19 -13
- package/skills/path/scripts/discussion_validate.py +152 -50
- package/skills/path/scripts/dispatch_driver.py +501 -46
- package/skills/path/scripts/git_guard.py +118 -31
- package/skills/path/scripts/integration.py +580 -25
- package/skills/path/scripts/isolation.py +1438 -57
- package/skills/path/scripts/lean_verification.py +99 -19
- package/skills/path/scripts/loop_run.py +31 -29
- package/skills/path/scripts/members.py +706 -0
- package/skills/path/scripts/path_config.py +5 -5
- package/skills/path/scripts/pipeline_git.py +124 -34
- package/skills/path/scripts/pipeline_state.py +287 -87
- package/skills/path/scripts/promote_lookahead.py +1 -1
- package/skills/path/scripts/review_panel.py +1 -1
- package/skills/path/scripts/state_checkpoint.py +135 -44
- package/skills/path/scripts/state_promote.py +2 -0
- package/skills/path/scripts/status_runtime.py +58 -10
- package/skills/path/scripts/task_context.py +12 -3
- package/skills/path/scripts/token_budget.py +12 -8
- package/skills/path/scripts/workflow_run.py +107 -30
- package/skills/path/scripts/worktree_paths.py +72 -10
- package/skills/path/templates/codebase.md +1 -1
- package/skills/path/templates/docs-audit.md +6 -2
- package/skills/path/templates/final-review.md +16 -4
- package/skills/path/templates/gap-review.md +2 -1
- 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 +1 -1
- package/skills/path/templates/task.md +1 -0
- package/skills/path/templates/wave-review.md +16 -4
- 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
package/scripts/migrate_core.py
CHANGED
|
@@ -119,8 +119,8 @@ def prepare(repo, output, files, manifest):
|
|
|
119
119
|
target.parent.mkdir(parents=True, exist_ok=True)
|
|
120
120
|
target.write_bytes(content)
|
|
121
121
|
manifest = dict(manifest, status="prepared", output=str(output))
|
|
122
|
-
(output / "manifest.json").
|
|
123
|
-
json.dumps(manifest, indent=2) + "\n"
|
|
122
|
+
(output / "manifest.json").write_bytes(
|
|
123
|
+
(json.dumps(manifest, indent=2) + "\n").encode("utf-8")
|
|
124
124
|
)
|
|
125
125
|
except BaseException:
|
|
126
126
|
shutil.rmtree(output)
|
package/scripts/path_config.py
CHANGED
|
@@ -13,7 +13,7 @@ sys.dont_write_bytecode = True
|
|
|
13
13
|
ROLES = ('coder', 'reviewer', 'review_panel', 'skeptic', 'inspect_codebase',
|
|
14
14
|
'inspect_docs', 'docs_audit', 'research', 'decide', 'roadmap', 'plan', 'plan_patch')
|
|
15
15
|
HOSTS = ('codex', 'claude', 'grok', 'opencode', 'copilot', 'qwen', 'antigravity',
|
|
16
|
-
'cursor', 'zed', 'kiro', 'kimi')
|
|
16
|
+
'cursor', 'zed', 'kiro', 'kimi', 'muse')
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
def sibling(name):
|
|
@@ -73,8 +73,8 @@ def validate_value(key, value):
|
|
|
73
73
|
if not isinstance(value, str) or not value or value != value.strip():
|
|
74
74
|
raise ValueError(f'{key} requires a nonempty string')
|
|
75
75
|
if key == 'integration':
|
|
76
|
-
if value not in ('direct', 'pull-request'):
|
|
77
|
-
raise ValueError('integration must be direct or
|
|
76
|
+
if value not in ('direct', 'pull-request', 'external-landing'):
|
|
77
|
+
raise ValueError('integration must be direct, pull-request, or external-landing')
|
|
78
78
|
elif key == 'review_panel':
|
|
79
79
|
if any(char.isspace() for char in value):
|
|
80
80
|
raise ValueError('use off, detected, or comma-separated families without spaces')
|
|
@@ -174,13 +174,13 @@ def set_value(repo, scope, key, value, reset=False):
|
|
|
174
174
|
if scope == 'project':
|
|
175
175
|
state, _, _ = sibling('pipeline_state').load_state(repo)
|
|
176
176
|
branch = subprocess.run(['git', '-C', str(repo), 'branch', '--show-current'],
|
|
177
|
-
capture_output=True,
|
|
177
|
+
capture_output=True, encoding="utf-8", errors="replace")
|
|
178
178
|
if branch.returncode or not state.branch or branch.stdout.strip() != state.branch:
|
|
179
179
|
raise ValueError('Run the router to bind the project branch before editing settings.')
|
|
180
180
|
head = subprocess.run(['git', '-C', str(repo), 'rev-parse', '--verify', 'HEAD'], capture_output=True)
|
|
181
181
|
if head.returncode == 0:
|
|
182
182
|
closed = subprocess.run([sys.executable, '-B', str(Path(__file__).with_name('git_guard.py')),
|
|
183
|
-
'closed-milestone'], cwd=repo, capture_output=True,
|
|
183
|
+
'closed-milestone'], cwd=repo, capture_output=True, encoding="utf-8", errors="replace")
|
|
184
184
|
if closed.returncode:
|
|
185
185
|
raise ValueError(closed.stderr.strip() or 'Cannot verify the milestone branch is open.')
|
|
186
186
|
if scope == 'project' and key == 'integration':
|
|
@@ -10,6 +10,7 @@ from __future__ import annotations
|
|
|
10
10
|
|
|
11
11
|
import argparse
|
|
12
12
|
import json
|
|
13
|
+
import os
|
|
13
14
|
import shlex
|
|
14
15
|
import sys
|
|
15
16
|
|
|
@@ -20,14 +21,14 @@ from typing import Callable, Optional, Sequence
|
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
def _load_diagnose_modules():
|
|
23
|
-
|
|
24
|
-
import archive_milestone
|
|
25
|
-
import detect_project
|
|
26
|
-
import discussion_records
|
|
27
|
-
import integration
|
|
28
|
-
import isolation
|
|
29
|
-
import pipeline_git
|
|
30
|
-
import pipeline_state
|
|
24
|
+
if __package__:
|
|
25
|
+
from . import archive_milestone
|
|
26
|
+
from . import detect_project
|
|
27
|
+
from . import discussion_records
|
|
28
|
+
from . import integration
|
|
29
|
+
from . import isolation
|
|
30
|
+
from . import pipeline_git
|
|
31
|
+
from . import pipeline_state
|
|
31
32
|
return (
|
|
32
33
|
archive_milestone,
|
|
33
34
|
detect_project,
|
|
@@ -37,17 +38,35 @@ def _load_diagnose_modules():
|
|
|
37
38
|
pipeline_git,
|
|
38
39
|
pipeline_state,
|
|
39
40
|
)
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
41
|
+
else:
|
|
42
|
+
try:
|
|
43
|
+
import archive_milestone
|
|
44
|
+
import detect_project
|
|
45
|
+
import discussion_records
|
|
46
|
+
import integration
|
|
47
|
+
import isolation
|
|
48
|
+
import pipeline_git
|
|
49
|
+
import pipeline_state
|
|
50
|
+
return (
|
|
51
|
+
archive_milestone,
|
|
52
|
+
detect_project,
|
|
53
|
+
discussion_records,
|
|
54
|
+
integration,
|
|
55
|
+
isolation,
|
|
56
|
+
pipeline_git,
|
|
57
|
+
pipeline_state,
|
|
58
|
+
)
|
|
59
|
+
except ModuleNotFoundError as error:
|
|
60
|
+
if error.name not in {
|
|
61
|
+
"archive_milestone",
|
|
62
|
+
"detect_project",
|
|
63
|
+
"discussion_records",
|
|
64
|
+
"integration",
|
|
65
|
+
"isolation",
|
|
66
|
+
"pipeline_git",
|
|
67
|
+
"pipeline_state",
|
|
68
|
+
}:
|
|
69
|
+
raise
|
|
51
70
|
try:
|
|
52
71
|
from scripts import (
|
|
53
72
|
archive_milestone,
|
|
@@ -116,21 +135,25 @@ _worktree_report = isolation._worktree_report
|
|
|
116
135
|
PipelineStateError = pipeline_state.PipelineStateError
|
|
117
136
|
status_state = pipeline_state.status_state
|
|
118
137
|
validate_state = pipeline_state.validate_state
|
|
138
|
+
_run_git = pipeline_state._run_git
|
|
119
139
|
|
|
120
|
-
|
|
121
|
-
import pipeline_undo
|
|
122
|
-
|
|
123
|
-
if error.name != "pipeline_undo":
|
|
124
|
-
raise
|
|
140
|
+
if __package__:
|
|
141
|
+
from . import pipeline_undo
|
|
142
|
+
else:
|
|
125
143
|
try:
|
|
126
|
-
|
|
144
|
+
import pipeline_undo
|
|
127
145
|
except ModuleNotFoundError as error:
|
|
128
|
-
if error.name
|
|
146
|
+
if error.name != "pipeline_undo":
|
|
129
147
|
raise
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
148
|
+
try:
|
|
149
|
+
from scripts import pipeline_undo
|
|
150
|
+
except ModuleNotFoundError as error:
|
|
151
|
+
if error.name not in {"scripts", "scripts.pipeline_undo"}:
|
|
152
|
+
raise
|
|
153
|
+
shared = Path(__file__).resolve().parents[2] / "gsd-path" / "scripts"
|
|
154
|
+
if str(shared) not in sys.path:
|
|
155
|
+
sys.path.insert(0, str(shared))
|
|
156
|
+
import pipeline_undo
|
|
134
157
|
|
|
135
158
|
UndoError = pipeline_undo.UndoError
|
|
136
159
|
undo_preview = pipeline_undo.preview
|
|
@@ -194,7 +217,12 @@ def _state_template() -> Path:
|
|
|
194
217
|
|
|
195
218
|
def _command(module: object, *arguments: object) -> str:
|
|
196
219
|
script = Path(str(getattr(module, "__file__"))).resolve()
|
|
197
|
-
|
|
220
|
+
def text(value: object) -> str:
|
|
221
|
+
# Agents paste this into Git Bash on Windows, where unquoted
|
|
222
|
+
# backslashes are escapes; forward slashes need no quoting.
|
|
223
|
+
return value.as_posix() if isinstance(value, Path) and os.name == "nt" else str(value)
|
|
224
|
+
|
|
225
|
+
return shlex.join([text(Path(sys.executable)), text(script), *map(text, arguments)])
|
|
198
226
|
|
|
199
227
|
|
|
200
228
|
def _route_retry(
|
|
@@ -391,6 +419,29 @@ def diagnose(repo: Path) -> dict[str, object]:
|
|
|
391
419
|
for key, path in (status.get("journals") or {}).items()
|
|
392
420
|
if path
|
|
393
421
|
}
|
|
422
|
+
pending_members = [row["name"] for row in status.get("members") or [] if row["close"] == "pending"]
|
|
423
|
+
if pending_members:
|
|
424
|
+
findings.append(
|
|
425
|
+
_finding(
|
|
426
|
+
"member-close",
|
|
427
|
+
"stuck",
|
|
428
|
+
"member close is pending for: " + ", ".join(pending_members),
|
|
429
|
+
_command(archive_milestone, "close-members", "--repo", resolved),
|
|
430
|
+
)
|
|
431
|
+
)
|
|
432
|
+
common = _run_git(resolved, "rev-parse", "--path-format=absolute", "--git-common-dir", check=False)
|
|
433
|
+
landings = sorted(
|
|
434
|
+
(Path(common.stdout.strip()) / "gsd-path" / "member-landings").glob("*.json")
|
|
435
|
+
) if common.returncode == 0 else []
|
|
436
|
+
if landings:
|
|
437
|
+
findings.append(
|
|
438
|
+
_finding(
|
|
439
|
+
"member-landing",
|
|
440
|
+
"stuck",
|
|
441
|
+
"member landing journal is pending: " + ", ".join(path.stem for path in landings),
|
|
442
|
+
"resume build; the dispatch driver finishes pending member landings before new work",
|
|
443
|
+
)
|
|
444
|
+
)
|
|
394
445
|
undo_probe = by_name["undo-preview"]
|
|
395
446
|
undo_result = undo_probe["result"] if undo_probe["ok"] else None
|
|
396
447
|
route_retry = _route_retry(resolved, route, undo_result)
|
package/scripts/pipeline_git.py
CHANGED
|
@@ -23,10 +23,13 @@ sys.dont_write_bytecode = True
|
|
|
23
23
|
from pathlib import Path
|
|
24
24
|
from typing import Optional, Sequence
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
import _common
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
if __package__:
|
|
27
|
+
from . import _common
|
|
28
|
+
else:
|
|
29
|
+
try:
|
|
30
|
+
import _common
|
|
31
|
+
except ImportError: # pragma: no cover - package import used by tests
|
|
32
|
+
from scripts import _common
|
|
30
33
|
|
|
31
34
|
|
|
32
35
|
ARCHIVE_NAME_RE = re.compile(r"^(\d{3,})-([a-z0-9][a-z0-9-]*)$")
|
|
@@ -123,8 +126,47 @@ def is_integrate_subject(subject: str, archive_name: str, default_branch: str) -
|
|
|
123
126
|
}
|
|
124
127
|
|
|
125
128
|
|
|
126
|
-
|
|
127
|
-
|
|
129
|
+
MEMBER_SHIP_ROW = re.compile(
|
|
130
|
+
r"(?m)^Member-Reviewed-HEAD: (?P<name>[^@\s]+)@(?P<reviewed_head>[0-9a-f]{40})\n"
|
|
131
|
+
r"Member: (?P=name) (?P<merge>[0-9a-f]{40}) (?P<tag>\S+)$"
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def ship_member_rows(body: str) -> list:
|
|
136
|
+
"""Closed-member rows named by a ship body; callers compare the rebuilt body exactly."""
|
|
137
|
+
return [match.groupdict() for match in MEMBER_SHIP_ROW.finditer(body)]
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def ship_commit_body(archive_path: str, reviewed_head: str, members: Sequence[dict] = ()) -> str:
|
|
141
|
+
"""The ship body; a multi-repo milestone adds each closed member in lock order."""
|
|
142
|
+
return f"Archive: {archive_path}\nReviewed-HEAD: {reviewed_head}\n" + "".join(
|
|
143
|
+
f"Member-Reviewed-HEAD: {row['name']}@{row['reviewed_head']}\n"
|
|
144
|
+
f"Member: {row['name']} {row['merge']} {row['tag']}\n"
|
|
145
|
+
for row in members
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
_TRAILER_LINE = re.compile(r"^[A-Za-z-]+:\s")
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def ship_body_matches(body: str, expected_body: str) -> bool:
|
|
153
|
+
"""True when body equals the contract or adds only optional git trailers after it."""
|
|
154
|
+
normalized = body.rstrip("\n")
|
|
155
|
+
expected = expected_body.rstrip("\n")
|
|
156
|
+
if normalized == expected:
|
|
157
|
+
return True
|
|
158
|
+
prefix = expected + "\n"
|
|
159
|
+
if not normalized.startswith(prefix):
|
|
160
|
+
return False
|
|
161
|
+
remainder = normalized[len(prefix):]
|
|
162
|
+
if not remainder:
|
|
163
|
+
return True
|
|
164
|
+
for line in remainder.splitlines():
|
|
165
|
+
if not line.strip():
|
|
166
|
+
return False
|
|
167
|
+
if not _TRAILER_LINE.match(line):
|
|
168
|
+
return False
|
|
169
|
+
return True
|
|
128
170
|
|
|
129
171
|
|
|
130
172
|
def integrate_commit_body(
|
|
@@ -200,7 +242,7 @@ def _run_git(
|
|
|
200
242
|
result = subprocess.run(
|
|
201
243
|
["git", "-C", str(repo), *args],
|
|
202
244
|
capture_output=True,
|
|
203
|
-
|
|
245
|
+
encoding="utf-8", errors="replace",
|
|
204
246
|
)
|
|
205
247
|
if check and result.returncode != 0:
|
|
206
248
|
detail = result.stderr.strip() or result.stdout.strip()
|
|
@@ -251,22 +293,50 @@ def _symbolic_branch(repo: Path) -> str:
|
|
|
251
293
|
return result.stdout.strip()
|
|
252
294
|
|
|
253
295
|
|
|
254
|
-
def
|
|
255
|
-
"""Return
|
|
256
|
-
|
|
296
|
+
def worktree_list_porcelain(repo: Path) -> tuple[str, bool]:
|
|
297
|
+
"""Return worktree list output and whether it is NUL-separated."""
|
|
298
|
+
result = _run_git(repo, "worktree", "list", "--porcelain", "-z", check=False)
|
|
299
|
+
if result.returncode == 0:
|
|
300
|
+
return result.stdout, True
|
|
301
|
+
result = _run_git(repo, "worktree", "list", "--porcelain", check=False)
|
|
302
|
+
if result.returncode != 0:
|
|
303
|
+
message = (result.stderr or result.stdout).strip() or "could not list worktrees"
|
|
304
|
+
raise PipelineGitError(message)
|
|
305
|
+
return result.stdout, False
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
def branch_worktrees_from_porcelain(output: str, *, nul_separated: bool) -> dict[str, Path]:
|
|
257
309
|
worktrees: dict[str, Path] = {}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
310
|
+
if nul_separated:
|
|
311
|
+
current_path: Optional[Path] = None
|
|
312
|
+
for field in output.split("\0"):
|
|
313
|
+
if not field:
|
|
314
|
+
continue
|
|
315
|
+
if field.startswith("worktree "):
|
|
316
|
+
current_path = Path(field.removeprefix("worktree ")).resolve()
|
|
317
|
+
elif field.startswith("branch ") and current_path is not None:
|
|
318
|
+
ref = field.removeprefix("branch ")
|
|
319
|
+
prefix = "refs/heads/"
|
|
320
|
+
if ref.startswith(prefix):
|
|
321
|
+
worktrees[ref.removeprefix(prefix)] = current_path
|
|
322
|
+
return worktrees
|
|
323
|
+
for block in output.strip().split("\n\n"):
|
|
324
|
+
fields = block.splitlines()
|
|
325
|
+
if not fields or not fields[0].startswith("worktree "):
|
|
326
|
+
continue
|
|
327
|
+
current_path = Path(fields[0].removeprefix("worktree ")).resolve()
|
|
328
|
+
for line in fields[1:]:
|
|
329
|
+
if line.startswith("branch refs/heads/"):
|
|
330
|
+
worktrees[line.removeprefix("branch refs/heads/")] = current_path
|
|
267
331
|
return worktrees
|
|
268
332
|
|
|
269
333
|
|
|
334
|
+
def _branch_worktrees(repo: Path) -> dict[str, Path]:
|
|
335
|
+
"""Return every checked-out local branch from Git's worktree registry."""
|
|
336
|
+
output, nul_separated = worktree_list_porcelain(repo)
|
|
337
|
+
return branch_worktrees_from_porcelain(output, nul_separated=nul_separated)
|
|
338
|
+
|
|
339
|
+
|
|
270
340
|
def _remote_ref_sha(repo: Path, ref: str) -> Optional[str]:
|
|
271
341
|
if not _origin_remote_exists(repo):
|
|
272
342
|
raise PipelineGitError("origin remote is not configured")
|
|
@@ -319,7 +389,7 @@ def _validated_shipped_state(repo: Path) -> dict[str, object]:
|
|
|
319
389
|
str(repo),
|
|
320
390
|
],
|
|
321
391
|
capture_output=True,
|
|
322
|
-
|
|
392
|
+
encoding="utf-8", errors="replace",
|
|
323
393
|
)
|
|
324
394
|
if result.returncode != 0:
|
|
325
395
|
detail = result.stderr.strip() or result.stdout.strip()
|
|
@@ -446,19 +516,16 @@ def _write_bind_next_journal(path: Path, value: dict[str, object]) -> None:
|
|
|
446
516
|
raise PipelineGitError(f"bind-next journal temporary path exists: {temporary}")
|
|
447
517
|
descriptor: Optional[int] = None
|
|
448
518
|
try:
|
|
449
|
-
descriptor = os.open(
|
|
450
|
-
|
|
519
|
+
descriptor = os.open(
|
|
520
|
+
temporary, os.O_WRONLY | os.O_CREAT | os.O_EXCL | _common.O_BINARY, 0o600
|
|
521
|
+
)
|
|
522
|
+
with os.fdopen(descriptor, "wb") as handle:
|
|
451
523
|
descriptor = None
|
|
452
|
-
json.
|
|
453
|
-
handle.write("\n")
|
|
524
|
+
handle.write((json.dumps(value, indent=2, sort_keys=True) + "\n").encode("utf-8"))
|
|
454
525
|
handle.flush()
|
|
455
526
|
os.fsync(handle.fileno())
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
try:
|
|
459
|
-
os.fsync(directory)
|
|
460
|
-
finally:
|
|
461
|
-
os.close(directory)
|
|
527
|
+
_common.replace(temporary, path)
|
|
528
|
+
_common.fsync_directory(path.parent)
|
|
462
529
|
finally:
|
|
463
530
|
if descriptor is not None:
|
|
464
531
|
os.close(descriptor)
|
|
@@ -473,10 +540,13 @@ def _initial_binding_snapshot(repo: Path) -> Optional[tuple]:
|
|
|
473
540
|
return None
|
|
474
541
|
if dirty != "?? .project/STATE.md\0":
|
|
475
542
|
raise PipelineGitError("primary worktree is not clean")
|
|
476
|
-
|
|
477
|
-
import pipeline_state
|
|
478
|
-
|
|
479
|
-
|
|
543
|
+
if __package__:
|
|
544
|
+
from . import pipeline_state
|
|
545
|
+
else:
|
|
546
|
+
try:
|
|
547
|
+
import pipeline_state
|
|
548
|
+
except ImportError: # pragma: no cover - package import used by tests
|
|
549
|
+
from scripts import pipeline_state
|
|
480
550
|
|
|
481
551
|
project = repo / ".project"
|
|
482
552
|
path = project / "STATE.md"
|
|
@@ -635,6 +705,25 @@ def retire_previous_branch(
|
|
|
635
705
|
_run_git(repo, "branch", "-d", previous_branch)
|
|
636
706
|
|
|
637
707
|
|
|
708
|
+
def _retire_members(repo: Path, ship_sha: str) -> None:
|
|
709
|
+
"""Retire each member the ship commit names; each step is idempotent for a resumed bind-next."""
|
|
710
|
+
message = _run_git(repo, "show", "-s", "--format=%B", ship_sha).stdout
|
|
711
|
+
rows = ship_member_rows(message)
|
|
712
|
+
if not rows:
|
|
713
|
+
return
|
|
714
|
+
if __package__:
|
|
715
|
+
from . import integration
|
|
716
|
+
else:
|
|
717
|
+
import integration
|
|
718
|
+
archive = re.search(r"(?m)^Archive: (\S+)$", message)
|
|
719
|
+
try:
|
|
720
|
+
for row in rows:
|
|
721
|
+
integration.retire_member(repo, row["name"], archive.group(1), row["reviewed_head"],
|
|
722
|
+
row["merge"], row["tag"])
|
|
723
|
+
except integration.ArchiveError as error:
|
|
724
|
+
raise PipelineGitError(f"member retirement failed: {error}") from error
|
|
725
|
+
|
|
726
|
+
|
|
638
727
|
def bind_next_milestone_branch(
|
|
639
728
|
repo: Path,
|
|
640
729
|
branch: str,
|
|
@@ -868,6 +957,7 @@ def bind_next_milestone_branch(
|
|
|
868
957
|
allow_remote_absent or journal["stage"] in {"switched", "retired"}
|
|
869
958
|
),
|
|
870
959
|
)
|
|
960
|
+
_retire_members(repo, ship_sha)
|
|
871
961
|
journal["stage"] = "retired"
|
|
872
962
|
_write_bind_next_journal(journal_path, journal)
|
|
873
963
|
return {
|