@danmoisan/drm-copilot-mcp 1.0.21 → 1.0.23

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 (43) hide show
  1. package/out/mcp-server.js +1730 -139
  2. package/package.json +1 -1
  3. package/resources/claude-customizations/.claude/agent-memory/epic-orchestrator/MEMORY.md +5 -1
  4. package/resources/claude-customizations/.claude/agent-memory/epic-orchestrator/feedback_commit_push_memory_before_pr.md +48 -2
  5. package/resources/claude-customizations/.claude/agent-memory/epic-orchestrator/feedback_no_sendmessage_tool.md +35 -0
  6. package/resources/claude-customizations/.claude/agent-memory/epic-orchestrator/feedback_worktree_isolation_branches_from_main.md +45 -0
  7. package/resources/claude-customizations/.claude/agents/parallel-orchestrator.md +257 -0
  8. package/resources/claude-customizations/.claude/agents/parallel-planner.md +183 -0
  9. package/resources/claude-customizations/.claude/hooks/enforce-epic-invocation-origin.ps1 +23 -11
  10. package/resources/claude-customizations/.claude/hooks/enforce-parallel-abandon-gate.ps1 +259 -0
  11. package/resources/claude-customizations/.claude/hooks/enforce-parallel-cohort-barrier.ps1 +499 -0
  12. package/resources/claude-customizations/.claude/hooks/enforce-parallel-drift-gate-helpers.ps1 +302 -0
  13. package/resources/claude-customizations/.claude/hooks/enforce-parallel-drift-gate.ps1 +359 -0
  14. package/resources/claude-customizations/.claude/hooks/enforce-parallel-worktree-removal-gate.ps1 +244 -0
  15. package/resources/claude-customizations/.claude/lib/bash/compute-cohorts.sh +143 -0
  16. package/resources/claude-customizations/.claude/lib/bash/compute-concurrency-batches.sh +122 -0
  17. package/resources/claude-customizations/.claude/lib/bash/parallel-cohorts.sh +330 -0
  18. package/resources/claude-customizations/.claude/lib/bash/parallel-common.sh +238 -0
  19. package/resources/claude-customizations/.claude/lib/bash/parallel-items-validate.sh +244 -0
  20. package/resources/claude-customizations/.claude/lib/bash/parallel-manifest-validate.sh +187 -0
  21. package/resources/claude-customizations/.claude/lib/bash/parallel-yaml-emit.sh +340 -0
  22. package/resources/claude-customizations/.claude/lib/bash/parallel-yaml-scan.sh +335 -0
  23. package/resources/claude-customizations/.claude/lib/bash/validate-parallel-manifest.sh +134 -0
  24. package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadius.psm1 +379 -0
  25. package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusConfig.psm1 +491 -0
  26. package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusExtraction.psm1 +490 -0
  27. package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusGlob.psm1 +429 -0
  28. package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusValidation.psm1 +366 -0
  29. package/resources/claude-customizations/.claude/rules/parallel-orchestration.md +184 -0
  30. package/resources/claude-customizations/.claude/rules/shell.md +7 -2
  31. package/resources/claude-customizations/.claude/settings.json +28 -0
  32. package/resources/claude-customizations/.claude/skills/parallel-add/SKILL.md +152 -0
  33. package/resources/claude-customizations/.claude/skills/parallel-close/SKILL.md +93 -0
  34. package/resources/claude-customizations/.claude/skills/parallel-orchestrate/SKILL.md +971 -0
  35. package/resources/claude-customizations/.claude/skills/parallel-plan/SKILL.md +461 -0
  36. package/resources/claude-customizations/.claude/skills/parallel-remove/SKILL.md +176 -0
  37. package/resources/claude-customizations/.claude/skills/parallel-run/SKILL.md +56 -0
  38. package/resources/claude-customizations/config/blast-radius.json +16 -0
  39. package/resources/claude-customizations/config/orchestration-routing.json +355 -0
  40. package/resources/claude-customizations/pack-manifests/core.json +32 -1
  41. package/resources/codex-and-agents-customizations/.codex/config.toml +1 -1
  42. package/resources/config/orchestration-routing.json +22 -0
  43. package/resources/powershell/PoshQC/settings/pester.runsettings.psd1 +29 -0
@@ -0,0 +1,461 @@
1
+ ---
2
+ name: parallel-plan
3
+ description: Prepare a set of thematically unrelated items for concurrent execution before any execution begins - item intake over issue numbers and potential-entry paths, concurrent preparation-mode child orchestrator delegations, blast-radius computation and V1-V3 validation, cohort seeding with a recomputation-parity check, run-manifest and planner-checkpoint authoring, and the parallel-orchestrator kickoff artifact.
4
+ argument-hint: "[items: issue numbers and/or potential-entry paths]"
5
+ context: fork
6
+ agent: parallel-planner
7
+ ---
8
+
9
+ # Parallel Plan Skill
10
+
11
+ A user invocation (`/parallel-plan <slug> <item> [<item> ...]`) forks the `parallel-planner` agent
12
+ with this procedure in context. The run slug and item list for this run are:
13
+
14
+ $ARGUMENTS
15
+
16
+ This skill frames work for the `parallel-planner` agent, parallel to how
17
+ `.claude/skills/epic-plan/SKILL.md` frames work for `epic-planner`. The `parallel` surface
18
+ schedules thematically unrelated items by computed blast-radius contention: there is no worthiness
19
+ assessment, no operator-supplied ordering, and no shared branch into which item work merges.
20
+ Planning ends at preflight clearance and cohort seeding; no atomic execution, PR authoring, or CI
21
+ monitoring occurs under this skill.
22
+
23
+ ## Prerequisites
24
+
25
+ Before proceeding, `parallel-planner` must:
26
+
27
+ 1. Read `CLAUDE.md` for repository tone policy and architectural context.
28
+ 2. Read applicable `.claude/rules/` files for the languages in scope, including
29
+ `.claude/rules/parallel-orchestration.md`, which is the schema authority for the run manifest,
30
+ both parallel checkpoints, and the nine parallel enums.
31
+ 3. Read the policy files listed in the compliance reading order section of `CLAUDE.md`.
32
+
33
+ ## Item Intake
34
+
35
+ Invocation shape: `/parallel-plan <slug> <item> [<item> ...]`, where each `<item>` is either a
36
+ GitHub issue number (already-promoted work) or a potential-entry path (unpromoted work). This is
37
+ the same intake domain as `/parallel-add`, so initial intake here and F6's add operation accept
38
+ identical forms.
39
+
40
+ - **Promotion.** Unpromoted items are promoted by their own preparation-mode child, not by the
41
+ planner. The `preparation` route already carries the promotion MCP tools (`new_potential_entry`,
42
+ `potential_to_issue`, `new_active_feature_folder`).
43
+ - **`issue_num` resolution.** `issue_num` is the primary key for every item reference. It is known
44
+ at intake for issue-number items. For potential-entry items, record negative placeholders in
45
+ intake order (`-1`, `-2`, ...) and back-fill the real number from each child's promotion receipt
46
+ as preparation completes. Ordering is safe by construction: cohort seeding requires declared
47
+ radii, radii require approved plans, and plans require promotion, so every placeholder resolves
48
+ before seeding runs.
49
+ - **Fully resolved before kickoff.** The manifest is committed in fully resolved form — no negative
50
+ `issue_num` remaining — before the kickoff artifact is written.
51
+ - **`feature_folder`.** Recorded at intake as a resolvable-hint basename, then resolved to a
52
+ concrete `docs/features/active/<basename>` path after promotion with any lifecycle prefix
53
+ stripped, per the `epic-orchestrate` convention. The concrete location is additionally fixed by
54
+ the per-item `branch_name` recorded in the checkpoint.
55
+ - **`kind`.** Record `kind: feature | bug` at intake from the item source (issue labels, or the
56
+ potential entry's declared kind). When the source is indeterminate, default to `feature` and note
57
+ the choice `[recommendation, not upstream-constrained]`.
58
+
59
+ The operator is never asked for ordering edges, cohort assignments, or a worthiness verdict.
60
+ Intake proceeds directly to preparation fan-out.
61
+
62
+ ## Preparation Fan-Out
63
+
64
+ One preparation-mode `Agent(orchestrator)` run per item. Preparation produces documents and plans
65
+ rather than code, and items carry no ordering constraint, so launch ALL item preparations
66
+ concurrently: one message, N `Agent` calls, each `isolation: "worktree"` and
67
+ `run_in_background: true`. Create each preparation worktree's branch from `origin/main`.
68
+
69
+ Each delegation prompt includes this literal kickoff line, followed by the model-budget marker
70
+ line:
71
+
72
+ > `Preparation mode: true. route_id: preparation. parallel_slug: <slug>. Perform promotion, research, feature documents (spec.md, user-story.md), atomic planning, and preflight clearance only. Atomic execution, PR authoring, and CI monitoring are out of scope for this run and are executed later by parallel-orchestrator. After the atomic-executor preflight returns PREFLIGHT: ALL CLEAR, commit the feature folder and plan to the current branch, push the current branch to origin, set out-of-scope step statuses to not-applicable, set next_step to S5_atomic_execution, and stop, reporting the plan-path and preflight status.`
73
+ >
74
+ > `model_budget.fable_policy: <disabled|available|preferred>.`
75
+
76
+ Properties of that line, each individually load-bearing:
77
+
78
+ - The markers `Preparation mode: true.` and `route_id: preparation.` are reused verbatim. Route
79
+ selection is marker-driven, so no issuer identity is required.
80
+ - `parallel_slug: <slug>.` replaces the epic context fields.
81
+ - The push instruction is an addition to the planner's own prompt, not to the child contract text
82
+ in `.claude/skills/orchestrate/SKILL.md`. It is required so each item's prepared work is durable
83
+ before its worktree is removed.
84
+ - Downstream attribution reads "executed later by parallel-orchestrator". The planner authors its
85
+ own prompt; the `orchestrate` skill text is untouched.
86
+ - The `model_budget.fable_policy` marker line is appended per the pattern in
87
+ `.claude/skills/epic-orchestrate/SKILL.md` `## Model Selection`. The default is `disabled` when
88
+ the marker is absent.
89
+
90
+ **Deliberate omissions.** The kickoff line above carries neither mode marker. It contains no
91
+ `Epic mode: true`, so `enforce-epic-wave-barrier.ps1` — which gates execution-phase delegations —
92
+ does not apply to preparation. It contains no `Parallel mode: true`, so F7's future cohort-barrier
93
+ hook, which matches that marker, will not gate preparation either. Both omissions are intentional
94
+ and must be preserved verbatim when the line is emitted.
95
+
96
+ **No edit to shared surfaces.** No edit is made to `.claude/skills/orchestrate/SKILL.md` or to
97
+ `config/orchestration-routing.json`, including the `preparation` route. The route mechanism is
98
+ marker-driven; the child contract's "commit ... to the current branch" wording is satisfied by a
99
+ branch created off `origin/main`; and `routes.preparation` declares no epic-specific required
100
+ agent, skill, or MCP tool.
101
+
102
+ **Collected per child at termination:** `plan-path`, preflight status, the promotion receipt (the
103
+ `issue_num` back-fill source), the model-routing receipt with `logical_agent: "orchestrator"`, the
104
+ topology receipt, `branch_name`, and `worktree_path`. There is no fan-in merge step: the planner
105
+ fetches and records each pushed item branch, back-fills `issue_num` into the manifest on
106
+ `parallel/<slug>-plan`, and updates the checkpoint.
107
+
108
+ ## Artifact Home
109
+
110
+ **Per-item artifacts.** Each item's prepared feature folder and approved atomic plan live on that
111
+ item's own feature branch, created from `origin/main` at preparation time, committed by the
112
+ unchanged `route_id: preparation` terminal step, pushed to `origin` before its worktree is removed,
113
+ and reused unchanged as the item's execution branch. Record `branch_name` and `worktree_path` per
114
+ item in the checkpoint.
115
+
116
+ **Run-level artifacts.** `docs/features/parallel/<slug>/parallel.md` (the run manifest) and
117
+ `docs/features/parallel/<slug>/parallel-kickoff.md` (the durable kickoff copy) live on the
118
+ planner-owned branch `parallel/<slug>-plan`, created off `origin/main` and pushed. That branch is
119
+ explicitly not an integration branch: no item branch ever merges into it, it never merges into any
120
+ item branch, and it holds only `docs/features/parallel/<slug>/**`, a subtree no item's blast radius
121
+ may include. Each item opens its own pull request against `main`.
122
+
123
+ **Read access.** Readers — validators and the future `parallel-orchestrator` — reach both artifact
124
+ classes by ref: `git fetch origin <branch>` followed by `git show <ref>:<path>`, without checking
125
+ the ref out, per the technique documented in `.claude/skills/epic-run/SKILL.md`.
126
+
127
+ Three residual risks are recorded rather than eliminated:
128
+
129
+ 1. **Stale execution base.** An item branch created at preparation time is based on an older `main`
130
+ tip by the time its cohort executes. Mitigation is F5-owned (the execution-phase child merges
131
+ `origin/main` at start, and cohort construction keeps peers non-conflicting); real overlap is
132
+ caught by F8 drift detection. This skill records the branch-reuse contract only.
133
+ 2. **Branch accumulation on withdrawal.** Withdrawn or abandoned items leave pushed preparation
134
+ branches. F6's `--disposition abandon` path is expected to delete the branch; the cleanup
135
+ expectation is recorded here so F6 can implement it.
136
+ 3. **Per-branch git-integrity requirement — F4-owned.** The readiness gate's git-integrity check
137
+ must verify committed plan blobs against each per-item branch ref plus the
138
+ `parallel/<slug>-plan` ref, rather than against a single shared ref. This obligation belongs to
139
+ the planner surface, not to the schema feature: `.claude/rules/parallel-orchestration.md` states
140
+ that F3's `require_ready_for_execution` gate is structural only and leaves git-integrity checks,
141
+ launch-evidence binding, and kickoff-contract cross-checks to F4.
142
+
143
+ ## Radius Computation and Validation
144
+
145
+ Reach blast-radius derivation, validation, and contention through the **destination-runtime
146
+ PowerShell port** under `.claude/lib/blast-radius/`, which is published by push-down and needs no
147
+ Python interpreter:
148
+
149
+ ```powershell
150
+ Import-Module .claude/lib/blast-radius/BlastRadius.psm1 -Force
151
+ ```
152
+
153
+ The facade re-exports the five functions this skill needs: `Get-PlanPaths` (port of
154
+ `extract_plan_paths`), `Get-BlastRadius` (port of `derive_blast_radius`),
155
+ `Get-BlastRadiusFromObservedPaths` (port of `radius_from_observed_paths`), `Test-BlastRadius`
156
+ (port of `validate_blast_radius`), and `Test-BlastRadiusConflict` (port of `conflicts`). Wrap a
157
+ call to `Test-BlastRadius` in `@(...)`: it writes its findings to the pipeline, so a zero-element
158
+ result writes nothing and a one-element result writes a single object.
159
+
160
+ The truth table the port reads is `config/blast-radius.json`, which push-down publishes into the
161
+ destination workspace alongside `.claude`.
162
+
163
+ The Python modules named below remain the repository authority and the parity reference; they are
164
+ cited for their contract, not invoked on the destination-runtime path. Landed contract, consumed
165
+ as-is and never reimplemented here:
166
+
167
+ - **Derivation.**
168
+ `derive_blast_radius(plan_text, spec_text, feature_folder, config, *, source, computed_at) -> BlastRadius`
169
+ in `scripts/dev_tools/compute_blast_radius.py`. It takes the approved atomic plan's **document
170
+ text** and the feature `spec.md`'s **document text**, the feature folder name, and the parsed
171
+ `config/blast-radius.json` truth table. It does not take file paths: read the documents and pass
172
+ their text.
173
+ - **Serialized shape.** `BlastRadius.to_dict()` yields exactly the key set
174
+ `("paths", "modules", "shared_surfaces", "contracts", "source", "computed_at")`, which is the
175
+ shape both the manifest and the checkpoint record.
176
+ - **Validation.** `validate_blast_radius(radius, plan_text, config, *, tracked_file_count)` in
177
+ `scripts/dev_tools/_blast_radius_validation.py` returns findings over three rules:
178
+ `RULE_COVERAGE = "V1"`, `RULE_SHARED_SURFACE = "V2"`, and `RULE_OVER_BREADTH = "V3"`. Each finding
179
+ carries a severity of `Blocking` or `Advisory`.
180
+ - **Contention.** `conflicts(a, b, config) -> ConflictResult`, re-exported from
181
+ `compute_blast_radius.py`. The signature takes three arguments; the third is the parsed
182
+ `config/blast-radius.json`. Reasons come from the fixed vocabulary
183
+ `{path_overlap, module_overlap, shared_surface_overlap, contract_dependency}`, and the relation
184
+ fails closed.
185
+
186
+ **The F1a corrections (issue #452, merged PR #453) are load-bearing.** Derivation now reaches
187
+ separator-free repository-root shared surfaces from plan and spec text, admitting such a token only
188
+ as an exact ordinal member of the configured `shared_surfaces` list in `config/blast-radius.json`;
189
+ and the contention path comparison now honours listed-directory prefixes on both sides, aligning
190
+ with `is_path_subsumed`. Both corrections move results in the fail-closed direction — they report
191
+ more contention, not less. Do not work around either correction, and do not narrow a radius in
192
+ order to suppress a conflict edge they produce.
193
+
194
+ ### Planner procedure
195
+
196
+ 1. After an item's plan is approved and preflight-clear, read the approved plan text and the
197
+ feature `spec.md` text, derive the radius with `source: "declared"`, and record it on the item.
198
+ The `declared` radius is the authoritative input to scheduling.
199
+ 2. Validate the radius and record the findings under the item's `radius_validation` entry.
200
+ 3. **V1 (coverage) or V2 (shared-surface enumeration) Blocking failure.** The item does NOT
201
+ transition to `prepared`. Record the findings in the checkpoint and issue a follow-up
202
+ preparation-mode delegation for that item carrying the findings as plan-revision instructions —
203
+ the same iterate-until-clear posture the child already applies to preflight. The item is
204
+ re-planned, not rejected. Withdrawal is a caller decision made through F6's remove operation and
205
+ is never a planner default.
206
+ 4. **V3 (over-breadth) Advisory.** Record it in the checkpoint and surface it in the completion
207
+ report. It has no state effect.
208
+ 5. **Readiness conjunction.** `prepared` requires BOTH `preflight_status == "PREFLIGHT: ALL CLEAR"`
209
+ AND a `declared` radius that passed V1 and V2.
210
+
211
+ Derivation, the V1-V3 rules, and the contention relation are implemented upstream. This skill calls
212
+ them; it defines none of them.
213
+
214
+ ## Cohort Seeding
215
+
216
+ Reach cohort computation through the **destination-runtime bash entry point** under
217
+ `.claude/lib/bash/`, which is published by push-down and needs no Python interpreter:
218
+
219
+ ```bash
220
+ bash .claude/lib/bash/compute-cohorts.sh --keys "<k1> <k2> ..." --edges "<a>:<b> <a>:<b> ..."
221
+ ```
222
+
223
+ `--edges` is optional; omitting it, or passing an empty string, means the conflict graph has no
224
+ edges. The entry point prints a compact JSON array of arrays on stdout, identical to Python
225
+ `json.dumps(..., separators=(",", ":"))`. On malformed input it prints the reference
226
+ implementation's exact message on stderr and exits 1; a token outside the accepted integer lexis
227
+ `-?(0|[1-9][0-9]*)` is rejected fail-closed with exit 2.
228
+
229
+ Landed contract, mirrored byte for byte by the bash entry point:
230
+
231
+ - `compute_cohorts(item_keys, conflict_edges) -> list[list[int]]` in
232
+ `scripts/dev_tools/parallel_cohort_computation.py` is the repository authority and the parity
233
+ reference. The signature accepts exactly two parameters, `item_keys: Iterable[int]` and
234
+ `conflict_edges: Iterable[tuple[int, int]]`. There is no third parameter and nothing further to
235
+ supply at seeding time.
236
+ - The return value is a plain list of lists in deterministic Welsh-Powell order: vertices are
237
+ visited by the composite key `(-degree, item_key)` ascending — descending distinct-neighbour
238
+ degree with ties broken by ascending item key — and each vertex takes the lowest cohort index not
239
+ already held by one of its neighbours.
240
+ - Recoloring support belongs to F6 and F8, which is why the landed seeding signature needs no
241
+ additional state input.
242
+
243
+ **Mapping to the recorded shape.** This planner maps the returned list of lists into the F3-owned
244
+ `cohorts[]` object shape, supplying `index` from the outer-list position and `generation: 0` itself.
245
+ The library returns the partition; the planner supplies the record fields.
246
+
247
+ ### Seeding procedure
248
+
249
+ 1. Invoke `compute-cohorts.sh` exactly once per plan run, over the full conflict graph, after every
250
+ item is `prepared` and radius-validated. Derive the conflict edge set by applying
251
+ `Test-BlastRadiusConflict` to every unordered pair of `declared` radii, then pass the pairs as
252
+ `--edges "<a>:<b> ..."` and the item keys as `--keys "<k1> <k2> ..."`.
253
+ 2. Record `cohorts[]` at `generation: 0`, each cohort's `item_keys[]` sorted ascending.
254
+ 3. Record `conflict_edges[]` as `{a, b, reason}` entries for auditability.
255
+ 4. Record `recolor_generation: 0` and `current_cohort: 0`.
256
+ 5. Record `max_concurrency` — default 4, bounded 1 through 8 by the F3 schema — without enforcing
257
+ it. Enforcement is F5's, through
258
+ `bash .claude/lib/bash/compute-concurrency-batches.sh --keys "<k1> ..." --max-concurrency <n>`
259
+ (the bash port of `compute_concurrency_batches(cohort_item_keys, max_concurrency)`), which fills
260
+ slots in ascending item-key order. Recoloring under add, remove, or drift mutation is F6 and F8
261
+ scope. This skill performs seeding only.
262
+
263
+ ### Recomputation parity (planner-owned check)
264
+
265
+ Planner invariant P5 in `.claude/rules/parallel-orchestration.md` is deliberately absent from the
266
+ F3 validator and states that recomputation parity against the cohort-computation module is the
267
+ planner-surface feature's check — the analogue of the epic planner's wave-number cross-check. This
268
+ skill discharges that obligation as documented procedure, not as a new module:
269
+
270
+ 1. After writing `cohorts[]` into the checkpoint and **before** emitting the kickoff artifact,
271
+ re-invoke `compute_cohorts` over exactly the `item_keys` and `conflict_edges` recorded in the
272
+ checkpoint.
273
+ 2. Assert that the recomputed list of lists maps to exactly the recorded `cohorts[]` at
274
+ `generation: 0`: the same partition, the same `index` assignment, and the same ascending
275
+ `item_keys[]` ordering.
276
+ 3. A mismatch is a **Blocking** condition. Stop the run and report the mismatch. Do not
277
+ auto-correct the recorded cohorts, and do not emit the kickoff artifact.
278
+
279
+ No production module is added for this check; it is a re-invocation of the landed library.
280
+
281
+ ## Manifest Authoring
282
+
283
+ Write `docs/features/parallel/<slug>/parallel.md` conforming to the F3-owned frontmatter schema
284
+ recorded in `.claude/rules/parallel-orchestration.md` (manifest invariants M1-M7):
285
+
286
+ - `parallel` — the run slug, a non-empty string.
287
+ - `mode` — `closed` or `open`; defaults to `closed` when absent.
288
+ - `max_concurrency` — an integer from 1 through 8; defaults to `4` when absent.
289
+ - `created_at` — a non-empty ISO-8601 string.
290
+ - `items[]` — one entry per item, each carrying `issue_num` (a positive integer, unique across
291
+ items), `feature_folder` (a non-empty string), `kind` (`feature` or `bug`), `state`, and
292
+ `blast_radius` carrying `paths`, `modules`, `shared_surfaces`, `contracts`, `source: "declared"`,
293
+ and `computed_at`.
294
+
295
+ The manifest carries no `depends_on` field at any level and no top-level `integration_branch`
296
+ field; both are prohibited-key rejections in the schema. Commit it to `parallel/<slug>-plan` in
297
+ fully resolved form — every negative placeholder `issue_num` replaced by its promoted number —
298
+ before the kickoff artifact is written.
299
+
300
+ Validate the manifest with the **destination-runtime bash entry point**, which is published by
301
+ push-down and needs no Python interpreter:
302
+
303
+ ```bash
304
+ bash .claude/lib/bash/validate-parallel-manifest.sh <manifest-path>
305
+ ```
306
+
307
+ It prints validation errors one per line on stdout and exits 0 for a valid manifest, 1 for an
308
+ invalid one, and 2 for an unreadable file or a YAML construct outside the supported subset. The two
309
+ default-resolving accessors are subcommands of the same entry point:
310
+
311
+ ```bash
312
+ bash .claude/lib/bash/validate-parallel-manifest.sh --print-mode <manifest-path>
313
+ bash .claude/lib/bash/validate-parallel-manifest.sh --print-max-concurrency <manifest-path>
314
+ ```
315
+
316
+ They resolve the documented defaults `closed` and `4` when the manifest omits the key or carries a
317
+ malformed value. Consume `mode` and `max_concurrency` through these accessors rather than reading
318
+ the frontmatter directly.
319
+
320
+ `scripts/dev_tools/parallel_manifest_contract.py` (`validate_parallel_manifest_text`,
321
+ `manifest_mode`, `manifest_max_concurrency`) remains the repository authority and the parity
322
+ reference. Manifest validation is deliberately not an MCP `artifact_type`; do not attempt to
323
+ validate the manifest through `mcp__drm-copilot__validate_orchestration_artifacts`.
324
+
325
+ ## Checkpoint Persistence
326
+
327
+ Write `artifacts/orchestration/parallel-planner-state.json` after every completed step.
328
+
329
+ Top-level fields: `objective`, `parallel_slug`, `parallel_manifest_path`, `mode`,
330
+ `max_concurrency`, `plan_home_branch` (`parallel/<slug>-plan`), `items[]`, `cohorts[]`,
331
+ `conflict_edges[]`, `recolor_generation`, `kickoff_prompt_path`
332
+ (`artifacts/orchestration/parallel-kickoff-<slug>.md`), `completed_steps`, `next_step`, and
333
+ `last_updated`. F3's landed required-key set (planner invariant P1) is a strict subset of this
334
+ list, and `plan_home_branch` is a permitted additional field.
335
+
336
+ Per item: `issue_num`, `feature_folder`, `kind`, `state`, `complexity_band`, `preparation_status`,
337
+ `research_path`, `plan_path`, `preflight_status`, `branch_name`, `worktree_path`, `blast_radius`
338
+ (with `source: "declared"`), `radius_validation` (the `v1`, `v2`, and `v3` results with their
339
+ severities), `model_routing_receipt`, and `topology_receipt`.
340
+
341
+ **Deliberately absent:** any `epic_worthiness` analogue, any `depends_on` field, and any `wave`
342
+ field. The parallel surface renders no worthiness verdict and expresses ordering only as
343
+ blast-radius overlap.
344
+
345
+ **Readiness contract.** Before reporting completion the checkpoint must satisfy F3's
346
+ `require_ready_for_execution` gate: at least two items (invariant P6); every item
347
+ `preparation_status: prepared` with `preflight_status` exactly `PREFLIGHT: ALL CLEAR`, non-empty
348
+ `research_path` and `plan_path`, and `blast_radius.source == "declared"` (P7); `next_step` exactly
349
+ the ready sentinel `PARALLEL_EXECUTION_READY` (P8); and `kickoff_prompt_path` exactly
350
+ `artifacts/orchestration/parallel-kickoff-<slug>.md` (P9).
351
+
352
+ **Git integrity is F4-owned.** F3's `require_ready_for_execution` gate is structural only, so
353
+ verifying that each item's committed plan blob exists on that item's pushed branch ref — and that
354
+ the manifest and durable kickoff exist on the `parallel/<slug>-plan` ref — is this planner
355
+ surface's obligation, layered behind the planner's own check without changing the F3 schema.
356
+ Perform it with `git cat-file -e <ref>:<path>` and `git show <ref>:<path>` against each per-item
357
+ branch ref plus `parallel/<slug>-plan`.
358
+
359
+ **Cache doctrine.** The checkpoint is a cache of durable state, not the source of truth. On resume,
360
+ re-derive ground truth from `git branch`, `git worktree list --porcelain`, and the pushed refs.
361
+ Where the checkpoint and the repository disagree, the repository wins and the checkpoint is
362
+ rewritten from it.
363
+
364
+ Validate the checkpoint through `mcp__drm-copilot__validate_orchestration_artifacts` with
365
+ `artifact_type: "parallel-planner-state"` before reporting completion.
366
+
367
+ ## F3 Ownership Boundary
368
+
369
+ The following surfaces are owned by the schema-and-validator feature (F3). This planner writes
370
+ conforming instances and consumes the fixed enums; it never extends or redefines them:
371
+
372
+ - The manifest schema and the planner-checkpoint schema, recorded as prose invariants in
373
+ `.claude/rules/parallel-orchestration.md`, together with all nine parallel enums.
374
+ - `scripts/dev_tools/validate_parallel_planner_state.py` and
375
+ `scripts/dev_tools/validate_parallel_orchestrator_state.py`.
376
+ - The two state MCP `artifact_type` values `parallel-planner-state` and
377
+ `parallel-orchestrator-state`.
378
+ - The `route_id: parallel` entry in `config/orchestration-routing.json`.
379
+
380
+ The kickoff contract is **not** F3-owned. `scripts/dev_tools/parallel_kickoff_contract.py` and the
381
+ MCP `artifact_type: "parallel-kickoff"` are F4-owned and are **delivered by this feature**, per the
382
+ epic-manifest adjudication "Planner Adjudication: the kickoff-contract boundary (F3 / F4)" and the
383
+ matching "F3 Scope Boundary — kickoff contract deferred to F4" section of
384
+ `.claude/rules/parallel-orchestration.md`. Both are landed modules, not a recommendation carrying a
385
+ pending contingency.
386
+
387
+ The single-item-run floor question is resolved by F3's landed ready-gate invariant P6, which
388
+ requires at least two items under `require_ready_for_execution`. A one-item run cannot reach a ready
389
+ checkpoint.
390
+
391
+ ## Kickoff Artifact
392
+
393
+ Write the working copy to `artifacts/orchestration/parallel-kickoff-<slug>.md` (a gitignored tree)
394
+ and commit a byte-identical durable copy to `docs/features/parallel/<slug>/parallel-kickoff.md` on
395
+ `parallel/<slug>-plan`.
396
+
397
+ ```markdown
398
+ # Parallel Kickoff: <slug>
399
+
400
+ Planned by parallel-planner on <iso8601>. All items are prepared: promoted, active folders created,
401
+ research complete, spec and user-story written, atomic plans approved, preflight ALL CLEAR, blast
402
+ radii declared and V1/V2-clear. Planning state:
403
+ artifacts/orchestration/parallel-planner-state.json (run branch: parallel/<slug>-plan).
404
+
405
+ ## Invocation Prompt
406
+
407
+ Run `/parallel-run <slug>` to execute this run, or paste the prompt below.
408
+
409
+ Use the parallel-orchestrator subagent to execute the prepared run whose manifest is
410
+ docs/features/parallel/<slug>/parallel.md on the plan-home branch parallel/<slug>-plan. Each item
411
+ resumes at atomic execution from its committed plan-path on its own pushed feature branch rather
412
+ than re-planning, and each item opens its own pull request against main.
413
+
414
+ ## Item Summary
415
+
416
+ | issue_num | feature_folder | cohort | complexity | branch | plan-path |
417
+ | --- | --- | --- | --- | --- | --- |
418
+ | ... | ... | ... | ... | ... | ... |
419
+
420
+ ## Integrity
421
+
422
+ planning_commit: <hex>
423
+
424
+ | plan-path | plan-hash |
425
+ | --- | --- |
426
+ | ... | ... |
427
+ ```
428
+
429
+ Structural requirements enforced by the contract module:
430
+
431
+ - The first line is exactly `# Parallel Kickoff: <slug>`, with the slug matching
432
+ `[a-z0-9][a-z0-9-]*`.
433
+ - `## Invocation Prompt` must name `` Run `/parallel-run <slug>` ``, the manifest path
434
+ `docs/features/parallel/<slug>/parallel.md`, the plan-home branch `parallel/<slug>-plan`, and the
435
+ resume-boundary sentence stating that each item resumes at atomic execution from its committed
436
+ plan-path on its own pushed feature branch.
437
+ - `## Item Summary` is a strict pipe table with the exact ordered headers
438
+ `issue_num | feature_folder | cohort | complexity | branch | plan-path` and at least one data row.
439
+ `issue_num` and `cohort` are integers; `complexity` is one of `C1`, `C2`, `C3`, `C4`.
440
+ - `## Integrity` is optional. When present it carries a `planning_commit:` field holding the head
441
+ commit of `parallel/<slug>-plan` as run-level provenance and a per-item `plan-path | plan-hash`
442
+ table whose hashes are 40 to 64 hex characters with no repeated plan path.
443
+
444
+ Validate the artifact through `mcp__drm-copilot__validate_orchestration_artifacts` with
445
+ `artifact_type: "parallel-kickoff"`. That artifact type dispatches to
446
+ `scripts/dev_tools/parallel_kickoff_contract.py`, which this feature delivers.
447
+
448
+ ## Completion Report
449
+
450
+ The final report to the operator must include:
451
+
452
+ - The manifest path `docs/features/parallel/<slug>/parallel.md` and the run branch
453
+ `parallel/<slug>-plan`.
454
+ - Per item: one `plan-path:` line, the branch name, the preflight status, and the
455
+ radius-validation result, including any V3 Advisory findings.
456
+ - The cohort table at `generation 0`, together with the result of the recomputation-parity check.
457
+ - Both kickoff artifact paths: `artifacts/orchestration/parallel-kickoff-<slug>.md` and
458
+ `docs/features/parallel/<slug>/parallel-kickoff.md`.
459
+
460
+ End with the statement that execution has NOT started and begins only when the operator runs
461
+ `/parallel-run <slug>` or replays the kickoff prompt from the main session.
@@ -0,0 +1,176 @@
1
+ ---
2
+ name: parallel-remove
3
+ description: Remove one item from a running parallel run per the state-dependent removal behavior table — withdraw and recolor for an unstarted item, detach or abandon for an in-flight item, reject for a merged item. No default disposition is ever inferred. The abandon path runs through one deterministic CLI invocation and is hook-gated.
4
+ argument-hint: "[item] [--disposition detach|abandon]"
5
+ context: fork
6
+ agent: parallel-orchestrator
7
+ ---
8
+
9
+ # Parallel Remove Skill
10
+
11
+ A user invocation (`/parallel-remove <item> [--disposition detach|abandon]`) forks the
12
+ `parallel-orchestrator` agent with this procedure in context. The item key and optional disposition
13
+ are:
14
+
15
+ $ARGUMENTS
16
+
17
+ This skill implements the mutation-protocol remove operation (spec FR2). It mutates a parallel run
18
+ that is already executing, so the pinning invariant and the recompute boundary in the
19
+ `## Mutation Protocol (F6)` section of `.claude/skills/parallel-orchestrate/SKILL.md` govern what
20
+ this operation may disturb. Read that section before applying anything here.
21
+
22
+ ## Prerequisites
23
+
24
+ - A parallel run is in progress and `artifacts/orchestration/parallel-orchestrator-state.json`
25
+ tracks its `parallel_slug`.
26
+ - `$ARGUMENTS` names exactly one item key — an integer `items[].issue_num`. Item keys are integers
27
+ throughout this surface; there is no string key.
28
+
29
+ ## Re-Derive Durable State Before Applying Anything
30
+
31
+ The checkpoint is a CACHE of durable state, not the source of truth
32
+ (`.claude/rules/parallel-orchestration.md`, Cache Doctrine). Before deciding a removal, re-derive
33
+ the target item's true state and rewrite the checkpoint from it when they disagree:
34
+
35
+ - `git worktree list --porcelain` — worktree existence and path.
36
+ - `git branch` — branch existence and name.
37
+ - `gh pr view <pr> --json state,mergedAt,headRefOid` — pull-request state and merge outcome.
38
+
39
+ The removal branch is selected by the item's state, so a stale state selects the wrong branch. An
40
+ item the checkpoint calls `scheduled` but which is really `in_flight` would be silently withdrawn
41
+ and recolored, moving work that is already running. The re-derivation is therefore mandatory.
42
+
43
+ ## State-Dependent Behavior Table (Normative)
44
+
45
+ Implement this table exactly, one branch per row:
46
+
47
+ | Item state | Behavior |
48
+ | --- | --- |
49
+ | `proposed`, `admitted`, `prepared`, `scheduled` | Mark `withdrawn`, drop the vertex, recolor the unstarted subgraph (recompute). |
50
+ | `in_flight` | **Reject** unless `--disposition` is supplied. A default disposition is never inferred. |
51
+ | `in_flight` with `--disposition detach` | Let the item finish and merge on its own; the run stops tracking it. No recompute. |
52
+ | `in_flight` with `--disposition abandon` | Close the PR, remove the worktree, mark `withdrawn`. Destructive; hook-gated. No recompute. |
53
+ | `merged` | Reject; the change is already in `main`. |
54
+
55
+ An item already `withdrawn` or `blocked` is not a live removal target and is rejected as an unknown
56
+ item.
57
+
58
+ ## No Default Disposition
59
+
60
+ Removing an item that is `in_flight` without an explicit `--disposition` is REJECTED. No default is
61
+ inferred, in either direction. The choice between letting running work finish and destroying it
62
+ changes what happens to a pull request and a worktree, so it belongs to the caller and never to
63
+ this procedure. Do not guess, do not prompt-and-assume, and do not pick `detach` because it is the
64
+ non-destructive option.
65
+
66
+ ## Rejected Removals Change Nothing
67
+
68
+ A rejected removal — `in_flight` without a disposition, `merged`, or an unknown or already-withdrawn
69
+ item — fails fast with a specific error, appends NO `mutations[]` entry, and makes NO state change.
70
+ Do not record a partial removal, and do not record the rejection itself in `mutations[]`.
71
+
72
+ ## Procedure
73
+
74
+ 1. Re-derive durable state as above and resolve the item key against `items[]`.
75
+
76
+ 2. Decide the removal by calling `decide_removal(item_key, items, disposition)` from
77
+ `scripts/dev_tools/parallel_mutation_protocol.py`. The engine raises the dedicated rejection
78
+ exception for every rejected row; surface its message and stop.
79
+
80
+ 3. **Unstarted removal (recompute).** Set the item's state to `withdrawn`, drop its vertex, and
81
+ recolor by calling `recolor_unstarted(unstarted_items, conflict_edges, pinned,
82
+ current_generation, current_cohort=current_cohort)`. Write
83
+ `RecolorResult.cohort_assignments` into `cohorts[]` and set the top-level `recolor_generation`
84
+ to `RecolorResult.generation`; the generation increments by exactly one. The result names no
85
+ pinned key, so no in-flight item moves.
86
+
87
+ `current_cohort` is F3's top-level field, read from the re-verified durable state, and is the
88
+ index the pinned items occupy. The returned indices are ABSOLUTE and are written VERBATIM into
89
+ `cohorts[].index`, never re-based to zero. Returned keys whose index equals `current_cohort` are
90
+ MERGED into the single existing current-generation cohort entry at that index alongside its
91
+ pinned members, never written as a second entry carrying the same `index`, which F3 invariant 13
92
+ rejects.
93
+
94
+ 4. **`detach` (no recompute).** Set the item's state to `withdrawn` and record
95
+ `disposition: "detach"` in the mutation entry. `recolor_generation` is UNCHANGED: the detached
96
+ item was pinned and was never a vertex of the unstarted subgraph, so its departure cannot change
97
+ the induced subgraph. Perform no side effect — the item's own pull request continues to its own
98
+ merge outcome and the run simply stops tracking it. The `closed`-mode completion predicate
99
+ excludes withdrawn items, so the run does not wait for a detached item.
100
+
101
+ 5. **`abandon` (no recompute, destructive, CLI-only).** Set the item's state to `withdrawn` and
102
+ record `disposition: "abandon"` in the mutation entry. `recolor_generation` is UNCHANGED, for the
103
+ same reason as `detach`. Execute the destructive side effects — closing the pull request and
104
+ removing the worktree — through the single deterministic CLI invocation below and through nothing
105
+ else:
106
+
107
+ ```bash
108
+ poetry run python scripts/dev_tools/parallel_mutation_abandon_cli.py --item <key> --disposition abandon --confirm-abandon --pr <pr-number> --worktree <worktree-path>
109
+ ```
110
+
111
+ Executing the abandon disposition through ad hoc `gh pr close` or `git worktree remove` commands
112
+ is PROHIBITED. The prohibition is not stylistic: the abandon gate matches on the tokens of the
113
+ invocation above, so an ad hoc command is not matchable and would bypass the confirmation
114
+ contract entirely. One invocation, one item, both side effects.
115
+
116
+ 6. **Append exactly one `mutations[]` entry** for a successful removal, built by
117
+ `build_remove_entry` from `scripts/dev_tools/parallel_mutation_protocol.py`:
118
+
119
+ | Case | `op` | `item_key` | `prior_state` | `new_state` | `disposition` | `recolor_generation` |
120
+ | --- | --- | --- | --- | --- | --- | --- |
121
+ | Remove, unstarted | `remove` | item key | prior state (`proposed`/`admitted`/`prepared`/`scheduled`) | `withdrawn` | null | `g` + 1 |
122
+ | Remove, `detach` | `remove` | item key | `in_flight` | `withdrawn` | `detach` | `g` (unchanged) |
123
+ | Remove, `abandon` | `remove` | item key | `in_flight` | `withdrawn` | `abandon` | `g` (unchanged) |
124
+
125
+ `disposition` is non-null only on an in-flight removal and is null on the unstarted row. The `at`
126
+ timestamp comes from the engine's injected clock seam.
127
+
128
+ 7. **Validate the checkpoint** before treating the removal as applied. Run the
129
+ `validate_orchestration_artifacts` MCP tool with `artifact_type:
130
+ "parallel-orchestrator-state"`. A non-empty error list means the removal was applied incorrectly;
131
+ correct the checkpoint rather than proceeding.
132
+
133
+ ## Abandon Confirmation-Marker Contract
134
+
135
+ The abandon path is guarded by the PreToolUse hook
136
+ `.claude/hooks/enforce-parallel-abandon-gate.ps1` on the `Bash` matcher. The contract is:
137
+
138
+ - A Bash command carrying the disposition token for abandon MUST also carry the explicit
139
+ confirmation marker `--confirm-abandon` in the SAME command.
140
+ - A command carrying the abandon disposition token WITHOUT the confirmation marker is DENIED. The
141
+ deny reason is prefixed `PARALLEL_ABANDON_BLOCKED`.
142
+ - A command carrying both tokens is allowed.
143
+ - A command carrying neither is out of scope and is allowed unchanged.
144
+
145
+ The two token values are declared once each in
146
+ `scripts/dev_tools/parallel_mutation_abandon_cli.py` (the producer) and once each in the hook (the
147
+ consumer), and the seam test
148
+ `tests/scripts/dev_tools/test_parallel_abandon_token_seam.py` parses all three artifacts — the CLI,
149
+ the hook, and the invocation line in step 5 above — at run time to prove they still agree. Renaming
150
+ a token in one artifact without the identical rename in the other two fails that test. The
151
+ invocation in step 5 is the file's only executable abandon command line, and the seam test parses
152
+ that one line; do not add a second one.
153
+
154
+ When the gate denies a command, the correct response is to add the confirmation marker
155
+ deliberately, not to reformulate the command to evade the match. Reformulating to evade the gate
156
+ defeats the only mechanism protecting a destructive operation.
157
+
158
+ ## Constraints
159
+
160
+ - One removal per invocation; at most one `mutations[]` entry per invocation.
161
+ - No field and no enum member is added to `mutations[]`, `items[]`, or any state or merge-status
162
+ enum. The nine parallel enums are owned by `.claude/rules/parallel-orchestration.md` and are
163
+ consumed, never extended.
164
+ - Neither `detach` nor `abandon` recomputes. An unstarted item previously deferred because of a
165
+ conflict with the removed item keeps its cohort assignment: the assignment stays valid and is at
166
+ most conservative, and no opportunistic recompute is performed.
167
+ - No in-flight item other than the removal target changes cohort or state.
168
+
169
+ ## Completion Requirements
170
+
171
+ - Report the item key, the branch of the behavior table taken, the disposition recorded, the
172
+ resulting `recolor_generation`, and the single appended `mutations[]` entry — or, for a rejected
173
+ removal, the rejection and the explicit confirmation that nothing was appended and no state
174
+ changed.
175
+ - For an abandon, report the CLI's exit code and both side-effect outcomes.
176
+ - Report the checkpoint validation result.