@danmoisan/drm-copilot-mcp 1.1.17 → 1.1.18

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 (56) hide show
  1. package/out/mcp-server.js +500 -106
  2. package/package.json +4 -3
  3. package/resources/claude-customizations/.claude/agents/feature-review.md +10 -1
  4. package/resources/claude-customizations/.claude/agents/orchestrator.md +16 -3
  5. package/resources/claude-customizations/.claude/agents/parallel-orchestrator.md +6 -0
  6. package/resources/claude-customizations/.claude/lib/bash/parallel-lane-assertion.sh +4 -2
  7. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorState.psm1 +6 -13
  8. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateIssueAdoption.psm1 +375 -0
  9. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateReceipts.psm1 +22 -15
  10. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateRemediationAccounting.psm1 +337 -0
  11. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateRoutingContract.psm1 +9 -1
  12. package/resources/claude-customizations/.claude/rules/orchestrator-state.md +119 -3
  13. package/resources/claude-customizations/.claude/rules/quality-tiers.md +1 -1
  14. package/resources/claude-customizations/.claude/skills/acceptance-criteria-tracking/SKILL.md +8 -0
  15. package/resources/claude-customizations/.claude/skills/atomic-plan-contract/SKILL.md +2 -0
  16. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/SKILL.md +11 -3
  17. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup-worktrees.sh +11 -2
  18. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_enumerate_lib.sh +169 -5
  19. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_preserve_lib.sh +1 -1
  20. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_report_records_lib.sh +6 -43
  21. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_scan_helper.sh +4 -15
  22. package/resources/claude-customizations/.claude/skills/epic-orchestrate/SKILL.md +13 -6
  23. package/resources/claude-customizations/.claude/skills/evidence-and-timestamp-conventions/SKILL.md +4 -0
  24. package/resources/claude-customizations/.claude/skills/feature-promotion-lifecycle/SKILL.md +10 -0
  25. package/resources/claude-customizations/.claude/skills/feature-review-workflow/SKILL.md +3 -1
  26. package/resources/claude-customizations/.claude/skills/orchestrate/SKILL.md +30 -12
  27. package/resources/claude-customizations/.claude/skills/parallel-orchestrate/SKILL.md +18 -3
  28. package/resources/claude-customizations/.claude/skills/remediation-handoff-atomic-planner/SKILL.md +5 -1
  29. package/resources/claude-customizations/pack-manifests/core.json +2 -0
  30. package/resources/codex-and-agents-customizations/.agents/skills/acceptance-criteria-tracking/SKILL.md +8 -0
  31. package/resources/codex-and-agents-customizations/.agents/skills/epic-orchestrate/SKILL.md +5 -3
  32. package/resources/codex-and-agents-customizations/.agents/skills/evidence-and-timestamp-conventions/SKILL.md +4 -0
  33. package/resources/codex-and-agents-customizations/.agents/skills/feature-promotion-lifecycle/SKILL.md +1 -1
  34. package/resources/codex-and-agents-customizations/.agents/skills/feature-review/SKILL.md +30 -6
  35. package/resources/codex-and-agents-customizations/.agents/skills/feature-review-workflow/SKILL.md +3 -1
  36. package/resources/codex-and-agents-customizations/.agents/skills/orchestrate/SKILL.md +30 -7
  37. package/resources/codex-and-agents-customizations/.agents/skills/orchestrator-state/SKILL.md +41 -2
  38. package/resources/codex-and-agents-customizations/.agents/skills/orchestrator-workflow/SKILL.md +18 -3
  39. package/resources/codex-and-agents-customizations/.agents/skills/quality-tiers/SKILL.md +1 -1
  40. package/resources/codex-and-agents-customizations/.agents/skills/remediation-handoff-atomic-planner/SKILL.md +2 -0
  41. package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c1.toml +1 -0
  42. package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c2.toml +1 -0
  43. package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c3-elevated.toml +1 -0
  44. package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c3.toml +1 -0
  45. package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c4.toml +1 -0
  46. package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer.toml +1 -0
  47. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c1.toml +1 -1
  48. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c2.toml +1 -1
  49. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c3-elevated.toml +1 -1
  50. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c3.toml +1 -1
  51. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c4.toml +1 -1
  52. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator.toml +1 -1
  53. package/resources/codex-and-agents-customizations/.codex/config.toml +1 -1
  54. package/resources/customizations/.github/skills/acceptance-criteria-tracking/SKILL.md +8 -0
  55. package/resources/customizations/.github/skills/evidence-and-timestamp-conventions/SKILL.md +4 -0
  56. package/resources/powershell/PoshQC/settings/pester.runsettings.psd1 +4 -0
@@ -4,16 +4,19 @@
4
4
  # every file within the 500-line cap. Provides the git-binary test seam
5
5
  # (cleanup_wt_git), branch/worktree enumeration (enumerate_branches,
6
6
  # parse_worktree_list), path normalization (normalize_wt_path), the
7
- # current-worktree/branch and base-branch protection set (compute_protected), and
8
- # the main-freshness warning (check_main_freshness). The classification ladder,
9
- # consolidation, deletion, and the CLI live in sibling files (cleanup_worktrees_lib.sh,
10
- # cleanup_worktrees_actions_lib.sh, cleanup-worktrees.sh).
7
+ # current-worktree/branch and base-branch protection set (compute_protected), the
8
+ # main-freshness warning (check_main_freshness), the shared absolute-path predicate
9
+ # (cleanup_wt_is_absolute_path), and the worktree-tracking scan roots
10
+ # (cleanup_wt_split_roots, cleanup_wt_derive_scan_roots, cleanup_wt_scan_roots). The
11
+ # classification ladder, consolidation, deletion, and the CLI live in sibling files
12
+ # (cleanup_worktrees_lib.sh, cleanup_worktrees_actions_lib.sh, cleanup-worktrees.sh).
11
13
  #
12
14
  # Sourcing contract: defines functions and the single constant CLEANUP_WT_BASE_BRANCH
13
15
  # and runs no other work at source time, so wrapper and bats suites source it safely.
14
16
  # It MUST be sourced before cleanup_worktrees_lib.sh, whose classification functions
15
17
  # call cleanup_wt_git, parse_worktree_list, compute_protected, and normalize_wt_path
16
- # defined here.
18
+ # defined here. The filesystem-scan helper cleanup_worktrees_scan_helper.sh runs as a
19
+ # separate process and sources this library directly for cleanup_wt_is_absolute_path.
17
20
  #
18
21
  # All git commands go through cleanup_wt_git so tests can stub the git binary via
19
22
  # CLEANUP_WT_GIT_BIN. Git exit-code capture rule: the `git worktree list --porcelain`
@@ -250,3 +253,164 @@ check_main_freshness() {
250
253
  fi
251
254
  return 0
252
255
  }
256
+
257
+ cleanup_wt_is_absolute_path() {
258
+ # Return 0 when <path> is absolute, else 1. Pure: no filesystem access.
259
+ #
260
+ # Absolute forms are a leading `/` (POSIX paths, MSYS `/c/...` paths, and `//server`
261
+ # UNC paths) and a drive letter followed by `/` or `\` (`C:/...`, `c:/...`,
262
+ # `C:\...`), which is the form Git for Windows writes into a worktree's `.git`
263
+ # pointer file (issue #706). A drive letter with no separator (`C:rel`) is
264
+ # drive-relative and is not absolute; an empty path is not absolute. This is the one
265
+ # absolute-path predicate of the skill: the preserve library and the filesystem-scan
266
+ # helper both call it.
267
+ #
268
+ # Args: $1 = path. Returns 0 (absolute) or 1 (not absolute).
269
+ local path=${1:-}
270
+ [[ $path == /* || $path == [A-Za-z]:[/\\]* ]]
271
+ }
272
+
273
+ cleanup_wt_split_roots() {
274
+ # Split a CLEANUP_WT_ORPHAN_ROOTS value into absolute roots, one per line.
275
+ #
276
+ # Entries are separated by `;`, by a newline, or by `:`. A `:` is part of the path
277
+ # instead when the text before it in the current entry is exactly one ASCII letter
278
+ # and the character after it is `/` or `\` (a drive letter, as in `C:/x`). Empty
279
+ # entries are dropped. An entry that is not absolute (cleanup_wt_is_absolute_path) is
280
+ # dropped with a one-line stderr diagnostic naming it, because a relative root would
281
+ # be resolved against the process's current working directory.
282
+ #
283
+ # The value is walked one character at a time with parameter expansion and never
284
+ # word-split, so no pathname expansion occurs and a `*` is emitted literally.
285
+ #
286
+ # Args: $1 = the override value. Always returns 0.
287
+ local value=${1:-}
288
+ local -a entries=()
289
+ local entry="" ch next i
290
+ for ((i = 0; i < ${#value}; i++)); do
291
+ ch=${value:i:1}
292
+ if [[ $ch == ';' || $ch == $'\n' ]]; then
293
+ entries+=("$entry")
294
+ entry=""
295
+ elif [[ $ch == ':' ]]; then
296
+ next=${value:i+1:1}
297
+ if [[ ${#entry} -eq 1 && $entry == [A-Za-z] && $next == [/\\] ]]; then
298
+ entry+=$ch
299
+ else
300
+ entries+=("$entry")
301
+ entry=""
302
+ fi
303
+ else
304
+ entry+=$ch
305
+ fi
306
+ done
307
+ entries+=("$entry")
308
+ for entry in "${entries[@]}"; do
309
+ [[ -z $entry ]] && continue
310
+ if ! cleanup_wt_is_absolute_path "$entry"; then
311
+ printf 'cleanup-worktrees: CLEANUP_WT_ORPHAN_ROOTS entry is not absolute, dropped: %s\n' "$entry" >&2
312
+ continue
313
+ fi
314
+ printf '%s\n' "$entry"
315
+ done
316
+ return 0
317
+ }
318
+
319
+ cleanup_wt_derive_scan_roots() {
320
+ # Echo the registration-derived scan roots, one per line.
321
+ #
322
+ # Input is parse_worktree_list output; its first record is the main worktree. The
323
+ # candidate for every later record is the parent directory of its path (backslashes
324
+ # converted to `/`). A candidate is kept only when its normalize_wt_path value N:
325
+ # - is not the main worktree's normalized path and is not one of its ancestors
326
+ # (scanning an ancestor would list the main worktree's siblings), and
327
+ # - is not equal to, and not inside, any registered worktree, main included
328
+ # (its subdirectories are that worktree's own content, not worktrees).
329
+ # Kept candidates are emitted in LC_ALL=C order of N, once per N, using the first
330
+ # spelling seen in record order.
331
+ #
332
+ # Args: $1 = parse_worktree_list output. Always returns 0.
333
+ local records=${1:-}
334
+ local -a paths=() norms=()
335
+ local record path
336
+ while IFS= read -r record; do
337
+ [[ -z $record ]] && continue
338
+ path=${record%%|*}
339
+ paths+=("$path")
340
+ norms+=("$(normalize_wt_path "$path")")
341
+ done <<<"$records"
342
+ ((${#paths[@]} < 2)) && return 0
343
+ local main_norm=${norms[0]}
344
+ local -A seen=()
345
+ local -a kept=()
346
+ local i p parent n w inside
347
+ for ((i = 1; i < ${#paths[@]}; i++)); do
348
+ p=${paths[i]//\\//}
349
+ parent=${p%/*}
350
+ [[ -z $parent || $parent == "$p" ]] && continue
351
+ n=$(normalize_wt_path "$parent")
352
+ [[ -z $n || -n ${seen[$n]:-} ]] && continue
353
+ [[ $n == "$main_norm" || $main_norm == "$n"/* ]] && continue
354
+ inside=0
355
+ for w in "${norms[@]}"; do
356
+ [[ -z $w ]] && continue
357
+ if [[ $n == "$w" || $n == "$w"/* ]]; then
358
+ inside=1
359
+ break
360
+ fi
361
+ done
362
+ ((inside == 1)) && continue
363
+ seen[$n]=1
364
+ kept+=("$n|$parent")
365
+ done
366
+ ((${#kept[@]} == 0)) && return 0
367
+ local line
368
+ while IFS= read -r line; do
369
+ printf '%s\n' "${line#*|}"
370
+ done < <(printf '%s\n' "${kept[@]}" | LC_ALL=C sort -t '|' -k1,1)
371
+ return 0
372
+ }
373
+
374
+ cleanup_wt_scan_roots() {
375
+ # Echo the worktree-tracking roots to scan, one per line.
376
+ #
377
+ # Configured roots come first: the CLEANUP_WT_ORPHAN_ROOTS entries
378
+ # (cleanup_wt_split_roots) when that variable is set, otherwise the default pair
379
+ # derived from the main worktree path (the first `git worktree list --porcelain`
380
+ # stanza, the same derivation consolidation_worktree_path uses in
381
+ # cleanup_worktrees_actions_lib.sh): `<main>/.claude/worktrees` then `<main>-wt`.
382
+ # Registration-derived roots (cleanup_wt_derive_scan_roots) are always appended.
383
+ # The combined list is deduplicated by normalize_wt_path, keeping the first spelling.
384
+ #
385
+ # The listing is read once (`out=$(...) || rc=$?`). On a parse_worktree_list hard
386
+ # failure nothing is derived from it: with no override no root is emitted at all,
387
+ # rather than a bare relative path resolved against the current working directory,
388
+ # and with an override exactly the override roots are emitted.
389
+ # cleanup_wt_scan_records returns 0 with no record for an empty root list, so the
390
+ # advisory records degrade to silence rather than to a misleading scan.
391
+ # Always returns 0.
392
+ local out rc=0 first_record main_wt="" configured="" derived=""
393
+ out=$(parse_worktree_list) || rc=$?
394
+ if ((rc == 0)); then
395
+ first_record=${out%%$'\n'*}
396
+ main_wt=${first_record%%|*}
397
+ derived=$(cleanup_wt_derive_scan_roots "$out")
398
+ fi
399
+ if [[ -n ${CLEANUP_WT_ORPHAN_ROOTS:-} ]]; then
400
+ configured=$(cleanup_wt_split_roots "$CLEANUP_WT_ORPHAN_ROOTS")
401
+ elif [[ -n $main_wt ]]; then
402
+ configured="${main_wt}/.claude/worktrees"$'\n'"${main_wt}-wt"
403
+ fi
404
+ local -A seen=()
405
+ local root n
406
+ while IFS= read -r root; do
407
+ [[ -z $root ]] && continue
408
+ n=$(normalize_wt_path "$root")
409
+ # A root of `/` normalizes to empty, which is not a valid array key.
410
+ [[ -z $n ]] && n=/
411
+ [[ -n ${seen[$n]:-} ]] && continue
412
+ seen[$n]=1
413
+ printf '%s\n' "$root"
414
+ done <<<"${configured}"$'\n'"${derived}"
415
+ return 0
416
+ }
@@ -158,7 +158,7 @@ preserve_relative_path_reason() {
158
158
  local name=${1-} val=${2-}
159
159
  if [[ -z $val ]]; then
160
160
  printf '%s is empty' "$name"
161
- elif [[ $val == /* || $val == [A-Za-z]:[\\/]* ]]; then
161
+ elif cleanup_wt_is_absolute_path "$val"; then
162
162
  printf '%s is absolute: %s' "$name" "$val"
163
163
  elif [[ $val == ".." || $val == "../"* || $val == *"/../"* || $val == *"/.." ]]; then
164
164
  printf '%s contains a .. segment: %s' "$name" "$val"
@@ -6,10 +6,10 @@
6
6
  # whose gitdir pointer no longer resolves, and the ancestor relationship between two
7
7
  # branches that both resolve NOT_MERGED. The enumeration/protection seam
8
8
  # (cleanup_wt_git, enumerate_branches, parse_worktree_list, normalize_wt_path,
9
- # compute_protected, check_main_freshness) lives in cleanup_worktrees_enumerate_lib.sh
10
- # and the classification ladder (classify_branch) lives in cleanup_worktrees_lib.sh;
11
- # both MUST be sourced before this file. Keeping these records in a sibling file keeps
12
- # every file within the 500-line cap.
9
+ # compute_protected, check_main_freshness, cleanup_wt_scan_roots) lives in
10
+ # cleanup_worktrees_enumerate_lib.sh and the classification ladder (classify_branch)
11
+ # lives in cleanup_worktrees_lib.sh; both MUST be sourced before this file. Keeping
12
+ # these records in a sibling file keeps every file within the 500-line cap.
13
13
  #
14
14
  # Sourcing contract: this library defines functions only; it never runs work at source
15
15
  # time, so the wrapper and the bats suites can source it without side effects.
@@ -111,47 +111,10 @@ scan_stale_refs() {
111
111
  return 0
112
112
  }
113
113
 
114
- cleanup_wt_scan_roots() {
115
- # Echo the worktree-tracking roots to scan, one per line.
116
- #
117
- # CLEANUP_WT_ORPHAN_ROOTS overrides the derivation with a colon-separated list.
118
- # Otherwise BOTH roots derive from the main worktree path — the first
119
- # `git worktree list --porcelain` stanza, the same derivation
120
- # consolidation_worktree_path uses in cleanup_worktrees_actions_lib.sh. They are
121
- # `<main-worktree-path>` joined with `.claude/worktrees` (the agent worktree folder)
122
- # and `<main-worktree-path>-wt` (the sibling worktree folder), in that order.
123
- #
124
- # Deriving both from one read means a parse_worktree_list hard failure emits no root
125
- # at all, rather than a bare relative path that would be resolved against whatever
126
- # the process's current working directory happened to be. cleanup_wt_scan_records
127
- # returns 0 with no record for an empty root list, so the advisory records degrade to
128
- # silence rather than to a misleading scan. Always returns 0.
129
- local override=${CLEANUP_WT_ORPHAN_ROOTS:-}
130
- if [[ -n $override ]]; then
131
- local IFS=:
132
- local part
133
- for part in $override; do
134
- [[ -n $part ]] && printf '%s\n' "$part"
135
- done
136
- return 0
137
- fi
138
- local out rc=0 first_record main_wt=""
139
- out=$(parse_worktree_list) || rc=$?
140
- if ((rc != 0)); then
141
- return 0
142
- fi
143
- first_record=${out%%$'\n'*}
144
- main_wt=${first_record%%|*}
145
- if [[ -n $main_wt ]]; then
146
- printf '%s\n' "${main_wt}/.claude/worktrees"
147
- printf '%s\n' "${main_wt}-wt"
148
- fi
149
- return 0
150
- }
151
-
152
114
  cleanup_wt_scan_records() {
153
115
  # Echo the raw `<path>|<has_gitfile>|<gitdir_target_exists>|<size>` records for every
154
- # candidate directory under the resolved scan roots, one per line.
116
+ # candidate directory under the resolved scan roots, one per line. The roots come
117
+ # from cleanup_wt_scan_roots in cleanup_worktrees_enumerate_lib.sh.
155
118
  #
156
119
  # Every filesystem read goes through the CLEANUP_WT_SCAN_BIN seam, so the bats suites
157
120
  # replay canned records instead of touching the real filesystem. The scan output is
@@ -40,6 +40,9 @@
40
40
  # the SHELL_QC_<TOOL>_BIN seams substitute a checked-in stand-in for a real dependency.
41
41
  # An empty value is treated as missing and falls back to `.git`.
42
42
  set -euo pipefail
43
+ # shellcheck source=.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_enumerate_lib.sh
44
+ # shellcheck disable=SC1091
45
+ source "$(dirname -- "${BASH_SOURCE[0]}")/cleanup_worktrees_enumerate_lib.sh"
43
46
 
44
47
  scan_helper_dir_size() {
45
48
  # Echo the best-effort human-readable size of a directory, or `unknown`.
@@ -70,20 +73,6 @@ scan_helper_gitfile_name() {
70
73
  printf '%s\n' ".git"
71
74
  }
72
75
 
73
- scan_helper_is_absolute_path() {
74
- # Return 0 when <path> is absolute, else 1. Pure: no filesystem access.
75
- #
76
- # Absolute forms are a leading `/` (POSIX paths, MSYS `/c/...` paths, and `//server`
77
- # UNC paths) and a drive letter followed by `/` or `\` (`C:/...`, `c:/...`,
78
- # `C:\...`), which is the form Git for Windows writes into a worktree's `.git`
79
- # pointer file (issue #706). A drive letter with no separator (`C:rel`) is
80
- # drive-relative and is not absolute; an empty path is not absolute.
81
- #
82
- # Args: $1 = path. Returns 0 (absolute) or 1 (not absolute).
83
- local path=${1:-}
84
- [[ $path == /* || $path == [A-Za-z]:[/\\]* ]]
85
- }
86
-
87
76
  scan_helper_target_present() {
88
77
  # Return 0 when <path> exists, else non-zero. This is the helper's single
89
78
  # filesystem existence check, kept in its own function as a test seam: bats tests
@@ -113,7 +102,7 @@ scan_helper_gitdir_target_exists() {
113
102
  printf '0\n'
114
103
  return 0
115
104
  fi
116
- if ! scan_helper_is_absolute_path "$target"; then
105
+ if ! cleanup_wt_is_absolute_path "$target"; then
117
106
  target="$dir/$target"
118
107
  fi
119
108
  if scan_helper_target_present "$target"; then
@@ -221,9 +221,10 @@ Procedure, triggered by S9 step 6's merge failure:
221
221
  3. The existing R1–R5 loop processes this finding exactly as a local blocking finding:
222
222
  `atomic-planner` (R1) plans the resolution, `atomic-executor` performs preflight (R2) then
223
223
  resolves the conflict markers, stages, and commits (R3), `feature-review` re-audits (R4).
224
- 4. The child's own `remediation_pass` counter is shared with local-finding and CI-failure passes
225
- (cap 3), unmodified.
226
- 5. On the third conflict pass without resolution, the child's `orchestrator` records
224
+ 4. Conflict cycles share the child's own `remediation_loop.completed_attempts` count with
225
+ local-finding and CI-failure cycles. The active cycle number is `completed_attempts + 1`, and a
226
+ cycle without an applied candidate consumes no number.
227
+ 5. After three completed attempts without resolution, the child's `orchestrator` records
227
228
  `step9_status: "blocked_conflict_loop_limit"` (parallel to `blocked_ci_loop_limit`), does not
228
229
  write DONE, and halts. It reports this status to `epic-orchestrator`, which mirrors it into
229
230
  the epic checkpoint's per-feature `merge_status: "blocked_conflict_loop_limit"` field.
@@ -242,9 +243,15 @@ cross-call/conversation-state visibility.
242
243
  dependency's `merge_status` is `merged` or `worktree_removed`.
243
244
  - **Layer 2 — retrospective backstop:** the wave-barrier ordering invariant inside
244
245
  `validate_epic_orchestrator_state_text`, enforced at `epic-orchestrator` `SubagentStop` time via
245
- the parameterized `validate-orchestrator-output.ps1` hook. It appends
246
- `EPIC_WAVE_BARRIER_VIOLATION: <f> started before dependency <d> merged` when a dependency edge's
247
- timing invariant is violated.
246
+ the parameterized `validate-orchestrator-output.ps1` hook. It checks only a dependent feature
247
+ that is treated as started: one with a string `worktree_created_at`, or with a `merge_status`
248
+ other than `not_started` (a missing or non-string `merge_status` counts as started). It appends
249
+ exactly one error per violated dependency edge. When the dependency's `merge_status` is not
250
+ `merged` or `worktree_removed`, the error is
251
+ `EPIC_WAVE_BARRIER_VIOLATION: <f> is treated as started while dependency <d> is not merged`.
252
+ Otherwise, when the dependency's `merge_confirmed_at` is later than the dependent's
253
+ `worktree_created_at`, the error is
254
+ `EPIC_WAVE_BARRIER_VIOLATION: <f> worktree_created_at precedes dependency <d> merge_confirmed_at`.
248
255
 
249
256
  Both layers are required; neither alone closes the gap. `epic-orchestrator` does not launch wave
250
257
  N+1 until every wave-N feature's dependency edges are durably confirmed merged, verified against
@@ -46,6 +46,8 @@ Use this skill when:
46
46
  Use `yyyy-MM-ddTHH-mm` for all audit, remediation, and evidence artifacts.
47
47
  Example: `2026-02-06T14-30`.
48
48
 
49
+ The `Timestamp` value is local time read from the host system clock when the recorded command runs (for example `Get-Date -Format yyyy-MM-ddTHH-mm`); the agent never composes or estimates it.
50
+
49
51
  ## Canonical Evidence Locations
50
52
 
51
53
  - Baseline evidence: `evidence/baseline/`
@@ -110,6 +112,8 @@ When evidence artifacts are used for automated checking or plan reconciliation,
110
112
  - `Command: <exact command>`
111
113
  - `EXIT_CODE: <int>`
112
114
 
115
+ The first occurrence of `Timestamp`, `Command`, `EXIT_CODE`, and `ExpectedExitCode` forms the record in both the Python and the TypeScript parser; later occurrences, including empty later values, are ignored. An artifact that records several gates therefore reports its first gate.
116
+
113
117
  One optional field may also be declared:
114
118
  - `ExpectedExitCode: <int>` — the exit code the gate is expected to produce.
115
119
 
@@ -40,6 +40,16 @@ Each `delegation_receipts.promotion.*` field stores the raw MCP receipt payload
40
40
 
41
41
  Note: VS Code command-palette commands may exist for interactive extension use, but this note is non-authoritative for agent sessions.
42
42
 
43
+ ## Pre-Existing Issue Path
44
+
45
+ When the GitHub issue already exists (it was transferred, filed before orchestration, or created by epic decomposition), do not call `potential_to_issue`: that tool creates a new issue and would duplicate the existing one. Instead:
46
+
47
+ 1. Verify the issue read-only with `gh issue view`, a `gh api` GET request, or a GitHub MCP issue read, and use its number as `${issue-num}`.
48
+ 2. Record a top-level `issue_adoption` object in the orchestrator checkpoint (`issue_num`, `issue_url`, `origin`, `verified_via`, `verified_at`, `evidence`, `waived_tools`, and `potential_record` when a promotion-entry tool is waived). A valid record waives the `potential_to_issue` receipt requirement at completion.
49
+ 3. `delegation_receipts.promotion.issue` may be omitted, because no promotion receipt exists for an adopted issue.
50
+
51
+ The field rules, the closed set of waivable tools, and the fail-closed behavior are defined in `.claude/rules/orchestrator-state.md` under `## Invariants (issue_adoption object)`.
52
+
43
53
  ## Canonical Variables
44
54
 
45
55
  - `${promotion-type}`: `feature` or `bug`
@@ -72,7 +72,7 @@ If the branch diff modifies any path matching `.github/workflows/**`, `scripts/b
72
72
  - The rule provides a second, independent line of defense for CI-gate-modifying features, separate from and prior to the orchestrator's S9 CI green gate.
73
73
  - "Green workflow run against the branch head" means a workflow run whose head SHA matches the current branch head and whose conclusion is success for the affected workflow.
74
74
  - A green `workflow_dispatch` run against the branch head also satisfies the rule, not only a PR-context run. This mitigates the chicken-and-egg case where a feature must land its CI gate before the gate can run in PR context (see spec.md Risks & Mitigations).
75
- - When the rule fires and no qualifying green-run evidence is present, record a Blocking finding and route it through the standard remediation handoff. The supporting validator `scripts/feature-review/Test-ModifiedWorkflowNeedsGreenRun.ps1` implements the trigger-path and evidence-presence logic.
75
+ - When the rule fires and no qualifying green-run evidence is present, record a Blocking finding classified `awaiting_ci` (the remediation inputs carry `Remediability: awaiting_ci` and a `Remediability-Evidence:` line naming the awaited workflow) and route it to the wait path (`AWAITING_CI` when no other class is present) instead of the remediation handoff.
76
76
 
77
77
  ## Ordered Procedure
78
78
 
@@ -147,6 +147,8 @@ If the branch diff modifies any path matching `.github/workflows/**`, `scripts/b
147
147
  - required acceptance criteria are FAIL or PARTIAL
148
148
  - coverage regression below policy threshold (< 80% repo-wide per language, < 80% or regression for modified files, or < 90% for new files)
149
149
  - coverage artifact absent for any language that has changed files
150
+ - Classify each blocking finding before triggering remediation: each receives one remediability class (`autonomous`, `external_dependency`, `policy_hold`, `awaiting_ci`, or `human_decision_required`; `autonomous` when no class is stated). A published MCP runtime that lags the repository contract is classified `external_dependency`.
151
+ - Trigger the remediation handoff only when at least one blocking finding is `autonomous`. When every blocking finding is non-remediable, write the remediation inputs with the `HALT_NON_REMEDIABLE` or `AWAITING_CI` verdict and create no remediation plan target.
150
152
  - Create `remediation-inputs.<timestamp>.md` first.
151
153
  - Create the target remediation plan file from the canonical plan template.
152
154
  - Hand off plan creation through `remediation-handoff-atomic-planner`.
@@ -81,7 +81,7 @@ blocked result before launch.
81
81
 
82
82
  Because model selection is required once delegation occurs (see `## Model Selection`), a resuming orchestrator must repair a missing model choice deterministically before delegating at a delegating `next_step`. When the resumed `next_step` is a delegating step:
83
83
 
84
- a. **Preflight the checkpoint.** Run the orchestrator-state validator with `--require-model-routing` (via `mcp__drm-copilot__validate_orchestration_artifacts` or the local CLI) against `artifacts/orchestration/orchestrator-state.json` before the first delegation. Record the result in a `model_routing_preflight` block `{ status ("pass"|"fail"), checked_at (ISO-8601 UTC), validator_command, output_summary }`.
84
+ a. **Preflight the checkpoint.** Run the orchestrator-state validator with `--require-model-routing` (via `mcp__drm-copilot__validate_orchestration_artifacts` or the repository-local validator CLI documented in `.claude/rules/orchestrator-state.md`) against `artifacts/orchestration/orchestrator-state.json` before the first delegation. Record the result in a `model_routing_preflight` block `{ status ("pass"|"fail"), checked_at (ISO-8601 UTC), validator_command, output_summary }`.
85
85
  b. **Recompute the floor.** For the upcoming phase, recompute the complexity floor with `Get-ComplexityFloor -SignalsPresent <names>` (`.claude/lib/model-routing/ModelRouting.psm1`); do not reimplement the formula.
86
86
  c. **Record the assessment.** Write a `complexity_assessments[]` entry `{ phase, band, floor, signals_present[], rationale, assessed_at }` with `floor` equal to the recomputed value and `band >= floor`.
87
87
  d. **Resolve and record the receipt.** Resolve the model with `Resolve-DelegationModel -Agent <agent> -Band <complexity_band> -FablePolicy <fable_policy>` (`.claude/lib/model-routing/ModelRouting.psm1`) and write a `model_routing_receipts[]` entry `{ agent, phase, complexity_band, fable_policy, table_model, clamped_from | null, model }`.
@@ -137,6 +137,7 @@ A delegation prompt carrying the literal marker `Preparation mode: true` (issued
137
137
  - **Route.** Select `route_id: preparation`. The route's routing-matrix entry requires receipts for `task-researcher`, `prd-feature`, `atomic-planner`, and `atomic-executor`; the skills `orchestrate`, `feature-promotion-lifecycle`, and `atomic-plan-contract`; and the promotion plus validator MCP tools.
138
138
  - **Scope.** Run promotion (MCP surface), research, feature documents (`spec.md`, `user-story.md`), atomic planning, and the atomic-executor preflight (precondition validation only, R2 semantics: iterate plan revisions until `PREFLIGHT: ALL CLEAR`). Atomic execution, PR authoring, CI monitoring, and feature review are out of scope and are executed later by `epic-orchestrator`.
139
139
  - **Terminal checkpoint.** Stop with `completed_steps` containing `S3_promotion` and `S4_atomic_planning`, `next_step: "S5_atomic_execution"`, out-of-scope step statuses set to `not-applicable`, and `blocked_reason: "none"`. Do NOT assert completion (`next_step: "complete"`, `S12_complete`, or a `completed` step8/9/10 status): the run has no PR or CI evidence, and the route's `requires_ci_gate: false` exempts it from `ci_gate` at the completion validator instead.
140
+ - **Premise-falsified halt.** Use `blocked_reason: "premise_falsified"` when every delegation and validator succeeded but evidence gathered during execution falsified the plan's premise. Still record the evidence path in free-form checkpoint keys; `blocked_reason` carries only the classification. The preparation terminal checkpoint above still sets `blocked_reason: "none"`. The full `blocked_reason` vocabulary and its partition are in `.claude/rules/orchestrator-state.md`.
140
141
  - **Commit.** Commit the prepared feature folder and plan to the current branch (the worktree branch created off the epic integration branch) before stopping, and report the `plan-path` and preflight status in the final output.
141
142
 
142
143
  ## Epic Mode Bounded Return
@@ -184,7 +185,7 @@ PR creation and PR body edits are delegated work, not orchestrator work. The orc
184
185
  The mandatory sequence is:
185
186
 
186
187
  1. The orchestrator first refreshes the PR-context artifact via `mcp__drm-copilot__collect_pr_context` (or the equivalent context-collection mechanism), which writes `artifacts/pr_context.summary.txt`.
187
- 2. The orchestrator runs the orchestrator-state validator (`mcp__drm-copilot__validate_orchestration_artifacts` or the equivalent local CLI call) against `artifacts/orchestration/orchestrator-state.json --require-pr-creation-ready` and records the pass/fail result under a new `pr_author_preflight` field in the checkpoint, alongside `pr_author_receipt`: `{status ("pass"|"fail"), checked_at (ISO-8601 UTC), checkpoint_path, validator_command, output_summary}`. The orchestrator must not delegate to `Agent(pr-author)` when this preflight fails. The validator's full-lifecycle completion flag (`ci_gate`/`pr_gate`/routing-contract receipts) remains reserved for the post-PR/CI completion context (Step S9 / PR Creation Gate condition 6), not this pre-PR-creation preflight, because those values cannot exist before the first `gh pr create` of a branch.
188
+ 2. The orchestrator runs the orchestrator-state validator (`mcp__drm-copilot__validate_orchestration_artifacts` or the equivalent repository-local validator CLI documented in `.claude/rules/orchestrator-state.md`) against `artifacts/orchestration/orchestrator-state.json --require-pr-creation-ready` and records the pass/fail result under a new `pr_author_preflight` field in the checkpoint, alongside `pr_author_receipt`: `{status ("pass"|"fail"), checked_at (ISO-8601 UTC), checkpoint_path, validator_command, output_summary}`. The orchestrator must not delegate to `Agent(pr-author)` when this preflight fails. The validator's full-lifecycle completion flag (`ci_gate`/`pr_gate`/routing-contract receipts) remains reserved for the post-PR/CI completion context (Step S9 / PR Creation Gate condition 6), not this pre-PR-creation preflight, because those values cannot exist before the first `gh pr create` of a branch.
188
189
  3. The orchestrator then delegates PR creation and any PR body edits to `Agent(pr-author)`. The `pr-author` agent runs the `pr-author` skill to author the body, writes the body file `artifacts/pr_body_<N>.md` and the sibling receipt `artifacts/pr_body_<N>.receipt.json` with the shape `{skill, pr_body_path, number, sha256 (lowercase hex of the body bytes), context_summary_path, created_at (ISO-8601 UTC, strictly newer than `artifacts/pr_context.summary.txt` last-write)}`, issues `gh pr create --body-file artifacts/pr_body_<N>.md` (or `gh pr edit --body-file ...`), and reports the resulting PR URL or PR number.
189
190
  4. The orchestrator records `pr_author_receipt` in the checkpoint, citing the body-file path and the receipt path that were verified.
190
191
 
@@ -237,20 +238,32 @@ After each `feature-review` delegation returns:
237
238
 
238
239
  1. Locate `remediation-inputs.<timestamp>.md` in the active feature folder (match the highest ISO-8601 timestamp).
239
240
  2. If no such file exists, treat as zero blocking findings and advance to the PR creation gate.
240
- 3. If the file exists, count lines matching `BLOCKING` or `Severity: Blocking` (case-sensitive). If count >= 1, enter the remediation loop. If count = 0, advance to the PR creation gate.
241
+ 3. If the file exists, count lines matching `BLOCKING` or `Severity: Blocking` (case-sensitive). If count >= 1, enter the remediation loop. If count = 0, advance to the PR creation gate. This count rule applies unchanged when the file carries no `Review-Verdict:` line: a count of at least 1 is `REMEDIATION_REQUIRED` and every finding is treated as `autonomous`.
242
+ 4. If the file carries a `Review-Verdict:` line, recompute the verdict from the `Remediability:` lines of the blocking findings (a blocking finding block without a `Remediability:` line counts as `autonomous`): no blocking finding is `PASS`; any `autonomous` finding is `REMEDIATION_REQUIRED`; otherwise any `external_dependency`, `policy_hold`, or `human_decision_required` finding is `HALT_NON_REMEDIABLE`; otherwise `AWAITING_CI`. The `remediation-inputs` file is authoritative; the optional `review-status:` token in the review result is a cross-check.
243
+ 5. A mismatch between the declared and recomputed verdicts is a reviewer contract error: record it under `artifact_errors`, re-request the review once, and halt with `blocked_reason: "delegate_contract_incomplete"` if it persists.
244
+ 6. Append a `remediation_loop.review_outcomes[]` entry (`verdict` plus one `findings[]` object with `remediability` per blocking finding) for every review, including `PASS`.
245
+ 7. Act on the verdict: `PASS` advances to the PR creation gate; `REMEDIATION_REQUIRED` enters the remediation loop with the plan scoped to the `autonomous` findings, carrying the non-remediable findings forward unchanged; `HALT_NON_REMEDIABLE` follows the halt branch; `AWAITING_CI` follows the wait branch.
246
+
247
+ Halt branch (`HALT_NON_REMEDIABLE`): set `blocked_reason` to the highest-precedence halt class present, append one `human_interaction.requirements[]` entry with `response: "halt"` for each halt class present (`external_dependency`, `policy_hold`, `human_decision_required`) describing the human action needed, leave `remediation_loop.completed_attempts` unchanged, write no cycle, create no remediation plan, and stop. The precedence is:
248
+
249
+ Halt precedence: human_decision_required > policy_hold > external_dependency
250
+
251
+ Wait branch (`AWAITING_CI`): set `blocked_reason: "awaiting_ci"` and set `next_step` to the step that re-checks (`S7_feature_review` for a review-time wait, `S9_ci_green` for an S9 poll timeout). Record no `human_interaction.requirements[]` entry for a wait, write no cycle, and create no remediation plan. Poll within the existing bounded S9 interval and timeout; when the bound is exhausted, persist and stop. On resume, set `blocked_reason: "none"` and re-run the named step. For S9, the awaited run is identified by `ci_gate.head_sha` and `ci_gate.pr_pipeline_run_id` with `conclusion: "pending"`; for a review-time wait, the awaited workflow is named in the finding's `Remediability-Evidence:` line.
241
252
 
242
253
  ## Remediation Loop (R1–R5)
243
254
 
244
- A bounded loop consisting of five steps. The loop variable `remediation_pass` starts at 1 and increments at R5 before returning to R1.
255
+ A bounded loop consisting of five steps. The attempt count is `remediation_loop.completed_attempts`, and `remediation_pass` equals `remediation_loop.completed_attempts`. The active cycle number is `completed_attempts + 1`, and `remediation.cycle_N` in `next_step` uses that number; `remediation_loop.current_cycle` is a record position in `cycles[]`, not a count. A halt or wait verdict never opens a cycle, and every cycle opened from a review records `opened_by_review`, the zero-based index of that `review_outcomes[]` entry.
256
+
257
+ Cycle accounting: a remediation attempt is complete when R3 execution finished (`execution_status: "complete"`) and the pre-R4 commit recorded a non-empty change set; only then set `candidate_applied: true` on that cycle and increment `completed_attempts`. A cycle that ends without a candidate (execution not started, execution failed, or an empty staged change set) records `candidate_applied: false` and consumes no number. It is followed by at most one re-plan under the same number when the executor output identifies an autonomous plan defect; otherwise reclassify the blocker (typically `external_dependency`) and halt. Two consecutive no-candidate cycles halt with `step6_status: "blocked_remediation_loop_limit"`. Local, CI-failure, merge-conflict, and parallel-drift cycles share the one count.
245
258
 
246
259
  - **R1 — Remediation planning:** Delegate to `atomic-planner` with `remediation-inputs.<timestamp>.md` path as primary context. Receive `remediation-plan.<timestamp>.md` in the active feature folder.
247
260
  - **R2 — Preflight clearance:** Delegate to `atomic-executor` for precondition validation only (no implementation). If the executor does not return `PREFLIGHT: ALL CLEAR`, return to R1 and re-delegate to `atomic-planner` with the required-changes output from the executor. Only after `PREFLIGHT: ALL CLEAR` may the orchestrator advance to R3.
248
261
  - **R3 — Remediation execution:** Delegate to `atomic-executor` with full execution authorization. Each task's toolchain loop (format → lint → type-check → test) is mandatory; no skipping.
249
262
  - **Pre-R4 commit:** Stage all changes (`git add -A`), delegate to `Agent(commit-message)` to generate a commit message from the staged diff (the agent returns message text only and does not commit), then commit with the generated message. The `git commit` action remains on the orchestrator. Advance to R4 only after a successful commit.
250
263
  - **R4 — Re-audit:** Delegate to `feature-review` with the same inputs as the original review (resolved base branch, feature folder, refreshed PR context artifacts, acceptance-criteria source). No scope narrowing. The canonical issue number line must be included.
251
- - **R5 — Loop-exit decision:** If the re-audit produces zero blocking findings, exit the loop and advance to the PR creation gate. Otherwise, record `remediation_pass` increment in the checkpoint and return to R1.
264
+ - **R5 — Loop-exit decision:** Evaluate the re-audit per Post-Review Outcome Evaluation. If it produces zero blocking findings, exit the loop and advance to the PR creation gate. If its verdict is `HALT_NON_REMEDIABLE` or `AWAITING_CI`, follow the halt or wait branch instead of opening the next cycle. Otherwise, record the cycle's `candidate_applied` value and the resulting `completed_attempts` in the checkpoint and return to R1.
252
265
 
253
- **Termination guard:** If `remediation_pass` reaches 3 without resolution, the orchestrator records `step6_status: "blocked_remediation_loop_limit"` in the checkpoint and halts. No further automation is attempted.
266
+ **Termination guard:** Halt after three completed attempts: when `remediation_loop.completed_attempts` equals 3 and the latest verdict is not `PASS`, the orchestrator records `step6_status: "blocked_remediation_loop_limit"` in the checkpoint and halts. No further automation is attempted.
254
267
 
255
268
  ## Issue Number Consistency
256
269
 
@@ -275,10 +288,12 @@ S9 procedure:
275
288
  1. Resolve the live PR head SHA for the feature branch (`gh pr view --json headRefOid` or equivalent).
276
289
  2. Invoke `gh pr checks --required --json bucket,name,state,link,workflow` (or an equivalent JSON-emitting command) against that head SHA. `gh` is the only sanctioned channel for querying GitHub Actions state.
277
290
  3. Parse the JSON by running `pwsh -NoProfile -File .claude/lib/ci-gate/Invoke-CiGateParser.ps1 -ChecksJson <checks-json> -HeadSha <head-sha>`, which emits the `ci_gate` object defined below and derives `ci_gate.conclusion` as `success` when all required checks pass, `failure` when any required check failed, and `pending` when any required check is still in progress.
278
- 4. Poll with a bounded interval and a documented total timeout while `conclusion == "pending"`. When the timeout is exhausted, set `step9_status: "failed_remediation_required"` and enter the remediation-loop CI-failure handling below with a timeout log.
291
+ 4. Poll with a bounded interval and a documented total timeout while `conclusion == "pending"`. When the timeout is exhausted, record the timeout as a finding with `Remediability: awaiting_ci` in `remediation-inputs.<timestamp>.md` and follow the wait branch in Post-Review Outcome Evaluation (`blocked_reason: "awaiting_ci"`, `next_step: "S9_ci_green"`); `step9_status` stays `pending`. A poll timeout does not enter the remediation loop.
279
292
  5. Write the `ci_gate` object and `last_verified_ci_sha` to the checkpoint, and set `step9_status` to `passed` only when `ci_gate.conclusion == "success"` AND `ci_gate.head_sha` equals the current PR head SHA.
280
293
  6. If the checkpoint's `epic_mode` is `true`, execute `gh pr merge --merge <PR>` merging the feature branch into `epic_context.integration_branch` (already the PR's base branch per the epic-mode `--base` override applied at S8). On success, record `epic_merge: { merge_commit_sha, target_branch, merged_at }` in the checkpoint. On failure due to merge conflict (non-mergeable PR), do not retry blindly: convert the conflict into a synthetic Blocking finding per "Merge-Conflict Remediation" below and re-enter the standard R1–R5 remediation loop; do not proceed to DONE.
281
294
 
295
+ CI-dependent acceptance criteria: when the item has acceptance criteria whose verification requires the result of CI on the PR head, the item's own orchestrator run owns their check-off, and a parent or coordinating session never commits them from its own root. After step 5 records `ci_gate.conclusion == "success"`, check off each CI-dependent criterion in the item's own worktree, commit, push to the PR branch, and re-run S9 from step 1 against the new head SHA, so that `ci_gate.head_sha` equals the final PR head before DONE. In epic mode this completes before step 6 merges. A failed re-run enters `## Remediation Loop — CI-Failure Handling` below; the shared `remediation_loop.completed_attempts` count and its halt after three completed attempts are unchanged.
296
+
282
297
  DONE is not written while `step9_status` is anything other than `passed`.
283
298
 
284
299
  ## Checkpoint Schema — CI Gate Fields
@@ -321,13 +336,13 @@ A checkpoint that predates this schema and has no `ci_gate` object (or no `step9
321
336
 
322
337
  ## Remediation Loop — CI-Failure Handling
323
338
 
324
- When S9 records `step9_status: "failed_remediation_required"` (a failed required check or an exhausted poll timeout):
339
+ When S9 records `step9_status: "failed_remediation_required"` (a failed required check; a poll timeout follows the wait branch per S9 step 4):
325
340
 
326
- 1. The failed-check log from `gh run view <run-id> --log-failed` (or the timeout log) is written as `remediation-inputs.<timestamp>.md` in the active feature folder.
341
+ 1. The failed-check log from `gh run view <run-id> --log-failed` is written as `remediation-inputs.<timestamp>.md` in the active feature folder.
327
342
  2. The failure is converted to a synthetic finding with severity `Blocking` that identifies the failing check by name and the failing job by URL.
328
343
  3. The existing R1-R5 remediation loop processes that finding exactly as it processes a local blocking finding. No new loop is introduced.
329
- 4. The `remediation_pass` counter is shared with local-finding passes; the cap is 3.
330
- 5. On the third CI-failure pass without resolution, the orchestrator records `step9_status: "blocked_ci_loop_limit"`, does not write DONE, and halts. No further automation is attempted.
344
+ 4. CI-failure cycles share `remediation_loop.completed_attempts` with local-finding cycles; a CI-failure finding stays `autonomous`, and the active cycle number is `completed_attempts + 1`.
345
+ 5. The shared guard applies: after three completed attempts without a passing result, the orchestrator records `step9_status: "blocked_ci_loop_limit"`, does not write DONE, and halts. No further automation is attempted.
331
346
 
332
347
  ## PR Creation Gate
333
348
 
@@ -335,6 +350,7 @@ The orchestrator must not create a PR, push a branch for PR purposes, or report
335
350
 
336
351
  1. `blocking_findings_resolved: true` — the most recent `feature-review` produced zero blocking findings.
337
352
  2. The AC verification artifact (`p14-acceptance-criteria-checkoff.md` or equivalent) confirms all acceptance criteria pass.
353
+ A CI-dependent acceptance criterion, one whose verification requires the result of CI on the PR head, cannot pass before CI exists: condition 2 is satisfied when every other criterion passes and each CI-dependent criterion is listed as pending-CI in the AC verification artifact. Pending-CI criteria are checked off under S9 before DONE. This clarifies condition 2 and adds no condition.
338
354
  3. The mandatory toolchain passed in its most recent run on the branch (no linting/type-check/test failures).
339
355
  4. The checkpoint `next_step` is `S8_create_pr` (precondition to entering S9).
340
356
  5. PR body produced via the pr-author handoff: `artifacts/pr_body_<N>.md` exists with a matching `artifacts/pr_body_<N>.receipt.json`, created with `--body-file`.
@@ -420,6 +436,8 @@ Example:
420
436
  ]
421
437
  ```
422
438
 
423
- The validator counts an MCP receipt as successful only when `tool` is a non-empty string, `ok` is exactly `true`, and `evidence` is a non-empty string. Every `required_mcp_tools` entry must have such a receipt.
439
+ The validator counts an MCP receipt as successful only when `tool` is a non-empty string, `ok` is exactly `true`, and `evidence` is a non-empty string. Every `required_mcp_tools` entry must have such a receipt unless a valid `issue_adoption` record waives it.
440
+
441
+ When the GitHub issue already exists before orchestration starts (transferred, filed by hand, or created by epic decomposition) and has been verified read-only (`gh issue view`, a `gh api` GET, or a GitHub MCP issue read), do not call `potential_to_issue`. Record a top-level `issue_adoption` object in the checkpoint instead of a `potential_to_issue` receipt. It may waive only `potential_to_issue` and, with a valid `potential_record` under `docs/features/potential/`, the checkpoint's promotion-entry tool (`new_potential_entry`, or `new_potential_bug_entry` for a bug-type checkpoint); `potential_to_issue` must always be listed. Every other required tool still needs a successful receipt. Any adoption error waives nothing. The field rules, the closed waivable set, and the error placement are defined in `.claude/rules/orchestrator-state.md` under `## Invariants (issue_adoption object)`.
424
442
 
425
443
  These three receipt arrays, populated with the retained required names of the selected route, are what allow the routing-contract validation under `require_complete: true` to pass.
@@ -313,6 +313,12 @@ unchanged: `.claude/skills/orchestrate/SKILL.md` is **not modified by this featu
313
313
  `parallel_mode` clause in its step 9, no `parallel_merge` object in the child checkpoint, and no
314
314
  additional condition on the child's PR Creation Gate.
315
315
 
316
+ Issue #744 later amended two parts of that child contract for CI-dependent acceptance criteria,
317
+ whose verification requires the result of CI on the item's pull-request head: PR Creation Gate
318
+ condition 2 and step S9 of `.claude/skills/orchestrate/SKILL.md`. The child checks those criteria
319
+ off in its own worktree, pushes the check-off commit to its pull-request branch, and re-runs S9
320
+ before DONE. The parent never commits acceptance-criteria check-offs from the coordinator root.
321
+
316
322
  Procedure, per item:
317
323
 
318
324
  1. The item's child orchestration runs unmodified, with `epic_mode` `false` or absent, and finishes
@@ -323,6 +329,11 @@ Procedure, per item:
323
329
  `gh pr view --json state,mergedAt,headRefOid`, and with `gh pr checks` when the check conclusion
324
330
  must be re-read — never from an in-memory completion notification — then record
325
331
  `merge_status: ci_green`.
332
+ Before recording `merge_status: ci_green`, confirm that the `headRefOid` value equals the
333
+ `ci_gate.head_sha` the child reported at DONE and that the child reported no pending
334
+ CI-dependent acceptance criteria. When either check fails, do not record
335
+ `merge_status: ci_green` and do not run `gh pr merge`; the item waits until its child pushes
336
+ the check-off and re-runs S9, and the parent does not commit the check-off itself.
326
337
  3. Execute `gh pr merge --merge <PR>` for that item's pull request, whose base is `main`.
327
338
  4. On success, record `merge_commit_sha`, `merged_at`, and `merge_status: merged`, then regenerate
328
339
  `docs/features/parallel/<slug>/parallel-status.md`.
@@ -417,8 +428,10 @@ the escalation path.
417
428
  2. The parent re-delegates that item's child orchestration. The child processes the finding through
418
429
  its unmodified R1 through R5 remediation loop exactly as it processes any local Blocking
419
430
  finding. No new remediation loop is introduced by this procedure.
420
- 3. The child's `remediation_pass` counter is shared with its local-finding and CI-failure passes,
421
- with the cap of 3, unmodified.
431
+ 3. Drift cycles share the child's `remediation_loop.completed_attempts` count with its
432
+ local-finding and CI-failure cycles, and the child halts after three completed attempts. The
433
+ active cycle number is `completed_attempts + 1`, and a cycle without an applied candidate
434
+ consumes no number.
422
435
  4. Each remediated pass ends again at child DONE with the pull request open and CI green, after
423
436
  which the parent retries the merge per `## Per-Item Merge to Main (Merge-on-Green)`. During
424
437
  remediation the item's `merge_status` legitimately remains `pr_open` or `ci_green`: the
@@ -567,6 +580,8 @@ hold:
567
580
  `artifact_type: "parallel-orchestrator-state"`.
568
581
  4. Each item's acceptance criteria have been checked off in that item's own acceptance-criteria
569
582
  source files by that item's own run, per the `acceptance-criteria-tracking` skill.
583
+ A CI-dependent criterion is checked off and pushed by that item's own run before its DONE, so
584
+ the head the parent merges already contains the check-off; the parent never commits it.
570
585
 
571
586
  In `open` mode there is no automatic completion. The run is a standing queue and terminates only via
572
587
  `/parallel-close`, which is owned by F6 and is neither specified nor shipped by this feature. Do not
@@ -1113,7 +1128,7 @@ R5 loop that drives the remediation preceding either write is **reused
1113
1128
  unmodified**: `atomic-planner` plans the resolution, `atomic-executor` performs preflight then
1114
1129
  resolves, `feature-review` re-audits, and the loop exits on zero blocking findings. No new
1115
1130
  remediation loop is authored, no line of the existing loop is modified, and the shared
1116
- `remediation_pass` cap of 3 applies. `.claude/skills/orchestrate/SKILL.md` is not modified by this
1131
+ `remediation_loop.completed_attempts` count applies, with the halt after three completed attempts. `.claude/skills/orchestrate/SKILL.md` is not modified by this
1117
1132
  feature.
1118
1133
 
1119
1134
  #### Layer-1 Narrowing — a Documented Limitation
@@ -54,6 +54,8 @@ Trigger remediation when any of these are true:
54
54
  - Acceptance criteria are not met.
55
55
  - A required CI check fails after the PR is open (workflow-file changes specifically must enter the loop and trigger the `modified-workflow-needs-green-run` rule defined in `.claude/skills/feature-review-workflow/SKILL.md`).
56
56
 
57
+ Remediation triggers only on blocking findings classified `autonomous`. Each blocking finding carries one remediability class (`autonomous`, `external_dependency`, `policy_hold`, `awaiting_ci`, or `human_decision_required`; `autonomous` when no class is stated). When no blocking finding is `autonomous`, the review verdict is `HALT_NON_REMEDIABLE` or `AWAITING_CI`: the orchestrator halts or waits, and no cycle, remediation plan, or `atomic-planner` handoff is created.
58
+
57
59
  ## Required Remediation Inputs
58
60
 
59
61
  The orchestrator authors `remediation/<entry-ts>/remediation-inputs.md` with:
@@ -118,11 +120,13 @@ Iteration ceiling. When a cycle's `iterations` would exceed 2, the orchestrator
118
120
 
119
121
  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.
120
122
 
123
+ Before the reaudit, the orchestrator records `candidate_applied` on the current cycle: `true` only when execution finished with `execution_status: "complete"` and the pre-reaudit commit recorded a non-empty change set, and `false` otherwise (execution not started, execution failed, or an empty staged change set). `remediation_loop.completed_attempts` equals the number of cycles whose `candidate_applied` is `true`, and a cycle with `candidate_applied: false` consumes no attempt number.
124
+
121
125
  When execution is complete, the orchestrator delegates to `feature-review`. `feature-review` produces the three reaudit artifacts under `docs/features/active/<slug>/audit/<exit-ts>/` using the exit timestamp.
122
126
 
123
127
  ## Exit Gate
124
128
 
125
- The orchestrator reads the latest cycle's three reaudit artifacts and computes `blocking_count` as the total number of FAIL findings plus material PARTIAL findings flagged as blocking. Only when `blocking_count == 0` does the orchestrator set `exit_condition_met = true` on the current cycle and mark the remediation loop complete. Otherwise, the orchestrator opens cycle N+1 with a new `remediation/<new-ts>/remediation-inputs.md` and runs the full chain again.
129
+ The orchestrator reads the latest cycle's three reaudit artifacts and computes `blocking_count` as the total number of FAIL findings plus material PARTIAL findings flagged as blocking. Only when `blocking_count == 0` does the orchestrator set `exit_condition_met = true` on the current cycle and mark the remediation loop complete. Otherwise, when at least one remaining blocking finding is `autonomous`, the orchestrator opens cycle N+1 with a new `remediation/<new-ts>/remediation-inputs.md` and runs the full chain again. When the remaining blocking findings are all non-remediable, the orchestrator does not open the next cycle: it halts on `HALT_NON_REMEDIABLE` or waits on `AWAITING_CI`.
126
130
 
127
131
  ## Context Package (When Required)
128
132