@danmoisan/drm-copilot-mcp 1.0.24 → 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.
- package/out/mcp-server.js +504 -174
- package/package.json +1 -1
- package/resources/claude-customizations/.claude/agents/feature-review.md +5 -3
- package/resources/claude-customizations/.claude/agents/parallel-orchestrator.md +11 -4
- package/resources/claude-customizations/.claude/agents/parallel-planner.md +5 -2
- package/resources/claude-customizations/.claude/hooks/enforce-discovery-artifact-gate.ps1 +28 -8
- package/resources/claude-customizations/.claude/hooks/validate-discovery-artifact-gate.ps1 +28 -8
- package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output.ps1 +117 -46
- package/resources/claude-customizations/.claude/lib/bash/parallel-manifest-validate.sh +115 -3
- package/resources/claude-customizations/.claude/lib/codex-routing/CodexDeployment.psm1 +312 -0
- package/resources/claude-customizations/.claude/lib/codex-routing/CodexTopology.psm1 +392 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryValidation.psm1 +500 -0
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorState.psm1 +58 -67
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateCheckpointValue.psm1 +383 -0
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateCodexModelReceipts.psm1 +297 -0
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateCodexTopologyReceipts.psm1 +298 -0
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateCompletion.psm1 +232 -43
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateCompletionChecks.psm1 +416 -0
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateModelReceipts.psm1 +366 -0
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateReceipts.psm1 +408 -0
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateRoutingContract.psm1 +428 -0
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateRoutingMatrix.psm1 +377 -0
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateUnconditional.psm1 +166 -0
- package/resources/claude-customizations/.claude/rules/general-unit-test.md +1 -1
- package/resources/claude-customizations/.claude/rules/parallel-orchestration.md +28 -3
- package/resources/claude-customizations/.claude/rules/powershell.md +1 -1
- package/resources/claude-customizations/.claude/rules/quality-tiers.md +3 -3
- package/resources/claude-customizations/.claude/skills/feature-review-workflow/SKILL.md +4 -4
- package/resources/claude-customizations/.claude/skills/parallel-add/SKILL.md +10 -5
- package/resources/claude-customizations/.claude/skills/parallel-orchestrate/SKILL.md +108 -34
- package/resources/claude-customizations/.claude/skills/parallel-plan/SKILL.md +71 -9
- package/resources/claude-customizations/.claude/skills/parallel-remove/SKILL.md +7 -3
- package/resources/claude-customizations/.claude/skills/powershell-qa-gate/SKILL.md +1 -1
- package/resources/claude-customizations/config/blast-radius.json +1 -3
- package/resources/claude-customizations/pack-manifests/core.json +12 -0
- package/resources/codex-and-agents-customizations/.agents/skills/general-unit-test/SKILL.md +1 -1
- package/resources/codex-and-agents-customizations/.agents/skills/quality-tiers/SKILL.md +3 -3
- package/resources/codex-and-agents-customizations/.codex/config.toml +1 -1
- package/resources/powershell/PoshQC/settings/pester.runsettings.psd1 +21 -0
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
<#
|
|
2
|
+
.SYNOPSIS
|
|
3
|
+
Portable routing-contract completion checks (inventory family C6).
|
|
4
|
+
|
|
5
|
+
.DESCRIPTION
|
|
6
|
+
Destination-runtime PowerShell port of `validate_routing_contract` in
|
|
7
|
+
`scripts/dev_tools/_orchestrator_state_routing.py`, covering parity-inventory
|
|
8
|
+
rows C6.1 through C6.14:
|
|
9
|
+
|
|
10
|
+
C6.1 routing matrix carries no routes object (returns)
|
|
11
|
+
C6.2 no route selected (returns)
|
|
12
|
+
C6.3 selected route has no routing-matrix entry (returns)
|
|
13
|
+
C6.4 required_agents must match the matrix
|
|
14
|
+
C6.5 required_skills must match the matrix
|
|
15
|
+
C6.6 required_mcp_tools must match the matrix
|
|
16
|
+
C6.7 per required agent with no delegation receipt
|
|
17
|
+
C6.8 per required skill with no acknowledged receipt
|
|
18
|
+
C6.9 per required MCP tool with no successful receipt
|
|
19
|
+
C6.10 local_execution_overrides empty-list rules (two message variants)
|
|
20
|
+
C6.11 delegation_bypasses empty-list rules (two message variants)
|
|
21
|
+
C6.12 lifecycle_operations must be a list when present
|
|
22
|
+
C6.13 per non-object lifecycle operation
|
|
23
|
+
C6.14 per lifecycle operation that did not use the MCP surface
|
|
24
|
+
|
|
25
|
+
The routing matrix is read from `OrchestratorStateRoutingMatrix.psm1`, which
|
|
26
|
+
implements deviation PD-1: the constants are pinned and no disk read occurs at
|
|
27
|
+
validation time. The optional -RoutingMatrix override mirrors the Python
|
|
28
|
+
`routing_matrix` keyword and is what makes row C6.1 reachable.
|
|
29
|
+
|
|
30
|
+
Bug-promotion tool substitution (C6.6 and C6.9). The routing matrix records
|
|
31
|
+
the feature-type promotion-entry tool `new_potential_entry` in every route's
|
|
32
|
+
`required_mcp_tools`. A bug-type promotion genuinely exercises
|
|
33
|
+
`new_potential_bug_entry` instead, so a bug-type checkpoint could never
|
|
34
|
+
truthfully record a `new_potential_entry` receipt. When, and only when, the
|
|
35
|
+
checkpoint's hyphenated `promotion-type` is exactly `"bug"`, each occurrence
|
|
36
|
+
is substituted, preserving matrix order and every other tool. The substituted
|
|
37
|
+
list drives both the exact-match check and the receipt-presence loop, so the
|
|
38
|
+
two never disagree.
|
|
39
|
+
|
|
40
|
+
Empty-list semantics (C6.10 and C6.11). The Python rule requires the key to
|
|
41
|
+
EXIST as a list: an ABSENT key is not a list and therefore produces the
|
|
42
|
+
"must be an empty list at completion" variant. That is deliberately stricter
|
|
43
|
+
than the PR-creation-readiness analogue in `OrchestratorState.psm1`, which
|
|
44
|
+
tolerates absence; both behaviours are preserved as-is.
|
|
45
|
+
|
|
46
|
+
Every function is pure: it reads no file, starts no process, and never mutates
|
|
47
|
+
its input.
|
|
48
|
+
#>
|
|
49
|
+
|
|
50
|
+
Set-StrictMode -Version Latest
|
|
51
|
+
|
|
52
|
+
# Import the shared checkpoint-value primitives and the pinned routing matrix,
|
|
53
|
+
# resolved relative to this module's directory so both imports travel with the
|
|
54
|
+
# pushed-down pack regardless of the working directory.
|
|
55
|
+
Import-Module (Join-Path -Path $PSScriptRoot -ChildPath 'OrchestratorStateCheckpointValue.psm1') -Force
|
|
56
|
+
Import-Module (Join-Path -Path $PSScriptRoot -ChildPath 'OrchestratorStateRoutingMatrix.psm1') -Force
|
|
57
|
+
|
|
58
|
+
# The promotion-entry MCP tools and the promotion type that triggers substitution.
|
|
59
|
+
$script:FEATURE_PROMOTION_ENTRY_TOOL = 'new_potential_entry'
|
|
60
|
+
$script:BUG_PROMOTION_ENTRY_TOOL = 'new_potential_bug_entry'
|
|
61
|
+
$script:BUG_PROMOTION_TYPE = 'bug'
|
|
62
|
+
$script:PROMOTION_TYPE_KEY = 'promotion-type'
|
|
63
|
+
|
|
64
|
+
# The two checkpoint fields that must exist as empty lists at completion.
|
|
65
|
+
$script:COMPLETION_EMPTY_LIST_KEYS = @('local_execution_overrides', 'delegation_bypasses')
|
|
66
|
+
|
|
67
|
+
# The lifecycle-operation surface every recorded operation must have used.
|
|
68
|
+
$script:LIFECYCLE_MCP_SURFACE = 'mcp'
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
function Get-CheckpointNonBlankStringList {
|
|
72
|
+
<#
|
|
73
|
+
.SYNOPSIS
|
|
74
|
+
Return a value as a list of non-blank strings, or $null when malformed.
|
|
75
|
+
.DESCRIPTION
|
|
76
|
+
Private helper mirroring the `_string_list` variant used by the routing
|
|
77
|
+
contract, which requires every member to be a non-blank string. A non-list
|
|
78
|
+
value, or any blank or non-string member, disqualifies the whole value.
|
|
79
|
+
.PARAMETER Value
|
|
80
|
+
The deserialized JSON value to inspect. May be $null.
|
|
81
|
+
.OUTPUTS
|
|
82
|
+
System.Collections.Hashtable with keys Ok (bool) and Value (string[]).
|
|
83
|
+
#>
|
|
84
|
+
[CmdletBinding()]
|
|
85
|
+
[OutputType([hashtable])]
|
|
86
|
+
param(
|
|
87
|
+
[Parameter(Mandatory = $true)]
|
|
88
|
+
[AllowNull()]
|
|
89
|
+
[object] $Value
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
if (-not (Test-CheckpointListValue -Value $Value)) {
|
|
93
|
+
return @{ Ok = $false; Value = [string[]]@() }
|
|
94
|
+
}
|
|
95
|
+
foreach ($item in @($Value)) {
|
|
96
|
+
if (-not ($item -is [string]) -or [string]::IsNullOrWhiteSpace([string]$item)) {
|
|
97
|
+
return @{ Ok = $false; Value = [string[]]@() }
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return @{ Ok = $true; Value = [string[]]@($Value) }
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function Get-ResolvedRequiredMcpTool {
|
|
104
|
+
<#
|
|
105
|
+
.SYNOPSIS
|
|
106
|
+
Resolve the promotion-entry MCP tool to the checkpoint's promotion type.
|
|
107
|
+
.DESCRIPTION
|
|
108
|
+
Private helper mirroring _resolve_promotion_entry_tools. Only an explicit
|
|
109
|
+
bug-type promotion swaps the promotion-entry tool; a feature type, an
|
|
110
|
+
absent key, a non-string value, and any other value leave the matrix list
|
|
111
|
+
untouched, so feature-type and legacy checkpoints validate exactly as
|
|
112
|
+
before. Matrix order is preserved.
|
|
113
|
+
.PARAMETER RequiredMcpTool
|
|
114
|
+
The route's declared required_mcp_tools list, in matrix order.
|
|
115
|
+
.PARAMETER State
|
|
116
|
+
The parsed checkpoint object, read for its hyphenated promotion-type key.
|
|
117
|
+
.OUTPUTS
|
|
118
|
+
System.String[] - the resolved tool list, in matrix order.
|
|
119
|
+
#>
|
|
120
|
+
[CmdletBinding()]
|
|
121
|
+
[OutputType([string[]])]
|
|
122
|
+
param(
|
|
123
|
+
[Parameter(Mandatory = $true)]
|
|
124
|
+
[AllowEmptyCollection()]
|
|
125
|
+
[string[]] $RequiredMcpTool,
|
|
126
|
+
|
|
127
|
+
[Parameter(Mandatory = $true)]
|
|
128
|
+
[psobject] $State
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
$promotionType = (Get-CheckpointObjectMember -Owner $State -Name $script:PROMOTION_TYPE_KEY).Value
|
|
132
|
+
if (-not (Test-PythonValueEqual -Actual $promotionType -Expected $script:BUG_PROMOTION_TYPE)) {
|
|
133
|
+
return [string[]]@($RequiredMcpTool)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
# Substitute the bug-type promotion-entry tool for the feature-type one while
|
|
137
|
+
# preserving matrix order and every other required tool exactly.
|
|
138
|
+
$resolved = foreach ($tool in $RequiredMcpTool) {
|
|
139
|
+
if ($tool -ceq $script:FEATURE_PROMOTION_ENTRY_TOOL) { $script:BUG_PROMOTION_ENTRY_TOOL } else { $tool }
|
|
140
|
+
}
|
|
141
|
+
return [string[]]@($resolved)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function Get-CheckpointReceiptAgentName {
|
|
145
|
+
<#
|
|
146
|
+
.SYNOPSIS
|
|
147
|
+
Collect the agent names recorded by delegation receipts.
|
|
148
|
+
.DESCRIPTION
|
|
149
|
+
Private harvest mirroring _receipt_agents plus _list_receipts. The object
|
|
150
|
+
form of delegation_receipts contributes through its `agents` namespace;
|
|
151
|
+
any other non-list value contributes nothing. Only a non-blank string
|
|
152
|
+
agent_name counts.
|
|
153
|
+
.PARAMETER State
|
|
154
|
+
The parsed checkpoint object.
|
|
155
|
+
.OUTPUTS
|
|
156
|
+
System.String[] - the recorded agent names.
|
|
157
|
+
#>
|
|
158
|
+
[CmdletBinding()]
|
|
159
|
+
[OutputType([string[]])]
|
|
160
|
+
param(
|
|
161
|
+
[Parameter(Mandatory = $true)]
|
|
162
|
+
[psobject] $State
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
$receipts = (Get-CheckpointObjectMember -Owner $State -Name 'delegation_receipts').Value
|
|
166
|
+
if (Test-CheckpointObjectValue -Value $receipts) {
|
|
167
|
+
$receipts = (Get-CheckpointObjectMember -Owner $receipts -Name 'agents').Value
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
$agents = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::Ordinal)
|
|
171
|
+
if (-not (Test-CheckpointListValue -Value $receipts)) { return [string[]]@($agents) }
|
|
172
|
+
|
|
173
|
+
# Harvest each well-formed receipt's agent name; a malformed entry is skipped
|
|
174
|
+
# rather than reported, because shape errors belong to the U5 family.
|
|
175
|
+
foreach ($receipt in @($receipts)) {
|
|
176
|
+
if (-not (Test-CheckpointObjectValue -Value $receipt)) { continue }
|
|
177
|
+
$name = (Get-CheckpointObjectMember -Owner $receipt -Name 'agent_name').Value
|
|
178
|
+
if (($name -is [string]) -and -not [string]::IsNullOrWhiteSpace([string]$name)) {
|
|
179
|
+
[void]$agents.Add([string]$name)
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return [string[]]@($agents)
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function Get-CheckpointAcknowledgedName {
|
|
186
|
+
<#
|
|
187
|
+
.SYNOPSIS
|
|
188
|
+
Collect acknowledged names from a receipt array with an evidence rule.
|
|
189
|
+
.DESCRIPTION
|
|
190
|
+
Private harvest shared by _receipt_skills and _mcp_tools, which differ
|
|
191
|
+
only in the array key, the name key, and the boolean flag key. A receipt
|
|
192
|
+
counts only when its name is a non-blank string, its flag is exactly the
|
|
193
|
+
boolean true, and its evidence is a non-blank string. Truthy-but-not-true
|
|
194
|
+
flags deliberately do not count.
|
|
195
|
+
.PARAMETER State
|
|
196
|
+
The parsed checkpoint object.
|
|
197
|
+
.PARAMETER ArrayKey
|
|
198
|
+
The checkpoint key holding the receipt array.
|
|
199
|
+
.PARAMETER NameKey
|
|
200
|
+
The per-receipt key holding the acknowledged name.
|
|
201
|
+
.PARAMETER FlagKey
|
|
202
|
+
The per-receipt key that must be exactly boolean true.
|
|
203
|
+
.OUTPUTS
|
|
204
|
+
System.String[] - the acknowledged names.
|
|
205
|
+
#>
|
|
206
|
+
[CmdletBinding()]
|
|
207
|
+
[OutputType([string[]])]
|
|
208
|
+
param(
|
|
209
|
+
[Parameter(Mandatory = $true)]
|
|
210
|
+
[psobject] $State,
|
|
211
|
+
|
|
212
|
+
[Parameter(Mandatory = $true)]
|
|
213
|
+
[string] $ArrayKey,
|
|
214
|
+
|
|
215
|
+
[Parameter(Mandatory = $true)]
|
|
216
|
+
[string] $NameKey,
|
|
217
|
+
|
|
218
|
+
[Parameter(Mandatory = $true)]
|
|
219
|
+
[string] $FlagKey
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
$names = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::Ordinal)
|
|
223
|
+
$receipts = (Get-CheckpointObjectMember -Owner $State -Name $ArrayKey).Value
|
|
224
|
+
if (-not (Test-CheckpointListValue -Value $receipts)) { return [string[]]@($names) }
|
|
225
|
+
|
|
226
|
+
# All three conditions must hold together: an acknowledged name, an explicit
|
|
227
|
+
# true flag, and non-blank evidence. A receipt failing any one contributes
|
|
228
|
+
# nothing, so the requirement it would have satisfied is reported missing.
|
|
229
|
+
foreach ($receipt in @($receipts)) {
|
|
230
|
+
if (-not (Test-CheckpointObjectValue -Value $receipt)) { continue }
|
|
231
|
+
$name = (Get-CheckpointObjectMember -Owner $receipt -Name $NameKey).Value
|
|
232
|
+
$flag = (Get-CheckpointObjectMember -Owner $receipt -Name $FlagKey).Value
|
|
233
|
+
$evidence = (Get-CheckpointObjectMember -Owner $receipt -Name 'evidence').Value
|
|
234
|
+
if (($name -is [string]) -and -not [string]::IsNullOrWhiteSpace([string]$name) -and
|
|
235
|
+
($flag -is [bool]) -and [bool]$flag -and
|
|
236
|
+
($evidence -is [string]) -and -not [string]::IsNullOrWhiteSpace([string]$evidence)) {
|
|
237
|
+
[void]$names.Add([string]$name)
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return [string[]]@($names)
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function Get-CompletionEmptyListError {
|
|
244
|
+
<#
|
|
245
|
+
.SYNOPSIS
|
|
246
|
+
Return the empty-list-at-completion errors for one key (rows C6.10/C6.11).
|
|
247
|
+
.DESCRIPTION
|
|
248
|
+
Private helper mirroring _validate_empty_list_field. The key must EXIST as
|
|
249
|
+
a list: an absent key, a null value, and any non-list value all produce the
|
|
250
|
+
"must be an empty list at completion" variant, while a present non-empty
|
|
251
|
+
list produces the "must be empty at completion" variant.
|
|
252
|
+
.PARAMETER State
|
|
253
|
+
The parsed checkpoint object.
|
|
254
|
+
.PARAMETER Key
|
|
255
|
+
The checkpoint key to check.
|
|
256
|
+
.OUTPUTS
|
|
257
|
+
System.String[] - zero or one error string.
|
|
258
|
+
#>
|
|
259
|
+
[CmdletBinding()]
|
|
260
|
+
[OutputType([string[]])]
|
|
261
|
+
param(
|
|
262
|
+
[Parameter(Mandatory = $true)]
|
|
263
|
+
[psobject] $State,
|
|
264
|
+
|
|
265
|
+
[Parameter(Mandatory = $true)]
|
|
266
|
+
[string] $Key
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
$value = (Get-CheckpointObjectMember -Owner $State -Name $Key).Value
|
|
270
|
+
if (-not (Test-CheckpointListValue -Value $value)) {
|
|
271
|
+
return [string[]]@("Checkpoint $Key must be an empty list at completion.")
|
|
272
|
+
}
|
|
273
|
+
if (@($value).Count -gt 0) {
|
|
274
|
+
return [string[]]@("Checkpoint $Key must be empty at completion.")
|
|
275
|
+
}
|
|
276
|
+
return [string[]]@()
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function Get-LifecycleOperationError {
|
|
280
|
+
<#
|
|
281
|
+
.SYNOPSIS
|
|
282
|
+
Return the lifecycle-operation errors (rows C6.12-C6.14).
|
|
283
|
+
.DESCRIPTION
|
|
284
|
+
Private helper mirroring _validate_lifecycle_operations. The key is
|
|
285
|
+
optional: an absent or null value contributes nothing. A present non-list
|
|
286
|
+
value is malformed, and each recorded operation must be an object whose
|
|
287
|
+
surface is exactly the MCP surface.
|
|
288
|
+
.PARAMETER State
|
|
289
|
+
The parsed checkpoint object.
|
|
290
|
+
.OUTPUTS
|
|
291
|
+
System.String[] - zero or more error strings.
|
|
292
|
+
#>
|
|
293
|
+
[CmdletBinding()]
|
|
294
|
+
[OutputType([string[]])]
|
|
295
|
+
param(
|
|
296
|
+
[Parameter(Mandatory = $true)]
|
|
297
|
+
[psobject] $State
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
$errors = [System.Collections.Generic.List[string]]::new()
|
|
301
|
+
|
|
302
|
+
$operations = (Get-CheckpointObjectMember -Owner $State -Name 'lifecycle_operations').Value
|
|
303
|
+
if ($null -eq $operations) { return $errors.ToArray() }
|
|
304
|
+
if (-not (Test-CheckpointListValue -Value $operations)) {
|
|
305
|
+
$errors.Add('Checkpoint lifecycle_operations must be a list when present.')
|
|
306
|
+
return $errors.ToArray()
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
# Report each malformed or non-MCP operation with its own index.
|
|
310
|
+
$index = 0
|
|
311
|
+
foreach ($operation in @($operations)) {
|
|
312
|
+
if (-not (Test-CheckpointObjectValue -Value $operation)) {
|
|
313
|
+
$errors.Add("Checkpoint lifecycle_operations #$index must be an object.")
|
|
314
|
+
$index++
|
|
315
|
+
continue
|
|
316
|
+
}
|
|
317
|
+
$surface = (Get-CheckpointObjectMember -Owner $operation -Name 'surface').Value
|
|
318
|
+
if (-not (Test-PythonValueEqual -Actual $surface -Expected $script:LIFECYCLE_MCP_SURFACE)) {
|
|
319
|
+
$errors.Add("Checkpoint lifecycle_operations #$index did not use MCP surface.")
|
|
320
|
+
}
|
|
321
|
+
$index++
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
return $errors.ToArray()
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
function Get-OrchestratorStateRoutingContractError {
|
|
328
|
+
<#
|
|
329
|
+
.SYNOPSIS
|
|
330
|
+
Return the routing-contract errors (inventory rows C6.1-C6.14).
|
|
331
|
+
.DESCRIPTION
|
|
332
|
+
Public entry mirroring validate_routing_contract. The first three rows are
|
|
333
|
+
terminal: a malformed matrix, an unselected route, and an unknown route
|
|
334
|
+
each return a single error, because none of the later checks can be
|
|
335
|
+
evaluated without a resolved route entry. The remaining rows accumulate.
|
|
336
|
+
.PARAMETER State
|
|
337
|
+
The parsed checkpoint object.
|
|
338
|
+
.PARAMETER RoutingMatrix
|
|
339
|
+
Optional matrix override. When omitted, the pinned matrix is used. A
|
|
340
|
+
matrix carrying no routes mapping is what makes row C6.1 reachable.
|
|
341
|
+
.OUTPUTS
|
|
342
|
+
System.String[] - zero or more error strings.
|
|
343
|
+
#>
|
|
344
|
+
[CmdletBinding()]
|
|
345
|
+
[OutputType([string[]])]
|
|
346
|
+
param(
|
|
347
|
+
[Parameter(Mandatory = $true)]
|
|
348
|
+
[psobject] $State,
|
|
349
|
+
|
|
350
|
+
[Parameter(Mandatory = $false)]
|
|
351
|
+
[AllowNull()]
|
|
352
|
+
[hashtable] $RoutingMatrix = $null
|
|
353
|
+
)
|
|
354
|
+
|
|
355
|
+
$errors = [System.Collections.Generic.List[string]]::new()
|
|
356
|
+
|
|
357
|
+
# C6.1: a matrix with no routes mapping cannot resolve any route.
|
|
358
|
+
$routes = Get-OrchestratorStateRoutingMatrixRouteMap -RoutingMatrix $RoutingMatrix
|
|
359
|
+
if ($null -eq $routes) {
|
|
360
|
+
return [string[]]@('Routing matrix missing routes object.')
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
# C6.2: the checkpoint must name a route as a non-blank string.
|
|
364
|
+
$routeId = Get-OrchestratorStateSelectedRouteId -State $State
|
|
365
|
+
if ($null -eq $routeId) {
|
|
366
|
+
return [string[]]@('Checkpoint route_id or path_selected must select a route.')
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
# C6.3: the named route must exist in the matrix.
|
|
370
|
+
$route = Get-OrchestratorStateRoute -RouteId $routeId -RoutingMatrix $RoutingMatrix
|
|
371
|
+
if ($null -eq $route) {
|
|
372
|
+
return [string[]]@("Checkpoint selected route has no routing-matrix entry: $routeId.")
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
$requiredAgents = @(Get-OrchestratorStateRouteRequiredList -RouteId $routeId -ListName 'required_agents' -RoutingMatrix $RoutingMatrix)
|
|
376
|
+
$requiredSkills = @(Get-OrchestratorStateRouteRequiredList -RouteId $routeId -ListName 'required_skills' -RoutingMatrix $RoutingMatrix)
|
|
377
|
+
$requiredMcpTools = @(Get-ResolvedRequiredMcpTool -State $State `
|
|
378
|
+
-RequiredMcpTool ([string[]]@(Get-OrchestratorStateRouteRequiredList -RouteId $routeId -ListName 'required_mcp_tools' -RoutingMatrix $RoutingMatrix)))
|
|
379
|
+
|
|
380
|
+
# C6.4 to C6.6: the checkpoint's own declared lists must equal the matrix
|
|
381
|
+
# lists exactly, in order. A malformed list is a mismatch, not a shape error.
|
|
382
|
+
$declaredLists = @(
|
|
383
|
+
@{ Key = 'required_agents'; Expected = $requiredAgents },
|
|
384
|
+
@{ Key = 'required_skills'; Expected = $requiredSkills },
|
|
385
|
+
@{ Key = 'required_mcp_tools'; Expected = $requiredMcpTools }
|
|
386
|
+
)
|
|
387
|
+
foreach ($declared in $declaredLists) {
|
|
388
|
+
$actual = Get-CheckpointNonBlankStringList -Value (Get-CheckpointObjectMember -Owner $State -Name $declared.Key).Value
|
|
389
|
+
if (-not $actual.Ok -or -not (Test-PythonValueEqual -Actual $actual.Value -Expected ([string[]]$declared.Expected))) {
|
|
390
|
+
$errors.Add("Checkpoint $($declared.Key) must match routing matrix for route $routeId.")
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
# C6.7 to C6.9: every required agent, skill, and MCP tool must be evidenced by
|
|
395
|
+
# a receipt, in matrix order so the report is deterministic.
|
|
396
|
+
$actualAgents = @(Get-CheckpointReceiptAgentName -State $State)
|
|
397
|
+
foreach ($agent in $requiredAgents) {
|
|
398
|
+
if ($actualAgents -cnotcontains $agent) {
|
|
399
|
+
$errors.Add("Checkpoint missing required agent receipt: $agent.")
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
$actualSkills = @(Get-CheckpointAcknowledgedName -State $State -ArrayKey 'skill_receipts' -NameKey 'skill' -FlagKey 'required')
|
|
404
|
+
foreach ($skill in $requiredSkills) {
|
|
405
|
+
if ($actualSkills -cnotcontains $skill) {
|
|
406
|
+
$errors.Add("Checkpoint missing required skill receipt: $skill.")
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
$actualTools = @(Get-CheckpointAcknowledgedName -State $State -ArrayKey 'mcp_call_receipts' -NameKey 'tool' -FlagKey 'ok')
|
|
411
|
+
foreach ($tool in $requiredMcpTools) {
|
|
412
|
+
if ($actualTools -cnotcontains $tool) {
|
|
413
|
+
$errors.Add("Checkpoint missing successful MCP receipt: $tool.")
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
# C6.10 to C6.14: the two empty-list fields and the lifecycle operations.
|
|
418
|
+
foreach ($key in $script:COMPLETION_EMPTY_LIST_KEYS) {
|
|
419
|
+
$errors.AddRange([string[]]@(Get-CompletionEmptyListError -State $State -Key $key))
|
|
420
|
+
}
|
|
421
|
+
$errors.AddRange([string[]]@(Get-LifecycleOperationError -State $State))
|
|
422
|
+
|
|
423
|
+
return $errors.ToArray()
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
# Only the family entry point is exported; the harvest and field helpers stay
|
|
427
|
+
# private so no consumer can evaluate a subset of the contract.
|
|
428
|
+
Export-ModuleMember -Function Get-OrchestratorStateRoutingContractError
|