@danmoisan/drm-copilot-mcp 1.1.12 → 1.1.15

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 +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/lib/ci-gate/Invoke-CiGateParser.ps1 +330 -0
  11. package/resources/claude-customizations/.claude/rules/parallel-orchestration.md +150 -2
  12. package/resources/claude-customizations/.claude/rules/plan-acceptance-gates.md +5 -5
  13. package/resources/claude-customizations/.claude/rules/shell.md +8 -7
  14. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/SKILL.md +8 -8
  15. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup-worktrees.sh +234 -0
  16. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_actions_lib.sh +451 -0
  17. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_detached_lib.sh +301 -0
  18. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_dirt_lib.sh +495 -0
  19. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_enumerate_lib.sh +252 -0
  20. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_lib.sh +496 -0
  21. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_preserve_eol_lib.sh +212 -0
  22. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_preserve_lib.sh +492 -0
  23. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_report_records_lib.sh +476 -0
  24. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_scan_helper.sh +182 -0
  25. package/resources/claude-customizations/.claude/skills/epic-orchestrate/SKILL.md +1 -1
  26. package/resources/claude-customizations/.claude/skills/epic-plan/SKILL.md +11 -0
  27. package/resources/claude-customizations/.claude/skills/orchestrate/SKILL.md +1 -1
  28. package/resources/claude-customizations/.claude/skills/parallel-add/SKILL.md +32 -17
  29. package/resources/claude-customizations/.claude/skills/parallel-plan/SKILL.md +39 -10
  30. package/resources/claude-customizations/config/blast-radius.json +14 -1
  31. package/resources/claude-customizations/pack-manifests/core.json +13 -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-epic-resolution.ps1 +493 -0
  34. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-epic-scope.ps1 +189 -0
  35. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-helpers.ps1 +27 -27
  36. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate.ps1 +14 -27
  37. package/resources/codex-and-agents-customizations/pack-manifests/core.json +2 -0
  38. package/resources/powershell/PoshQC/settings/pester.runsettings.psd1 +16 -0
@@ -0,0 +1,301 @@
1
+ #!/usr/bin/env bash
2
+ # cleanup_worktrees_detached_lib.sh: sourceable function group for detached-HEAD
3
+ # worktree registrations in the cleanup-worktrees tool. A branch-backed worktree is
4
+ # classified by branch name through classify_branch; a detached registration has no
5
+ # branch to classify, so this library classifies it on its own HEAD SHA and reports it
6
+ # as the five-field record WORKTREE|<path>|DETACHED|<state>|<flags>. The branch-backed
7
+ # four-field record WORKTREE|<path>|<branch>|<flags> is unchanged; the detached record
8
+ # replaces it for a detached registration rather than adding a second line.
9
+ #
10
+ # Sourcing contract: this file defines functions only; it never runs work at source
11
+ # time, so the wrapper and the bats suites can source it without side effects. It MUST
12
+ # be sourced after cleanup_worktrees_enumerate_lib.sh and cleanup_worktrees_lib.sh in
13
+ # every context, and additionally after cleanup_worktrees_actions_lib.sh in any context
14
+ # that calls remove_detached_worktree or apply_detached_worktrees, because it calls
15
+ # cleanup_wt_git, parse_worktree_list, normalize_wt_path, compute_protected, the four
16
+ # classification ladder rungs (classify_ancestry, classify_content_neutral,
17
+ # classify_cherry_equivalent, classify_residual_commit), and remove_worktree_safe. Bash
18
+ # resolves function names at call time, so run_report and run_apply may call into this
19
+ # file even though .claude/skills/cleanup-merged-worktrees/scripts/cleanup-worktrees.sh sources it last.
20
+ #
21
+ # Git exit-code capture rule: every git-backed read is captured in the PARENT shell with
22
+ # `|| rc=$?` and fails closed, matching the invariant documented at
23
+ # .claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_actions_lib.sh:19-35. A hard git failure always maps to
24
+ # the ANCESTRY_ERROR state and a non-zero return, never to a MERGED_* verdict and never
25
+ # to a removal.
26
+ #
27
+ # Deliberate non-reuse of classify_branch: its worktree lookup matches on branch name,
28
+ # and a detached record's branch field is the literal DETACHED, so the caller's own
29
+ # detached worktree would escape PROTECTED_CURRENT. It also emits into the BRANCH|
30
+ # namespace and can fabricate SHA-keyed COMMIT| records that cherry_pick_candidates
31
+ # would misread. Protection for a detached candidate is therefore decided BY NORMALIZED
32
+ # PATH against compute_protected's protected-path| records, and only the four ladder
33
+ # rungs (which accept a bare committish) are reused.
34
+ #
35
+ # Detached state vocabulary, exactly one token per classification:
36
+ # MERGED_CLEAN | MERGED_CONTENT_NEUTRAL | MERGED_EQUIVALENT | NOT_MERGED |
37
+ # HAS_UNIQUE_RESIDUALS | PROTECTED_CURRENT | ANCESTRY_ERROR
38
+ # The first three are the delete-eligible allowlist. Removal is never forced and
39
+ # `git worktree prune` is never invoked by this tool.
40
+
41
+ is_detached_candidate() {
42
+ # Return 0 iff a porcelain flag set marks a detached-HEAD removal candidate.
43
+ #
44
+ # The predicate is the porcelain FLAG, not the branch field: emit_record writes the
45
+ # literal DETACHED into the branch field whenever the branch accumulator is empty
46
+ # (.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_enumerate_lib.sh:115-116), which is also true of a
47
+ # bare-repository stanza, and a local branch literally named DETACHED would produce
48
+ # the same branch field with no `detached` flag.
49
+ #
50
+ # Returns 0 iff <flags> contains the `detached` token and contains neither `main`
51
+ # (the main worktree is never a candidate) nor `bare`. Makes no git call.
52
+ #
53
+ # Args: $1 = comma-separated flag set (may be empty).
54
+ local flags=${1:-}
55
+ case ",$flags," in
56
+ *,main,* | *,bare,*) return 1 ;;
57
+ esac
58
+ case ",$flags," in
59
+ *,detached,*) return 0 ;;
60
+ esac
61
+ return 1
62
+ }
63
+
64
+ classify_detached_head() {
65
+ # Classify one detached-HEAD worktree on its own HEAD SHA and echo one state token.
66
+ #
67
+ # Order (load-bearing): the PROTECTED_CURRENT check runs FIRST, by normalized path
68
+ # against compute_protected's protected-path| records, and returns BEFORE any
69
+ # classification git call, so the caller's own detached worktree is never probed for
70
+ # ancestry. The remaining rungs are the ladder from cleanup_worktrees_lib.sh applied
71
+ # to the bare SHA:
72
+ # 1. ancestry -> MERGED_CLEAN
73
+ # 2. content-neutral -> MERGED_CONTENT_NEUTRAL
74
+ # 3. cherry equivalence -> MERGED_EQUIVALENT
75
+ # 4. rename-aware blob fallback: all residuals CONTENT_ON_MAIN -> MERGED_EQUIVALENT
76
+ # 5. remaining unique residuals -> HAS_UNIQUE_RESIDUALS when the HEAD was partially
77
+ # incorporated on main (a cherry `-` line or a CONTENT_ON_MAIN residual), else
78
+ # NOT_MERGED.
79
+ # No BRANCH| or COMMIT| record is emitted, and classify_branch is never called.
80
+ #
81
+ # Args: $1 = detached HEAD sha, $2 = worktree path.
82
+ # Returns 0 normally; 2 on any hard git failure, which always echoes ANCESTRY_ERROR.
83
+ local head="$1" path="$2"
84
+ local cpout cprc=0 pline norm
85
+ # Guarded parent-shell capture: a compute_protected hard failure must fail closed as
86
+ # ANCESTRY_ERROR, not degrade to a weakened (empty) protected set that could let the
87
+ # caller's own worktree reach a delete-eligible verdict.
88
+ cpout=$(compute_protected) || cprc=$?
89
+ if ((cprc != 0)); then
90
+ printf 'ANCESTRY_ERROR\n'
91
+ return 2
92
+ fi
93
+ norm=$(normalize_wt_path "$path")
94
+ while IFS= read -r pline; do
95
+ [[ $pline == protected-path\|* ]] || continue
96
+ if [[ -n $norm && ${pline#protected-path|} == "$norm" ]]; then
97
+ printf 'PROTECTED_CURRENT\n'
98
+ return 0
99
+ fi
100
+ done <<<"$cpout"
101
+ local v
102
+ v=$(classify_ancestry "$head")
103
+ case "$v" in
104
+ MERGED_CLEAN)
105
+ printf 'MERGED_CLEAN\n'
106
+ return 0
107
+ ;;
108
+ ANCESTRY_ERROR)
109
+ printf 'ANCESTRY_ERROR\n'
110
+ return 2
111
+ ;;
112
+ esac
113
+ v=$(classify_content_neutral "$head")
114
+ case "$v" in
115
+ MERGED_CONTENT_NEUTRAL)
116
+ printf 'MERGED_CONTENT_NEUTRAL\n'
117
+ return 0
118
+ ;;
119
+ CONTENT_NEUTRAL_ERROR)
120
+ printf 'ANCESTRY_ERROR\n'
121
+ return 2
122
+ ;;
123
+ esac
124
+ local ce
125
+ ce=$(classify_cherry_equivalent "$head")
126
+ if [[ $ce == "CHERRY_ERROR" || $ce == "DIFF_TREE_ERROR" ]]; then
127
+ printf 'ANCESTRY_ERROR\n'
128
+ return 2
129
+ fi
130
+ if [[ $ce == "MERGED_EQUIVALENT" ]]; then
131
+ printf 'MERGED_EQUIVALENT\n'
132
+ return 0
133
+ fi
134
+ # Residual `+` commits exist; resolve each via the rename-aware blob tier.
135
+ local sha verdict unique_count=0 content_count=0
136
+ while IFS= read -r pline; do
137
+ [[ $pline == RESIDUAL\ * ]] || continue
138
+ sha=${pline#RESIDUAL }
139
+ verdict=$(classify_residual_commit "$head" "$sha")
140
+ if [[ $verdict == "RESIDUAL_ERROR" ]]; then
141
+ printf 'ANCESTRY_ERROR\n'
142
+ return 2
143
+ fi
144
+ if [[ $verdict == UNIQUE\|* ]]; then
145
+ unique_count=$((unique_count + 1))
146
+ elif [[ $verdict == "CONTENT_ON_MAIN" ]]; then
147
+ content_count=$((content_count + 1))
148
+ fi
149
+ done <<<"$ce"
150
+ if ((unique_count == 0)); then
151
+ # Every residual was content-on-main; the HEAD is content-equivalent-merged.
152
+ printf 'MERGED_EQUIVALENT\n'
153
+ return 0
154
+ fi
155
+ # Partial-merge signal, read from the already-captured cherry verdict rather than a
156
+ # second `git cherry` invocation whose exit code would be discarded in a pipeline.
157
+ local minus_present=0
158
+ [[ $ce == *MINUS_PRESENT* ]] && minus_present=1
159
+ if ((minus_present == 1)) || ((content_count > 0)); then
160
+ printf 'HAS_UNIQUE_RESIDUALS\n'
161
+ else
162
+ printf 'NOT_MERGED\n'
163
+ fi
164
+ return 0
165
+ }
166
+
167
+ report_detached_worktrees() {
168
+ # Emit one five-field detached registration record per detached candidate.
169
+ #
170
+ # Consumes parse_worktree_list output (the caller's already-guarded capture, so a
171
+ # worktree-list hard failure has aborted upstream before this function is reached).
172
+ # Records are emitted in parse_worktree_list order; no sort is applied, because the
173
+ # branch-backed emission loop this replaces is likewise porcelain-ordered.
174
+ #
175
+ # The record's head field must be bound in the `read`; both pre-existing emission
176
+ # sites discard it with the `_` placeholder.
177
+ #
178
+ # Args: $1 = parse_worktree_list output.
179
+ # Returns the maximum classify_detached_head return code (0, or 2 when any candidate
180
+ # hard-failed), so the caller can fold a detached hard failure into its own rc.
181
+ local wlout="$1" record wpath whead wflags state crc rc=0
182
+ while IFS= read -r record; do
183
+ [[ -z $record ]] && continue
184
+ IFS='|' read -r wpath whead _ wflags <<<"$record"
185
+ is_detached_candidate "$wflags" || continue
186
+ crc=0
187
+ state=$(classify_detached_head "$whead" "$wpath") || crc=$?
188
+ printf 'WORKTREE|%s|DETACHED|%s|%s\n' "$wpath" "$state" "$wflags"
189
+ if ((crc > rc)); then
190
+ rc=$crc
191
+ fi
192
+ done <<<"$wlout"
193
+ return "$rc"
194
+ }
195
+
196
+ reverify_detached_delete_eligible() {
197
+ # Same-process re-verification immediately before a destructive action.
198
+ #
199
+ # Re-runs classify_detached_head in-process and confirms the FRESH state is still
200
+ # delete-eligible: MERGED_CLEAN | MERGED_CONTENT_NEUTRAL | MERGED_EQUIVALENT. Any
201
+ # other verdict, and any hard git failure, emits
202
+ # ACTION|worktree-remove|<path>|BLOCKED-REVERIFY and returns 1. This is the detached
203
+ # counterpart of reverify_delete_eligible, which re-verifies by branch name.
204
+ #
205
+ # Args: $1 = detached HEAD sha, $2 = worktree path.
206
+ # Returns 0 when the fresh verdict is delete-eligible; 1 otherwise.
207
+ local head="$1" path="$2" state crc=0
208
+ # Guarded parent-shell capture: a hard failure maps explicitly to BLOCKED-REVERIFY
209
+ # and return 1, in addition to the state-token allowlist below.
210
+ state=$(classify_detached_head "$head" "$path") || crc=$?
211
+ if ((crc != 0)); then
212
+ printf 'ACTION|worktree-remove|%s|BLOCKED-REVERIFY\n' "$path"
213
+ return 1
214
+ fi
215
+ case "$state" in
216
+ MERGED_CLEAN | MERGED_CONTENT_NEUTRAL | MERGED_EQUIVALENT)
217
+ return 0
218
+ ;;
219
+ esac
220
+ printf 'ACTION|worktree-remove|%s|BLOCKED-REVERIFY\n' "$path"
221
+ return 1
222
+ }
223
+
224
+ remove_detached_worktree() {
225
+ # Remove one delete-eligible detached worktree, in a load-bearing order:
226
+ # 1. locked -> emit ACTION|worktree-remove|<path>|BLOCKED-LOCKED, invoke NO git
227
+ # command, return 1.
228
+ # 2. prunable -> report-only: return 0 with no output and no git command. This tool
229
+ # never executes worktree pruning.
230
+ # 3. re-verify with reverify_detached_delete_eligible; return 1 on a flipped verdict.
231
+ # 4. remove_worktree_safe "<path>" and propagate its return.
232
+ # Steps 1 and 2 are pure string tests over the already-read porcelain flags and MUST
233
+ # precede every git invocation, so "no removal was attempted" is observable as an
234
+ # empty argv log rather than inferred from a report line.
235
+ #
236
+ # remove_worktree_safe is consumed as an opaque contract and is not modified: it owns
237
+ # the non-forced `git worktree remove`, the DIRTY| lines, and the BLOCKED-DIRTY result
238
+ # token. This function emits no DIRTY| line of its own. The forced-removal flag is
239
+ # never passed.
240
+ #
241
+ # Args: $1 = worktree path, $2 = detached HEAD sha, $3 = porcelain flag set.
242
+ # Returns 0 on successful removal or a prunable skip; 1 when blocked.
243
+ local path="$1" head="$2" flags="$3"
244
+ case ",$flags," in
245
+ *,locked,*)
246
+ printf 'ACTION|worktree-remove|%s|BLOCKED-LOCKED\n' "$path"
247
+ return 1
248
+ ;;
249
+ esac
250
+ case ",$flags," in
251
+ *,prunable,*)
252
+ return 0
253
+ ;;
254
+ esac
255
+ reverify_detached_delete_eligible "$head" "$path" || return 1
256
+ remove_worktree_safe "$path"
257
+ }
258
+
259
+ apply_detached_worktrees() {
260
+ # Apply-mode driver half for detached registrations: classify, report, then remove
261
+ # the delete-eligible ones.
262
+ #
263
+ # For each detached candidate it classifies once, emits
264
+ # WORKTREE|<path>|DETACHED|<state>|<flags> from THAT verdict before deciding removal,
265
+ # and only then acts. The record emission is part of this function's contract, not an
266
+ # optional extra: the apply-mode emission loop in cleanup_worktrees_actions_lib.sh
267
+ # skips detached candidates, so this is the only producer of a detached registration
268
+ # record in apply mode and each mode therefore emits exactly one record per detached
269
+ # registration. classify_detached_head is not called a second time for the record.
270
+ # The separate re-classification inside reverify_detached_delete_eligible is the
271
+ # same-process re-verification gate, not a duplicate of this reporting call.
272
+ #
273
+ # A hard failure sets rc=1 and performs no removal. A delete-eligible verdict calls
274
+ # remove_detached_worktree and sets rc=1 if it fails. Any other state performs no
275
+ # removal and emits no further line.
276
+ #
277
+ # Args: $1 = parse_worktree_list output.
278
+ # Returns 0 when every candidate was handled without failure or block; 1 otherwise.
279
+ local wlout="$1" record wpath whead wflags state crc rc=0
280
+ while IFS= read -r record; do
281
+ [[ -z $record ]] && continue
282
+ IFS='|' read -r wpath whead _ wflags <<<"$record"
283
+ is_detached_candidate "$wflags" || continue
284
+ crc=0
285
+ state=$(classify_detached_head "$whead" "$wpath") || crc=$?
286
+ printf 'WORKTREE|%s|DETACHED|%s|%s\n' "$wpath" "$state" "$wflags"
287
+ if ((crc != 0)); then
288
+ # A hard classification failure never triggers a removal; its state is an
289
+ # error state, not on the delete-eligible allowlist.
290
+ rc=1
291
+ continue
292
+ fi
293
+ case "$state" in
294
+ MERGED_CLEAN | MERGED_CONTENT_NEUTRAL | MERGED_EQUIVALENT)
295
+ remove_detached_worktree "$wpath" "$whead" "$wflags" || rc=1
296
+ ;;
297
+ *) : ;;
298
+ esac
299
+ done <<<"$wlout"
300
+ return "$rc"
301
+ }