@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.
Files changed (23) hide show
  1. package/out/mcp-server.js +30 -78
  2. package/package.json +2 -2
  3. package/resources/claude-customizations/.claude/agents/parallel-planner.md +18 -1
  4. package/resources/claude-customizations/.claude/hooks/enforce-completion-consistency.ps1 +16 -8
  5. package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-helpers.ps1 +27 -27
  6. package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadius.psm1 +43 -6
  7. package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusScheduling.psm1 +486 -0
  8. package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusValidation.psm1 +5 -2
  9. package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusWriteIntent.psm1 +446 -0
  10. package/resources/claude-customizations/.claude/rules/parallel-orchestration.md +150 -2
  11. package/resources/claude-customizations/.claude/rules/plan-acceptance-gates.md +5 -5
  12. package/resources/claude-customizations/.claude/skills/epic-plan/SKILL.md +11 -0
  13. package/resources/claude-customizations/.claude/skills/parallel-add/SKILL.md +32 -17
  14. package/resources/claude-customizations/.claude/skills/parallel-plan/SKILL.md +39 -10
  15. package/resources/claude-customizations/config/blast-radius.json +14 -1
  16. package/resources/claude-customizations/pack-manifests/core.json +2 -0
  17. package/resources/codex-and-agents-customizations/.codex/config.toml +1 -1
  18. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-epic-resolution.ps1 +493 -0
  19. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-epic-scope.ps1 +189 -0
  20. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-helpers.ps1 +27 -27
  21. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate.ps1 +14 -27
  22. package/resources/codex-and-agents-customizations/pack-manifests/core.json +2 -0
  23. 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
- # issue #663). Interpolation characters are unresolvable in every quote state, because a
32
- # double-quoted span still expands them. Redirection characters are unresolvable only
33
- # outside a quoted span: inside single or double quotes the shell treats `<` and `>` as
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:RedirectionCommandCharacters = [char[]]@('>', '<')
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 is tracked while scanning so a chain operator
64
- inside a quoted span does not split. The returned `Balanced` flag reports whether
65
- the scan ended outside every quote; unbalanced text is not splittable and 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 issue #663. Quote state is tracked with the same
116
- state machine as Split-OrchestrationCommandLine. An interpolation character (`$` or
117
- backtick) answers true in any quote state; a redirection character (`<` or `>`)
118
- answers true only outside a quoted span. Backslash escapes are not modelled, so a
119
- backslash before any quote character, or anywhere inside a double-quoted span,
120
- answers true: the shell may end the span where this scan does not (fail closed).
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 (issue #663 remediation CR-1).
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
- # redirection characters are judged only where the shell would honour them.
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:RedirectionCommandCharacters -contains $character) {
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
- # The message option is the only modelled option on either subcommand. Rows
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: interpolation anywhere, redirection outside quotes, and unmodelled backslash
468
- # escapes are not statically resolvable, so the operand list cannot be trusted.
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