@opengsd/gsd-path 1.4.0 → 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/CHANGELOG.md +325 -344
- package/DOCS.md +12 -2
- package/FULL.md +3 -2
- package/HOOKS.md +95 -8
- package/QUICK.md +1 -1
- package/README.md +78 -110
- package/RUNTIME.md +1 -1
- package/UPDATE.md +4 -3
- package/WORKFLOW.md +22 -1
- package/package.json +5 -2
- package/platforms/shared-agents/dispatch.md +13 -0
- package/scripts/_common.py +149 -1
- package/scripts/archive_milestone.py +14 -13
- package/scripts/build_recovery.py +96 -31
- package/scripts/build_state.py +79 -3
- package/scripts/check_docs_audit.py +77 -4
- package/scripts/check_handoffs.py +546 -30
- package/scripts/check_task_briefs.py +279 -23
- package/scripts/detect_project.py +243 -18
- package/scripts/discussion_validate.py +86 -29
- package/scripts/dispatch_driver.py +392 -22
- package/scripts/git_guard.py +3 -3
- package/scripts/guard_hook.py +1416 -165
- package/scripts/install.mjs +23 -8
- package/scripts/install.py +49 -9
- package/scripts/integration.py +146 -1
- package/scripts/isolation.py +392 -60
- package/scripts/loop_run.py +16 -4
- package/scripts/members.py +11 -9
- package/scripts/path_config.py +3 -3
- package/scripts/pipeline_git.py +63 -12
- package/scripts/pipeline_state.py +111 -33
- package/scripts/pipeline_undo.py +101 -8
- package/scripts/runtime_store.py +20 -2
- package/scripts/skill-resources.json +9 -2
- package/scripts/state_checkpoint.py +9 -27
- package/scripts/status_runtime.py +22 -4
- package/scripts/task_context.py +12 -3
- package/scripts/wizard.mjs +1 -0
- package/scripts/workflow_run.py +5 -2
- package/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path/DEFINE.md +28 -3
- package/skills/gsd-path/PLAN.md +11 -3
- package/skills/gsd-path/RESEARCH.md +11 -0
- package/skills/gsd-path/SHIP.md +6 -1
- package/skills/gsd-path/references/build-native.md +16 -1
- package/skills/gsd-path/references/dispatch.md +13 -0
- package/skills/gsd-path/references/docs-auditor.md +5 -0
- package/skills/gsd-path/references/planner.md +14 -4
- package/skills/gsd-path/references/reviewer-final.md +20 -2
- package/skills/gsd-path/references/reviewer-wave.md +15 -4
- 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 +149 -1
- package/skills/gsd-path/scripts/archive_milestone.py +14 -13
- package/skills/gsd-path/scripts/build_recovery.py +96 -31
- package/skills/gsd-path/scripts/build_state.py +79 -3
- package/skills/gsd-path/scripts/check_docs_audit.py +77 -4
- package/skills/gsd-path/scripts/check_handoffs.py +546 -30
- package/skills/gsd-path/scripts/check_task_briefs.py +279 -23
- package/skills/gsd-path/scripts/detect_project.py +243 -18
- package/skills/gsd-path/scripts/discussion_validate.py +86 -29
- package/skills/gsd-path/scripts/dispatch_driver.py +392 -22
- package/skills/gsd-path/scripts/git_guard.py +3 -3
- package/skills/gsd-path/scripts/integration.py +146 -1
- package/skills/gsd-path/scripts/isolation.py +392 -60
- package/skills/gsd-path/scripts/loop_run.py +16 -4
- package/skills/gsd-path/scripts/members.py +11 -9
- package/skills/gsd-path/scripts/path_config.py +3 -3
- package/skills/gsd-path/scripts/pipeline_git.py +63 -12
- package/skills/gsd-path/scripts/pipeline_state.py +111 -33
- package/skills/gsd-path/scripts/state_checkpoint.py +9 -27
- package/skills/gsd-path/scripts/status_runtime.py +22 -4
- package/skills/gsd-path/scripts/task_context.py +12 -3
- package/skills/gsd-path/scripts/workflow_run.py +5 -2
- package/skills/gsd-path/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path/templates/docs-audit.md +5 -1
- package/skills/gsd-path/templates/final-review.md +11 -2
- 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/wave-review.md +16 -6
- package/skills/gsd-path-build/references/build-native.md +16 -1
- package/skills/gsd-path-build/references/dispatch.md +13 -0
- package/skills/gsd-path-build/references/reviewer-final.md +20 -2
- package/skills/gsd-path-build/references/reviewer-wave.md +15 -4
- 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 +149 -1
- package/skills/gsd-path-build/scripts/archive_milestone.py +14 -13
- package/skills/gsd-path-build/scripts/build_recovery.py +96 -31
- package/skills/gsd-path-build/scripts/build_state.py +79 -3
- package/skills/gsd-path-build/scripts/check_handoffs.py +546 -30
- package/skills/gsd-path-build/scripts/check_task_briefs.py +279 -23
- package/skills/gsd-path-build/scripts/detect_project.py +243 -18
- package/skills/gsd-path-build/scripts/discussion_validate.py +86 -29
- package/skills/gsd-path-build/scripts/dispatch_driver.py +392 -22
- package/skills/gsd-path-build/scripts/integration.py +146 -1
- package/skills/gsd-path-build/scripts/isolation.py +392 -60
- package/skills/gsd-path-build/scripts/loop_run.py +16 -4
- package/skills/gsd-path-build/scripts/members.py +11 -9
- package/skills/gsd-path-build/scripts/path_config.py +3 -3
- package/skills/gsd-path-build/scripts/pipeline_git.py +63 -12
- package/skills/gsd-path-build/scripts/pipeline_state.py +111 -33
- package/skills/gsd-path-build/scripts/state_checkpoint.py +9 -27
- package/skills/gsd-path-build/scripts/task_context.py +12 -3
- package/skills/gsd-path-build/scripts/workflow_run.py +5 -2
- package/skills/gsd-path-build/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path-build/templates/wave-review.md +16 -6
- package/skills/gsd-path-decide/references/dispatch.md +13 -0
- package/skills/gsd-path-decide/scripts/_common.py +149 -1
- package/skills/gsd-path-decide/scripts/archive_milestone.py +14 -13
- package/skills/gsd-path-decide/scripts/build_recovery.py +96 -31
- package/skills/gsd-path-decide/scripts/check_handoffs.py +546 -30
- package/skills/gsd-path-decide/scripts/check_task_briefs.py +279 -23
- package/skills/gsd-path-decide/scripts/detect_project.py +243 -18
- package/skills/gsd-path-decide/scripts/discussion_validate.py +86 -29
- package/skills/gsd-path-decide/scripts/integration.py +146 -1
- package/skills/gsd-path-decide/scripts/isolation.py +392 -60
- package/skills/gsd-path-decide/scripts/loop_run.py +16 -4
- package/skills/gsd-path-decide/scripts/members.py +11 -9
- package/skills/gsd-path-decide/scripts/path_config.py +3 -3
- package/skills/gsd-path-decide/scripts/pipeline_git.py +63 -12
- package/skills/gsd-path-decide/scripts/pipeline_state.py +111 -33
- package/skills/gsd-path-decide/scripts/state_checkpoint.py +9 -27
- package/skills/gsd-path-decide/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path-define/SKILL.md +28 -3
- package/skills/gsd-path-define/references/spec-probes.md +150 -0
- package/skills/gsd-path-define/scripts/_common.py +149 -1
- package/skills/gsd-path-define/scripts/archive_milestone.py +14 -13
- package/skills/gsd-path-define/scripts/build_recovery.py +96 -31
- package/skills/gsd-path-define/scripts/check_handoffs.py +546 -30
- package/skills/gsd-path-define/scripts/check_task_briefs.py +279 -23
- package/skills/gsd-path-define/scripts/detect_project.py +243 -18
- package/skills/gsd-path-define/scripts/discussion_validate.py +86 -29
- package/skills/gsd-path-define/scripts/integration.py +146 -1
- package/skills/gsd-path-define/scripts/isolation.py +392 -60
- package/skills/gsd-path-define/scripts/loop_run.py +16 -4
- package/skills/gsd-path-define/scripts/members.py +11 -9
- package/skills/gsd-path-define/scripts/path_config.py +3 -3
- package/skills/gsd-path-define/scripts/pipeline_git.py +63 -12
- package/skills/gsd-path-define/scripts/pipeline_state.py +111 -33
- package/skills/gsd-path-define/scripts/state_checkpoint.py +9 -27
- package/skills/gsd-path-define/scripts/worktree_paths.py +54 -2
- 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/scripts/_common.py +149 -1
- package/skills/gsd-path-discuss/scripts/loop_run.py +16 -4
- package/skills/gsd-path-discuss/scripts/path_config.py +3 -3
- package/skills/gsd-path-discuss/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path-docs-audit/references/dispatch.md +13 -0
- package/skills/gsd-path-docs-audit/references/docs-auditor.md +5 -0
- package/skills/gsd-path-docs-audit/scripts/_common.py +149 -1
- package/skills/gsd-path-docs-audit/scripts/archive_milestone.py +14 -13
- package/skills/gsd-path-docs-audit/scripts/build_recovery.py +96 -31
- package/skills/gsd-path-docs-audit/scripts/check_docs_audit.py +77 -4
- package/skills/gsd-path-docs-audit/scripts/check_handoffs.py +546 -30
- package/skills/gsd-path-docs-audit/scripts/check_task_briefs.py +279 -23
- package/skills/gsd-path-docs-audit/scripts/detect_project.py +243 -18
- package/skills/gsd-path-docs-audit/scripts/discussion_validate.py +86 -29
- package/skills/gsd-path-docs-audit/scripts/integration.py +146 -1
- package/skills/gsd-path-docs-audit/scripts/isolation.py +392 -60
- package/skills/gsd-path-docs-audit/scripts/loop_run.py +16 -4
- package/skills/gsd-path-docs-audit/scripts/members.py +11 -9
- package/skills/gsd-path-docs-audit/scripts/path_config.py +3 -3
- package/skills/gsd-path-docs-audit/scripts/pipeline_git.py +63 -12
- package/skills/gsd-path-docs-audit/scripts/pipeline_state.py +111 -33
- package/skills/gsd-path-docs-audit/scripts/state_checkpoint.py +9 -27
- package/skills/gsd-path-docs-audit/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path-docs-audit/templates/docs-audit.md +5 -1
- package/skills/gsd-path-forensics/scripts/_common.py +149 -1
- package/skills/gsd-path-forensics/scripts/loop_run.py +16 -4
- package/skills/gsd-path-forensics/scripts/path_config.py +3 -3
- package/skills/gsd-path-forensics/scripts/pipeline_undo.py +101 -8
- package/skills/gsd-path-forensics/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path-inspect/references/dispatch.md +13 -0
- package/skills/gsd-path-inspect/references/docs-auditor.md +5 -0
- package/skills/gsd-path-inspect/scripts/_common.py +149 -1
- package/skills/gsd-path-inspect/scripts/archive_milestone.py +14 -13
- package/skills/gsd-path-inspect/scripts/build_recovery.py +96 -31
- package/skills/gsd-path-inspect/scripts/check_docs_audit.py +77 -4
- package/skills/gsd-path-inspect/scripts/check_handoffs.py +546 -30
- package/skills/gsd-path-inspect/scripts/check_task_briefs.py +279 -23
- package/skills/gsd-path-inspect/scripts/detect_project.py +243 -18
- package/skills/gsd-path-inspect/scripts/discussion_validate.py +86 -29
- package/skills/gsd-path-inspect/scripts/integration.py +146 -1
- package/skills/gsd-path-inspect/scripts/isolation.py +392 -60
- package/skills/gsd-path-inspect/scripts/loop_run.py +16 -4
- package/skills/gsd-path-inspect/scripts/members.py +11 -9
- package/skills/gsd-path-inspect/scripts/path_config.py +3 -3
- package/skills/gsd-path-inspect/scripts/pipeline_git.py +63 -12
- package/skills/gsd-path-inspect/scripts/pipeline_state.py +111 -33
- package/skills/gsd-path-inspect/scripts/state_checkpoint.py +9 -27
- package/skills/gsd-path-inspect/scripts/workflow_run.py +5 -2
- package/skills/gsd-path-inspect/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path-inspect/templates/docs-audit.md +5 -1
- package/skills/gsd-path-inspect/templates/state.md +1 -1
- package/skills/gsd-path-loop/scripts/_common.py +149 -1
- package/skills/gsd-path-loop/scripts/loop_run.py +16 -4
- package/skills/gsd-path-loop/scripts/path_config.py +3 -3
- package/skills/gsd-path-loop/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path-migrate/scripts/_common.py +149 -1
- package/skills/gsd-path-migrate/scripts/loop_run.py +16 -4
- package/skills/gsd-path-migrate/scripts/path_config.py +3 -3
- package/skills/gsd-path-plan/SKILL.md +11 -3
- package/skills/gsd-path-plan/references/dispatch.md +13 -0
- package/skills/gsd-path-plan/references/planner.md +14 -4
- package/skills/gsd-path-plan/references/spec-probes.md +150 -0
- package/skills/gsd-path-plan/scripts/_common.py +149 -1
- package/skills/gsd-path-plan/scripts/archive_milestone.py +14 -13
- package/skills/gsd-path-plan/scripts/build_recovery.py +96 -31
- package/skills/gsd-path-plan/scripts/check_handoffs.py +546 -30
- package/skills/gsd-path-plan/scripts/check_task_briefs.py +279 -23
- package/skills/gsd-path-plan/scripts/detect_project.py +243 -18
- package/skills/gsd-path-plan/scripts/discussion_validate.py +86 -29
- package/skills/gsd-path-plan/scripts/integration.py +146 -1
- package/skills/gsd-path-plan/scripts/isolation.py +392 -60
- package/skills/gsd-path-plan/scripts/loop_run.py +16 -4
- package/skills/gsd-path-plan/scripts/members.py +11 -9
- package/skills/gsd-path-plan/scripts/path_config.py +3 -3
- package/skills/gsd-path-plan/scripts/pipeline_git.py +63 -12
- package/skills/gsd-path-plan/scripts/pipeline_state.py +111 -33
- package/skills/gsd-path-plan/scripts/state_checkpoint.py +9 -27
- package/skills/gsd-path-plan/scripts/workflow_run.py +5 -2
- package/skills/gsd-path-plan/scripts/worktree_paths.py +54 -2
- 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-research/SKILL.md +11 -0
- package/skills/gsd-path-research/references/dispatch.md +13 -0
- package/skills/gsd-path-research/scripts/_common.py +149 -1
- package/skills/gsd-path-research/scripts/archive_milestone.py +14 -13
- package/skills/gsd-path-research/scripts/build_recovery.py +96 -31
- package/skills/gsd-path-research/scripts/check_handoffs.py +546 -30
- package/skills/gsd-path-research/scripts/check_task_briefs.py +279 -23
- package/skills/gsd-path-research/scripts/detect_project.py +243 -18
- package/skills/gsd-path-research/scripts/discussion_validate.py +86 -29
- package/skills/gsd-path-research/scripts/integration.py +146 -1
- package/skills/gsd-path-research/scripts/isolation.py +392 -60
- package/skills/gsd-path-research/scripts/loop_run.py +16 -4
- package/skills/gsd-path-research/scripts/members.py +11 -9
- package/skills/gsd-path-research/scripts/path_config.py +3 -3
- package/skills/gsd-path-research/scripts/pipeline_git.py +63 -12
- package/skills/gsd-path-research/scripts/pipeline_state.py +111 -33
- package/skills/gsd-path-research/scripts/state_checkpoint.py +9 -27
- package/skills/gsd-path-research/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path-research/templates/research-handoff.md +14 -3
- package/skills/gsd-path-roadmap/references/dispatch.md +13 -0
- package/skills/gsd-path-roadmap/scripts/_common.py +149 -1
- package/skills/gsd-path-roadmap/scripts/archive_milestone.py +14 -13
- package/skills/gsd-path-roadmap/scripts/build_recovery.py +96 -31
- package/skills/gsd-path-roadmap/scripts/check_handoffs.py +546 -30
- package/skills/gsd-path-roadmap/scripts/check_task_briefs.py +279 -23
- package/skills/gsd-path-roadmap/scripts/detect_project.py +243 -18
- package/skills/gsd-path-roadmap/scripts/discussion_validate.py +86 -29
- package/skills/gsd-path-roadmap/scripts/integration.py +146 -1
- package/skills/gsd-path-roadmap/scripts/isolation.py +392 -60
- package/skills/gsd-path-roadmap/scripts/loop_run.py +16 -4
- package/skills/gsd-path-roadmap/scripts/members.py +11 -9
- package/skills/gsd-path-roadmap/scripts/path_config.py +3 -3
- package/skills/gsd-path-roadmap/scripts/pipeline_git.py +63 -12
- package/skills/gsd-path-roadmap/scripts/pipeline_state.py +111 -33
- package/skills/gsd-path-roadmap/scripts/state_checkpoint.py +9 -27
- package/skills/gsd-path-roadmap/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path-ship/SKILL.md +6 -1
- package/skills/gsd-path-ship/references/dispatch.md +13 -0
- package/skills/gsd-path-ship/references/reviewer-final.md +20 -2
- package/skills/gsd-path-ship/references/reviewer-wave.md +15 -4
- 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 +149 -1
- package/skills/gsd-path-ship/scripts/archive_milestone.py +14 -13
- package/skills/gsd-path-ship/scripts/build_recovery.py +96 -31
- package/skills/gsd-path-ship/scripts/build_state.py +79 -3
- package/skills/gsd-path-ship/scripts/check_handoffs.py +546 -30
- package/skills/gsd-path-ship/scripts/check_task_briefs.py +279 -23
- package/skills/gsd-path-ship/scripts/detect_project.py +243 -18
- package/skills/gsd-path-ship/scripts/discussion_validate.py +86 -29
- package/skills/gsd-path-ship/scripts/integration.py +146 -1
- package/skills/gsd-path-ship/scripts/isolation.py +392 -60
- package/skills/gsd-path-ship/scripts/loop_run.py +16 -4
- package/skills/gsd-path-ship/scripts/members.py +11 -9
- package/skills/gsd-path-ship/scripts/path_config.py +3 -3
- package/skills/gsd-path-ship/scripts/pipeline_git.py +63 -12
- package/skills/gsd-path-ship/scripts/pipeline_state.py +111 -33
- package/skills/gsd-path-ship/scripts/state_checkpoint.py +9 -27
- package/skills/gsd-path-ship/scripts/workflow_run.py +5 -2
- package/skills/gsd-path-ship/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path-ship/templates/final-review.md +11 -2
- package/skills/gsd-path-ship/templates/patch-findings.md +3 -3
- package/skills/gsd-path-ship/templates/wave-review.md +16 -6
- package/skills/gsd-path-undo/scripts/_common.py +149 -1
- package/skills/gsd-path-undo/scripts/loop_run.py +16 -4
- package/skills/gsd-path-undo/scripts/path_config.py +3 -3
- package/skills/gsd-path-undo/scripts/pipeline_undo.py +101 -8
- package/skills/gsd-path-undo/scripts/worktree_paths.py +54 -2
- package/skills/path/DEFINE.md +28 -3
- package/skills/path/PLAN.md +11 -3
- package/skills/path/RESEARCH.md +11 -0
- package/skills/path/SHIP.md +6 -1
- package/skills/path/references/build-native.md +16 -1
- package/skills/path/references/dispatch.md +13 -0
- package/skills/path/references/docs-auditor.md +5 -0
- package/skills/path/references/planner.md +14 -4
- package/skills/path/references/reviewer-final.md +20 -2
- package/skills/path/references/reviewer-wave.md +15 -4
- package/skills/path/references/reviewer.md +3 -1
- package/skills/path/references/spec-probes.md +150 -0
- package/skills/path/scripts/_common.py +149 -1
- package/skills/path/scripts/archive_milestone.py +14 -13
- package/skills/path/scripts/build_recovery.py +96 -31
- package/skills/path/scripts/build_state.py +79 -3
- package/skills/path/scripts/check_docs_audit.py +77 -4
- package/skills/path/scripts/check_handoffs.py +546 -30
- package/skills/path/scripts/check_task_briefs.py +279 -23
- package/skills/path/scripts/detect_project.py +243 -18
- package/skills/path/scripts/discussion_validate.py +86 -29
- package/skills/path/scripts/dispatch_driver.py +392 -22
- package/skills/path/scripts/git_guard.py +3 -3
- package/skills/path/scripts/integration.py +146 -1
- package/skills/path/scripts/isolation.py +392 -60
- package/skills/path/scripts/loop_run.py +16 -4
- package/skills/path/scripts/members.py +11 -9
- package/skills/path/scripts/path_config.py +3 -3
- package/skills/path/scripts/pipeline_git.py +63 -12
- package/skills/path/scripts/pipeline_state.py +111 -33
- package/skills/path/scripts/state_checkpoint.py +9 -27
- package/skills/path/scripts/status_runtime.py +22 -4
- package/skills/path/scripts/task_context.py +12 -3
- package/skills/path/scripts/workflow_run.py +5 -2
- package/skills/path/scripts/worktree_paths.py +54 -2
- package/skills/path/templates/docs-audit.md +5 -1
- package/skills/path/templates/final-review.md +11 -2
- 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/wave-review.md +16 -6
- 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
|
@@ -24,7 +24,7 @@ if __package__:
|
|
|
24
24
|
)
|
|
25
25
|
from .pipeline_git import task_commit_subject
|
|
26
26
|
from .pipeline_state import PipelineStateError, load_state
|
|
27
|
-
from . import _common
|
|
27
|
+
from . import _common, check_handoffs
|
|
28
28
|
else:
|
|
29
29
|
try:
|
|
30
30
|
from check_task_briefs import _frontmatter, _sections
|
|
@@ -37,6 +37,7 @@ else:
|
|
|
37
37
|
from pipeline_git import task_commit_subject
|
|
38
38
|
from pipeline_state import PipelineStateError, load_state
|
|
39
39
|
import _common
|
|
40
|
+
import check_handoffs
|
|
40
41
|
except ImportError: # pragma: no cover - package imports used by tests
|
|
41
42
|
from scripts.check_task_briefs import _frontmatter, _sections
|
|
42
43
|
from scripts.isolation import (
|
|
@@ -47,7 +48,7 @@ else:
|
|
|
47
48
|
)
|
|
48
49
|
from scripts.pipeline_git import task_commit_subject
|
|
49
50
|
from scripts.pipeline_state import PipelineStateError, load_state
|
|
50
|
-
from scripts import _common
|
|
51
|
+
from scripts import _common, check_handoffs
|
|
51
52
|
|
|
52
53
|
|
|
53
54
|
DEFAULT_PROJECT_DIR = ".project"
|
|
@@ -57,6 +58,10 @@ FULL_SHA_RE = re.compile(r"^[0-9a-f]{40}$")
|
|
|
57
58
|
# recover verdicts that count as landed, mapped to their evidence classification.
|
|
58
59
|
LANDED_VERDICTS = {"recovered": "proven-landed", "attested": "attested"}
|
|
59
60
|
WAVE_HEADING_RE = re.compile(r"(?m)^## Wave (?P<wave>\d+)\b.*$")
|
|
61
|
+
REVIEW_VERDICT_RE = re.compile(
|
|
62
|
+
r"(?m)^Wave verdict:\s*(?P<verdict>pass|blocked)\s*(?:<!--.*?-->)?\s*$"
|
|
63
|
+
)
|
|
64
|
+
REVIEW_FINDINGS_HEADING = "Review findings"
|
|
60
65
|
VERIFY_HEAVY_RE = re.compile(r"(?m)^Heavy:\s*(?P<value>yes|no)\s*(?:<!--.*-->)?\s*$")
|
|
61
66
|
VALID_TASK_STATUSES = {"pending", "in-progress", "done", "failed", "blocked"}
|
|
62
67
|
VERIFY_RESULTS = _common.VERIFY_RESULTS
|
|
@@ -88,6 +93,7 @@ class Task:
|
|
|
88
93
|
task_file: str
|
|
89
94
|
verify_heavy: bool
|
|
90
95
|
repo: str = ""
|
|
96
|
+
review_findings: bool = False
|
|
91
97
|
|
|
92
98
|
|
|
93
99
|
@dataclass(frozen=True)
|
|
@@ -241,6 +247,7 @@ def _parse_task(path: Path, relative_path: str, task_file: Optional[str] = None)
|
|
|
241
247
|
task_file=task_file or relative_path,
|
|
242
248
|
verify_heavy=_verify_heavy(text, label),
|
|
243
249
|
repo=str(fields.get("repo") or ""),
|
|
250
|
+
review_findings=REVIEW_FINDINGS_HEADING in _sections(text),
|
|
244
251
|
)
|
|
245
252
|
|
|
246
253
|
|
|
@@ -485,6 +492,36 @@ def _overlap(left: Task, right: Task) -> List[str]:
|
|
|
485
492
|
return sorted(set(left.files) & set(right.files))
|
|
486
493
|
|
|
487
494
|
|
|
495
|
+
def _blocked_wave_reviews(project: Project) -> Dict[int, int]:
|
|
496
|
+
"""Return waves whose highest canonical review cycle has a blocked lens."""
|
|
497
|
+
|
|
498
|
+
review_dir = project.tasks_dir.parent / "review"
|
|
499
|
+
if review_dir.is_symlink() or not review_dir.is_dir():
|
|
500
|
+
return {}
|
|
501
|
+
|
|
502
|
+
latest: Dict[int, int] = {}
|
|
503
|
+
verdicts: Dict[Tuple[int, int], List[str]] = {}
|
|
504
|
+
for path in sorted(review_dir.iterdir()):
|
|
505
|
+
named = check_handoffs.WAVE_REVIEW_NAME.fullmatch(path.name)
|
|
506
|
+
if named is None or path.is_symlink() or not path.is_file():
|
|
507
|
+
continue
|
|
508
|
+
wave, cycle = int(named.group("wave")), int(named.group("cycle"))
|
|
509
|
+
latest[wave] = max(latest.get(wave, 0), cycle)
|
|
510
|
+
try:
|
|
511
|
+
text = path.read_text(encoding="utf-8")
|
|
512
|
+
except (OSError, UnicodeDecodeError):
|
|
513
|
+
continue
|
|
514
|
+
verdict = REVIEW_VERDICT_RE.search(text)
|
|
515
|
+
if verdict is not None:
|
|
516
|
+
verdicts.setdefault((wave, cycle), []).append(verdict.group("verdict"))
|
|
517
|
+
|
|
518
|
+
return {
|
|
519
|
+
wave: cycle
|
|
520
|
+
for wave, cycle in latest.items()
|
|
521
|
+
if "blocked" in verdicts.get((wave, cycle), [])
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
|
|
488
525
|
def ready(repo: str, project_dir: str = DEFAULT_PROJECT_DIR, *,
|
|
489
526
|
allow_done: bool = False) -> Dict[str, object]:
|
|
490
527
|
"""Return task readiness, optionally accepting build/done for completion checks."""
|
|
@@ -494,6 +531,39 @@ def ready(repo: str, project_dir: str = DEFAULT_PROJECT_DIR, *,
|
|
|
494
531
|
by_id = {task.task_id: task for task in project.tasks}
|
|
495
532
|
unfinished_waves = sorted({task.wave for task in project.tasks if task.status != "done"})
|
|
496
533
|
current_wave = unfinished_waves[0] if unfinished_waves else None
|
|
534
|
+
blocked_reviews = _blocked_wave_reviews(project)
|
|
535
|
+
blocked_wave = min(
|
|
536
|
+
(
|
|
537
|
+
wave
|
|
538
|
+
for wave in blocked_reviews
|
|
539
|
+
if (current_wave is None or wave < current_wave)
|
|
540
|
+
and any(task.wave == wave for task in project.tasks)
|
|
541
|
+
and all(task.status == "done" for task in project.tasks if task.wave == wave)
|
|
542
|
+
),
|
|
543
|
+
default=None,
|
|
544
|
+
)
|
|
545
|
+
repair_for_wave: Optional[int] = None
|
|
546
|
+
blocked_review: Optional[Dict[str, object]] = None
|
|
547
|
+
if blocked_wave is not None:
|
|
548
|
+
source_ids = {task.task_id for task in project.tasks if task.wave == blocked_wave}
|
|
549
|
+
repairs = [
|
|
550
|
+
task
|
|
551
|
+
for task in project.tasks
|
|
552
|
+
if task.status != "done"
|
|
553
|
+
and task.wave > blocked_wave
|
|
554
|
+
and task.review_findings
|
|
555
|
+
and source_ids.intersection(task.deps)
|
|
556
|
+
]
|
|
557
|
+
if repairs:
|
|
558
|
+
repair_for_wave = blocked_wave
|
|
559
|
+
current_wave = min(task.wave for task in repairs)
|
|
560
|
+
else:
|
|
561
|
+
current_wave = blocked_wave
|
|
562
|
+
blocked_review = {
|
|
563
|
+
"wave": blocked_wave,
|
|
564
|
+
"cycle": blocked_reviews[blocked_wave],
|
|
565
|
+
"waiting_waves": unfinished_waves,
|
|
566
|
+
}
|
|
497
567
|
active = [task for task in project.tasks if task.status == "in-progress"]
|
|
498
568
|
if current_wave is not None and any(task.wave != current_wave for task in active):
|
|
499
569
|
task = next(task for task in active if task.wave != current_wave)
|
|
@@ -536,7 +606,7 @@ def ready(repo: str, project_dir: str = DEFAULT_PROJECT_DIR, *,
|
|
|
536
606
|
)
|
|
537
607
|
|
|
538
608
|
wave_active = any(task.wave == current_wave for task in active)
|
|
539
|
-
if current_wave is not None and not selectable and not wave_active:
|
|
609
|
+
if current_wave is not None and blocked_review is None and not selectable and not wave_active:
|
|
540
610
|
stalled = [
|
|
541
611
|
{
|
|
542
612
|
"id": task.task_id,
|
|
@@ -556,11 +626,17 @@ def ready(repo: str, project_dir: str = DEFAULT_PROJECT_DIR, *,
|
|
|
556
626
|
{"wave": current_wave, "tasks": stalled},
|
|
557
627
|
)
|
|
558
628
|
|
|
629
|
+
typed: Dict[str, object] = {}
|
|
630
|
+
if repair_for_wave is not None:
|
|
631
|
+
typed["repair_for_wave"] = repair_for_wave
|
|
632
|
+
if blocked_review is not None:
|
|
633
|
+
typed["blocked_review"] = blocked_review
|
|
559
634
|
return {
|
|
560
635
|
"command": "ready",
|
|
561
636
|
"branch": project.branch,
|
|
562
637
|
"head": project.head,
|
|
563
638
|
"current_wave": current_wave,
|
|
639
|
+
**typed,
|
|
564
640
|
"ready": [
|
|
565
641
|
{
|
|
566
642
|
"id": task.task_id,
|
|
@@ -8,6 +8,10 @@ with testable claims where every claim row carries a valid type, a valid
|
|
|
8
8
|
verdict, and real evidence, a `## Descriptive docs` list for claimless docs,
|
|
9
9
|
the two sets disjoint and together equal to the frozen inventory, and a
|
|
10
10
|
remediation queue with one classified row per non-verified claim.
|
|
11
|
+
Queue numbers are unique, positive and strictly increasing, not necessarily
|
|
12
|
+
contiguous. With `--prior-audit`, persisting rows keep their number and new
|
|
13
|
+
rows use a number above every prior queue number and User rulings Queue #.
|
|
14
|
+
Numbers stay bound to their original (doc, claim); never reuse a retired one.
|
|
11
15
|
`## User rulings` is fixed-format durable memory. Pass the pre-rewrite audit
|
|
12
16
|
with `--prior-audit FILE`; every prior row, including its Planned value, must
|
|
13
17
|
remain an exact ordered prefix.
|
|
@@ -96,6 +100,12 @@ def _table_rows(body: str, width: int, label: str) -> List[List[str]]:
|
|
|
96
100
|
return rows
|
|
97
101
|
|
|
98
102
|
|
|
103
|
+
def _remediation_queue_rows(body: str, label: str, required: bool = False) -> List[List[str]]:
|
|
104
|
+
if not required and "|" not in body:
|
|
105
|
+
return []
|
|
106
|
+
return _table_rows(body, 6, label)
|
|
107
|
+
|
|
108
|
+
|
|
99
109
|
def _not_placeholder(value: str, label: str) -> None:
|
|
100
110
|
normalized = value.strip().strip("`\"").strip()
|
|
101
111
|
if (
|
|
@@ -247,6 +257,63 @@ def _check_carried(
|
|
|
247
257
|
raise AuditError(f"{label}: doc or evidence changed since the prior audit: {', '.join(moved)}")
|
|
248
258
|
|
|
249
259
|
|
|
260
|
+
def _queue_number(number: str, label: str) -> int:
|
|
261
|
+
if not re.fullmatch(r"[1-9][0-9]*", number):
|
|
262
|
+
raise AuditError(f"{label}: queue numbers must be positive integers")
|
|
263
|
+
return int(number)
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def _check_queue_number_history(
|
|
267
|
+
queue: Sequence[Sequence[str]],
|
|
268
|
+
prior_sections: Dict[str, str],
|
|
269
|
+
) -> None:
|
|
270
|
+
if "Remediation queue" not in prior_sections:
|
|
271
|
+
raise AuditError("prior audit is missing section: ## Remediation queue")
|
|
272
|
+
if "User rulings" not in prior_sections:
|
|
273
|
+
raise AuditError("prior audit is missing section: ## User rulings")
|
|
274
|
+
|
|
275
|
+
prior_queue = _remediation_queue_rows(
|
|
276
|
+
prior_sections["Remediation queue"], "Prior remediation queue"
|
|
277
|
+
)
|
|
278
|
+
prior_items_by_number: Dict[int, tuple] = {}
|
|
279
|
+
prior_numbers_by_item: Dict[tuple, int] = {}
|
|
280
|
+
for number, doc, claim, *_ in prior_queue:
|
|
281
|
+
numeric_number = _queue_number(number, "Prior remediation queue")
|
|
282
|
+
identity = (doc, claim)
|
|
283
|
+
prior_items_by_number[numeric_number] = identity
|
|
284
|
+
prior_numbers_by_item[identity] = numeric_number
|
|
285
|
+
|
|
286
|
+
prior_rulings = _user_rulings(
|
|
287
|
+
prior_sections["User rulings"], "Prior user rulings"
|
|
288
|
+
)
|
|
289
|
+
prior_ruling_numbers = {int(row[0]) for row in prior_rulings}
|
|
290
|
+
prior_max = max(
|
|
291
|
+
[*prior_items_by_number, *prior_ruling_numbers],
|
|
292
|
+
default=0,
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
for number, doc, claim, *_ in queue:
|
|
296
|
+
numeric_number = _queue_number(number, "Remediation queue")
|
|
297
|
+
identity = (doc, claim)
|
|
298
|
+
prior_number = prior_numbers_by_item.get(identity)
|
|
299
|
+
if numeric_number in prior_ruling_numbers and prior_items_by_number.get(numeric_number) != identity:
|
|
300
|
+
raise AuditError(
|
|
301
|
+
f"Remediation queue #{number}: Queue # {number} is already retired by a prior "
|
|
302
|
+
"User rulings row for a different item; give new items a number above every "
|
|
303
|
+
"prior queue number and User rulings Queue #"
|
|
304
|
+
)
|
|
305
|
+
if prior_number is not None and numeric_number != prior_number:
|
|
306
|
+
raise AuditError(
|
|
307
|
+
f"Remediation queue #{number}: persisting item must keep its prior queue "
|
|
308
|
+
f"number #{prior_number}"
|
|
309
|
+
)
|
|
310
|
+
if prior_number is None and numeric_number <= prior_max:
|
|
311
|
+
raise AuditError(
|
|
312
|
+
f"Remediation queue #{number}: new items must use a number above every prior "
|
|
313
|
+
f"queue number and User rulings Queue # (maximum {prior_max})"
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
|
|
250
317
|
def validate(
|
|
251
318
|
repo: Path,
|
|
252
319
|
audit_relative: str,
|
|
@@ -354,7 +421,9 @@ def validate(
|
|
|
354
421
|
|
|
355
422
|
queue_body = sections["Remediation queue"]
|
|
356
423
|
non_verified = sum(tallies[verdict] for verdict in VERDICTS if verdict != "verified")
|
|
357
|
-
queue =
|
|
424
|
+
queue = _remediation_queue_rows(
|
|
425
|
+
queue_body, "Remediation queue", required=bool(non_verified)
|
|
426
|
+
)
|
|
358
427
|
expected_queue = sorted(
|
|
359
428
|
(doc, claim["claim"], claim["verdict"])
|
|
360
429
|
for doc, claims in docs.items()
|
|
@@ -371,9 +440,13 @@ def validate(
|
|
|
371
440
|
_not_placeholder(action, f"Remediation queue #{number}: action")
|
|
372
441
|
if len(queue) != non_verified:
|
|
373
442
|
raise AuditError(f"Remediation queue has {len(queue)} rows for {non_verified} non-verified claims")
|
|
374
|
-
numbers = [row[0] for row in queue]
|
|
375
|
-
if
|
|
376
|
-
raise AuditError(
|
|
443
|
+
numbers = [_queue_number(row[0], "Remediation queue") for row in queue]
|
|
444
|
+
if any(later <= earlier for earlier, later in zip(numbers, numbers[1:])):
|
|
445
|
+
raise AuditError(
|
|
446
|
+
"Remediation queue numbers must be unique and strictly increasing"
|
|
447
|
+
)
|
|
448
|
+
if prior_sections is not None:
|
|
449
|
+
_check_queue_number_history(queue, prior_sections)
|
|
377
450
|
actual_queue = sorted((doc, claim, verdict) for _, doc, claim, verdict, _, _ in queue)
|
|
378
451
|
if actual_queue != expected_queue:
|
|
379
452
|
raise AuditError(
|