@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
|
@@ -5,27 +5,45 @@ import argparse
|
|
|
5
5
|
import hashlib
|
|
6
6
|
import json
|
|
7
7
|
import os
|
|
8
|
+
import re
|
|
8
9
|
import subprocess
|
|
9
10
|
import sys
|
|
10
11
|
import tempfile
|
|
11
12
|
from pathlib import Path
|
|
12
13
|
|
|
13
14
|
try:
|
|
14
|
-
from scripts import _common
|
|
15
|
+
from scripts import _common, isolation
|
|
15
16
|
except ImportError: # bundled copy inside a skill's scripts directory
|
|
16
17
|
import _common
|
|
18
|
+
import isolation
|
|
17
19
|
|
|
18
20
|
|
|
19
21
|
class StepFailed(RuntimeError):
|
|
20
22
|
pass
|
|
21
23
|
|
|
24
|
+
|
|
25
|
+
def _table_rows(body):
|
|
26
|
+
"""Cells of a Markdown table's data rows (header and separator skipped)."""
|
|
27
|
+
lines = [line.strip() for line in (body or "").splitlines() if line.strip().startswith("|")]
|
|
28
|
+
return [[cell.strip() for cell in re.split(r"(?<!\\)\|", line.strip("|"))] for line in lines[2:]]
|
|
29
|
+
|
|
22
30
|
INSPECTION_SPECS = (("inspect_codebase", "codebase-mapper", "codebase", "evidence-codebase.md"),
|
|
23
31
|
("inspect_docs", "docs-auditor", "docs-audit", "DOCS-AUDIT.md"))
|
|
24
32
|
|
|
25
33
|
|
|
34
|
+
def _task_member(repo: Path, project_dir: str, task_id: str):
|
|
35
|
+
"""The `repo:` member a task names, or None for a coordinator task."""
|
|
36
|
+
for path in sorted((repo / project_dir / "tasks").glob(f"{task_id}-*.md")):
|
|
37
|
+
fields, error = isolation.task_frontmatter(path.read_text(encoding="utf-8"))
|
|
38
|
+
if error:
|
|
39
|
+
raise StepFailed(error)
|
|
40
|
+
return fields.get("repo")
|
|
41
|
+
return None
|
|
42
|
+
|
|
43
|
+
|
|
26
44
|
def run_workflow(repo: Path, action: str, project_dir: str, expected_head: str = None,
|
|
27
45
|
task_id: str = None, round_size: int = None, inspection: Path = None,
|
|
28
|
-
mapper_reviewed: bool = False) -> dict:
|
|
46
|
+
mapper_reviewed: bool = False, kind: str = None) -> dict:
|
|
29
47
|
steps = []
|
|
30
48
|
outputs = {}
|
|
31
49
|
scripts = Path(__file__).resolve().parent
|
|
@@ -33,7 +51,7 @@ def run_workflow(repo: Path, action: str, project_dir: str, expected_head: str =
|
|
|
33
51
|
|
|
34
52
|
def step(script, *arguments, raw=False):
|
|
35
53
|
command = [sys.executable, "-B", str(helpers / script), *arguments]
|
|
36
|
-
completed = subprocess.run(command, cwd=repo, capture_output=True,
|
|
54
|
+
completed = subprocess.run(command, cwd=repo, capture_output=True, encoding="utf-8", errors="replace")
|
|
37
55
|
receipt = {"script": script, "command": command, "exit_code": completed.returncode,
|
|
38
56
|
"stdout": completed.stdout, "stderr": completed.stderr}
|
|
39
57
|
steps.append(receipt)
|
|
@@ -50,12 +68,29 @@ def run_workflow(repo: Path, action: str, project_dir: str, expected_head: str =
|
|
|
50
68
|
return receipt["result"]
|
|
51
69
|
|
|
52
70
|
common = ["--repo", str(repo), "--project-dir", project_dir]
|
|
71
|
+
next_step = "$gsd-path-forensics"
|
|
72
|
+
|
|
73
|
+
def gate_plan():
|
|
74
|
+
if step("discussion_records.py", "pending", "--repo", str(repo))["pending"]:
|
|
75
|
+
raise StepFailed("pending discussion requires its owner disposition")
|
|
76
|
+
step("check_handoffs.py", "plan", *common)
|
|
77
|
+
head = subprocess.run(["git", "rev-parse", "--verify", "HEAD"],
|
|
78
|
+
cwd=repo, capture_output=True, encoding="utf-8", errors="replace", check=True).stdout.strip()
|
|
79
|
+
step("check_task_briefs.py", "--repo", str(repo), "--base", head,
|
|
80
|
+
"--tasks-dir", f"{project_dir}/tasks", "--project-dir", project_dir)
|
|
81
|
+
panel = ["validate-plan", "--plan", str(repo / project_dir / "plan/PLAN.md"),
|
|
82
|
+
"--intent", str(repo / project_dir / "intent/INTENT.md")]
|
|
83
|
+
charter = repo / ".project/CHARTER.md"
|
|
84
|
+
if charter.exists():
|
|
85
|
+
panel += ["--charter", str(charter)]
|
|
86
|
+
return step("review_panel.py", *panel)
|
|
87
|
+
|
|
53
88
|
try:
|
|
54
89
|
if os.path.lexists(repo / ".gsd-path/runtime.json"):
|
|
55
90
|
resolved = subprocess.run(
|
|
56
91
|
[sys.executable, "-B", str(repo / ".gsd-path/status_runtime.py"),
|
|
57
92
|
"--repo", str(repo), "--runtime-path"],
|
|
58
|
-
cwd=repo, capture_output=True,
|
|
93
|
+
cwd=repo, capture_output=True, encoding="utf-8", errors="replace")
|
|
59
94
|
if resolved.returncode:
|
|
60
95
|
sys.stderr.write(resolved.stderr)
|
|
61
96
|
raise StepFailed(resolved.stderr.strip())
|
|
@@ -71,7 +106,7 @@ def run_workflow(repo: Path, action: str, project_dir: str, expected_head: str =
|
|
|
71
106
|
(repo / project_dir / "research" / spec[3]).is_symlink() for spec in specs):
|
|
72
107
|
raise StepFailed("prior inspection evidence requires the re-inspection contract")
|
|
73
108
|
branch = subprocess.run(["git", "branch", "--show-current"], cwd=repo,
|
|
74
|
-
capture_output=True,
|
|
109
|
+
capture_output=True, encoding="utf-8", errors="replace", check=True).stdout.strip()
|
|
75
110
|
if branch != state["branch"]:
|
|
76
111
|
raise StepFailed("current branch differs from the recorded inspection branch")
|
|
77
112
|
pending = step("discussion_records.py", "pending", "--repo", str(repo))
|
|
@@ -87,7 +122,7 @@ def run_workflow(repo: Path, action: str, project_dir: str, expected_head: str =
|
|
|
87
122
|
raise StepFailed(f"missing inspection resource: {path}")
|
|
88
123
|
staging = Path(tempfile.mkdtemp(prefix="gsd-path-inspect-"))
|
|
89
124
|
inventory_file = staging / "inventory.txt"
|
|
90
|
-
inventory_file.
|
|
125
|
+
inventory_file.write_bytes(inventory.encode("utf-8"))
|
|
91
126
|
assignments = []
|
|
92
127
|
for task_name, role, template, filename in specs:
|
|
93
128
|
isolated = step("isolation.py", "isolate-verify", "--repo", str(repo),
|
|
@@ -100,13 +135,14 @@ def run_workflow(repo: Path, action: str, project_dir: str, expected_head: str =
|
|
|
100
135
|
f"Template: {template_path}\nRepository and command cwd: {isolated['worktree']}\n"
|
|
101
136
|
f"Recorded baseline and Audited HEAD: {isolated['base']}\n"
|
|
102
137
|
f"Write only: {Path(isolated['worktree']) / output}\n"
|
|
138
|
+
f"Write header Repo root: {repo}\n"
|
|
103
139
|
"Use only this supplied sidecar for project commands; do not create worktrees.\n"
|
|
104
140
|
"The parent owns gates, collection, retirement, and phase state.\n"
|
|
105
141
|
"Exclude .git, node_modules, .project/archive, and installed GSD Path and path skill bundles.\n")
|
|
106
142
|
if task_name == "inspect_docs":
|
|
107
143
|
brief += ("Alignment mode: false. No prior audit or changed set.\n"
|
|
108
144
|
"Frozen inventory follows; use it exactly, without rediscovery:\n" + inventory)
|
|
109
|
-
brief_file.
|
|
145
|
+
brief_file.write_bytes(brief.encode("utf-8"))
|
|
110
146
|
assignments.append({**isolated, "task_name": task_name, "role": str(role_path),
|
|
111
147
|
"template": str(template_path), "output": output,
|
|
112
148
|
"brief_file": str(brief_file)})
|
|
@@ -136,16 +172,16 @@ def run_workflow(repo: Path, action: str, project_dir: str, expected_head: str =
|
|
|
136
172
|
if state["phase"] != "inspect" or state["status"] != "active":
|
|
137
173
|
raise StepFailed("inspection completion requires inspect/active")
|
|
138
174
|
branch = subprocess.run(["git", "branch", "--show-current"], cwd=repo,
|
|
139
|
-
capture_output=True,
|
|
175
|
+
capture_output=True, encoding="utf-8", errors="replace", check=True).stdout.strip()
|
|
140
176
|
if state["branch"] != branch:
|
|
141
177
|
raise StepFailed("current branch differs from the recorded inspection branch")
|
|
142
178
|
pending = step("discussion_records.py", "pending", "--repo", str(repo))
|
|
143
179
|
if pending["pending"]:
|
|
144
180
|
raise StepFailed("pending discussion requires its owner disposition")
|
|
145
181
|
docs = assignments["inspect_docs"]
|
|
146
|
-
step("check_docs_audit.py", "--repo", docs["worktree"], "--
|
|
147
|
-
"--inventory", str(inventory_file))
|
|
148
|
-
if f"Audited HEAD: {expected_head}" not in (Path(docs["worktree"]) / docs["output"]).read_text().splitlines():
|
|
182
|
+
step("check_docs_audit.py", "--repo", docs["worktree"], "--primary", str(repo),
|
|
183
|
+
"--audit", docs["output"], "--inventory", str(inventory_file))
|
|
184
|
+
if f"Audited HEAD: {expected_head}" not in (Path(docs["worktree"]) / docs["output"]).read_text(encoding="utf-8").splitlines():
|
|
149
185
|
raise StepFailed("audit does not name the supplied inspection baseline")
|
|
150
186
|
for task_name, _, _, _ in INSPECTION_SPECS:
|
|
151
187
|
assignment = assignments[task_name]
|
|
@@ -161,10 +197,14 @@ def run_workflow(repo: Path, action: str, project_dir: str, expected_head: str =
|
|
|
161
197
|
"--set-phase", "inspect", "--set-status", "done", "--event", "inspection artifacts passed")
|
|
162
198
|
elif action == "lint-round":
|
|
163
199
|
head = subprocess.run(["git", "rev-parse", "--verify", "HEAD"],
|
|
164
|
-
cwd=repo, capture_output=True,
|
|
200
|
+
cwd=repo, capture_output=True, encoding="utf-8", errors="replace", check=True).stdout.strip()
|
|
165
201
|
step("check_task_briefs.py", "--repo", str(repo), "--base", head,
|
|
166
|
-
"--tasks-dir", f"{project_dir}/tasks")
|
|
202
|
+
"--tasks-dir", f"{project_dir}/tasks", "--project-dir", project_dir)
|
|
167
203
|
step("check_handoffs.py", "plan", *common)
|
|
204
|
+
elif action == "prepare-task" and _task_member(repo, project_dir, task_id):
|
|
205
|
+
# A member task works in a sidecar of its member; its Verify runs there at finish.
|
|
206
|
+
step("isolation.py", "isolate-member-task", "--repo", str(repo),
|
|
207
|
+
"--member", _task_member(repo, project_dir, task_id), "--task-id", task_id)
|
|
168
208
|
elif action == "prepare-task":
|
|
169
209
|
task = step("isolation.py", "isolate-task", "--repo", str(repo),
|
|
170
210
|
"--base", expected_head, "--task-id", task_id,
|
|
@@ -186,33 +226,67 @@ def run_workflow(repo: Path, action: str, project_dir: str, expected_head: str =
|
|
|
186
226
|
raise StepFailed("pending discussion requires its owner disposition")
|
|
187
227
|
step("build_state.py", "verify-landed", *common, "--head", expected_head)
|
|
188
228
|
step("lean_verification.py", "--repo", str(repo), "--expected-head", expected_head)
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
229
|
+
elif action == "preauthorize":
|
|
230
|
+
# A block here is not a failure: the gate asks its owner as usual.
|
|
231
|
+
next_step = "ask the owner at this gate"
|
|
232
|
+
if project_dir != ".project" or kind not in {"intent", "plan"}:
|
|
233
|
+
raise StepFailed("pre-approval covers only intent or plan on the active track")
|
|
234
|
+
routed = step("pipeline_state.py", "route", *common)
|
|
235
|
+
if routed["route"].get("action") != "run-phase" or "recovery" in routed:
|
|
236
|
+
raise StepFailed("pre-approval needs an ordinary phase route")
|
|
237
|
+
if step("discussion_records.py", "pending", "--repo", str(repo))["pending"]:
|
|
192
238
|
raise StepFailed("pending discussion requires its owner disposition")
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
239
|
+
track = repo / project_dir
|
|
240
|
+
intent = (track / "intent/INTENT.md").read_text(encoding="utf-8")
|
|
241
|
+
lane = re.search(r"(?m)^Lane:\s*(.+)$", intent)
|
|
242
|
+
if not lane or lane.group(1).split("<!--", 1)[0].strip().strip("`") != "quick":
|
|
243
|
+
raise StepFailed("pre-approval covers only the quick lane")
|
|
244
|
+
intent = re.sub(r"(?s)<!--.*?-->", "", intent)
|
|
245
|
+
if re.search(r"(?m)^\s*-\s*\[(RESEARCH|NEEDS-USER)\]", _common.section_body(intent, "Open questions") or ""):
|
|
246
|
+
raise StepFailed("INTENT.md has open RESEARCH or NEEDS-USER questions")
|
|
247
|
+
audit_path = track / "research/DOCS-AUDIT.md"
|
|
248
|
+
if audit_path.exists():
|
|
249
|
+
audit = audit_path.read_text(encoding="utf-8")
|
|
250
|
+
queue = _table_rows(_common.section_body(audit, "Remediation queue"))
|
|
251
|
+
ruled = set()
|
|
252
|
+
for row in _table_rows(_common.section_body(audit, "User rulings")):
|
|
253
|
+
if len(row) != 4 or row[1] not in {"fix-code", "fix-doc", "accept-drift"}:
|
|
254
|
+
continue
|
|
255
|
+
words = row[2].strip().strip('`"').strip()
|
|
256
|
+
if words and words.casefold() != "none" and not re.fullmatch(r"<[^>]*>", words):
|
|
257
|
+
ruled.add(row[0])
|
|
258
|
+
if any(len(row) == 6 and row[4] == "NEEDS-USER" and row[0] not in ruled for row in queue):
|
|
259
|
+
raise StepFailed("DOCS-AUDIT.md has NEEDS-USER rows without a user ruling")
|
|
260
|
+
if kind == "intent":
|
|
261
|
+
# Malformed or incomplete spec-probe tables are not a pre-approvable draft.
|
|
262
|
+
step("check_handoffs.py", "intent", *common)
|
|
263
|
+
if kind == "plan":
|
|
264
|
+
if gate_plan()["mode"] != "off":
|
|
265
|
+
raise StepFailed("pre-approval requires review_panel off")
|
|
266
|
+
plan = re.sub(r"(?s)<!--.*?-->", "", (track / "plan/PLAN.md").read_text(encoding="utf-8"))
|
|
267
|
+
config = _common.section_body(plan, "Config") or ""
|
|
268
|
+
skeptics = re.search(r"(?m)^[ \t]*-[ \t]*finding_skeptics:[ \t]*(\S+)", config)
|
|
269
|
+
if skeptics and skeptics.group(1) != "off":
|
|
270
|
+
raise StepFailed("pre-approval requires finding_skeptics off")
|
|
271
|
+
# Quick-lane limit from project policy (gsd-path-plan Quick mode): one wave, at most two tasks.
|
|
272
|
+
if (len(re.findall(r"(?m)^## Wave \d+ — ", plan)) != 1
|
|
273
|
+
or len(list((track / "tasks").glob("T[0-9][0-9][0-9]-*.md"))) > 2):
|
|
274
|
+
raise StepFailed("pre-approval requires one wave and at most two tasks")
|
|
275
|
+
step("pipeline_state.py", "pre-approve", "--repo", str(repo), "--use", kind)
|
|
276
|
+
else:
|
|
277
|
+
gate_plan()
|
|
204
278
|
if action == "approve-plan":
|
|
205
279
|
step("pipeline_state.py", "approve", *common, "--kind", "plan",
|
|
206
280
|
"--expected-head", expected_head)
|
|
207
281
|
except (StepFailed, OSError, subprocess.CalledProcessError, ValueError, KeyError, TypeError) as error:
|
|
208
282
|
return {"status": "blocked", "reason": str(error), "steps": steps,
|
|
209
|
-
"next":
|
|
283
|
+
"next": next_step}
|
|
210
284
|
return {"status": "complete", "steps": steps, **outputs}
|
|
211
285
|
|
|
212
286
|
|
|
213
287
|
def main(argv=None):
|
|
214
288
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
215
|
-
parser.add_argument("action", choices=("route", "gate-plan", "approve-plan", "build-evidence", "lint-round", "prepare-task", "prepare-final", "prepare-inspect", "finish-inspect"))
|
|
289
|
+
parser.add_argument("action", choices=("route", "gate-plan", "approve-plan", "build-evidence", "lint-round", "prepare-task", "prepare-final", "prepare-inspect", "finish-inspect", "preauthorize"))
|
|
216
290
|
parser.add_argument("--repo", type=Path, required=True)
|
|
217
291
|
parser.add_argument("--project-dir", choices=(".project", ".project/next"), default=".project")
|
|
218
292
|
parser.add_argument("--expected-head")
|
|
@@ -220,15 +294,18 @@ def main(argv=None):
|
|
|
220
294
|
parser.add_argument("--round-size", type=int)
|
|
221
295
|
parser.add_argument("--inspection", type=Path)
|
|
222
296
|
parser.add_argument("--mapper-reviewed", action="store_true")
|
|
297
|
+
parser.add_argument("--kind", choices=("intent", "plan"))
|
|
223
298
|
arguments = parser.parse_args(argv)
|
|
224
299
|
if arguments.action in {"approve-plan", "build-evidence", "prepare-task", "prepare-final", "prepare-inspect", "finish-inspect"} and not arguments.expected_head:
|
|
225
300
|
parser.error(f"{arguments.action} requires --expected-head")
|
|
226
301
|
if arguments.action == "prepare-task" and (not arguments.task_id or arguments.round_size is None):
|
|
227
302
|
parser.error("prepare-task requires --task-id and --round-size")
|
|
303
|
+
if arguments.action == "preauthorize" and not arguments.kind:
|
|
304
|
+
parser.error("preauthorize requires --kind")
|
|
228
305
|
result = run_workflow(arguments.repo.resolve(), arguments.action,
|
|
229
306
|
arguments.project_dir, arguments.expected_head,
|
|
230
307
|
arguments.task_id, arguments.round_size, arguments.inspection,
|
|
231
|
-
arguments.mapper_reviewed)
|
|
308
|
+
arguments.mapper_reviewed, arguments.kind)
|
|
232
309
|
print(json.dumps(result, sort_keys=True))
|
|
233
310
|
return 0 if result["status"] == "complete" else 1
|
|
234
311
|
|
|
@@ -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):
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
(brownfield mode), researchers (fifth standard dimension), the planner
|
|
5
5
|
(conventions are binding), and reviewers. -->
|
|
6
6
|
|
|
7
|
-
Repo root: <absolute
|
|
7
|
+
Repo root: <absolute primary repo root, never a sidecar>
|
|
8
8
|
Scanned: <date>
|
|
9
9
|
Checks run: <exact commands run and their results, e.g. `npm test` → 37/40 pass>
|
|
10
10
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<!-- Written by the docs auditor ($gsd-path-docs-audit or $gsd-path-inspect).
|
|
4
4
|
Every verdict carries evidence; a verdict without evidence is a defect. -->
|
|
5
5
|
|
|
6
|
-
Repo root: <absolute
|
|
6
|
+
Repo root: <absolute primary repo root, never a sidecar>
|
|
7
7
|
Audited: <date>
|
|
8
8
|
Audited HEAD: <40-hex commit the claims were checked at, or none>
|
|
9
9
|
Alignment mode: <yes | no — yes when .project/ artifacts were also audited>
|
|
@@ -62,7 +62,11 @@ Worst drift: <one sentence — the most misleading claim found>
|
|
|
62
62
|
## Remediation queue
|
|
63
63
|
|
|
64
64
|
<!-- Every non-verified claim, classified. The user rules on this queue;
|
|
65
|
-
the auditor never fixes anything.
|
|
65
|
+
the auditor never fixes anything.
|
|
66
|
+
Numbers are unique and strictly increasing, not necessarily contiguous.
|
|
67
|
+
A persisting row keeps its number; a new row takes a number above every
|
|
68
|
+
prior queue number and every User rulings Queue #. Never reuse a retired
|
|
69
|
+
number: a ruling stays bound to the item it was made for. -->
|
|
66
70
|
|
|
67
71
|
| # | Doc | Claim | Verdict | Class | Suggested action |
|
|
68
72
|
|---|-----|-------|---------|-------|------------------|
|
|
@@ -4,20 +4,32 @@
|
|
|
4
4
|
criterion appears exactly once and carries checked evidence. A criterion
|
|
5
5
|
listed in PLAN.md's Surface contract also names its Surface, and its
|
|
6
6
|
Check is the walkthrough performed — never internal test output. Embedded
|
|
7
|
-
angle brackets are valid in concrete Check and Observed values.
|
|
7
|
+
angle brackets are valid in concrete Check and Observed values.
|
|
8
|
+
When .project/build/members.json locks members, add one line per locked
|
|
9
|
+
member after Reviewed HEAD: `Member reviewed HEAD: <member> <full SHA>`,
|
|
10
|
+
naming that member's bound branch tip. -->
|
|
8
11
|
|
|
9
12
|
Reviewed HEAD: <full SHA>
|
|
10
13
|
Overall verdict: <pass | blocked>
|
|
11
14
|
|
|
12
15
|
<!-- pass only when every criterion is met; blocked when any criterion is
|
|
13
|
-
not-met or unverifiable.
|
|
16
|
+
not-met or unverifiable.
|
|
17
|
+
A criterion with a held-out edge (E#) or judgment prohibition (N#) in
|
|
18
|
+
INTENT.md is met only when Check, Observed, or Reference cites every such
|
|
19
|
+
id with its evidence; otherwise it is unverifiable with
|
|
20
|
+
`Finding: insufficient spec evidence: <id> ...`. -->
|
|
14
21
|
|
|
15
22
|
## Success criteria
|
|
16
23
|
|
|
17
|
-
|
|
24
|
+
<!-- Each `### SCn —` title must match INTENT.md `## Success criteria` as
|
|
25
|
+
`_success_criteria` stores it: continuation lines join with a single
|
|
26
|
+
space and keep `- ` sub-bullet markers; comparison uses `_normalize_ws`
|
|
27
|
+
only. -->
|
|
28
|
+
|
|
29
|
+
### SC1 — <criterion as stored by the gate>
|
|
18
30
|
|
|
19
31
|
- **Verdict**: <met | not-met | unverifiable>
|
|
20
|
-
- **Surface**: <the surface PLAN.md's Surface contract lists this criterion under; omit the whole field for any other criterion>
|
|
32
|
+
- **Surface**: <exactly the surface name PLAN.md's Surface contract lists this criterion under, with no detail after it; omit the whole field for any other criterion>
|
|
21
33
|
- **Check**: `<command actually run, or "none">`
|
|
22
34
|
- **Observed**: <relevant output or observed behavior>
|
|
23
35
|
- **Reference**: <file:line, artifact path, or "none">
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# Gap Review — <N>: <risk identity>
|
|
2
2
|
|
|
3
3
|
<!-- Written by one final gap reviewer. This file covers exactly one
|
|
4
|
-
cross-wave integration risk named in the review brief.
|
|
4
|
+
cross-wave integration risk named in the review brief. Repeat FINAL.md's
|
|
5
|
+
`Member reviewed HEAD: <member> <full SHA>` lines after Reviewed HEAD. -->
|
|
5
6
|
|
|
6
7
|
Reviewed HEAD: <full SHA>
|
|
7
8
|
Gap verdict: <pass | blocked>
|
|
@@ -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.>
|
|
@@ -11,6 +11,6 @@ State: ship/blocked
|
|
|
11
11
|
### P001 — <short finding title>
|
|
12
12
|
|
|
13
13
|
- **Source**: `.project/review/FINAL.md`
|
|
14
|
-
- **Locator**:
|
|
15
|
-
- **Evidence**: <
|
|
16
|
-
- **Fix direction**: <
|
|
14
|
+
- **Locator**: <copy the full `Risk: ...` line from a gap review, or the `SC<n>` id from `FINAL.md`>
|
|
15
|
+
- **Evidence**: <copy the gap review's `Found` or `FINAL.md`'s `Finding` field verbatim>
|
|
16
|
+
- **Fix direction**: <copy the source's `Fix direction` field verbatim>
|
|
@@ -47,8 +47,8 @@ Goal: <the end-to-end slice that runs>
|
|
|
47
47
|
Review depth: <full | deep | verify-only>
|
|
48
48
|
|
|
49
49
|
<!-- More waves: features by dependency, then polish. Rules:
|
|
50
|
-
- deps only in earlier waves
|
|
51
|
-
-
|
|
50
|
+
- deps only in earlier waves or the same wave
|
|
51
|
+
- same-wave tasks share files only when one transitively depends on the other
|
|
52
52
|
- nothing from INTENT.md scope-out appears anywhere -->
|
|
53
53
|
|
|
54
54
|
## Surface contract
|
|
@@ -83,6 +83,21 @@ Walkthrough:
|
|
|
83
83
|
|-----------|------|------------|
|
|
84
84
|
| SC1 | T001 | AC1 |
|
|
85
85
|
|
|
86
|
+
## Held-out checks
|
|
87
|
+
|
|
88
|
+
<!-- Required when INTENT.md Edge coverage has a held-out edge; omit the
|
|
89
|
+
section entirely when it has none. One row per held-out edge, given to
|
|
90
|
+
the task that owns the edge's criterion. Test is a file listed in that
|
|
91
|
+
task's files (optionally `path::test_name`); the task's Verify runs it
|
|
92
|
+
and its Acceptance
|
|
93
|
+
criteria state the edge id and the ruling from INTENT.md Detail. Final
|
|
94
|
+
review cites this test's recorded result for the edge.
|
|
95
|
+
`scripts/check_handoffs.py plan` gates this table. -->
|
|
96
|
+
|
|
97
|
+
| Edge | Task | Test |
|
|
98
|
+
|------|------|------|
|
|
99
|
+
| E1 | T001 | <test path from T001 files> |
|
|
100
|
+
|
|
86
101
|
## Dependency notes
|
|
87
102
|
|
|
88
103
|
<Per non-obvious edge: the exact data or landed effect that makes X precede Y,
|
|
@@ -14,12 +14,23 @@ Intent: `.project/intent/INTENT.md`
|
|
|
14
14
|
<!-- Include every standard dimension exactly once. A custom dimension may
|
|
15
15
|
supplement these rows, never replace a standard row. -->
|
|
16
16
|
- `domain` — dispatched → `.project/research/evidence-domain.md` — <why this dimension ran>
|
|
17
|
-
- `stack` —
|
|
17
|
+
- `stack` — dispatched → `.project/research/evidence-stack.md` — <why this dimension ran>
|
|
18
18
|
- `pitfalls` — skipped → none — <why this dimension was skipped>
|
|
19
19
|
- `similar` — skipped → none — <why this dimension was skipped>
|
|
20
20
|
|
|
21
21
|
## Question assignments
|
|
22
22
|
|
|
23
23
|
<!-- Copy every [RESEARCH] question from INTENT.md exactly once. Use `- none`
|
|
24
|
-
only when INTENT.md has no [RESEARCH] questions.
|
|
25
|
-
|
|
24
|
+
only when INTENT.md has no [RESEARCH] questions. The question is a
|
|
25
|
+
CommonMark code span: choose a fence length not used by a backtick run in
|
|
26
|
+
the question (a longer fence is usually easiest), with one space of
|
|
27
|
+
padding on each side. Each row may target one or more dispatched
|
|
28
|
+
dimensions, each in its own code span and separated by commas. Every
|
|
29
|
+
dispatched dimension must receive a question and answer all its assigned
|
|
30
|
+
questions in its evidence file. For example:
|
|
31
|
+
- `` [RESEARCH] Does `Widget` match `sample.json`? `` → `domain`, `stack`
|
|
32
|
+
A question that ends in a backtick also needs padding, as in:
|
|
33
|
+
- `` [RESEARCH] Does the label end with `Widget`?` `` → `domain`
|
|
34
|
+
After removing the fence and CommonMark padding, the text must equal the
|
|
35
|
+
INTENT question exactly. -->
|
|
36
|
+
- `` [RESEARCH] <question copied from INTENT.md> `` → `domain`, `stack`
|
|
@@ -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
|
---
|
|
@@ -10,6 +10,7 @@ worktree: null # orchestrator-owned: isolated task worktree while active
|
|
|
10
10
|
task_branch: null # orchestrator-owned: gsd-path-task/<id> while parallel; null when serial
|
|
11
11
|
# Optional explicit dispatch overrides: model: <advertised slug|inherit>
|
|
12
12
|
# effort: <advertised effort|inherit>
|
|
13
|
+
# repo: <member> # multi-repo only: the MEMBERS.md member this task changes; omit for the coordinator
|
|
13
14
|
files: # every file this task may touch — dispatch checks overlap
|
|
14
15
|
- <path>
|
|
15
16
|
---
|
|
@@ -10,8 +10,11 @@
|
|
|
10
10
|
with actual values, otherwise omit them:
|
|
11
11
|
Reviewed HEAD: <full review commit SHA>
|
|
12
12
|
Review scope: final
|
|
13
|
-
In each surface SC block
|
|
14
|
-
|
|
13
|
+
In each surface SC block keep the mandatory `- ✅` / `- ❌` evidence line
|
|
14
|
+
(the wave gate requires it). Also include Surface, Check, and Observed
|
|
15
|
+
fields using the final-review format. Surface holds exactly the surface name
|
|
16
|
+
from PLAN.md's Surface contract; put walkthrough detail in Check and Observed.
|
|
17
|
+
The `- ✅` line may summarize Observed; do not omit it. -->
|
|
15
18
|
|
|
16
19
|
Wave verdict: <pass | blocked — blocked if any task fails>
|
|
17
20
|
Cycle: <C>
|
|
@@ -43,12 +46,21 @@ Contract violations (blocking):
|
|
|
43
46
|
<!-- One heading per INTENT.md success criterion owned by a task in this
|
|
44
47
|
wave, ending `: pass` or `: fail`. `scripts/check_handoffs.py wave
|
|
45
48
|
--review <this file>` gates the SC id set and verdicts. Omit this
|
|
46
|
-
section when no task in the wave owns an SC.
|
|
49
|
+
section when no task in the wave owns an SC.
|
|
50
|
+
Copy the criterion text from INTENT.md `## Success criteria` exactly as
|
|
51
|
+
`_success_criteria` stores it: indented continuation lines join with a
|
|
52
|
+
single space and keep their leading `- ` markers; the gate compares
|
|
53
|
+
heading text with `_normalize_ws` only (no paraphrase or stripped
|
|
54
|
+
sub-bullets). -->
|
|
47
55
|
|
|
48
|
-
### SC1 — <criterion>: <pass | fail>
|
|
56
|
+
### SC1 — <criterion as stored by the gate>: <pass | fail>
|
|
49
57
|
- ✅ <evidence: verify output / file:line checked>
|
|
50
58
|
- ❌ <criterion> — found: <what exists instead, file:line>
|
|
51
59
|
fix: <concrete direction a coder can execute without re-investigating>
|
|
60
|
+
<!-- Quick-lane final scope (Review scope: final): add after the evidence line:
|
|
61
|
+
- **Surface**: <surface name from PLAN.md>
|
|
62
|
+
- **Check**: `<walkthrough command>`
|
|
63
|
+
- **Observed**: <what was seen> -->
|
|
52
64
|
|
|
53
65
|
## Fixed since last cycle
|
|
54
66
|
|
|
Binary file
|
|
Binary file
|