@danmoisan/drm-copilot-mcp 1.1.16 → 1.1.18
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 +1139 -133
- package/package.json +4 -3
- package/resources/claude-customizations/.claude/agents/feature-review.md +10 -1
- package/resources/claude-customizations/.claude/agents/orchestrator.md +16 -3
- package/resources/claude-customizations/.claude/agents/parallel-orchestrator.md +18 -6
- package/resources/claude-customizations/.claude/agents/python-typed-engineer.md +3 -3
- package/resources/claude-customizations/.claude/hooks/{enforce-powershell-batch-budget-route.ps1 → enforce-batch-budget-route.ps1} +12 -10
- package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate-resolution.ps1 +221 -0
- package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate.ps1 +42 -66
- package/resources/claude-customizations/.claude/hooks/enforce-epic-wave-barrier.ps1 +58 -10
- package/resources/claude-customizations/.claude/hooks/enforce-epic-worktree-removal-gate-resolution.ps1 +144 -0
- package/resources/claude-customizations/.claude/hooks/enforce-epic-worktree-removal-gate.ps1 +36 -47
- package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-epic-scope.ps1 +179 -27
- package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate.ps1 +21 -38
- package/resources/claude-customizations/.claude/hooks/enforce-parallel-abandon-gate.ps1 +4 -4
- package/resources/claude-customizations/.claude/hooks/enforce-parallel-cohort-barrier.ps1 +58 -10
- package/resources/claude-customizations/.claude/hooks/enforce-parallel-drift-gate.ps1 +59 -9
- package/resources/claude-customizations/.claude/hooks/enforce-parallel-worktree-removal-gate.ps1 +114 -37
- package/resources/claude-customizations/.claude/hooks/enforce-powershell-batch-budget.ps1 +3 -3
- package/resources/claude-customizations/.claude/hooks/enforce-python-batch-budget.ps1 +99 -64
- package/resources/claude-customizations/.claude/lib/bash/abandon-parallel-item.sh +176 -0
- package/resources/claude-customizations/.claude/lib/bash/parallel-lane-assertion.sh +4 -2
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusConflict.psm1 +193 -14
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusGlob.psm1 +51 -28
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusScheduling.psm1 +5 -8
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorState.psm1 +6 -13
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateIssueAdoption.psm1 +375 -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/parallel-drift/Invoke-ParallelDriftDetection.ps1 +336 -0
- package/resources/claude-customizations/.claude/lib/parallel-drift/ParallelDrift.psm1 +467 -0
- package/resources/claude-customizations/.claude/lib/parallel-drift/ParallelDriftHalt.psm1 +388 -0
- package/resources/claude-customizations/.claude/lib/worktree-resolution/EpicScopeResolution.psm1 +53 -32
- package/resources/claude-customizations/.claude/lib/worktree-resolution/WorktreeItemResolution.psm1 +19 -4
- package/resources/claude-customizations/.claude/lib/worktree-resolution/WorktreeRunResolution.psm1 +497 -0
- package/resources/claude-customizations/.claude/rules/orchestrator-state.md +119 -3
- package/resources/claude-customizations/.claude/rules/parallel-orchestration.md +21 -0
- package/resources/claude-customizations/.claude/rules/quality-tiers.md +1 -1
- package/resources/claude-customizations/.claude/skills/acceptance-criteria-tracking/SKILL.md +8 -0
- package/resources/claude-customizations/.claude/skills/atomic-plan-contract/SKILL.md +2 -0
- 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_enumerate_lib.sh +169 -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 +4 -15
- package/resources/claude-customizations/.claude/skills/epic-orchestrate/SKILL.md +15 -6
- package/resources/claude-customizations/.claude/skills/evidence-and-timestamp-conventions/SKILL.md +4 -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 +3 -1
- package/resources/claude-customizations/.claude/skills/invoke-csharp-engineer/SKILL.md +4 -0
- package/resources/claude-customizations/.claude/skills/invoke-powershell-engineer/SKILL.md +4 -0
- package/resources/claude-customizations/.claude/skills/invoke-python-engineer/SKILL.md +6 -3
- package/resources/claude-customizations/.claude/skills/orchestrate/SKILL.md +33 -13
- package/resources/claude-customizations/.claude/skills/parallel-orchestrate/SKILL.md +50 -21
- package/resources/claude-customizations/.claude/skills/parallel-remove/SKILL.md +10 -10
- package/resources/claude-customizations/.claude/skills/python-change-budget-router/SKILL.md +11 -35
- package/resources/claude-customizations/.claude/skills/remediation-handoff-atomic-planner/SKILL.md +5 -1
- package/resources/claude-customizations/pack-manifests/core.json +10 -0
- package/resources/claude-customizations/pack-manifests/powershell.json +0 -1
- package/resources/codex-and-agents-customizations/.agents/skills/acceptance-criteria-tracking/SKILL.md +8 -0
- package/resources/codex-and-agents-customizations/.agents/skills/epic-orchestrate/SKILL.md +5 -3
- package/resources/codex-and-agents-customizations/.agents/skills/evidence-and-timestamp-conventions/SKILL.md +4 -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 +3 -1
- package/resources/codex-and-agents-customizations/.agents/skills/invoke-powershell-engineer/SKILL.md +0 -1
- package/resources/codex-and-agents-customizations/.agents/skills/invoke-python-engineer/SKILL.md +2 -3
- package/resources/codex-and-agents-customizations/.agents/skills/orchestrate/SKILL.md +30 -7
- 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 +18 -3
- package/resources/codex-and-agents-customizations/.agents/skills/python-change-budget-router/SKILL.md +10 -34
- package/resources/codex-and-agents-customizations/.agents/skills/quality-tiers/SKILL.md +1 -1
- package/resources/codex-and-agents-customizations/.agents/skills/remediation-handoff-atomic-planner/SKILL.md +2 -0
- 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 +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c2.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c3-elevated.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c3.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c4.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/python-orchestrator.toml +2 -2
- package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c1.toml +3 -3
- package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c2.toml +3 -3
- package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c3-elevated.toml +3 -3
- package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c3.toml +3 -3
- package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c4.toml +3 -3
- package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer.toml +3 -3
- package/resources/codex-and-agents-customizations/.codex/config.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-batch-budget-route.ps1 +139 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-powershell-batch-budget.ps1 +4 -124
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-python-batch-budget.ps1 +169 -79
- package/resources/codex-and-agents-customizations/pack-manifests/core.json +1 -0
- package/resources/customizations/.github/agents/python-orchestrator.agent.md +4 -4
- package/resources/customizations/.github/agents/python-typed-engineer.agent.md +7 -8
- package/resources/customizations/.github/prompts/orchestrate-python-work.prompt.md +3 -3
- package/resources/customizations/.github/skills/acceptance-criteria-tracking/SKILL.md +8 -0
- package/resources/customizations/.github/skills/evidence-and-timestamp-conventions/SKILL.md +4 -0
- package/resources/powershell/PoshQC/settings/pester.runsettings.psd1 +16 -1
package/resources/codex-and-agents-customizations/.codex/hooks/enforce-python-batch-budget.ps1
CHANGED
|
@@ -1,32 +1,44 @@
|
|
|
1
1
|
|
|
2
2
|
<#
|
|
3
3
|
.SYNOPSIS
|
|
4
|
-
Pre-tool-use hook that
|
|
4
|
+
Pre-tool-use hook that routes Python changes of more than three production files to the orchestrated large path.
|
|
5
5
|
|
|
6
6
|
.DESCRIPTION
|
|
7
7
|
This script is invoked by the Codex PreToolUse hook before any Write or Edit
|
|
8
|
-
operation. When the target file is a Python file, it
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
8
|
+
operation. When the target file is a Python file (.py), it decides whether the
|
|
9
|
+
change may proceed in direct mode.
|
|
10
|
+
|
|
11
|
+
Direct mode counts distinct production Python paths per Codex session. The running
|
|
12
|
+
set is persisted under .codex/state/python-batch-budget.<session_id>.json, and
|
|
13
|
+
repeated edits to the same file are counted once. The 4th distinct production path
|
|
14
|
+
is denied with a PYTHON_LARGE_PATH_REQUIRED reason that instructs the caller to
|
|
15
|
+
route the change through .codex/prompts/orchestrate-work.md.
|
|
16
|
+
|
|
17
|
+
The orchestrated large path is detected from
|
|
18
|
+
<root>/artifacts/orchestration/orchestrator-state.json. The selected route is the
|
|
19
|
+
route_id value when that key is present, otherwise the path_selected value, and it
|
|
20
|
+
is usable only as a non-blank string. When the selected route is large,
|
|
21
|
+
remediation, or preparation and the checkpoint is not terminal (next_step is not
|
|
22
|
+
complete and completed_steps does not contain S12_complete), no path is denied for
|
|
23
|
+
count and no state is read or written. Every other checkpoint outcome, including
|
|
24
|
+
an absent, unreadable, or malformed checkpoint, enforces direct mode.
|
|
25
|
+
|
|
26
|
+
Test files are never counted. They are those matching:
|
|
18
27
|
- tests/**/*.py
|
|
19
28
|
- test_*.py
|
|
20
29
|
|
|
21
|
-
All other .py files are
|
|
30
|
+
All other .py files are production files. Non-Python paths pass through. The
|
|
31
|
+
threshold of three production files is a routing constant and is not configurable
|
|
32
|
+
at runtime. Legacy prodCap, testCap, and testFiles keys in a persisted state file
|
|
33
|
+
are ignored when the state is loaded.
|
|
22
34
|
|
|
23
|
-
|
|
24
|
-
|
|
35
|
+
When a production path is denied, the script emits a PreToolUse JSON response with
|
|
36
|
+
hookSpecificOutput.permissionDecision = 'deny' and exits 0. Files already counted
|
|
37
|
+
are always allowed through.
|
|
25
38
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
batch. Files already counted are always allowed through.
|
|
39
|
+
Known limitation: a stale non-terminal large-path checkpoint left at the root
|
|
40
|
+
exempts a later direct-mode session at that root. Orchestrator checkpoint hygiene
|
|
41
|
+
(issue #673) moves foreign checkpoints aside before a new run.
|
|
30
42
|
|
|
31
43
|
.NOTES
|
|
32
44
|
Compatible with PowerShell 7+.
|
|
@@ -38,26 +50,28 @@ param()
|
|
|
38
50
|
# mapping for every tool name the ^(apply_patch|Edit|Write)$ matcher admits.
|
|
39
51
|
. (Join-Path $PSScriptRoot 'codex-pretooluse-file-mapping.ps1')
|
|
40
52
|
|
|
53
|
+
# Shared route helpers; this file is byte-identical to the Claude runtime copy.
|
|
54
|
+
. (Join-Path $PSScriptRoot 'enforce-batch-budget-route.ps1')
|
|
55
|
+
|
|
41
56
|
function Get-PythonBatchBudgetState {
|
|
57
|
+
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'TestCap', Justification = 'Accepted and ignored for callers written against the removed test-file cap.')]
|
|
42
58
|
[CmdletBinding()]
|
|
43
59
|
[OutputType([System.Collections.Specialized.OrderedDictionary])]
|
|
44
60
|
param(
|
|
45
61
|
[Parameter(Mandatory)]
|
|
46
62
|
[int] $ProdCap,
|
|
47
63
|
|
|
48
|
-
[
|
|
49
|
-
[int] $TestCap
|
|
64
|
+
[int] $TestCap = 0
|
|
50
65
|
)
|
|
51
66
|
|
|
52
67
|
[ordered]@{
|
|
53
68
|
prodCap = $ProdCap
|
|
54
|
-
testCap = $TestCap
|
|
55
69
|
prodFiles = @()
|
|
56
|
-
testFiles = @()
|
|
57
70
|
}
|
|
58
71
|
}
|
|
59
72
|
|
|
60
73
|
function ConvertTo-PythonBatchBudgetState {
|
|
74
|
+
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'TestCap', Justification = 'Accepted and ignored for callers written against the removed test-file cap.')]
|
|
61
75
|
[CmdletBinding()]
|
|
62
76
|
[OutputType([System.Collections.Specialized.OrderedDictionary])]
|
|
63
77
|
param(
|
|
@@ -67,15 +81,13 @@ function ConvertTo-PythonBatchBudgetState {
|
|
|
67
81
|
[Parameter(Mandatory)]
|
|
68
82
|
[int] $ProdCap,
|
|
69
83
|
|
|
70
|
-
[
|
|
71
|
-
[int] $TestCap
|
|
84
|
+
[int] $TestCap = 0
|
|
72
85
|
)
|
|
73
86
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
87
|
+
# Only prodFiles is carried over. Persisted prodCap, testCap, and testFiles keys
|
|
88
|
+
# come from the removed test-file cap and recorded overrides and are ignored.
|
|
89
|
+
$state = Get-PythonBatchBudgetState -ProdCap $ProdCap
|
|
77
90
|
if ($null -ne $InputObject.prodFiles) { $state.prodFiles = @($InputObject.prodFiles) }
|
|
78
|
-
if ($null -ne $InputObject.testFiles) { $state.testFiles = @($InputObject.testFiles) }
|
|
79
91
|
|
|
80
92
|
return $state
|
|
81
93
|
}
|
|
@@ -105,6 +117,7 @@ function Get-PythonBatchBudgetBlockDecision {
|
|
|
105
117
|
}
|
|
106
118
|
|
|
107
119
|
function Invoke-PythonBatchBudgetDecision {
|
|
120
|
+
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'TestCap', Justification = 'Accepted and ignored for callers written against the removed test-file cap.')]
|
|
108
121
|
[CmdletBinding()]
|
|
109
122
|
[OutputType([System.Collections.Specialized.OrderedDictionary])]
|
|
110
123
|
param(
|
|
@@ -114,8 +127,15 @@ function Invoke-PythonBatchBudgetDecision {
|
|
|
114
127
|
[Parameter(Mandatory)]
|
|
115
128
|
[System.Collections.IDictionary] $State,
|
|
116
129
|
|
|
117
|
-
[
|
|
118
|
-
[string] $StateFile
|
|
130
|
+
[AllowEmptyString()]
|
|
131
|
+
[string] $StateFile = '',
|
|
132
|
+
|
|
133
|
+
[int] $TestCap = 0,
|
|
134
|
+
|
|
135
|
+
[switch] $LargePathRoute,
|
|
136
|
+
|
|
137
|
+
[AllowEmptyString()]
|
|
138
|
+
[string] $ObservedRoute = ''
|
|
119
139
|
)
|
|
120
140
|
|
|
121
141
|
$normalized = $FilePath -replace '\\', '/'
|
|
@@ -123,26 +143,32 @@ function Invoke-PythonBatchBudgetDecision {
|
|
|
123
143
|
return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' }; state = $State; shouldWriteState = $false }
|
|
124
144
|
}
|
|
125
145
|
|
|
146
|
+
# The orchestrated large path has no production-file cap, so nothing is counted.
|
|
147
|
+
if ($LargePathRoute) {
|
|
148
|
+
return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' }; state = $State; shouldWriteState = $false }
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
# Test files never count toward the routing threshold.
|
|
126
152
|
$isTestFile = ($normalized -match '(^|/)tests/.*\.py$') -or ($normalized -match '(^|/)test_[^/]+\.py$')
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
153
|
+
if ($isTestFile) {
|
|
154
|
+
return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' }; state = $State; shouldWriteState = $false }
|
|
155
|
+
}
|
|
130
156
|
|
|
131
|
-
|
|
157
|
+
$countedFiles = @($State.prodFiles)
|
|
158
|
+
if ($countedFiles -contains $normalized) {
|
|
132
159
|
return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' }; state = $State; shouldWriteState = $false }
|
|
133
160
|
}
|
|
134
161
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
162
|
+
$cap = [int]$State.prodCap
|
|
163
|
+
if ($countedFiles.Count -ge $cap) {
|
|
164
|
+
Write-Verbose "Denying production Python path '$normalized' in direct mode; counted paths are recorded in '$StateFile'."
|
|
165
|
+
$counted = $countedFiles -join ', '
|
|
166
|
+
$route = if ([string]::IsNullOrWhiteSpace($ObservedRoute)) { 'none' } else { $ObservedRoute }
|
|
167
|
+
$reason = "PYTHON_LARGE_PATH_REQUIRED: this change touches more than $cap production Python files (already counted: $counted; requested: $normalized). A change of this size belongs on the orchestrated large path, which has no production-file cap. Route the change through .codex/prompts/orchestrate-work.md. Checkpoint route observed: $route."
|
|
138
168
|
return Get-PythonBatchBudgetBlockDecision -Reason $reason -State $State
|
|
139
169
|
}
|
|
140
170
|
|
|
141
|
-
|
|
142
|
-
$State.testFiles = @($State.testFiles) + @($normalized)
|
|
143
|
-
} else {
|
|
144
|
-
$State.prodFiles = @($State.prodFiles) + @($normalized)
|
|
145
|
-
}
|
|
171
|
+
$State.prodFiles = $countedFiles + @($normalized)
|
|
146
172
|
|
|
147
173
|
return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' }; state = $State; shouldWriteState = $true }
|
|
148
174
|
}
|
|
@@ -155,7 +181,13 @@ function Invoke-PythonBatchBudgetHook {
|
|
|
155
181
|
[string] $SessionId = 'default',
|
|
156
182
|
[string] $Root = (Get-Location).Path,
|
|
157
183
|
[int] $ProdCap = 3,
|
|
158
|
-
[
|
|
184
|
+
[scriptblock] $ReadCheckpoint = {
|
|
185
|
+
param([string] $Path)
|
|
186
|
+
if (Test-Path -LiteralPath $Path -PathType Leaf) {
|
|
187
|
+
return (Get-Content -LiteralPath $Path -Raw)
|
|
188
|
+
}
|
|
189
|
+
return ''
|
|
190
|
+
},
|
|
159
191
|
[scriptblock] $TestPathExists = { param([string] $Path) Test-Path -Path $Path },
|
|
160
192
|
[scriptblock] $EnsureDirectory = { param([string] $Path) New-Item -ItemType Directory -Path $Path -Force | Out-Null },
|
|
161
193
|
[scriptblock] $ReadState = { param([string] $Path) Get-Content -Path $Path -Raw },
|
|
@@ -186,23 +218,41 @@ function Invoke-PythonBatchBudgetHook {
|
|
|
186
218
|
}
|
|
187
219
|
|
|
188
220
|
$stateDir = Join-Path -Path $Root -ChildPath '.codex/state'
|
|
221
|
+
$stateFile = Join-Path -Path $stateDir -ChildPath ("python-batch-budget.$SessionId.json")
|
|
222
|
+
|
|
223
|
+
# The checkpoint is read before any state operation, so the large path neither
|
|
224
|
+
# creates the state directory nor reads or writes the state file.
|
|
225
|
+
$checkpointPath = Join-Path -Path $Root -ChildPath 'artifacts/orchestration/orchestrator-state.json'
|
|
226
|
+
$checkpointText = ''
|
|
227
|
+
try {
|
|
228
|
+
$checkpointText = [string](& $ReadCheckpoint $checkpointPath)
|
|
229
|
+
} catch {
|
|
230
|
+
Write-Verbose "Treating unreadable orchestrator checkpoint '$checkpointPath' as direct mode: $($_.Exception.Message)"
|
|
231
|
+
$checkpointText = ''
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
$isLargePath = Test-BatchBudgetLargePathRoute -CheckpointText $checkpointText
|
|
235
|
+
$observedRoute = Get-BatchBudgetSelectedRoute -CheckpointText $checkpointText
|
|
236
|
+
if ($isLargePath) {
|
|
237
|
+
return Invoke-PythonBatchBudgetDecision -FilePath $filePath -State (Get-PythonBatchBudgetState -ProdCap $ProdCap) -StateFile $stateFile -LargePathRoute
|
|
238
|
+
}
|
|
239
|
+
|
|
189
240
|
if (-not (& $TestPathExists $stateDir)) {
|
|
190
241
|
& $EnsureDirectory $stateDir
|
|
191
242
|
}
|
|
192
243
|
|
|
193
|
-
$
|
|
194
|
-
$state = Get-PythonBatchBudgetState -ProdCap $ProdCap -TestCap $TestCap
|
|
244
|
+
$state = Get-PythonBatchBudgetState -ProdCap $ProdCap
|
|
195
245
|
|
|
196
246
|
if (& $TestPathExists $stateFile) {
|
|
197
247
|
try {
|
|
198
248
|
$loaded = & $ReadState $stateFile | ConvertFrom-Json -ErrorAction Stop
|
|
199
|
-
$state = ConvertTo-PythonBatchBudgetState -InputObject $loaded -ProdCap $ProdCap
|
|
249
|
+
$state = ConvertTo-PythonBatchBudgetState -InputObject $loaded -ProdCap $ProdCap
|
|
200
250
|
} catch {
|
|
201
251
|
Write-Verbose "Ignoring unreadable Python batch-budget state file '$stateFile': $($_.Exception.Message)"
|
|
202
252
|
}
|
|
203
253
|
}
|
|
204
254
|
|
|
205
|
-
$decision = Invoke-PythonBatchBudgetDecision -FilePath $filePath -State $state -StateFile $stateFile
|
|
255
|
+
$decision = Invoke-PythonBatchBudgetDecision -FilePath $filePath -State $state -StateFile $stateFile -ObservedRoute $observedRoute
|
|
206
256
|
if ($decision.shouldWriteState) {
|
|
207
257
|
try {
|
|
208
258
|
& $WriteState $stateFile $decision.state
|
|
@@ -214,41 +264,81 @@ function Invoke-PythonBatchBudgetHook {
|
|
|
214
264
|
return $decision
|
|
215
265
|
}
|
|
216
266
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
267
|
+
function Invoke-PythonBatchBudgetCodexEntryPoint {
|
|
268
|
+
<#
|
|
269
|
+
.SYNOPSIS
|
|
270
|
+
Runs the Codex Python batch-budget decision and returns the process exit code.
|
|
271
|
+
.DESCRIPTION
|
|
272
|
+
Parses the Codex PreToolUse payload through the shared transport, collects both
|
|
273
|
+
sides of every mapped file edit, and evaluates each path with the Python hook.
|
|
274
|
+
The first deny is written to the output stream as compact JSON without its state
|
|
275
|
+
property, followed by exit code 0. When nothing is denied the function returns
|
|
276
|
+
0 and writes nothing else. Any failure writes the error text to standard error
|
|
277
|
+
and returns 2. The function does not call exit.
|
|
278
|
+
.PARAMETER PayloadRaw
|
|
279
|
+
Raw PreToolUse payload text.
|
|
280
|
+
.PARAMETER RepositoryRoot
|
|
281
|
+
Root used to locate the Codex state directory and the orchestrator checkpoint.
|
|
282
|
+
.PARAMETER HookSeams
|
|
283
|
+
Optional seam overrides splatted into Invoke-PythonBatchBudgetHook.
|
|
284
|
+
#>
|
|
285
|
+
[CmdletBinding()]
|
|
286
|
+
[OutputType([int])]
|
|
287
|
+
param(
|
|
288
|
+
[Parameter(Mandatory)]
|
|
289
|
+
[AllowNull()]
|
|
290
|
+
[AllowEmptyString()]
|
|
291
|
+
[string] $PayloadRaw,
|
|
292
|
+
|
|
293
|
+
[Parameter(Mandatory)]
|
|
294
|
+
[string] $RepositoryRoot,
|
|
220
295
|
|
|
221
|
-
|
|
222
|
-
# Transport and mapping come from the shared module. session_id is still
|
|
223
|
-
# required because the batch counter is keyed by it.
|
|
224
|
-
$payload = ConvertFrom-CodexPreToolUsePayload -PayloadRaw ([Console]::In.ReadToEnd()) -HookName 'enforce-python-batch-budget' -RequireSessionId
|
|
225
|
-
$sessionId = ([string]$payload.session_id) -replace '[^A-Za-z0-9._-]', '_'
|
|
226
|
-
$repositoryRoot = Split-Path (Split-Path $PSScriptRoot -Parent) -Parent
|
|
227
|
-
$prodCap = 3
|
|
228
|
-
$testCap = 3
|
|
229
|
-
|
|
230
|
-
# Both sides of a rename consume budget, matching the pre-fix path scan that
|
|
231
|
-
# collected Add/Update/Delete targets and Move destinations alike. Ordering
|
|
232
|
-
# and de-duplication are preserved. A well-formed payload that maps to no
|
|
233
|
-
# file yields no paths, so no state is written and the hook allows silently.
|
|
234
|
-
$budgetPaths = @(
|
|
235
|
-
@(ConvertTo-CodexFileEditInput -Payload $payload) |
|
|
236
|
-
ForEach-Object { $_.source_path; $_.file_path } |
|
|
237
|
-
Where-Object { -not [string]::IsNullOrWhiteSpace($_) } |
|
|
238
|
-
Select-Object -Unique
|
|
296
|
+
[hashtable] $HookSeams = @{}
|
|
239
297
|
)
|
|
240
298
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
299
|
+
try {
|
|
300
|
+
# Transport and mapping come from the shared module. session_id is still
|
|
301
|
+
# required because the direct-mode counter is keyed by it.
|
|
302
|
+
$payload = ConvertFrom-CodexPreToolUsePayload -PayloadRaw $PayloadRaw -HookName 'enforce-python-batch-budget' -RequireSessionId
|
|
303
|
+
$sessionId = ([string]$payload.session_id) -replace '[^A-Za-z0-9._-]', '_'
|
|
304
|
+
|
|
305
|
+
# Both sides of a rename are evaluated, matching the path scan that collected
|
|
306
|
+
# Add/Update/Delete targets and Move destinations alike. Ordering and
|
|
307
|
+
# de-duplication are preserved. A well-formed payload that maps to no file
|
|
308
|
+
# yields no paths, so no state is written and the hook allows silently.
|
|
309
|
+
$budgetPaths = @(
|
|
310
|
+
@(ConvertTo-CodexFileEditInput -Payload $payload) |
|
|
311
|
+
ForEach-Object { $_.source_path; $_.file_path } |
|
|
312
|
+
Where-Object { -not [string]::IsNullOrWhiteSpace($_) } |
|
|
313
|
+
Select-Object -Unique
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
foreach ($path in $budgetPaths) {
|
|
317
|
+
$toolInputRaw = @{ file_path = $path } | ConvertTo-Json -Compress
|
|
318
|
+
$decision = Invoke-PythonBatchBudgetHook -ToolInputRaw $toolInputRaw -SessionId $sessionId -Root $RepositoryRoot @HookSeams
|
|
319
|
+
if ($decision.hookSpecificOutput.permissionDecision -eq 'deny') {
|
|
320
|
+
$decision.Remove('state')
|
|
321
|
+
$decision | ConvertTo-Json -Compress -Depth 5 | Write-Output
|
|
322
|
+
return 0
|
|
323
|
+
}
|
|
248
324
|
}
|
|
325
|
+
|
|
326
|
+
return 0
|
|
327
|
+
} catch {
|
|
328
|
+
[Console]::Error.WriteLine([string]$_)
|
|
329
|
+
return 2
|
|
249
330
|
}
|
|
250
|
-
exit 0
|
|
251
|
-
} catch {
|
|
252
|
-
[Console]::Error.WriteLine([string]$_)
|
|
253
|
-
exit 2
|
|
254
331
|
}
|
|
332
|
+
|
|
333
|
+
if ($MyInvocation.InvocationName -eq '.') {
|
|
334
|
+
return
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
# The entry point returns its [int] exit code as the last pipeline element and any
|
|
338
|
+
# deny JSON before it, so the JSON is written explicitly before the process exits.
|
|
339
|
+
$entryPointResult = @(Invoke-PythonBatchBudgetCodexEntryPoint -PayloadRaw ([Console]::In.ReadToEnd()) -RepositoryRoot (Split-Path (Split-Path $PSScriptRoot -Parent) -Parent))
|
|
340
|
+
if ($entryPointResult.Count -gt 1) {
|
|
341
|
+
$entryPointResult[0..($entryPointResult.Count - 2)] | Write-Output
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
exit ([int]$entryPointResult[-1])
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
".codex/hooks/validate-codex-subagent-routing.ps1",
|
|
49
49
|
".codex/hooks/check-powershell-test-purity.ps1",
|
|
50
50
|
".codex/hooks/check-python-test-purity.ps1",
|
|
51
|
+
".codex/hooks/enforce-batch-budget-route.ps1",
|
|
51
52
|
".codex/hooks/enforce-checkpoint-monotonic.ps1",
|
|
52
53
|
".codex/hooks/enforce-completion-consistency.ps1",
|
|
53
54
|
".codex/hooks/enforce-completion-helpers.ps1",
|
|
@@ -97,7 +97,7 @@ Use these reusable skills to avoid duplicating shared operations:
|
|
|
97
97
|
3) **Single source of routing truth = change budget**
|
|
98
98
|
- First action is always to estimate rough change budget by identifying likely affected production Python files.
|
|
99
99
|
- If estimate is `1-3` production Python files (+ corresponding tests), use **small path**.
|
|
100
|
-
- If estimate is
|
|
100
|
+
- If estimate is more than 3 (`>3`) production Python files, use **large path**. The large path has no production-file cap. Test files are not counted toward the routing threshold.
|
|
101
101
|
|
|
102
102
|
4) **Deterministic variable handling**
|
|
103
103
|
- Persist and reuse these variables exactly as names:
|
|
@@ -117,7 +117,7 @@ Use these reusable skills to avoid duplicating shared operations:
|
|
|
117
117
|
|
|
118
118
|
## Phase 0 — Intake and budget estimate (mandatory)
|
|
119
119
|
|
|
120
|
-
1. Read user request and infer likely touched production Python files
|
|
120
|
+
1. Read user request and infer likely touched production Python files.
|
|
121
121
|
2. Estimate rough change budget.
|
|
122
122
|
3. Write/update orchestration checkpoint.
|
|
123
123
|
4. Route to one of two paths:
|
|
@@ -126,7 +126,7 @@ Use these reusable skills to avoid duplicating shared operations:
|
|
|
126
126
|
|
|
127
127
|
---
|
|
128
128
|
|
|
129
|
-
## Small path (budget 1-3 production Python files
|
|
129
|
+
## Small path (budget 1-3 production Python files)
|
|
130
130
|
|
|
131
131
|
Follow this exact sequence.
|
|
132
132
|
|
|
@@ -243,7 +243,7 @@ Hard enforcement for S8:
|
|
|
243
243
|
|
|
244
244
|
---
|
|
245
245
|
|
|
246
|
-
## Large path (budget >3 production Python files
|
|
246
|
+
## Large path (budget >3 production Python files)
|
|
247
247
|
|
|
248
248
|
Follow this exact sequence.
|
|
249
249
|
|
|
@@ -58,12 +58,12 @@ If any instructions conflict, **halt and notify the user**.
|
|
|
58
58
|
|
|
59
59
|
## 1) Scope control (NO scope creep)
|
|
60
60
|
|
|
61
|
-
- Default scope is **one feature slice** (typically **1
|
|
62
|
-
-
|
|
61
|
+
- Default scope is **one feature slice** (typically **1-3 production files** within the same package) plus its corresponding test file(s).
|
|
62
|
+
- Within the direct-mode budget, a slice may include production files beyond the primary module only when it is required to:
|
|
63
63
|
- introduce a minimal seam for testability (I/O boundary isolation, dependency injection),
|
|
64
64
|
- make typing changes required for Pyright cleanliness in the slice, or
|
|
65
65
|
- update the smallest set of call sites needed to preserve a stable public API.
|
|
66
|
-
-
|
|
66
|
+
- If the change requires more than 3 production files, stop and instruct the caller to use `python-orchestrator` (or `.github/prompts/orchestrate-python-work.prompt.md`). The orchestrated large path has no production-file cap.
|
|
67
67
|
- You may not modify additional production files unless:
|
|
68
68
|
- the user explicitly expands scope, OR
|
|
69
69
|
- a shared helper is objectively broken and the minimal fix is required for the in-scope change.
|
|
@@ -73,11 +73,10 @@ If any instructions conflict, **halt and notify the user**.
|
|
|
73
73
|
- the smallest alternative that avoids expanding scope
|
|
74
74
|
Proceed only after user approval.
|
|
75
75
|
|
|
76
|
-
## 2) Change budget (
|
|
76
|
+
## 2) Change budget (routing threshold)
|
|
77
77
|
|
|
78
|
-
-
|
|
79
|
-
-
|
|
80
|
-
- If no override is provided, the 3/3 limit applies; if an override is requested, comfirm compliance before Phase C.
|
|
78
|
+
- Direct mode budget: 1-3 production Python files (+ corresponding tests). A change of more than 3 production Python files belongs on the orchestrated large path (`python-orchestrator`).
|
|
79
|
+
- Test files are not counted toward the routing threshold, and the orchestrated large path has no production-file cap.
|
|
81
80
|
|
|
82
81
|
## 3) Deterministic unit tests only (no temp files, no external systems)
|
|
83
82
|
|
|
@@ -135,7 +134,7 @@ If no plan is provided, delegate the creation of a plan to the `atomic_planner`.
|
|
|
135
134
|
- Mocking plan (what is mocked, where patched, and why)
|
|
136
135
|
- Exact files to change (must match scope guardrails)
|
|
137
136
|
|
|
138
|
-
Before exiting Phase B, perform a quick line-count check on all in-scope files. If any file is near the 500-line limit or planned additions would push it over 500, decide upfront to split now (counting new files against the budget)
|
|
137
|
+
Before exiting Phase B, perform a quick line-count check on all in-scope files. If any file is near the 500-line limit or planned additions would push it over 500, decide upfront to split now (counting new files against the budget) before Phase C. If uncertain, treat it as at-risk and plan for a split rather than discovering it mid-execution. If an approved plan would create a 500-line violation, halt and seek clarification before proceeding.
|
|
139
138
|
|
|
140
139
|
Do not proceed to edits until the user explicitly approves (e.g., “Proceed.”).
|
|
141
140
|
However, if a plan is provided in the initial prompt, it is already implicitly approved.
|
|
@@ -20,10 +20,10 @@ Coordinate the user request from intake to completion using the correct path bas
|
|
|
20
20
|
|
|
21
21
|
## Required orchestration behavior
|
|
22
22
|
|
|
23
|
-
1. Estimate rough change budget first (production Python files
|
|
24
|
-
2. If budget is **1
|
|
23
|
+
1. Estimate rough change budget first (production Python files; test files are not counted toward the routing threshold).
|
|
24
|
+
2. If budget is **1-3 production Python files** (+ corresponding tests):
|
|
25
25
|
- Delegate directly to `python-typed-engineer` for plan + implementation + QA closure.
|
|
26
|
-
3. If budget is
|
|
26
|
+
3. If budget is **more than 3 production Python files**:
|
|
27
27
|
- Execute full large-path lifecycle:
|
|
28
28
|
1) Scope and create potential entry (`feature` vs `bug`, short-name creation)
|
|
29
29
|
2) Promote to GitHub issue and capture issue metadata
|
|
@@ -68,6 +68,14 @@ During plan execution, after completing a task whose work satisfies an acceptanc
|
|
|
68
68
|
|
|
69
69
|
Timing: Check off AC items as soon as the corresponding plan task passes verification — do not defer all AC updates to the end of plan execution.
|
|
70
70
|
|
|
71
|
+
### CI-Dependent Criteria
|
|
72
|
+
|
|
73
|
+
A CI-dependent criterion is one whose verification requires the result of CI on the PR head. It cannot be verified before the pull request exists, so it stays unchecked and is listed as pending-CI in the AC verification artifact until CI has run.
|
|
74
|
+
|
|
75
|
+
- Owner: the item's own orchestrator run owns the check-off and performs it at S9; this is the one case in which an orchestrator run checks off AC. A parent or coordinating session never commits the check-off from its own root.
|
|
76
|
+
- Timing: after the CI green gate (S9) records `ci_gate.conclusion` as `success`, and before the run reports DONE.
|
|
77
|
+
- Push and re-verify: the check-off is committed in the item's own worktree and pushed to the PR branch, and the CI green gate is re-run against the new head SHA so that `ci_gate.head_sha` equals the final PR head before DONE.
|
|
78
|
+
|
|
71
79
|
### When Reviewers Check Off AC
|
|
72
80
|
|
|
73
81
|
During feature review (feature-audit phase):
|
|
@@ -19,6 +19,8 @@ Use this skill when:
|
|
|
19
19
|
Use `yyyy-MM-ddTHH-mm` for all audit, remediation, and evidence artifacts.
|
|
20
20
|
Example: `2026-02-06T14-30`.
|
|
21
21
|
|
|
22
|
+
The `Timestamp` value is local time read from the host system clock when the recorded command runs (for example `Get-Date -Format yyyy-MM-ddTHH-mm`); the agent never composes or estimates it.
|
|
23
|
+
|
|
22
24
|
## Canonical Evidence Locations
|
|
23
25
|
|
|
24
26
|
- Baseline evidence: `evidence/baseline/`
|
|
@@ -83,6 +85,8 @@ When evidence artifacts are used for automated checking or plan reconciliation,
|
|
|
83
85
|
- `Command: <exact command>`
|
|
84
86
|
- `EXIT_CODE: <int>`
|
|
85
87
|
|
|
88
|
+
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.
|
|
89
|
+
|
|
86
90
|
One optional field may also be declared:
|
|
87
91
|
- `ExpectedExitCode: <int>` — the exit code the gate is expected to produce.
|
|
88
92
|
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
'.claude/hooks/check-powershell-test-purity.ps1'
|
|
30
30
|
'.claude/hooks/enforce-python-batch-budget.ps1'
|
|
31
31
|
'.claude/hooks/enforce-powershell-batch-budget.ps1'
|
|
32
|
-
'.claude/hooks/enforce-
|
|
32
|
+
'.claude/hooks/enforce-batch-budget-route.ps1'
|
|
33
33
|
# Issue #272 hardened this PreToolUse hook with a new orchestrator-state preflight
|
|
34
34
|
# check; measured here so the change produces real per-file coverage evidence.
|
|
35
35
|
'.claude/hooks/enforce-pr-author-skill.ps1'
|
|
@@ -45,8 +45,10 @@
|
|
|
45
45
|
'.claude/hooks/enforce-epic-merge-gate.ps1'
|
|
46
46
|
# Issue #670: CodeCoverage.Path is an explicit per-file allow-list, so the dot-sourced helpers file is listed here.
|
|
47
47
|
'.claude/hooks/enforce-epic-merge-gate-authorization.ps1'
|
|
48
|
+
'.claude/hooks/enforce-epic-merge-gate-resolution.ps1'
|
|
48
49
|
'.claude/hooks/enforce-epic-wave-barrier.ps1'
|
|
49
50
|
'.claude/hooks/enforce-epic-worktree-removal-gate.ps1'
|
|
51
|
+
'.claude/hooks/enforce-epic-worktree-removal-gate-resolution.ps1'
|
|
50
52
|
'.claude/hooks/enforce-pr-author-skill.ps1'
|
|
51
53
|
'.claude/hooks/validate-orchestrator-output.ps1'
|
|
52
54
|
'.claude/hooks/enforce-pr-author-skill.epic-base-branch.ps1'
|
|
@@ -102,6 +104,8 @@
|
|
|
102
104
|
# measured here so the new production modules are not excluded from coverage.
|
|
103
105
|
'.claude/lib/orchestrator-state/OrchestratorStateCheckpointValue.psm1'
|
|
104
106
|
'.claude/lib/orchestrator-state/OrchestratorStateReceipts.psm1'
|
|
107
|
+
# Issue #484 added the remediation-loop R5-R11 accounting module.
|
|
108
|
+
'.claude/lib/orchestrator-state/OrchestratorStateRemediationAccounting.psm1'
|
|
105
109
|
'.claude/lib/orchestrator-state/OrchestratorStateModelReceipts.psm1'
|
|
106
110
|
# Issue #475 added the portable Codex routing resolvers so the U6.X and U6.T
|
|
107
111
|
# checkpoint checks resolve deployments and topologies without a Python
|
|
@@ -119,6 +123,8 @@
|
|
|
119
123
|
'.claude/lib/orchestrator-state/OrchestratorStateRoutingMatrix.psm1'
|
|
120
124
|
'.claude/lib/orchestrator-state/OrchestratorStateCompletionChecks.psm1'
|
|
121
125
|
'.claude/lib/orchestrator-state/OrchestratorStateRoutingContract.psm1'
|
|
126
|
+
# Issue #509 added the issue-adoption resolver consumed by the routing contract.
|
|
127
|
+
'.claude/lib/orchestrator-state/OrchestratorStateIssueAdoption.psm1'
|
|
122
128
|
'.claude/lib/orchestrator-state/OrchestratorStateUnconditional.psm1'
|
|
123
129
|
# Issue #392 changed the Invoke-PoshQCTest default seams ($EnsureModule -Global
|
|
124
130
|
# import and the global-session-state $InvokePester trampoline) so the bundled
|
|
@@ -135,6 +141,7 @@
|
|
|
135
141
|
'.codex/hooks/check-powershell-test-purity.ps1'
|
|
136
142
|
'.codex/hooks/enforce-python-batch-budget.ps1'
|
|
137
143
|
'.codex/hooks/enforce-powershell-batch-budget.ps1'
|
|
144
|
+
'.codex/hooks/enforce-batch-budget-route.ps1'
|
|
138
145
|
'.codex/hooks/enforce-evidence-locations.ps1'
|
|
139
146
|
'.codex/hooks/enforce-checkpoint-monotonic.ps1'
|
|
140
147
|
'.codex/hooks/enforce-orchestration-preimplementation-gate.ps1'
|
|
@@ -318,11 +325,19 @@
|
|
|
318
325
|
# Issue #663 added the epic-scope resolver and its pure readiness predicates.
|
|
319
326
|
'.claude/lib/worktree-resolution/EpicScopeResolution.psm1'
|
|
320
327
|
'.claude/lib/worktree-resolution/EpicScopeReadiness.psm1'
|
|
328
|
+
# Issue #690 added the run-target resolver; registered so it stays in the coverage denominator.
|
|
329
|
+
'.claude/lib/worktree-resolution/WorktreeRunResolution.psm1'
|
|
321
330
|
# Issue #762 relocated the CI gate parser into the bundled .claude/lib tree so
|
|
322
331
|
# push-down carries it with the orchestrate and epic-orchestrate skills.
|
|
323
332
|
# CodeCoverage.Path is an explicit per-file allow-list, so the relocated production
|
|
324
333
|
# file is registered here to stay in the coverage denominator.
|
|
325
334
|
'.claude/lib/ci-gate/Invoke-CiGateParser.ps1'
|
|
335
|
+
# Issue #763 ported radius drift detection to the destination runtime as two pure
|
|
336
|
+
# modules and an entry script under .claude/lib/parallel-drift. CodeCoverage.Path is an
|
|
337
|
+
# explicit per-file allow-list, so each new production file is registered here.
|
|
338
|
+
'.claude/lib/parallel-drift/ParallelDriftHalt.psm1'
|
|
339
|
+
'.claude/lib/parallel-drift/ParallelDrift.psm1'
|
|
340
|
+
'.claude/lib/parallel-drift/Invoke-ParallelDriftDetection.ps1'
|
|
326
341
|
)
|
|
327
342
|
# Optional: don't fail the run on coverage percentage
|
|
328
343
|
CoveragePercentTarget = 0
|