@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
|
@@ -16,14 +16,20 @@ from pathlib import Path
|
|
|
16
16
|
from typing import Iterator, Optional, Sequence
|
|
17
17
|
|
|
18
18
|
def _load_pipeline_modules():
|
|
19
|
-
|
|
20
|
-
import archive_milestone
|
|
21
|
-
import pipeline_state
|
|
22
|
-
import _common
|
|
19
|
+
if __package__:
|
|
20
|
+
from . import archive_milestone
|
|
21
|
+
from . import pipeline_state
|
|
22
|
+
from . import _common
|
|
23
23
|
return _common, archive_milestone, pipeline_state
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
else:
|
|
25
|
+
try:
|
|
26
|
+
import archive_milestone
|
|
27
|
+
import pipeline_state
|
|
28
|
+
import _common
|
|
29
|
+
return _common, archive_milestone, pipeline_state
|
|
30
|
+
except ModuleNotFoundError as error:
|
|
31
|
+
if error.name not in {"archive_milestone", "pipeline_state", "_common"}:
|
|
32
|
+
raise
|
|
27
33
|
try:
|
|
28
34
|
from scripts import archive_milestone, pipeline_state, _common
|
|
29
35
|
return _common, archive_milestone, pipeline_state
|
|
@@ -111,7 +117,7 @@ def record_count(directory: Path) -> int:
|
|
|
111
117
|
def validate_or_empty(directory: Path) -> None:
|
|
112
118
|
if directory.is_symlink() or not directory.is_dir():
|
|
113
119
|
raise DiscussionError("discussion records must be a real directory")
|
|
114
|
-
if sorted(path.name for path in directory.iterdir()) != sorted(FILES):
|
|
120
|
+
if sorted(path.name for path in directory.iterdir() if not _common.is_ignored_junk(path)) != sorted(FILES):
|
|
115
121
|
raise DiscussionError("discussion directory must contain exactly DIALOGUE.md and ANSWERS.md")
|
|
116
122
|
if record_count(directory) == 0:
|
|
117
123
|
if "### D" in (directory / "DIALOGUE.md").read_text(encoding="utf-8"):
|
|
@@ -170,7 +176,7 @@ def validate_contents(project: Path, files: dict) -> None:
|
|
|
170
176
|
staging.mkdir()
|
|
171
177
|
try:
|
|
172
178
|
for name in FILES:
|
|
173
|
-
(staging / name).
|
|
179
|
+
(staging / name).write_bytes(files[name].encode("utf-8"))
|
|
174
180
|
validate_or_empty(staging)
|
|
175
181
|
finally:
|
|
176
182
|
shutil.rmtree(staging)
|
|
@@ -187,11 +193,11 @@ def initialize_records(discussion: Path, dialogue_template: Path, answers_templa
|
|
|
187
193
|
shutil.rmtree(staging)
|
|
188
194
|
staging.mkdir()
|
|
189
195
|
try:
|
|
190
|
-
(staging / "DIALOGUE.md").
|
|
191
|
-
template_header(dialogue_template, "### D001")
|
|
196
|
+
(staging / "DIALOGUE.md").write_bytes(
|
|
197
|
+
template_header(dialogue_template, "### D001").encode("utf-8")
|
|
192
198
|
)
|
|
193
|
-
(staging / "ANSWERS.md").
|
|
194
|
-
template_header(answers_template, "## Answer A001")
|
|
199
|
+
(staging / "ANSWERS.md").write_bytes(
|
|
200
|
+
template_header(answers_template, "## Answer A001").encode("utf-8")
|
|
195
201
|
)
|
|
196
202
|
os.replace(staging, discussion)
|
|
197
203
|
finally:
|
|
@@ -14,12 +14,16 @@ from datetime import date
|
|
|
14
14
|
from pathlib import Path, PurePosixPath
|
|
15
15
|
from typing import Optional, Sequence
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
from pipeline_state import PipelineState
|
|
19
|
-
import _common
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
if __package__:
|
|
18
|
+
from .pipeline_state import PipelineState
|
|
19
|
+
from . import _common
|
|
20
|
+
else:
|
|
21
|
+
try:
|
|
22
|
+
from pipeline_state import PipelineState
|
|
23
|
+
import _common
|
|
24
|
+
except ImportError: # pragma: no cover - package import used by tests
|
|
25
|
+
from scripts.pipeline_state import PipelineState
|
|
26
|
+
from scripts import _common
|
|
23
27
|
|
|
24
28
|
|
|
25
29
|
atomic_replace = _common.atomic_replace
|
|
@@ -105,7 +109,7 @@ def validate_discussion_directory(
|
|
|
105
109
|
) -> None:
|
|
106
110
|
if directory.is_symlink() or not directory.is_dir():
|
|
107
111
|
raise ArchiveError("discussion archive must be a real directory")
|
|
108
|
-
entries = sorted(path.name for path in directory.iterdir())
|
|
112
|
+
entries = sorted(path.name for path in directory.iterdir() if not _common.is_ignored_junk(path))
|
|
109
113
|
if entries != sorted(DISCUSSION_FILES):
|
|
110
114
|
raise ArchiveError("discussion archive must contain exactly DIALOGUE.md and ANSWERS.md")
|
|
111
115
|
dialogue, answers = (directory / name for name in DISCUSSION_FILES)
|
|
@@ -463,15 +467,17 @@ def completed_field(lines: Sequence[str], field: str, artifact: str) -> str:
|
|
|
463
467
|
|
|
464
468
|
|
|
465
469
|
def completed_bullet_field(lines: Sequence[str], field: str, artifact: str) -> str:
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
for line in lines:
|
|
469
|
-
match = pattern.fullmatch(line)
|
|
470
|
-
if match:
|
|
471
|
-
values.append(match.group(1).strip().strip("`"))
|
|
472
|
-
if len(values) != 1 or not values[0] or archive_milestone.contains_placeholder(values[0]):
|
|
470
|
+
matches = _common.find_review_bullet_field_values(lines, field)
|
|
471
|
+
if len(matches) != 1:
|
|
473
472
|
raise ArchiveError(f"{artifact} requires one completed {field} field")
|
|
474
|
-
|
|
473
|
+
raw_value = matches[0].strip()
|
|
474
|
+
value = raw_value.strip("`")
|
|
475
|
+
# Scan the value as written. Removing an outer backtick first can unbalance
|
|
476
|
+
# every code span after a leading or trailing one. contains_placeholder
|
|
477
|
+
# already handles a wholly quoted placeholder such as `<command>`.
|
|
478
|
+
if not value or archive_milestone.contains_placeholder(raw_value):
|
|
479
|
+
raise ArchiveError(f"{artifact} requires one completed {field} field")
|
|
480
|
+
return value
|
|
475
481
|
|
|
476
482
|
|
|
477
483
|
def section_lines(lines: Sequence[str], heading: str, artifact: str) -> Sequence[str]:
|
|
@@ -490,10 +496,13 @@ def archived_intent_criteria(archive: Path) -> dict[int, str]:
|
|
|
490
496
|
if not archive_milestone.is_real_file(intent):
|
|
491
497
|
raise ArchiveError("archived intent must be a real INTENT.md file")
|
|
492
498
|
text = HTML_COMMENT_PATTERN.sub("", intent.read_text(encoding="utf-8"))
|
|
493
|
-
|
|
494
|
-
import check_handoffs
|
|
495
|
-
|
|
496
|
-
|
|
499
|
+
if __package__:
|
|
500
|
+
from . import check_handoffs
|
|
501
|
+
else:
|
|
502
|
+
try:
|
|
503
|
+
import check_handoffs
|
|
504
|
+
except ImportError:
|
|
505
|
+
from scripts import check_handoffs
|
|
497
506
|
try:
|
|
498
507
|
criteria = check_handoffs._success_criteria(text)
|
|
499
508
|
except check_handoffs.HandoffError as error:
|
|
@@ -502,10 +511,19 @@ def archived_intent_criteria(archive: Path) -> dict[int, str]:
|
|
|
502
511
|
|
|
503
512
|
|
|
504
513
|
def parse_final_review(archive: Path) -> tuple:
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
514
|
+
reviewed_head, criteria, _raw_evidence = _final_review(archive)
|
|
515
|
+
return reviewed_head, criteria
|
|
516
|
+
|
|
517
|
+
|
|
518
|
+
def _final_review(archive: Path) -> tuple:
|
|
519
|
+
"""Parse FINAL.md and retain evidence as written for placeholder scans."""
|
|
520
|
+
if __package__:
|
|
521
|
+
from . import check_handoffs
|
|
522
|
+
else:
|
|
523
|
+
try:
|
|
524
|
+
import check_handoffs
|
|
525
|
+
except ImportError: # pragma: no cover - package import used by tests
|
|
526
|
+
from scripts import check_handoffs
|
|
509
527
|
|
|
510
528
|
final = archive / "review" / "FINAL.md"
|
|
511
529
|
if not archive_milestone.is_real_file(final):
|
|
@@ -552,18 +570,21 @@ def parse_final_review(archive: Path) -> tuple:
|
|
|
552
570
|
|
|
553
571
|
expected_fields = ("Verdict", "Check", "Observed", "Reference", "Finding", "Fix direction")
|
|
554
572
|
criteria = []
|
|
573
|
+
raw_evidence = []
|
|
555
574
|
for position, (heading_index, _, criterion) in enumerate(headings):
|
|
556
575
|
section_start = heading_index + 1
|
|
557
576
|
section_end = headings[position + 1][0] if position + 1 < len(headings) else criteria_end
|
|
577
|
+
section = lines[section_start:section_end]
|
|
558
578
|
values = {}
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
key, value = match.groups()
|
|
564
|
-
if key in values:
|
|
579
|
+
raw_values = {}
|
|
580
|
+
for key in expected_fields:
|
|
581
|
+
matches = _common.find_review_bullet_field_values(section, key)
|
|
582
|
+
if len(matches) > 1:
|
|
565
583
|
raise ArchiveError(f"FINAL.md repeats {key} for {criterion}")
|
|
566
|
-
|
|
584
|
+
if len(matches) != 1:
|
|
585
|
+
raise ArchiveError(f"FINAL.md criterion is incomplete: {criterion}")
|
|
586
|
+
raw_values[key] = matches[0].strip()
|
|
587
|
+
values[key] = raw_values[key].strip("`")
|
|
567
588
|
surface_values = [
|
|
568
589
|
line.removeprefix("- **Surface**:").strip().strip("`")
|
|
569
590
|
for line in lines[section_start:section_end]
|
|
@@ -583,22 +604,44 @@ def parse_final_review(archive: Path) -> tuple:
|
|
|
583
604
|
check_handoffs._surface_value(value, f"FINAL.md surface {field}")
|
|
584
605
|
except check_handoffs.HandoffError as error:
|
|
585
606
|
raise ArchiveError(str(error)) from error
|
|
586
|
-
elif not value or archive_milestone.contains_placeholder(
|
|
607
|
+
elif not value or archive_milestone.contains_placeholder(raw_values[field]):
|
|
587
608
|
raise ArchiveError(f"FINAL.md criterion is incomplete: {criterion}")
|
|
588
609
|
if values["Verdict"] != "met":
|
|
589
610
|
raise ArchiveError(f"FINAL.md criterion lacks passing evidence: {criterion}")
|
|
590
|
-
|
|
591
|
-
(
|
|
611
|
+
evidence_field = next(
|
|
612
|
+
(field for field in ("Reference", "Check", "Observed") if values[field] != "none"),
|
|
592
613
|
None,
|
|
593
614
|
)
|
|
594
|
-
if
|
|
615
|
+
if evidence_field is None:
|
|
595
616
|
raise ArchiveError(f"FINAL.md criterion lacks passing evidence: {criterion}")
|
|
596
|
-
criteria.append((criterion, "met",
|
|
597
|
-
|
|
617
|
+
criteria.append((criterion, "met", values[evidence_field]))
|
|
618
|
+
raw_evidence.append(raw_values[evidence_field])
|
|
619
|
+
return reviewed_head.lower(), criteria, raw_evidence
|
|
620
|
+
|
|
621
|
+
|
|
622
|
+
def _member_heads(text: str, source: str) -> dict:
|
|
623
|
+
if __package__:
|
|
624
|
+
from . import check_handoffs
|
|
625
|
+
else:
|
|
626
|
+
try:
|
|
627
|
+
import check_handoffs
|
|
628
|
+
except ImportError: # pragma: no cover - package import used by tests
|
|
629
|
+
from scripts import check_handoffs
|
|
630
|
+
try:
|
|
631
|
+
return check_handoffs.member_reviewed_heads(text, source)
|
|
632
|
+
except check_handoffs.HandoffError as error:
|
|
633
|
+
raise ArchiveError(str(error)) from error
|
|
598
634
|
|
|
599
635
|
|
|
600
636
|
def validate_gap_reviews(archive: Path, reviewed_head: str) -> None:
|
|
601
637
|
review = archive / "review"
|
|
638
|
+
member_heads = _member_heads((review / "FINAL.md").read_text(encoding="utf-8"), "FINAL.md")
|
|
639
|
+
lock = archive / "build" / "members.json"
|
|
640
|
+
locked = [item["name"] for item in json.loads(lock.read_text(encoding="utf-8"))["members"]] if lock.is_file() else []
|
|
641
|
+
if sorted(member_heads) != sorted(locked):
|
|
642
|
+
raise ArchiveError(
|
|
643
|
+
"FINAL.md Member reviewed HEAD lines must name each locked member: " + (", ".join(locked) or "none")
|
|
644
|
+
)
|
|
602
645
|
candidates = sorted(path for path in review.iterdir() if path.name.startswith("final-gap-"))
|
|
603
646
|
if not candidates:
|
|
604
647
|
raise ArchiveError("final review requires at least one final-gap-N.md artifact")
|
|
@@ -626,6 +669,8 @@ def validate_gap_reviews(archive: Path, reviewed_head: str) -> None:
|
|
|
626
669
|
gap_head = completed_field(lines, "Reviewed HEAD:", path.name).lower()
|
|
627
670
|
if gap_head != reviewed_head:
|
|
628
671
|
raise ArchiveError(f"{path.name} Reviewed HEAD does not match FINAL.md")
|
|
672
|
+
if _member_heads("\n".join(lines), path.name) != member_heads:
|
|
673
|
+
raise ArchiveError(f"{path.name} Member reviewed HEAD lines do not match FINAL.md")
|
|
629
674
|
if completed_field(lines, "Gap verdict:", path.name) != "pass":
|
|
630
675
|
raise ArchiveError(f"{path.name} gap review did not pass")
|
|
631
676
|
risk = completed_field(lines, "Risk:", path.name)
|
|
@@ -655,10 +700,13 @@ def validate_gap_reviews(archive: Path, reviewed_head: str) -> None:
|
|
|
655
700
|
|
|
656
701
|
|
|
657
702
|
def meaningful_review_evidence(lines: Sequence[str], marker: str, task_text: str = "") -> bool:
|
|
658
|
-
|
|
659
|
-
from check_handoffs import task_review_observation
|
|
660
|
-
|
|
661
|
-
|
|
703
|
+
if __package__:
|
|
704
|
+
from .check_handoffs import task_review_observation
|
|
705
|
+
else:
|
|
706
|
+
try:
|
|
707
|
+
from check_handoffs import task_review_observation
|
|
708
|
+
except ImportError: # pragma: no cover - package import used by tests
|
|
709
|
+
from scripts.check_handoffs import task_review_observation
|
|
662
710
|
|
|
663
711
|
prefix = f"- {marker} "
|
|
664
712
|
evidence = []
|
|
@@ -778,10 +826,14 @@ def validate_wave_review(
|
|
|
778
826
|
expected_depth: str,
|
|
779
827
|
expected_lens: Optional[str] = None,
|
|
780
828
|
task_texts: Optional[dict[str, str]] = None,
|
|
829
|
+
*,
|
|
830
|
+
is_last_cycle: bool = True,
|
|
781
831
|
) -> Sequence[str]:
|
|
782
832
|
lines = path.read_text(encoding="utf-8").splitlines()
|
|
783
833
|
depth = completed_field(lines, "Depth:", path.name)
|
|
784
|
-
if depth
|
|
834
|
+
if depth not in {"full", "deep", "verify-only"}:
|
|
835
|
+
raise ArchiveError(f"{path.name} has an invalid review depth")
|
|
836
|
+
if is_last_cycle and depth != expected_depth:
|
|
785
837
|
raise ArchiveError(f"{path.name} has an invalid review depth")
|
|
786
838
|
if expected_lens is not None:
|
|
787
839
|
lens = completed_field(lines, "Lens:", path.name)
|
|
@@ -806,10 +858,32 @@ def validate_wave_review(
|
|
|
806
858
|
normalized_expected = [
|
|
807
859
|
(task_id, " ".join(title.split())) for task_id, title in expected_tasks
|
|
808
860
|
]
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
861
|
+
expected_by_id = dict(normalized_expected)
|
|
862
|
+
enforce_plan_tasks = is_last_cycle and wave_verdict != "blocked"
|
|
863
|
+
if enforce_plan_tasks:
|
|
864
|
+
if actual_tasks != normalized_expected:
|
|
865
|
+
raise ArchiveError(
|
|
866
|
+
f"{path.name} tasks and titles do not match its wave task files in order"
|
|
867
|
+
)
|
|
868
|
+
else:
|
|
869
|
+
known_ids = set(expected_by_id)
|
|
870
|
+
for task_id in task_ids:
|
|
871
|
+
if task_id not in known_ids:
|
|
872
|
+
raise ArchiveError(
|
|
873
|
+
f"{path.name} tasks and titles do not match its wave task files in order"
|
|
874
|
+
)
|
|
875
|
+
plan_order = [task_id for task_id, _title in normalized_expected]
|
|
876
|
+
reviewed_order = [task_id for task_id in plan_order if task_id in task_ids]
|
|
877
|
+
if task_ids != reviewed_order:
|
|
878
|
+
raise ArchiveError(
|
|
879
|
+
f"{path.name} tasks and titles do not match its wave task files in order"
|
|
880
|
+
)
|
|
881
|
+
for _index, task_id, title, _verdict in headings:
|
|
882
|
+
expected_title = expected_by_id.get(task_id)
|
|
883
|
+
if expected_title is not None and " ".join(title.split()) != expected_title:
|
|
884
|
+
raise ArchiveError(
|
|
885
|
+
f"{path.name} tasks and titles do not match its wave task files in order"
|
|
886
|
+
)
|
|
813
887
|
|
|
814
888
|
verdicts = []
|
|
815
889
|
for position, (heading_index, _task_id, _title, verdict) in enumerate(headings):
|
|
@@ -834,6 +908,9 @@ def validate_wave_review(
|
|
|
834
908
|
)
|
|
835
909
|
verdicts.append(verdict)
|
|
836
910
|
|
|
911
|
+
if not is_last_cycle:
|
|
912
|
+
return verdicts
|
|
913
|
+
|
|
837
914
|
coverage_indexes = [
|
|
838
915
|
index for index, line in enumerate(lines) if line == "## Intent coverage"
|
|
839
916
|
]
|
|
@@ -1047,10 +1124,17 @@ def review_cycle_counts(archive: Path) -> Sequence[int]:
|
|
|
1047
1124
|
depth,
|
|
1048
1125
|
lens,
|
|
1049
1126
|
task_texts,
|
|
1127
|
+
is_last_cycle=cycle == max(cycles),
|
|
1050
1128
|
)
|
|
1051
1129
|
)
|
|
1052
1130
|
|
|
1053
1131
|
last_cycle = max(cycles)
|
|
1132
|
+
for cycle, verdicts in wave_verdicts.items():
|
|
1133
|
+
if cycle != last_cycle and "blocked" not in verdicts:
|
|
1134
|
+
raise ArchiveError(
|
|
1135
|
+
f"superseded review cycle {cycle} for wave {wave} "
|
|
1136
|
+
"must include a blocked Wave verdict"
|
|
1137
|
+
)
|
|
1054
1138
|
if any(verdict != "pass" for verdict in wave_verdicts[last_cycle]):
|
|
1055
1139
|
raise ArchiveError(f"last review cycle for wave {wave} did not pass")
|
|
1056
1140
|
if any(task_verdict != "pass" for task_verdict in task_verdicts[last_cycle]):
|
|
@@ -1071,8 +1155,17 @@ def archive_file_inventory(archive: Path) -> Sequence[str]:
|
|
|
1071
1155
|
for path in archive.rglob("*"):
|
|
1072
1156
|
if path.is_symlink():
|
|
1073
1157
|
raise ArchiveError(f"archive contents must not be symlinks: {path}")
|
|
1074
|
-
if path.is_file()
|
|
1075
|
-
|
|
1158
|
+
if not path.is_file() or path.name == "MANIFEST.md":
|
|
1159
|
+
continue
|
|
1160
|
+
relative = path.relative_to(archive)
|
|
1161
|
+
if _common.is_ignored_junk(path):
|
|
1162
|
+
if len(relative.parts) == 1:
|
|
1163
|
+
continue
|
|
1164
|
+
original = archive.parent.parent / relative
|
|
1165
|
+
project = archive.parent.parent.parent
|
|
1166
|
+
if run_git(project, "check-ignore", "-q", "--", original.relative_to(project).as_posix()).returncode == 0:
|
|
1167
|
+
continue
|
|
1168
|
+
contents.append(relative.as_posix())
|
|
1076
1169
|
return sorted(contents)
|
|
1077
1170
|
|
|
1078
1171
|
|
|
@@ -1175,7 +1268,7 @@ def validate_manifest(project: Path, archive: Path, state: PipelineState) -> tup
|
|
|
1175
1268
|
if fields["Final verdict:"] != "all criteria met; project verify passed":
|
|
1176
1269
|
raise ArchiveError("manifest final verdict does not record the passed final gate")
|
|
1177
1270
|
|
|
1178
|
-
reviewed_head, final_criteria =
|
|
1271
|
+
reviewed_head, final_criteria, final_raw_evidence = _final_review(archive)
|
|
1179
1272
|
validate_gap_reviews(archive, reviewed_head)
|
|
1180
1273
|
task_files, attested = archive_milestone.landed_task_evidence(project, archive / "tasks", reviewed_head)
|
|
1181
1274
|
cycle_counts = review_cycle_counts(archive)
|
|
@@ -1219,14 +1312,23 @@ def validate_manifest(project: Path, archive: Path, state: PipelineState) -> tup
|
|
|
1219
1312
|
continue
|
|
1220
1313
|
criteria_rows.append(cells)
|
|
1221
1314
|
criteria_line_indexes.add(index)
|
|
1315
|
+
|
|
1316
|
+
def evidence_as_written(position: int, row: Sequence[str]) -> str:
|
|
1317
|
+
# Manifest evidence stores FINAL.md's normalized value. Scan the source
|
|
1318
|
+
# text when the row matches, so its inner code spans stay balanced.
|
|
1319
|
+
if position < len(final_criteria) and tuple(row) == tuple(final_criteria[position]):
|
|
1320
|
+
return final_raw_evidence[position]
|
|
1321
|
+
return row[2]
|
|
1322
|
+
|
|
1222
1323
|
if not criteria_rows or any(
|
|
1223
1324
|
len(row) != 3
|
|
1224
1325
|
or not row[0]
|
|
1225
1326
|
or row[1] != "met"
|
|
1226
1327
|
or not row[2]
|
|
1227
1328
|
or row[2] == "none"
|
|
1228
|
-
or
|
|
1229
|
-
|
|
1329
|
+
or archive_milestone.contains_placeholder(row[1])
|
|
1330
|
+
or archive_milestone.contains_placeholder(evidence_as_written(position, row))
|
|
1331
|
+
for position, row in enumerate(criteria_rows)
|
|
1230
1332
|
):
|
|
1231
1333
|
raise ArchiveError("manifest success-criteria rows are incomplete")
|
|
1232
1334
|
if [tuple(row) for row in criteria_rows] != list(final_criteria):
|