@windyroad/itil 0.55.1 → 0.55.2-preview.840

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.
@@ -497,5 +497,5 @@
497
497
  }
498
498
  },
499
499
  "name": "wr-itil",
500
- "version": "0.55.1"
500
+ "version": "0.55.2"
501
501
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@windyroad/itil",
3
- "version": "0.55.1",
3
+ "version": "0.55.2-preview.840",
4
4
  "description": "ITIL-aligned IT service management for Claude Code (problem, and future incident/change skills)",
5
5
  "bin": {
6
6
  "windyroad-itil": "./bin/install.mjs"
@@ -189,7 +189,9 @@ wr-itil-check-fix-rfc-trace <problem-file>
189
189
  ```
190
190
 
191
191
  - **Empty stdout** (an RFC already traces the problem): proceed to the traversal below.
192
- - **Non-empty stdout** (directive `no-rfc-trace: P<NNN> …`): **auto-create** a problem-traced skeleton RFC — do NOT block, do NOT skip, do NOT ask (ADR-073 auto-create-everywhere; the create is framework-mediated, not cat-1 direction-setting, so NO `AskUserQuestion` consent gate fires hereP132 / inverse-P078). Delegate to `/wr-itil:capture-rfc` with a problem trace derived from this Known Error (`--problem=P<NNN>` + a fix-scoped title from the problem's `## Fix Strategy` / root cause), which is the canonical ADR-070-compliant vehicle (allocates the next RFC ID, refreshes the RFC README, emits no Considered-Options block — no create logic is duplicated). Then re-run the predicate (now empty) and proceed. The auto-created RFC is the fix-proposal artifact; its body is fleshed out as fix work proceeds (ADR-073 a living scope artifact, not a one-shot).
192
+ - **Non-empty stdout** (directive `no-rfc-trace: P<NNN> …`): the predicate has confirmed only that *no RFC's `problems:` array names this PID*it has NOT decided that no fix vehicle exists. Distinguish **two sub-cases** before acting (P371; ADR-073 auto-create is intended ONLY when no fix vehicle exists, NOT when an existing vehicle merely lacks the trace edgearchitect-confirmed):
193
+ - **(a) Existing-vehicle-untraced — an RFC is already this ticket's fix vehicle but just hasn't wired the trace edge.** Read the ticket's `## Fix Strategy` / `## Resolution` / `## Dependencies` / `## Related` sections for an RFC cited as the **fix vehicle** — i.e. the fix IS that RFC's task set (the recurring shape: a rework / follow-on Known Error whose fix is an existing RFC's B-tasks, so that RFC's `problems:` array names the *original driver* problem, not this ticket). This is a **judgement read of the citation context, NOT a blind "any cited RFC" match**: an RFC named only as context / `composes with` / `**Related**` background is NOT a fix vehicle — wiring its trace edge would pollute its `problems:` array. If a genuine existing fix vehicle is found: **wire** this problem's trace edge into that RFC's frontmatter `problems:` array (Edit the `problems: [...]` line to include `P<NNN>` + a short inline `**Problems**:` body annotation noting the edge was wired because the vehicle already exists), then run `wr-itil-update-problem-rfcs-section <problem-file>` so the ticket's derived `## RFCs` section reflects the wired trace. Re-run the predicate (now empty) and proceed. Do **NOT** auto-create — minting a second RFC here produces a redundant duplicate that fragments the fix across two trace vehicles (the exact P371 defect). Structured-log the wire event (e.g. `I13: wired P<NNN> trace edge into existing fix-vehicle RFC-<NNN>`) to the iter summary `notes` for the JTBD-006 audit trail.
194
+ - **(b) No-vehicle — no existing RFC is this ticket's fix vehicle.** **auto-create** a problem-traced skeleton RFC — do NOT block, do NOT skip, do NOT ask (ADR-073 auto-create-everywhere; the create is framework-mediated, not cat-1 direction-setting, so NO `AskUserQuestion` consent gate fires here — P132 / inverse-P078). Delegate to `/wr-itil:capture-rfc` with a problem trace derived from this Known Error (`--problem=P<NNN>` + a fix-scoped title from the problem's `## Fix Strategy` / root cause), which is the canonical ADR-070-compliant vehicle (allocates the next RFC ID, refreshes the RFC README, emits no Considered-Options block — no create logic is duplicated). Then re-run the predicate (now empty) and proceed. The auto-created RFC is the fix-proposal artifact; its body is fleshed out as fix work proceeds (ADR-073 — a living scope artifact, not a one-shot). Structured-log the auto-create event to the iter summary `notes` (the ADR-073 reassessment criterion — auto-created-RFC-under-scoped signal feeds `/wr-retrospective:run-retro`).
193
195
 
194
196
  The predicate is the load-bearing detection half (committed shell + behavioural bats per ADR-052: `packages/itil/scripts/test/check-fix-rfc-trace.bats`); the create half is orchestrated through `capture-rfc` (the ADR-060 I1 load-bearing-from-the-start standard — deterministic detection in committed shell, create through the canonical capture surface). This gate fires at **every** fix-time surface; the AFK `/wr-itil:work-problems` orchestrator dispatches its fix work *through this same manage-problem traversal*, so the gate covers the AFK surface transitively (ADR-073 "everywhere").
195
197
 
@@ -284,7 +284,7 @@ The `## Inbound Upstream Reports` README section (ADR-062 § Step 9e renderer pe
284
284
 
285
285
  #### 4.5 AFK-loop behaviour
286
286
 
287
- When invoked from `/wr-itil:work-problems` Step 6.5 (AFK orchestrator), Step 4.5 runs silently per the mechanical-stage carve-out. The only user-attention surface during AFK is the existing external-comms gate UX (a known interrupt class per ADR-028 amended); per-branch `AskUserQuestion` would re-introduce the friction P132 was engineered to remove.
287
+ When invoked from `/wr-itil:work-problems` as a `claude -p` pre-flight subprocess (the Step 0b inbound-discovery pre-flight dispatch; AFK-by-construction per the Step 5 dispatch constraint + ADR-032 subprocess isolation), Step 4.5 runs silently per the mechanical-stage carve-out. The only user-attention surface during AFK is the existing external-comms gate UX (a known interrupt class per ADR-028 amended); per-branch `AskUserQuestion` would re-introduce the friction P132 was engineered to remove.
288
288
 
289
289
  ### 4.6. Relevance-close pass (P346 / P347 / ADR-079 Phase 1 + Phase 2)
290
290
 
@@ -335,7 +335,7 @@ Exit-code routing (one verdict line per ticket on stdout):
335
335
 
336
336
  1. **Surface a batch** — run the evaluator across the dual-tolerant glob in 4.6a; group all `CLOSE-CANDIDATE` and `CLOSE-CANDIDATE-WITH-CAVEAT` verdicts as a batch.
337
337
  2. **Interactive surface (`AskUserQuestion`)** — present each batch of ~5 candidates with their shape annotations + caveats; user confirms close / amend / defer. Surface caveat tickets adjacent to their clean-close siblings so the maintainer sees the full batch class together. The interactive batch is the one-and-only `AskUserQuestion` per relevance-close pass (mechanical-stage carve-out per ADR-044 cat 4 + P132 — do NOT ask per-ticket; ask per-batch).
338
- 3. **AFK (`/wr-itil:work-problems` Step 6.5)** close clean `CLOSE-CANDIDATE` verdicts silently per ADR-013 Rule 5 + ADR-044 cat 4 (file existence + frontmatter inspection + line-anchored grep are empirical). Route `CLOSE-CANDIDATE-WITH-CAVEAT` verdicts to the next interactive review's `AskUserQuestion` surface — the caveat short-tag is the maintainer's decision input.
338
+ 3. **AFK (dispatched as a `claude -p` subprocess that is AFK-by-construction)** — when `/wr-itil:review-problems` is reached via the `/wr-itil:work-problems` side-effect dispatch path (Step 0b/0c/0d pre-flight or Step 3.6 pre-dispatch relevance gate), it runs in a subprocess whose Step 5 dispatch constraint forbids `AskUserQuestion` in the worker (ADR-032 subprocess isolation), so this surface-batch-confirm flow takes the silent-close branch automatically. Close clean `CLOSE-CANDIDATE` verdicts silently per ADR-013 Rule 5 + ADR-044 cat 4 (file existence + frontmatter inspection + line-anchored grep are empirical). Route `CLOSE-CANDIDATE-WITH-CAVEAT` verdicts to the next interactive review's `AskUserQuestion` surface — the caveat short-tag is the maintainer's decision input.
339
339
  4. **Batched closure commit per ADR-014** — all relevance-closes from one review pass batch into ONE commit (mirroring `/wr-itil:transition-problems` P139 batch grain).
340
340
 
341
341
  Real-backlog smoke test 2026-05-31 against today's labeled fixtures: P012 → `CLOSE-CANDIDATE-WITH-CAVEAT` (shapes 2 + 5 + multi-phase-mixed-progress caveat); P136 → `KEEP-WITH-NOTE` (sibling-file class); P303/P326 → `SKIP` (age gate, recent observations).
@@ -392,7 +392,7 @@ Step 5's README refresh rides the same commit per ADR-014 single-commit grain
392
392
 
393
393
  #### 4.6d. AFK-policy-authorised silent proceed (ADR-013 Rule 5 / ADR-044 category 4)
394
394
 
395
- The relevance-close pass runs **unconditionally** during AFK orchestration (`/wr-itil:work-problems` Step 6.5). File existence is empirical, not user-judgment — the mechanical-stage carve-out (P132) applies per ADR-044 category-4 silent framework action. Do NOT fire `AskUserQuestion` per CLOSE-CANDIDATE; the framework has already resolved the close-on-empirical-evidence question.
395
+ The relevance-close pass runs **unconditionally** during AFK orchestration: when `/wr-itil:work-problems` reaches `/wr-itil:review-problems` via its side-effect dispatch path (Step 0b/0c/0d pre-flight or Step 3.6 pre-dispatch relevance gate), the dispatched `claude -p` subprocess is AFK-by-construction — the Step 5 dispatch constraint forbids `AskUserQuestion` in the worker (ADR-032 subprocess isolation), so this pass takes the silent-close branch automatically. File existence is empirical, not user-judgment — the mechanical-stage carve-out (P132) applies per ADR-044 category-4 silent framework action. Do NOT fire `AskUserQuestion` per CLOSE-CANDIDATE; the framework has already resolved the close-on-empirical-evidence question.
396
396
 
397
397
  **Worked example (Phase 1 smoke test, 2026-05-31)**: across 143 open / known-error tickets, Phase 1 surfaced 6 CLOSE-CANDIDATEs (4.2%) — but the post-batch-1 verification showed 60% of those were false-positives (state-suffix / sibling-file / rename class). Phase 2's false-positive fixes route those to `KEEP-WITH-NOTE`. The same-day foreground relevance-scan that used the broader Phase 2 shape vocabulary produced 14 actual closes across 5 batches — empirically calibrating the Phase 2 shape set.
398
398
 
@@ -642,7 +642,7 @@ rm -f "$ITER_JSON"
642
642
 
643
643
  1. **Context**: this is one iteration of the AFK work-problems loop. The user is AFK. The orchestrator selected `P<NNN> (<title>)` as the highest-WSJF actionable ticket.
644
644
  2. **Task**: apply the `/wr-itil:manage-problem` workflow for `work highest WSJF problem that can be progressed non-interactively as the user is AFK`. Follow manage-problem SKILL.md verbatim, including architect / jtbd / style-guide / voice-tone gate reviews and the commit gate (manage-problem Step 11). Because this subprocess has the Agent tool in its own surface, the normal review-via-subagent paths work — no inline-verdict fallback needed.
645
- 3. **Constraints**: commit the completed work per ADR-014. Do NOT push, do NOT run `push:watch`, do NOT run `release:watch` — the orchestrator's Step 6.5 owns release cadence. Do NOT invoke `capture-*` background skills mid-iter (AFK carve-out — ADR-032), **EXCEPT** (a) **retro-surfaced observations of recurring class-of-behaviour** — those route to `/wr-itil:capture-problem` per the **P342 mechanical-stage carve-out** (see retro-on-exit constraint #4 below; same trust-boundary as `/wr-retrospective:run-retro` Step 4a verification close-on-evidence — P342); and (b) **the I13 fix-time RFC auto-create** — when the propose-fix gate inside the delegated `/wr-itil:manage-problem` traversal detects an RFC-less Known Error (`wr-itil-check-fix-rfc-trace` emits a `no-rfc-trace:` directive), the iter auto-creates a problem-traced skeleton RFC via `/wr-itil:capture-rfc` then proceeds (ADR-073 auto-create-everywhere). This is NOT an aside-capture distraction: the auto-created RFC is the **mandatory vehicle for THIS iter's own fix** (ADR-071), not a tangential observation — it is in-scope working of the current ticket, framework-mediated (NOT cat-1 direction-setting → NO `AskUserQuestion`, P132), and the loop is NEVER skipped or blocked for a missing RFC (ADR-073). Structured-log the auto-create event to the iter summary (`notes`) per JTBD-006 audit-trail + the ADR-073 reassessment criterion (auto-created-RFC-under-scoped signal feeds `/wr-retrospective:run-retro`). Do NOT use `ScheduleWakeup` under any circumstance (P083 — iteration workers must not self-reschedule). **NEVER call `AskUserQuestion` mid-loop in AFK** (P135 / ADR-044): direction / deviation-approval / one-time-override / silent-framework observations queue at `ITERATION_SUMMARY.outstanding_questions` for loop-end batched presentation. **This includes the manage-problem substance-confirm-before-build guard (ADR-074 (Confirm a decision's substance before building dependent work)):** when the propose-fix step detects that the fix builds on a born-`proposed` decision whose substance is unconfirmed (via `wr-architect-is-decision-unconfirmed`), the iter does NOT implement on it and does NOT ask mid-loop — it queues a `category: "direction"` entry naming the unconfirmed ADR + its Decision Outcome for loop-end confirmation, and routes the ticket to `action: skipped`, `skip_reason_category: user-answerable`. Building on the unconfirmed substance instead (or guessing the choice) is the P315 failure this guard exists to prevent. The queued substance-confirm is a legitimate cat-1 direction ask — it is NOT counted as lazy in the Step 2d Ask Hygiene Pass (ADR-074 lazy-count exclusion). Per-iter `AskUserQuestion` calls are sub-contracting framework-resolved decisions back to the user (lazy deferral per Step 2d Ask Hygiene Pass classification). Non-interactive defaults apply per ADR-013 Rule 6 + ADR-044's framework-resolution boundary. **Treat the user as transient** (P130): even when observably present at orchestrator dispatch time, the user may answer one question and disappear for hours; presence is not a reliable signal and is not the goal. The iter's job is to progress the ticket and accumulate questions for batched surfacing — not to ask "is it OK to proceed?" at a mechanical-stage boundary. **Do NOT poll `bats` output with a bats-console-summary regex against TAP-format output** (P146 — bash until-loop-deadlock antipattern). The bats-console-summary line `<N> tests, <M> failures` is emitted ONLY by bats's *default* (non-TAP) formatter; `bats --tap` does not emit a console summary, so a polling loop of shape `until [ -f $OUT ] && grep -qE '^[0-9]+ tests?,' $OUT; do sleep 5; done` spins forever after bats completes (silent deadlock — no error, no exit; recovery requires manual SIGTERM with metadata loss per the P146/P147 stuck-before-emit subclass). When you need to wait on a backgrounded bats run, prefer `wait $bg_pid` (Unix idiom — completion signaled by process exit, no regex required) or, for the Bash tool, `run_in_background=true` + `BashOutput` polling on the tool's exit-state field rather than regex-poll on stdout. If you genuinely must regex-poll TAP output, anchor on the TAP plan line `^[0-9]+\.\.[0-9]+` (e.g. `1..1455`) — TAP's plan line is emitted on completion and is format-stable across bats versions; the bats-console-summary line is not. The console-summary vs TAP-format divergence is the load-bearing detail: `bats` and `bats --tap` produce structurally different stdout, and the antipattern assumes the former when iter dispatch typically uses the latter. **Do NOT poll subprocess completion with `pgrep -f '<pattern>'` inside an `until` / `while` loop** (P232 — self-referential pgrep deadlock; sibling variant of P146). `pgrep -f` matches against the FULL command line of every running process, so the polling loop's own `zsh -c` argument (which contains the literal `pgrep -f '<pattern>'` text) matches itself; with multiple concurrent polling loops, each loop matches the others and spins forever. Worked example of the antipattern: `until ! pgrep -f 'bats --recursive' > /dev/null 2>&1; do sleep 5; done` — the 2026-05-16 P232 deadlock witness; 4 concurrent polling loops each matched the others' command lines while no actual bats process ran; 45 min wall-clock + $20-30 wasted before manual SIGTERM. The same self-reference shape applies to `while pgrep -f ...; do sleep; done` and to `until ! pkill -0 -f '<pattern>'` / `while pkill -0 -f '<pattern>'` (signal-0 polling). The structural fix is the same as P146: prefer `wait $bg_pid` (Unix idiom — shell-native completion signal, no regex / no pgrep) or Bash-tool `run_in_background=true` + `BashOutput` polling (harness-tracked completion state). The hook `packages/itil/hooks/itil-bash-polling-antipattern-detect.sh` denies these shapes at PreToolUse:Bash, but the prompt rule belongs here too — structural enforcement + prompt discipline together close the class. **If the fix changes shippable code or package behaviour** (any path under `packages/<plugin>/{src,bin,hooks,skills,scripts,lib,agents}` excluding test paths — `test/`, `hooks/test/`, `scripts/test/` — and excluding `README.md` + `docs/*.md`), **the iter MUST author a `.changeset/*.md` entry in the same single ADR-014-grain commit as the fix** (the changeset names the bumping plugin via the YAML frontmatter `"@windyroad/<plugin>": <patch|minor|major>` per the changesets-action contract). **Doc-only changes** (under `docs/`, `*.md`) **and test-only changes** (under any `test/` path) **that ship no behaviour MAY omit the changeset**. The orchestrator's Step 6.5 release-cadence drain runs `release:watch` only when `.changeset/` is non-empty after push — without an iter-authored changeset, code-shape fixes accumulate without ever shipping to npm (violating JTBD-006's audit-trail expectation + JTBD-007's "Keep Plugins Current" closure dependency). Hook `packages/itil/hooks/itil-changeset-discipline.sh` (P141) provides hook-level enforcement at `git commit` time as defence-in-depth — but plugin hook execution depends on the marketplace cache carrying the current hook version, so the prompt-time constraint here MUST land independently (composes-with the hook; does NOT rely on the hook being installed). Inbound-reported from downstream consumer bbstats as their P195 — see [Related](#related) for `**Origin**: inbound-reported (bbstats#195)` per ADR-076. **`@jtbd JTBD-006`** (load-bearing) **`@jtbd JTBD-007`** (closure-dependent).
645
+ 3. **Constraints**: commit the completed work per ADR-014. Do NOT push, do NOT run `push:watch`, do NOT run `release:watch` — the orchestrator's Step 6.5 owns release cadence. Do NOT invoke `capture-*` background skills mid-iter (AFK carve-out — ADR-032), **EXCEPT** (a) **retro-surfaced observations of recurring class-of-behaviour** — those route to `/wr-itil:capture-problem` per the **P342 mechanical-stage carve-out** (see retro-on-exit constraint #4 below; same trust-boundary as `/wr-retrospective:run-retro` Step 4a verification close-on-evidence — P342); and (b) **the I13 fix-time RFC auto-create** — when the propose-fix gate inside the delegated `/wr-itil:manage-problem` traversal detects an RFC-less Known Error (`wr-itil-check-fix-rfc-trace` emits a `no-rfc-trace:` directive), the iter auto-creates a problem-traced skeleton RFC via `/wr-itil:capture-rfc` then proceeds (ADR-073 auto-create-everywhere) — **UNLESS** an existing RFC cited in the ticket is already its fix vehicle and merely lacks the trace edge, in which case the iter **wires** the trace edge into that RFC's `problems:` array (running `wr-itil-update-problem-rfcs-section`) rather than minting a redundant duplicate RFC that fragments the fix (P371; existing-vehicle-untraced sub-case — ADR-073 auto-create is the *no-vehicle* case only; vehicle-vs-merely-related is a judgement read of citation context, structured-logged as `I13: wired P<NNN> trace edge into existing RFC-<NNN>`; the load-bearing branch prose lives in the delegated `/wr-itil:manage-problem` I13 gate). This is NOT an aside-capture distraction: the auto-created RFC is the **mandatory vehicle for THIS iter's own fix** (ADR-071), not a tangential observation — it is in-scope working of the current ticket, framework-mediated (NOT cat-1 direction-setting → NO `AskUserQuestion`, P132), and the loop is NEVER skipped or blocked for a missing RFC (ADR-073). Structured-log the auto-create event to the iter summary (`notes`) per JTBD-006 audit-trail + the ADR-073 reassessment criterion (auto-created-RFC-under-scoped signal feeds `/wr-retrospective:run-retro`). Do NOT use `ScheduleWakeup` under any circumstance (P083 — iteration workers must not self-reschedule). **NEVER call `AskUserQuestion` mid-loop in AFK** (P135 / ADR-044): direction / deviation-approval / one-time-override / silent-framework observations queue at `ITERATION_SUMMARY.outstanding_questions` for loop-end batched presentation. **This includes the manage-problem substance-confirm-before-build guard (ADR-074 (Confirm a decision's substance before building dependent work)):** when the propose-fix step detects that the fix builds on a born-`proposed` decision whose substance is unconfirmed (via `wr-architect-is-decision-unconfirmed`), the iter does NOT implement on it and does NOT ask mid-loop — it queues a `category: "direction"` entry naming the unconfirmed ADR + its Decision Outcome for loop-end confirmation, and routes the ticket to `action: skipped`, `skip_reason_category: user-answerable`. Building on the unconfirmed substance instead (or guessing the choice) is the P315 failure this guard exists to prevent. The queued substance-confirm is a legitimate cat-1 direction ask — it is NOT counted as lazy in the Step 2d Ask Hygiene Pass (ADR-074 lazy-count exclusion). Per-iter `AskUserQuestion` calls are sub-contracting framework-resolved decisions back to the user (lazy deferral per Step 2d Ask Hygiene Pass classification). Non-interactive defaults apply per ADR-013 Rule 6 + ADR-044's framework-resolution boundary. **Treat the user as transient** (P130): even when observably present at orchestrator dispatch time, the user may answer one question and disappear for hours; presence is not a reliable signal and is not the goal. The iter's job is to progress the ticket and accumulate questions for batched surfacing — not to ask "is it OK to proceed?" at a mechanical-stage boundary. **Do NOT poll `bats` output with a bats-console-summary regex against TAP-format output** (P146 — bash until-loop-deadlock antipattern). The bats-console-summary line `<N> tests, <M> failures` is emitted ONLY by bats's *default* (non-TAP) formatter; `bats --tap` does not emit a console summary, so a polling loop of shape `until [ -f $OUT ] && grep -qE '^[0-9]+ tests?,' $OUT; do sleep 5; done` spins forever after bats completes (silent deadlock — no error, no exit; recovery requires manual SIGTERM with metadata loss per the P146/P147 stuck-before-emit subclass). When you need to wait on a backgrounded bats run, prefer `wait $bg_pid` (Unix idiom — completion signaled by process exit, no regex required) or, for the Bash tool, `run_in_background=true` + `BashOutput` polling on the tool's exit-state field rather than regex-poll on stdout. If you genuinely must regex-poll TAP output, anchor on the TAP plan line `^[0-9]+\.\.[0-9]+` (e.g. `1..1455`) — TAP's plan line is emitted on completion and is format-stable across bats versions; the bats-console-summary line is not. The console-summary vs TAP-format divergence is the load-bearing detail: `bats` and `bats --tap` produce structurally different stdout, and the antipattern assumes the former when iter dispatch typically uses the latter. **Do NOT poll subprocess completion with `pgrep -f '<pattern>'` inside an `until` / `while` loop** (P232 — self-referential pgrep deadlock; sibling variant of P146). `pgrep -f` matches against the FULL command line of every running process, so the polling loop's own `zsh -c` argument (which contains the literal `pgrep -f '<pattern>'` text) matches itself; with multiple concurrent polling loops, each loop matches the others and spins forever. Worked example of the antipattern: `until ! pgrep -f 'bats --recursive' > /dev/null 2>&1; do sleep 5; done` — the 2026-05-16 P232 deadlock witness; 4 concurrent polling loops each matched the others' command lines while no actual bats process ran; 45 min wall-clock + $20-30 wasted before manual SIGTERM. The same self-reference shape applies to `while pgrep -f ...; do sleep; done` and to `until ! pkill -0 -f '<pattern>'` / `while pkill -0 -f '<pattern>'` (signal-0 polling). The structural fix is the same as P146: prefer `wait $bg_pid` (Unix idiom — shell-native completion signal, no regex / no pgrep) or Bash-tool `run_in_background=true` + `BashOutput` polling (harness-tracked completion state). The hook `packages/itil/hooks/itil-bash-polling-antipattern-detect.sh` denies these shapes at PreToolUse:Bash, but the prompt rule belongs here too — structural enforcement + prompt discipline together close the class. **If the fix changes shippable code or package behaviour** (any path under `packages/<plugin>/{src,bin,hooks,skills,scripts,lib,agents}` excluding test paths — `test/`, `hooks/test/`, `scripts/test/` — and excluding `README.md` + `docs/*.md`), **the iter MUST author a `.changeset/*.md` entry in the same single ADR-014-grain commit as the fix** (the changeset names the bumping plugin via the YAML frontmatter `"@windyroad/<plugin>": <patch|minor|major>` per the changesets-action contract). **Doc-only changes** (under `docs/`, `*.md`) **and test-only changes** (under any `test/` path) **that ship no behaviour MAY omit the changeset**. The orchestrator's Step 6.5 release-cadence drain runs `release:watch` only when `.changeset/` is non-empty after push — without an iter-authored changeset, code-shape fixes accumulate without ever shipping to npm (violating JTBD-006's audit-trail expectation + JTBD-007's "Keep Plugins Current" closure dependency). Hook `packages/itil/hooks/itil-changeset-discipline.sh` (P141) provides hook-level enforcement at `git commit` time as defence-in-depth — but plugin hook execution depends on the marketplace cache carrying the current hook version, so the prompt-time constraint here MUST land independently (composes-with the hook; does NOT rely on the hook being installed). Inbound-reported from downstream consumer bbstats as their P195 — see [Related](#related) for `**Origin**: inbound-reported (bbstats#195)` per ADR-076. **`@jtbd JTBD-006`** (load-bearing) **`@jtbd JTBD-007`** (closure-dependent).
646
646
  4. **Retro-on-exit (P086) + retro-surfaced observation classification (P342) + iter-owned BRIEFING commit (P212)**: before emitting `ITERATION_SUMMARY`, invoke `/wr-retrospective:run-retro`. Retro runs INSIDE this subprocess so its Step 2b pipeline-instability scan has access to the iteration's rich tool-call history (hook misbehaviour, repeat-workaround patterns, subagent-delegation friction, release-path instability). Tickets retro creates ride a separate path: they delegate through `/wr-itil:manage-problem` which IS ADR-014 in-scope and self-commits each ticket per its own Step 11. Those commits land independently and the orchestrator picks them up on the next Step 1 scan.
647
647
 
648
648
  **BRIEFING.md commit responsibility — iter owns, run-retro does not (P212).** run-retro is explicitly out-of-scope for self-commit per ADR-014's Scope section (which lists `packages/retrospective/skills/run-retro/SKILL.md` under "Out of scope for now"). Retro therefore EDITS but DOES NOT COMMIT `docs/BRIEFING.md` / `docs/briefing/*.md`. The iter subprocess (NOT run-retro, NOT the orchestrator main turn) owns the BRIEFING commit. After retro completes, run `git status --porcelain docs/BRIEFING.md docs/briefing/`. If non-empty, the iter: