@opengsd/gsd-path 1.3.0 → 1.4.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 +294 -0
- package/DOCS.md +19 -10
- package/FULL.md +9 -3
- package/GUIDE.md +1 -1
- package/HOOKS.md +9 -6
- package/QUICK.md +4 -1
- package/README.md +63 -11
- package/RUNTIME.md +1 -1
- package/UPDATE.md +61 -12
- package/WORKFLOW.md +22 -6
- package/package.json +9 -8
- package/scripts/_common.py +472 -19
- package/scripts/archive_milestone.py +146 -73
- package/scripts/bootstrap_repository.py +8 -5
- package/scripts/build_recovery.py +4 -1
- package/scripts/build_state.py +66 -23
- package/scripts/check_docs_audit.py +14 -3
- package/scripts/check_handoffs.py +116 -20
- package/scripts/check_task_briefs.py +60 -8
- 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 +345 -15
- package/scripts/discussion_records.py +19 -13
- package/scripts/discussion_validate.py +66 -21
- package/scripts/dispatch_driver.py +111 -26
- package/scripts/git_guard.py +116 -29
- package/scripts/guard_hook.py +151 -29
- package/scripts/install.mjs +55 -39
- package/scripts/install.py +564 -41
- package/scripts/integration.py +434 -24
- package/scripts/isolation.py +1077 -28
- package/scripts/lean_verification.py +99 -19
- package/scripts/loop_run.py +20 -30
- package/scripts/members.py +704 -0
- package/scripts/migrate_core.py +2 -2
- package/scripts/path_config.py +2 -2
- package/scripts/pipeline_diagnose.py +82 -31
- package/scripts/pipeline_git.py +61 -22
- package/scripts/pipeline_state.py +176 -54
- package/scripts/pipeline_undo.py +117 -22
- package/scripts/promote_lookahead.py +1 -1
- package/scripts/review_panel.py +1 -1
- package/scripts/runtime_store.py +49 -11
- package/scripts/skill-resources.json +28 -3
- package/scripts/state_checkpoint.py +140 -31
- package/scripts/state_promote.py +2 -0
- package/scripts/status_runtime.py +36 -6
- package/scripts/sync_skill_resources.py +8 -7
- package/scripts/token_budget.py +12 -8
- package/scripts/workflow_run.py +103 -29
- package/scripts/worktree_paths.py +18 -8
- package/skills/gsd-path/BUILD.md +7 -1
- package/skills/gsd-path/DECIDE.md +11 -4
- package/skills/gsd-path/DEFINE.md +8 -1
- package/skills/gsd-path/DOCS-AUDIT.md +6 -4
- package/skills/gsd-path/INSPECT.md +5 -4
- package/skills/gsd-path/PLAN.md +7 -1
- package/skills/gsd-path/RESEARCH.md +2 -1
- package/skills/gsd-path/ROADMAP.md +2 -1
- package/skills/gsd-path/SHIP.md +27 -10
- package/skills/gsd-path/SKILL.md +45 -1
- package/skills/gsd-path/references/build-native.md +47 -14
- package/skills/gsd-path/references/codebase-mapper.md +2 -1
- package/skills/gsd-path/references/docs-auditor.md +2 -1
- package/skills/gsd-path/references/operating-rules.md +214 -0
- package/skills/gsd-path/references/planner.md +8 -0
- package/skills/gsd-path/references/reviewer-wave.md +3 -1
- package/skills/gsd-path/scripts/__pycache__/_common.cpython-312.pyc +0 -0
- package/skills/gsd-path/scripts/__pycache__/check_handoffs.cpython-312.pyc +0 -0
- package/skills/gsd-path/scripts/_common.py +472 -19
- package/skills/gsd-path/scripts/archive_milestone.py +146 -73
- package/skills/gsd-path/scripts/bootstrap_repository.py +8 -5
- package/skills/gsd-path/scripts/build_recovery.py +4 -1
- package/skills/gsd-path/scripts/build_state.py +66 -23
- package/skills/gsd-path/scripts/check_docs_audit.py +14 -3
- package/skills/gsd-path/scripts/check_handoffs.py +116 -20
- package/skills/gsd-path/scripts/check_task_briefs.py +60 -8
- package/skills/gsd-path/scripts/check_update.py +2 -2
- package/skills/gsd-path/scripts/detect_project.py +345 -15
- package/skills/gsd-path/scripts/discussion_records.py +19 -13
- package/skills/gsd-path/scripts/discussion_validate.py +66 -21
- package/skills/gsd-path/scripts/dispatch_driver.py +111 -26
- package/skills/gsd-path/scripts/git_guard.py +116 -29
- package/skills/gsd-path/scripts/integration.py +434 -24
- package/skills/gsd-path/scripts/isolation.py +1077 -28
- package/skills/gsd-path/scripts/lean_verification.py +99 -19
- package/skills/gsd-path/scripts/loop_run.py +20 -30
- package/skills/gsd-path/scripts/members.py +704 -0
- package/skills/gsd-path/scripts/path_config.py +2 -2
- package/skills/gsd-path/scripts/pipeline_git.py +61 -22
- package/skills/gsd-path/scripts/pipeline_state.py +176 -54
- 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 +140 -31
- package/skills/gsd-path/scripts/state_promote.py +2 -0
- package/skills/gsd-path/scripts/status_runtime.py +36 -6
- package/skills/gsd-path/scripts/token_budget.py +12 -8
- package/skills/gsd-path/scripts/workflow_run.py +103 -29
- package/skills/gsd-path/scripts/worktree_paths.py +18 -8
- package/skills/gsd-path/templates/codebase.md +1 -1
- package/skills/gsd-path/templates/docs-audit.md +1 -1
- package/skills/gsd-path/templates/final-review.md +5 -2
- package/skills/gsd-path/templates/gap-review.md +2 -1
- package/skills/gsd-path/templates/task.md +1 -0
- package/skills/gsd-path/templates/wave-review.md +3 -1
- package/skills/gsd-path-build/SKILL.md +7 -1
- package/skills/gsd-path-build/references/build-native.md +47 -14
- package/skills/gsd-path-build/references/operating-rules.md +214 -0
- package/skills/gsd-path-build/references/reviewer-wave.md +3 -1
- package/skills/gsd-path-build/scripts/__pycache__/_common.cpython-312.pyc +0 -0
- package/skills/gsd-path-build/scripts/__pycache__/check_handoffs.cpython-312.pyc +0 -0
- package/skills/gsd-path-build/scripts/_common.py +472 -19
- package/skills/gsd-path-build/scripts/archive_milestone.py +146 -73
- package/skills/gsd-path-build/scripts/build_recovery.py +4 -1
- package/skills/gsd-path-build/scripts/build_state.py +66 -23
- package/skills/gsd-path-build/scripts/check_handoffs.py +116 -20
- package/skills/gsd-path-build/scripts/check_task_briefs.py +60 -8
- package/skills/gsd-path-build/scripts/detect_project.py +345 -15
- package/skills/gsd-path-build/scripts/discussion_records.py +19 -13
- package/skills/gsd-path-build/scripts/discussion_validate.py +66 -21
- package/skills/gsd-path-build/scripts/dispatch_driver.py +111 -26
- package/skills/gsd-path-build/scripts/integration.py +434 -24
- package/skills/gsd-path-build/scripts/isolation.py +1077 -28
- package/skills/gsd-path-build/scripts/loop_run.py +20 -30
- package/skills/gsd-path-build/scripts/members.py +704 -0
- package/skills/gsd-path-build/scripts/path_config.py +2 -2
- package/skills/gsd-path-build/scripts/pipeline_git.py +61 -22
- package/skills/gsd-path-build/scripts/pipeline_state.py +176 -54
- 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 +140 -31
- package/skills/gsd-path-build/scripts/state_promote.py +2 -0
- package/skills/gsd-path-build/scripts/token_budget.py +12 -8
- package/skills/gsd-path-build/scripts/workflow_run.py +103 -29
- package/skills/gsd-path-build/scripts/worktree_paths.py +18 -8
- package/skills/gsd-path-build/templates/task.md +1 -0
- package/skills/gsd-path-build/templates/wave-review.md +3 -1
- package/skills/gsd-path-decide/SKILL.md +11 -4
- package/skills/gsd-path-decide/references/operating-rules.md +214 -0
- package/skills/gsd-path-decide/scripts/_common.py +472 -19
- package/skills/gsd-path-decide/scripts/archive_milestone.py +146 -73
- package/skills/gsd-path-decide/scripts/build_recovery.py +4 -1
- package/skills/gsd-path-decide/scripts/check_handoffs.py +116 -20
- package/skills/gsd-path-decide/scripts/check_task_briefs.py +60 -8
- package/skills/gsd-path-decide/scripts/detect_project.py +345 -15
- package/skills/gsd-path-decide/scripts/discussion_records.py +19 -13
- package/skills/gsd-path-decide/scripts/discussion_validate.py +66 -21
- package/skills/gsd-path-decide/scripts/integration.py +434 -24
- package/skills/gsd-path-decide/scripts/isolation.py +1077 -28
- package/skills/gsd-path-decide/scripts/loop_run.py +20 -30
- package/skills/gsd-path-decide/scripts/members.py +704 -0
- package/skills/gsd-path-decide/scripts/path_config.py +2 -2
- package/skills/gsd-path-decide/scripts/pipeline_git.py +61 -22
- package/skills/gsd-path-decide/scripts/pipeline_state.py +176 -54
- 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 +140 -31
- package/skills/gsd-path-decide/scripts/state_promote.py +2 -0
- package/skills/gsd-path-decide/scripts/worktree_paths.py +18 -8
- package/skills/gsd-path-define/SKILL.md +8 -1
- package/skills/gsd-path-define/references/operating-rules.md +214 -0
- package/skills/gsd-path-define/scripts/_common.py +472 -19
- package/skills/gsd-path-define/scripts/archive_milestone.py +146 -73
- package/skills/gsd-path-define/scripts/build_recovery.py +4 -1
- package/skills/gsd-path-define/scripts/check_handoffs.py +116 -20
- package/skills/gsd-path-define/scripts/check_task_briefs.py +60 -8
- package/skills/gsd-path-define/scripts/detect_project.py +345 -15
- package/skills/gsd-path-define/scripts/discussion_records.py +19 -13
- package/skills/gsd-path-define/scripts/discussion_validate.py +66 -21
- package/skills/gsd-path-define/scripts/integration.py +434 -24
- package/skills/gsd-path-define/scripts/isolation.py +1077 -28
- package/skills/gsd-path-define/scripts/loop_run.py +20 -30
- package/skills/gsd-path-define/scripts/members.py +704 -0
- package/skills/gsd-path-define/scripts/path_config.py +2 -2
- package/skills/gsd-path-define/scripts/pipeline_git.py +61 -22
- package/skills/gsd-path-define/scripts/pipeline_state.py +176 -54
- 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 +140 -31
- package/skills/gsd-path-define/scripts/state_promote.py +2 -0
- package/skills/gsd-path-define/scripts/worktree_paths.py +18 -8
- 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 +472 -19
- package/skills/gsd-path-discuss/scripts/discussion_records.py +19 -13
- package/skills/gsd-path-discuss/scripts/loop_run.py +20 -30
- package/skills/gsd-path-discuss/scripts/path_config.py +2 -2
- package/skills/gsd-path-discuss/scripts/review_panel.py +1 -1
- package/skills/gsd-path-discuss/scripts/worktree_paths.py +18 -8
- package/skills/gsd-path-docs-audit/SKILL.md +6 -4
- package/skills/gsd-path-docs-audit/references/docs-auditor.md +2 -1
- package/skills/gsd-path-docs-audit/references/operating-rules.md +214 -0
- package/skills/gsd-path-docs-audit/scripts/_common.py +472 -19
- package/skills/gsd-path-docs-audit/scripts/archive_milestone.py +146 -73
- package/skills/gsd-path-docs-audit/scripts/build_recovery.py +4 -1
- package/skills/gsd-path-docs-audit/scripts/check_docs_audit.py +14 -3
- package/skills/gsd-path-docs-audit/scripts/check_handoffs.py +116 -20
- package/skills/gsd-path-docs-audit/scripts/check_task_briefs.py +60 -8
- package/skills/gsd-path-docs-audit/scripts/detect_project.py +345 -15
- package/skills/gsd-path-docs-audit/scripts/discussion_records.py +19 -13
- package/skills/gsd-path-docs-audit/scripts/discussion_validate.py +66 -21
- package/skills/gsd-path-docs-audit/scripts/integration.py +434 -24
- package/skills/gsd-path-docs-audit/scripts/isolation.py +1077 -28
- package/skills/gsd-path-docs-audit/scripts/loop_run.py +20 -30
- package/skills/gsd-path-docs-audit/scripts/members.py +704 -0
- package/skills/gsd-path-docs-audit/scripts/path_config.py +2 -2
- package/skills/gsd-path-docs-audit/scripts/pipeline_git.py +61 -22
- package/skills/gsd-path-docs-audit/scripts/pipeline_state.py +176 -54
- 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 +140 -31
- package/skills/gsd-path-docs-audit/scripts/state_promote.py +2 -0
- package/skills/gsd-path-docs-audit/scripts/worktree_paths.py +18 -8
- package/skills/gsd-path-docs-audit/templates/docs-audit.md +1 -1
- 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 +472 -19
- package/skills/gsd-path-forensics/scripts/discussion_records.py +19 -13
- package/skills/gsd-path-forensics/scripts/loop_run.py +20 -30
- package/skills/gsd-path-forensics/scripts/path_config.py +2 -2
- package/skills/gsd-path-forensics/scripts/pipeline_diagnose.py +82 -31
- package/skills/gsd-path-forensics/scripts/pipeline_undo.py +117 -22
- package/skills/gsd-path-forensics/scripts/review_panel.py +1 -1
- package/skills/gsd-path-forensics/scripts/worktree_paths.py +18 -8
- 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/docs-auditor.md +2 -1
- package/skills/gsd-path-inspect/references/operating-rules.md +214 -0
- package/skills/gsd-path-inspect/scripts/__pycache__/_common.cpython-312.pyc +0 -0
- package/skills/gsd-path-inspect/scripts/_common.py +472 -19
- package/skills/gsd-path-inspect/scripts/archive_milestone.py +146 -73
- package/skills/gsd-path-inspect/scripts/build_recovery.py +4 -1
- package/skills/gsd-path-inspect/scripts/check_docs_audit.py +14 -3
- package/skills/gsd-path-inspect/scripts/check_handoffs.py +116 -20
- package/skills/gsd-path-inspect/scripts/check_task_briefs.py +60 -8
- package/skills/gsd-path-inspect/scripts/detect_project.py +345 -15
- package/skills/gsd-path-inspect/scripts/discussion_records.py +19 -13
- package/skills/gsd-path-inspect/scripts/discussion_validate.py +66 -21
- package/skills/gsd-path-inspect/scripts/integration.py +434 -24
- package/skills/gsd-path-inspect/scripts/isolation.py +1077 -28
- package/skills/gsd-path-inspect/scripts/loop_run.py +20 -30
- package/skills/gsd-path-inspect/scripts/members.py +704 -0
- package/skills/gsd-path-inspect/scripts/path_config.py +2 -2
- package/skills/gsd-path-inspect/scripts/pipeline_git.py +61 -22
- package/skills/gsd-path-inspect/scripts/pipeline_state.py +176 -54
- 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 +140 -31
- package/skills/gsd-path-inspect/scripts/state_promote.py +2 -0
- package/skills/gsd-path-inspect/scripts/workflow_run.py +103 -29
- package/skills/gsd-path-inspect/scripts/worktree_paths.py +18 -8
- package/skills/gsd-path-inspect/templates/codebase.md +1 -1
- package/skills/gsd-path-inspect/templates/docs-audit.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 +472 -19
- package/skills/gsd-path-loop/scripts/discussion_records.py +19 -13
- package/skills/gsd-path-loop/scripts/loop_run.py +20 -30
- package/skills/gsd-path-loop/scripts/path_config.py +2 -2
- package/skills/gsd-path-loop/scripts/review_panel.py +1 -1
- package/skills/gsd-path-loop/scripts/worktree_paths.py +18 -8
- 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 +472 -19
- 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 +20 -30
- package/skills/gsd-path-migrate/scripts/migrate_core.py +2 -2
- package/skills/gsd-path-migrate/scripts/path_config.py +2 -2
- package/skills/gsd-path-migrate/scripts/review_panel.py +1 -1
- package/skills/gsd-path-plan/SKILL.md +7 -1
- package/skills/gsd-path-plan/references/operating-rules.md +214 -0
- package/skills/gsd-path-plan/references/planner.md +8 -0
- package/skills/gsd-path-plan/scripts/__pycache__/_common.cpython-312.pyc +0 -0
- package/skills/gsd-path-plan/scripts/_common.py +472 -19
- package/skills/gsd-path-plan/scripts/archive_milestone.py +146 -73
- package/skills/gsd-path-plan/scripts/build_recovery.py +4 -1
- package/skills/gsd-path-plan/scripts/check_handoffs.py +116 -20
- package/skills/gsd-path-plan/scripts/check_task_briefs.py +60 -8
- package/skills/gsd-path-plan/scripts/detect_project.py +345 -15
- package/skills/gsd-path-plan/scripts/discussion_records.py +19 -13
- package/skills/gsd-path-plan/scripts/discussion_validate.py +66 -21
- package/skills/gsd-path-plan/scripts/integration.py +434 -24
- package/skills/gsd-path-plan/scripts/isolation.py +1077 -28
- package/skills/gsd-path-plan/scripts/loop_run.py +20 -30
- package/skills/gsd-path-plan/scripts/members.py +704 -0
- package/skills/gsd-path-plan/scripts/path_config.py +2 -2
- package/skills/gsd-path-plan/scripts/pipeline_git.py +61 -22
- package/skills/gsd-path-plan/scripts/pipeline_state.py +176 -54
- 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 +140 -31
- package/skills/gsd-path-plan/scripts/state_promote.py +2 -0
- package/skills/gsd-path-plan/scripts/workflow_run.py +103 -29
- package/skills/gsd-path-plan/scripts/worktree_paths.py +18 -8
- package/skills/gsd-path-plan/templates/task.md +1 -0
- package/skills/gsd-path-research/SKILL.md +2 -1
- package/skills/gsd-path-research/references/operating-rules.md +214 -0
- package/skills/gsd-path-research/scripts/_common.py +472 -19
- package/skills/gsd-path-research/scripts/archive_milestone.py +146 -73
- package/skills/gsd-path-research/scripts/build_recovery.py +4 -1
- package/skills/gsd-path-research/scripts/check_handoffs.py +116 -20
- package/skills/gsd-path-research/scripts/check_task_briefs.py +60 -8
- package/skills/gsd-path-research/scripts/detect_project.py +345 -15
- package/skills/gsd-path-research/scripts/discussion_records.py +19 -13
- package/skills/gsd-path-research/scripts/discussion_validate.py +66 -21
- package/skills/gsd-path-research/scripts/integration.py +434 -24
- package/skills/gsd-path-research/scripts/isolation.py +1077 -28
- package/skills/gsd-path-research/scripts/loop_run.py +20 -30
- package/skills/gsd-path-research/scripts/members.py +704 -0
- package/skills/gsd-path-research/scripts/path_config.py +2 -2
- package/skills/gsd-path-research/scripts/pipeline_git.py +61 -22
- package/skills/gsd-path-research/scripts/pipeline_state.py +176 -54
- 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 +140 -31
- package/skills/gsd-path-research/scripts/state_promote.py +2 -0
- package/skills/gsd-path-research/scripts/worktree_paths.py +18 -8
- package/skills/gsd-path-roadmap/SKILL.md +2 -1
- package/skills/gsd-path-roadmap/references/operating-rules.md +214 -0
- package/skills/gsd-path-roadmap/scripts/_common.py +472 -19
- package/skills/gsd-path-roadmap/scripts/archive_milestone.py +146 -73
- package/skills/gsd-path-roadmap/scripts/build_recovery.py +4 -1
- package/skills/gsd-path-roadmap/scripts/check_handoffs.py +116 -20
- package/skills/gsd-path-roadmap/scripts/check_task_briefs.py +60 -8
- package/skills/gsd-path-roadmap/scripts/detect_project.py +345 -15
- package/skills/gsd-path-roadmap/scripts/discussion_records.py +19 -13
- package/skills/gsd-path-roadmap/scripts/discussion_validate.py +66 -21
- package/skills/gsd-path-roadmap/scripts/integration.py +434 -24
- package/skills/gsd-path-roadmap/scripts/isolation.py +1077 -28
- package/skills/gsd-path-roadmap/scripts/loop_run.py +20 -30
- package/skills/gsd-path-roadmap/scripts/members.py +704 -0
- package/skills/gsd-path-roadmap/scripts/path_config.py +2 -2
- package/skills/gsd-path-roadmap/scripts/pipeline_git.py +61 -22
- package/skills/gsd-path-roadmap/scripts/pipeline_state.py +176 -54
- 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 +140 -31
- package/skills/gsd-path-roadmap/scripts/state_promote.py +2 -0
- package/skills/gsd-path-roadmap/scripts/worktree_paths.py +18 -8
- package/skills/gsd-path-ship/SKILL.md +27 -10
- package/skills/gsd-path-ship/references/operating-rules.md +214 -0
- package/skills/gsd-path-ship/references/reviewer-wave.md +3 -1
- package/skills/gsd-path-ship/scripts/__pycache__/_common.cpython-312.pyc +0 -0
- package/skills/gsd-path-ship/scripts/_common.py +472 -19
- package/skills/gsd-path-ship/scripts/archive_milestone.py +146 -73
- package/skills/gsd-path-ship/scripts/build_recovery.py +4 -1
- package/skills/gsd-path-ship/scripts/build_state.py +66 -23
- package/skills/gsd-path-ship/scripts/check_handoffs.py +116 -20
- package/skills/gsd-path-ship/scripts/check_task_briefs.py +60 -8
- package/skills/gsd-path-ship/scripts/detect_project.py +345 -15
- package/skills/gsd-path-ship/scripts/discussion_records.py +19 -13
- package/skills/gsd-path-ship/scripts/discussion_validate.py +66 -21
- package/skills/gsd-path-ship/scripts/integration.py +434 -24
- package/skills/gsd-path-ship/scripts/isolation.py +1077 -28
- package/skills/gsd-path-ship/scripts/lean_verification.py +99 -19
- package/skills/gsd-path-ship/scripts/loop_run.py +20 -30
- package/skills/gsd-path-ship/scripts/members.py +704 -0
- package/skills/gsd-path-ship/scripts/path_config.py +2 -2
- package/skills/gsd-path-ship/scripts/pipeline_git.py +61 -22
- package/skills/gsd-path-ship/scripts/pipeline_state.py +176 -54
- 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 +140 -31
- package/skills/gsd-path-ship/scripts/state_promote.py +2 -0
- package/skills/gsd-path-ship/scripts/workflow_run.py +103 -29
- package/skills/gsd-path-ship/scripts/worktree_paths.py +18 -8
- package/skills/gsd-path-ship/templates/final-review.md +5 -2
- package/skills/gsd-path-ship/templates/gap-review.md +2 -1
- package/skills/gsd-path-ship/templates/wave-review.md +3 -1
- 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 +472 -19
- package/skills/gsd-path-undo/scripts/discussion_records.py +19 -13
- package/skills/gsd-path-undo/scripts/loop_run.py +20 -30
- package/skills/gsd-path-undo/scripts/path_config.py +2 -2
- package/skills/gsd-path-undo/scripts/pipeline_undo.py +117 -22
- package/skills/gsd-path-undo/scripts/review_panel.py +1 -1
- package/skills/gsd-path-undo/scripts/worktree_paths.py +18 -8
- package/skills/path/BUILD.md +7 -1
- package/skills/path/DECIDE.md +11 -4
- package/skills/path/DEFINE.md +8 -1
- package/skills/path/DOCS-AUDIT.md +6 -4
- package/skills/path/INSPECT.md +5 -4
- package/skills/path/PLAN.md +7 -1
- package/skills/path/RESEARCH.md +2 -1
- package/skills/path/ROADMAP.md +2 -1
- package/skills/path/SHIP.md +27 -10
- package/skills/path/SKILL.md +45 -1
- package/skills/path/references/build-native.md +47 -14
- package/skills/path/references/codebase-mapper.md +2 -1
- package/skills/path/references/docs-auditor.md +2 -1
- package/skills/path/references/operating-rules.md +214 -0
- package/skills/path/references/planner.md +8 -0
- package/skills/path/references/reviewer-wave.md +3 -1
- package/skills/path/scripts/_common.py +472 -19
- package/skills/path/scripts/archive_milestone.py +146 -73
- package/skills/path/scripts/bootstrap_repository.py +8 -5
- package/skills/path/scripts/build_recovery.py +4 -1
- package/skills/path/scripts/build_state.py +66 -23
- package/skills/path/scripts/check_docs_audit.py +14 -3
- package/skills/path/scripts/check_handoffs.py +116 -20
- package/skills/path/scripts/check_task_briefs.py +60 -8
- package/skills/path/scripts/check_update.py +2 -2
- package/skills/path/scripts/detect_project.py +345 -15
- package/skills/path/scripts/discussion_records.py +19 -13
- package/skills/path/scripts/discussion_validate.py +66 -21
- package/skills/path/scripts/dispatch_driver.py +111 -26
- package/skills/path/scripts/git_guard.py +116 -29
- package/skills/path/scripts/integration.py +434 -24
- package/skills/path/scripts/isolation.py +1077 -28
- package/skills/path/scripts/lean_verification.py +99 -19
- package/skills/path/scripts/loop_run.py +20 -30
- package/skills/path/scripts/members.py +704 -0
- package/skills/path/scripts/path_config.py +2 -2
- package/skills/path/scripts/pipeline_git.py +61 -22
- package/skills/path/scripts/pipeline_state.py +176 -54
- 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 +140 -31
- package/skills/path/scripts/state_promote.py +2 -0
- package/skills/path/scripts/status_runtime.py +36 -6
- package/skills/path/scripts/token_budget.py +12 -8
- package/skills/path/scripts/workflow_run.py +103 -29
- package/skills/path/scripts/worktree_paths.py +18 -8
- package/skills/path/templates/codebase.md +1 -1
- package/skills/path/templates/docs-audit.md +1 -1
- package/skills/path/templates/final-review.md +5 -2
- package/skills/path/templates/gap-review.md +2 -1
- package/skills/path/templates/task.md +1 -0
- package/skills/path/templates/wave-review.md +3 -1
|
@@ -19,8 +19,6 @@ import hashlib
|
|
|
19
19
|
import json
|
|
20
20
|
import os
|
|
21
21
|
import re
|
|
22
|
-
import shlex
|
|
23
|
-
import signal
|
|
24
22
|
import subprocess
|
|
25
23
|
import sys
|
|
26
24
|
import tempfile
|
|
@@ -170,12 +168,7 @@ def child_running(state: Dict[str, object]) -> bool:
|
|
|
170
168
|
return state.get("finished_at") is None and bool(state.get("pid")) and process_alive(int(state["pid"]))
|
|
171
169
|
|
|
172
170
|
|
|
173
|
-
|
|
174
|
-
try:
|
|
175
|
-
os.kill(pid, 0)
|
|
176
|
-
except ProcessLookupError:
|
|
177
|
-
return False
|
|
178
|
-
return True
|
|
171
|
+
process_alive = _common.process_alive
|
|
179
172
|
|
|
180
173
|
|
|
181
174
|
# --- child process ---------------------------------------------------------
|
|
@@ -208,13 +201,13 @@ def child_main(state_path: Path) -> int:
|
|
|
208
201
|
attempt_dir = state_path.parent
|
|
209
202
|
with open(attempt_dir / "brief.md", "rb") as brief, \
|
|
210
203
|
open(attempt_dir / "stdout", "wb") as out, open(attempt_dir / "stderr", "wb") as err:
|
|
211
|
-
process =
|
|
212
|
-
|
|
204
|
+
process = _common.popen_group(_common.resolve_argv(state["command"]), cwd=state["worktree"],
|
|
205
|
+
stdin=brief, stdout=out, stderr=err)
|
|
213
206
|
try:
|
|
214
207
|
exit_code: Optional[int] = process.wait(timeout=state.get("child_timeout"))
|
|
215
208
|
timed_out = False
|
|
216
209
|
except subprocess.TimeoutExpired:
|
|
217
|
-
|
|
210
|
+
_common.kill_tree(process)
|
|
218
211
|
process.wait()
|
|
219
212
|
exit_code, timed_out = None, True
|
|
220
213
|
save_state(attempt_dir / "exit.json",
|
|
@@ -224,6 +217,7 @@ def child_main(state_path: Path) -> int:
|
|
|
224
217
|
|
|
225
218
|
def brief_text(state: Dict[str, object], role_brief: Path, task_template: Path) -> str:
|
|
226
219
|
worktree = Path(str(state["worktree"]))
|
|
220
|
+
project_root = Path(str(state.get("project_root") or worktree))
|
|
227
221
|
task_id = state["task_id"]
|
|
228
222
|
agents = worktree / "AGENTS.md"
|
|
229
223
|
workflow = worktree / "WORKFLOW.md"
|
|
@@ -234,12 +228,14 @@ def brief_text(state: Dict[str, object], role_brief: Path, task_template: Path)
|
|
|
234
228
|
f"Work only in this worktree root: {worktree}",
|
|
235
229
|
f"Task file: {worktree / str(state['task_file'])}",
|
|
236
230
|
f"Task template: {task_template}",
|
|
237
|
-
f"INTENT.md: {
|
|
231
|
+
f"INTENT.md: {project_root / '.project/intent/INTENT.md'}",
|
|
238
232
|
f"AGENTS.md: {agents if agents.exists() else 'absent'}",
|
|
239
233
|
f"WORKFLOW.md: {workflow if workflow.exists() else 'absent'}",
|
|
240
234
|
f"Recorded base: {state['base']}",
|
|
241
235
|
f"Dispatch mode: {state['mode']} ("
|
|
242
236
|
+ ("the primary worktree on the bound branch" if state["mode"] == "serial"
|
|
237
|
+
else f"an isolated worktree of member {state['member']}; never touch the member team's "
|
|
238
|
+
"checkout or the coordinator" if state["mode"] == "member"
|
|
243
239
|
else "an isolated task worktree; never touch the primary") + ").",
|
|
244
240
|
"Next consumer: the build orchestrator reruns Verify in an isolated checkout and lands "
|
|
245
241
|
"the task. Gate: Verify passes and only the task's declared files plus its Log changed.",
|
|
@@ -248,7 +244,7 @@ def brief_text(state: Dict[str, object], role_brief: Path, task_template: Path)
|
|
|
248
244
|
if state.get("answered"):
|
|
249
245
|
lines.append(f"The task Log now records an `{ANSWER_MARK}` to your earlier question; "
|
|
250
246
|
"continue from it.")
|
|
251
|
-
lines.append(task_context.render(
|
|
247
|
+
lines.append(task_context.render(project_root, worktree / str(state['task_file'])))
|
|
252
248
|
return "\n".join(lines) + "\n"
|
|
253
249
|
|
|
254
250
|
|
|
@@ -282,7 +278,7 @@ def selected_command(state: Dict[str, object], options: argparse.Namespace, comm
|
|
|
282
278
|
if caps_path is None:
|
|
283
279
|
if overrides or previous or model_policy.policy_path(primary, project_dir).exists():
|
|
284
280
|
raise model_policy.PolicyError('model policy requires --model-capabilities for this dispatch')
|
|
285
|
-
return
|
|
281
|
+
return _common.split_command(command), None
|
|
286
282
|
caps = model_policy.read_json(caps_path)
|
|
287
283
|
action = getattr(options, 'action', 'round')
|
|
288
284
|
role = {'round': 'coder', 'review': 'reviewer', 'panel': 'review_panel',
|
|
@@ -297,7 +293,7 @@ def selected_command(state: Dict[str, object], options: argparse.Namespace, comm
|
|
|
297
293
|
dict(overrides, model=state['slug']), previous)
|
|
298
294
|
model_policy.validate_panel(selection, state['family'], state.get('excluded_families', []))
|
|
299
295
|
state['slug'] = selection['selected']['model']
|
|
300
|
-
return model_policy.command_args(
|
|
296
|
+
return model_policy.command_args(_common.split_command(command), selection), selection
|
|
301
297
|
|
|
302
298
|
|
|
303
299
|
def retain_selection(root: Path, state: Dict[str, object]) -> Dict[str, object]:
|
|
@@ -340,12 +336,12 @@ def spawn(root: Path, state: Dict[str, object], options: argparse.Namespace,
|
|
|
340
336
|
"child_timeout": options.child_timeout, "outcome": None,
|
|
341
337
|
"dispatched_at": now(), "origin": "question" if state.get("answered") else "dispatch"})
|
|
342
338
|
state_path = attempt_dir / "state.json"
|
|
343
|
-
(attempt_dir / "brief.md").
|
|
339
|
+
(attempt_dir / "brief.md").write_bytes(brief(state).encode("utf-8"))
|
|
344
340
|
save_state(state_path, state)
|
|
345
|
-
wrapper =
|
|
341
|
+
wrapper = _common.popen_detached(
|
|
346
342
|
[sys.executable, "-B", str(Path(__file__).resolve()), "_child", "--state", str(state_path)],
|
|
347
343
|
cwd=state["worktree"], stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL,
|
|
348
|
-
stderr=subprocess.DEVNULL,
|
|
344
|
+
stderr=subprocess.DEVNULL,
|
|
349
345
|
)
|
|
350
346
|
state["_path"] = str(state_path)
|
|
351
347
|
update_state(state, pid=wrapper.pid)
|
|
@@ -356,8 +352,11 @@ def spawn(root: Path, state: Dict[str, object], options: argparse.Namespace,
|
|
|
356
352
|
|
|
357
353
|
|
|
358
354
|
def log_delta(primary: Path, state: Dict[str, object]) -> str:
|
|
359
|
-
|
|
355
|
+
contract_file = state.get("contract_file") or state["task_file"]
|
|
356
|
+
base_text = isolation.git_text(primary, "show", f"{state['base']}:{contract_file}")
|
|
360
357
|
text = (Path(str(state["worktree"])) / str(state["task_file"])).read_text(encoding="utf-8")
|
|
358
|
+
if state["mode"] == "member":
|
|
359
|
+
return isolation.member_log_delta(base_text, text)
|
|
361
360
|
return isolation.task_log_delta(base_text, text)
|
|
362
361
|
|
|
363
362
|
|
|
@@ -374,14 +373,14 @@ def snapshot_tree(primary: Path) -> str:
|
|
|
374
373
|
env = dict(os.environ, GIT_INDEX_FILE=str(Path(temporary) / "index"))
|
|
375
374
|
for arguments in (("read-tree", "HEAD"), ("add", "-A"), ("write-tree",)):
|
|
376
375
|
completed = subprocess.run(("git", "-C", str(primary), *arguments), env=env,
|
|
377
|
-
|
|
376
|
+
encoding="utf-8", errors="replace", capture_output=True)
|
|
378
377
|
if completed.returncode:
|
|
379
378
|
raise DriverStop(f"git {' '.join(arguments)} failed: {completed.stderr.strip()}")
|
|
380
379
|
return completed.stdout.strip()
|
|
381
380
|
|
|
382
381
|
|
|
383
382
|
def run_verify(command: str, cwd: Path) -> Dict[str, object]:
|
|
384
|
-
completed = _common.run_command(
|
|
383
|
+
completed = _common.run_command(*_common.bash_argv(command), cwd=cwd)
|
|
385
384
|
return {"exit_code": completed.returncode, "stdout": completed.stdout, "stderr": completed.stderr}
|
|
386
385
|
|
|
387
386
|
|
|
@@ -394,6 +393,30 @@ def state_from_task(primary: Path, task_id: str) -> Dict[str, object]:
|
|
|
394
393
|
break
|
|
395
394
|
else:
|
|
396
395
|
raise DriverStop(f"task {task_id} has no task file")
|
|
396
|
+
member = fields.get("repo")
|
|
397
|
+
if member:
|
|
398
|
+
# A member activation lives in the live copy inside its member sidecar.
|
|
399
|
+
try:
|
|
400
|
+
checkout, project, _ = isolation._member_context(primary, str(member))
|
|
401
|
+
except isolation.IsolationError as error:
|
|
402
|
+
raise DriverStop(str(error), task=task_id) from error
|
|
403
|
+
task_file = task_path.relative_to(primary).as_posix()
|
|
404
|
+
sidecar = isolation.sidecar_root(checkout, "task", f"{project}-{task_id}").resolve()
|
|
405
|
+
copy = isolation.member_task_copy(sidecar, task_file)
|
|
406
|
+
live, _ = isolation.task_frontmatter(copy.read_text(encoding="utf-8")) if copy.is_file() else ({}, None)
|
|
407
|
+
if not live or live.get("status") != "in-progress" or not live.get("base") or not live.get("member_base"):
|
|
408
|
+
raise DriverStop(f"member task {task_id} has no activated live copy in {sidecar}", task=task_id)
|
|
409
|
+
return {"task_id": task_id, "title": str(live.get("title")), "task_file": copy.relative_to(sidecar).as_posix(),
|
|
410
|
+
"contract_file": task_file, "files": list(live.get("files") or []), "base": str(live["base"]),
|
|
411
|
+
"worktree": str(sidecar), "task_branch": f"{isolation.TASK_BRANCH_PREFIX}{project}-{task_id}",
|
|
412
|
+
"mode": "member", "member": str(member), "member_base": str(live["member_base"]),
|
|
413
|
+
"project_root": str(primary), "sidecar": None}
|
|
414
|
+
if fields.get("status") != "in-progress" or not fields.get("base"):
|
|
415
|
+
# A parallel activation lives only in its isolate; the primary copy stays pending.
|
|
416
|
+
isolate = isolation.sidecar_root(primary, "task", task_id).resolve()
|
|
417
|
+
if isolation.authorized_task_worktree(isolate, isolation.require_bound(primary)):
|
|
418
|
+
fields, _ = isolation.task_frontmatter(
|
|
419
|
+
(isolate / task_path.relative_to(primary)).read_text(encoding="utf-8"))
|
|
397
420
|
if fields.get("status") != "in-progress" or not fields.get("base"):
|
|
398
421
|
raise DriverStop(f"task {task_id} is not an in-progress task with a recorded base")
|
|
399
422
|
def value(key: str) -> Optional[str]:
|
|
@@ -453,7 +476,21 @@ def finish_task(primary: Path, state: Dict[str, object]) -> Dict[str, object]:
|
|
|
453
476
|
if not passed:
|
|
454
477
|
if state["mode"] == "parallel":
|
|
455
478
|
isolation.deactivate_task(worktree, task_id, str(state["task_branch"]))
|
|
479
|
+
elif state["mode"] == "member":
|
|
480
|
+
isolation.deactivate_member_task(primary, str(state["member"]), task_id)
|
|
456
481
|
raise DriverStop("Verify failed in the isolate", task=task_id, execution=execution)
|
|
482
|
+
if state["mode"] == "member":
|
|
483
|
+
member = str(state["member"])
|
|
484
|
+
landed = isolation.land_member(primary, member, task_id, str(state["title"]),
|
|
485
|
+
str(state["contract_file"]), base, str(state["member_base"]))
|
|
486
|
+
landing = str(landed["landing"])
|
|
487
|
+
# Only a landing whose parent is the member base proves the verified member tree.
|
|
488
|
+
ledger = isolation.git_output(worktree, "rev-parse", f"{landing}^") == str(state["member_base"])
|
|
489
|
+
if ledger:
|
|
490
|
+
build_state.verify_record(str(primary), command, landing, "pass", execution=execution, member=member)
|
|
491
|
+
isolation.retire_member_task(primary, member, task_id)
|
|
492
|
+
return {"task": task_id, "commit": str(landed["commit"]), "mode": "member",
|
|
493
|
+
"landing": landing, "verify": execution, "ledger": ledger}
|
|
457
494
|
landed = isolation.land(primary, worktree, base, task_id, str(state["title"]), task_file,
|
|
458
495
|
list(state["files"]))
|
|
459
496
|
commit = str(landed["commit"])
|
|
@@ -485,7 +522,8 @@ def recover_report(primary: Path, project_dir: str, receipt: Dict[str, object])
|
|
|
485
522
|
|
|
486
523
|
def checkpoint_project(primary: Path, receipt: Dict[str, object], subject: str, body: str) -> Optional[str]:
|
|
487
524
|
"""Commit .project bookkeeping through the canonical checkpoint; None when nothing is dirty."""
|
|
488
|
-
if not any(path.startswith(".project/") for path in isolation.uncommitted_paths(primary))
|
|
525
|
+
if not any(path.startswith(".project/") for path in isolation.uncommitted_paths(primary)) \
|
|
526
|
+
and not isolation.ignored_legacy_ledger(primary):
|
|
489
527
|
return None
|
|
490
528
|
result = isolation.checkpoint(primary, isolation.current_sha(primary), subject, body, [".project"])
|
|
491
529
|
receipt["steps"].append({"script": "isolation.py checkpoint", "result": result})
|
|
@@ -582,7 +620,7 @@ class Round:
|
|
|
582
620
|
"""Run the bundled token_budget.py against this milestone's ledger; blocked is a stop."""
|
|
583
621
|
command = [sys.executable, "-B", str(Path(__file__).resolve().parent / "token_budget.py"),
|
|
584
622
|
action, "--ledger", str(budget_ledger(self.primary)), *arguments]
|
|
585
|
-
completed = subprocess.run(command, cwd=self.primary, capture_output=True,
|
|
623
|
+
completed = subprocess.run(command, cwd=self.primary, capture_output=True, encoding="utf-8", errors="replace")
|
|
586
624
|
result = json.loads(completed.stdout) if completed.stdout.strip() else {}
|
|
587
625
|
self.receipt["steps"].append({"script": f"token_budget.py {action}", "command": command,
|
|
588
626
|
"exit_code": completed.returncode, "result": result,
|
|
@@ -605,12 +643,24 @@ class Round:
|
|
|
605
643
|
# recovery -------------------------------------------------------------
|
|
606
644
|
|
|
607
645
|
def recover(self) -> None:
|
|
646
|
+
# A journaled member landing is safe to finish; it never lands the same work twice.
|
|
647
|
+
journals = isolation.common_git_dir(self.primary).joinpath(*isolation.MEMBER_LANDING_DIR)
|
|
648
|
+
retired_members = set()
|
|
649
|
+
for journal in sorted(journals.glob("*.json")) if journals.is_dir() else []:
|
|
650
|
+
result = isolation.recover_member_landing(self.primary, journal.stem)
|
|
651
|
+
self.receipt["steps"].append({"script": "isolation.recover_member_landing", "task": journal.stem,
|
|
652
|
+
"result": result})
|
|
653
|
+
if result["state"] == "landed":
|
|
654
|
+
isolation.retire_member_task(self.primary, str(result["member"]), journal.stem)
|
|
655
|
+
retired_members.add(journal.stem)
|
|
608
656
|
report = recover_report(self.primary, self.project_dir, self.receipt)
|
|
609
657
|
for task in report["tasks"]:
|
|
610
658
|
worktree = task.get("worktree")
|
|
611
659
|
verdict = task["verdict"]
|
|
612
660
|
if verdict in ("recovered", "attested"):
|
|
613
661
|
self.proven[str(task.get("task_id"))] = str(task.get("commit"))
|
|
662
|
+
if verdict == "recovered" and task.get("member") and task.get("task_id") not in retired_members:
|
|
663
|
+
isolation.retire_member_task(self.primary, str(task["member"]), str(task["task_id"]))
|
|
614
664
|
if verdict == "recovered" and worktree and worktree["clean"] and task.get("task_branch"):
|
|
615
665
|
isolation.retire(self.primary, Path(str(worktree["path"])),
|
|
616
666
|
str(task["task_branch"]), False)
|
|
@@ -730,6 +780,8 @@ class Round:
|
|
|
730
780
|
if state.get("wave") != self.receipt["wave"]:
|
|
731
781
|
raise DriverStop("task is outside the requested wave", task=state["task_id"],
|
|
732
782
|
wave=state.get("wave"), requested_wave=self.receipt["wave"])
|
|
783
|
+
if state.get("mode") == "member":
|
|
784
|
+
isolation.ensure_member_hooks(self.primary, str(state["member"]), str(state["task_id"]))
|
|
733
785
|
fresh = spawn(self.root, state, self.options,
|
|
734
786
|
lambda fresh: brief_text(fresh, self.options.role_brief, self.options.task_template))
|
|
735
787
|
self.receipt["dispatched"].append(self.summary(fresh))
|
|
@@ -805,6 +857,28 @@ class Round:
|
|
|
805
857
|
self.runner("lint-round", head)
|
|
806
858
|
round_size = len(selected) + len(in_flight)
|
|
807
859
|
for task in selected:
|
|
860
|
+
if task.get("repo"):
|
|
861
|
+
member = str(task["repo"])
|
|
862
|
+
retained = isolation.retained_member_task(self.primary, member, task["id"],
|
|
863
|
+
task["task_file"], head)
|
|
864
|
+
if retained and retained["state"] == "unused":
|
|
865
|
+
isolation.retire_member_task(self.primary, member, task["id"])
|
|
866
|
+
retained = None
|
|
867
|
+
if retained:
|
|
868
|
+
isolate, active = retained["isolate"], retained["active"]
|
|
869
|
+
else:
|
|
870
|
+
isolate = isolation.isolate_member_task(self.primary, member, task["id"])
|
|
871
|
+
active = isolation.activate_member_task(self.primary, member, task["id"],
|
|
872
|
+
f"build_{task['id'].lower()}", task["task_file"], head)
|
|
873
|
+
sidecar_path = Path(str(active["worktree"]))
|
|
874
|
+
self.launch({"task_id": task["id"], "title": task["title"],
|
|
875
|
+
"task_file": Path(str(active["copy"])).relative_to(sidecar_path).as_posix(),
|
|
876
|
+
"contract_file": task["task_file"], "files": task["files"], "wave": task["wave"],
|
|
877
|
+
"verify_heavy": task["verify_heavy"], "base": head, "worktree": str(sidecar_path),
|
|
878
|
+
"task_branch": isolate["task_branch"], "mode": "member", "member": member,
|
|
879
|
+
"member_base": isolate["member_base"], "project_root": str(self.primary),
|
|
880
|
+
"sidecar": None, "answered": False, "model_selection": task['model_selection']})
|
|
881
|
+
continue
|
|
808
882
|
prepared = self.runner("prepare-task", head, task["id"], round_size)
|
|
809
883
|
isolate = prepared[0]["result"]
|
|
810
884
|
sidecar = prepared[1]["result"] if len(prepared) > 1 else None
|
|
@@ -1178,7 +1252,7 @@ class Review:
|
|
|
1178
1252
|
def helper_json(receipt: Dict[str, object], script: str, *arguments: str, cwd: Path) -> Dict[str, object]:
|
|
1179
1253
|
"""Run a bundled helper and return its JSON stdout; a non-zero exit is a typed stop."""
|
|
1180
1254
|
command = [sys.executable, "-B", str(Path(__file__).resolve().parent / script), *arguments]
|
|
1181
|
-
completed = subprocess.run(command, cwd=cwd, capture_output=True,
|
|
1255
|
+
completed = subprocess.run(command, cwd=cwd, capture_output=True, encoding="utf-8", errors="replace")
|
|
1182
1256
|
step = {"script": script, "command": command, "exit_code": completed.returncode,
|
|
1183
1257
|
"stdout": completed.stdout, "stderr": completed.stderr}
|
|
1184
1258
|
receipt["steps"].append(step)
|
|
@@ -1746,7 +1820,7 @@ Heavy: {'yes' if heavy else 'no'}
|
|
|
1746
1820
|
receipt["plan_wave"] = fix_wave
|
|
1747
1821
|
lint = subprocess.run([sys.executable, "-B", str(Path(__file__).resolve().parent / "check_task_briefs.py"),
|
|
1748
1822
|
"--repo", str(primary), "--base", isolation.current_sha(primary),
|
|
1749
|
-
"--tasks-dir", f"{options.project_dir}/tasks"], capture_output=True,
|
|
1823
|
+
"--tasks-dir", f"{options.project_dir}/tasks"], capture_output=True, encoding="utf-8", errors="replace")
|
|
1750
1824
|
receipt["steps"].append({"script": "check_task_briefs.py", "exit_code": lint.returncode,
|
|
1751
1825
|
"stdout": lint.stdout, "stderr": lint.stderr})
|
|
1752
1826
|
if lint.returncode:
|
|
@@ -1981,6 +2055,17 @@ def main(argv=None) -> int:
|
|
|
1981
2055
|
current.recover()
|
|
1982
2056
|
records = [state for state in latest_states(current.root)
|
|
1983
2057
|
if state["task_id"] == arguments.task_id]
|
|
2058
|
+
native = None
|
|
2059
|
+
if records and records[0].get("outcome") is not None:
|
|
2060
|
+
# A settled driver record at an older base is superseded by a native retry.
|
|
2061
|
+
try:
|
|
2062
|
+
native = state_from_task(primary, arguments.task_id)
|
|
2063
|
+
except DriverStop:
|
|
2064
|
+
pass
|
|
2065
|
+
if native and native["base"] != records[0].get("base"):
|
|
2066
|
+
records = []
|
|
2067
|
+
else:
|
|
2068
|
+
native = None
|
|
1984
2069
|
if arguments.task_id in current.proven:
|
|
1985
2070
|
commit = current.proven[arguments.task_id]
|
|
1986
2071
|
if records and records[0].get("outcome") is None:
|
|
@@ -1997,7 +2082,7 @@ def main(argv=None) -> int:
|
|
|
1997
2082
|
current.classify(record)
|
|
1998
2083
|
else: # a coder dispatched by hand: derive the isolate from the task frontmatter
|
|
1999
2084
|
current.receipt["landed"].append(
|
|
2000
|
-
finish_task(primary, state_from_task(primary, arguments.task_id)))
|
|
2085
|
+
finish_task(primary, native or state_from_task(primary, arguments.task_id)))
|
|
2001
2086
|
result = {**current.receipt, "status": "landed" if current.receipt["landed"] else "blocked"}
|
|
2002
2087
|
elif arguments.action == "answer":
|
|
2003
2088
|
result = answer(primary, arguments.task_id, arguments.answer)
|