@danmoisan/drm-copilot-mcp 1.1.17 → 1.1.19
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/out/mcp-server.js +1405 -684
- package/package.json +6 -4
- package/resources/claude-customizations/.claude/agents/atomic-executor.md +11 -0
- package/resources/claude-customizations/.claude/agents/atomic-planner.md +10 -0
- package/resources/claude-customizations/.claude/agents/epic-orchestrator.md +12 -4
- package/resources/claude-customizations/.claude/agents/epic-planner.md +5 -4
- package/resources/claude-customizations/.claude/agents/feature-review.md +16 -5
- package/resources/claude-customizations/.claude/agents/orchestrator.md +21 -7
- package/resources/claude-customizations/.claude/agents/parallel-orchestrator.md +37 -13
- package/resources/claude-customizations/.claude/agents/parallel-planner.md +9 -6
- package/resources/claude-customizations/.claude/agents/pr-author.md +15 -2
- package/resources/claude-customizations/.claude/agents/prd-feature.md +1 -1
- package/resources/claude-customizations/.claude/hooks/check-powershell-test-purity.ps1 +7 -1
- package/resources/claude-customizations/.claude/hooks/check-python-test-purity.ps1 +7 -1
- package/resources/claude-customizations/.claude/hooks/enforce-checkpoint-monotonic.ps1 +7 -1
- package/resources/claude-customizations/.claude/hooks/enforce-completion-consistency.ps1 +111 -46
- package/resources/claude-customizations/.claude/hooks/enforce-completion-helpers.ps1 +105 -0
- package/resources/claude-customizations/.claude/hooks/enforce-discovery-artifact-gate.ps1 +8 -1
- package/resources/claude-customizations/.claude/hooks/enforce-epic-invocation-origin.ps1 +7 -1
- package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate-resolution.ps1 +116 -59
- package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate.ps1 +55 -23
- package/resources/claude-customizations/.claude/hooks/enforce-epic-wave-barrier.ps1 +74 -75
- package/resources/claude-customizations/.claude/hooks/enforce-epic-worktree-removal-gate-resolution.ps1 +127 -35
- package/resources/claude-customizations/.claude/hooks/enforce-epic-worktree-removal-gate.ps1 +61 -57
- package/resources/claude-customizations/.claude/hooks/enforce-evidence-locations.ps1 +7 -1
- package/resources/claude-customizations/.claude/hooks/enforce-feature-folder-order.ps1 +129 -39
- package/resources/claude-customizations/.claude/hooks/enforce-mermaid-validation.ps1 +7 -1
- package/resources/claude-customizations/.claude/hooks/enforce-model-routing-receipt.ps1 +9 -3
- package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-epic-scope.ps1 +39 -51
- package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-helpers.ps1 +31 -58
- package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-modes.ps1 +63 -47
- package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-targets.ps1 +433 -0
- package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate.ps1 +17 -12
- package/resources/claude-customizations/.claude/hooks/enforce-parallel-abandon-gate.ps1 +9 -3
- package/resources/claude-customizations/.claude/hooks/enforce-parallel-cohort-barrier.ps1 +65 -50
- package/resources/claude-customizations/.claude/hooks/enforce-parallel-drift-gate.ps1 +49 -42
- package/resources/claude-customizations/.claude/hooks/enforce-parallel-worktree-removal-gate.ps1 +54 -72
- package/resources/claude-customizations/.claude/hooks/enforce-powershell-batch-budget.ps1 +8 -2
- package/resources/claude-customizations/.claude/hooks/enforce-pr-author-command-allowlist.ps1 +279 -0
- package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill-helpers.ps1 +129 -75
- package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.artifact-root.ps1 +233 -0
- package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.docs-only.ps1 +224 -0
- package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.ps1 +69 -24
- package/resources/claude-customizations/.claude/hooks/enforce-prd-feature-before-planner-helpers.ps1 +29 -18
- package/resources/claude-customizations/.claude/hooks/enforce-prd-feature-before-planner.ps1 +10 -4
- package/resources/claude-customizations/.claude/hooks/enforce-promotion-mcp-only.ps1 +14 -5
- package/resources/claude-customizations/.claude/hooks/enforce-python-batch-budget.ps1 +8 -2
- package/resources/claude-customizations/.claude/hooks/feature-folder-resolution.ps1 +373 -0
- package/resources/claude-customizations/.claude/hooks/feature-review-coverage-thresholds.ps1 +85 -0
- package/resources/claude-customizations/.claude/hooks/hook-command-heredoc.ps1 +119 -0
- package/resources/claude-customizations/.claude/hooks/hook-command-invocation-operands.ps1 +198 -0
- package/resources/claude-customizations/.claude/hooks/hook-command-invocation.ps1 +254 -255
- package/resources/claude-customizations/.claude/hooks/hook-command-payload-powershell.ps1 +201 -0
- package/resources/claude-customizations/.claude/hooks/hook-command-payload.ps1 +484 -0
- package/resources/claude-customizations/.claude/hooks/hook-command-scanner.ps1 +27 -110
- package/resources/claude-customizations/.claude/hooks/hook-dependency-guard.ps1 +114 -0
- package/resources/claude-customizations/.claude/hooks/hook-docs-only-diff.ps1 +493 -0
- package/resources/claude-customizations/.claude/hooks/subagentstop-envelope.ps1 +192 -0
- package/resources/claude-customizations/.claude/hooks/validate-bash.ps1 +9 -3
- package/resources/claude-customizations/.claude/hooks/validate-discovery-artifact-gate.ps1 +40 -42
- package/resources/claude-customizations/.claude/hooks/validate-executor-output.ps1 +66 -38
- package/resources/claude-customizations/.claude/hooks/validate-feature-review-coverage-metrics.ps1 +180 -0
- package/resources/claude-customizations/.claude/hooks/validate-feature-review-coverage-rules.ps1 +195 -0
- package/resources/claude-customizations/.claude/hooks/validate-feature-review-coverage.ps1 +141 -395
- package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output-resolution.ps1 +311 -0
- package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output-routing.ps1 +170 -0
- package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output.ps1 +115 -190
- package/resources/claude-customizations/.claude/hooks/validate-planner-output.ps1 +64 -32
- package/resources/claude-customizations/.claude/hooks/validate-pr-author-output.ps1 +39 -44
- package/resources/claude-customizations/.claude/hooks/validate-prd-feature-output.ps1 +43 -14
- package/resources/claude-customizations/.claude/hooks/validate-required-artifact-output.ps1 +66 -36
- package/resources/claude-customizations/.claude/hooks/validate-task-researcher-output.ps1 +31 -34
- package/resources/claude-customizations/.claude/lib/bash/mutate-parallel-run.sh +191 -0
- package/resources/claude-customizations/.claude/lib/bash/parallel-cohorts.sh +13 -3
- package/resources/claude-customizations/.claude/lib/bash/parallel-lane-assertion.sh +4 -2
- package/resources/claude-customizations/.claude/lib/bash/parallel-mutation-cli.sh +152 -0
- package/resources/claude-customizations/.claude/lib/bash/parallel-mutation-ops.sh +193 -0
- package/resources/claude-customizations/.claude/lib/bash/parallel-mutation.sh +322 -0
- package/resources/claude-customizations/.claude/lib/bash/remove-parallel-item.sh +146 -0
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusExtraction.psm1 +23 -33
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusTokenShape.psm1 +86 -6
- package/resources/claude-customizations/.claude/lib/ci-gate/Invoke-CiGateParser.ps1 +91 -19
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorState.psm1 +6 -13
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateEpicWaveBarrier.psm1 +346 -0
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateIssueAdoption.psm1 +396 -0
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateReceipts.psm1 +22 -15
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateRemediationAccounting.psm1 +337 -0
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateRoutingContract.psm1 +9 -1
- package/resources/claude-customizations/.claude/lib/worktree-resolution/WorktreeItemResolution.psm1 +79 -2
- package/resources/claude-customizations/.claude/lib/worktree-resolution/WorktreeRunResolution.psm1 +3 -3
- package/resources/claude-customizations/.claude/rules/architecture-boundaries.md +5 -5
- package/resources/claude-customizations/.claude/rules/csharp.md +2 -2
- package/resources/claude-customizations/.claude/rules/general-code-change.md +1 -1
- package/resources/claude-customizations/.claude/rules/general-unit-test.md +3 -2
- package/resources/claude-customizations/.claude/rules/orchestrator-state.md +153 -4
- package/resources/claude-customizations/.claude/rules/parallel-orchestration.md +50 -5
- package/resources/claude-customizations/.claude/rules/plan-acceptance-gates.md +47 -8
- package/resources/claude-customizations/.claude/rules/quality-tiers.md +11 -7
- package/resources/claude-customizations/.claude/rules/shell.md +10 -8
- package/resources/claude-customizations/.claude/rules/typescript.md +1 -1
- package/resources/claude-customizations/.claude/settings.json +3 -4
- package/resources/claude-customizations/.claude/skills/acceptance-criteria-tracking/SKILL.md +9 -1
- package/resources/claude-customizations/.claude/skills/atomic-plan-contract/SKILL.md +7 -1
- package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/SKILL.md +11 -3
- package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup-worktrees.sh +11 -2
- package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_detached_lib.sh +1 -1
- package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_enumerate_lib.sh +171 -5
- package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_preserve_lib.sh +1 -1
- package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_report_records_lib.sh +6 -43
- package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_scan_helper.sh +6 -15
- package/resources/claude-customizations/.claude/skills/epic-orchestrate/SKILL.md +45 -11
- package/resources/claude-customizations/.claude/skills/epic-plan/SKILL.md +1 -1
- package/resources/claude-customizations/.claude/skills/evidence-and-timestamp-conventions/SKILL.md +13 -0
- package/resources/claude-customizations/.claude/skills/feature-promotion-lifecycle/SKILL.md +10 -0
- package/resources/claude-customizations/.claude/skills/feature-review-workflow/SKILL.md +7 -4
- package/resources/claude-customizations/.claude/skills/orchestrate/SKILL.md +42 -16
- package/resources/claude-customizations/.claude/skills/parallel-add/SKILL.md +52 -14
- package/resources/claude-customizations/.claude/skills/parallel-close/SKILL.md +22 -9
- package/resources/claude-customizations/.claude/skills/parallel-orchestrate/SKILL.md +97 -19
- package/resources/claude-customizations/.claude/skills/parallel-plan/SKILL.md +63 -7
- package/resources/claude-customizations/.claude/skills/parallel-remove/SKILL.md +35 -12
- package/resources/claude-customizations/.claude/skills/pr-author/SKILL.md +3 -1
- package/resources/claude-customizations/.claude/skills/quota-throttling/SKILL.md +1 -1
- package/resources/claude-customizations/.claude/skills/remediation-handoff-atomic-planner/SKILL.md +7 -3
- package/resources/claude-customizations/pack-manifests/core.json +25 -0
- package/resources/codex-and-agents-customizations/.agents/skills/acceptance-criteria-tracking/SKILL.md +9 -1
- package/resources/codex-and-agents-customizations/.agents/skills/architecture-boundaries/SKILL.md +5 -5
- package/resources/codex-and-agents-customizations/.agents/skills/atomic-executor/SKILL.md +11 -0
- package/resources/codex-and-agents-customizations/.agents/skills/atomic-plan-contract/SKILL.md +4 -0
- package/resources/codex-and-agents-customizations/.agents/skills/atomic-planner/SKILL.md +10 -0
- package/resources/codex-and-agents-customizations/.agents/skills/csharp/SKILL.md +2 -2
- package/resources/codex-and-agents-customizations/.agents/skills/csharp-qa-gate/SKILL.md +2 -2
- package/resources/codex-and-agents-customizations/.agents/skills/epic-orchestrate/SKILL.md +13 -3
- package/resources/codex-and-agents-customizations/.agents/skills/epic-plan/SKILL.md +17 -1
- package/resources/codex-and-agents-customizations/.agents/skills/epic-run/SKILL.md +2 -1
- package/resources/codex-and-agents-customizations/.agents/skills/evidence-and-timestamp-conventions/SKILL.md +13 -0
- package/resources/codex-and-agents-customizations/.agents/skills/feature-promotion-lifecycle/SKILL.md +1 -1
- package/resources/codex-and-agents-customizations/.agents/skills/feature-review/SKILL.md +30 -6
- package/resources/codex-and-agents-customizations/.agents/skills/feature-review-workflow/SKILL.md +16 -6
- package/resources/codex-and-agents-customizations/.agents/skills/general-code-change/SKILL.md +1 -1
- package/resources/codex-and-agents-customizations/.agents/skills/general-unit-test/SKILL.md +3 -2
- package/resources/codex-and-agents-customizations/.agents/skills/orchestrate/SKILL.md +43 -11
- package/resources/codex-and-agents-customizations/.agents/skills/orchestrator-state/SKILL.md +41 -2
- package/resources/codex-and-agents-customizations/.agents/skills/orchestrator-workflow/SKILL.md +19 -4
- package/resources/codex-and-agents-customizations/.agents/skills/quality-tiers/SKILL.md +11 -7
- package/resources/codex-and-agents-customizations/.agents/skills/remediation-handoff-atomic-planner/SKILL.md +2 -0
- package/resources/codex-and-agents-customizations/.agents/skills/translate-claude-to-codex/SKILL.md +1 -1
- package/resources/codex-and-agents-customizations/.agents-variants/csharp-legacy/skills/csharp/SKILL.md +2 -2
- package/resources/codex-and-agents-customizations/.agents-variants/csharp-legacy/skills/csharp-qa-gate/SKILL.md +2 -2
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c1.toml +11 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c2.toml +11 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c3-elevated.toml +11 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c3.toml +11 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c4.toml +11 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor.toml +11 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c1.toml +10 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c2.toml +10 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c3-elevated.toml +10 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c3.toml +10 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c4.toml +10 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner.toml +10 -0
- package/resources/codex-and-agents-customizations/.codex/agents/epic-orchestrator.toml +2 -1
- package/resources/codex-and-agents-customizations/.codex/agents/feature-review.toml +6 -6
- package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c1.toml +1 -0
- package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c2.toml +1 -0
- package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c3-elevated.toml +1 -0
- package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c3.toml +1 -0
- package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c4.toml +1 -0
- package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer.toml +1 -0
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c1.toml +3 -3
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c2.toml +3 -3
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c3-elevated.toml +3 -3
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c3.toml +3 -3
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c4.toml +3 -3
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator.toml +3 -3
- package/resources/codex-and-agents-customizations/.codex/codex-web-setup.sh +318 -273
- package/resources/codex-and-agents-customizations/.codex/config.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/check-powershell-test-purity.ps1 +7 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/check-python-test-purity.ps1 +7 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/codex-epic-child-launch-attestation.ps1 +1 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-checkpoint-monotonic.ps1 +7 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-codex-model-routing.ps1 +8 -2
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-completion-consistency.ps1 +97 -44
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-completion-helpers.ps1 +105 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-child-worktree-binding.ps1 +7 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-merge-gate.ps1 +37 -5
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-planning-only.ps1 +6 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-root-invocation.ps1 +7 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-wave-barrier.ps1 +7 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-worktree-removal-gate.ps1 +54 -41
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-evidence-locations.ps1 +7 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-epic-scope.ps1 +35 -14
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-helpers.ps1 +31 -58
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-modes.ps1 +63 -47
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-targets.ps1 +433 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate.ps1 +24 -11
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-powershell-batch-budget.ps1 +8 -2
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-promotion-mcp-only.ps1 +13 -4
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-python-batch-budget.ps1 +8 -2
- package/resources/codex-and-agents-customizations/.codex/hooks/feature-folder-resolution.ps1 +373 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/feature-review-coverage-thresholds.ps1 +85 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-heredoc.ps1 +119 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-invocation-operands.ps1 +198 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-invocation.ps1 +254 -255
- package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-payload-powershell.ps1 +201 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-payload.ps1 +484 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-scanner.ps1 +27 -110
- package/resources/codex-and-agents-customizations/.codex/hooks/hook-dependency-guard.ps1 +114 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/hook-docs-only-diff.ps1 +493 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/validate-bash.ps1 +8 -2
- package/resources/codex-and-agents-customizations/.codex/hooks/validate-codex-subagent-routing.ps1 +7 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/validate-feature-review-coverage.ps1 +24 -8
- package/resources/codex-and-agents-customizations/pack-manifests/core.json +9 -0
- package/resources/customizations/.github/agents/csharp-typed-engineer.agent.md +2 -2
- package/resources/customizations/.github/instructions/csharp-code-change.instructions.md +4 -4
- package/resources/customizations/.github/instructions/csharp-unit-test.instructions.md +2 -2
- package/resources/customizations/.github/skills/acceptance-criteria-tracking/SKILL.md +9 -1
- package/resources/customizations/.github/skills/atomic-plan-contract/SKILL.md +4 -0
- package/resources/customizations/.github/skills/evidence-and-timestamp-conventions/SKILL.md +13 -0
- package/resources/customizations/.github/skills/feature-review-workflow/SKILL.md +1 -1
- package/resources/powershell/PoshQC/PoshQC.Coverage.psm1 +314 -0
- package/resources/powershell/PoshQC/PoshQC.Testing.psm1 +25 -28
- package/resources/powershell/PoshQC/PoshQC.psm1 +1 -0
- package/resources/powershell/PoshQC/README.md +8 -2
- package/resources/powershell/PoshQC/settings/pester.runsettings.psd1 +2 -315
|
@@ -104,6 +104,10 @@ For short-path/minimal-audit plans, Phase 0 evidence is incomplete unless both a
|
|
|
104
104
|
|
|
105
105
|
`Output Summary:` is mandatory for each command-step artifact and must concisely summarize the essential result signal (for example: pass/fail status, key counts, coverage headline, or primary diagnostic).
|
|
106
106
|
|
|
107
|
+
## Evidence Filename Timestamps in Plans
|
|
108
|
+
|
|
109
|
+
Plans name evidence artifacts `<name>.<timestamp>.md` and never fix a plan-time stamp in an evidence filename. An acceptance condition identifies a consumed evidence artifact by the derivation in `evidence-and-timestamp-conventions` (`### Evidence Filename Timestamp`): the lexicographically greatest file matching `<name>.*.md`, not a pre-stamped literal path. This section governs artifact paths only: asserted search tokens remain concrete.
|
|
110
|
+
|
|
107
111
|
## Coverage Evidence Contract (Mandatory when policy requires coverage)
|
|
108
112
|
|
|
109
113
|
For any language in scope where repository policy requires coverage validation:
|
|
@@ -191,7 +195,7 @@ Before a plan can be treated as approved:
|
|
|
191
195
|
|
|
192
196
|
The same validator call also applies the acceptance-gate rules G1 through G6 defined in `.claude/rules/plan-acceptance-gates.md`. Those rules report acceptance conditions that cannot fail — a coverage argument that collects no data, or a search for a literal that returns zero matches whatever the executor does. They run automatically on the existing `plan` route with no additional flag. Blocking findings appear in the validator's error output and fail the gate; Warnings are surfaced without failing it, prefixed with `PLAN GATE WARNING: ` on the CLI and carried on the optional `warnings` field of the MCP result. Read that rule file before authoring acceptance conditions.
|
|
193
197
|
|
|
194
|
-
The same call additionally applies the rules G7, G8, G8b, and G9, which report a write-mode command observed only by its exit code, an unanchored `git diff`, a name-listing diff with no companion span, and a coverage command that prints no table. All four ship in the Warning channel, so they surface without failing the gate. The complete shipped set is therefore G1 through
|
|
198
|
+
The same call additionally applies the rules G7, G8, G8b, and G9, which report a write-mode command observed only by its exit code, an unanchored `git diff`, a name-listing diff with no companion span, and a coverage command that prints no table. All four ship in the Warning channel, so they surface without failing the gate. The same call also applies G10, a document-level rule that reports a SCRATCH definition not namespaced by issue number. G10 ships in the Blocking channel and reports each finding with a `Line N: ` prefix rather than a task identifier, because the definition sits outside any task window. The complete shipped set is therefore G1 through G10.
|
|
195
199
|
|
|
196
200
|
## Wrap-Tolerant Assertion Authoring (Mandatory)
|
|
197
201
|
|
|
@@ -212,6 +216,8 @@ Rules:
|
|
|
212
216
|
- **Observe a command's success-case output before asserting over that output (mandatory).** Run the command, or read a recorded run of it, and confirm the value you intend to assert is actually printed on a *successful* run. Do not infer it from the tool's documentation, from the plan, or from what the tool prints on failure. This requirement exists because the class of defect it prevents is not detectable by reading: an assertion on a line the tool prints only when it changed something is unsatisfiable on a clean run; a demand for a zero-diagnostic count from a tool that returns only an ok flag names a value with no source; a demand for separate line and branch percentages from a coverage run that prints one combined column reads two numbers that are never printed. G7 and G9 cover two decidable slices of this class. The remainder is covered by this requirement and by nothing else, so a reviewer cannot rely on the gate to catch it.
|
|
213
217
|
- **Fix the evidence in the plan; never leave the executor to select it.** An executor free to choose the evidence it is judged against cannot fail. Do not write an acceptance condition that asks the executor to identify "the known-genuine pair", to choose a survivor list, or to pick any suitable instance. Name the instances, or state the mechanical derivation that produces them, so a third party re-running it obtains the same set. This is authoring guidance and not a rule: a validator rule that scanned acceptance text for selection vocabulary was proposed and rejected, because that vocabulary is ordinary plan prose used in roles carrying no selection semantics and a keyword scan over prose is not statically decidable for the property it would claim to detect. The judgment is the author's, and it is not automated. `.claude/rules/plan-acceptance-gates.md` records the rejection and the reason for it.
|
|
214
218
|
- **Check that the task-ordering does not make the condition unsatisfiable.** No rule covers this. A gate that runs a test path containing deliberately-failing cases added by an earlier task, before the later task that makes them pass, cannot exit 0. A baseline captured after a write-mode formatter has already repaired pre-existing drift becomes either a blanket waiver or makes a later gate unsatisfiable. Read each acceptance condition against the state the plan will actually be in when its task runs.
|
|
219
|
+
- **Name the runner and job for a Pester acceptance criterion.** CI runs Pester in two jobs of `.github/workflows/_poshqc.yml`: `poshqc / PowerShell QC` runs every suite with coverage on `windows-latest`, and `poshqc / PowerShell hook suites (Linux)` runs only `tests/scripts/claude-hooks` and `tests/scripts/codex-hooks` on `ubuntu-latest`, with coverage disabled. A Pester acceptance criterion may cite `ubuntu-latest` only for suites under `tests/scripts/claude-hooks` or `tests/scripts/codex-hooks`, never for coverage, and must name the job it relies on (`poshqc / PowerShell QC` or `poshqc / PowerShell hook suites (Linux)`).
|
|
220
|
+
- **Do not assert a fixed-string search literal that contains a backslash.** Git for Windows grep 3.0 reads a doubled backslash in a `grep -F` pattern as one backslash, so the same check returns a different count locally than on a CI runner and cannot pass in both places. Assert a backslash-free substring of the literal, a named test, or a hash or byte-identity check instead.
|
|
215
221
|
|
|
216
222
|
## Plan-Path Continuity Contract (Mandatory)
|
|
217
223
|
|
|
@@ -128,9 +128,17 @@ The script emits pipe-delimited, `LC_ALL=C`-ordered records, one per line:
|
|
|
128
128
|
per-file outcome is reported by the companion `ACTION|preserve-stage|...` record.
|
|
129
129
|
- `ORPHAN_DIR|<path>|<size>` — a directory under a worktree-tracking root that carries
|
|
130
130
|
no `.git` pointer file and no `git worktree list` entry. `<size>` is best-effort and
|
|
131
|
-
may be the literal `unknown`. The
|
|
132
|
-
|
|
133
|
-
|
|
131
|
+
may be the literal `unknown`. The scanned roots are the default pair
|
|
132
|
+
`<main>/.claude/worktrees` and `<main>-wt`, or the `CLEANUP_WT_ORPHAN_ROOTS` entries
|
|
133
|
+
when that variable is set (the override replaces the default pair), plus the parent
|
|
134
|
+
directory of every non-main registered worktree, which is always added. A derived
|
|
135
|
+
parent is skipped when it is the main worktree or one of its ancestors, or is equal to
|
|
136
|
+
or inside a registered worktree. `CLEANUP_WT_ORPHAN_ROOTS` entries are separated by a
|
|
137
|
+
semicolon, a newline, or a colon; a colon that follows a single drive letter and
|
|
138
|
+
precedes `/` or `\` is part of the path, and empty or relative entries are dropped.
|
|
139
|
+
The record is advisory: it reports the directory, and nothing in apply mode acts on
|
|
140
|
+
it. For the disposition, see the Dirty Worktree Triage Procedure's step 7, which
|
|
141
|
+
governs how an orphaned directory is handled.
|
|
134
142
|
- `STALE_REF|<refname>` — a `refs/remotes/<name>/*` ref whose `<name>` is not a
|
|
135
143
|
configured remote, named in full ref form. Advisory only; no ref is ever pruned by
|
|
136
144
|
this tool.
|
|
@@ -139,8 +139,17 @@ Environment overrides:
|
|
|
139
139
|
nonexistent value is treated as missing (falls back to
|
|
140
140
|
the bundled cleanup_worktrees_scan_helper.sh). This is
|
|
141
141
|
the filesystem-scan test-stub seam.
|
|
142
|
-
CLEANUP_WT_ORPHAN_ROOTS
|
|
143
|
-
|
|
142
|
+
CLEANUP_WT_ORPHAN_ROOTS Worktree-tracking roots scanned for ORPHAN_DIR and
|
|
143
|
+
WARN|registration-lost. Entries are separated by a
|
|
144
|
+
semicolon, a newline, or a colon; a colon that follows
|
|
145
|
+
a single drive letter and precedes / or \ is part of
|
|
146
|
+
the path (C:/x). Empty and relative entries are
|
|
147
|
+
dropped. When set, it replaces the default pair
|
|
148
|
+
<main>/.claude/worktrees and <main>-wt. The parent of
|
|
149
|
+
every non-main registered worktree is always added,
|
|
150
|
+
except a parent that is the main worktree or its
|
|
151
|
+
ancestor, or is equal to or inside a registered
|
|
152
|
+
worktree.
|
|
144
153
|
CLEANUP_WT_STUB_SCENARIO Scenario directory consumed by the checked-in git and
|
|
145
154
|
scan stubs (tests only).
|
|
146
155
|
CLEANUP_WT_CONSOLIDATION_PATH Override the derived consolidation worktree path
|
|
@@ -43,7 +43,7 @@ is_detached_candidate() {
|
|
|
43
43
|
#
|
|
44
44
|
# The predicate is the porcelain FLAG, not the branch field: emit_record writes the
|
|
45
45
|
# literal DETACHED into the branch field whenever the branch accumulator is empty
|
|
46
|
-
# (
|
|
46
|
+
# (emit_record, nested in parse_worktree_list in cleanup_worktrees_enumerate_lib.sh), which is also true of a
|
|
47
47
|
# bare-repository stanza, and a local branch literally named DETACHED would produce
|
|
48
48
|
# the same branch field with no `detached` flag.
|
|
49
49
|
#
|
|
@@ -4,16 +4,19 @@
|
|
|
4
4
|
# every file within the 500-line cap. Provides the git-binary test seam
|
|
5
5
|
# (cleanup_wt_git), branch/worktree enumeration (enumerate_branches,
|
|
6
6
|
# parse_worktree_list), path normalization (normalize_wt_path), the
|
|
7
|
-
# current-worktree/branch and base-branch protection set (compute_protected),
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
7
|
+
# current-worktree/branch and base-branch protection set (compute_protected), the
|
|
8
|
+
# main-freshness warning (check_main_freshness), the shared absolute-path predicate
|
|
9
|
+
# (cleanup_wt_is_absolute_path), and the worktree-tracking scan roots
|
|
10
|
+
# (cleanup_wt_split_roots, cleanup_wt_derive_scan_roots, cleanup_wt_scan_roots). The
|
|
11
|
+
# classification ladder, consolidation, deletion, and the CLI live in sibling files
|
|
12
|
+
# (cleanup_worktrees_lib.sh, cleanup_worktrees_actions_lib.sh, cleanup-worktrees.sh).
|
|
11
13
|
#
|
|
12
14
|
# Sourcing contract: defines functions and the single constant CLEANUP_WT_BASE_BRANCH
|
|
13
15
|
# and runs no other work at source time, so wrapper and bats suites source it safely.
|
|
14
16
|
# It MUST be sourced before cleanup_worktrees_lib.sh, whose classification functions
|
|
15
17
|
# call cleanup_wt_git, parse_worktree_list, compute_protected, and normalize_wt_path
|
|
16
|
-
# defined here.
|
|
18
|
+
# defined here. The filesystem-scan helper cleanup_worktrees_scan_helper.sh runs as a
|
|
19
|
+
# separate process and sources this library directly for cleanup_wt_is_absolute_path.
|
|
17
20
|
#
|
|
18
21
|
# All git commands go through cleanup_wt_git so tests can stub the git binary via
|
|
19
22
|
# CLEANUP_WT_GIT_BIN. Git exit-code capture rule: the `git worktree list --porcelain`
|
|
@@ -250,3 +253,166 @@ check_main_freshness() {
|
|
|
250
253
|
fi
|
|
251
254
|
return 0
|
|
252
255
|
}
|
|
256
|
+
|
|
257
|
+
cleanup_wt_is_absolute_path() {
|
|
258
|
+
# Return 0 when <path> is absolute, else 1. Pure: no filesystem access.
|
|
259
|
+
#
|
|
260
|
+
# Absolute forms are a leading `/` (POSIX paths, MSYS `/c/...` paths, and `//server`
|
|
261
|
+
# UNC paths) and a drive letter followed by `/` or `\` (`C:/...`, `c:/...`,
|
|
262
|
+
# `C:\...`), which is the form Git for Windows writes into a worktree's `.git`
|
|
263
|
+
# pointer file (issue #706). A drive letter with no separator (`C:rel`) is
|
|
264
|
+
# drive-relative and is not absolute; an empty path is not absolute. This is the one
|
|
265
|
+
# absolute-path predicate of the skill: the preserve library and the filesystem-scan
|
|
266
|
+
# helper both call it.
|
|
267
|
+
#
|
|
268
|
+
# Args: $1 = path. Returns 0 (absolute) or 1 (not absolute).
|
|
269
|
+
local path=${1:-}
|
|
270
|
+
[[ $path == /* || $path == [A-Za-z]:[/\\]* ]]
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
cleanup_wt_split_roots() {
|
|
274
|
+
# Split a CLEANUP_WT_ORPHAN_ROOTS value into absolute roots, one per line.
|
|
275
|
+
#
|
|
276
|
+
# Entries are separated by `;`, by a newline, or by `:`. A `:` is part of the path
|
|
277
|
+
# instead when the text before it in the current entry is exactly one ASCII letter
|
|
278
|
+
# and the character after it is `/` or `\` (a drive letter, as in `C:/x`). Empty
|
|
279
|
+
# entries are dropped. An entry that is not absolute (cleanup_wt_is_absolute_path) is
|
|
280
|
+
# dropped with a one-line stderr diagnostic naming it, because a relative root would
|
|
281
|
+
# be resolved against the process's current working directory.
|
|
282
|
+
#
|
|
283
|
+
# The value is walked one character at a time with parameter expansion and never
|
|
284
|
+
# word-split, so no pathname expansion occurs and a `*` is emitted literally.
|
|
285
|
+
#
|
|
286
|
+
# Args: $1 = the override value. Always returns 0.
|
|
287
|
+
local value=${1:-}
|
|
288
|
+
local -a entries=()
|
|
289
|
+
local entry="" ch next i
|
|
290
|
+
for ((i = 0; i < ${#value}; i++)); do
|
|
291
|
+
ch=${value:i:1}
|
|
292
|
+
if [[ $ch == ';' || $ch == $'\n' ]]; then
|
|
293
|
+
entries+=("$entry")
|
|
294
|
+
entry=""
|
|
295
|
+
elif [[ $ch == ':' ]]; then
|
|
296
|
+
next=${value:i+1:1}
|
|
297
|
+
if [[ ${#entry} -eq 1 && $entry == [A-Za-z] && $next == [/\\] ]]; then
|
|
298
|
+
entry+=$ch
|
|
299
|
+
else
|
|
300
|
+
entries+=("$entry")
|
|
301
|
+
entry=""
|
|
302
|
+
fi
|
|
303
|
+
else
|
|
304
|
+
entry+=$ch
|
|
305
|
+
fi
|
|
306
|
+
done
|
|
307
|
+
entries+=("$entry")
|
|
308
|
+
for entry in "${entries[@]}"; do
|
|
309
|
+
[[ -z $entry ]] && continue
|
|
310
|
+
if ! cleanup_wt_is_absolute_path "$entry"; then
|
|
311
|
+
printf 'cleanup-worktrees: CLEANUP_WT_ORPHAN_ROOTS entry is not absolute, dropped: %s\n' "$entry" >&2
|
|
312
|
+
continue
|
|
313
|
+
fi
|
|
314
|
+
printf '%s\n' "$entry"
|
|
315
|
+
done
|
|
316
|
+
return 0
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
cleanup_wt_derive_scan_roots() {
|
|
320
|
+
# Echo the registration-derived scan roots, one per line.
|
|
321
|
+
#
|
|
322
|
+
# Input is parse_worktree_list output; its first record is the main worktree. The
|
|
323
|
+
# candidate for every later record is the parent directory of its path (backslashes
|
|
324
|
+
# converted to `/`). A candidate is kept only when its normalize_wt_path value N:
|
|
325
|
+
# - is not the main worktree's normalized path and is not one of its ancestors
|
|
326
|
+
# (scanning an ancestor would list the main worktree's siblings), and
|
|
327
|
+
# - is not equal to, and not inside, any registered worktree, main included
|
|
328
|
+
# (its subdirectories are that worktree's own content, not worktrees).
|
|
329
|
+
# Kept candidates are emitted in LC_ALL=C order of N, once per N, using the first
|
|
330
|
+
# spelling seen in record order.
|
|
331
|
+
#
|
|
332
|
+
# Args: $1 = parse_worktree_list output. Always returns 0.
|
|
333
|
+
local records=${1:-}
|
|
334
|
+
local -a paths=() norms=()
|
|
335
|
+
local record path
|
|
336
|
+
while IFS= read -r record; do
|
|
337
|
+
[[ -z $record ]] && continue
|
|
338
|
+
path=${record%%|*}
|
|
339
|
+
paths+=("$path")
|
|
340
|
+
norms+=("$(normalize_wt_path "$path")")
|
|
341
|
+
done <<<"$records"
|
|
342
|
+
((${#paths[@]} < 2)) && return 0
|
|
343
|
+
local main_norm=${norms[0]}
|
|
344
|
+
local -A seen=()
|
|
345
|
+
local -a kept=()
|
|
346
|
+
local i p parent n w inside
|
|
347
|
+
for ((i = 1; i < ${#paths[@]}; i++)); do
|
|
348
|
+
p=${paths[i]//\\//}
|
|
349
|
+
parent=${p%/*}
|
|
350
|
+
[[ -z $parent || $parent == "$p" ]] && continue
|
|
351
|
+
# A drive-relative parent (a registration directly under a drive root, such as D:/wt) is not an absolute root and is dropped.
|
|
352
|
+
cleanup_wt_is_absolute_path "$parent" || continue
|
|
353
|
+
n=$(normalize_wt_path "$parent")
|
|
354
|
+
[[ -z $n || -n ${seen[$n]:-} ]] && continue
|
|
355
|
+
[[ $n == "$main_norm" || $main_norm == "$n"/* ]] && continue
|
|
356
|
+
inside=0
|
|
357
|
+
for w in "${norms[@]}"; do
|
|
358
|
+
[[ -z $w ]] && continue
|
|
359
|
+
if [[ $n == "$w" || $n == "$w"/* ]]; then
|
|
360
|
+
inside=1
|
|
361
|
+
break
|
|
362
|
+
fi
|
|
363
|
+
done
|
|
364
|
+
((inside == 1)) && continue
|
|
365
|
+
seen[$n]=1
|
|
366
|
+
kept+=("$n|$parent")
|
|
367
|
+
done
|
|
368
|
+
((${#kept[@]} == 0)) && return 0
|
|
369
|
+
local line
|
|
370
|
+
while IFS= read -r line; do
|
|
371
|
+
printf '%s\n' "${line#*|}"
|
|
372
|
+
done < <(printf '%s\n' "${kept[@]}" | LC_ALL=C sort -t '|' -k1,1)
|
|
373
|
+
return 0
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
cleanup_wt_scan_roots() {
|
|
377
|
+
# Echo the worktree-tracking roots to scan, one per line.
|
|
378
|
+
#
|
|
379
|
+
# Configured roots come first: the CLEANUP_WT_ORPHAN_ROOTS entries
|
|
380
|
+
# (cleanup_wt_split_roots) when that variable is set, otherwise the default pair
|
|
381
|
+
# derived from the main worktree path (the first `git worktree list --porcelain`
|
|
382
|
+
# stanza, the same derivation consolidation_worktree_path uses in
|
|
383
|
+
# cleanup_worktrees_actions_lib.sh): `<main>/.claude/worktrees` then `<main>-wt`.
|
|
384
|
+
# Registration-derived roots (cleanup_wt_derive_scan_roots) are always appended.
|
|
385
|
+
# The combined list is deduplicated by normalize_wt_path, keeping the first spelling.
|
|
386
|
+
#
|
|
387
|
+
# The listing is read once (`out=$(...) || rc=$?`). On a parse_worktree_list hard
|
|
388
|
+
# failure nothing is derived from it: with no override no root is emitted at all,
|
|
389
|
+
# rather than a bare relative path resolved against the current working directory,
|
|
390
|
+
# and with an override exactly the override roots are emitted.
|
|
391
|
+
# cleanup_wt_scan_records returns 0 with no record for an empty root list, so the
|
|
392
|
+
# advisory records degrade to silence rather than to a misleading scan.
|
|
393
|
+
# Always returns 0.
|
|
394
|
+
local out rc=0 first_record main_wt="" configured="" derived=""
|
|
395
|
+
out=$(parse_worktree_list) || rc=$?
|
|
396
|
+
if ((rc == 0)); then
|
|
397
|
+
first_record=${out%%$'\n'*}
|
|
398
|
+
main_wt=${first_record%%|*}
|
|
399
|
+
derived=$(cleanup_wt_derive_scan_roots "$out")
|
|
400
|
+
fi
|
|
401
|
+
if [[ -n ${CLEANUP_WT_ORPHAN_ROOTS:-} ]]; then
|
|
402
|
+
configured=$(cleanup_wt_split_roots "$CLEANUP_WT_ORPHAN_ROOTS")
|
|
403
|
+
elif [[ -n $main_wt ]]; then
|
|
404
|
+
configured="${main_wt}/.claude/worktrees"$'\n'"${main_wt}-wt"
|
|
405
|
+
fi
|
|
406
|
+
local -A seen=()
|
|
407
|
+
local root n
|
|
408
|
+
while IFS= read -r root; do
|
|
409
|
+
[[ -z $root ]] && continue
|
|
410
|
+
n=$(normalize_wt_path "$root")
|
|
411
|
+
# A root of `/` normalizes to empty, which is not a valid array key.
|
|
412
|
+
[[ -z $n ]] && n=/
|
|
413
|
+
[[ -n ${seen[$n]:-} ]] && continue
|
|
414
|
+
seen[$n]=1
|
|
415
|
+
printf '%s\n' "$root"
|
|
416
|
+
done <<<"${configured}"$'\n'"${derived}"
|
|
417
|
+
return 0
|
|
418
|
+
}
|
|
@@ -158,7 +158,7 @@ preserve_relative_path_reason() {
|
|
|
158
158
|
local name=${1-} val=${2-}
|
|
159
159
|
if [[ -z $val ]]; then
|
|
160
160
|
printf '%s is empty' "$name"
|
|
161
|
-
elif
|
|
161
|
+
elif cleanup_wt_is_absolute_path "$val"; then
|
|
162
162
|
printf '%s is absolute: %s' "$name" "$val"
|
|
163
163
|
elif [[ $val == ".." || $val == "../"* || $val == *"/../"* || $val == *"/.." ]]; then
|
|
164
164
|
printf '%s contains a .. segment: %s' "$name" "$val"
|
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
# whose gitdir pointer no longer resolves, and the ancestor relationship between two
|
|
7
7
|
# branches that both resolve NOT_MERGED. The enumeration/protection seam
|
|
8
8
|
# (cleanup_wt_git, enumerate_branches, parse_worktree_list, normalize_wt_path,
|
|
9
|
-
# compute_protected, check_main_freshness) lives in
|
|
10
|
-
# and the classification ladder (classify_branch)
|
|
11
|
-
# both MUST be sourced before this file. Keeping
|
|
12
|
-
# every file within the 500-line cap.
|
|
9
|
+
# compute_protected, check_main_freshness, cleanup_wt_scan_roots) lives in
|
|
10
|
+
# cleanup_worktrees_enumerate_lib.sh and the classification ladder (classify_branch)
|
|
11
|
+
# lives in cleanup_worktrees_lib.sh; both MUST be sourced before this file. Keeping
|
|
12
|
+
# these records in a sibling file keeps every file within the 500-line cap.
|
|
13
13
|
#
|
|
14
14
|
# Sourcing contract: this library defines functions only; it never runs work at source
|
|
15
15
|
# time, so the wrapper and the bats suites can source it without side effects.
|
|
@@ -111,47 +111,10 @@ scan_stale_refs() {
|
|
|
111
111
|
return 0
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
cleanup_wt_scan_roots() {
|
|
115
|
-
# Echo the worktree-tracking roots to scan, one per line.
|
|
116
|
-
#
|
|
117
|
-
# CLEANUP_WT_ORPHAN_ROOTS overrides the derivation with a colon-separated list.
|
|
118
|
-
# Otherwise BOTH roots derive from the main worktree path — the first
|
|
119
|
-
# `git worktree list --porcelain` stanza, the same derivation
|
|
120
|
-
# consolidation_worktree_path uses in cleanup_worktrees_actions_lib.sh. They are
|
|
121
|
-
# `<main-worktree-path>` joined with `.claude/worktrees` (the agent worktree folder)
|
|
122
|
-
# and `<main-worktree-path>-wt` (the sibling worktree folder), in that order.
|
|
123
|
-
#
|
|
124
|
-
# Deriving both from one read means a parse_worktree_list hard failure emits no root
|
|
125
|
-
# at all, rather than a bare relative path that would be resolved against whatever
|
|
126
|
-
# the process's current working directory happened to be. cleanup_wt_scan_records
|
|
127
|
-
# returns 0 with no record for an empty root list, so the advisory records degrade to
|
|
128
|
-
# silence rather than to a misleading scan. Always returns 0.
|
|
129
|
-
local override=${CLEANUP_WT_ORPHAN_ROOTS:-}
|
|
130
|
-
if [[ -n $override ]]; then
|
|
131
|
-
local IFS=:
|
|
132
|
-
local part
|
|
133
|
-
for part in $override; do
|
|
134
|
-
[[ -n $part ]] && printf '%s\n' "$part"
|
|
135
|
-
done
|
|
136
|
-
return 0
|
|
137
|
-
fi
|
|
138
|
-
local out rc=0 first_record main_wt=""
|
|
139
|
-
out=$(parse_worktree_list) || rc=$?
|
|
140
|
-
if ((rc != 0)); then
|
|
141
|
-
return 0
|
|
142
|
-
fi
|
|
143
|
-
first_record=${out%%$'\n'*}
|
|
144
|
-
main_wt=${first_record%%|*}
|
|
145
|
-
if [[ -n $main_wt ]]; then
|
|
146
|
-
printf '%s\n' "${main_wt}/.claude/worktrees"
|
|
147
|
-
printf '%s\n' "${main_wt}-wt"
|
|
148
|
-
fi
|
|
149
|
-
return 0
|
|
150
|
-
}
|
|
151
|
-
|
|
152
114
|
cleanup_wt_scan_records() {
|
|
153
115
|
# Echo the raw `<path>|<has_gitfile>|<gitdir_target_exists>|<size>` records for every
|
|
154
|
-
# candidate directory under the resolved scan roots, one per line.
|
|
116
|
+
# candidate directory under the resolved scan roots, one per line. The roots come
|
|
117
|
+
# from cleanup_wt_scan_roots in cleanup_worktrees_enumerate_lib.sh.
|
|
155
118
|
#
|
|
156
119
|
# Every filesystem read goes through the CLEANUP_WT_SCAN_BIN seam, so the bats suites
|
|
157
120
|
# replay canned records instead of touching the real filesystem. The scan output is
|
|
@@ -40,6 +40,11 @@
|
|
|
40
40
|
# the SHELL_QC_<TOOL>_BIN seams substitute a checked-in stand-in for a real dependency.
|
|
41
41
|
# An empty value is treated as missing and falls back to `.git`.
|
|
42
42
|
set -euo pipefail
|
|
43
|
+
# The library path is computed at runtime from BASH_SOURCE, so shellcheck (run without
|
|
44
|
+
# -x) cannot follow it; SC1091 is the expected, benign result.
|
|
45
|
+
# shellcheck source=.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_enumerate_lib.sh
|
|
46
|
+
# shellcheck disable=SC1091
|
|
47
|
+
source "$(dirname -- "${BASH_SOURCE[0]}")/cleanup_worktrees_enumerate_lib.sh"
|
|
43
48
|
|
|
44
49
|
scan_helper_dir_size() {
|
|
45
50
|
# Echo the best-effort human-readable size of a directory, or `unknown`.
|
|
@@ -70,20 +75,6 @@ scan_helper_gitfile_name() {
|
|
|
70
75
|
printf '%s\n' ".git"
|
|
71
76
|
}
|
|
72
77
|
|
|
73
|
-
scan_helper_is_absolute_path() {
|
|
74
|
-
# Return 0 when <path> is absolute, else 1. Pure: no filesystem access.
|
|
75
|
-
#
|
|
76
|
-
# Absolute forms are a leading `/` (POSIX paths, MSYS `/c/...` paths, and `//server`
|
|
77
|
-
# UNC paths) and a drive letter followed by `/` or `\` (`C:/...`, `c:/...`,
|
|
78
|
-
# `C:\...`), which is the form Git for Windows writes into a worktree's `.git`
|
|
79
|
-
# pointer file (issue #706). A drive letter with no separator (`C:rel`) is
|
|
80
|
-
# drive-relative and is not absolute; an empty path is not absolute.
|
|
81
|
-
#
|
|
82
|
-
# Args: $1 = path. Returns 0 (absolute) or 1 (not absolute).
|
|
83
|
-
local path=${1:-}
|
|
84
|
-
[[ $path == /* || $path == [A-Za-z]:[/\\]* ]]
|
|
85
|
-
}
|
|
86
|
-
|
|
87
78
|
scan_helper_target_present() {
|
|
88
79
|
# Return 0 when <path> exists, else non-zero. This is the helper's single
|
|
89
80
|
# filesystem existence check, kept in its own function as a test seam: bats tests
|
|
@@ -113,7 +104,7 @@ scan_helper_gitdir_target_exists() {
|
|
|
113
104
|
printf '0\n'
|
|
114
105
|
return 0
|
|
115
106
|
fi
|
|
116
|
-
if !
|
|
107
|
+
if ! cleanup_wt_is_absolute_path "$target"; then
|
|
117
108
|
target="$dir/$target"
|
|
118
109
|
fi
|
|
119
110
|
if scan_helper_target_present "$target"; then
|
|
@@ -95,14 +95,32 @@ function of the DAG.
|
|
|
95
95
|
2. Before starting each wave, `epic-orchestrator` runs
|
|
96
96
|
`git fetch origin epic/<epic-slug>-integration` so the wave's child worktrees branch off the
|
|
97
97
|
current remote tip, not a stale local ref.
|
|
98
|
-
3.
|
|
98
|
+
3. Before each wave launches (wave 0 included), `epic-orchestrator` runs
|
|
99
|
+
`git fetch origin main` and then
|
|
100
|
+
`git rev-list --count origin/epic/<epic-slug>-integration..origin/main`. A zero count
|
|
101
|
+
proceeds directly to the wave. A non-zero count means `origin/main` has commits the
|
|
102
|
+
integration branch lacks, and the main-sync runs as a dedicated chore child item before the
|
|
103
|
+
wave launches, following the `epic-852-main-sync` / PR #882 pattern. Before delegating it,
|
|
104
|
+
`epic-orchestrator` writes the sync child's `features[]` row (with `depends_on: []`) and its
|
|
105
|
+
own `waves[]` entry to the epic checkpoint, because `enforce-epic-wave-barrier.ps1` denies a
|
|
106
|
+
delegation whose feature record is absent. The sync child must not reuse a manifest child's
|
|
107
|
+
issue number; it uses the epic issue number or a dedicated chore issue. Its branch is created
|
|
108
|
+
from the integration branch, merges `origin/main` with a merge commit
|
|
109
|
+
(`git merge --no-ff origin/main`; no rebase, no force-push), resolves any conflict inside its
|
|
110
|
+
own remediation loop, and opens a PR into the integration branch. The wave does not launch
|
|
111
|
+
until that PR has merged into the integration branch and the sync entry's `merge_status` is
|
|
112
|
+
`merged`. At most one main-sync child runs per wave: after it merges, `epic-orchestrator`
|
|
113
|
+
re-runs step 2 and launches the wave without repeating the count, and commits that reach
|
|
114
|
+
`origin/main` afterwards are picked up by the next wave's check or by the final integration
|
|
115
|
+
PR in step 6.
|
|
116
|
+
4. Each child feature's worktree/branch (created via
|
|
99
117
|
`Agent(orchestrator, isolation: "worktree", run_in_background: true)`) is branched from
|
|
100
118
|
`origin/<integration_branch>`, not `origin/main`. The child's own `orchestrator` instance
|
|
101
119
|
honors this via the epic-mode kickoff line below.
|
|
102
|
-
|
|
120
|
+
5. Each child feature's PR base branch is the integration branch, not `main` — an explicit
|
|
103
121
|
epic-mode override recorded in the checkpoint, not a reliance on `pr-base-branch-merge-base`'s
|
|
104
122
|
ancestry heuristic. Non-epic (standalone) orchestration is unchanged.
|
|
105
|
-
|
|
123
|
+
6. At epic completion (every feature in the final wave has `merge_status: "merged"`),
|
|
106
124
|
`epic-orchestrator` drives a final PR merging `epic/<epic-slug>-integration` into `main`,
|
|
107
125
|
delegating PR authoring to `Agent(pr-author)` and refreshing context via
|
|
108
126
|
`mcp__drm-copilot__collect_pr_context`. `epic-orchestrator` runs the same S9 CI-green
|
|
@@ -221,9 +239,10 @@ Procedure, triggered by S9 step 6's merge failure:
|
|
|
221
239
|
3. The existing R1–R5 loop processes this finding exactly as a local blocking finding:
|
|
222
240
|
`atomic-planner` (R1) plans the resolution, `atomic-executor` performs preflight (R2) then
|
|
223
241
|
resolves the conflict markers, stages, and commits (R3), `feature-review` re-audits (R4).
|
|
224
|
-
4.
|
|
225
|
-
|
|
226
|
-
|
|
242
|
+
4. Conflict cycles share the child's own `remediation_loop.completed_attempts` count with
|
|
243
|
+
local-finding and CI-failure cycles. The active cycle number is `completed_attempts + 1`, and a
|
|
244
|
+
cycle without an applied candidate consumes no number.
|
|
245
|
+
5. After three completed attempts without resolution, the child's `orchestrator` records
|
|
227
246
|
`step9_status: "blocked_conflict_loop_limit"` (parallel to `blocked_ci_loop_limit`), does not
|
|
228
247
|
write DONE, and halts. It reports this status to `epic-orchestrator`, which mirrors it into
|
|
229
248
|
the epic checkpoint's per-feature `merge_status: "blocked_conflict_loop_limit"` field.
|
|
@@ -240,11 +259,26 @@ cross-call/conversation-state visibility.
|
|
|
240
259
|
prompt text, reads `artifacts/orchestration/epic-orchestrator-state.json`, looks up that
|
|
241
260
|
feature's `depends_on`, and denies with reason `EPIC_WAVE_BARRIER_BLOCKED` unless every
|
|
242
261
|
dependency's `merge_status` is `merged` or `worktree_removed`.
|
|
243
|
-
- **Layer 2 — retrospective backstop:** the wave-barrier ordering invariant
|
|
244
|
-
`validate_epic_orchestrator_state_text`, enforced at `epic-orchestrator` `SubagentStop` time
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
262
|
+
- **Layer 2 — retrospective backstop:** the wave-barrier ordering invariant of
|
|
263
|
+
`validate_epic_orchestrator_state_text`, enforced at `epic-orchestrator` `SubagentStop` time by a
|
|
264
|
+
PowerShell port, `Get-OrchestratorStateEpicWaveBarrierError` in
|
|
265
|
+
`.claude/lib/orchestrator-state/OrchestratorStateEpicWaveBarrier.psm1`, which the parameterized
|
|
266
|
+
`validate-orchestrator-output.ps1` hook invokes for `epic-orchestrator-state` after resolving the
|
|
267
|
+
epic checkpoint through `WorktreeRunResolution.psm1`. The hook starts no Python process. Parity
|
|
268
|
+
with `validate_epic_orchestrator_state_text` is pinned by the shared fixtures under
|
|
269
|
+
`tests/fixtures/epic_wave_barrier/`, and the Python validator remains the authority used through
|
|
270
|
+
the `mcp__drm-copilot__validate_orchestration_artifacts` call. It checks only a dependent feature
|
|
271
|
+
that is treated as started: one with a string `worktree_created_at`, or with a `merge_status`
|
|
272
|
+
other than `not_started` (a missing or non-string `merge_status` counts as started). It appends
|
|
273
|
+
exactly one error per violated dependency edge. When the dependency's `merge_status` is not
|
|
274
|
+
`merged` or `worktree_removed`, the error is
|
|
275
|
+
`EPIC_WAVE_BARRIER_VIOLATION: <f> is treated as started while dependency <d> is not merged`.
|
|
276
|
+
Otherwise, when the dependency's `merge_confirmed_at` is later than the dependent's
|
|
277
|
+
`worktree_created_at`, the error is
|
|
278
|
+
`EPIC_WAVE_BARRIER_VIOLATION: <f> worktree_created_at precedes dependency <d> merge_confirmed_at`.
|
|
279
|
+
A violation blocks with an instruction to report it to the operator and halt. The `SubagentStop`
|
|
280
|
+
transport and exit-code defect that this check previously depended on was resolved by epic #904
|
|
281
|
+
and issue #928: a violation blocks the stop with exit 2 and a stderr reason.
|
|
248
282
|
|
|
249
283
|
Both layers are required; neither alone closes the gap. `epic-orchestrator` does not launch wave
|
|
250
284
|
N+1 until every wave-N feature's dependency edges are durably confirmed merged, verified against
|
|
@@ -211,7 +211,7 @@ With no ready feature checkpoint, the exemption admits two attribution-trailer f
|
|
|
211
211
|
- The trailer option: `git commit -m 'docs: plan' --trailer 'Co-Authored-By: Name <email>' --trailer 'Claude-Session: <url>' -- <exempt paths>`. The separate-value form and the `--trailer=<value>` form are both admitted, any number of times, on `git commit` only; `git add --trailer` and a trailer option with no value are denied. Git writes every trailer value into one trailer block.
|
|
212
212
|
- The one-paragraph multi-message form: the subject in the first `-m` and every trailer in one single-quoted second `-m` value, separated by a literal newline. Each `-m` value becomes its own paragraph and git parses only the last paragraph as the trailer block, so trailers split across separate `-m` values do not form one trailer block.
|
|
213
213
|
|
|
214
|
-
Quoting rules: `$` and backtick are literal and admitted inside single quotes, and denied outside quotes and inside double quotes, where the shell expands them. `<` and `>` are admitted inside single or double quotes and denied outside quotes. An unquoted `#` is denied anywhere, because it starts a shell comment that the exemption does not model; a `#` inside quotes is admitted. A typographic quote character (U+2018 to U+201E) anywhere in the command line is denied, because a PowerShell host reads it as a quote.
|
|
214
|
+
Quoting rules: `$` and backtick are literal and admitted inside single quotes, and denied outside quotes and inside double quotes, where the shell expands them. `<` and `>` are admitted inside single or double quotes and denied outside quotes. An unquoted `#` is denied anywhere, because it starts a shell comment that the exemption does not model; a `#` inside quotes is admitted. A typographic quote character (U+2018 to U+201E) anywhere in the command line is denied, because a PowerShell host reads it as a quote. Because the executing shell is undetermined (issue #735), a shape whose meaning differs between a POSIX shell and PowerShell is denied: a backslash anywhere in the command line is denied, and `{`, `}`, `,`, `(`, `)`, and `@` are denied outside quotes. Every staging operand must be a plain forward-slash repository-relative path that uses only the characters `A-Z a-z 0-9 . _ / -`.
|
|
215
215
|
|
|
216
216
|
Not admitted: heredoc-fed messages, including `git commit -m "$(cat <<'EOF' ... EOF)"` and `git commit -F - <<'EOF'`, and message files supplied through `-F <file>` or `--file=<file>`. Use one of the two forms above instead.
|
|
217
217
|
|
package/resources/claude-customizations/.claude/skills/evidence-and-timestamp-conventions/SKILL.md
CHANGED
|
@@ -46,6 +46,17 @@ Use this skill when:
|
|
|
46
46
|
Use `yyyy-MM-ddTHH-mm` for all audit, remediation, and evidence artifacts.
|
|
47
47
|
Example: `2026-02-06T14-30`.
|
|
48
48
|
|
|
49
|
+
The `Timestamp` value is UTC read from the host system clock when the recorded command runs (for example `Get-Date -AsUTC -Format yyyy-MM-ddTHH-mm` in PowerShell 7, `(Get-Date).ToUniversalTime().ToString('yyyy-MM-ddTHH-mm')` in Windows PowerShell 5.1, or `date -u +%Y-%m-%dT%H-%M` in a POSIX shell); the agent never composes or estimates it. The value is written without a zone suffix.
|
|
50
|
+
|
|
51
|
+
### Evidence Filename Timestamp
|
|
52
|
+
|
|
53
|
+
The stamp in the filename of every artifact under `<FEATURE>/evidence/<kind>/` is the UTC time at which that file is written, read from the host system clock immediately before the write, in the same `yyyy-MM-ddTHH-mm` shape with no zone suffix. It is never a plan-time stamp, a plan-cycle identifier, or any other value fixed before the write.
|
|
54
|
+
|
|
55
|
+
- Plans name such an artifact `<name>.<timestamp>.md`, and the executor substitutes the write time. A later loop pass writes a new file with a new stamp.
|
|
56
|
+
- A task that consumes an evidence artifact selects the lexicographically greatest file matching `<name>.*.md`. The fixed-width UTC shape sorts in chronological order, so that file is the most recently written one.
|
|
57
|
+
- Plan files (`plan.<timestamp>.md`, stamped by the feature-folder tooling in America/New_York) and the review artifact set (`policy-audit`, `code-review`, `feature-audit`, `remediation-inputs`, which share one stamp) are outside this rule.
|
|
58
|
+
- Existing evidence files whose names carry a plan-time stamp are not renamed.
|
|
59
|
+
|
|
49
60
|
## Canonical Evidence Locations
|
|
50
61
|
|
|
51
62
|
- Baseline evidence: `evidence/baseline/`
|
|
@@ -110,6 +121,8 @@ When evidence artifacts are used for automated checking or plan reconciliation,
|
|
|
110
121
|
- `Command: <exact command>`
|
|
111
122
|
- `EXIT_CODE: <int>`
|
|
112
123
|
|
|
124
|
+
The first occurrence of `Timestamp`, `Command`, `EXIT_CODE`, and `ExpectedExitCode` forms the record in both the Python and the TypeScript parser; later occurrences, including empty later values, are ignored. An artifact that records several gates therefore reports its first gate.
|
|
125
|
+
|
|
113
126
|
One optional field may also be declared:
|
|
114
127
|
- `ExpectedExitCode: <int>` — the exit code the gate is expected to produce.
|
|
115
128
|
|
|
@@ -40,6 +40,16 @@ Each `delegation_receipts.promotion.*` field stores the raw MCP receipt payload
|
|
|
40
40
|
|
|
41
41
|
Note: VS Code command-palette commands may exist for interactive extension use, but this note is non-authoritative for agent sessions.
|
|
42
42
|
|
|
43
|
+
## Pre-Existing Issue Path
|
|
44
|
+
|
|
45
|
+
When the GitHub issue already exists (it was transferred, filed before orchestration, or created by epic decomposition), do not call `potential_to_issue`: that tool creates a new issue and would duplicate the existing one. Instead:
|
|
46
|
+
|
|
47
|
+
1. Verify the issue read-only with `gh issue view`, a `gh api` GET request, or a GitHub MCP issue read, and use its number as `${issue-num}`.
|
|
48
|
+
2. Record a top-level `issue_adoption` object in the orchestrator checkpoint (`issue_num`, `issue_url`, `origin`, `verified_via`, `verified_at`, `evidence`, `waived_tools`, and, when a promotion-entry tool is waived, `potential_record`). For that waiver `potential_record` is required when `origin` is `epic_decomposition`, optional when `origin` is `transferred` or `filed_before_orchestration`, and validated whenever it is present. A valid record waives the `potential_to_issue` receipt requirement at completion.
|
|
49
|
+
3. `delegation_receipts.promotion.issue` may be omitted, because no promotion receipt exists for an adopted issue.
|
|
50
|
+
|
|
51
|
+
The field rules, the closed set of waivable tools, and the fail-closed behavior are defined in `.claude/rules/orchestrator-state.md` under `## Invariants (issue_adoption object)`.
|
|
52
|
+
|
|
43
53
|
## Canonical Variables
|
|
44
54
|
|
|
45
55
|
- `${promotion-type}`: `feature` or `bug`
|
|
@@ -70,9 +70,9 @@ Always apply:
|
|
|
70
70
|
If the branch diff modifies any path matching `.github/workflows/**`, `scripts/benchmarks/**`, or `.github/actions/**`, the policy audit emits a Blocking finding unless evidence of a green workflow run against the branch head is present in the remediation inputs.
|
|
71
71
|
|
|
72
72
|
- The rule provides a second, independent line of defense for CI-gate-modifying features, separate from and prior to the orchestrator's S9 CI green gate.
|
|
73
|
-
- "Green workflow run against the branch head" means a workflow
|
|
73
|
+
- "Green workflow run against the branch head" means a run of the affected workflow whose conclusion is success and which satisfies either (a) or (b): (a) its head SHA equals the current branch head; or (b) all three predecessor-head conditions hold: (1) the run's head SHA is an ancestor of, or equal to, the current branch head and contains the latest commit that changes any path outside the active feature folder (`git merge-base --is-ancestor <commit> <run-sha>`); (2) every commit after the run's head SHA changes only paths inside the active feature folder (`git log <run-sha>..HEAD -- . ":!<feature-folder>"` returns no commits); (3) the policy audit states that the orchestrator's S9 CI green gate remains responsible for `ci_gate.conclusion == "success"` with `ci_gate.head_sha` equal to the final PR head before DONE. Condition (b) exists because an in-repo evidence artifact cannot name the SHA of the commit that contains it.
|
|
74
74
|
- A green `workflow_dispatch` run against the branch head also satisfies the rule, not only a PR-context run. This mitigates the chicken-and-egg case where a feature must land its CI gate before the gate can run in PR context (see spec.md Risks & Mitigations).
|
|
75
|
-
- When the rule fires and no qualifying green-run evidence is present, record a Blocking finding and
|
|
75
|
+
- When the rule fires and no qualifying green-run evidence is present, record a Blocking finding classified `awaiting_ci` (the remediation inputs carry `Remediability: awaiting_ci` and a `Remediability-Evidence:` line naming the awaited workflow) and route it to the wait path (`AWAITING_CI` when no other class is present) instead of the remediation handoff.
|
|
76
76
|
|
|
77
77
|
## Ordered Procedure
|
|
78
78
|
|
|
@@ -108,12 +108,13 @@ If the branch diff modifies any path matching `.github/workflows/**`, `scripts/b
|
|
|
108
108
|
- Python: `poetry run pytest --cov` → artifact: `artifacts/python/lcov.info`
|
|
109
109
|
- PowerShell: `mcp__drm-copilot__run_poshqc_test` → artifact: `artifacts/pester/powershell-coverage.xml`
|
|
110
110
|
- C#: `dotnet test --collect:"XPlat Code Coverage"` → artifact: `artifacts/csharp/coverage.xml`
|
|
111
|
-
- Coverage thresholds (
|
|
111
|
+
- Coverage thresholds (threshold precedence per `.claude/rules/quality-tiers.md` and `.claude/rules/general-unit-test.md`: when the repository's root `CLAUDE.md` states line or branch coverage thresholds, those thresholds govern; otherwise the default thresholds below govern; each metric falls back independently, so a root `CLAUDE.md` that states only one of the two thresholds governs only that metric). The branch threshold applies only to branch-capable languages — TypeScript, Python, and C#. PowerShell is a coverage language and is fully subject to the line threshold and the no-regression requirement, but Pester measures command (instruction) coverage and line coverage only, so no branch percentage exists to evaluate and no branch threshold applies to it (see `.claude/rules/powershell.md`). Do not flag a missing PowerShell branch figure as FAIL:
|
|
112
112
|
- New code files (added in this feature): line coverage >= 85%, and branch coverage >= 75% for branch-capable languages. Flag as FAIL otherwise.
|
|
113
113
|
- Modified files (changed but previously existing): line coverage >= 85%, branch coverage >= 75% for branch-capable languages, and no regression on changed lines relative to baseline. Flag as FAIL otherwise.
|
|
114
114
|
- Repo-wide per language: line coverage >= 85%, and branch coverage >= 75% for branch-capable languages. Flag as FAIL otherwise.
|
|
115
115
|
- If coverage artifacts already exist from the executor run, inspect them instead of re-running.
|
|
116
116
|
- If no coverage artifact exists for a language that has changed files, flag as FAIL — coverage verification is mandatory for all languages with changed files.
|
|
117
|
+
- Tier classification findings: report a missing or incomplete `quality-tiers.yml` only when the repository has adopted tiers, that is, when `quality-tiers.yml` exists at the repository root on the resolved base branch or the repository's CI runs a tier-classification check. Otherwise record tier classification as not applicable; it is not a finding.
|
|
117
118
|
- Run the smallest relevant subset first when the repo policy permits it.
|
|
118
119
|
- If a tool cannot run in the environment, mark the affected section unverified or partial with a concrete reason.
|
|
119
120
|
|
|
@@ -145,8 +146,10 @@ If the branch diff modifies any path matching `.github/workflows/**`, `scripts/b
|
|
|
145
146
|
- toolchain checks fail
|
|
146
147
|
- the code review contains blockers
|
|
147
148
|
- required acceptance criteria are FAIL or PARTIAL
|
|
148
|
-
- coverage
|
|
149
|
+
- coverage below the governing thresholds defined in step 5 (repo-wide per language, modified files including any regression on changed lines, or new files)
|
|
149
150
|
- coverage artifact absent for any language that has changed files
|
|
151
|
+
- Classify each blocking finding before triggering remediation: each receives one remediability class (`autonomous`, `external_dependency`, `policy_hold`, `awaiting_ci`, or `human_decision_required`; `autonomous` when no class is stated). A published MCP runtime that lags the repository contract is classified `external_dependency`.
|
|
152
|
+
- Trigger the remediation handoff only when at least one blocking finding is `autonomous`. When every blocking finding is non-remediable, write the remediation inputs with the `HALT_NON_REMEDIABLE` or `AWAITING_CI` verdict and create no remediation plan target.
|
|
150
153
|
- Create `remediation-inputs.<timestamp>.md` first.
|
|
151
154
|
- Create the target remediation plan file from the canonical plan template.
|
|
152
155
|
- Hand off plan creation through `remediation-handoff-atomic-planner`.
|