@danmoisan/drm-copilot-mcp 1.0.23 → 1.0.26

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 (43) hide show
  1. package/out/mcp-server.js +504 -174
  2. package/package.json +1 -1
  3. package/resources/claude-customizations/.claude/agents/feature-review.md +5 -3
  4. package/resources/claude-customizations/.claude/agents/parallel-orchestrator.md +11 -4
  5. package/resources/claude-customizations/.claude/agents/parallel-planner.md +5 -2
  6. package/resources/claude-customizations/.claude/hooks/enforce-discovery-artifact-gate.ps1 +28 -8
  7. package/resources/claude-customizations/.claude/hooks/validate-discovery-artifact-gate.ps1 +28 -8
  8. package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output.ps1 +117 -46
  9. package/resources/claude-customizations/.claude/lib/bash/parallel-manifest-validate.sh +115 -3
  10. package/resources/claude-customizations/.claude/lib/codex-routing/CodexDeployment.psm1 +312 -0
  11. package/resources/claude-customizations/.claude/lib/codex-routing/CodexTopology.psm1 +392 -0
  12. package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryValidation.psm1 +500 -0
  13. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorState.psm1 +58 -67
  14. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateCheckpointValue.psm1 +383 -0
  15. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateCodexModelReceipts.psm1 +297 -0
  16. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateCodexTopologyReceipts.psm1 +298 -0
  17. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateCompletion.psm1 +232 -43
  18. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateCompletionChecks.psm1 +416 -0
  19. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateModelReceipts.psm1 +366 -0
  20. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateReceipts.psm1 +408 -0
  21. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateRoutingContract.psm1 +428 -0
  22. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateRoutingMatrix.psm1 +377 -0
  23. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateUnconditional.psm1 +166 -0
  24. package/resources/claude-customizations/.claude/rules/general-unit-test.md +1 -1
  25. package/resources/claude-customizations/.claude/rules/parallel-orchestration.md +28 -3
  26. package/resources/claude-customizations/.claude/rules/powershell.md +1 -1
  27. package/resources/claude-customizations/.claude/rules/quality-tiers.md +3 -3
  28. package/resources/claude-customizations/.claude/skills/feature-review-workflow/SKILL.md +4 -4
  29. package/resources/claude-customizations/.claude/skills/parallel-add/SKILL.md +10 -5
  30. package/resources/claude-customizations/.claude/skills/parallel-orchestrate/SKILL.md +108 -34
  31. package/resources/claude-customizations/.claude/skills/parallel-plan/SKILL.md +71 -9
  32. package/resources/claude-customizations/.claude/skills/parallel-remove/SKILL.md +7 -3
  33. package/resources/claude-customizations/.claude/skills/powershell-qa-gate/SKILL.md +1 -1
  34. package/resources/claude-customizations/.claude-variants/csharp-legacy/rules/csharp.md +4 -4
  35. package/resources/claude-customizations/.claude-variants/csharp-legacy/skills/csharp-qa-gate/SKILL.md +5 -3
  36. package/resources/claude-customizations/config/blast-radius.json +1 -3
  37. package/resources/claude-customizations/pack-manifests/core.json +12 -0
  38. package/resources/codex-and-agents-customizations/.agents/skills/general-unit-test/SKILL.md +1 -1
  39. package/resources/codex-and-agents-customizations/.agents/skills/quality-tiers/SKILL.md +3 -3
  40. package/resources/codex-and-agents-customizations/.agents-variants/csharp-legacy/skills/csharp/SKILL.md +3 -3
  41. package/resources/codex-and-agents-customizations/.agents-variants/csharp-legacy/skills/csharp-qa-gate/SKILL.md +5 -3
  42. package/resources/codex-and-agents-customizations/.codex/config.toml +1 -1
  43. package/resources/powershell/PoshQC/settings/pester.runsettings.psd1 +21 -0
@@ -0,0 +1,366 @@
1
+ <#
2
+ .SYNOPSIS
3
+ Portable complexity-assessment and model-routing-receipt per-entry checks.
4
+
5
+ .DESCRIPTION
6
+ Destination-runtime PowerShell port of the key-gated per-entry validators the
7
+ authoritative Python validator runs in its unconditional block. The rows
8
+ ported here are the parity-inventory families U6.C (complexity_assessments,
9
+ rows U6.C1-U6.C7) and U6.M (model_routing_receipts, rows U6.M1-U6.M6),
10
+ matching the error-string templates in
11
+ `scripts/dev_tools/_orchestrator_state_complexity.py` and
12
+ `scripts/dev_tools/_orchestrator_state_model_routing.py`.
13
+
14
+ SINGLE-IMPLEMENTATION RULE. Row U6.C5 recomputes the floor by calling
15
+ `Get-ComplexityFloor` and row U6.M4 resolves the expected model by calling
16
+ `Resolve-DelegationModel`, both from `.claude/lib/model-routing/ModelRouting.psm1`.
17
+ Neither formula is re-implemented here, mirroring the Python gate's own reuse
18
+ constraint. A future change to either formula must be made in that one module.
19
+
20
+ Every function is pure: it reads no file, starts no process, and never mutates
21
+ its input. Each check returns a string array, empty when the block is valid.
22
+ #>
23
+
24
+ Set-StrictMode -Version Latest
25
+
26
+ # Import the shared checkpoint-value primitives and the two reference formulas,
27
+ # resolved relative to this module's directory so the imports travel with the
28
+ # pushed-down pack regardless of the consumer repository's working directory.
29
+ Import-Module (Join-Path -Path $PSScriptRoot -ChildPath 'OrchestratorStateCheckpointValue.psm1') -Force
30
+ $script:ModelRoutingModulePath = Join-Path -Path (Join-Path -Path $PSScriptRoot -ChildPath '..') -ChildPath (Join-Path -Path 'model-routing' -ChildPath 'ModelRouting.psm1')
31
+ Import-Module $script:ModelRoutingModulePath -Force
32
+
33
+ # The complexity-band vocabulary, ordered lowest to highest. Pinned to BAND_ORDER
34
+ # in scripts/dev_tools/compute_complexity_floor.py and to the identical ordering
35
+ # inside ModelRouting.psm1. This is the enum and its ordering only; the floor and
36
+ # model formulas themselves are never duplicated here.
37
+ $script:BAND_ORDER = @('C1', 'C2', 'C3', 'C4')
38
+
39
+ # The model tier removed from consideration under the disabled policy, the tier a
40
+ # disabled-mode fable cell clamps down to, and the policy literal itself.
41
+ $script:FABLE_MODEL = 'fable'
42
+ $script:DISABLED_CLAMP_MODEL = 'opus'
43
+ $script:DISABLED_POLICY = 'disabled'
44
+
45
+
46
+ function Get-CheckpointStringList {
47
+ <#
48
+ .SYNOPSIS
49
+ Return a value as a string list only when it has that exact shape.
50
+ .DESCRIPTION
51
+ Private helper mirroring _string_list in the Python complexity module. A
52
+ non-list value, or a list containing a non-string element, has no string
53
+ list form; an empty list does, and yields an empty result.
54
+ .PARAMETER Value
55
+ The deserialized JSON value to inspect. May be $null.
56
+ .OUTPUTS
57
+ System.Collections.Hashtable with keys Ok (bool) and Value (string[]).
58
+ #>
59
+ [CmdletBinding()]
60
+ [OutputType([hashtable])]
61
+ param(
62
+ [Parameter(Mandatory = $true)]
63
+ [AllowNull()]
64
+ [object] $Value
65
+ )
66
+
67
+ if (-not (Test-CheckpointListValue -Value $Value)) {
68
+ return @{ Ok = $false; Value = [string[]]@() }
69
+ }
70
+
71
+ # A single non-string element disqualifies the whole list, matching Python's
72
+ # all(isinstance(item, str)) guard.
73
+ foreach ($item in $Value) {
74
+ if (-not ($item -is [string])) {
75
+ return @{ Ok = $false; Value = [string[]]@() }
76
+ }
77
+ }
78
+
79
+ return @{ Ok = $true; Value = [string[]]@($Value) }
80
+ }
81
+
82
+ function Get-ComplexityAssessmentEntryError {
83
+ <#
84
+ .SYNOPSIS
85
+ Return one complexity assessment's errors (rows U6.C3-U6.C7).
86
+ .DESCRIPTION
87
+ Private helper mirroring _validate_one_assessment: band enum membership,
88
+ a recomputable signals list, floor equality against Get-ComplexityFloor,
89
+ the band-at-or-above-floor lower bound, and a non-empty rationale. The
90
+ floor is never recomputed inline; the shared formula is called.
91
+ .PARAMETER Index
92
+ The assessment's zero-based position, used for error context.
93
+ .PARAMETER Assessment
94
+ The deserialized assessment object.
95
+ .OUTPUTS
96
+ System.String[] - zero or more error strings.
97
+ #>
98
+ [CmdletBinding()]
99
+ [OutputType([string[]])]
100
+ param(
101
+ [Parameter(Mandatory = $true)]
102
+ [int] $Index,
103
+
104
+ [Parameter(Mandatory = $true)]
105
+ [psobject] $Assessment
106
+ )
107
+
108
+ $errors = [System.Collections.Generic.List[string]]::new()
109
+ $band = (Get-CheckpointObjectMember -Owner $Assessment -Name 'band').Value
110
+ $floor = (Get-CheckpointObjectMember -Owner $Assessment -Name 'floor').Value
111
+ $signalsPresent = (Get-CheckpointObjectMember -Owner $Assessment -Name 'signals_present').Value
112
+ $rationale = (Get-CheckpointObjectMember -Owner $Assessment -Name 'rationale').Value
113
+
114
+ $bandValid = ($band -is [string]) -and ($script:BAND_ORDER -ccontains [string]$band)
115
+ $floorValid = ($floor -is [string]) -and ($script:BAND_ORDER -ccontains [string]$floor)
116
+
117
+ # U6.C3: band must be within the permitted enum.
118
+ if (-not $bandValid) {
119
+ $errors.Add("Checkpoint complexity_assessments #$Index band must be one of C1, C2, C3, C4; got: $(ConvertTo-PythonDisplayText -Value $band).")
120
+ }
121
+
122
+ # U6.C4 / U6.C5: the floor can only be recomputed from a list of strings, so a
123
+ # malformed signals list reports itself and suppresses the equality check.
124
+ $signalList = Get-CheckpointStringList -Value $signalsPresent
125
+ if (-not $signalList.Ok) {
126
+ $errors.Add("Checkpoint complexity_assessments #$Index signals_present must be a list of strings.")
127
+ } else {
128
+ $expectedFloor = Get-ComplexityFloor -SignalsPresent $signalList.Value
129
+ if (-not ($floor -is [string]) -or ([string]$floor -cne [string]$expectedFloor)) {
130
+ $errors.Add("Checkpoint complexity_assessments #$Index floor $(ConvertTo-PythonDisplayText -Value $floor) does not equal compute_complexity_floor(signals_present) $expectedFloor.")
131
+ }
132
+ }
133
+
134
+ # U6.C6: the band-at-or-above-floor lower bound. Both values must be valid
135
+ # bands to compare, so a prior enum error suppresses a spurious ordering error.
136
+ if ($bandValid -and $floorValid -and
137
+ ($script:BAND_ORDER.IndexOf([string]$band) -lt $script:BAND_ORDER.IndexOf([string]$floor))) {
138
+ $errors.Add("Checkpoint complexity_assessments #$Index band $band is below its floor $floor.")
139
+ }
140
+
141
+ # U6.C7: rationale must be a non-empty string.
142
+ if (-not ($rationale -is [string]) -or [string]::IsNullOrWhiteSpace([string]$rationale)) {
143
+ $errors.Add("Checkpoint complexity_assessments #$Index rationale must be a non-empty string.")
144
+ }
145
+
146
+ return $errors.ToArray()
147
+ }
148
+
149
+ function Get-OrchestratorStateComplexityAssessmentError {
150
+ <#
151
+ .SYNOPSIS
152
+ Return the complexity_assessments errors (inventory rows U6.C1-U6.C7).
153
+ .DESCRIPTION
154
+ Public entry mirroring _validate_complexity_assessments. The caller invokes
155
+ this only when the key is present, so a non-list value is itself the error.
156
+ Each entry is validated independently so callers receive a complete list.
157
+ .PARAMETER Value
158
+ The raw deserialized value of the checkpoint's complexity_assessments key.
159
+ .OUTPUTS
160
+ System.String[] - zero or more error strings.
161
+ #>
162
+ [CmdletBinding()]
163
+ [OutputType([string[]])]
164
+ param(
165
+ [Parameter(Mandatory = $true)]
166
+ [AllowNull()]
167
+ [object] $Value
168
+ )
169
+
170
+ $errors = [System.Collections.Generic.List[string]]::new()
171
+
172
+ if (-not (Test-CheckpointListValue -Value $Value)) {
173
+ $errors.Add('Checkpoint complexity_assessments must be a list when present.')
174
+ return $errors.ToArray()
175
+ }
176
+
177
+ # Walk every entry position so each malformed assessment is reported with its
178
+ # own index rather than stopping at the first one.
179
+ $index = 0
180
+ foreach ($assessment in @($Value)) {
181
+ if (-not (Test-CheckpointObjectValue -Value $assessment)) {
182
+ $errors.Add("Checkpoint complexity_assessments #$index must be an object.")
183
+ $index++
184
+ continue
185
+ }
186
+ $errors.AddRange([string[]]@(Get-ComplexityAssessmentEntryError -Index $index -Assessment $assessment))
187
+ $index++
188
+ }
189
+
190
+ return $errors.ToArray()
191
+ }
192
+
193
+ function Get-ModelRoutingDisabledClampError {
194
+ <#
195
+ .SYNOPSIS
196
+ Return one receipt's disabled-mode clamp errors (rows U6.M5-U6.M6).
197
+ .DESCRIPTION
198
+ Private helper mirroring _validate_disabled_clamp. Under the disabled
199
+ policy fable is removed from the consideration set, so no receipt may
200
+ resolve to fable, and a fable table cell must record the clamp to opus
201
+ with clamped_from fable.
202
+ .PARAMETER Index
203
+ The receipt's zero-based position, used for error context.
204
+ .PARAMETER TableModel
205
+ The receipt's pre-clamp table_model value.
206
+ .PARAMETER ClampedFrom
207
+ The receipt's clamped_from value.
208
+ .PARAMETER Model
209
+ The receipt's post-clamp model value.
210
+ .OUTPUTS
211
+ System.String[] - zero or more error strings.
212
+ #>
213
+ [CmdletBinding()]
214
+ [OutputType([string[]])]
215
+ param(
216
+ [Parameter(Mandatory = $true)]
217
+ [int] $Index,
218
+
219
+ [Parameter(Mandatory = $true)]
220
+ [AllowNull()]
221
+ [object] $TableModel,
222
+
223
+ [Parameter(Mandatory = $true)]
224
+ [AllowNull()]
225
+ [object] $ClampedFrom,
226
+
227
+ [Parameter(Mandatory = $true)]
228
+ [AllowNull()]
229
+ [object] $Model
230
+ )
231
+
232
+ $errors = [System.Collections.Generic.List[string]]::new()
233
+
234
+ # U6.M5: no receipt model may be fable under the disabled policy.
235
+ if (($Model -is [string]) -and ([string]$Model -ceq $script:FABLE_MODEL)) {
236
+ $errors.Add("Checkpoint model_routing_receipts #$Index model must not be fable under fable_policy disabled.")
237
+ }
238
+
239
+ # U6.M6: a fable table cell must record the clamp provenance; both halves of
240
+ # the provenance (clamped_from fable and model opus) are required together.
241
+ if (($TableModel -is [string]) -and ([string]$TableModel -ceq $script:FABLE_MODEL)) {
242
+ $clampRecorded = ($ClampedFrom -is [string]) -and ([string]$ClampedFrom -ceq $script:FABLE_MODEL) -and
243
+ ($Model -is [string]) -and ([string]$Model -ceq $script:DISABLED_CLAMP_MODEL)
244
+ if (-not $clampRecorded) {
245
+ $errors.Add("Checkpoint model_routing_receipts #$Index table_model fable under fable_policy disabled must record clamped_from fable and model opus.")
246
+ }
247
+ }
248
+
249
+ return $errors.ToArray()
250
+ }
251
+
252
+ function Get-ModelRoutingReceiptEntryError {
253
+ <#
254
+ .SYNOPSIS
255
+ Return one model-routing receipt's errors (rows U6.M3-U6.M6).
256
+ .DESCRIPTION
257
+ Private helper mirroring _validate_one_receipt: the band must be a valid
258
+ enum member before the resolver can run, the recorded model must equal
259
+ Resolve-DelegationModel's result, and the disabled-mode clamp invariants
260
+ apply when the session policy removed fable. The model formula is never
261
+ re-implemented here; the shared formula is called.
262
+ .PARAMETER Index
263
+ The receipt's zero-based position, used for error context.
264
+ .PARAMETER Receipt
265
+ The deserialized receipt object.
266
+ .OUTPUTS
267
+ System.String[] - zero or more error strings.
268
+ #>
269
+ [CmdletBinding()]
270
+ [OutputType([string[]])]
271
+ param(
272
+ [Parameter(Mandatory = $true)]
273
+ [int] $Index,
274
+
275
+ [Parameter(Mandatory = $true)]
276
+ [psobject] $Receipt
277
+ )
278
+
279
+ $errors = [System.Collections.Generic.List[string]]::new()
280
+ $agent = (Get-CheckpointObjectMember -Owner $Receipt -Name 'agent').Value
281
+ $band = (Get-CheckpointObjectMember -Owner $Receipt -Name 'complexity_band').Value
282
+ $fablePolicy = (Get-CheckpointObjectMember -Owner $Receipt -Name 'fable_policy').Value
283
+ $tableModel = (Get-CheckpointObjectMember -Owner $Receipt -Name 'table_model').Value
284
+ $clampedFrom = (Get-CheckpointObjectMember -Owner $Receipt -Name 'clamped_from').Value
285
+ $model = (Get-CheckpointObjectMember -Owner $Receipt -Name 'model').Value
286
+
287
+ # U6.M3: an invalid band cannot be resolved, so report it and stop this
288
+ # receipt rather than calling the resolver with an out-of-table key.
289
+ if (-not ($band -is [string]) -or -not ($script:BAND_ORDER -ccontains [string]$band)) {
290
+ $errors.Add("Checkpoint model_routing_receipts #$Index complexity_band must be one of C1, C2, C3, C4; got: $(ConvertTo-PythonDisplayText -Value $band).")
291
+ return $errors.ToArray()
292
+ }
293
+
294
+ # U6.M4: resolve the expected model from the canonical shared formula. Agent
295
+ # and policy are rendered through the Python str() renderer because the Python
296
+ # reference coerces both with str() before the lookup.
297
+ $expected = Resolve-DelegationModel `
298
+ -Agent (ConvertTo-PythonDisplayText -Value $agent) `
299
+ -Band ([string]$band) `
300
+ -FablePolicy (ConvertTo-PythonDisplayText -Value $fablePolicy)
301
+ $expectedModel = [string]$expected['model']
302
+ if (-not ($model -is [string]) -or ([string]$model -cne $expectedModel)) {
303
+ $errors.Add("Checkpoint model_routing_receipts #$Index model $(ConvertTo-PythonDisplayText -Value $model) does not equal resolve_delegation_model(agent, complexity_band, fable_policy) $expectedModel.")
304
+ }
305
+
306
+ # The clamp invariants apply only when fable is removed from the consideration
307
+ # set for this session.
308
+ if (($fablePolicy -is [string]) -and ([string]$fablePolicy -ceq $script:DISABLED_POLICY)) {
309
+ $errors.AddRange([string[]]@(
310
+ Get-ModelRoutingDisabledClampError -Index $Index -TableModel $tableModel -ClampedFrom $clampedFrom -Model $model
311
+ ))
312
+ }
313
+
314
+ return $errors.ToArray()
315
+ }
316
+
317
+ function Get-OrchestratorStateModelRoutingReceiptError {
318
+ <#
319
+ .SYNOPSIS
320
+ Return the model_routing_receipts errors (inventory rows U6.M1-U6.M6).
321
+ .DESCRIPTION
322
+ Public entry mirroring _validate_model_routing_receipts. The caller invokes
323
+ this only when the key is present, so a non-list value is itself the error.
324
+ Each receipt is validated independently so callers receive a complete list.
325
+ .PARAMETER Value
326
+ The raw deserialized value of the checkpoint's model_routing_receipts key.
327
+ .OUTPUTS
328
+ System.String[] - zero or more error strings.
329
+ #>
330
+ [CmdletBinding()]
331
+ [OutputType([string[]])]
332
+ param(
333
+ [Parameter(Mandatory = $true)]
334
+ [AllowNull()]
335
+ [object] $Value
336
+ )
337
+
338
+ $errors = [System.Collections.Generic.List[string]]::new()
339
+
340
+ if (-not (Test-CheckpointListValue -Value $Value)) {
341
+ $errors.Add('Checkpoint model_routing_receipts must be a list when present.')
342
+ return $errors.ToArray()
343
+ }
344
+
345
+ # Walk every receipt position so each malformed entry is reported with its own
346
+ # index rather than stopping at the first one.
347
+ $index = 0
348
+ foreach ($receipt in @($Value)) {
349
+ if (-not (Test-CheckpointObjectValue -Value $receipt)) {
350
+ $errors.Add("Checkpoint model_routing_receipts #$index must be an object.")
351
+ $index++
352
+ continue
353
+ }
354
+ $errors.AddRange([string[]]@(Get-ModelRoutingReceiptEntryError -Index $index -Receipt $receipt))
355
+ $index++
356
+ }
357
+
358
+ return $errors.ToArray()
359
+ }
360
+
361
+ # Both family entry points are exported for the U-family aggregator and for the
362
+ # completion gate's M3 reuse leg, which invokes this same implementation rather
363
+ # than re-implementing the per-entry rows.
364
+ Export-ModuleMember -Function `
365
+ Get-OrchestratorStateComplexityAssessmentError, `
366
+ Get-OrchestratorStateModelRoutingReceiptError