@danmoisan/drm-copilot-mcp 1.1.11 → 1.1.12

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.
Files changed (52) hide show
  1. package/out/mcp-server.js +366 -159
  2. package/package.json +1 -1
  3. package/resources/claude-customizations/.claude/agents/epic-orchestrator.md +1 -1
  4. package/resources/claude-customizations/.claude/agents/epic-planner.md +4 -1
  5. package/resources/claude-customizations/.claude/agents/pr-author.md +15 -0
  6. package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate-authorization.ps1 +443 -0
  7. package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate.ps1 +33 -37
  8. package/resources/claude-customizations/.claude/hooks/enforce-model-routing-receipt.ps1 +120 -5
  9. package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-epic-scope.ps1 +127 -0
  10. package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-helpers.ps1 +163 -15
  11. package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate.ps1 +14 -27
  12. package/resources/claude-customizations/.claude/hooks/enforce-parallel-worktree-removal-gate.ps1 +66 -5
  13. package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill-helpers.ps1 +134 -10
  14. package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.epic-base-branch.ps1 +37 -8
  15. package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.ps1 +3 -1
  16. package/resources/claude-customizations/.claude/hooks/enforce-prd-feature-before-planner-helpers.ps1 +332 -0
  17. package/resources/claude-customizations/.claude/hooks/enforce-prd-feature-before-planner.ps1 +211 -182
  18. package/resources/claude-customizations/.claude/lib/codex-routing/CodexDeployment.psm1 +1 -0
  19. package/resources/claude-customizations/.claude/lib/worktree-resolution/EpicScopeReadiness.psm1 +176 -0
  20. package/resources/claude-customizations/.claude/lib/worktree-resolution/EpicScopeResolution.psm1 +369 -0
  21. package/resources/claude-customizations/.claude/lib/worktree-resolution/WorktreeItemResolution.psm1 +392 -0
  22. package/resources/claude-customizations/.claude/lib/worktree-resolution/WorktreeResolution.psm1 +500 -0
  23. package/resources/claude-customizations/.claude/lib/worktree-resolution/WorktreeTargetResolution.psm1 +347 -0
  24. package/resources/claude-customizations/.claude/rules/orchestrator-state.md +27 -0
  25. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/SKILL.md +12 -0
  26. package/resources/claude-customizations/.claude/skills/epic-orchestrate/SKILL.md +14 -1
  27. package/resources/claude-customizations/.claude/skills/epic-plan/SKILL.md +4 -0
  28. package/resources/claude-customizations/.claude/skills/orchestrate/SKILL.md +4 -1
  29. package/resources/claude-customizations/.claude/skills/parallel-orchestrate/SKILL.md +39 -6
  30. package/resources/claude-customizations/.claude/skills/pr-author/SKILL.md +15 -0
  31. package/resources/claude-customizations/.claude/skills/quota-throttling/SKILL.md +221 -0
  32. package/resources/claude-customizations/pack-manifests/core.json +9 -0
  33. package/resources/codex-and-agents-customizations/.agents/skills/codex-model-routing/SKILL.md +13 -14
  34. package/resources/codex-and-agents-customizations/.codex/config.toml +1 -1
  35. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-merge-gate.ps1 +193 -0
  36. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-planning-only.ps1 +15 -5
  37. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-helpers.ps1 +163 -15
  38. package/resources/codex-and-agents-customizations/.codex/scripts/Resolve-CodexDeployment.ps1 +87 -0
  39. package/resources/codex-and-agents-customizations/.codex/scripts/Resolve-CodexTopology.ps1 +96 -0
  40. package/resources/codex-and-agents-customizations/.codex/scripts/codex-routing-cli-common.ps1 +370 -0
  41. package/resources/codex-and-agents-customizations/.codex/scripts/epic-child-launch-contract.ps1 +475 -0
  42. package/resources/codex-and-agents-customizations/.codex/scripts/epic-child-launch-runtime.ps1 +445 -0
  43. package/resources/codex-and-agents-customizations/.codex/scripts/epic-child-persistence-runtime.ps1 +118 -0
  44. package/resources/codex-and-agents-customizations/.codex/scripts/epic-child-sandbox-preflight.ps1 +69 -0
  45. package/resources/codex-and-agents-customizations/.codex/scripts/launch-epic-child-wave.ps1 +471 -0
  46. package/resources/codex-and-agents-customizations/.codex/scripts/post-codex-worktree-session.ps1 +280 -0
  47. package/resources/codex-and-agents-customizations/.codex/scripts/resume-epic-child.ps1 +263 -0
  48. package/resources/codex-and-agents-customizations/.codex-variants/csharp-legacy/agents/csharp-typed-engineer.toml +2 -1
  49. package/resources/codex-and-agents-customizations/pack-manifests/core.json +18 -1
  50. package/resources/lib/codex-routing/CodexDeployment.psm1 +315 -0
  51. package/resources/lib/codex-routing/CodexTopology.psm1 +394 -0
  52. package/resources/powershell/PoshQC/settings/pester.runsettings.psd1 +26 -0
@@ -0,0 +1,394 @@
1
+ <#
2
+ .SYNOPSIS
3
+ Codex implementation-topology resolver, ported from the Python reference.
4
+
5
+ .DESCRIPTION
6
+ Destination-runtime PowerShell port of
7
+ `scripts/dev_tools/resolve_codex_topology.py`. It resolves the initial
8
+ implementation agent for one change from deterministic scope data: the
9
+ languages touched, the production and test file counts, the execution
10
+ context, the cross-cutting indicator, and an optional forced root persona.
11
+
12
+ Routing summary. A standalone, single-language change inside that language's
13
+ canonical direct-mode budget selects the language's typed engineer on the
14
+ `small` route. Every escalation condition selects the orchestrator on the
15
+ `large` route. An explicit root epic persona selects itself on the `epic`
16
+ route. The escalation conditions are evaluated in a fixed precedence order,
17
+ and the first match wins:
18
+
19
+ epic_child_context -> invalid_estimate -> cross_language ->
20
+ unsupported_language -> cross_cutting -> direct_mode_disabled ->
21
+ production_budget_exceeded
22
+
23
+ SINGLE-IMPLEMENTATION RULE. The orchestrator-state U6.T checks
24
+ (`OrchestratorStateCodexTopologyReceipts.psm1`) MUST call
25
+ `Resolve-CodexTopology` and read `Get-CodexForcedRootPersona` from this
26
+ module. They must never re-implement the language-budget table or the
27
+ escalation precedence. This module is the one PowerShell implementation of
28
+ the Codex topology axis.
29
+
30
+ Every constant below is pinned to `config/orchestration-routing.json`
31
+ (`codex_topology_policy`). Following the `ModelRouting.psm1` pattern, the
32
+ values are hard-coded here and never read from disk, because this module is
33
+ pushed down to consumer repositories that do not receive that config.
34
+
35
+ Error surface, relied on by the U6.T receipt checks:
36
+ - [System.ArgumentException] is the ValueError-equivalent surface. Its
37
+ Message text reproduces the Python message verbatim, including Python
38
+ tuple and repr() rendering, because inventory row U6.T10 interpolates
39
+ the exception text into its error string.
40
+
41
+ Documented divergence: Python raises TypeError (not ValueError) when
42
+ `languages` is not iterable, and the receipt validator does not catch
43
+ TypeError. This port treats a null Language argument as an empty collection,
44
+ which routes to the `unsupported_language` escalation. The difference is
45
+ unreachable from the U6.T checks, which reject a non-list `languages` before
46
+ the resolver is ever called.
47
+
48
+ The function is pure: it reads no file, starts no process, and never mutates
49
+ its input.
50
+ CONVENTION: this module fails fast at module scope and imports its siblings with -ErrorAction Stop.
51
+ #>
52
+
53
+ Set-StrictMode -Version Latest
54
+ $ErrorActionPreference = 'Stop'
55
+
56
+ # The three permitted execution contexts, the sorted tuple rendering the Python
57
+ # message interpolates, and the two contexts that mark epic child work.
58
+ $script:VALID_EXECUTION_CONTEXTS = @('standalone', 'epic_preparation_child', 'epic_execution_child')
59
+ $script:VALID_EXECUTION_CONTEXTS_PYTHON_TUPLE = "('epic_execution_child', 'epic_preparation_child', 'standalone')"
60
+ $script:EPIC_CHILD_CONTEXTS = @('epic_preparation_child', 'epic_execution_child')
61
+ $script:STANDALONE_CONTEXT = 'standalone'
62
+
63
+ # The two personas that may be forced as the root of a run, and the logical agent
64
+ # every escalation routes to.
65
+ $script:FORCED_ROOT_PERSONAS = @('epic-planner', 'epic-orchestrator')
66
+ $script:ORCHESTRATOR_LOGICAL_AGENT = 'orchestrator'
67
+
68
+ # The per-language direct-mode budgets. A language absent from this table is an
69
+ # unsupported language and escalates.
70
+ $script:LANGUAGE_BUDGETS = @{
71
+ python = @{ direct_mode_enabled = $true; max_production_files = 3; max_test_files = 3; logical_agent = 'python-typed-engineer' }
72
+ powershell = @{ direct_mode_enabled = $true; max_production_files = 2; max_test_files = 3; logical_agent = 'powershell-typed-engineer' }
73
+ csharp = @{ direct_mode_enabled = $true; max_production_files = 3; max_test_files = 3; logical_agent = 'csharp-typed-engineer' }
74
+ typescript = @{ direct_mode_enabled = $false; max_production_files = 0; max_test_files = 0; logical_agent = 'typescript-engineer' }
75
+ }
76
+
77
+ # The integral CLR types a JSON integer can deserialize to. A CLR boolean is
78
+ # deliberately absent: Python rejects bool where an int is required.
79
+ $script:INTEGRAL_TYPES = @([int], [long], [short], [byte])
80
+
81
+
82
+ function Get-CodexForcedRootPersona {
83
+ <#
84
+ .SYNOPSIS
85
+ Return the two personas that may be forced as the root of a run.
86
+ .DESCRIPTION
87
+ Read-only accessor for FORCED_ROOT_PERSONAS. Exported so the U6.T
88
+ root_persona enum check reads the same set the resolver enforces instead
89
+ of restating it.
90
+ .OUTPUTS
91
+ System.String[] - the forced root persona names, in declaration order.
92
+ The names are emitted to the pipeline individually, so a caller collects
93
+ them with @(...) in the usual way.
94
+ #>
95
+ [CmdletBinding()]
96
+ [OutputType([string[]])]
97
+ param()
98
+
99
+ return [string[]]@($script:FORCED_ROOT_PERSONAS)
100
+ }
101
+
102
+ function Test-CodexIntegralValue {
103
+ <#
104
+ .SYNOPSIS
105
+ Report whether a value is an integer, rejecting booleans.
106
+ .DESCRIPTION
107
+ Private predicate mirroring the Python guard
108
+ `isinstance(value, bool) or not isinstance(value, int)`. Python's bool is
109
+ a subclass of int, so the reference rejects it explicitly; this port
110
+ compares the exact CLR type so no boolean satisfies the test.
111
+ .PARAMETER Value
112
+ The candidate value. May be $null.
113
+ .OUTPUTS
114
+ System.Boolean - $true only for a non-boolean integral value.
115
+ #>
116
+ [CmdletBinding()]
117
+ [OutputType([bool])]
118
+ param(
119
+ [Parameter(Mandatory = $true)]
120
+ [AllowNull()]
121
+ [object] $Value
122
+ )
123
+
124
+ if ($null -eq $Value -or $Value -is [bool]) { return $false }
125
+ foreach ($integralType in $script:INTEGRAL_TYPES) {
126
+ if ($Value.GetType() -eq $integralType) { return $true }
127
+ }
128
+ return $false
129
+ }
130
+
131
+ function Get-CodexNormalizedLanguage {
132
+ <#
133
+ .SYNOPSIS
134
+ Return unique, lowercased language names in stable ordinal order.
135
+ .DESCRIPTION
136
+ Private helper mirroring _normalize_languages. Every element must be a
137
+ non-blank string; anything else throws the ValueError-equivalent. The
138
+ result is deduplicated and ordinally sorted so the resolved receipt is
139
+ order-independent, matching Python's sorted(set(...)).
140
+ .PARAMETER Language
141
+ The raw language collection. A null value is treated as empty.
142
+ .OUTPUTS
143
+ System.String[] - the normalized language names. Declared additionally as
144
+ System.Object[] because the array is emitted through the unary-comma form
145
+ that stops PowerShell unrolling it.
146
+ #>
147
+ [CmdletBinding()]
148
+ [OutputType([string[]], [object[]])]
149
+ param(
150
+ [Parameter(Mandatory = $true)]
151
+ [AllowNull()]
152
+ [object] $Language
153
+ )
154
+
155
+ $normalized = [System.Collections.Generic.HashSet[string]]::new()
156
+
157
+ # Reject the whole collection on the first malformed member so a partially
158
+ # valid language list can never route a delegation.
159
+ foreach ($item in @($Language)) {
160
+ if (-not ($item -is [string]) -or [string]::IsNullOrWhiteSpace([string]$item)) {
161
+ throw [System.ArgumentException]::new('languages must contain non-empty strings.')
162
+ }
163
+ [void]$normalized.Add(([string]$item).Trim().ToLowerInvariant())
164
+ }
165
+
166
+ # Ordinal ordering matches Python's sorted() over the same names; PowerShell's
167
+ # culture-aware Sort-Object would not be guaranteed to. The unary comma stops
168
+ # PowerShell from unrolling the array on return, which would otherwise turn a
169
+ # single-language result into a bare string and a zero-language result into
170
+ # nothing at all.
171
+ $sorted = [string[]]@($normalized)
172
+ [Array]::Sort($sorted, [System.StringComparer]::Ordinal)
173
+ return , $sorted
174
+ }
175
+
176
+ function Get-CodexEscalationReceipt {
177
+ <#
178
+ .SYNOPSIS
179
+ Build a large-route orchestrator receipt for one escalation reason.
180
+ .DESCRIPTION
181
+ Private pure builder mirroring _orchestrator_receipt. Every escalation returns
182
+ the same shape and differs only in routing_reason and in whether a
183
+ language budget was known at the point of escalation.
184
+ .PARAMETER ExecutionContext
185
+ The validated execution context.
186
+ .PARAMETER Language
187
+ The normalized language names.
188
+ .PARAMETER ProductionFileCount
189
+ The validated production file count.
190
+ .PARAMETER TestFileCount
191
+ The validated test file count.
192
+ .PARAMETER CrossCutting
193
+ The validated cross-cutting indicator.
194
+ .PARAMETER Reason
195
+ The escalation reason recorded in routing_reason.
196
+ .PARAMETER Budget
197
+ The language budget when one was resolved, otherwise $null. When absent,
198
+ both max file counts are reported as null.
199
+ .OUTPUTS
200
+ System.Collections.Hashtable - the twelve-key topology receipt.
201
+ #>
202
+ [CmdletBinding()]
203
+ [OutputType([hashtable])]
204
+ param(
205
+ [Parameter(Mandatory = $true)][string] $ExecutionContext,
206
+ [Parameter(Mandatory = $true)][AllowEmptyCollection()][string[]] $Language,
207
+ [Parameter(Mandatory = $true)][int] $ProductionFileCount,
208
+ [Parameter(Mandatory = $true)][int] $TestFileCount,
209
+ [Parameter(Mandatory = $true)][bool] $CrossCutting,
210
+ [Parameter(Mandatory = $true)][string] $Reason,
211
+ [Parameter(Mandatory = $false)][AllowNull()][hashtable] $Budget = $null
212
+ )
213
+
214
+ return @{
215
+ execution_context = $ExecutionContext
216
+ languages = $Language
217
+ production_file_count = $ProductionFileCount
218
+ test_file_count = $TestFileCount
219
+ cross_cutting = $CrossCutting
220
+ root_persona = $null
221
+ route = 'large'
222
+ topology = 'orchestrator'
223
+ logical_agent = $script:ORCHESTRATOR_LOGICAL_AGENT
224
+ routing_reason = $Reason
225
+ max_production_files = $(if ($null -ne $Budget) { $Budget['max_production_files'] } else { $null })
226
+ max_test_files = $(if ($null -ne $Budget) { $Budget['max_test_files'] } else { $null })
227
+ }
228
+ }
229
+
230
+ function Resolve-CodexTopology {
231
+ <#
232
+ .SYNOPSIS
233
+ Resolve the initial Codex implementation agent from scope data.
234
+ .DESCRIPTION
235
+ Faithful PowerShell port of resolve_codex_topology
236
+ (scripts/dev_tools/resolve_codex_topology.py). Validates the execution
237
+ context, the language collection, the two file counts, and the
238
+ cross-cutting indicator, then applies the forced-root-persona branch or
239
+ the fixed escalation precedence documented in the module header.
240
+ .PARAMETER Language
241
+ The languages the change touches. Normalized to unique lowercase names.
242
+ .PARAMETER ProductionFileCount
243
+ The production file count. Must be a non-boolean integer.
244
+ .PARAMETER TestFileCount
245
+ The test file count. Must be a non-boolean integer.
246
+ .PARAMETER ExecutionContext
247
+ One of standalone, epic_preparation_child, epic_execution_child.
248
+ .PARAMETER CrossCutting
249
+ Whether the change is cross-cutting. Must be a boolean.
250
+ .PARAMETER RootPersona
251
+ An optional forced root persona, which requires a standalone context.
252
+ .OUTPUTS
253
+ System.Collections.Hashtable with the twelve resolved keys:
254
+ execution_context, languages, production_file_count, test_file_count,
255
+ cross_cutting, root_persona, route, topology, logical_agent,
256
+ routing_reason, max_production_files, max_test_files.
257
+ #>
258
+ [CmdletBinding()]
259
+ [OutputType([hashtable])]
260
+ param(
261
+ [Parameter(Mandatory = $true)]
262
+ [AllowNull()]
263
+ [object] $Language,
264
+
265
+ [Parameter(Mandatory = $true)]
266
+ [AllowNull()]
267
+ [object] $ProductionFileCount,
268
+
269
+ [Parameter(Mandatory = $true)]
270
+ [AllowNull()]
271
+ [object] $TestFileCount,
272
+
273
+ [Parameter(Mandatory = $true)]
274
+ [AllowNull()]
275
+ [AllowEmptyString()]
276
+ [string] $ExecutionContext,
277
+
278
+ [Parameter(Mandatory = $false)]
279
+ [AllowNull()]
280
+ [object] $CrossCutting = $false,
281
+
282
+ [Parameter(Mandatory = $false)]
283
+ [AllowNull()]
284
+ [object] $RootPersona = $null
285
+ )
286
+
287
+ if ($script:VALID_EXECUTION_CONTEXTS -cnotcontains $ExecutionContext) {
288
+ throw [System.ArgumentException]::new(
289
+ "execution_context must be one of $($script:VALID_EXECUTION_CONTEXTS_PYTHON_TUPLE), found '$ExecutionContext'."
290
+ )
291
+ }
292
+ $context = $ExecutionContext
293
+ $languages = Get-CodexNormalizedLanguage -Language $Language
294
+
295
+ # Counts are validated before any routing so a malformed estimate can never
296
+ # be silently coerced into a route decision.
297
+ if (-not (Test-CodexIntegralValue -Value $ProductionFileCount)) {
298
+ throw [System.ArgumentException]::new('production_file_count must be an integer.')
299
+ }
300
+ if (-not (Test-CodexIntegralValue -Value $TestFileCount)) {
301
+ throw [System.ArgumentException]::new('test_file_count must be an integer.')
302
+ }
303
+ if (-not ($CrossCutting -is [bool])) {
304
+ throw [System.ArgumentException]::new('cross_cutting must be a boolean.')
305
+ }
306
+ $productionCount = [int]$ProductionFileCount
307
+ $testCount = [int]$TestFileCount
308
+ $isCrossCutting = [bool]$CrossCutting
309
+
310
+ # A forced root persona short-circuits all escalation logic and selects
311
+ # itself, but only from a standalone context.
312
+ if ($null -ne $RootPersona) {
313
+ if (-not ($RootPersona -is [string]) -or ($script:FORCED_ROOT_PERSONAS -cnotcontains [string]$RootPersona)) {
314
+ throw [System.ArgumentException]::new("Unsupported Codex root persona: '$RootPersona'.")
315
+ }
316
+ if ($context -cne $script:STANDALONE_CONTEXT) {
317
+ throw [System.ArgumentException]::new('A forced root persona requires standalone context.')
318
+ }
319
+ return @{
320
+ execution_context = $context
321
+ languages = $languages
322
+ production_file_count = $productionCount
323
+ test_file_count = $testCount
324
+ cross_cutting = $isCrossCutting
325
+ root_persona = [string]$RootPersona
326
+ route = 'epic'
327
+ topology = 'epic_persona'
328
+ logical_agent = [string]$RootPersona
329
+ routing_reason = 'forced_root_persona'
330
+ max_production_files = $null
331
+ max_test_files = $null
332
+ }
333
+ }
334
+
335
+ # Escalation precedence. The first matching condition wins, so the order of
336
+ # these guards is part of the contract, not an implementation detail: epic
337
+ # child work escalates before any estimate is trusted, an invalid estimate
338
+ # escalates before language analysis, and the budget checks run last because
339
+ # they require a resolved single-language budget.
340
+ $escalationArgument = @{
341
+ ExecutionContext = $context
342
+ Language = $languages
343
+ ProductionFileCount = $productionCount
344
+ TestFileCount = $testCount
345
+ CrossCutting = $isCrossCutting
346
+ }
347
+
348
+ if ($script:EPIC_CHILD_CONTEXTS -ccontains $context) {
349
+ return Get-CodexEscalationReceipt @escalationArgument -Reason 'epic_child_context'
350
+ }
351
+ if ($productionCount -le 0 -or $testCount -lt 0) {
352
+ return Get-CodexEscalationReceipt @escalationArgument -Reason 'invalid_estimate'
353
+ }
354
+ if ($languages.Count -gt 1) {
355
+ return Get-CodexEscalationReceipt @escalationArgument -Reason 'cross_language'
356
+ }
357
+ if ($languages.Count -ne 1) {
358
+ return Get-CodexEscalationReceipt @escalationArgument -Reason 'unsupported_language'
359
+ }
360
+ if (-not $script:LANGUAGE_BUDGETS.ContainsKey($languages[0])) {
361
+ return Get-CodexEscalationReceipt @escalationArgument -Reason 'unsupported_language'
362
+ }
363
+
364
+ $budget = $script:LANGUAGE_BUDGETS[$languages[0]]
365
+ if ($isCrossCutting) {
366
+ return Get-CodexEscalationReceipt @escalationArgument -Reason 'cross_cutting' -Budget $budget
367
+ }
368
+ if (-not $budget['direct_mode_enabled']) {
369
+ return Get-CodexEscalationReceipt @escalationArgument -Reason 'direct_mode_disabled' -Budget $budget
370
+ }
371
+ if ($productionCount -gt $budget['max_production_files']) {
372
+ return Get-CodexEscalationReceipt @escalationArgument -Reason 'production_budget_exceeded' -Budget $budget
373
+ }
374
+
375
+ return @{
376
+ execution_context = $context
377
+ languages = $languages
378
+ production_file_count = $productionCount
379
+ test_file_count = $testCount
380
+ cross_cutting = $isCrossCutting
381
+ root_persona = $null
382
+ route = 'small'
383
+ topology = 'typed_engineer'
384
+ logical_agent = $budget['logical_agent']
385
+ routing_reason = 'within_language_budget'
386
+ max_production_files = $budget['max_production_files']
387
+ max_test_files = $budget['max_test_files']
388
+ }
389
+ }
390
+
391
+ # The resolver and the forced-root-persona accessor are exported; the validation,
392
+ # normalization, and receipt-construction helpers stay private so no consumer can
393
+ # bypass the single entry point.
394
+ Export-ModuleMember -Function Resolve-CodexTopology, Get-CodexForcedRootPersona
@@ -42,6 +42,8 @@
42
42
  # Issue #275 remediation cycle 1 (fix #3): measure the epic-orchestrate hook set and
43
43
  # its dot-sourced sibling module so no production hook is excluded from coverage.
44
44
  '.claude/hooks/enforce-epic-merge-gate.ps1'
45
+ # Issue #670: CodeCoverage.Path is an explicit per-file allow-list, so the dot-sourced helpers file is listed here.
46
+ '.claude/hooks/enforce-epic-merge-gate-authorization.ps1'
45
47
  '.claude/hooks/enforce-epic-wave-barrier.ps1'
46
48
  '.claude/hooks/enforce-epic-worktree-removal-gate.ps1'
47
49
  '.claude/hooks/enforce-pr-author-skill.ps1'
@@ -105,6 +107,12 @@
105
107
  # interpreter; measured here so the new production modules are not excluded.
106
108
  '.claude/lib/codex-routing/CodexDeployment.psm1'
107
109
  '.claude/lib/codex-routing/CodexTopology.psm1'
110
+ # Issue #697 added the PowerShell routing CLI wrappers and their shared
111
+ # helper so destinations resolve routing without a Python interpreter;
112
+ # measured here so the new production scripts are not excluded.
113
+ '.codex/scripts/codex-routing-cli-common.ps1'
114
+ '.codex/scripts/Resolve-CodexDeployment.ps1'
115
+ '.codex/scripts/Resolve-CodexTopology.ps1'
108
116
  '.claude/lib/orchestrator-state/OrchestratorStateCodexModelReceipts.psm1'
109
117
  '.claude/lib/orchestrator-state/OrchestratorStateCodexTopologyReceipts.psm1'
110
118
  '.claude/lib/orchestrator-state/OrchestratorStateRoutingMatrix.psm1'
@@ -231,10 +239,16 @@
231
239
  # table and the epic and parallel readiness predicates; registered so the new
232
240
  # production file stays in the coverage denominator per the Coverage Exclusion Policy.
233
241
  '.claude/hooks/enforce-orchestration-preimplementation-gate-modes.ps1'
242
+ # Issue #663 added this dot-sourced sibling for the epic-scope command and path legs.
243
+ '.claude/hooks/enforce-orchestration-preimplementation-gate-epic-scope.ps1'
234
244
  '.claude/hooks/enforce-evidence-locations.ps1'
235
245
  '.claude/hooks/enforce-feature-folder-order.ps1'
236
246
  '.claude/hooks/enforce-checkpoint-monotonic.ps1'
237
247
  '.claude/hooks/enforce-prd-feature-before-planner.ps1'
248
+ # Issue #672 split the prd-feature gate's resolution logic into a dot-sourced
249
+ # sibling; registered so the new production file stays in the coverage
250
+ # denominator per the Coverage Exclusion Policy.
251
+ '.claude/hooks/enforce-prd-feature-before-planner-helpers.ps1'
238
252
  '.claude/hooks/enforce-parallel-cohort-barrier-helpers.ps1'
239
253
  '.claude/hooks/enforce-pr-author-skill-helpers.ps1'
240
254
  # Issue #526 added this out-of-band release-verification module (Layer B of the
@@ -280,6 +294,18 @@
280
294
  '.codex/hooks/enforce-epic-merge-gate.ps1'
281
295
  '.codex/hooks/enforce-epic-worktree-removal-gate.ps1'
282
296
  '.codex/hooks/validate-bash.ps1'
297
+ # Issue #669 added the worktree-resolution module (target-worktree locator, path
298
+ # normaliser, and four-state call-target derivation). CodeCoverage.Path is an
299
+ # explicit per-file allow-list, so an unregistered production file would sit
300
+ # outside the coverage denominator, which the Coverage Exclusion Policy forbids.
301
+ # Registered here beside the other .claude/lib modules.
302
+ '.claude/lib/worktree-resolution/WorktreeResolution.psm1'
303
+ '.claude/lib/worktree-resolution/WorktreeTargetResolution.psm1'
304
+ # Issue #673 added the identity-resolution module, registered for the same reason.
305
+ '.claude/lib/worktree-resolution/WorktreeItemResolution.psm1'
306
+ # Issue #663 added the epic-scope resolver and its pure readiness predicates.
307
+ '.claude/lib/worktree-resolution/EpicScopeResolution.psm1'
308
+ '.claude/lib/worktree-resolution/EpicScopeReadiness.psm1'
283
309
  )
284
310
  # Optional: don't fail the run on coverage percentage
285
311
  CoveragePercentTarget = 0