@danmoisan/drm-copilot-mcp 1.1.12 → 1.1.14
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 +30 -78
- package/package.json +2 -2
- package/resources/claude-customizations/.claude/agents/parallel-planner.md +18 -1
- package/resources/claude-customizations/.claude/hooks/enforce-completion-consistency.ps1 +16 -8
- package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-helpers.ps1 +27 -27
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadius.psm1 +43 -6
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusScheduling.psm1 +486 -0
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusValidation.psm1 +5 -2
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusWriteIntent.psm1 +446 -0
- package/resources/claude-customizations/.claude/rules/parallel-orchestration.md +150 -2
- package/resources/claude-customizations/.claude/rules/plan-acceptance-gates.md +5 -5
- package/resources/claude-customizations/.claude/skills/epic-plan/SKILL.md +11 -0
- package/resources/claude-customizations/.claude/skills/parallel-add/SKILL.md +32 -17
- package/resources/claude-customizations/.claude/skills/parallel-plan/SKILL.md +39 -10
- package/resources/claude-customizations/config/blast-radius.json +14 -1
- package/resources/claude-customizations/pack-manifests/core.json +2 -0
- package/resources/codex-and-agents-customizations/.codex/config.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-epic-resolution.ps1 +493 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-epic-scope.ps1 +189 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-helpers.ps1 +27 -27
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate.ps1 +14 -27
- package/resources/codex-and-agents-customizations/pack-manifests/core.json +2 -0
- package/resources/powershell/PoshQC/settings/pester.runsettings.psd1 +11 -0
|
@@ -28,12 +28,12 @@ $script:OrchestrationBookkeepingTrees = @(
|
|
|
28
28
|
)
|
|
29
29
|
|
|
30
30
|
# Characters that make a command line statically unresolvable (D4 row 12, as narrowed by
|
|
31
|
-
#
|
|
32
|
-
#
|
|
33
|
-
#
|
|
34
|
-
# literal text, so a quoted Co-Authored-By trailer is not a redirection.
|
|
31
|
+
# issues #663 and #713): interpolation characters outside single quotes; outside-quote
|
|
32
|
+
# characters (`<`, `>`, and the `#` comment introducer) outside any quote; and typographic
|
|
33
|
+
# quotes (U+2018 to U+201E) anywhere, because a PowerShell host reads them as quotes.
|
|
35
34
|
$script:InterpolationCommandCharacters = [char[]]@('$', '`')
|
|
36
|
-
$script:
|
|
35
|
+
$script:OutsideQuoteCommandCharacters = [char[]]@('>', '<', '#')
|
|
36
|
+
$script:TypographicQuoteCharacters = [char[]]@(0x2018, 0x2019, 0x201A, 0x201B, 0x201C, 0x201D, 0x201E)
|
|
37
37
|
|
|
38
38
|
# Wildcards that make an operand a glob (D4 row 15). Only the literal prefix before the
|
|
39
39
|
# first of these is prefix-tested.
|
|
@@ -60,10 +60,9 @@ function Split-OrchestrationCommandLine {
|
|
|
60
60
|
.SYNOPSIS
|
|
61
61
|
Splits a command line into segments on chain operators outside quotes.
|
|
62
62
|
.DESCRIPTION
|
|
63
|
-
Realizes D4 row 13. Quote state
|
|
64
|
-
|
|
65
|
-
the
|
|
66
|
-
caller denies (D4 rows 11 and 13). Empty and whitespace-only segments are dropped.
|
|
63
|
+
Realizes D4 row 13. Quote state and POSIX backslash escapes (issue #710) are tracked, so a quoted or
|
|
64
|
+
escaped chain operator does not split. `Balanced` reports whether the scan ended outside every quote;
|
|
65
|
+
the caller denies unbalanced text (D4 rows 11 and 13). Empty and whitespace-only segments are dropped.
|
|
67
66
|
.OUTPUTS
|
|
68
67
|
System.Collections.Hashtable with keys `Balanced` (bool) and `Segments` (string[]).
|
|
69
68
|
#>
|
|
@@ -74,8 +73,9 @@ function Split-OrchestrationCommandLine {
|
|
|
74
73
|
$segments = [System.Collections.Generic.List[string]]::new()
|
|
75
74
|
$current = [System.Text.StringBuilder]::new()
|
|
76
75
|
$openQuote = [char]0
|
|
77
|
-
|
|
76
|
+
$escaped = $false
|
|
78
77
|
foreach ($character in $CommandText.ToCharArray()) {
|
|
78
|
+
if ($escaped -or ($character -eq '\' -and $openQuote -ne "'")) { $escaped = -not $escaped; [void]$current.Append($character); continue }
|
|
79
79
|
if ($openQuote -ne [char]0) {
|
|
80
80
|
if ($character -eq $openQuote) {
|
|
81
81
|
$openQuote = [char]0
|
|
@@ -112,12 +112,12 @@ function Test-OrchestrationCommandTextUnresolvable {
|
|
|
112
112
|
.SYNOPSIS
|
|
113
113
|
Reports whether a command line carries a statically unresolvable character.
|
|
114
114
|
.DESCRIPTION
|
|
115
|
-
Realizes D4 row 12 as narrowed by
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
115
|
+
Realizes D4 row 12 as narrowed by issues #663 and #713, with quote state tracked as in
|
|
116
|
+
Split-OrchestrationCommandLine. `$` or backtick answers true outside quotes or inside
|
|
117
|
+
double quotes (single quotes keep it literal); `<`, `>`, or a `#` comment answers true
|
|
118
|
+
only outside a quoted span. A typographic quote (U+2018 to U+201E), a backslash before
|
|
119
|
+
any quote character, or a backslash inside a double-quoted span answers true anywhere:
|
|
120
|
+
a shell may end the span where this scan does not (fail closed).
|
|
121
121
|
.PARAMETER CommandText
|
|
122
122
|
The full command line as the shell would receive it.
|
|
123
123
|
.OUTPUTS
|
|
@@ -127,17 +127,17 @@ function Test-OrchestrationCommandTextUnresolvable {
|
|
|
127
127
|
[OutputType([bool])]
|
|
128
128
|
param([Parameter(Mandatory)][AllowEmptyString()][string] $CommandText)
|
|
129
129
|
|
|
130
|
-
# An escaped quote moves a span boundary the scan cannot model (
|
|
131
|
-
if ($CommandText.Contains('\"') -or $CommandText.Contains("\'")) {
|
|
130
|
+
# An escaped or typographic quote moves a span boundary the scan cannot model (#663, #713).
|
|
131
|
+
if ($CommandText.Contains('\"') -or $CommandText.Contains("\'") -or $CommandText.IndexOfAny($script:TypographicQuoteCharacters) -ge 0) {
|
|
132
132
|
return $true
|
|
133
133
|
}
|
|
134
134
|
|
|
135
135
|
$openQuote = [char]0
|
|
136
136
|
|
|
137
137
|
# Scan every character once, tracking whether it sits inside a quoted span so that
|
|
138
|
-
#
|
|
138
|
+
# outside-quote characters are judged only where the shell would honour them.
|
|
139
139
|
foreach ($character in $CommandText.ToCharArray()) {
|
|
140
|
-
if ($script:InterpolationCommandCharacters -contains $character) {
|
|
140
|
+
if ($openQuote -ne "'" -and $script:InterpolationCommandCharacters -contains $character) {
|
|
141
141
|
return $true
|
|
142
142
|
}
|
|
143
143
|
|
|
@@ -153,7 +153,7 @@ function Test-OrchestrationCommandTextUnresolvable {
|
|
|
153
153
|
}
|
|
154
154
|
} elseif ($character -eq '"' -or $character -eq "'") {
|
|
155
155
|
$openQuote = $character
|
|
156
|
-
} elseif ($script:
|
|
156
|
+
} elseif ($script:OutsideQuoteCommandCharacters -contains $character) {
|
|
157
157
|
return $true
|
|
158
158
|
}
|
|
159
159
|
}
|
|
@@ -393,21 +393,21 @@ function Test-ExemptOrchestrationSegmentToken {
|
|
|
393
393
|
}
|
|
394
394
|
|
|
395
395
|
if ($candidate.StartsWith('-')) {
|
|
396
|
-
#
|
|
396
|
+
# Only the message and trailer options of commit are modelled (issue #713). Rows
|
|
397
397
|
# 2, 5, 6, 8, and 10 all land here and deny, including a dash-leading
|
|
398
398
|
# operand supplied without a preceding separator.
|
|
399
399
|
if ($subcommand -cne 'commit') {
|
|
400
400
|
return $false
|
|
401
401
|
}
|
|
402
|
-
if ($candidate -ceq '-m' -or $candidate -ceq '--message') {
|
|
403
|
-
# The message value is the following token and is not a pathspec.
|
|
402
|
+
if ($candidate -ceq '-m' -or $candidate -ceq '--message' -or $candidate -ceq '--trailer') {
|
|
403
|
+
# The message or trailer value is the following token and is not a pathspec.
|
|
404
404
|
$index += 2
|
|
405
405
|
if ($index -gt $Token.Count) {
|
|
406
406
|
return $false
|
|
407
407
|
}
|
|
408
408
|
continue
|
|
409
409
|
}
|
|
410
|
-
if ($candidate.StartsWith('--message=') -or
|
|
410
|
+
if ($candidate.StartsWith('--message=') -or $candidate.StartsWith('--trailer=') -or
|
|
411
411
|
($candidate.Length -gt 2 -and $candidate.StartsWith('-m'))) {
|
|
412
412
|
$index++
|
|
413
413
|
continue
|
|
@@ -464,8 +464,8 @@ function Test-ExemptOrchestrationStagingCommand {
|
|
|
464
464
|
return $false
|
|
465
465
|
}
|
|
466
466
|
|
|
467
|
-
# Row 12:
|
|
468
|
-
#
|
|
467
|
+
# Row 12: `$` or backtick outside single quotes, `<`, `>`, or `#` outside quotes, any
|
|
468
|
+
# typographic quote, and unmodelled backslash escapes make the operand list untrustworthy.
|
|
469
469
|
if (Test-OrchestrationCommandTextUnresolvable -CommandText $CommandText) {
|
|
470
470
|
return $false
|
|
471
471
|
}
|
|
@@ -20,6 +20,9 @@ param()
|
|
|
20
20
|
# normative contract and which lacks headroom; leaving that file byte-untouched is the
|
|
21
21
|
# proof the issue #539 exemption is behaviourally unchanged.
|
|
22
22
|
. (Join-Path $PSScriptRoot 'enforce-orchestration-preimplementation-gate-modes.ps1')
|
|
23
|
+
# Epic-scope command and path legs (issue #707, porting issue #663 decision D2), plus the
|
|
24
|
+
# two per-mode read seams relocated from this file to keep it inside the 500-line cap.
|
|
25
|
+
. (Join-Path $PSScriptRoot 'enforce-orchestration-preimplementation-gate-epic-scope.ps1')
|
|
23
26
|
# Shared command-line parser (issue #545): per-segment scan text and structural matching.
|
|
24
27
|
. (Join-Path $PSScriptRoot 'hook-command-scanner.ps1')
|
|
25
28
|
. (Join-Path $PSScriptRoot 'hook-command-invocation.ps1')
|
|
@@ -286,33 +289,6 @@ function Get-CheckpointContent {
|
|
|
286
289
|
return Get-Content -Raw -LiteralPath $script:CheckpointPath
|
|
287
290
|
}
|
|
288
291
|
|
|
289
|
-
# The two per-mode read seams (issue #554). Each takes its path from the fixed mode
|
|
290
|
-
# table and never from a delegation's own text; an absent file returns an empty
|
|
291
|
-
# string, which the readiness predicate then treats as a deny.
|
|
292
|
-
function Get-EpicCheckpointContent {
|
|
293
|
-
[CmdletBinding()]
|
|
294
|
-
[OutputType([string])]
|
|
295
|
-
param()
|
|
296
|
-
|
|
297
|
-
$path = Get-OrchestrationDelegationCheckpointPath -Mode 'epic'
|
|
298
|
-
if (-not (Test-Path -LiteralPath $path)) {
|
|
299
|
-
return ''
|
|
300
|
-
}
|
|
301
|
-
return Get-Content -Raw -LiteralPath $path
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
function Get-ParallelCheckpointContent {
|
|
305
|
-
[CmdletBinding()]
|
|
306
|
-
[OutputType([string])]
|
|
307
|
-
param()
|
|
308
|
-
|
|
309
|
-
$path = Get-OrchestrationDelegationCheckpointPath -Mode 'parallel'
|
|
310
|
-
if (-not (Test-Path -LiteralPath $path)) {
|
|
311
|
-
return ''
|
|
312
|
-
}
|
|
313
|
-
return Get-Content -Raw -LiteralPath $path
|
|
314
|
-
}
|
|
315
|
-
|
|
316
292
|
function Get-OrchestrationPreimplementationGateAllowDecision {
|
|
317
293
|
[CmdletBinding()]
|
|
318
294
|
[OutputType([System.Collections.Specialized.OrderedDictionary])]
|
|
@@ -398,6 +374,7 @@ function Invoke-OrchestrationPreimplementationGateDecision {
|
|
|
398
374
|
# default wording they have today.
|
|
399
375
|
$mode = $script:OrchestrationDelegationDefaultMode
|
|
400
376
|
$prompt = ''
|
|
377
|
+
$command = ''
|
|
401
378
|
$filePath = Get-StringProperty -Value $toolInput -Name 'file_path'
|
|
402
379
|
if ($filePath) {
|
|
403
380
|
$normalized = ([string]$filePath) -replace '\\', '/'
|
|
@@ -427,6 +404,16 @@ function Invoke-OrchestrationPreimplementationGateDecision {
|
|
|
427
404
|
Get-OrchestrationModeDenyReason -Mode $mode -Failure 'declared-checkpoint-path')
|
|
428
405
|
}
|
|
429
406
|
|
|
407
|
+
# The command, apply_patch, and path legs consult the epic checkpoint first (issue #707,
|
|
408
|
+
# porting issue #663). A call that is not epic scope yields $null and continues to the
|
|
409
|
+
# unchanged single-feature path.
|
|
410
|
+
if ($filePath -or $command) {
|
|
411
|
+
$epicDecision = Get-OrchestrationEpicScopeDecision -Command $command -FilePath $filePath
|
|
412
|
+
if ($null -ne $epicDecision) {
|
|
413
|
+
return $epicDecision
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
430
417
|
if ($mode -eq 'epic' -or $mode -eq 'parallel') {
|
|
431
418
|
$isEpic = ($mode -eq 'epic')
|
|
432
419
|
$injected = if ($isEpic) { 'EpicCheckpointRaw' } else { 'ParallelCheckpointRaw' }
|
|
@@ -38,6 +38,8 @@
|
|
|
38
38
|
".codex/hooks/enforce-epic-root-invocation.ps1",
|
|
39
39
|
".codex/hooks/enforce-epic-wave-barrier.ps1",
|
|
40
40
|
".codex/hooks/enforce-epic-worktree-removal-gate.ps1",
|
|
41
|
+
".codex/hooks/enforce-orchestration-preimplementation-gate-epic-resolution.ps1",
|
|
42
|
+
".codex/hooks/enforce-orchestration-preimplementation-gate-epic-scope.ps1",
|
|
41
43
|
".codex/hooks/enforce-orchestration-preimplementation-gate-helpers.ps1",
|
|
42
44
|
".codex/hooks/enforce-orchestration-preimplementation-gate-modes.ps1",
|
|
43
45
|
".codex/hooks/hook-command-invocation.ps1",
|
|
@@ -145,6 +145,9 @@
|
|
|
145
145
|
# table and the epic and parallel readiness predicates; registered so the new
|
|
146
146
|
# production file stays in the coverage denominator per the Coverage Exclusion Policy.
|
|
147
147
|
'.codex/hooks/enforce-orchestration-preimplementation-gate-modes.ps1'
|
|
148
|
+
# Issue #707 added these two dot-sourced siblings for the Codex epic-scope command and path legs.
|
|
149
|
+
'.codex/hooks/enforce-orchestration-preimplementation-gate-epic-scope.ps1'
|
|
150
|
+
'.codex/hooks/enforce-orchestration-preimplementation-gate-epic-resolution.ps1'
|
|
148
151
|
# Issue #415 remediation cycle 2 (R-COV): the detached-HEAD null-guard fix changed
|
|
149
152
|
# these two Codex PreToolUse hooks. Both were absent from this list, so the changed
|
|
150
153
|
# production surface was outside the coverage denominator. Measured here so the
|
|
@@ -180,6 +183,14 @@
|
|
|
180
183
|
# BlastRadius.psm1. CodeCoverage.Path is an explicit per-file allow-list, so
|
|
181
184
|
# the new module must be named here to be measured.
|
|
182
185
|
'.claude/lib/blast-radius/BlastRadiusConflict.psm1'
|
|
186
|
+
# Issue #722 added the ninth file below, the integration-cost scheduling
|
|
187
|
+
# layer over the unchanged contention relation. CodeCoverage.Path is an
|
|
188
|
+
# explicit per-file allow-list, so the new module is named here to keep
|
|
189
|
+
# it in the coverage denominator.
|
|
190
|
+
'.claude/lib/blast-radius/BlastRadiusScheduling.psm1'
|
|
191
|
+
# Issue #722 also added the tenth file below, the write-intent
|
|
192
|
+
# extraction layer the facade and validation module delegate to.
|
|
193
|
+
'.claude/lib/blast-radius/BlastRadiusWriteIntent.psm1'
|
|
183
194
|
# Issue #643 also added the merge library below: the line grammar, the
|
|
184
195
|
# keyed-union merge, and the entry script. The entry script is measured
|
|
185
196
|
# like the two modules because its Pester suite dot-sources it behind a
|