@danmoisan/drm-copilot-mcp 1.1.5 → 1.1.7

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 (27) hide show
  1. package/out/mcp-server.js +49 -14
  2. package/package.json +1 -1
  3. package/resources/claude-customizations/.claude/agents/atomic-planner.md +2 -0
  4. package/resources/claude-customizations/.claude/agents/prd-feature.md +5 -0
  5. package/resources/claude-customizations/.claude/agents/task-researcher.md +3 -0
  6. package/resources/claude-customizations/.claude/hooks/enforce-epic-worktree-removal-gate.ps1 +163 -18
  7. package/resources/claude-customizations/.claude/hooks/validate-planner-output.ps1 +122 -0
  8. package/resources/claude-customizations/.claude/hooks/validate-prd-feature-output.ps1 +91 -0
  9. package/resources/claude-customizations/.claude/hooks/validate-task-researcher-output.ps1 +69 -1
  10. package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadius.psm1 +11 -0
  11. package/resources/claude-customizations/.claude/lib/requirements/GeneratedDocumentCounters.psm1 +32 -0
  12. package/resources/claude-customizations/.claude/rules/parallel-orchestration.md +1 -0
  13. package/resources/claude-customizations/.claude/settings.json +9 -0
  14. package/resources/claude-customizations/.claude/skills/acceptance-criteria-tracking/SKILL.md +2 -0
  15. package/resources/claude-customizations/.claude/skills/atomic-plan-contract/SKILL.md +32 -0
  16. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/SKILL.md +136 -4
  17. package/resources/claude-customizations/.claude/skills/fill-feature-docs/SKILL.md +3 -0
  18. package/resources/claude-customizations/.claude/skills/parallel-add/SKILL.md +5 -1
  19. package/resources/claude-customizations/.claude/skills/parallel-orchestrate/SKILL.md +18 -9
  20. package/resources/claude-customizations/.claude/skills/parallel-plan/SKILL.md +10 -1
  21. package/resources/claude-customizations/.claude/skills/pr-context-artifacts/SKILL.md +22 -0
  22. package/resources/claude-customizations/.claude/skills/remediation-handoff-atomic-planner/SKILL.md +12 -0
  23. package/resources/claude-customizations/.claude/skills/research-issue/SKILL.md +3 -0
  24. package/resources/claude-customizations/pack-manifests/core.json +2 -0
  25. package/resources/codex-and-agents-customizations/.agents/skills/pr-context-artifacts/SKILL.md +22 -0
  26. package/resources/codex-and-agents-customizations/.codex/config.toml +1 -1
  27. package/resources/customizations/.github/skills/pr-context-artifacts/SKILL.md +22 -0
@@ -161,6 +161,68 @@ function Test-AutomationFeasibilitySection {
161
161
  return @{ Ok = $true; Message = $null }
162
162
  }
163
163
 
164
+ function Test-NumericDerivationEvidence {
165
+ [CmdletBinding()]
166
+ [OutputType([hashtable])]
167
+ param(
168
+ [Parameter(Mandatory = $true)]
169
+ [AllowEmptyString()]
170
+ [string] $Content
171
+ )
172
+
173
+ $numericClaimPattern = '(?im)^\s*[-*]\s*Numeric\s+spec\.md\s+acceptance\s+criterion:\s*.*\b\d+\b'
174
+ if (-not [regex]::IsMatch($Content, $numericClaimPattern)) {
175
+ return @{ Ok = $true; Message = $null }
176
+ }
177
+
178
+ $section = [regex]::Match($Content, '(?ims)^##\s+Numeric\s+Derivation\s+Evidence\s*$.*?(?=^##\s|\z)')
179
+ if (-not $section.Success) {
180
+ return @{ Ok = $false; Message = 'task-researcher hook: numeric spec.md acceptance criterion is missing ## Numeric Derivation Evidence.' }
181
+ }
182
+
183
+ $requiredLabels = @(
184
+ 'Complete Family', 'Exhaustive Search Scope', 'Inclusion Rules', 'Exclusion Rules',
185
+ 'Primary Search Strategy or Query Expression', 'Primary Member Set', 'Primary Count',
186
+ 'Cross-check Search Strategy or Query Expression', 'Cross-check Member Set', 'Cross-check Count',
187
+ 'Member-set Comparison'
188
+ )
189
+ $values = @{}
190
+ foreach ($label in $requiredLabels) {
191
+ $match = [regex]::Match($section.Value, "(?im)^[\t ]*[-*]?[\t ]*$([regex]::Escape($label))[\t ]*:[\t ]*(?<value>\S(?:.*\S)?)[\t ]*$")
192
+ if (-not $match.Success) { return @{ Ok = $false; Message = "task-researcher hook: numeric derivation evidence is missing $label." } }
193
+ $values[$label] = $match.Groups['value'].Value.Trim()
194
+ }
195
+ if ($values['Exhaustive Search Scope'] -notmatch '(?i)\b(entire|all|complete)\b.*\b(repository|repo|source tree|tree)\b') {
196
+ return @{ Ok = $false; Message = 'task-researcher hook: numeric derivation evidence does not declare an exhaustive repository search scope.' }
197
+ }
198
+ $primaryStrategy = $values['Primary Search Strategy or Query Expression']
199
+ $crossCheckStrategy = $values['Cross-check Search Strategy or Query Expression']
200
+ if ($primaryStrategy -match '(?i)\b(single|narrow|named[- ]?pattern)\b' -or $crossCheckStrategy -match '(?i)\b(single|narrow|named[- ]?pattern)\b') {
201
+ return @{ Ok = $false; Message = 'task-researcher hook: numeric derivation evidence uses a narrow named-pattern search.' }
202
+ }
203
+ if ([regex]::Replace($primaryStrategy, '\s+', '').ToLowerInvariant() -eq [regex]::Replace($crossCheckStrategy, '\s+', '').ToLowerInvariant()) {
204
+ return @{ Ok = $false; Message = 'task-researcher hook: numeric derivation cross-check repeats the primary search strategy or query expression.' }
205
+ }
206
+ $familyMembers = @($values['Complete Family'].Split(',') | ForEach-Object { $_.Trim() } | Where-Object { -not [string]::IsNullOrWhiteSpace($_) })
207
+ foreach ($familyMember in $familyMembers) {
208
+ if ($primaryStrategy -notmatch [regex]::Escape($familyMember) -or $crossCheckStrategy -notmatch [regex]::Escape($familyMember)) {
209
+ return @{ Ok = $false; Message = "task-researcher hook: numeric derivation search does not cover complete family member '$familyMember'." }
210
+ }
211
+ }
212
+ if ($values['Primary Count'] -notmatch '^\d+$' -or $values['Cross-check Count'] -notmatch '^\d+$') { return @{ Ok = $false; Message = 'task-researcher hook: numeric derivation counts must be numeric.' } }
213
+ $primaryMembers = @($values['Primary Member Set'].Split(',') | ForEach-Object { $_.Trim() } | Where-Object { -not [string]::IsNullOrWhiteSpace($_) })
214
+ $crossCheckMembers = @($values['Cross-check Member Set'].Split(',') | ForEach-Object { $_.Trim() } | Where-Object { -not [string]::IsNullOrWhiteSpace($_) })
215
+ if ([int]$values['Primary Count'] -ne $primaryMembers.Count -or [int]$values['Cross-check Count'] -ne $crossCheckMembers.Count) {
216
+ return @{ Ok = $false; Message = 'task-researcher hook: numeric derivation count does not match its independently enumerated member set.' }
217
+ }
218
+ $normalizedPrimaryMembers = @($primaryMembers | ForEach-Object { $_.ToLowerInvariant() } | Sort-Object -Unique) -join '|'
219
+ $normalizedCrossCheckMembers = @($crossCheckMembers | ForEach-Object { $_.ToLowerInvariant() } | Sort-Object -Unique) -join '|'
220
+ if ($normalizedPrimaryMembers -ne $normalizedCrossCheckMembers) { return @{ Ok = $false; Message = 'task-researcher hook: numeric derivation primary and cross-check member sets disagree.' } }
221
+ if ($values['Member-set Comparison'] -notmatch '(?i)\b(equal|match|identical)\b') { return @{ Ok = $false; Message = 'task-researcher hook: numeric derivation evidence is missing an explicit member-set comparison.' } }
222
+
223
+ return @{ Ok = $true; Message = $null }
224
+ }
225
+
164
226
  function Invoke-TaskResearcherOutputValidation {
165
227
  [CmdletBinding()]
166
228
  [OutputType([hashtable])]
@@ -209,6 +271,13 @@ function Invoke-TaskResearcherOutputValidation {
209
271
  return @{ Ok = $false; Message = $feasibilityResult.Message }
210
272
  }
211
273
 
274
+ if (Test-Path -LiteralPath $researchPath -PathType Leaf) {
275
+ $numericEvidenceResult = Test-NumericDerivationEvidence -Content (Get-Content -LiteralPath $researchPath -Raw -ErrorAction Stop)
276
+ if (-not $numericEvidenceResult.Ok) {
277
+ return $numericEvidenceResult
278
+ }
279
+ }
280
+
212
281
  return @{ Ok = $true; Message = $null }
213
282
  }
214
283
 
@@ -223,4 +292,3 @@ if (-not $result.Ok) {
223
292
  }
224
293
 
225
294
  exit 0
226
-
@@ -428,6 +428,17 @@ function Test-BlastRadiusConflict {
428
428
  .OUTPUTS
429
429
  System.Collections.Hashtable. Keys conflict (a boolean) and reasons (an
430
430
  array of hashtables with keys kind and detail).
431
+
432
+ Read the verdict from the conflict key of the returned hashtable.
433
+ Do not test the returned object itself: the hashtable is
434
+ unconditionally truthy under PowerShell boolean coercion, so
435
+ 'if ($result)' treats every pair as contending.
436
+ System.Collections.Hashtable implements IDictionary and ICollection but
437
+ not IList, and the count-based truthiness rule applies only to IList
438
+ implementations, so a hashtable falls under the rule for any other
439
+ non-collection type and is always $true. The Python port agrees with its
440
+ own verdict; this mirror provably cannot, because PowerShell exposes no
441
+ hook by which a type can decline or change the conversion.
431
442
  #>
432
443
  [CmdletBinding()]
433
444
  [OutputType([hashtable])]
@@ -0,0 +1,32 @@
1
+ Set-StrictMode -Version Latest
2
+
3
+ <#
4
+ .SYNOPSIS
5
+ Counts markdown checkbox items contained by a named heading section.
6
+ #>
7
+ function Get-NamedSectionCheckboxCount {
8
+ [CmdletBinding()]
9
+ [OutputType([int])]
10
+ param(
11
+ [Parameter(Mandatory = $true)][AllowEmptyString()][string] $Document,
12
+ [Parameter(Mandatory = $true)][string] $Heading
13
+ )
14
+
15
+ $headingPattern = '^(?<marks>#{1,6})\s+' + [regex]::Escape($Heading) + '\s*$'
16
+ $inside = $false
17
+ $level = 0
18
+ $count = 0
19
+ foreach ($line in ($Document -split "`r?`n")) {
20
+ if (-not $inside) {
21
+ $match = [regex]::Match($line, $headingPattern)
22
+ if ($match.Success) { $inside = $true; $level = $match.Groups['marks'].Value.Length }
23
+ continue
24
+ }
25
+ $nextHeading = [regex]::Match($line, '^(?<marks>#{1,6})\s+')
26
+ if ($nextHeading.Success -and $nextHeading.Groups['marks'].Value.Length -le $level) { break }
27
+ if ($line -match '^\s*[-*]\s+\[[ xX]\]\s+') { $count++ }
28
+ }
29
+ return $count
30
+ }
31
+
32
+ Export-ModuleMember -Function Get-NamedSectionCheckboxCount
@@ -409,3 +409,4 @@ an unclassified key or a key present in only one copy fails loudly and names its
409
409
  - Enforcement is therefore Python validator logic, plus the TypeScript parity port, plus this prose file. It is NEVER an imported JSON Schema. No schema file is read at validation time.
410
410
  - The `parallel` route entry lives in `config/orchestration-routing.json` with `requires_pr_gate: false` (there is no run-level pull request to gate; each child's own route checkpoint enforces its per-item pull-request gate) and is mirrored byte-for-byte in `extensions/drm-copilot/resources/config/orchestration-routing.json`.
411
411
  - The `PreToolUse` merge gate `.claude/hooks/enforce-epic-merge-gate.ps1` carries a parallel allow-branch that authorizes a per-item `gh pr merge --merge` from the parallel-orchestrator checkpoint when `route_id == "parallel"`, the target item's `merge_status == "ci_green"`, and the command's PR number matches that item's `pr_number`; any other case fails closed with `EPIC_MERGE_GATE_BLOCKED`.
412
+ - The `PreToolUse` worktree-removal gate `.claude/hooks/enforce-epic-worktree-removal-gate.ps1` likewise carries a parallel allow-branch that authorizes a per-item worktree removal from the parallel-orchestrator checkpoint when `route_id == "parallel"` and the `items[]` entry whose `worktree_path` matches the normalized removal target has `merge_status` in `{merged, worktree_removed}`; any other case — neither checkpoint present, either checkpoint unparseable, `route_id` absent or not `"parallel"`, no matching `worktree_path`, or a matched entry whose `merge_status` is outside that set or absent — fails closed with `EPIC_WORKTREE_REMOVAL_BLOCKED`. Removal is keyed on the worktree path rather than on `pr_number`, because the command names a path. This gate and the sibling gate `.claude/hooks/enforce-parallel-worktree-removal-gate.ps1`, which owns `PARALLEL_WORKTREE_REMOVAL_BLOCKED`, both fire on the same command, and `PreToolUse` denials are conjunctive, so both must allow for a removal to proceed.
@@ -239,6 +239,15 @@
239
239
  }
240
240
  ]
241
241
  },
242
+ {
243
+ "matcher": "prd-feature",
244
+ "hooks": [
245
+ {
246
+ "type": "command",
247
+ "command": "pwsh -NoProfile -File .claude/hooks/validate-prd-feature-output.ps1"
248
+ }
249
+ ]
250
+ },
242
251
  {
243
252
  "matcher": "pr-author",
244
253
  "hooks": [
@@ -35,6 +35,8 @@ When multiple AC source files exist, track checkboxes in **each** applicable fil
35
35
 
36
36
  ## AC Identification
37
37
 
38
+ For generated-document summaries, call `.claude/lib/requirements/GeneratedDocumentCounters.psm1` and supply `Acceptance Criteria` as the named section. The counter begins after that heading and ends at the next equal-or-shallower heading. Do not use `scripts/dev_tools/plan_progress_report.py`, which counts plan tasks rather than generated requirements criteria.
39
+
38
40
  Acceptance criteria are markdown checkbox items within AC source files.
39
41
 
40
42
  Deterministic heading rule:
@@ -139,8 +139,26 @@ For command-bearing tasks in approved plans (especially Phase 2 final-QC tasks):
139
139
 
140
140
  Any regression test task expected to fail must be tagged with `[expect-fail]` and include an auditable evidence artifact per `evidence-and-timestamp-conventions`.
141
141
 
142
+ ## Planner Adversarial Self-Review (Mandatory)
143
+
144
+ Before any plan handoff, `atomic-planner` MUST complete one explicit adversarial self-review pass over every fact, assumption, and line or file citation the plan relies on. The pass is required on initial authoring and on every revision-delta round. A revision round is not exempt because it changed only part of the plan: the citations the revision touched describe the tree as it stands after the revision, and no earlier pass observed that state.
145
+
146
+ Rules:
147
+
148
+ - **Re-derive every citation in this pass.** Any line, file, test, or assertion that the planner's own edit touched, added, or removed in the current authoring or revision pass MUST be re-derived directly against current repository state in that same pass. The prohibited source is a citation carried forward from an earlier round, including one the planner itself verified in a prior round: that earlier verification observed the tree before the intervening edits, so it is evidence about a superseded state rather than about the state the plan now asserts.
149
+ - **Re-check the sibling region.** The self-review MUST re-check the sibling lines, tests, and assertions that sit in the same file or region as any edited citation. The failure mechanism is sibling invalidation: a fix to one line can invalidate an assumption baked into a sibling line or test that a prior round's citation did not cover, so a pass that verifies only the edited line leaves the invalidated sibling unreported and it surfaces as a defect on a later round.
150
+
151
+ Declaration requirement. Every plan handoff MUST carry exactly one of these two signal lines, written in the directive-line form already used elsewhere in this contract:
152
+
153
+ - `SELF-REVIEW: RE-DERIVED THIS PASS` — the adversarial self-review pass completed in this pass. This signal MUST be followed by an enumeration of the citations re-derived in that pass, one entry per citation, each naming the file and the line, test, or identifier that was re-derived. A signal carrying no enumeration is not a completed declaration.
154
+ - `SELF-REVIEW: BLOCKED` — the pass could not be completed. This signal halts the handoff. It does not permit a self-approved plan: the planner reports the blocking reason and waits for the caller rather than proceeding to hand off an unverified plan.
155
+
142
156
  ## Preflight Validation (Planner ↔ Executor)
143
157
 
158
+ ### Planner Internal Review Record
159
+
160
+ Before executor preflight, the planner must emit exactly one bounded record between `PLANNER-INTERNAL-REVIEW: PASS` and the existing `PREFLIGHT:` signal. The record requires exactly one passing declaration each for `CITATION-TO-TREE`, `AC-TRACEABILITY`, and `SCOPE-BOUNDARY`; one or more `CITATION: <repository-relative path> | <nonblank locator>` entries; exactly one `AC-INVENTORY:` declaration containing unique nonblank IDs; one `AC-MAPPING: <ID> | IMPLEMENTATION: <nonblank> | TESTS: <nonblank> | EVIDENCE: <nonblank>` for every and only inventory ID; and exactly one `UNRESOLVED-GAPS: NONE`. Missing, blank, duplicate, non-passing, out-of-bounds, or inventory/mapping-disagreeing declarations block handoff. If review cannot pass, emit `SELF-REVIEW: BLOCKED` and do not hand the plan to preflight. `SELF-REVIEW: RE-DERIVED THIS PASS` remains distinct and does not replace executor clearance.
161
+
144
162
  When validating or handing off plans for execution:
145
163
  - Use the directive line: `DIRECTIVE: PREFLIGHT VALIDATION ONLY`.
146
164
  - Require one of the exact signals:
@@ -149,6 +167,20 @@ When validating or handing off plans for execution:
149
167
  - If revisions are required, provide a precise plan delta and repeat validation until all clear.
150
168
  - If the required planner ↔ executor handoff cannot be started or completed, stop and report blocked state; do not self-approve the plan.
151
169
 
170
+ Review depth and reporting rules:
171
+
172
+ - **Review the entire plan in one pass.** Under `DIRECTIVE: PREFLIGHT VALIDATION ONLY`, `atomic-executor` MUST continue checking every remaining phase, task, and prose region after finding an initial defect. Stopping at the first defect is prohibited: the unchecked remainder holds defects that the same pass could have reported, and each one that is left unreported becomes an additional round.
173
+ - **Enumerate every defect found.** `PREFLIGHT: REVISIONS REQUIRED` output MUST list every defect found in that pass, not only the first. The failure mechanism is round inflation: a single-defect report causes the next round to rediscover a defect the same pass could have reported, so the round count rises without the review having covered more of the plan.
174
+ - **Check the delta against its own rule.** Before returning either signal, `atomic-executor` MUST check its proposed fix or delta text against every rule the plan enforces, including that delta's own prose against the same violation class it is remediating. Worked example: the delta prose of a tonality-compliance fix must not itself contain the hyperbole or humor that `.claude/rules/tonality.md` prohibits, because a delta that violates the rule it is written to enforce reintroduces the finding it closes.
175
+ - **Two-round target.** The quality bar is a target of at most two preflight rounds per plan. Exhaustive first-pass review is the mechanism that holds the round count to that target: a pass that reports every defect it can find leaves at most a revision round and a confirming round, whereas a pass that reports one defect at a time cannot reach the target however correct each individual report is.
176
+
177
+ Convergence signal. Every preflight return, whether it carries `PREFLIGHT: ALL CLEAR` or `PREFLIGHT: REVISIONS REQUIRED`, MUST additionally carry exactly one of these two forward-looking lines:
178
+
179
+ - `CONVERGENCE: NO FURTHER ROUNDS EXPECTED` — the reviewer expects the plan to clear without a further round.
180
+ - `CONVERGENCE: FURTHER ROUNDS LIKELY` — the reviewer expects at least one further round, and states why.
181
+
182
+ The convergence line is a required signal rather than free prose. It is a second required line accompanying the preflight signal, not a third value of the signal set that the `Require one of the exact signals:` bullet above enumerates: that bullet's two-value set is unchanged, and every return carries one value from it together with one convergence line.
183
+
152
184
  ## Validator Gate (Mandatory)
153
185
 
154
186
  Before a plan can be treated as approved:
@@ -3,11 +3,23 @@ name: cleanup-merged-worktrees
3
3
  description: 'Detect, consolidate, and delete git worktrees/branches that are fully merged into main; use after an epic or feature''s PRs have merged and stale drm-copilot-wt-* branches/worktrees remain, driving the detect -> report -> consolidate -> pr-author handoff -> post-merge deletion workflow.'
4
4
  allowed-tools:
5
5
  - Read
6
+ - Grep
7
+ - Glob
8
+ - Agent
6
9
  - "Bash(bash scripts/bash/cleanup-worktrees.sh *)"
7
10
  - "Bash(git fetch *)"
8
11
  - "Bash(git merge-base *)"
9
12
  - "Bash(git push *)"
10
13
  - "Bash(git rev-parse *)"
14
+ - "Bash(git status *)"
15
+ - "Bash(git log *)"
16
+ - "Bash(git show *)"
17
+ - "Bash(git diff *)"
18
+ - "Bash(git branch -r*)"
19
+ - "Bash(git worktree list*)"
20
+ - "Bash(gh issue view *)"
21
+ - mcp__drm-copilot__new_potential_bug_entry
22
+ - mcp__drm-copilot__potential_to_issue
11
23
  ---
12
24
 
13
25
  # Cleanup Merged Worktrees
@@ -35,8 +47,12 @@ and is out of the script's scope.
35
47
  which carry unmerged or unique work (`NOT_MERGED`, `HAS_UNIQUE_RESIDUALS`).
36
48
  - When stranded documentation/agent-memory commits were appended to a worktree branch
37
49
  after its feature content already merged and must be preserved before deletion.
50
+ - When a worktree is reported `BLOCKED-DIRTY`, or its branch is classified `NOT_MERGED`
51
+ or `HAS_UNIQUE_RESIDUALS`, and the uncommitted or unmerged content it holds must be
52
+ triaged into disposable versus must-preserve before the worktree can ever be deleted.
38
53
  - Do not use this skill to manage remote branches; its scope is local branches and
39
- local worktree registrations only.
54
+ local worktree registrations only, except for the explicitly confirmed origin-branch
55
+ offer in the Dirty Worktree Triage Procedure's final step.
40
56
 
41
57
  ## Report Line Contract
42
58
 
@@ -99,7 +115,9 @@ The script emits pipe-delimited, `LC_ALL=C`-ordered records, one per line:
99
115
  (without force; a dirty worktree is reported via `DIRTY|` lines and skipped), then
100
116
  deletes branches with `git branch -D`. The now-merged `documentationandmemories`
101
117
  branch and its worktree become `MERGED_CLEAN` instances and are cleaned up by the same
102
- mechanics.
118
+ mechanics. Any worktree left standing afterward — reported `BLOCKED-DIRTY`, or whose
119
+ branch classified `NOT_MERGED` or `HAS_UNIQUE_RESIDUALS` — is not abandoned; it moves
120
+ to the Dirty Worktree Triage Procedure below.
103
121
 
104
122
  ## Nothing to Consolidate (Short Path)
105
123
 
@@ -108,6 +126,108 @@ with an empty cherry-pick-candidate list, skip steps 3-5 entirely: proceed direc
108
126
  the report to `bash scripts/bash/cleanup-worktrees.sh --apply`. Cleanup completes in a
109
127
  single session with no PR.
110
128
 
129
+ ## Dirty Worktree Triage Procedure
130
+
131
+ **Trigger.** A worktree reported `ACTION|worktree-remove|<path>|BLOCKED-DIRTY` (with
132
+ accompanying `DIRTY|<path>|<status-porcelain-line>` records), or a branch classified
133
+ `NOT_MERGED` or `HAS_UNIQUE_RESIDUALS`, carries uncommitted or unmerged content the
134
+ script correctly refuses to discard. That refusal is correct and this procedure never
135
+ overrides it — a dirty worktree is never force-removed. This procedure is the systematic
136
+ follow-up: deciding, per worktree, whether that content is disposable or must be
137
+ preserved before the worktree can ever be deleted.
138
+
139
+ Steps 1-7 are read-only investigation. Run them per worktree, or fan out one
140
+ `Agent(general-purpose)` investigation per worktree (or small batch) concurrently per
141
+ step 8, each returning a `SAFE_TO_DELETE` / `PRESERVE` verdict with justification citing
142
+ specific files or commit SHAs, before step 9 acts on any finding.
143
+
144
+ 1. **Re-verify current state before analyzing.** Worktrees can be actively in use by
145
+ another concurrent session. Re-run `git status --porcelain` in the worktree and
146
+ re-check the branch's merge status fresh — do not reuse the original scan's
147
+ snapshot. If the worktree's `.git`/index/HEAD mtimes show activity in the last few
148
+ minutes, treat it as possibly live and pause rather than analyze it as abandoned.
149
+
150
+ 2. **Check committed-but-unmerged commits, not only the working tree.** Run
151
+ `git log main..<branch> --oneline`. Some worktrees carry real commits that never
152
+ merged, separate from uncommitted working-tree changes. Both need the classification
153
+ in step 5.
154
+
155
+ 3. **Check for equivalent content already on `main`, by topic, not only by path.** For
156
+ every dirty, untracked, or unmerged file, check `git show main:<path>` at the same
157
+ path, and also grep broadly across the relevant shared namespace (for example
158
+ `.claude/agent-memory/**` for lesson files, `docs/features/**` for feature docs)
159
+ since the same fact is often re-recorded under a different filename on `main`.
160
+
161
+ 4. **For feature-folder doc snapshots** (`issue.md`, `plan.md`, `spec.md`,
162
+ `research/*`), check whether the feature is fully closed on `main` — acceptance
163
+ criteria all checked, code-review/feature-audit/policy-audit artifacts present, an
164
+ evidence trail present. An earlier draft of an already-closed feature is almost
165
+ always fully superseded; diff it against the closed feature's final artifacts to
166
+ confirm rather than assume.
167
+
168
+ 5. **Classify any content that is not obviously superseded** into exactly one of:
169
+ - `DEAD_ONE_OFF` — real, but tied to an already-executed, closed plan with no reuse
170
+ elsewhere (check whether the same pattern appears in shared `.claude/skills/**`
171
+ templates or in other feature plans). Low value; safe to discard even though it is
172
+ not technically duplicated.
173
+ - `ALREADY_SOLVED_ELSEWHERE` — the underlying problem it documents is fixed a
174
+ different way on `main` (check `main`'s current code/config/script, not only its
175
+ memory files — a memory file can describe a bug that no longer exists).
176
+ - `STALE_OR_CONTRADICTED` — `main`'s current version of the same lesson has since
177
+ been corrected to state something different or opposite. This is not merely
178
+ redundant; it is actively wrong, and discarding is the right call.
179
+ - `GENUINELY_NEW` / `STILL_RELEVANT` — not found anywhere else, or it corrects
180
+ something `main` currently gets wrong, or it documents unresolved scope on a
181
+ still-open issue (verify open/closed with `gh issue view <n>`; never assume). Must
182
+ be preserved before the worktree is deleted.
183
+
184
+ 6. **Handle non-memory dirty content on its own terms.** Some worktrees carry stale
185
+ build artifacts (a modified `.csproj`/`packages.config`/`app.config` from a build run
186
+ in that worktree) rather than documentation. Diff a representative sample against
187
+ `main` (`git diff main -- <path>`) to characterize the change before deciding it is
188
+ disposable.
189
+
190
+ 7. **Recognize orphaned non-worktree directories.** A path can still exist on disk
191
+ under a worktree-tracking folder after `git worktree remove` partially ran or
192
+ failed, with no `.git` file inside and no entry in `git worktree list`. These are no
193
+ longer worktrees — flag them for plain filesystem removal, not `git worktree
194
+ remove`, which will misfire or no-op on them. Filesystem removal of an orphaned
195
+ directory is a destructive action outside this skill's pre-approved tool surface; it
196
+ requires explicit user confirmation each time, the same as any other irreversible
197
+ delete.
198
+
199
+ 8. **Parallelize the triage.** Steps 1-7 are pure read-only investigation. Fan out one
200
+ `Agent(general-purpose)` investigation per worktree (or a small batch) concurrently,
201
+ each following steps 1-7 and returning a structured `SAFE_TO_DELETE` / `PRESERVE`
202
+ verdict with justification. This scales far better than triaging serially.
203
+
204
+ 9. **Route `PRESERVE` findings through the existing consolidation flow** (the
205
+ `documentationandmemories` branch/PR mechanism in steps 3-4 of the End-to-End
206
+ Workflow above) before that worktree's dirty content is discarded. If a finding
207
+ describes unresolved product scope rather than a process lesson, promote it to a
208
+ real follow-up issue instead of folding it into the docs/memory PR: file it with
209
+ `mcp__drm-copilot__new_potential_bug_entry` and promote with
210
+ `mcp__drm-copilot__potential_to_issue` per
211
+ `.claude/skills/feature-promotion-lifecycle/SKILL.md`. For a `SAFE_TO_DELETE`
212
+ verdict, discard the content as a distinct, individually confirmed manual action —
213
+ clear the dirty working tree, or delete a disposable `NOT_MERGED`/
214
+ `HAS_UNIQUE_RESIDUALS` branch directly. This is never automated: the script's
215
+ classification ladder and apply-mode allowlist are never changed to accept these
216
+ states, so a `--apply` run never deletes them on its own, before or after triage. If
217
+ discarding the working-tree content changes the branch's classification (for example
218
+ to content-neutral against `main`), a follow-up report/apply pass then picks it up
219
+ through the normal deterministic path.
220
+
221
+ 10. **After local branch deletion, check origin too.** This skill is local-only by
222
+ design (see "When to Use This Skill"), which leaves stale branches on the remote for
223
+ anything already merged. After `--apply` finishes, diff the deleted-local-branch
224
+ list against `git branch -r` (post-prune) to find remote branches whose local
225
+ counterpart is gone, and offer to delete the remainder on origin. Because this
226
+ mutates shared, visible remote state, each deletion requires explicit user
227
+ confirmation — never delete an origin branch as an automatic consequence of local
228
+ cleanup, and never rely on this skill's general `Bash(git push *)` allowance to
229
+ perform it silently.
230
+
111
231
  ## Prohibited Shortcuts
112
232
 
113
233
  - Never invoke `gh pr create` or `gh pr edit --body*` from this skill or the scripts. PR
@@ -116,10 +236,19 @@ single session with no PR.
116
236
  - Never pass a force flag to `git worktree remove`. A dirty worktree blocks deletion and
117
237
  is reported for manual handling; it is never force-removed.
118
238
  - Never execute `git worktree prune`. Prunable registrations are report-only.
119
- - Never act on `NOT_MERGED`, `HAS_UNIQUE_RESIDUALS`, or `PROTECTED_CURRENT` candidates;
120
- the caller's worktree and branch, and the main worktree, are never mutated.
239
+ - Never act on `NOT_MERGED`, `HAS_UNIQUE_RESIDUALS`, or `PROTECTED_CURRENT` candidates
240
+ through the script or its apply-mode allowlist; `--apply` never mutates them, and the
241
+ caller's worktree and branch, and the main worktree, are never mutated under any
242
+ disposition. The Dirty Worktree Triage Procedure's `SAFE_TO_DELETE` verdict authorizes
243
+ only a distinct, individually confirmed manual action outside that automated path for
244
+ `NOT_MERGED`/`HAS_UNIQUE_RESIDUALS` — never a change to the classification ladder
245
+ itself, and never for `PROTECTED_CURRENT`.
121
246
  - Never use commit-message text matching as a classification input, and never
122
247
  auto-resolve cherry-pick conflicts.
248
+ - Never delete an origin branch, or run plain filesystem removal on an orphaned
249
+ worktree-tracking directory, without explicit per-item user confirmation — both are
250
+ outside this skill's pre-approved tool surface regardless of how the triage verdict
251
+ came out.
123
252
 
124
253
  ## Cross-References
125
254
 
@@ -130,3 +259,6 @@ single session with no PR.
130
259
  - `.claude/rules/shell.md` — the bash toolchain (shfmt/shellcheck/bats/kcov), the
131
260
  500-line cap, the no-temp-files test policy, and the `CLEANUP_WT_GIT_BIN` seam
132
261
  convention.
262
+ - `.claude/skills/feature-promotion-lifecycle/SKILL.md` — the potential-entry-to-issue
263
+ promotion path used by the Dirty Worktree Triage Procedure's step 9 for `PRESERVE`
264
+ findings that describe unresolved product scope.
@@ -12,6 +12,8 @@ This direct-use wrapper delegates feature-document work to the `prd-feature` wor
12
12
  - Feature folder issue and research context
13
13
  - Existing spec and user-story files when present
14
14
 
15
+ For a numeric `spec.md` acceptance criterion, the research context must contain complete `## Numeric Derivation Evidence` with `Complete Family`, `Exhaustive Search Scope`, `Inclusion Rules`, `Exclusion Rules`, `Primary Search Strategy or Query Expression`, `Primary Member Set`, `Primary Count`, `Cross-check Search Strategy or Query Expression`, `Cross-check Member Set`, `Cross-check Count`, and `Member-set Comparison`. The two derivations must be non-empty, independently constructed, distinct in strategy or query expression, exhaustive across the complete family, independently enumerated, and explicitly compared. The worker must withhold a numeric assertion for missing, copied, incomplete, non-exhaustive, narrow, or disagreeing evidence; a single grep, a named-pattern-only query, matching totals, distinct query text, or equal member sets alone does not approve a number.
16
+
15
17
  ## Output Paths
16
18
 
17
19
  - `docs/features/active/<feature>/spec.md`
@@ -20,3 +22,4 @@ This direct-use wrapper delegates feature-document work to the `prd-feature` wor
20
22
  ## Worker Routing
21
23
 
22
24
  - Worker: `prd-feature`
25
+ - Require the worker to report the authoritative `research-path` when a numeric acceptance criterion is written.
@@ -21,6 +21,8 @@ this operation may and may not disturb. Read that section before applying anythi
21
21
 
22
22
  ## Prerequisites
23
23
 
24
+ - Reject a pending or not-started run with guidance to consolidate the initial set through `/parallel-plan`. Admit exactly one item only after execution has started in an open run; closed runs are not eligible.
25
+
24
26
  - A parallel run is in progress and `artifacts/orchestration/parallel-orchestrator-state.json`
25
27
  tracks its `parallel_slug`. This skill does not start a run; use `/parallel-plan` and
26
28
  `/parallel-run` for that.
@@ -64,7 +66,9 @@ re-derivation is mandatory and is not an optimization to skip when the checkpoin
64
66
  required parsed `config/blast-radius.json` mapping, which push-down publishes into the
65
67
  destination workspace. `conflicts(a, b, config)` in `scripts/dev_tools/compute_blast_radius.py`
66
68
  (defined in `scripts/dev_tools/_blast_radius_conflicts.py`) remains the repository authority and
67
- the parity reference. Map each conflicting pair onto an `(int, int)` conflict edge
69
+ the parity reference. Read the verdict from the conflict key of the returned hashtable.
70
+ The hashtable itself is always truthy, so a bare boolean test on the result treats every pair as
71
+ conflicting. Map each conflicting pair onto an `(int, int)` conflict edge
68
72
  of `items[].issue_num` values, normalized so `a < b`. Do not reimplement the relation and do not
69
73
  compute edges over the unstarted subset only: an in-flight conflict is precisely what the
70
74
  admission decision turns on.
@@ -387,15 +387,21 @@ checkout, never from inside a child worktree — issues `git worktree remove <wo
387
387
  success it records `merge_status: worktree_removed` and `worktree_removed_at`, then regenerates
388
388
  `docs/features/parallel/<slug>/parallel-status.md`.
389
389
 
390
- Mechanical gating of this command for parallel worktrees is F7 scope.
391
- `.claude/hooks/enforce-epic-worktree-removal-gate.ps1` is a project-wide `PreToolUse` Bash-matcher
392
- hook that denies any `git worktree remove` unless the epic checkpoint carries a matching
393
- `features[]` record whose `merge_status` is `merged` or `worktree_removed`; an unreadable checkpoint
394
- or an absent record also denies. Its block reason is `EPIC_WORKTREE_REMOVAL_BLOCKED`. A parallel run
395
- has no epic checkpoint record for its worktrees, so removal is denied until F7 both delivers
396
- `enforce-parallel-worktree-removal-gate.ps1` and coordinates the epic gate's allow conditions:
397
- `PreToolUse` denials are conjunctive, so a new allow-hook alone cannot override the existing deny.
398
- This feature ships no hook file and makes no `.claude/settings.json` change.
390
+ Mechanical gating of this command for parallel worktrees is delivered. Both halves have landed.
391
+ `.claude/hooks/enforce-parallel-worktree-removal-gate.ps1` exists and is registered in
392
+ `.claude/settings.json` on the `Bash` matcher; it authorizes a removal from the
393
+ parallel-orchestrator checkpoint and owns the block reason
394
+ `PARALLEL_WORKTREE_REMOVAL_BLOCKED`. `.claude/hooks/enforce-epic-worktree-removal-gate.ps1` is a
395
+ project-wide `PreToolUse` Bash-matcher hook registered alongside it whose block reason is
396
+ `EPIC_WORKTREE_REMOVAL_BLOCKED`; it now carries a second, parallel allow-branch, so it authorizes a
397
+ removal either from a matching epic checkpoint `features[]` record or from a parallel-orchestrator
398
+ checkpoint whose `route_id` is `parallel` and whose matching `items[].worktree_path` record has
399
+ `merge_status` in `{merged, worktree_removed}`. An unreadable checkpoint, an absent record, or a
400
+ non-authorizing `merge_status` still denies on both branches. The coordination matters because
401
+ `PreToolUse` denials are conjunctive: a new allow-hook alone could not have overridden the epic
402
+ gate's independent deny, which is why the epic gate itself had to gain the parallel branch.
403
+ The parallel-orchestrator-surface feature (F7) shipped no hook file and made no
404
+ `.claude/settings.json` change of its own.
399
405
 
400
406
  ## Documentation Maintenance Boundaries
401
407
 
@@ -736,6 +742,9 @@ against `items[].worktree_path`. Removal is allowed only when that item's `merge
736
742
  or `worktree_removed`; anything else — including an unreadable checkpoint or no matching record —
737
743
  denies with a reason prefixed `PARALLEL_WORKTREE_REMOVAL_BLOCKED`. Commands that are not
738
744
  `git worktree remove` always allow. This is the mechanical counterpart to `## Worktree Cleanup`.
745
+ `.claude/hooks/enforce-epic-worktree-removal-gate.ps1` fires on the same command and now carries a
746
+ matching parallel allow-branch keyed on the same checkpoint, so both gates must allow for a removal
747
+ to proceed.
739
748
 
740
749
  **Invocation-origin extension.** `.claude/hooks/enforce-epic-invocation-origin.ps1` was extended
741
750
  additively so `$script:GatedSubagentTypes` lists `epic-planner`, `epic-orchestrator`,
@@ -32,6 +32,8 @@ Before proceeding, `parallel-planner` must:
32
32
 
33
33
  ## Item Intake
34
34
 
35
+ Initial intake must provide the complete item set in one `/parallel-plan <slug> <item> [<item> ...]` invocation before waves are calculated. `/parallel-add` is not an initial-intake path.
36
+
35
37
  Invocation shape: `/parallel-plan <slug> <item> [<item> ...]`, where each `<item>` is either a
36
38
  GitHub issue number (already-promoted work) or a potential-entry path (unpromoted work). This is
37
39
  the same intake domain as `/parallel-add`, so initial intake here and F6's add operation accept
@@ -214,7 +216,9 @@ as-is and never reimplemented here:
214
216
  `compute_blast_radius.py`. The signature takes three arguments; the third is the parsed
215
217
  `config/blast-radius.json`. Reasons come from the fixed vocabulary
216
218
  `{path_overlap, module_overlap, shared_surface_overlap, contract_dependency}`, and the relation
217
- fails closed.
219
+ fails closed. Read the verdict from the conflict field of the returned ConflictResult.
220
+ The result's boolean projection now agrees with that field, so `if conflicts(a, b, config):`
221
+ yields the verdict rather than the unconditional truth a bare object test gave before issue #576.
218
222
 
219
223
  **The F1a corrections (issue #452, merged PR #453) are load-bearing.** Derivation now reaches
220
224
  separator-free repository-root shared surfaces from plan and spec text, admitting such a token only
@@ -303,6 +307,11 @@ The library returns the partition; the planner supplies the record fields.
303
307
  item is `prepared` and radius-validated. Derive the conflict edge set by applying
304
308
  `Test-BlastRadiusConflict` to every unordered pair of `declared` radii, then pass the pairs as
305
309
  `--edges "<a>:<b> ..."` and the item keys as `--keys "<k1> <k2> ..."`.
310
+ Read the verdict from the conflict key of the returned hashtable.
311
+ The hashtable itself is always truthy, so a bare boolean test on the result treats every pair as
312
+ conflicting and serializes the whole run. This is the sibling hazard to the `@(...)` warning
313
+ above for `Test-BlastRadius`: that function writes an `IList`-shaped pipeline result whose
314
+ emptiness is falsy, while this one returns a hashtable whose emptiness is not expressible at all.
306
315
  2. Immediately after the conflict-edge set is derived and before anything consumes it, run the
307
316
  lane-assertion diagnostic:
308
317
  `poetry run python -m scripts.dev_tools.parallel_lane_assertion --manifest docs/features/parallel/<slug>/parallel.md --edges "<a>:<b> ..."`
@@ -28,3 +28,25 @@ If the artifacts are missing or stale relative to the current branch state, re-g
28
28
  - Do not infer the refresh base from the repository default branch unless merge-base resolution fails for all candidates.
29
29
  - Treat an already-fresh artifact pair as authoritative; do not refresh solely because no explicit `PRBaseBranch` input was provided.
30
30
 
31
+ ### Freshness Cross-Check
32
+
33
+ Both artifacts open with a `Context generated` section carrying the generation timestamp and a
34
+ `Head SHA:` line. Decide freshness from those two values in two steps, and from nothing else.
35
+
36
+ 1. **Pair identity.** The generated-context timestamp must be byte-identical in the summary and in
37
+ the appendix. A mismatch proves the two files came from different invocations — a summary
38
+ refreshed while a stale appendix persists, or the reverse — so the pair does not describe one
39
+ run and must be regenerated.
40
+ 2. **Head binding.** The head SHA recorded in both files must equal the current head of the branch
41
+ under review. A mismatch proves the pair predates the current head, so it describes a different
42
+ diff than the one being reviewed and must be regenerated.
43
+
44
+ File existence and file modification time are not freshness signals. A file left at the expected
45
+ path by a previous invocation satisfies an existence check, and a stale file that was copied or
46
+ touched satisfies a modification-time check. Both operands of the cross-check above are read from
47
+ the artifacts themselves and from git, so the check is deterministic and does not depend on a wall
48
+ clock.
49
+
50
+ When the head SHA renders the `(unknown)` token, the collected context carried no head SHA. Head
51
+ binding cannot be established in that case, so treat the pair as unverified and regenerate it.
52
+
@@ -81,6 +81,10 @@ Timestamp rule:
81
81
 
82
82
  A cycle with fewer than five artifacts is malformed. A cycle that uses the same timestamp value for both its `remediation/<ts>/` and `audit/<ts>/` folders is malformed unless entry and exit genuinely ran within the same minute — the two folders remain distinct either way, since one is named `remediation/` and the other `audit/`.
83
83
 
84
+ ### Cycle-Document Sweep Scope
85
+
86
+ A comprehensive or final sweep in a remediation cycle covers that cycle's own plan and audit documents — `remediation-plan.md`, `code-review.md`, `feature-audit.md`, and `policy-audit.md` — in addition to production and test code. The failure mechanism a code-only sweep leaves open is self-referential rule violation: a policy-compliance fix whose own descriptive text violates the policy it enforces is written into one of those four documents rather than into code, so a sweep scoped to code only reports no finding and the violation ships with the cycle.
87
+
84
88
  ## Plan Shape
85
89
 
86
90
  `remediation/<entry-ts>/remediation-plan.md` MUST conform to `.claude/skills/atomic-plan-contract/SKILL.md`. In particular:
@@ -102,6 +106,14 @@ After the plan is authored, `atomic-executor` runs preflight under the directive
102
106
 
103
107
  The orchestrator records the preflight outcome in `remediation_loop.cycles[current_cycle].preflight` with `iterations` (counter) and `final_status` (`clear|changes_requested|pending`).
104
108
 
109
+ For a well-scoped item where `preflight.iterations > 1`, record a process-defect investigation that identifies the incomplete planner internal-review dimension. Treat excess rounds as a process signal, not routine iteration.
110
+
111
+ The exhaustive-pass, defect-enumeration, and delta-self-check rules that govern how `atomic-executor` conducts preflight are defined in the `## Preflight Validation (Planner ↔ Executor)` section of `.claude/skills/atomic-plan-contract/SKILL.md` and are not restated here.
112
+
113
+ Alongside `iterations` and `final_status`, the orchestrator also records in `remediation_loop.cycles[current_cycle].preflight` the convergence line `atomic-executor` returned on that round, which is one of `CONVERGENCE: NO FURTHER ROUNDS EXPECTED` or `CONVERGENCE: FURTHER ROUNDS LIKELY`. This convergence field extends the field set already recorded at `remediation_loop.cycles[current_cycle].preflight` rather than replacing it: `iterations` and `final_status` continue to be recorded exactly as stated above, and the convergence field is written in addition to them.
114
+
115
+ Iteration ceiling. When a cycle's `iterations` would exceed 2, the orchestrator records `final_status: "blocked_preflight_iteration_limit"`, halts the preflight sub-loop, and escalates to the caller, rather than continuing the sub-loop indefinitely. `blocked_preflight_iteration_limit` is a fourth `final_status` value extending the `clear|changes_requested|pending` enumeration stated above. This ceiling bounds the repeat-until-clear behavior stated above it: the sub-loop still repeats until `PREFLIGHT: ALL CLEAR` is returned, and the ceiling supplies the terminating condition for the case where that signal is not reached within two iterations.
116
+
105
117
  ## Execution and Reaudit
106
118
 
107
119
  When preflight is clear, `atomic-executor` executes the plan task-by-task. The executor invokes workers (`python-typed-engineer`, `typescript-engineer`, `csharp-typed-engineer`, `powershell-typed-engineer`) internally as needed. The orchestrator does not call workers.
@@ -55,6 +55,8 @@ Create or update a single research file at one of the two tracked research roots
55
55
 
56
56
  - Map acceptance criteria into a concrete design.
57
57
  - Propose state model, transitions, internal API boundaries, and required file changes.
58
+ - For every numeric count, enumeration, or population proposed for an approved `spec.md` acceptance criterion, add complete `## Numeric Derivation Evidence`. Each record must identify `Complete Family`, `Exhaustive Search Scope`, `Inclusion Rules`, `Exclusion Rules`, `Primary Search Strategy or Query Expression`, `Primary Member Set`, `Primary Count`, `Cross-check Search Strategy or Query Expression`, `Cross-check Member Set`, `Cross-check Count`, and `Member-set Comparison`.
59
+ - Both derivations must be non-empty and independently constructed. They must use distinct search strategies or query expressions, independently enumerate the member sets, and explicitly compare normalized member sets. The scope must cover the entire declared family, including all relevant overloads and members; reject a single grep, a narrow named-pattern search, or a query that covers only one family member even when totals and member sets appear equal. Withhold the numeric assertion if the records are incomplete, duplicated, non-exhaustive, narrow, or disagree.
58
60
 
59
61
  ### 5. Testing Implications
60
62
 
@@ -67,3 +69,4 @@ Create or update a single research file at one of the two tracked research roots
67
69
  - Ground all findings in verified evidence from the codebase and authoritative external sources.
68
70
  - Keep discussion of non-selected approaches brief.
69
71
  - Do not claim or perform nested worker delegation.
72
+ - Omit numeric acceptance-criterion facts when the numeric derivation record is absent, incomplete, or disagrees.
@@ -53,6 +53,7 @@
53
53
  ".claude/hooks/validate-feature-review-coverage.ps1",
54
54
  ".claude/hooks/validate-orchestrator-output.ps1",
55
55
  ".claude/hooks/validate-planner-output.ps1",
56
+ ".claude/hooks/validate-prd-feature-output.ps1",
56
57
  ".claude/hooks/validate-required-artifact-output.ps1",
57
58
  ".claude/hooks/validate-task-researcher-output.ps1",
58
59
  ".claude/rules/architecture-boundaries.md",
@@ -110,6 +111,7 @@
110
111
  ".claude/skills/translate-copilot-to-claude/SKILL.md",
111
112
  ".claude/skills/update-status/SKILL.md",
112
113
  ".claude/lib/hook-payload/HookPayload.psm1",
114
+ ".claude/lib/requirements/GeneratedDocumentCounters.psm1",
113
115
  ".claude/lib/model-routing/ModelRouting.psm1",
114
116
  ".claude/lib/orchestrator-state/OrchestratorState.psm1",
115
117
  ".claude/lib/orchestrator-state/OrchestratorStateCompletion.psm1",