@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.
- package/out/mcp-server.js +366 -159
- package/package.json +1 -1
- package/resources/claude-customizations/.claude/agents/epic-orchestrator.md +1 -1
- package/resources/claude-customizations/.claude/agents/epic-planner.md +4 -1
- package/resources/claude-customizations/.claude/agents/pr-author.md +15 -0
- package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate-authorization.ps1 +443 -0
- package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate.ps1 +33 -37
- package/resources/claude-customizations/.claude/hooks/enforce-model-routing-receipt.ps1 +120 -5
- package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-epic-scope.ps1 +127 -0
- package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-helpers.ps1 +163 -15
- package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate.ps1 +14 -27
- package/resources/claude-customizations/.claude/hooks/enforce-parallel-worktree-removal-gate.ps1 +66 -5
- package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill-helpers.ps1 +134 -10
- package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.epic-base-branch.ps1 +37 -8
- package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.ps1 +3 -1
- package/resources/claude-customizations/.claude/hooks/enforce-prd-feature-before-planner-helpers.ps1 +332 -0
- package/resources/claude-customizations/.claude/hooks/enforce-prd-feature-before-planner.ps1 +211 -182
- package/resources/claude-customizations/.claude/lib/codex-routing/CodexDeployment.psm1 +1 -0
- package/resources/claude-customizations/.claude/lib/worktree-resolution/EpicScopeReadiness.psm1 +176 -0
- package/resources/claude-customizations/.claude/lib/worktree-resolution/EpicScopeResolution.psm1 +369 -0
- package/resources/claude-customizations/.claude/lib/worktree-resolution/WorktreeItemResolution.psm1 +392 -0
- package/resources/claude-customizations/.claude/lib/worktree-resolution/WorktreeResolution.psm1 +500 -0
- package/resources/claude-customizations/.claude/lib/worktree-resolution/WorktreeTargetResolution.psm1 +347 -0
- package/resources/claude-customizations/.claude/rules/orchestrator-state.md +27 -0
- package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/SKILL.md +12 -0
- package/resources/claude-customizations/.claude/skills/epic-orchestrate/SKILL.md +14 -1
- package/resources/claude-customizations/.claude/skills/epic-plan/SKILL.md +4 -0
- package/resources/claude-customizations/.claude/skills/orchestrate/SKILL.md +4 -1
- package/resources/claude-customizations/.claude/skills/parallel-orchestrate/SKILL.md +39 -6
- package/resources/claude-customizations/.claude/skills/pr-author/SKILL.md +15 -0
- package/resources/claude-customizations/.claude/skills/quota-throttling/SKILL.md +221 -0
- package/resources/claude-customizations/pack-manifests/core.json +9 -0
- package/resources/codex-and-agents-customizations/.agents/skills/codex-model-routing/SKILL.md +13 -14
- package/resources/codex-and-agents-customizations/.codex/config.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-merge-gate.ps1 +193 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-planning-only.ps1 +15 -5
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-helpers.ps1 +163 -15
- package/resources/codex-and-agents-customizations/.codex/scripts/Resolve-CodexDeployment.ps1 +87 -0
- package/resources/codex-and-agents-customizations/.codex/scripts/Resolve-CodexTopology.ps1 +96 -0
- package/resources/codex-and-agents-customizations/.codex/scripts/codex-routing-cli-common.ps1 +370 -0
- package/resources/codex-and-agents-customizations/.codex/scripts/epic-child-launch-contract.ps1 +475 -0
- package/resources/codex-and-agents-customizations/.codex/scripts/epic-child-launch-runtime.ps1 +445 -0
- package/resources/codex-and-agents-customizations/.codex/scripts/epic-child-persistence-runtime.ps1 +118 -0
- package/resources/codex-and-agents-customizations/.codex/scripts/epic-child-sandbox-preflight.ps1 +69 -0
- package/resources/codex-and-agents-customizations/.codex/scripts/launch-epic-child-wave.ps1 +471 -0
- package/resources/codex-and-agents-customizations/.codex/scripts/post-codex-worktree-session.ps1 +280 -0
- package/resources/codex-and-agents-customizations/.codex/scripts/resume-epic-child.ps1 +263 -0
- package/resources/codex-and-agents-customizations/.codex-variants/csharp-legacy/agents/csharp-typed-engineer.toml +2 -1
- package/resources/codex-and-agents-customizations/pack-manifests/core.json +18 -1
- package/resources/lib/codex-routing/CodexDeployment.psm1 +315 -0
- package/resources/lib/codex-routing/CodexTopology.psm1 +394 -0
- package/resources/powershell/PoshQC/settings/pester.runsettings.psd1 +26 -0
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
#Requires -Version 7.0
|
|
2
|
+
<#
|
|
3
|
+
.SYNOPSIS
|
|
4
|
+
Shared helpers for the Codex routing CLI wrappers (issue #697).
|
|
5
|
+
|
|
6
|
+
.DESCRIPTION
|
|
7
|
+
Dot-sourced by Resolve-CodexTopology.ps1 and Resolve-CodexDeployment.ps1 so
|
|
8
|
+
the two wrappers share one implementation of module-candidate resolution,
|
|
9
|
+
GNU-style token parsing, and Python-compatible JSON serialization. The
|
|
10
|
+
wrappers replace `poetry run python -m scripts.dev_tools.resolve_codex_*` in
|
|
11
|
+
destinations that have no Python toolchain, and must print byte-identical
|
|
12
|
+
receipts, so the serializer reproduces Python
|
|
13
|
+
`json.dumps(receipt, indent=2, sort_keys=True)` with `ensure_ascii=True`.
|
|
14
|
+
|
|
15
|
+
This file defines functions only and has no top-level side effects.
|
|
16
|
+
#>
|
|
17
|
+
|
|
18
|
+
function Get-CodexRoutingModuleCandidate {
|
|
19
|
+
<#
|
|
20
|
+
.SYNOPSIS
|
|
21
|
+
Return the ordered module candidate paths for one codex-routing module.
|
|
22
|
+
.DESCRIPTION
|
|
23
|
+
The first candidate is the published destination location
|
|
24
|
+
(.codex/lib/codex-routing beside .codex/scripts). The second is the
|
|
25
|
+
self-hosting location in this repository (.claude/lib/codex-routing),
|
|
26
|
+
used where no .codex/lib directory exists.
|
|
27
|
+
.PARAMETER ScriptRoot
|
|
28
|
+
Directory of the calling wrapper (its $PSScriptRoot).
|
|
29
|
+
.PARAMETER ModuleName
|
|
30
|
+
Module file name, for example CodexTopology.psm1.
|
|
31
|
+
.OUTPUTS
|
|
32
|
+
System.String[] - the two candidate paths in resolution order.
|
|
33
|
+
#>
|
|
34
|
+
[CmdletBinding()]
|
|
35
|
+
[OutputType([string[]])]
|
|
36
|
+
param(
|
|
37
|
+
[Parameter(Mandatory = $true)][string] $ScriptRoot,
|
|
38
|
+
[Parameter(Mandatory = $true)][string] $ModuleName
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
return [string[]]@(
|
|
42
|
+
(Join-Path $ScriptRoot "../lib/codex-routing/$ModuleName"),
|
|
43
|
+
(Join-Path $ScriptRoot "../../.claude/lib/codex-routing/$ModuleName")
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function Resolve-CodexRoutingModulePath {
|
|
48
|
+
<#
|
|
49
|
+
.SYNOPSIS
|
|
50
|
+
Return the first existing module candidate, or $null when none exists.
|
|
51
|
+
.PARAMETER Candidate
|
|
52
|
+
Candidate module paths in resolution order.
|
|
53
|
+
.OUTPUTS
|
|
54
|
+
System.String - the first candidate that is an existing file, or $null.
|
|
55
|
+
#>
|
|
56
|
+
[CmdletBinding()]
|
|
57
|
+
[OutputType([string])]
|
|
58
|
+
param(
|
|
59
|
+
[Parameter(Mandatory = $true)][AllowEmptyCollection()][string[]] $Candidate
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
# The first existing candidate wins, so a published destination module
|
|
63
|
+
# always takes precedence over the self-hosting fallback.
|
|
64
|
+
foreach ($path in $Candidate) {
|
|
65
|
+
if (Test-Path -LiteralPath $path -PathType Leaf) {
|
|
66
|
+
return $path
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return $null
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function Test-CodexRoutingOptionValueToken {
|
|
73
|
+
<#
|
|
74
|
+
.SYNOPSIS
|
|
75
|
+
Decide whether a token can be consumed as an option value.
|
|
76
|
+
.DESCRIPTION
|
|
77
|
+
Mirrors argparse: a token that looks like an option (a leading '-' that
|
|
78
|
+
is not a negative number) is not a value, so the preceding option
|
|
79
|
+
reports that it expected one argument.
|
|
80
|
+
.PARAMETER Token
|
|
81
|
+
The candidate value token.
|
|
82
|
+
.OUTPUTS
|
|
83
|
+
System.Boolean
|
|
84
|
+
#>
|
|
85
|
+
[CmdletBinding()]
|
|
86
|
+
[OutputType([bool])]
|
|
87
|
+
param([Parameter(Mandatory = $true)][AllowEmptyString()][string] $Token)
|
|
88
|
+
|
|
89
|
+
if (-not $Token.StartsWith('-')) {
|
|
90
|
+
return $true
|
|
91
|
+
}
|
|
92
|
+
return ($Token -match '^-\d+$|^-\d*\.\d+$')
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function ConvertFrom-CodexRoutingArgument {
|
|
96
|
+
<#
|
|
97
|
+
.SYNOPSIS
|
|
98
|
+
Parse GNU-style CLI tokens against a wrapper specification.
|
|
99
|
+
.DESCRIPTION
|
|
100
|
+
Supports `--flag value` and `--flag=value`. An `append` option collects
|
|
101
|
+
every occurrence; a `switch` option takes no value; for other options
|
|
102
|
+
the last occurrence wins. Error messages follow argparse wording so the
|
|
103
|
+
wrappers report the same failures as the Python CLIs.
|
|
104
|
+
.PARAMETER Arguments
|
|
105
|
+
The CLI tokens.
|
|
106
|
+
.PARAMETER Specification
|
|
107
|
+
Ordered dictionary from option name (for example '--language') to a
|
|
108
|
+
hashtable with Key, Kind ('value', 'append', 'switch', or 'int'),
|
|
109
|
+
Required, optional Choices, and Default.
|
|
110
|
+
.OUTPUTS
|
|
111
|
+
PSCustomObject with Values (hashtable keyed by each option's Key) and
|
|
112
|
+
Error ($null, or an argparse-style 'error: ...' message).
|
|
113
|
+
#>
|
|
114
|
+
[CmdletBinding()]
|
|
115
|
+
[OutputType([pscustomobject])]
|
|
116
|
+
param(
|
|
117
|
+
[Parameter(Mandatory = $true)][AllowEmptyCollection()][AllowEmptyString()][string[]] $Arguments,
|
|
118
|
+
[Parameter(Mandatory = $true)][System.Collections.IDictionary] $Specification
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
$values = @{}
|
|
122
|
+
$appended = @{}
|
|
123
|
+
$seen = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::Ordinal)
|
|
124
|
+
$unrecognized = [System.Collections.Generic.List[string]]::new()
|
|
125
|
+
|
|
126
|
+
# Seed defaults so every key is present even when its option is absent.
|
|
127
|
+
foreach ($name in $Specification.Keys) {
|
|
128
|
+
$entry = $Specification[$name]
|
|
129
|
+
if ($entry.Kind -eq 'append') {
|
|
130
|
+
$appended[$entry.Key] = [System.Collections.Generic.List[string]]::new()
|
|
131
|
+
} else {
|
|
132
|
+
$values[$entry.Key] = $entry.Default
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
# Consume tokens left to right. Value errors stop immediately, as argparse
|
|
137
|
+
# does; unknown options and positional tokens are reported after the
|
|
138
|
+
# required-option check, matching argparse's reporting order.
|
|
139
|
+
$index = 0
|
|
140
|
+
while ($index -lt $Arguments.Count) {
|
|
141
|
+
$token = $Arguments[$index]
|
|
142
|
+
$index++
|
|
143
|
+
if ($token -eq '--') {
|
|
144
|
+
# Every token after the separator is positional, and neither
|
|
145
|
+
# wrapper accepts positional tokens.
|
|
146
|
+
for ($rest = $index; $rest -lt $Arguments.Count; $rest++) {
|
|
147
|
+
$unrecognized.Add($Arguments[$rest])
|
|
148
|
+
}
|
|
149
|
+
break
|
|
150
|
+
}
|
|
151
|
+
if (-not $token.StartsWith('--') -or $token.Length -le 2) {
|
|
152
|
+
$unrecognized.Add($token)
|
|
153
|
+
continue
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
$separator = $token.IndexOf('=')
|
|
157
|
+
$name = if ($separator -ge 0) { $token.Substring(0, $separator) } else { $token }
|
|
158
|
+
$inlineValue = if ($separator -ge 0) { $token.Substring($separator + 1) } else { $null }
|
|
159
|
+
if (-not $Specification.Contains($name)) {
|
|
160
|
+
$unrecognized.Add($token)
|
|
161
|
+
continue
|
|
162
|
+
}
|
|
163
|
+
$entry = $Specification[$name]
|
|
164
|
+
[void]$seen.Add($name)
|
|
165
|
+
|
|
166
|
+
# A switch takes no value; every other kind requires exactly one.
|
|
167
|
+
if ($entry.Kind -eq 'switch') {
|
|
168
|
+
if ($null -ne $inlineValue) {
|
|
169
|
+
return [pscustomobject]@{ Values = $values; Error = "error: argument ${name}: ignored explicit argument '$inlineValue'" }
|
|
170
|
+
}
|
|
171
|
+
$values[$entry.Key] = $true
|
|
172
|
+
continue
|
|
173
|
+
}
|
|
174
|
+
if ($null -ne $inlineValue) {
|
|
175
|
+
$value = $inlineValue
|
|
176
|
+
} elseif ($index -lt $Arguments.Count -and (Test-CodexRoutingOptionValueToken -Token $Arguments[$index])) {
|
|
177
|
+
$value = $Arguments[$index]
|
|
178
|
+
$index++
|
|
179
|
+
} else {
|
|
180
|
+
return [pscustomobject]@{ Values = $values; Error = "error: argument ${name}: expected one argument" }
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if ($null -ne $entry.Choices -and @($entry.Choices) -cnotcontains $value) {
|
|
184
|
+
$choices = (@($entry.Choices) | ForEach-Object { "'$_'" }) -join ', '
|
|
185
|
+
return [pscustomobject]@{ Values = $values; Error = "error: argument ${name}: invalid choice: '$value' (choose from $choices)" }
|
|
186
|
+
}
|
|
187
|
+
if ($entry.Kind -eq 'int') {
|
|
188
|
+
$number = 0
|
|
189
|
+
$parsedNumber = [int]::TryParse(
|
|
190
|
+
$value,
|
|
191
|
+
[System.Globalization.NumberStyles]::Integer,
|
|
192
|
+
[System.Globalization.CultureInfo]::InvariantCulture,
|
|
193
|
+
[ref] $number)
|
|
194
|
+
if (-not $parsedNumber) {
|
|
195
|
+
return [pscustomobject]@{ Values = $values; Error = "error: argument ${name}: invalid int value: '$value'" }
|
|
196
|
+
}
|
|
197
|
+
$values[$entry.Key] = $number
|
|
198
|
+
} elseif ($entry.Kind -eq 'append') {
|
|
199
|
+
$appended[$entry.Key].Add($value)
|
|
200
|
+
} else {
|
|
201
|
+
$values[$entry.Key] = $value
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
$missing = @($Specification.Keys | Where-Object { $Specification[$_].Required -and -not $seen.Contains($_) })
|
|
206
|
+
if ($missing.Count -gt 0) {
|
|
207
|
+
return [pscustomobject]@{ Values = $values; Error = "error: the following arguments are required: $($missing -join ', ')" }
|
|
208
|
+
}
|
|
209
|
+
if ($unrecognized.Count -gt 0) {
|
|
210
|
+
return [pscustomobject]@{ Values = $values; Error = "error: unrecognized arguments: $($unrecognized -join ' ')" }
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
# Append options surface as string arrays, empty when never supplied.
|
|
214
|
+
foreach ($key in $appended.Keys) {
|
|
215
|
+
$values[$key] = [string[]]$appended[$key].ToArray()
|
|
216
|
+
}
|
|
217
|
+
return [pscustomobject]@{ Values = $values; Error = $null }
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function ConvertTo-CodexRoutingJsonString {
|
|
221
|
+
<#
|
|
222
|
+
.SYNOPSIS
|
|
223
|
+
Encode one string as a JSON literal the way Python json.dumps does.
|
|
224
|
+
.DESCRIPTION
|
|
225
|
+
Escapes quote, backslash, and the short control escapes; every other
|
|
226
|
+
character below 0x20 or above 0x7E becomes a lowercase \uXXXX escape per
|
|
227
|
+
UTF-16 code unit (ensure_ascii=True), so astral characters produce two.
|
|
228
|
+
.PARAMETER Value
|
|
229
|
+
The string to encode.
|
|
230
|
+
.OUTPUTS
|
|
231
|
+
System.String - the quoted JSON literal.
|
|
232
|
+
#>
|
|
233
|
+
[CmdletBinding()]
|
|
234
|
+
[OutputType([string])]
|
|
235
|
+
param([Parameter(Mandatory = $true)][AllowEmptyString()][string] $Value)
|
|
236
|
+
|
|
237
|
+
$builder = [System.Text.StringBuilder]::new()
|
|
238
|
+
[void]$builder.Append('"')
|
|
239
|
+
foreach ($character in $Value.ToCharArray()) {
|
|
240
|
+
$code = [int]$character
|
|
241
|
+
switch ($code) {
|
|
242
|
+
0x22 { [void]$builder.Append('\"'); break }
|
|
243
|
+
0x5C { [void]$builder.Append('\\'); break }
|
|
244
|
+
0x08 { [void]$builder.Append('\b'); break }
|
|
245
|
+
0x0C { [void]$builder.Append('\f'); break }
|
|
246
|
+
0x0A { [void]$builder.Append('\n'); break }
|
|
247
|
+
0x0D { [void]$builder.Append('\r'); break }
|
|
248
|
+
0x09 { [void]$builder.Append('\t'); break }
|
|
249
|
+
default {
|
|
250
|
+
if ($code -lt 0x20 -or $code -gt 0x7E) {
|
|
251
|
+
[void]$builder.Append('\u').Append($code.ToString('x4', [System.Globalization.CultureInfo]::InvariantCulture))
|
|
252
|
+
} else {
|
|
253
|
+
[void]$builder.Append($character)
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
[void]$builder.Append('"')
|
|
259
|
+
return $builder.ToString()
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function ConvertTo-CodexRoutingJsonText {
|
|
263
|
+
<#
|
|
264
|
+
.SYNOPSIS
|
|
265
|
+
Recursively render one value at an indentation level.
|
|
266
|
+
.PARAMETER Value
|
|
267
|
+
Null, boolean, string, integer, dictionary, or enumerable.
|
|
268
|
+
.PARAMETER Level
|
|
269
|
+
Current nesting depth; each level indents by two spaces.
|
|
270
|
+
.OUTPUTS
|
|
271
|
+
System.String
|
|
272
|
+
#>
|
|
273
|
+
[CmdletBinding()]
|
|
274
|
+
[OutputType([string])]
|
|
275
|
+
param(
|
|
276
|
+
[Parameter(Mandatory = $true)][AllowNull()] $Value,
|
|
277
|
+
[Parameter(Mandatory = $true)][int] $Level
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
$inner = ' ' * (2 * ($Level + 1))
|
|
281
|
+
$outer = ' ' * (2 * $Level)
|
|
282
|
+
# Routing table: scalars first, then strings before enumerables (a string
|
|
283
|
+
# is enumerable), then objects and arrays; anything else is rejected.
|
|
284
|
+
if ($null -eq $Value) {
|
|
285
|
+
return 'null'
|
|
286
|
+
}
|
|
287
|
+
if ($Value -is [bool]) {
|
|
288
|
+
return $(if ($Value) { 'true' } else { 'false' })
|
|
289
|
+
}
|
|
290
|
+
if ($Value -is [string]) {
|
|
291
|
+
return ConvertTo-CodexRoutingJsonString -Value $Value
|
|
292
|
+
}
|
|
293
|
+
if ($Value -is [int] -or $Value -is [long] -or $Value -is [int16] -or $Value -is [byte]) {
|
|
294
|
+
return $Value.ToString([System.Globalization.CultureInfo]::InvariantCulture)
|
|
295
|
+
}
|
|
296
|
+
if ($Value -is [System.Collections.IDictionary]) {
|
|
297
|
+
$keys = [string[]]@($Value.Keys)
|
|
298
|
+
if ($keys.Count -eq 0) {
|
|
299
|
+
return '{}'
|
|
300
|
+
}
|
|
301
|
+
[Array]::Sort($keys, [System.StringComparer]::Ordinal)
|
|
302
|
+
$members = foreach ($key in $keys) {
|
|
303
|
+
$inner + (ConvertTo-CodexRoutingJsonString -Value $key) + ': ' + (ConvertTo-CodexRoutingJsonText -Value $Value[$key] -Level ($Level + 1))
|
|
304
|
+
}
|
|
305
|
+
return "{`n" + ($members -join ",`n") + "`n$outer}"
|
|
306
|
+
}
|
|
307
|
+
if ($Value -is [System.Collections.IEnumerable]) {
|
|
308
|
+
$items = @(foreach ($item in $Value) {
|
|
309
|
+
$inner + (ConvertTo-CodexRoutingJsonText -Value $item -Level ($Level + 1))
|
|
310
|
+
})
|
|
311
|
+
if ($items.Count -eq 0) {
|
|
312
|
+
return '[]'
|
|
313
|
+
}
|
|
314
|
+
return "[`n" + ($items -join ",`n") + "`n$outer]"
|
|
315
|
+
}
|
|
316
|
+
throw [System.ArgumentException]::new("unsupported JSON value type: $($Value.GetType().FullName)")
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
function ConvertTo-CodexRoutingJson {
|
|
320
|
+
<#
|
|
321
|
+
.SYNOPSIS
|
|
322
|
+
Serialize a receipt like Python json.dumps(indent=2, sort_keys=True).
|
|
323
|
+
.DESCRIPTION
|
|
324
|
+
Keys are sorted with the ordinal comparer, members are separated by a
|
|
325
|
+
comma and newline, and key and value are separated by ': '. The result
|
|
326
|
+
carries no trailing newline; the wrapper appends one as print() does.
|
|
327
|
+
.PARAMETER InputObject
|
|
328
|
+
The value to serialize.
|
|
329
|
+
.OUTPUTS
|
|
330
|
+
System.String
|
|
331
|
+
#>
|
|
332
|
+
[CmdletBinding()]
|
|
333
|
+
[OutputType([string])]
|
|
334
|
+
param([Parameter(Mandatory = $true)][AllowNull()] $InputObject)
|
|
335
|
+
|
|
336
|
+
return ConvertTo-CodexRoutingJsonText -Value $InputObject -Level 0
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
function New-CodexRoutingCliResult {
|
|
340
|
+
<#
|
|
341
|
+
.SYNOPSIS
|
|
342
|
+
Build the result object a wrapper returns: exit code and both streams.
|
|
343
|
+
.DESCRIPTION
|
|
344
|
+
Creates an in-memory object only; it changes no system state. It
|
|
345
|
+
declares ShouldProcess support to satisfy the repository analyzer
|
|
346
|
+
settings for the New verb and returns the object under -WhatIf too.
|
|
347
|
+
.PARAMETER ExitCode
|
|
348
|
+
Process exit code: 0 success, 1 resolver error, 2 usage error.
|
|
349
|
+
.PARAMETER Stdout
|
|
350
|
+
Standard output text.
|
|
351
|
+
.PARAMETER Stderr
|
|
352
|
+
Standard error text.
|
|
353
|
+
.OUTPUTS
|
|
354
|
+
PSCustomObject with ExitCode, Stdout, and Stderr.
|
|
355
|
+
#>
|
|
356
|
+
[CmdletBinding(SupportsShouldProcess = $true)]
|
|
357
|
+
[OutputType([pscustomobject])]
|
|
358
|
+
param(
|
|
359
|
+
[Parameter(Mandatory = $true)][int] $ExitCode,
|
|
360
|
+
[AllowEmptyString()][string] $Stdout = '',
|
|
361
|
+
[AllowEmptyString()][string] $Stderr = ''
|
|
362
|
+
)
|
|
363
|
+
|
|
364
|
+
[void]$PSCmdlet.ShouldProcess('codex routing CLI result', 'Create')
|
|
365
|
+
return [pscustomobject]@{
|
|
366
|
+
ExitCode = $ExitCode
|
|
367
|
+
Stdout = $Stdout
|
|
368
|
+
Stderr = $Stderr
|
|
369
|
+
}
|
|
370
|
+
}
|