@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.
- 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/.claude-variants/csharp-legacy/rules/csharp.md +4 -4
- package/resources/claude-customizations/.claude-variants/csharp-legacy/skills/csharp-qa-gate/SKILL.md +5 -3
- 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/.agents-variants/csharp-legacy/skills/csharp/SKILL.md +3 -3
- package/resources/codex-and-agents-customizations/.agents-variants/csharp-legacy/skills/csharp-qa-gate/SKILL.md +5 -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,312 @@
|
|
|
1
|
+
<#
|
|
2
|
+
.SYNOPSIS
|
|
3
|
+
Codex deployment resolver, ported from the Python reference implementation.
|
|
4
|
+
|
|
5
|
+
.DESCRIPTION
|
|
6
|
+
Destination-runtime PowerShell port of
|
|
7
|
+
`scripts/dev_tools/resolve_codex_deployment.py`. It resolves the exact Codex
|
|
8
|
+
deployment agent, model, and reasoning effort for one delegation from the
|
|
9
|
+
logical agent, the assessed complexity band, the execution context, and the
|
|
10
|
+
orchestration complexity ceiling. C3 defaults to Terra/high and elevates to
|
|
11
|
+
Sol/high only for an epic child or a C4 orchestration ceiling; the epic
|
|
12
|
+
planner and epic orchestrator personas are always forced to Sol/ultra. No
|
|
13
|
+
model alias and no silent fallback is accepted.
|
|
14
|
+
|
|
15
|
+
SINGLE-IMPLEMENTATION RULE. The orchestrator-state U6.X checks
|
|
16
|
+
(`OrchestratorStateCodexModelReceipts.psm1`) MUST call `Resolve-CodexDeployment`
|
|
17
|
+
from this module. They must never re-implement the profile table, the C3
|
|
18
|
+
overlay rule, or the forced-persona rule. This module is the one PowerShell
|
|
19
|
+
implementation of the Codex deployment axis.
|
|
20
|
+
|
|
21
|
+
Every constant below is pinned to `config/orchestration-routing.json`
|
|
22
|
+
(`codex_model_policy`) by a static config-parity check in the Python
|
|
23
|
+
reference. Following the `ModelRouting.psm1` pattern, the values are hard-coded
|
|
24
|
+
here and never read from disk, because this module is pushed down to consumer
|
|
25
|
+
repositories that do not receive `config/orchestration-routing.json`.
|
|
26
|
+
|
|
27
|
+
Error surface, relied on by the U6.X receipt checks:
|
|
28
|
+
- [System.ArgumentException] is the ValueError-equivalent surface. Its
|
|
29
|
+
Message text reproduces the Python message verbatim, including Python
|
|
30
|
+
tuple and repr() rendering, because inventory row U6.X5 interpolates the
|
|
31
|
+
exception text into its error string.
|
|
32
|
+
- [System.InvalidOperationException] is the ModelUnavailableError-equivalent
|
|
33
|
+
surface. The Python receipt validator catches only ValueError, so this
|
|
34
|
+
exception deliberately does NOT satisfy the U6.X5 branch; it can only be
|
|
35
|
+
raised when a caller supplies an availability set, which the checks never do.
|
|
36
|
+
|
|
37
|
+
The function is pure: it reads no file, starts no process, and never mutates
|
|
38
|
+
its input.
|
|
39
|
+
#>
|
|
40
|
+
|
|
41
|
+
Set-StrictMode -Version Latest
|
|
42
|
+
|
|
43
|
+
# The complexity-band vocabulary, ordered lowest to highest. Pinned to BAND_ORDER
|
|
44
|
+
# in scripts/dev_tools/compute_complexity_floor.py.
|
|
45
|
+
$script:BAND_ORDER = @('C1', 'C2', 'C3', 'C4')
|
|
46
|
+
|
|
47
|
+
# Rendered form of the Python BAND_ORDER tuple, used verbatim inside the
|
|
48
|
+
# ValueError-equivalent message so the ported text matches character for character.
|
|
49
|
+
$script:BAND_ORDER_PYTHON_TUPLE = "('C1', 'C2', 'C3', 'C4')"
|
|
50
|
+
|
|
51
|
+
# The three permitted execution contexts, and the sorted tuple rendering the
|
|
52
|
+
# Python message interpolates.
|
|
53
|
+
$script:VALID_EXECUTION_CONTEXTS = @('standalone', 'epic_preparation_child', 'epic_execution_child')
|
|
54
|
+
$script:VALID_EXECUTION_CONTEXTS_PYTHON_TUPLE = "('epic_execution_child', 'epic_preparation_child', 'standalone')"
|
|
55
|
+
|
|
56
|
+
# The execution contexts that elevate a C3 delegation, and the ceiling band that
|
|
57
|
+
# does so independently of context.
|
|
58
|
+
$script:C3_ELEVATED_EXECUTION_CONTEXTS = @('epic_preparation_child', 'epic_execution_child')
|
|
59
|
+
$script:C3_ELEVATED_CEILING = 'C4'
|
|
60
|
+
$script:C3_BAND = 'C3'
|
|
61
|
+
|
|
62
|
+
# The agent families for which a generated per-band deployment agent exists, and
|
|
63
|
+
# the logical-to-family alias map.
|
|
64
|
+
$script:GENERATED_AGENT_FAMILIES = @(
|
|
65
|
+
'orchestrator',
|
|
66
|
+
'atomic-planner',
|
|
67
|
+
'atomic-executor',
|
|
68
|
+
'feature-reviewer',
|
|
69
|
+
'task-researcher',
|
|
70
|
+
'prd-feature',
|
|
71
|
+
'pr-author',
|
|
72
|
+
'python-typed-engineer',
|
|
73
|
+
'powershell-typed-engineer',
|
|
74
|
+
'csharp-typed-engineer',
|
|
75
|
+
'typescript-engineer'
|
|
76
|
+
)
|
|
77
|
+
$script:LOGICAL_AGENT_ALIASES = @{ 'feature-review' = 'feature-reviewer' }
|
|
78
|
+
|
|
79
|
+
# The per-band deployment profiles (suffix, model, reasoning effort).
|
|
80
|
+
$script:BASE_PROFILES = @{
|
|
81
|
+
C1 = @{ suffix = 'c1'; model = 'gpt-5.6-luna'; model_reasoning_effort = 'low' }
|
|
82
|
+
C2 = @{ suffix = 'c2'; model = 'gpt-5.6-terra'; model_reasoning_effort = 'medium' }
|
|
83
|
+
C3 = @{ suffix = 'c3'; model = 'gpt-5.6-terra'; model_reasoning_effort = 'high' }
|
|
84
|
+
C4 = @{ suffix = 'c4'; model = 'gpt-5.6-sol'; model_reasoning_effort = 'max' }
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
# The profile a C3 delegation elevates to when the overlay applies.
|
|
88
|
+
$script:C3_ELEVATED_PROFILE = @{ suffix = 'c3-elevated'; model = 'gpt-5.6-sol'; model_reasoning_effort = 'high' }
|
|
89
|
+
|
|
90
|
+
# The personas whose profile is forced regardless of band, context, or ceiling.
|
|
91
|
+
# Their deployment agent is the logical agent itself (empty suffix).
|
|
92
|
+
$script:FORCED_PERSONA_PROFILES = @{
|
|
93
|
+
'epic-planner' = @{ suffix = ''; model = 'gpt-5.6-sol'; model_reasoning_effort = 'ultra' }
|
|
94
|
+
'epic-orchestrator' = @{ suffix = ''; model = 'gpt-5.6-sol'; model_reasoning_effort = 'ultra' }
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
function Assert-CodexBand {
|
|
99
|
+
<#
|
|
100
|
+
.SYNOPSIS
|
|
101
|
+
Return a valid complexity band or throw the field-specific ValueError text.
|
|
102
|
+
.DESCRIPTION
|
|
103
|
+
Private helper mirroring _validate_band. The thrown message reproduces the
|
|
104
|
+
Python text exactly, including the tuple rendering of BAND_ORDER and the
|
|
105
|
+
repr() rendering of the offending value, because U6.X5 interpolates it.
|
|
106
|
+
.PARAMETER Value
|
|
107
|
+
The candidate band value.
|
|
108
|
+
.PARAMETER FieldName
|
|
109
|
+
The field name to name in the message.
|
|
110
|
+
.OUTPUTS
|
|
111
|
+
System.String - the validated band.
|
|
112
|
+
#>
|
|
113
|
+
[CmdletBinding()]
|
|
114
|
+
[OutputType([string])]
|
|
115
|
+
param(
|
|
116
|
+
[Parameter(Mandatory = $true)]
|
|
117
|
+
[AllowNull()]
|
|
118
|
+
[AllowEmptyString()]
|
|
119
|
+
[string] $Value,
|
|
120
|
+
|
|
121
|
+
[Parameter(Mandatory = $true)]
|
|
122
|
+
[string] $FieldName
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
if ($script:BAND_ORDER -cnotcontains $Value) {
|
|
126
|
+
throw [System.ArgumentException]::new(
|
|
127
|
+
"$FieldName must be one of $($script:BAND_ORDER_PYTHON_TUPLE), found '$Value'."
|
|
128
|
+
)
|
|
129
|
+
}
|
|
130
|
+
return $Value
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function Assert-CodexExecutionContext {
|
|
134
|
+
<#
|
|
135
|
+
.SYNOPSIS
|
|
136
|
+
Return a valid execution context or throw the ValueError-equivalent text.
|
|
137
|
+
.DESCRIPTION
|
|
138
|
+
Private helper mirroring _validate_context, reproducing the Python message
|
|
139
|
+
including the sorted-tuple rendering of the permitted contexts.
|
|
140
|
+
.PARAMETER Value
|
|
141
|
+
The candidate execution-context value.
|
|
142
|
+
.OUTPUTS
|
|
143
|
+
System.String - the validated execution context.
|
|
144
|
+
#>
|
|
145
|
+
[CmdletBinding()]
|
|
146
|
+
[OutputType([string])]
|
|
147
|
+
param(
|
|
148
|
+
[Parameter(Mandatory = $true)]
|
|
149
|
+
[AllowNull()]
|
|
150
|
+
[AllowEmptyString()]
|
|
151
|
+
[string] $Value
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
if ($script:VALID_EXECUTION_CONTEXTS -cnotcontains $Value) {
|
|
155
|
+
throw [System.ArgumentException]::new(
|
|
156
|
+
"execution_context must be one of $($script:VALID_EXECUTION_CONTEXTS_PYTHON_TUPLE), found '$Value'."
|
|
157
|
+
)
|
|
158
|
+
}
|
|
159
|
+
return $Value
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function Get-CodexC3OverlayReason {
|
|
163
|
+
<#
|
|
164
|
+
.SYNOPSIS
|
|
165
|
+
Return the deterministic C3 elevation reason, or $null when none applies.
|
|
166
|
+
.DESCRIPTION
|
|
167
|
+
Private helper mirroring _select_c3_overlay_reason. Both conditions
|
|
168
|
+
together report the combined reason; the ordering matters because the
|
|
169
|
+
combined reason must win over either single reason.
|
|
170
|
+
.PARAMETER ExecutionContext
|
|
171
|
+
The validated execution context.
|
|
172
|
+
.PARAMETER OrchestrationComplexityCeiling
|
|
173
|
+
The validated orchestration ceiling band.
|
|
174
|
+
.OUTPUTS
|
|
175
|
+
System.String - the reason, or $null.
|
|
176
|
+
#>
|
|
177
|
+
[CmdletBinding()]
|
|
178
|
+
[OutputType([string])]
|
|
179
|
+
param(
|
|
180
|
+
[Parameter(Mandatory = $true)]
|
|
181
|
+
[string] $ExecutionContext,
|
|
182
|
+
|
|
183
|
+
[Parameter(Mandatory = $true)]
|
|
184
|
+
[string] $OrchestrationComplexityCeiling
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
$epicContext = $script:C3_ELEVATED_EXECUTION_CONTEXTS -ccontains $ExecutionContext
|
|
188
|
+
$c4Ceiling = ($OrchestrationComplexityCeiling -ceq $script:C3_ELEVATED_CEILING)
|
|
189
|
+
|
|
190
|
+
if ($epicContext -and $c4Ceiling) { return 'epic_context_and_c4_ceiling' }
|
|
191
|
+
if ($epicContext) { return 'epic_context' }
|
|
192
|
+
if ($c4Ceiling) { return 'c4_orchestration_ceiling' }
|
|
193
|
+
return $null
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function Resolve-CodexDeployment {
|
|
197
|
+
<#
|
|
198
|
+
.SYNOPSIS
|
|
199
|
+
Resolve the exact Codex deployment agent, model, and reasoning effort.
|
|
200
|
+
.DESCRIPTION
|
|
201
|
+
Faithful PowerShell port of resolve_codex_deployment
|
|
202
|
+
(scripts/dev_tools/resolve_codex_deployment.py). Validates both bands and
|
|
203
|
+
the execution context, rejects a ceiling below the band, then selects the
|
|
204
|
+
profile: a forced persona wins outright; otherwise a C3 delegation may
|
|
205
|
+
elevate under the overlay rule and every other band reads the base table.
|
|
206
|
+
The deployment agent name is the resolved family plus the profile suffix.
|
|
207
|
+
.PARAMETER LogicalAgent
|
|
208
|
+
The logical agent name being delegated to.
|
|
209
|
+
.PARAMETER ComplexityBand
|
|
210
|
+
The assessed complexity band, one of C1..C4.
|
|
211
|
+
.PARAMETER ExecutionContext
|
|
212
|
+
One of standalone, epic_preparation_child, epic_execution_child.
|
|
213
|
+
.PARAMETER OrchestrationComplexityCeiling
|
|
214
|
+
The orchestration ceiling band, one of C1..C4, at or above ComplexityBand.
|
|
215
|
+
.PARAMETER AvailableModel
|
|
216
|
+
Optional availability set. When supplied and the routed model is absent
|
|
217
|
+
from it, the resolver throws rather than falling back to another model.
|
|
218
|
+
.OUTPUTS
|
|
219
|
+
System.Collections.Hashtable with the nine resolved keys: logical_agent,
|
|
220
|
+
deployment_agent, complexity_band, execution_context,
|
|
221
|
+
orchestration_complexity_ceiling, c3_overlay_applied, c3_overlay_reason,
|
|
222
|
+
model, model_reasoning_effort.
|
|
223
|
+
#>
|
|
224
|
+
[CmdletBinding()]
|
|
225
|
+
[OutputType([hashtable])]
|
|
226
|
+
param(
|
|
227
|
+
[Parameter(Mandatory = $true)]
|
|
228
|
+
[AllowNull()]
|
|
229
|
+
[AllowEmptyString()]
|
|
230
|
+
[string] $LogicalAgent,
|
|
231
|
+
|
|
232
|
+
[Parameter(Mandatory = $true)]
|
|
233
|
+
[AllowNull()]
|
|
234
|
+
[AllowEmptyString()]
|
|
235
|
+
[string] $ComplexityBand,
|
|
236
|
+
|
|
237
|
+
[Parameter(Mandatory = $true)]
|
|
238
|
+
[AllowNull()]
|
|
239
|
+
[AllowEmptyString()]
|
|
240
|
+
[string] $ExecutionContext,
|
|
241
|
+
|
|
242
|
+
[Parameter(Mandatory = $true)]
|
|
243
|
+
[AllowNull()]
|
|
244
|
+
[AllowEmptyString()]
|
|
245
|
+
[string] $OrchestrationComplexityCeiling,
|
|
246
|
+
|
|
247
|
+
[Parameter(Mandatory = $false)]
|
|
248
|
+
[AllowNull()]
|
|
249
|
+
[string[]] $AvailableModel = $null
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
$band = Assert-CodexBand -Value $ComplexityBand -FieldName 'complexity_band'
|
|
253
|
+
$ceiling = Assert-CodexBand -Value $OrchestrationComplexityCeiling -FieldName 'orchestration_complexity_ceiling'
|
|
254
|
+
$context = Assert-CodexExecutionContext -Value $ExecutionContext
|
|
255
|
+
|
|
256
|
+
# The ceiling is an upper bound on the delegation band; a ceiling below the
|
|
257
|
+
# band is an inconsistent pair rather than a clamp.
|
|
258
|
+
if ($script:BAND_ORDER.IndexOf($band) -gt $script:BAND_ORDER.IndexOf($ceiling)) {
|
|
259
|
+
throw [System.ArgumentException]::new(
|
|
260
|
+
"orchestration_complexity_ceiling must be greater than or equal to complexity_band, found $ceiling below $band."
|
|
261
|
+
)
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
# Routing table: a forced persona ignores band, context, and ceiling entirely
|
|
265
|
+
# and keeps its own name as the deployment agent; every other agent resolves
|
|
266
|
+
# through the family alias map, the C3 overlay rule, and the base profiles.
|
|
267
|
+
if ($script:FORCED_PERSONA_PROFILES.ContainsKey($LogicalAgent)) {
|
|
268
|
+
$deploymentProfile = $script:FORCED_PERSONA_PROFILES[$LogicalAgent]
|
|
269
|
+
$deploymentAgent = $LogicalAgent
|
|
270
|
+
$overlayReason = $null
|
|
271
|
+
} else {
|
|
272
|
+
$deploymentFamily = $LogicalAgent
|
|
273
|
+
if ($script:LOGICAL_AGENT_ALIASES.ContainsKey($LogicalAgent)) {
|
|
274
|
+
$deploymentFamily = $script:LOGICAL_AGENT_ALIASES[$LogicalAgent]
|
|
275
|
+
}
|
|
276
|
+
if ($script:GENERATED_AGENT_FAMILIES -cnotcontains $deploymentFamily) {
|
|
277
|
+
throw [System.ArgumentException]::new("Unsupported Codex logical agent: '$LogicalAgent'.")
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
# The overlay is a C3-only rule; every other band reads the base table.
|
|
281
|
+
$overlayReason = $null
|
|
282
|
+
if ($band -ceq $script:C3_BAND) {
|
|
283
|
+
$overlayReason = Get-CodexC3OverlayReason -ExecutionContext $context -OrchestrationComplexityCeiling $ceiling
|
|
284
|
+
}
|
|
285
|
+
$deploymentProfile = if ($overlayReason) { $script:C3_ELEVATED_PROFILE } else { $script:BASE_PROFILES[$band] }
|
|
286
|
+
$deploymentAgent = "$deploymentFamily-$($deploymentProfile['suffix'])"
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
# An availability set that omits the routed model is a hard failure: silent
|
|
290
|
+
# fallback to a different model is prohibited.
|
|
291
|
+
if ($null -ne $AvailableModel -and $AvailableModel -cnotcontains $deploymentProfile['model']) {
|
|
292
|
+
throw [System.InvalidOperationException]::new(
|
|
293
|
+
"model_unavailable: required Codex model '$($deploymentProfile['model'])' is unavailable; silent fallback is prohibited."
|
|
294
|
+
)
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
return @{
|
|
298
|
+
logical_agent = $LogicalAgent
|
|
299
|
+
deployment_agent = $deploymentAgent
|
|
300
|
+
complexity_band = $band
|
|
301
|
+
execution_context = $context
|
|
302
|
+
orchestration_complexity_ceiling = $ceiling
|
|
303
|
+
c3_overlay_applied = ($null -ne $overlayReason)
|
|
304
|
+
c3_overlay_reason = $overlayReason
|
|
305
|
+
model = $deploymentProfile['model']
|
|
306
|
+
model_reasoning_effort = $deploymentProfile['model_reasoning_effort']
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
# Only the resolver is exported; the validation and overlay helpers are private so
|
|
311
|
+
# no consumer can bypass the single entry point.
|
|
312
|
+
Export-ModuleMember -Function Resolve-CodexDeployment
|