@danmoisan/drm-copilot-mcp 1.1.4 → 1.1.6

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 (38) hide show
  1. package/out/mcp-server.js +335 -24
  2. package/package.json +1 -1
  3. package/resources/claude-customizations/.claude/hooks/enforce-epic-worktree-removal-gate.ps1 +163 -18
  4. package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-modes.ps1 +477 -0
  5. package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate.ps1 +120 -12
  6. package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadius.psm1 +11 -0
  7. package/resources/claude-customizations/.claude/rules/parallel-orchestration.md +1 -0
  8. package/resources/claude-customizations/.claude/rules/plan-acceptance-gates.md +131 -2
  9. package/resources/claude-customizations/.claude/skills/atomic-plan-contract/SKILL.md +37 -0
  10. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/SKILL.md +136 -4
  11. package/resources/claude-customizations/.claude/skills/parallel-add/SKILL.md +3 -1
  12. package/resources/claude-customizations/.claude/skills/parallel-orchestrate/SKILL.md +18 -9
  13. package/resources/claude-customizations/.claude/skills/parallel-plan/SKILL.md +8 -1
  14. package/resources/claude-customizations/.claude/skills/pr-context-artifacts/SKILL.md +22 -0
  15. package/resources/claude-customizations/.claude/skills/remediation-handoff-atomic-planner/SKILL.md +10 -0
  16. package/resources/claude-customizations/config/orchestration-routing.json +1 -0
  17. package/resources/claude-customizations/pack-manifests/core.json +1 -0
  18. package/resources/codex-and-agents-customizations/.agents/skills/codex-model-routing/SKILL.md +10 -0
  19. package/resources/codex-and-agents-customizations/.agents/skills/pr-context-artifacts/SKILL.md +22 -0
  20. package/resources/codex-and-agents-customizations/.codex/agents/commit-steward-c1.toml +22 -0
  21. package/resources/codex-and-agents-customizations/.codex/agents/commit-steward-c2.toml +22 -0
  22. package/resources/codex-and-agents-customizations/.codex/agents/commit-steward-c3-elevated.toml +22 -0
  23. package/resources/codex-and-agents-customizations/.codex/agents/commit-steward-c3.toml +22 -0
  24. package/resources/codex-and-agents-customizations/.codex/agents/commit-steward-c4.toml +22 -0
  25. package/resources/codex-and-agents-customizations/.codex/agents/commit-steward.toml +2 -0
  26. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c1.toml +7 -0
  27. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c2.toml +7 -0
  28. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c3-elevated.toml +7 -0
  29. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c3.toml +7 -0
  30. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c4.toml +7 -0
  31. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator.toml +7 -0
  32. package/resources/codex-and-agents-customizations/.codex/config.toml +1 -1
  33. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-modes.ps1 +477 -0
  34. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate.ps1 +125 -12
  35. package/resources/codex-and-agents-customizations/pack-manifests/core.json +8 -1
  36. package/resources/config/orchestration-routing.json +1 -0
  37. package/resources/customizations/.github/skills/pr-context-artifacts/SKILL.md +22 -0
  38. package/resources/powershell/PoshQC/settings/pester.runsettings.psd1 +10 -2
@@ -4,14 +4,51 @@
4
4
 
5
5
  .DESCRIPTION
6
6
  Invoked by the Claude Code PreToolUse hook on the "Bash" matcher before any Bash
7
- command runs. Regex-matches git worktree remove against the envelope's tool_input.command,
8
- extracts the target worktree path argument, reads
9
- artifacts/orchestration/epic-orchestrator-state.json, and finds the features[] record
10
- whose worktree_path matches. Allows removal only when that record's merge_status is
11
- merged or worktree_removed. Denies with reason EPIC_WORKTREE_REMOVAL_BLOCKED when the
12
- checkpoint is unreadable, no matching record exists, or merge_status is anything else -
13
- fail-closed, following the enforce-orchestration-preimplementation-gate.ps1 precedent of
14
- treating an unreadable/no-match checkpoint as deny.
7
+ command runs. Regex-matches git worktree remove against the envelope's
8
+ tool_input.command, extracts the target worktree path argument, and allows the
9
+ removal only when one of two checkpoint-only conditions holds. The branches are
10
+ evaluated in this order and are ORed, not ANDed: the first that authorizes wins and
11
+ the second is not consulted.
12
+
13
+ 1. Epic path: artifacts/orchestration/epic-orchestrator-state.json carries a
14
+ features[] record whose worktree_path matches the removal target and whose
15
+ merge_status is merged or worktree_removed.
16
+ 2. Parallel path: artifacts/orchestration/parallel-orchestrator-state.json has
17
+ route_id == "parallel" and carries an items[] entry whose worktree_path matches
18
+ the removal target and whose merge_status is merged or worktree_removed.
19
+
20
+ Otherwise the command is denied with reason EPIC_WORKTREE_REMOVAL_BLOCKED. The gate
21
+ is fail-closed in every failure mode: neither checkpoint present, either checkpoint
22
+ unparseable, route_id absent or not "parallel", no matching worktree_path, a matched
23
+ record whose merge_status is not in the allowed set, or a matched record carrying no
24
+ merge_status key. The cascade is a disjunction of two positive predicates; no
25
+ negative path returns an allow. An envelope-level anomaly is checked first and denies
26
+ before either checkpoint is read.
27
+
28
+ Both branches key on the worktree PATH because the command names a path, and both
29
+ normalize separators and trim a trailing slash on each side of the comparison, so
30
+ Windows- and POSIX-style paths compare equal. Path is also why the two branches are
31
+ mutually exclusive in practice: an epic run and a parallel run allocate worktrees
32
+ under distinct per-run, per-item paths, so a path recorded in one checkpoint is not a
33
+ path recorded in the other, and adding branch 2 cannot widen what branch 1 authorizes.
34
+ The authorization is a property of the path rather than of the caller, and the safety
35
+ property this gate protects - do not destroy unmerged work - is likewise a property of
36
+ the path's recorded merge state.
37
+
38
+ Accepted residual: artifacts/ is gitignored, so the parallel checkpoint persists after
39
+ a run ends and a stale document remains readable here. For a stale document to
40
+ authorize a removal it should not, a worktree would have to exist at a path
41
+ byte-identical, after normalization, to one it records with merge_status merged or
42
+ worktree_removed. Worktree paths carry a session or timestamp component, so a
43
+ collision is implausible, and where the recorded status is worktree_removed the path
44
+ was already deleted. This is a documented accepted trade, not an unexamined gap; the
45
+ route_id check does not reduce it, because a stale parallel checkpoint legitimately
46
+ declares that route.
47
+
48
+ The sibling gate enforce-parallel-worktree-removal-gate.ps1 fires on the same command
49
+ and owns its own reason prefix. PreToolUse denials are conjunctive, so both gates must
50
+ allow for a removal to proceed; this gate keeps the EPIC_WORKTREE_REMOVAL_BLOCKED
51
+ prefix for both of its branches so transcript attribution stays unambiguous.
15
52
 
16
53
  .NOTES
17
54
  Compatible with PowerShell 7+. No external module dependencies. Filesystem reads go
@@ -24,6 +61,7 @@ param()
24
61
 
25
62
  Import-Module (Join-Path $PSScriptRoot '../lib/hook-payload/HookPayload.psm1') -Force
26
63
  $script:EpicCheckpointPath = 'artifacts/orchestration/epic-orchestrator-state.json'
64
+ $script:ParallelCheckpointPath = 'artifacts/orchestration/parallel-orchestrator-state.json'
27
65
  $script:AllowedMergeStatuses = @('merged', 'worktree_removed')
28
66
 
29
67
  function Get-EpicWorktreeGateCheckpointContent {
@@ -44,6 +82,52 @@ function Get-EpicWorktreeGateCheckpointContent {
44
82
  return (Get-Content -LiteralPath $script:EpicCheckpointPath -Raw)
45
83
  }
46
84
 
85
+ function Get-EpicWorktreeGateParallelCheckpointContent {
86
+ <#
87
+ .SYNOPSIS
88
+ Read the raw JSON text of the parallel-orchestrator checkpoint. Tests mock
89
+ this function (read seam).
90
+ .OUTPUTS
91
+ System.String or $null
92
+ #>
93
+ [CmdletBinding()]
94
+ [OutputType([string])]
95
+ param()
96
+
97
+ if (-not (Test-Path -LiteralPath $script:ParallelCheckpointPath -PathType Leaf)) {
98
+ return $null
99
+ }
100
+ return (Get-Content -LiteralPath $script:ParallelCheckpointPath -Raw)
101
+ }
102
+
103
+ function ConvertFrom-EpicWorktreeGateJson {
104
+ <#
105
+ .SYNOPSIS
106
+ Parse checkpoint JSON text, returning $null on unreadable/invalid content.
107
+ .DESCRIPTION
108
+ Shared by both authorization branches so the two checkpoints are parsed by
109
+ one implementation rather than by duplicated inline logic.
110
+ .PARAMETER Raw
111
+ Raw checkpoint text, or $null when the file does not exist.
112
+ .OUTPUTS
113
+ System.Object or $null
114
+ #>
115
+ [CmdletBinding()]
116
+ param(
117
+ [AllowNull()]
118
+ [string] $Raw
119
+ )
120
+
121
+ if ([string]::IsNullOrWhiteSpace($Raw)) {
122
+ return $null
123
+ }
124
+ try {
125
+ return ($Raw | ConvertFrom-Json -ErrorAction Stop)
126
+ } catch {
127
+ return $null
128
+ }
129
+ }
130
+
47
131
  function Get-EpicWorktreeRemovalCommandPath {
48
132
  <#
49
133
  .SYNOPSIS
@@ -138,6 +222,70 @@ function Test-EpicWorktreeRemovalAllowed {
138
222
  return $script:AllowedMergeStatuses -contains ([string]$FeatureRecord.merge_status)
139
223
  }
140
224
 
225
+ function Test-ParallelCheckpointAllowsWorktreeRemoval {
226
+ <#
227
+ .SYNOPSIS
228
+ Decision logic for the parallel-orchestrator checkpoint path (branch 2).
229
+ .DESCRIPTION
230
+ Allows only when the checkpoint declares the parallel route identity and
231
+ carries an items[] entry whose worktree_path matches the removal target and
232
+ whose merge_status is in the allowed set. Every other shape returns $false,
233
+ so the branch is a positive predicate with no negative path to an allow.
234
+ .PARAMETER Checkpoint
235
+ Parsed parallel-orchestrator checkpoint, or $null when absent/unreadable.
236
+ .PARAMETER WorktreePath
237
+ The target worktree path extracted from the command text.
238
+ .OUTPUTS
239
+ System.Boolean
240
+ #>
241
+ [CmdletBinding()]
242
+ [OutputType([bool])]
243
+ param(
244
+ [AllowNull()]
245
+ $Checkpoint,
246
+
247
+ [AllowNull()]
248
+ [string] $WorktreePath
249
+ )
250
+
251
+ if ($null -eq $Checkpoint -or [string]::IsNullOrWhiteSpace($WorktreePath)) {
252
+ return $false
253
+ }
254
+ $props = @($Checkpoint.PSObject.Properties.Name)
255
+ # Route identity is orchestrator invariant 2, so a document at the parallel path
256
+ # that does not declare it is malformed by the rule's own definition and inert here.
257
+ if ($props -notcontains 'route_id' -or ([string]$Checkpoint.route_id) -ne 'parallel') {
258
+ return $false
259
+ }
260
+ if ($props -notcontains 'items' -or $null -eq $Checkpoint.items) {
261
+ return $false
262
+ }
263
+
264
+ $normalizedTarget = ($WorktreePath -replace '\\', '/').TrimEnd('/')
265
+
266
+ # Scan every recorded item for a worktree_path that matches the removal target;
267
+ # path separators are normalized exactly as the epic branch normalizes them.
268
+ foreach ($item in @($Checkpoint.items)) {
269
+ if ($null -eq $item) {
270
+ continue
271
+ }
272
+ $itemProps = @($item.PSObject.Properties.Name)
273
+ if ($itemProps -notcontains 'worktree_path') {
274
+ continue
275
+ }
276
+ $normalizedItemPath = (([string]$item.worktree_path) -replace '\\', '/').TrimEnd('/')
277
+ if ($normalizedItemPath -ne $normalizedTarget) {
278
+ continue
279
+ }
280
+ if ($itemProps -notcontains 'merge_status') {
281
+ return $false
282
+ }
283
+ return $script:AllowedMergeStatuses -contains ([string]$item.merge_status)
284
+ }
285
+
286
+ return $false
287
+ }
288
+
141
289
  function Get-EpicWorktreeGateAllowDecision {
142
290
  [CmdletBinding()]
143
291
  [OutputType([System.Collections.Specialized.OrderedDictionary])]
@@ -202,22 +350,19 @@ function Invoke-EpicWorktreeRemovalGateDecision {
202
350
 
203
351
  $worktreePath = Get-EpicWorktreeRemovalCommandPath -CommandText $commandText
204
352
 
205
- $checkpointRaw = Get-EpicWorktreeGateCheckpointContent
206
- $checkpoint = $null
207
- if (-not [string]::IsNullOrWhiteSpace($checkpointRaw)) {
208
- try {
209
- $checkpoint = $checkpointRaw | ConvertFrom-Json -ErrorAction Stop
210
- } catch {
211
- $checkpoint = $null
212
- }
213
- }
353
+ $checkpoint = ConvertFrom-EpicWorktreeGateJson -Raw (Get-EpicWorktreeGateCheckpointContent)
214
354
 
215
355
  $featureRecord = Find-EpicWorktreeFeatureRecord -Checkpoint $checkpoint -WorktreePath $worktreePath
216
356
  if (Test-EpicWorktreeRemovalAllowed -FeatureRecord $featureRecord) {
217
357
  return Get-EpicWorktreeGateAllowDecision
218
358
  }
219
359
 
220
- return Get-EpicWorktreeGateBlockDecision -Reason "EPIC_WORKTREE_REMOVAL_BLOCKED: git worktree remove for '$worktreePath' requires a matching epic checkpoint features[] record with merge_status in {merged, worktree_removed}. The checkpoint was unreadable, no matching record was found, or merge_status was not yet safe for removal."
360
+ $parallelCheckpoint = ConvertFrom-EpicWorktreeGateJson -Raw (Get-EpicWorktreeGateParallelCheckpointContent)
361
+ if (Test-ParallelCheckpointAllowsWorktreeRemoval -Checkpoint $parallelCheckpoint -WorktreePath $worktreePath) {
362
+ return Get-EpicWorktreeGateAllowDecision
363
+ }
364
+
365
+ return Get-EpicWorktreeGateBlockDecision -Reason "EPIC_WORKTREE_REMOVAL_BLOCKED: git worktree remove for '$worktreePath' requires either an epic checkpoint features[] record with merge_status in {merged, worktree_removed}, or a parallel-orchestrator checkpoint with route_id == ""parallel"" whose matching items[] record (matched by worktree_path) has merge_status in {merged, worktree_removed}. No checkpoint authorized this removal."
221
366
  }
222
367
 
223
368
  function Invoke-EpicWorktreeRemovalGateEntryPoint {