@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
|
@@ -17,12 +17,15 @@ from datetime import date
|
|
|
17
17
|
from pathlib import Path, PurePosixPath
|
|
18
18
|
from typing import Mapping, Optional, Sequence
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
from isolation import IsolationError, checkpoint as isolation_checkpoint,
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
if __package__:
|
|
21
|
+
from .isolation import IsolationError, checkpoint as isolation_checkpoint, PROJECT_ENTRIES
|
|
22
|
+
else:
|
|
23
|
+
try:
|
|
24
|
+
from isolation import IsolationError, checkpoint as isolation_checkpoint, PROJECT_ENTRIES
|
|
25
|
+
except ModuleNotFoundError as error: # pragma: no cover - package imports used by tests
|
|
26
|
+
if error.name != "isolation":
|
|
27
|
+
raise
|
|
28
|
+
from scripts.isolation import IsolationError, checkpoint as isolation_checkpoint, PROJECT_ENTRIES
|
|
26
29
|
|
|
27
30
|
|
|
28
31
|
if __package__:
|
|
@@ -66,6 +69,11 @@ def _sha256(content: str) -> str:
|
|
|
66
69
|
return hashlib.sha256(content.encode("utf-8")).hexdigest()
|
|
67
70
|
|
|
68
71
|
|
|
72
|
+
def _is_junk_file(path: Path) -> bool:
|
|
73
|
+
# Drift digests skip OS junk by name: Finder rewrites it whatever its ignore status.
|
|
74
|
+
return path.name in pipeline_state._common.OS_JUNK_NAMES and path.is_file() and not path.is_symlink()
|
|
75
|
+
|
|
76
|
+
|
|
69
77
|
def _tree_digest(path: Path, excluded: Sequence[str] = ()) -> str:
|
|
70
78
|
if path.is_symlink() or not path.is_dir():
|
|
71
79
|
raise PipelineStateError(f"promotion path must be a real directory: {path}")
|
|
@@ -74,7 +82,7 @@ def _tree_digest(path: Path, excluded: Sequence[str] = ()) -> str:
|
|
|
74
82
|
if child.is_symlink():
|
|
75
83
|
raise PipelineStateError(f"promotion path contains a symlink: {child}")
|
|
76
84
|
relative = child.relative_to(path).as_posix()
|
|
77
|
-
if PurePosixPath(relative).parts[0] in excluded:
|
|
85
|
+
if PurePosixPath(relative).parts[0] in excluded or _is_junk_file(child):
|
|
78
86
|
continue
|
|
79
87
|
if child.is_dir():
|
|
80
88
|
digest.update(f"d\0{relative}\0".encode())
|
|
@@ -87,15 +95,15 @@ def _tree_digest(path: Path, excluded: Sequence[str] = ()) -> str:
|
|
|
87
95
|
|
|
88
96
|
|
|
89
97
|
def _checkpoint_artifact_digest(project: Path, mutable_paths: set[str]) -> str:
|
|
90
|
-
"""Hash
|
|
98
|
+
"""Hash approval artifacts except helper-owned metadata and OS junk."""
|
|
91
99
|
digest = hashlib.sha256()
|
|
92
100
|
for child in sorted(project.rglob("*")):
|
|
93
101
|
if child.is_symlink():
|
|
94
102
|
raise PipelineStateError(f"checkpoint path contains a symlink: {child}")
|
|
95
103
|
relative = child.relative_to(project).as_posix()
|
|
96
|
-
#
|
|
97
|
-
|
|
98
|
-
|
|
104
|
+
# Finder can rewrite OS junk during approval; it must not cause artifact drift.
|
|
105
|
+
if (relative in mutable_paths or relative.split("/", 1)[0] not in PROJECT_ENTRIES
|
|
106
|
+
or _is_junk_file(child)):
|
|
99
107
|
continue
|
|
100
108
|
if child.is_dir():
|
|
101
109
|
digest.update(f"d\0{relative}\0".encode())
|
|
@@ -333,11 +341,7 @@ def _converge_checkpoint_file(path: Path, before: str, after: str, label: str) -
|
|
|
333
341
|
|
|
334
342
|
def _unlink_checkpoint_journal(path: Path) -> None:
|
|
335
343
|
path.unlink()
|
|
336
|
-
|
|
337
|
-
try:
|
|
338
|
-
os.fsync(descriptor)
|
|
339
|
-
finally:
|
|
340
|
-
os.close(descriptor)
|
|
344
|
+
pipeline_state._common.fsync_directory(path.parent)
|
|
341
345
|
|
|
342
346
|
|
|
343
347
|
def _resume_checkpoint_locked(
|
|
@@ -439,41 +443,85 @@ def _validate_plan_briefs(repo: Path, kind: str, project_dir: str) -> None:
|
|
|
439
443
|
if head.returncode != 0:
|
|
440
444
|
# Pre-Git approval defers base-dependent checks to build.
|
|
441
445
|
return
|
|
446
|
+
if __package__:
|
|
447
|
+
from .check_task_briefs import BriefError, _member_bases, plan_validation_bases, validate_task_briefs
|
|
448
|
+
else:
|
|
449
|
+
try:
|
|
450
|
+
from check_task_briefs import BriefError, _member_bases, plan_validation_bases, validate_task_briefs
|
|
451
|
+
except ModuleNotFoundError as error: # pragma: no cover - package imports
|
|
452
|
+
if error.name != "check_task_briefs":
|
|
453
|
+
raise
|
|
454
|
+
from scripts.check_task_briefs import BriefError, _member_bases, plan_validation_bases, validate_task_briefs
|
|
455
|
+
if __package__:
|
|
456
|
+
from . import check_handoffs
|
|
457
|
+
else:
|
|
458
|
+
try:
|
|
459
|
+
import check_handoffs
|
|
460
|
+
except ModuleNotFoundError as error:
|
|
461
|
+
if error.name != "check_handoffs":
|
|
462
|
+
raise
|
|
463
|
+
from scripts import check_handoffs
|
|
442
464
|
try:
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
from scripts.check_task_briefs import BriefError, validate_task_briefs
|
|
448
|
-
try:
|
|
449
|
-
import check_handoffs
|
|
450
|
-
except ModuleNotFoundError as error:
|
|
451
|
-
if error.name != "check_handoffs":
|
|
452
|
-
raise
|
|
453
|
-
from scripts import check_handoffs
|
|
454
|
-
try:
|
|
455
|
-
tasks, dependency_files = check_handoffs.plan_brief_inputs(repo, project_dir)
|
|
456
|
-
landed_bases = {}
|
|
457
|
-
for task_id, text in tasks.items():
|
|
458
|
-
if check_handoffs._task_scalar(text, task_id, "status") != "done":
|
|
459
|
-
continue
|
|
460
|
-
agent = check_handoffs._task_scalar(text, task_id, "agent")
|
|
461
|
-
if agent in {"", "null"}:
|
|
462
|
-
raise BriefError(f"{task_id} landed task has no recorded agent")
|
|
463
|
-
recorded_base = check_handoffs._task_scalar(text, task_id, "base")
|
|
464
|
-
try:
|
|
465
|
-
landed_bases[task_id] = require_commit(repo, require_full_sha(recorded_base))
|
|
466
|
-
except IsolationError as error:
|
|
467
|
-
raise BriefError(f"{task_id} landed task has invalid historical base: {error}") from error
|
|
468
|
-
dependency_files[task_id] = set()
|
|
465
|
+
member_base = _member_bases(repo)
|
|
466
|
+
tasks, dependency_files, landed_bases = plan_validation_bases(
|
|
467
|
+
repo, project_dir, member_base, initial=True
|
|
468
|
+
)
|
|
469
469
|
validate_task_briefs(
|
|
470
470
|
repo, head.stdout.strip(), f"{project_dir}/tasks",
|
|
471
471
|
dependency_files=dependency_files, landed_bases=landed_bases,
|
|
472
|
+
member_base=member_base,
|
|
472
473
|
)
|
|
474
|
+
if project_dir == ".project/next":
|
|
475
|
+
# Promotion checks lookahead member tasks from the bases their briefs were checked at.
|
|
476
|
+
named = {
|
|
477
|
+
str(check_handoffs._strict_frontmatter(text, task_id).get("repo"))
|
|
478
|
+
for task_id, text in tasks.items()
|
|
479
|
+
if check_handoffs._strict_frontmatter(text, task_id).get("repo")
|
|
480
|
+
and check_handoffs._task_scalar(text, task_id, "status") != "done"
|
|
481
|
+
}
|
|
482
|
+
if named:
|
|
483
|
+
bases = {name: member_base(name)[1] for name in sorted(named)}
|
|
484
|
+
milestone = pipeline_state.load_state(repo, project_dir)[0].milestone
|
|
485
|
+
path = _lookahead_member_bases_path(repo, str(milestone))
|
|
486
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
487
|
+
pipeline_state._common.atomic_write(path, json.dumps(
|
|
488
|
+
{"schema": LOOKAHEAD_MEMBER_BASES_SCHEMA, "milestone": milestone, "bases": bases},
|
|
489
|
+
indent=2, sort_keys=True) + "\n")
|
|
473
490
|
except (BriefError, check_handoffs.HandoffError) as error:
|
|
474
491
|
raise PipelineStateError(f"task brief validation failed: {error}") from error
|
|
475
492
|
|
|
476
493
|
|
|
494
|
+
LOOKAHEAD_MEMBER_BASES_SCHEMA = "gsd-path/lookahead-member-bases/v1"
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
def _lookahead_member_bases_path(repo: Path, milestone: str) -> Path:
|
|
498
|
+
common = pipeline_state._run_git(repo, "rev-parse", "--path-format=absolute", "--git-common-dir").stdout.strip()
|
|
499
|
+
return Path(common) / "gsd-path" / "lookahead-member-bases" / f"{milestone}.json"
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
def _lookahead_member_bases(repo: Path, milestone: str) -> Optional[dict]:
|
|
503
|
+
path = _lookahead_member_bases_path(repo, milestone)
|
|
504
|
+
if not path.is_file():
|
|
505
|
+
return None
|
|
506
|
+
value = json.loads(path.read_text(encoding="utf-8"))
|
|
507
|
+
if value.get("schema") != LOOKAHEAD_MEMBER_BASES_SCHEMA or value.get("milestone") != milestone:
|
|
508
|
+
return None
|
|
509
|
+
return value.get("bases")
|
|
510
|
+
|
|
511
|
+
|
|
512
|
+
def _shipped_member_merges(repo: Path, landing: str) -> dict:
|
|
513
|
+
"""Member merges named by the ship commit the integration landing merged."""
|
|
514
|
+
if __package__:
|
|
515
|
+
from .pipeline_git import ship_member_rows
|
|
516
|
+
else:
|
|
517
|
+
from pipeline_git import ship_member_rows
|
|
518
|
+
ship = pipeline_state._run_git(repo, "rev-parse", "--verify", "--quiet", f"{landing}^2", check=False)
|
|
519
|
+
if ship.returncode != 0:
|
|
520
|
+
return {}
|
|
521
|
+
message = pipeline_state._run_git(repo, "show", "-s", "--format=%B", ship.stdout.strip()).stdout
|
|
522
|
+
return {row["name"]: row["merge"] for row in ship_member_rows(message)}
|
|
523
|
+
|
|
524
|
+
|
|
477
525
|
def checkpoint_approval(
|
|
478
526
|
repo: Path,
|
|
479
527
|
kind: str,
|
|
@@ -1027,6 +1075,46 @@ def _classify_plan_drift(
|
|
|
1027
1075
|
}
|
|
1028
1076
|
approved = _approved_task_contracts(repo, checkpoint)
|
|
1029
1077
|
current = _task_contracts_at(repo, revision)
|
|
1078
|
+
if __package__:
|
|
1079
|
+
from . import check_handoffs
|
|
1080
|
+
else:
|
|
1081
|
+
import check_handoffs
|
|
1082
|
+
# Member task paths live in member repos: compare each member from the base its brief
|
|
1083
|
+
# was checked at to the member merge the shipped milestone made (both fixed commits).
|
|
1084
|
+
task_repos = {
|
|
1085
|
+
task_id: str(check_handoffs._strict_frontmatter(contract.text, contract.path).get("repo") or "")
|
|
1086
|
+
for task_id, contract in approved.items()
|
|
1087
|
+
}
|
|
1088
|
+
active_member_tasks = {
|
|
1089
|
+
task_id for task_id, name in task_repos.items()
|
|
1090
|
+
if name and check_handoffs._task_scalar(approved[task_id].text, task_id, "status") != "done"
|
|
1091
|
+
}
|
|
1092
|
+
active_members = {task_repos[task_id] for task_id in active_member_tasks}
|
|
1093
|
+
member_changes: dict[str, list] = {}
|
|
1094
|
+
if active_members:
|
|
1095
|
+
bases = _lookahead_member_bases(repo, str(state.milestone)) or {}
|
|
1096
|
+
if any(name not in bases for name in active_members):
|
|
1097
|
+
return {
|
|
1098
|
+
"class": "unverifiable",
|
|
1099
|
+
"checkpoint": checkpoint,
|
|
1100
|
+
"task_ids": [],
|
|
1101
|
+
"changed_paths": [],
|
|
1102
|
+
"contract_paths": [],
|
|
1103
|
+
"member_tasks": True,
|
|
1104
|
+
"reason": "member bases were not recorded at plan approval",
|
|
1105
|
+
}
|
|
1106
|
+
if __package__:
|
|
1107
|
+
from . import members
|
|
1108
|
+
else:
|
|
1109
|
+
import members
|
|
1110
|
+
checkouts = {item["name"]: Path(item["checkout"]) for item in members.read_members(repo)}
|
|
1111
|
+
merges = _shipped_member_merges(repo, landing or revision)
|
|
1112
|
+
for name in active_members:
|
|
1113
|
+
member_changes[name] = [
|
|
1114
|
+
item for item in pipeline_state._run_git(
|
|
1115
|
+
checkouts[name], "diff", "--no-renames", "--name-only", "-z", bases[name], merges[name]
|
|
1116
|
+
).stdout.split("\0") if item
|
|
1117
|
+
] if name in merges else []
|
|
1030
1118
|
|
|
1031
1119
|
contract_paths: set[str] = set()
|
|
1032
1120
|
flagged_ids: set[str] = set()
|
|
@@ -1050,9 +1138,12 @@ def _classify_plan_drift(
|
|
|
1050
1138
|
|
|
1051
1139
|
product_paths: set[str] = set()
|
|
1052
1140
|
for task_id, contract in approved.items():
|
|
1141
|
+
member = task_repos.get(task_id)
|
|
1142
|
+
if member and task_id not in active_member_tasks:
|
|
1143
|
+
continue
|
|
1053
1144
|
matches = sorted(
|
|
1054
|
-
changed_path
|
|
1055
|
-
for changed_path in changed
|
|
1145
|
+
(f"{member}:{changed_path}" if member else changed_path)
|
|
1146
|
+
for changed_path in (member_changes[member] if member else changed)
|
|
1056
1147
|
if any(
|
|
1057
1148
|
changed_path == path
|
|
1058
1149
|
or changed_path.startswith(f"{path.rstrip('/')}/")
|
|
@@ -82,6 +82,8 @@ def _promotion_event(
|
|
|
82
82
|
if isinstance(task_ids, list) and task_ids:
|
|
83
83
|
return f"{prefix}; plan drift flagged tasks {', '.join(task_ids)}"
|
|
84
84
|
return f"{prefix}; plan contract changed after approval"
|
|
85
|
+
if drift_class == "unverifiable" and drift.get("member_tasks"):
|
|
86
|
+
return f"{prefix}; plan drift unverifiable because member bases were not recorded at plan approval"
|
|
85
87
|
if drift_class == "unverifiable":
|
|
86
88
|
return f"{prefix}; plan drift unverifiable because approval checkpoint is missing"
|
|
87
89
|
return prefix
|
|
@@ -13,10 +13,34 @@ import os
|
|
|
13
13
|
import tempfile
|
|
14
14
|
from pathlib import Path
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
import _common
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
if __package__:
|
|
17
|
+
from . import _common
|
|
18
|
+
else:
|
|
19
|
+
try:
|
|
20
|
+
import _common
|
|
21
|
+
except ImportError:
|
|
22
|
+
from scripts import _common
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _worktree_list_porcelain(primary: Path) -> tuple[str, bool]:
|
|
26
|
+
try:
|
|
27
|
+
if __package__:
|
|
28
|
+
from . import pipeline_git as pg
|
|
29
|
+
else:
|
|
30
|
+
from scripts import pipeline_git as pg
|
|
31
|
+
except ImportError:
|
|
32
|
+
try:
|
|
33
|
+
import pipeline_git as pg
|
|
34
|
+
except ImportError:
|
|
35
|
+
pg = None
|
|
36
|
+
if pg is not None:
|
|
37
|
+
return pg.worktree_list_porcelain(primary)
|
|
38
|
+
try:
|
|
39
|
+
output = _git(primary, "worktree", "list", "--porcelain", "-z")
|
|
40
|
+
return output, True
|
|
41
|
+
except ValueError:
|
|
42
|
+
output = _git(primary, "worktree", "list", "--porcelain")
|
|
43
|
+
return output, False
|
|
20
44
|
|
|
21
45
|
|
|
22
46
|
def _git(primary: Path, *args: str) -> str:
|
|
@@ -27,7 +51,10 @@ def _git(primary: Path, *args: str) -> str:
|
|
|
27
51
|
|
|
28
52
|
|
|
29
53
|
def _identity(path: Path) -> str:
|
|
30
|
-
|
|
54
|
+
digest = hashlib.sha256(os.fsencode(path)).hexdigest()
|
|
55
|
+
# Two identities nest in every managed path; full digests would use about
|
|
56
|
+
# 130 of Windows' 260-character MAX_PATH before any repository content.
|
|
57
|
+
return digest[:16] if os.name == "nt" else digest
|
|
31
58
|
|
|
32
59
|
|
|
33
60
|
def _workspace(primary: Path, pin: bool) -> Path:
|
|
@@ -65,7 +92,7 @@ def _workspace(primary: Path, pin: bool) -> Path:
|
|
|
65
92
|
receipt.parent.mkdir(parents=True, exist_ok=True)
|
|
66
93
|
fd, temporary = tempfile.mkstemp(dir=receipt.parent)
|
|
67
94
|
try:
|
|
68
|
-
with os.fdopen(fd, "w", encoding="utf-8") as handle:
|
|
95
|
+
with os.fdopen(fd, "w", encoding="utf-8", newline="\n") as handle:
|
|
69
96
|
json.dump({"primary": str(primary), "root": str(workspace)}, handle)
|
|
70
97
|
try:
|
|
71
98
|
os.link(temporary, receipt)
|
|
@@ -76,17 +103,52 @@ def _workspace(primary: Path, pin: bool) -> Path:
|
|
|
76
103
|
return workspace
|
|
77
104
|
|
|
78
105
|
|
|
106
|
+
def release_workspace(primary: Path) -> bool:
|
|
107
|
+
"""Forget the pinned placement receipt once no linked worktrees remain.
|
|
108
|
+
|
|
109
|
+
Lets GSD_PATH_WORKTREE_ROOT (or a new default) apply again at the next
|
|
110
|
+
milestone's first allocation. Returns True when a receipt was removed;
|
|
111
|
+
any remaining linked worktree (including one only still registered) keeps
|
|
112
|
+
the pin.
|
|
113
|
+
"""
|
|
114
|
+
primary = primary.resolve()
|
|
115
|
+
common = Path(_git(primary, "rev-parse", "--git-common-dir"))
|
|
116
|
+
common = (primary / common).resolve()
|
|
117
|
+
receipt = common / "gsd-path" / "workspaces" / f"{_identity(primary)}.json"
|
|
118
|
+
if not receipt.is_file():
|
|
119
|
+
return False
|
|
120
|
+
output, nul_separated = _worktree_list_porcelain(primary)
|
|
121
|
+
records = output.split("\0\0") if nul_separated else [
|
|
122
|
+
block for block in output.strip().split("\n\n") if block.strip()
|
|
123
|
+
]
|
|
124
|
+
for record in records:
|
|
125
|
+
fields = record.split("\0") if nul_separated else record.splitlines()
|
|
126
|
+
for field in fields:
|
|
127
|
+
if field.startswith("worktree ") and Path(field[len("worktree "):]).resolve() != primary:
|
|
128
|
+
return False
|
|
129
|
+
receipt.unlink()
|
|
130
|
+
return True
|
|
131
|
+
|
|
132
|
+
|
|
79
133
|
def worktree_path(primary: Path, kind: str, name: str, *, pin: bool = False) -> Path:
|
|
80
134
|
primary = primary.resolve()
|
|
81
|
-
if kind not in {"task", "verify", "integrate"} or not name or Path(name).name != name or name in {".", ".."}:
|
|
135
|
+
if kind not in {"task", "verify", "integrate", "bound"} or not name or Path(name).name != name or name in {".", ".."}:
|
|
82
136
|
raise ValueError("invalid managed worktree kind or name")
|
|
137
|
+
if kind == "bound":
|
|
138
|
+
return _workspace(primary, pin) / kind / name
|
|
83
139
|
legacy = (primary.parent / f".{primary.name}-gsd-path-integrate-{name}"
|
|
84
140
|
if kind == "integrate" else primary.parent / f"{primary.name}.gsd-path" / kind / name)
|
|
85
141
|
branch = f"refs/heads/gsd-path-{kind}/{name}"
|
|
86
|
-
|
|
142
|
+
output, nul_separated = _worktree_list_porcelain(primary)
|
|
143
|
+
if nul_separated:
|
|
144
|
+
records = output.split("\0\0")
|
|
145
|
+
else:
|
|
146
|
+
records = [block for block in output.strip().split("\n\n") if block.strip()]
|
|
87
147
|
for record in records:
|
|
88
|
-
fields = record.split("\0")
|
|
89
|
-
|
|
148
|
+
fields = record.split("\0") if nul_separated else record.splitlines()
|
|
149
|
+
# Compare as paths: git prints forward slashes on Windows.
|
|
150
|
+
worktrees = [Path(field[len("worktree "):]) for field in fields if field.startswith("worktree ")]
|
|
151
|
+
if legacy in worktrees and f"branch {branch}" in fields:
|
|
90
152
|
return legacy
|
|
91
153
|
# Keep collision checks and missing-directory recovery at the old location.
|
|
92
154
|
if os.path.lexists(legacy):
|
|
@@ -57,6 +57,36 @@ paragraph the user signed off on — do not edit without a new sign-off.>
|
|
|
57
57
|
1. <criterion — a thing you can run/measure/see>
|
|
58
58
|
2. ...
|
|
59
59
|
|
|
60
|
+
## Edge coverage
|
|
61
|
+
|
|
62
|
+
<!-- Written by define's edge probe (references/spec-probes.md). Walk every
|
|
63
|
+
success criterion; each applicable edge gets one row ruled by the user.
|
|
64
|
+
Disposition: criterion SCn (stated in that criterion) | held-out (a named
|
|
65
|
+
test pins the ruling written in Detail) | dismissed (Detail says why the
|
|
66
|
+
edge cannot occur). Every SCn appears at least once; a criterion with no
|
|
67
|
+
data shape gets category none, dismissed. Categories: boundary,
|
|
68
|
+
adjacency, empty, encoding, ordering, precision, idempotency,
|
|
69
|
+
concurrency, none. `check_handoffs.py intent` gates this table. -->
|
|
70
|
+
|
|
71
|
+
| Edge | Criterion | Category | Disposition | Detail |
|
|
72
|
+
|------|-----------|----------|-------------|--------|
|
|
73
|
+
| E1 | SC1 | <category> | <disposition> | <ruling, examples, or dismissal reason> |
|
|
74
|
+
|
|
75
|
+
## Prohibitions
|
|
76
|
+
|
|
77
|
+
<!-- Written by define's prohibition probe. What each criterion must never
|
|
78
|
+
silently become: values, safety, privacy, fairness, transparency. Not
|
|
79
|
+
routine engineering, not generic security canon.
|
|
80
|
+
Disposition: criterion SCn (checkable; stated in that criterion) |
|
|
81
|
+
judgment (final reviewer judges it; Detail says what to look for) |
|
|
82
|
+
dismissed. A single row with Criterion `all`, Must not `none`, and
|
|
83
|
+
disposition dismissed, and no other row, records work that affects no
|
|
84
|
+
person directly. -->
|
|
85
|
+
|
|
86
|
+
| Prohibition | Criterion | Must not | Disposition | Detail |
|
|
87
|
+
|-------------|-----------|----------|-------------|--------|
|
|
88
|
+
| N1 | SC1 | <what it must never become> | <disposition> | <what the reviewer looks for, or why dismissed> |
|
|
89
|
+
|
|
60
90
|
## Scope: in
|
|
61
91
|
|
|
62
92
|
<The smallest version that hits the success criteria. Bullet list.>
|
|
@@ -10,7 +10,7 @@ branch: null # bound per milestone as gsd-path/M00N; after integration
|
|
|
10
10
|
# the router rebinds before any next-milestone file change
|
|
11
11
|
# the bound branch is never main; ship integrates it there
|
|
12
12
|
archive: null # persisted archive transaction path; never recomputed
|
|
13
|
-
integration_default: direct # direct | pull-request; project setting
|
|
13
|
+
integration_default: direct # direct | pull-request | external-landing; project setting
|
|
14
14
|
integration: direct # current milestone; may override the default before build
|
|
15
15
|
integration_source: default # default | milestone; preserves override provenance
|
|
16
16
|
---
|
|
@@ -3,7 +3,8 @@ name: gsd-path-discuss
|
|
|
3
3
|
description: Hold an explicit, evidence-grounded discussion about an active GSD Path milestone from any phase, preserve the verbatim dialogue and answer records under .project/discuss/, use local code and existing artifacts before focused research, challenge unsupported assumptions, and identify the phase owner for follow-up. Use only when the user explicitly invokes $gsd-path-discuss to ask questions, explore a decision, request a progress explanation, or close a discussion without advancing the pipeline.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
Before executing project helpers, read [runtime selection](references/runtime-selection.md)
|
|
6
|
+
Before executing project helpers, read [runtime selection](references/runtime-selection.md)
|
|
7
|
+
and [operating rules](references/operating-rules.md).
|
|
7
8
|
|
|
8
9
|
# GSD Path Discussion
|
|
9
10
|
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# Operating rules for phase work
|
|
2
|
+
|
|
3
|
+
These rules extend the project `AGENTS.md` block. Every GSD Path skill
|
|
4
|
+
bundles this file; spawned agents follow their role brief instead.
|
|
5
|
+
|
|
6
|
+
## Files and state
|
|
7
|
+
|
|
8
|
+
- `.project/discuss/DIALOGUE.md` and `.project/discuss/ANSWERS.md` are the
|
|
9
|
+
append-only memory for any-phase discussion. Read them before continuing an
|
|
10
|
+
existing thread; never treat chat history alone as durable context.
|
|
11
|
+
- The discussion skill never commits. Every phase orchestrator treats only
|
|
12
|
+
complete append-only discussion records as expected bookkeeping and includes
|
|
13
|
+
them in its next normal `.project/` checkpoint; build does so before its next
|
|
14
|
+
clean layer base, and ship includes them in its transaction.
|
|
15
|
+
- Write every output to the handoff path in WORKFLOW.md, using the absolute
|
|
16
|
+
bundled template path supplied by the active phase skill. An output that
|
|
17
|
+
needs verbal explanation is defective.
|
|
18
|
+
- With no `.project/STATE.md`, route through the bundled
|
|
19
|
+
`scripts/detect_project.py initialize --repo <absolute-root> --template
|
|
20
|
+
<absolute-state-template> --require-git` helper; `route: setup-repository`
|
|
21
|
+
leaves the invocation folder unchanged and routes to repository setup before
|
|
22
|
+
state creation or branch binding. Never delete the invocation folder or its
|
|
23
|
+
state to satisfy bootstrap path checks. Do not classify from a directory listing
|
|
24
|
+
or conversation. Follow its JSON `verdict` and `route`. Reserve `classify`
|
|
25
|
+
for read-only inspection; do not use it as a state-initialization preflight.
|
|
26
|
+
- `.project/STATE.md` tracks phase position. Parse and validate it only with
|
|
27
|
+
the bundled `scripts/pipeline_state.py validate` command, route with its
|
|
28
|
+
`route` command, and make ordinary phase transitions only with its
|
|
29
|
+
expected-state `transition`. A journaled transaction helper may write only
|
|
30
|
+
the state fields its contract explicitly owns. Never reproduce these
|
|
31
|
+
deterministic operations in model reasoning. The
|
|
32
|
+
orchestrator alone owns task frontmatter base, isolated worktree/branch,
|
|
33
|
+
status, and agent; the landing commit is proven from git by `isolation.py
|
|
34
|
+
recover`, never recorded. Require `pipeline: gsd-path/v2`; never
|
|
35
|
+
consume an ambiguous or differently owned state file. Artifacts outrank
|
|
36
|
+
summaries; reconcile STATE.md when it disagrees with task frontmatter.
|
|
37
|
+
During a program build, `.project/next/STATE.md` may hold
|
|
38
|
+
the lookahead planning track for the next milestone; it follows the same
|
|
39
|
+
marker rule, owns no task frontmatter, and never binds a branch.
|
|
40
|
+
- STATE.integration_default is the project closeout choice and
|
|
41
|
+
STATE.integration is the current milestone choice. Both are `direct` or
|
|
42
|
+
`pull-request`; STATE.integration_source is `default` or `milestone` and
|
|
43
|
+
preserves explicit override provenance. Older v2 state defaults to `direct`,
|
|
44
|
+
and modes may be changed only through `pipeline_state.py
|
|
45
|
+
configure-integration` before build. A next milestone resets its current
|
|
46
|
+
choice from the project default.
|
|
47
|
+
- Spawned agents have isolated context. Follow the installed runtime dispatch
|
|
48
|
+
contract and brief them with exact input and output paths, constraints, a
|
|
49
|
+
deterministic logical task name, and a bounded responsibility. Independent
|
|
50
|
+
briefs may run in parallel up to available child capacity; a dependent
|
|
51
|
+
brief runs as soon as its dependencies complete.
|
|
52
|
+
|
|
53
|
+
## Stay in role
|
|
54
|
+
|
|
55
|
+
- The codebase mapper and docs auditor observe and verify; they are strictly
|
|
56
|
+
read-only, report observations rather than judgments, and never resolve a
|
|
57
|
+
doc-vs-code conflict — that ruling belongs to the user.
|
|
58
|
+
- Build, test, lint, and help commands are not presumed read-safe. Read-only
|
|
59
|
+
roles run project commands only in orchestrator-created disposable worktrees
|
|
60
|
+
at a recorded revision; otherwise they use static evidence or mark the check
|
|
61
|
+
unverifiable. They never create worktrees or run commands in the source tree.
|
|
62
|
+
- Researchers gather evidence; they do not decide. A dimension is researched
|
|
63
|
+
only when it has open questions; the research phase records dispatched and
|
|
64
|
+
skipped dimensions. Brownfield adds `evidence-codebase.md` as settled input.
|
|
65
|
+
- The decider works from existing evidence; it does not re-research. An
|
|
66
|
+
unresolved or uncited required decision fails the synthesis gate.
|
|
67
|
+
- The planner reads both INTENT.md and SYNTHESIS.md and specs
|
|
68
|
+
deliverable-sized outcomes and constraints; every INTENT success criterion
|
|
69
|
+
maps to a task AC and Verify in PLAN.md Intent coverage. Coders own
|
|
70
|
+
implementation decisions inside those bounds.
|
|
71
|
+
- Coders implement only their full task contract, including owned INTENT
|
|
72
|
+
success criteria read from INTENT.md, and append their result to the
|
|
73
|
+
task Log. They never change task state, review acceptance, stage, commit, or
|
|
74
|
+
freelance outside declared files.
|
|
75
|
+
- The orchestrator dispatches, arbitrates, and creates task isolation and
|
|
76
|
+
verify sidecars through the bundled `scripts/isolation.py` helper — named
|
|
77
|
+
branches only, never a detached HEAD — lands task work serially, and
|
|
78
|
+
records each clean base in task frontmatter; `land` stamps the landed
|
|
79
|
+
state into the task's own commit, so a task has exactly one commit. It
|
|
80
|
+
writes no product code. When a done task's work already sits on the bound
|
|
81
|
+
branch without a landing commit, only an explicit owner ruling through
|
|
82
|
+
`isolation.py attest` may stand in for it: one `.project/`-only commit that
|
|
83
|
+
names the base, the attested HEAD, the declared files that changed, the
|
|
84
|
+
task Verify recorded as passing at that HEAD, and the ruling verbatim.
|
|
85
|
+
`recover` reports it as `attested`, never as a proven landing.
|
|
86
|
+
- All pipeline work for a milestone lives on `gsd-path/M00N` (M001, M002,
|
|
87
|
+
…) bound in STATE.branch. The next milestone binds a new unused
|
|
88
|
+
`gsd-path/M00N` at the remote default after the previous ship integrates.
|
|
89
|
+
Integration at ship is the only path from the bound branch to the default
|
|
90
|
+
branch — either Path's direct merge or a Path-owned PR merged by the user.
|
|
91
|
+
The bound branch never receives merges or back-merges and is never the
|
|
92
|
+
GitHub default.
|
|
93
|
+
- After initialization writes STATE.md, and before entering the first pipeline
|
|
94
|
+
phase in an existing Git repository, the router calls
|
|
95
|
+
`scripts/pipeline_git.py bind-initial` with the selected M00N and exact
|
|
96
|
+
fetched `origin/main` SHA. The helper alone checks worktree identity and
|
|
97
|
+
cleanliness, exact base, and every local, remote, and other-worktree
|
|
98
|
+
collision before creating or adopting the branch. The sole cleanliness
|
|
99
|
+
exception is untracked `.project/STATE.md`: validated v2 state in active
|
|
100
|
+
inspect or define, with null milestone, branch, and archive, in a real
|
|
101
|
+
directory containing only that regular file with no hard links. The helper
|
|
102
|
+
checks its identity and bytes across binding. Do not commit initialization
|
|
103
|
+
before binding. The router persists its
|
|
104
|
+
typed result in the new state. Build has no branch-creation authority.
|
|
105
|
+
- After `validate-integrated` passes and before any next-milestone file
|
|
106
|
+
changes, the router calls the bundled `scripts/pipeline_git.py bind-next`
|
|
107
|
+
helper with the previous bound branch, exact ship SHA, and exact current
|
|
108
|
+
`origin/main` SHA. The helper moves the clean primary worktree to the new
|
|
109
|
+
unused `gsd-path/M00N` branch at that SHA without moving the previous
|
|
110
|
+
branch or entering the default checkout, then retires the integrated
|
|
111
|
+
previous branch — deleted locally and on origin; the ship commit stays
|
|
112
|
+
reachable from the integration merge and its annotated tag. The router
|
|
113
|
+
persists the new branch in STATE; a wrong-SHA or colliding branch blocks.
|
|
114
|
+
After validated PR integration, `bind-next --allow-missing-previous` may
|
|
115
|
+
retire only the local previous branch when GitHub already auto-deleted its
|
|
116
|
+
remote branch.
|
|
117
|
+
`bind-initial`, this handoff, and the approved new-repository bootstrap are
|
|
118
|
+
the only bound-branch creation authorities, and the handoff's retirement
|
|
119
|
+
push is the router's only bound-branch deletion authority. When a lookahead
|
|
120
|
+
track exists, the router then calls `scripts/pipeline_state.py promote-next`;
|
|
121
|
+
only that journaled helper moves the track, updates state and roadmap,
|
|
122
|
+
classifies plan drift, and writes the router promotion commit.
|
|
123
|
+
- Build adopts the branch recorded in STATE.branch, never whatever is current
|
|
124
|
+
when a recorded branch exists. A new-GitHub REPOSITORY.md proves the
|
|
125
|
+
default checkout and first bound branch; later milestones may rebind
|
|
126
|
+
`gsd-path/M00N` without rewriting that artifact. Build ignores older
|
|
127
|
+
milestone ship and integrate commits inherited through main. A ship commit
|
|
128
|
+
for the current STATE.branch milestone must be an ancestor of origin/main;
|
|
129
|
+
if it is not, that milestone's integration is incomplete and control routes
|
|
130
|
+
to ship, not build. Direct mode requires the matching canonical `integrate:`
|
|
131
|
+
commit; PR mode requires tag metadata and a two-parent merge whose second
|
|
132
|
+
parent is the ship commit. A null branch returns
|
|
133
|
+
to the router; build never creates, selects, switches, or rebinds it.
|
|
134
|
+
- The ship phase makes exactly one commit on the bound branch — the
|
|
135
|
+
`.project/`-only ship commit recording
|
|
136
|
+
STATE.md, the final-review artifacts, and the archive — and additionally
|
|
137
|
+
owns the integration leg. Direct mode creates and pushes one `--no-ff` merge
|
|
138
|
+
onto `main` with subject
|
|
139
|
+
`integrate: M00N — merge gsd-path/M00N into main`. Pull-request mode creates
|
|
140
|
+
or reuses one GitHub.com PR and waits for the user to merge it with a merge
|
|
141
|
+
commit; it never auto-merges. Both modes create one annotated
|
|
142
|
+
`milestone/<NNN>-<slug>` tag after merge validation.
|
|
143
|
+
The roadmap and
|
|
144
|
+
plan phases each make exactly one approval checkpoint commit
|
|
145
|
+
(`.project/`-only, deferred to the build transition commit during a
|
|
146
|
+
new-repository transaction or before Git exists). Their bundled
|
|
147
|
+
`pipeline_state.py approve` command journals before changing STATE or
|
|
148
|
+
ROADMAP.md and owns that canonical checkpoint; a routed
|
|
149
|
+
`resume-checkpoint` must finish before phase work. The router makes one
|
|
150
|
+
bookkeeping commit through `pipeline_state.py promote-next` when promoting a
|
|
151
|
+
lookahead track at a milestone boundary. Every other commit belongs to the
|
|
152
|
+
orchestrator.
|
|
153
|
+
- Reviewers verify and block; they never fix. A block names the criterion,
|
|
154
|
+
observed result, evidence location, and concrete fix direction. An optional
|
|
155
|
+
review panel is advisory: the canonical reviewer remains the only wave
|
|
156
|
+
pass/fail, and panel findings never average or auto-replan. Same-model
|
|
157
|
+
agreement is not independent verification: matching verdicts from one
|
|
158
|
+
model family count as a single evidence path. Independence comes from
|
|
159
|
+
re-run commands, reconstructed patches, different sources, or a
|
|
160
|
+
different model family. Resolve panel
|
|
161
|
+
membership with the bundled `scripts/review_panel.py` helper; do not invent
|
|
162
|
+
model families or slugs. Create task isolation and verify sidecars with the
|
|
163
|
+
bundled `scripts/isolation.py` helper; do not invent `git worktree add` or
|
|
164
|
+
`--detach`. Undo unpublished pipeline work with `scripts/pipeline_undo.py`;
|
|
165
|
+
do not invent `git reset`. Diagnose a stuck pipeline with
|
|
166
|
+
`scripts/pipeline_diagnose.py`.
|
|
167
|
+
- A bundled helper that exits non-zero stops the current step. Print its
|
|
168
|
+
stderr verbatim, run `scripts/pipeline_diagnose.py diagnose --repo
|
|
169
|
+
<absolute-root>` (bundled with `$gsd-path-forensics`), and report both.
|
|
170
|
+
Do not rerun the same command unchanged unless the helper's own contract
|
|
171
|
+
names that exact rerun as its interruption recovery. Never repair state or
|
|
172
|
+
Git by hand instead.
|
|
173
|
+
- The discussion sidecar may run during any non-shipped phase. It grounds
|
|
174
|
+
answers in code and phase artifacts, may perform focused research when
|
|
175
|
+
needed, and writes only its discussion artifacts; it never changes phase
|
|
176
|
+
state or bypasses a phase gate.
|
|
177
|
+
- During an uncommitted archive transaction, discussion writes a complete
|
|
178
|
+
active copy that extends the archived pair. The ship phase reruns `prepare`;
|
|
179
|
+
the helper validates the prefix and atomically reconciles both files.
|
|
180
|
+
Discussion never edits an archive directly or writes after shipment.
|
|
181
|
+
- The loop runner wraps explicit skills in a bounded check → verify → fix →
|
|
182
|
+
verify pass driven by a LOOP.md spec. It never advances a phase gate
|
|
183
|
+
itself and never commits or pushes.
|
|
184
|
+
- Fix tasks use the complete task template, not an abbreviated finding.
|
|
185
|
+
|
|
186
|
+
## New GitHub repositories
|
|
187
|
+
|
|
188
|
+
- Create a GitHub repository only from an explicit user request followed by an
|
|
189
|
+
approval of the exact owner/name, visibility, default-checkout path,
|
|
190
|
+
`gsd-path/M001` branch, and linked primary-worktree path. Before the
|
|
191
|
+
external action produces an artifact, present those proposed targets as the
|
|
192
|
+
inline **Review** surface using the active router's preview contract.
|
|
193
|
+
Do not write a
|
|
194
|
+
preview file into the invocation directory or another repository. Run the
|
|
195
|
+
bundled bootstrap helper's read-only `preview` command for this evidence.
|
|
196
|
+
- After approval, the bootstrap helper persists the exact targets under the
|
|
197
|
+
approved workspace before the first external mutation. Its `create` command
|
|
198
|
+
creates or verifies the remote, checkout, branch, and linked worktree one
|
|
199
|
+
stage at a time. A matching journal permits explicit resume and adoption; a
|
|
200
|
+
collision without that journal blocks. The helper removes the journal only
|
|
201
|
+
after writing owned STATE.md and fixed-format `.project/REPOSITORY.md` in the
|
|
202
|
+
linked worktree.
|
|
203
|
+
- During an approved new-repository transaction, the router may create the
|
|
204
|
+
first GSD Path branch and linked primary worktree at the verified
|
|
205
|
+
remote-default SHA and persist that branch in STATE.md and REPOSITORY.md.
|
|
206
|
+
Build must verify and adopt that exact binding from REPOSITORY.md, never a
|
|
207
|
+
free-form log. Task branches and task worktrees remain exclusively
|
|
208
|
+
build-orchestrator owned.
|
|
209
|
+
- Keep the cloned default checkout clean on the remote default branch. Run the
|
|
210
|
+
pipeline from the linked GSD Path worktree; never initialize `.project/` in
|
|
211
|
+
the default checkout, reuse an existing branch or path (except an explicitly
|
|
212
|
+
approved empty linked-worktree folder via `--reuse-empty-worktree`), move an existing
|
|
213
|
+
repository, or recover a partial GitHub creation without the exact approved
|
|
214
|
+
journal and re-verification.
|