@windyroad/itil 0.47.10 → 0.47.11-preview.591

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.47.10"
500
+ "version": "0.47.11"
501
501
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@windyroad/itil",
3
- "version": "0.47.10",
3
+ "version": "0.47.11-preview.591",
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"
@@ -27,25 +27,27 @@ This is the structural rationale for:
27
27
  - **Title-only filename match** — body-content matches would be too noisy at the conservative threshold. Files whose filenames have zero overlap but whose bodies mention a keyword are almost always different tickets that happen to discuss similar topics. False-positive cost would dominate.
28
28
  - **No halt-on-match** — even when matches are found, capture proceeds. The duplicate gets resolved at next `/wr-itil:review-problems` (where the full-rank scan can detect and merge actual duplicates with the user in the loop).
29
29
 
30
- ### Deferred-README-refresh contract
30
+ ### README refresh: inline (P199 Option 2 amendment, 2026-06-05)
31
31
 
32
- Capture-problem skips the P094 inline README refresh that `/wr-itil:manage-problem` Step 5 performs. The trade-off:
32
+ Capture-problem stages `docs/problems/README.md` inline at Step 6, mirroring `/wr-itil:manage-problem` Step 5 P094 (refresh-on-create) + P134 (last-reviewed rotation). The previously-load-bearing "Deferred-README-refresh contract" was reversed by user direction recorded in P199 on 2026-05-31, then implemented on 2026-06-05.
33
33
 
34
- | Surface | Inline refresh (manage-problem) | Deferred refresh (capture-problem) |
35
- |---------|---------------------------------|-------------------------------------|
36
- | README authoritativeness | Always current at commit boundary | Lags new captures until next review |
37
- | Capture-time turn cost | +1-2 turns (regenerate + stage) | 0 turns |
38
- | WSJF ranking visibility | Immediate | Pending review |
39
- | Audit trail (commit) | One commit covers ticket + README | One commit covers ticket only |
40
- | README staleness window | None | Bounded by next review invocation |
34
+ **Rationale for the reversal** (user direction):
35
+ - The P165 README-refresh-discipline hook (shipped after the initial capture-problem design) blocks every capture commit that does not stage README. The P262 workaround (a `RISK_BYPASS: capture-deferred-readme` trailer) cleared the gate but kept the README transiently stale by design — a contract that always felt half-superseded by P165 reality.
36
+ - Option 2 acknowledges reality: stage the README. The cost is one mechanical render-and-stage primitive (already proven in `/wr-itil:manage-problem`); the capture-time speed distinction from manage-problem comes from the wide-net duplicate grep + AskUserQuestion branches that capture-problem skips, not the README skip.
37
+ - The `RISK_BYPASS: capture-deferred-readme` trailer is dropped from emission. The allow-list entry in `packages/itil/hooks/lib/readme-refresh-detect.sh::_README_REFRESH_BYPASS_TRAILERS` is retained as inert dead code for adopter compatibility (minimal-change discipline).
41
38
 
42
- The deferred contract is acceptable because:
39
+ **Trade-off table (post-amendment)**:
43
40
 
44
- 1. **The on-disk ticket inventory remains the source of truth**. README.md is a derived view — consumers that need WSJF rankings can re-derive from the ticket files (and `/wr-itil:list-problems` does exactly that on cache-stale fallback).
45
- 2. **The trailing pointer in Step 7 is the user-visible signal** that the README is transiently stale. The user has explicit instructions for how to reconcile.
46
- 3. **`/wr-itil:review-problems` Step 9b's auto-transition pass already re-rates deferred-placeholder tickets** (the literal string `(deferred — re-rate at next /wr-itil:review-problems)` is the keying signal). One review pass folds all captured-but-not-rated tickets into the ranking.
41
+ | Surface | manage-problem | capture-problem (post-P199) |
42
+ |---------|----------------|------------------------------|
43
+ | README authoritativeness | Always current at commit boundary | Always current at commit boundary |
44
+ | Capture-time turn cost | +1-2 turns (regenerate + stage) | +1-2 turns (same primitive) |
45
+ | WSJF ranking visibility | Immediate (deferred-placeholder row) | Immediate (deferred-placeholder row) |
46
+ | Audit trail (commit) | One commit covers ticket + README | One commit covers ticket + README |
47
+ | README staleness window | None | None |
48
+ | Distinguishing cost shape | Wide-net duplicate grep + multi-AskUserQuestion branches | Title-only 3-keyword grep + zero AskUserQuestion |
47
49
 
48
- The bound on the staleness window is "until the next `/wr-itil:review-problems` invocation". For sessions that capture and never review, the README stays stale but the on-disk inventory is always correct, and the next session-start `wr-itil-reconcile-readme` preflight catches drift if it propagates beyond a single session.
50
+ The on-disk ticket inventory remains the source of truth; `/wr-itil:list-problems` cache-stale fallback re-derives directly from ticket files when needed.
49
51
 
50
52
  ### No AskUserQuestion at all
51
53
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: wr-itil:capture-problem
3
- description: Lightweight problem-capture skill for aside-invocation during foreground work — minimal duplicate-check, skeleton ticket file, single commit per capture, no inline README refresh. Defers full duplicate analysis and README refresh to /wr-itil:review-problems. Use this when the user (or agent mid-iter) wants to capture an observation quickly without disrupting current task flow. For full-intake new-problem creation, use /wr-itil:manage-problem.
3
+ description: Lightweight problem-capture skill for aside-invocation during foreground work — minimal duplicate-check, skeleton ticket file, single commit per capture (covers new ticket + inline README refresh per P094 per P199 Option 2 amendment 2026-06-05). Defers full duplicate analysis to /wr-itil:review-problems. Use this when the user (or agent mid-iter) wants to capture an observation quickly without disrupting current task flow. For full-intake new-problem creation, use /wr-itil:manage-problem.
4
4
  allowed-tools: Read, Write, Edit, Bash, Grep, Glob, AskUserQuestion
5
5
  ---
6
6
 
@@ -46,6 +46,8 @@ This skill has **at most one direction-setting AskUserQuestion (the I12 derive-t
46
46
 
47
47
  Per ADR-013 Rule 6 fail-safe: every decision above resolves without interactive user input in non-interactive contexts. The derive-then-ratify AskUserQuestion fires only on derivation-failure (interactive surface) AND only when `--no-prompt` is absent (AFK callers pre-resolve via flags or halt-with-stderr-directive — never silently swallow the ratification gate).
48
48
 
49
+ **ADR-013 Rule 6 carve-out audit (P352, 2026-06-06 amendment)**: the universal AFK default is **queue-and-continue** (queue the decision, continue the loop). The HALT-with-stderr-directive carve-outs in the Resolution table above (Empty `$ARGUMENTS`, AFK halt-without-flags) are documented deviations from the universal default, authorised by **ADR-074** (Confirm decision substance before building dependent work). Rationale: capture-problem creates a durable ticket artefact; auto-creating with derived-but-unratified persona/JTBD substance would build dependent work (the ticket file, the README row, the WSJF rank) on an unconfirmed decision — the precise harm ADR-074 prohibits. No-ticket-created is the user-pinned protection; the HALT is the persona-correct shape (JTBD-006's "queued for my return, not guessed at" is satisfied by the stderr directive surfacing on user return + the AFK loop continuing to the next problem).
50
+
49
51
  ## Steps
50
52
 
51
53
  ### 0. README reconciliation preflight (P118)
@@ -287,12 +289,27 @@ The deferred-placeholder pattern is load-bearing — `/wr-itil:review-problems`
287
289
 
288
290
  Single `Write` to `docs/problems/open/<NNN>-<kebab-title>.md` (per ADR-031 per-state-subdir layout). The P119 PreToolUse hook permits the Write because Step 2 set the marker.
289
291
 
290
- ### 6. Commit per ADR-014 — single commit, no README refresh
292
+ ### 6. Commit per ADR-014 — single commit, inline README refresh (P094)
293
+
294
+ **P199 / Option 2 amendment (2026-06-05).** This step previously skipped the README refresh and emitted a `RISK_BYPASS: capture-deferred-readme` trailer to clear the P165 README-refresh gate. The user-directed Option 2 resolution (recorded 2026-05-31 on P199) kills the deferred-README-refresh contract: capture-problem now stages `docs/problems/README.md` inline, mirroring `/wr-itil:manage-problem` Step 5 P094 (refresh-on-create) + P134 (last-reviewed rotation). The trailer is dropped from the commit; the allow-list entry in `packages/itil/hooks/lib/readme-refresh-detect.sh::_README_REFRESH_BYPASS_TRAILERS` is retained as inert dead code (minimal-change discipline — future adopters that registered against the token continue to work). Authority: P199 Option 2 user direction + ADR-032 amendment + ADR-014 bypass-token-table amendment (same single coherent commit).
295
+
296
+ #### README.md refresh on new ticket (P094)
297
+
298
+ After writing the new `.open.md` file at Step 5, regenerate `docs/problems/README.md` to insert the new ticket's row into the WSJF Rankings, and stage the refreshed README in the same commit as the new ticket. The mechanism is **inline at this execution site per P331** — not deferred via cross-reference — so a single-pass agent reading Step 6 does not silently skip the archive step (the canonical P331 silent-skip regression).
291
299
 
292
- **Stage list**: ONLY the new ticket file. **Do NOT** stage `docs/problems/README.md`. The deferred-README-refresh contract is the load-bearing distinction from `/wr-itil:manage-problem` capture-time speed depends on skipping the regenerate-and-stage cycle.
300
+ **Mechanism**: use the same rendering rules as `/wr-itil:manage-problem` Step 5 P094 / Step 7 P062 (glob `docs/problems/*.open.md` / `*.known-error.md` / `*.verifying.md` / `*.parked.md` AND the per-state-subdir layout `docs/problems/open/*.md` / `docs/problems/known-error/*.md` / `docs/problems/verifying/*.md` / `docs/problems/parked/*.md`; rank open/known-error by WSJF; list verifyings in the Verification Queue ordered by Released date ASC per P150; list parkeds in the Parked section). The refresh is a **render, not a re-rank** — existing WSJF values on the other ticket files are trusted per P062's established discipline. Only the new ticket's own (deferred-placeholder) WSJF is consumed from its freshly-written file. **WSJF Rankings tier + tie-break sort** (P138 + ADR-076) and **Verification Queue sort direction** (P150) and **Likely-verified cell shape** (P186) all follow the canonical render rules — see `/wr-itil:manage-problem` Step 5 P094 block for the full prose; drift here re-opens those tickets.
301
+
302
+ **P134 last-reviewed rotation** — inline at this execution site (not deferred to a § subsection) per P331 silent-skip discipline. MUST execute IN ORDER:
303
+
304
+ 1. **Read** line 3 of `docs/problems/README.md`: `awk 'NR==3' docs/problems/README.md`.
305
+ 2. **Append-if-non-empty (BEFORE step 3, not after)** — if line 3 is non-empty AND not a same-session same-verb near-duplicate of the new fragment, append the existing line 3 verbatim to `docs/problems/README-history.md` under a `## YYYY-MM-DD` heading (creating the heading on first append for that date; subsequent same-day appends nest under the existing heading). Run this BEFORE the Edit-tool rewrite in step 3 — Edit's replace pattern destroys the displaced content otherwise.
306
+ 3. **Rewrite** line 3 of `docs/problems/README.md` with the new fragment of form `> Last reviewed: YYYY-MM-DD **P<NNN> captured** — <one-line title> (lightweight aside via /wr-itil:capture-problem)`. Soft cap ≤ 1024 bytes per fragment; hard ceiling 5120 bytes per ADR-040 Tier 3 envelope.
307
+ 4. **Stage all three** — `git add docs/problems/open/<NNN>-<kebab-title>.md docs/problems/README.md docs/problems/README-history.md` so the same single commit per ADR-014 captures the new ticket + refreshed README + (when line-3 displaced) history. Omit `README-history.md` from the stage list when no line-3 displacement occurred (no untracked diff). Canonical rationale anchor: `/wr-itil:manage-problem` § Last-reviewed line discipline (P134) subsection.
293
308
 
294
309
  ```bash
295
- git add docs/problems/open/<NNN>-<kebab-title>.md
310
+ git add docs/problems/open/<NNN>-<kebab-title>.md docs/problems/README.md
311
+ # If line-3 was rotated above, also:
312
+ git add docs/problems/README-history.md
296
313
  ```
297
314
 
298
315
  Satisfy the commit gate per ADR-014 — same two-path pattern as manage-problem Step 11:
@@ -300,20 +317,17 @@ Satisfy the commit gate per ADR-014 — same two-path pattern as manage-problem
300
317
  - **Primary**: delegate to subagent type `wr-risk-scorer:pipeline` via the Agent tool.
301
318
  - **Fallback**: invoke `/wr-risk-scorer:assess-release` via the Skill tool when the subagent type is unavailable in the current tool surface.
302
319
 
303
- Land the commit via the **`wr-risk-scorer-restage-commit`** helper — atomic re-stage + commit in a single bash call (P326 wrapper). The Agent-tool delegation above can silently clear the index; the helper re-adds the supplied path, asserts non-empty staging, then runs `git commit` with the supplied `-m` args. The `RISK_BYPASS: capture-deferred-readme` trailer rides as a second `-m` paragraph so the literal token appears in the resulting commit-message command string the PreToolUse hook inspects:
320
+ Land the commit via the **`wr-risk-scorer-restage-commit`** helper — atomic re-stage + commit in a single bash call (P326 wrapper). The Agent-tool delegation above can silently clear the index; the helper re-adds the supplied paths, asserts non-empty staging, then runs `git commit` with the supplied `-m` args:
304
321
 
305
322
  ```bash
306
323
  wr-risk-scorer-restage-commit \
307
324
  -m "docs(problems): capture P<NNN> <title>" \
308
- -m "RISK_BYPASS: capture-deferred-readme" \
309
- -- docs/problems/open/<NNN>-<kebab-title>.md
325
+ -- docs/problems/open/<NNN>-<kebab-title>.md docs/problems/README.md
326
+ # If README-history.md was modified, append it to the path list:
327
+ # -- docs/problems/open/<NNN>-<kebab-title>.md docs/problems/README.md docs/problems/README-history.md
310
328
  ```
311
329
 
312
- The `capture` verb in the message is the audit signal that this ticket landed via the lightweight aside path (vs. `open` for manage-problem's full intake).
313
-
314
- **Why the trailer (P262)**: the P165 README-refresh-discipline hook (`packages/itil/hooks/itil-readme-refresh-discipline.sh`) treats any newly-staged ticket file as ranking-bearing and DENIES a `git commit` that does not also stage `docs/problems/README.md`. That enforcement is correct for `/wr-itil:manage-problem`'s full-intake path (P094 refresh-on-create) but conflicts with this skill's deliberate deferred-README-refresh contract. The `RISK_BYPASS: capture-deferred-readme` trailer is a registered allow-list token (P265 mechanism; registry of record is the ADR-014 commit-message bypass-token table) that clears the **README-refresh gate ONLY** — the commit is still risk-scored normally (`risk-score-commit-gate.sh` does not recognise this token).
315
-
316
- Do NOT drop the trailer and stage the README instead — that would silently abandon the deferred-README-refresh contract (the capture-time-speed distinction this skill exists to provide per ADR-032). The README is reconciled at the next `/wr-itil:review-problems` per Step 7's trailing pointer.
330
+ The `capture` verb in the message is the audit signal that this ticket landed via the lightweight aside path (vs. `open` for manage-problem's full intake). The P165 README-refresh-discipline hook now allows the commit naturally because the README is staged — no `RISK_BYPASS` trailer needed.
317
331
 
318
332
  ### 7. Report
319
333
 
@@ -331,15 +345,15 @@ After the commit, report:
331
345
 
332
346
  | `preflight_reason` | Trailing-pointer shape |
333
347
  |---------------------------------------------------|--------------------------------------------------------------------------------------------------------|
334
- | `no-deferred-placeholders` / `below-threshold ...` / `fresh-readme ...` | Default (low-priority) pointer: *"Run `/wr-itil:review-problems` next to fold P\<NNN\> into the WSJF rankings, re-rate the deferred placeholders, and refresh `docs/problems/README.md`."* |
335
- | `no-readme count=<N>` | **Highlighted (actionable) pointer**: *"⚠ `<N>` deferred-placeholder ticket(s) have accumulated AND `docs/problems/README.md` is missing/malformed — run `/wr-itil:review-problems` NOW to rebuild the README and re-rate placeholders."* |
336
- | `stale-readme count=<N> age=<X>s threshold=<Y>s` | **Highlighted (actionable) pointer**: *"⚠ `<N>` deferred-placeholder ticket(s) have accumulated AND the WSJF Rankings cadence is `<X>` days stale (> 7-day threshold) — run `/wr-itil:review-problems` NOW to re-rate placeholders and refresh `docs/problems/README.md`."* |
348
+ | `no-deferred-placeholders` / `below-threshold ...` / `fresh-readme ...` | Default (low-priority) pointer: *"Run `/wr-itil:review-problems` next to re-rate the deferred Priority/Effort placeholders on P\<NNN\>."* (README is now refreshed inline at Step 6 per P199 Option 2 — the pointer no longer names a README-refresh action in the default shape.) |
349
+ | `no-readme count=<N>` | **Highlighted (actionable) pointer**: *"⚠ `<N>` deferred-placeholder ticket(s) have accumulated AND `docs/problems/README.md` is missing/malformed — run `/wr-itil:review-problems` NOW to rebuild the README and re-rate placeholders."* (Fires only when README is genuinely missing/malformed despite this skill's inline refresh — a drift class the helper still surfaces.) |
350
+ | `stale-readme count=<N> age=<X>s threshold=<Y>s` | **Highlighted (actionable) pointer**: *"⚠ `<N>` deferred-placeholder ticket(s) have accumulated AND the WSJF Rankings cadence is `<X>` days stale (> 7-day threshold) — run `/wr-itil:review-problems` NOW to re-rate placeholders."* (Inline refresh at Step 6 freshens the README mtime on every capture, so this shape now fires only when captures are absent for > 7 days — a real cadence-stale signal, not capture-driven drift.) |
337
351
 
338
- **Why conditional, not auto-dispatch** (ADR-032 + JTBD-001): capture-problem is intentionally lightweight per ADR-032 P155 amendment. Auto-dispatching review-problems from capture would re-introduce the ~10-turn ceremony the lightweight aside is engineered to avoid. The conditional pointer preserves the speed-of-capture contract while surfacing the signal "the README is now MORE than transiently stale" when both axes hit threshold. The user picks when to absorb the re-rate cost.
352
+ **Why conditional, not auto-dispatch** (ADR-032 + JTBD-001): capture-problem is intentionally lightweight per ADR-032 P155 amendment. Auto-dispatching review-problems from capture would re-introduce the ~10-turn ceremony the lightweight aside is engineered to avoid. The conditional pointer surfaces the signal "deferred-placeholder backlog has grown AND the cadence axis hit threshold" when both axes fire. The user picks when to absorb the re-rate cost.
339
353
 
340
354
  **Fail-soft**: any error in the helper invocation MUST NOT block the report — fall back to the default pointer shape.
341
355
 
342
- The trailing pointer is **not optional** — it is the user-visible signal that the README is transiently stale and how to reconcile it. The conditional highlight (P271) escalates the signal when the deferred-placeholder backlog AND the cadence axis both hit threshold. Drift here re-opens P271.
356
+ The trailing pointer is **not optional** — it is the user-visible signal for deferred-placeholder re-rating cadence. The conditional highlight (P271) escalates the signal when the deferred-placeholder backlog AND the cadence axis both hit threshold. Drift here re-opens P271.
343
357
 
344
358
  <!-- @jtbd JTBD-001 (Enforce Governance Without Slowing Down — conditional highlight escalates the signal without forcing a flow break) -->
345
359
 
@@ -353,7 +367,7 @@ The trailing pointer is **not optional** — it is the user-visible signal that
353
367
  | Type-tag prompt | RETIRED (P287, 2026-06-02) | RETIRED (P287, 2026-06-02) — the technical/user-business axis was removed as redundant with RFC/Story persona-anchoring per ADR-060 Phase 4 |
354
368
  | JTBD-trace + persona | Step 4-equivalent ingestion path | Step 1.5b I12 derive-then-ratify dispatch (ADR-060 Amendment 2026-06-02) — flag pre-resolution (`--jtbd=` / `--persona=`) silent-proceeds; lexical detection of JTBD-NNN citations silent-proceeds; cited-JTBD persona derivation silent-proceeds; derivation-failure → AskUserQuestion proposal with REJECT (= problem rejected; no ticket) / option-pick (acceptance) / free-text correction (correction-as-acceptance); AFK callers pre-resolve via flags or halt-with-stderr-directive when `--no-prompt` |
355
369
  | AskUserQuestion authority | Multiple branches (deviation-approval / direction-setting / taste / mechanical) | One direction-setting branch on the I12 derive-failure fallback (ADR-044 category 1); silent-framework (category 4) on derive-success paths; zero control-flow branches keyed on the answer's substance (REJECT/option-pick/correction are uniform handlers) |
356
- | README refresh | P094 inline (regenerate + stage in same commit) | Deferred to next `/wr-itil:review-problems` |
370
+ | README refresh | P094 inline (regenerate + stage in same commit) | P094 inline (regenerate + stage in same commit) — P199 Option 2 amendment 2026-06-05; previously deferred to next `/wr-itil:review-problems` |
357
371
  | Status transitions | Step 7 owns Open → Known Error → Verifying → Closed | Out of scope (creation only) |
358
372
  | Commit grain | One commit per intake (or per split-concern set) | One commit per capture |
359
373
  | Use case | Full-intake new problem; user wants to walk the flow | Aside-invocation; capture-and-continue |
@@ -366,8 +380,9 @@ The two skills share the `/tmp/manage-problem-grep-${SESSION_ID}` create-gate ma
366
380
  - **P014** (`docs/problems/open/014-aside-invocation-for-governance-skills.md`) — parent / master tracker.
367
381
  - **P078** — capture-on-correction OFFER pattern; depends on capture-problem shipping.
368
382
  - **P119** — manage-problem create-gate hook; capture-problem composes with the same marker.
369
- - **P262** — the P165 README-refresh-discipline hook conflicted with this skill's deferred-README-refresh contract (Step 6 "do NOT stage README" was denied by the hook on every capture commit). Resolved by the `RISK_BYPASS: capture-deferred-readme` allow-list token (Step 6 trailer above); clears the README-refresh gate only, not the risk-score gate.
370
- - **P265** — the RISK_BYPASS-trailer allow-list mechanism in `readme-refresh-detect.sh` that P262's `capture-deferred-readme` token registers into.
383
+ - **P199** (`docs/problems/verifying/199-...md`) Option 2 amendment 2026-06-05: kill the deferred-README-refresh contract; Step 6 now stages README inline per P094. User direction recorded 2026-05-31 in the ticket. This SKILL change rides with the ADR-032 + ADR-014 amendments in the same coherent commit.
384
+ - **P262** (closed) — the P165 README-refresh-discipline hook conflicted with this skill's previous deferred-README-refresh contract. The prior workaround was the `RISK_BYPASS: capture-deferred-readme` allow-list token. Superseded by P199 Option 2 (2026-06-05) — capture-problem now stages README inline and the trailer is no longer emitted. The allow-list entry in `packages/itil/hooks/lib/readme-refresh-detect.sh::_README_REFRESH_BYPASS_TRAILERS` is retained as inert dead code (minimal-change discipline; adopter compatibility).
385
+ - **P265** — the RISK_BYPASS-trailer allow-list mechanism in `readme-refresh-detect.sh`. Still in force for the `adr-031-migration` token; the `capture-deferred-readme` entry is now inert (no live emitter) but registered for adopter compatibility.
371
386
  - **P170** (`docs/problems/known-error/170-problem-tickets-strain-as-fixes-decompose-into-multiple-coordinated-changes-need-rfc-framework.md`) — RFC framework driver; Slice 4 B7.T3 / item 8c historically authored the type-classification prompt at Step 1.5 (RETIRED by P287, 2026-06-02).
372
387
  - **P176** — agent-side I2 (no type-branching) coverage gap on the SKILL.md surface. P287 retires the type axis altogether; the regression guard is preserved under `packages/itil/scripts/test/no-type-regression-guard.bats` (asserting the `**Type**:` field is GONE from skeleton templates).
373
388
  - **P287** (`docs/problems/.../287-remove-technical-user-business-type-classification-from-problems-redundant-with-rfc-persona-anchoring.md`) — the user direction (twice-confirmed 2026-05-25 + 2026-06-02) that retired Step 1.5 Type classification; ADR-060 amendment substance (I12 replacement, Phase-4 rework) queued for user re-confirmation per ADR-074.
@@ -179,7 +179,7 @@ What "work" means depends on the problem's status:
179
179
  Exit 0 = unconfirmed (born without `human-oversight: confirmed`, not superseded) → the guard fires for that ADR. Exit 1 = confirmed or superseded → OK to build. Exit 2 = not found → treat as not-a-blocker (surface in the report).
180
180
  3. **If any referenced decision is unconfirmed**: do NOT implement yet. Surface its **substance** (the chosen option the ADR records — not a grain/meta question) for human confirmation:
181
181
  - **Interactive**: `AskUserQuestion` presenting the ADR's Decision Outcome + Considered Options so the user confirms / amends / rejects the substantive choice. On confirm, the recording skill writes the `human-oversight: confirmed` marker (ADR-066) before the build proceeds.
182
- - **AFK** (`/wr-itil:work-problems` orchestrator): NEVER ask mid-loop — queue the substance to the iteration's `outstanding_questions` (ADR-044 AFK carve-out) and skip the build; do not guess.
182
+ - **AFK** (`/wr-itil:work-problems` orchestrator): NEVER ask mid-loop — queue the substance to the iteration's `outstanding_questions` (ADR-044 AFK carve-out) and skip the build; do not guess. This is the **queue-and-continue** universal default per ADR-013 Rule 6 (P352, 2026-06-06 amendment): the iter queues the substance + advances; the orchestrator main turn surfaces the queued question at loop end via the Step 2.5 batched AskUserQuestion.
183
183
  4. This ask is **ADR-044 category-1 direction-setting** and is EXCLUDED from the lazy-AskUserQuestion regression metric (it is legitimate, not lazy). The trigger is narrow — detection is mechanical (the predicate); only genuine unconfirmed decisions about to be built on fire it. Do NOT over-fire on confirmed/superseded/obvious decisions (inverse-P078 / P132 guard). A born-`proposed` marker is fine for *recording*; it is not a licence to *build* (ADR-066 carve-out).
184
184
 
185
185
  The Phase 2 working-the-problem traversal makes "implement the fix" concretely traceable via stories (per ADR-060 lines 300-320). Replaces the prior vague "implement the fix following the project's development workflow" with a deterministic problem → RFC → story dispatch:
@@ -496,6 +496,8 @@ Before writing the problem file, perform a concern-boundary analysis on the gath
496
496
 
497
497
  **Non-interactive fallback**: When `AskUserQuestion` is unavailable (e.g., non-interactive/AFK mode), automatically split into separate problems and note the auto-split in output. Do not block creation.
498
498
 
499
+ **ADR-013 Rule 6 carve-out audit (P352, 2026-06-06 amendment)**: the universal AFK default is **queue-and-continue**; this site is a documented **AUTO-DEFAULT** carve-out. Authorising principle: policy-authorised safe default per ADR-044 category 4 (silent framework). Splitting is fully reversible (manual combine via Related cross-references + WSJF re-rank), the framework's lifecycle model rewards explicit per-concern WSJF ranking, and "split when in doubt" is the persona-correct safe heuristic for JTBD-006 — the loop progresses, over-splits are cheap to combine, and halt would cost more loop throughput than the over-split risk. Symmetric with the parallel `/wr-architect:create-adr` Step 1 multi-decision auto-split (same authority, same rationale).
500
+
499
501
  **Split implementation**: When splitting, assign consecutive IDs (e.g., if next ID is 035, create P035 and P036). Create each problem file independently. Cross-reference each ticket in the other's "Related" section.
500
502
 
501
503
  **Scope**: This step applies only to **new problem creation** (steps 2–5). It does NOT apply to updates, status transitions, or reviews of existing tickets.
@@ -401,10 +401,11 @@ Open the issue:
401
401
  gh issue create \
402
402
  --repo "${UPSTREAM_OWNER_REPO}" \
403
403
  --title "${TITLE_PREFIXED_BY_TEMPLATE}" \
404
- --body "${FILLED_BODY}" \
405
- --label "${MATCHED_TEMPLATE_LABEL_IF_ANY}"
404
+ --body "${FILLED_BODY}"
406
405
  ```
407
406
 
407
+ Do **not** pass `--label` on this call (P207). Labels are supplied by the matched template's YAML `labels:` frontmatter and applied by GitHub when the issue form is submitted; passing `--label <name>` for a label that has not been pre-created on the upstream repo causes `gh issue create` to hard-fail with `could not add label: '<name>' not found`. The flag is redundant when the matched template carries `labels:` and a hard-fail surface when it does not. If the upstream has no matched template at all (structured-default body path, Step 3 preference order item 7), omit labels entirely — leave triage to the upstream maintainer's existing routing.
408
+
408
409
  Capture the returned issue URL. The voice-tone gate per ADR-028 may delegate-and-retry; treat this as expected (see "Voice-tone gate interaction" above). Proceed to Step 7 once the issue is created.
409
410
 
410
411
  ### 5c. Comment path (P070)
@@ -134,7 +134,7 @@ Per ADR-062 (peer of ADR-024). Polls configured upstream channels, runs each unm
134
134
  Read `docs/problems/.upstream-channels.json`. Branch on state:
135
135
 
136
136
  - **File exists and parses cleanly** → continue to 4.5b with the parsed `channels[]` list.
137
- - **File exists but is malformed JSON** → log an advisory note (`channel config malformed JSON; inbound-discovery skipped this pass — fix the file then re-invoke`) and skip Step 4.5. This is genuine fail-soft because the user already SHIPPED a config and the malformation is an editing artefact best resolved by the user reading the parse error; auto-rewriting their file would destroy their work.
137
+ - **File exists but is malformed JSON** → log an advisory note (`channel config malformed JSON; inbound-discovery skipped this pass — fix the file then re-invoke`) and skip Step 4.5. **ADR-013 Rule 6 carve-out (P352, 2026-06-06 amendment)**: this is a documented SKIP carve-out (deviation from the universal queue-and-continue default). Authorising principle: user-shipped artefact protection — the user already SHIPPED a config and the malformation is an editing artefact best resolved by the user reading the parse error; auto-rewriting their file (queue-then-overwrite-on-return) would destroy their work. The advisory note IS the queued surface for user attention on next interactive session; the loop continues. Same shape as a parse-error halt at a user-owned file boundary.
138
138
  - **File does NOT exist** → run the **auto-bootstrap routine** below per P351 / JTBD-101 / JTBD-007. **Adopters who never want to configure inbound-discovery** can keep `.upstream-channels.json` absent by answering `decline` at the interactive prompt OR allowing the AFK-mode outstanding-question to lapse; the absence stays zero-ceremony-tax (ADR-062 § Downstream-adopter non-obligation), but the silent skip is replaced by an explicit one-time-per-session prompt so the adopter has a visible signal that the inbound-discovery capability exists. <!-- @jtbd JTBD-101 (Extend the Suite — deliver-installed-features signal) --> <!-- @jtbd JTBD-007 (Keep Plugins Current — process reports what configured) --> <!-- @problem P351 (auto-bootstrap on missing precondition config) -->
139
139
 
140
140
  **Auto-bootstrap routine (P351)**: replaces the prior "missing file → silent skip" behaviour. The routine branches on AskUserQuestion availability per ADR-013 Rule 6 + ADR-044 category 1 (direction-setting):
@@ -149,6 +149,9 @@ Read `docs/problems/.upstream-channels.json`. Branch on state:
149
149
  - On `Decline permanently (write empty channels stub)`: write `{"channels": [], "ttl_seconds": 86400, "declined_at": "<ISO>"}` so future invocations parse cleanly + skip silently. Per ADR-062 § Downstream-adopter non-obligation — the empty-channels stub IS the documented "I never want this" surface.
150
150
 
151
151
  - **AFK mode** (AskUserQuestion unavailable, e.g. invoked from `/wr-itil:work-problems`):
152
+
153
+ **ADR-013 Rule 6 universal default (P352, 2026-06-06 amendment)** — queue-and-continue. This branch is the canonical exemplar: P351 lifted this site from the prior "missing file → silent skip" anti-pattern to queue-and-continue. The pattern below is the model the rest of the suite follows.
154
+
152
155
  1. Log advisory (`inbound-discovery: channel config absent; queued config-direction outstanding_question, skipping THIS pass to allow other passes to proceed`).
153
156
  2. Queue a `direction` entry per `/wr-itil:work-problems` SKILL.md Step 5 `outstanding_questions` schema (ADR-044 category 1):
154
157
 
@@ -164,6 +164,8 @@ When all three checks pass, the host emits a one-shot `AskUserQuestion` prompt w
164
164
 
165
165
  **AFK fail-safe**: when the host is invoked from an AFK orchestrator, do NOT fire the prompt. Append a one-line "pending intake scaffold" note to the iteration report and continue. The user catches up on next interactive session.
166
166
 
167
+ **ADR-013 Rule 6 universal default (P352, 2026-06-06 amendment)**: this IS queue-and-continue — the iteration-report note is the queued surface; the loop advances. Persona-correct for JTBD-006 ("queued for my return, not guessed at"). Not a carve-out — this is the canonical default shape.
168
+
167
169
  ### Trigger 2: Pre-publish PreToolUse gate (hard stop)
168
170
 
169
171
  `packages/itil/hooks/pre-publish-intake-gate.sh` matches `npm publish` and `gh pr merge ... changeset-release/*` and denies if any of the five intake files are missing AND the decline marker is absent AND `INTAKE_BYPASS` is not set.
@@ -511,7 +511,7 @@ rm -f "$ITER_JSON"
511
511
 
512
512
  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.
513
513
  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.
514
- 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 for 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). 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.
514
+ 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 for 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). 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).
515
515
  4. **Retro-on-exit (P086) + retro-surfaced observation classification (P342)**: 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). Retro may create tickets or update `docs/BRIEFING.md` — run-retro commits its own work per ADR-014; any tickets it creates ride into either the iteration's own commit (if retro runs before the main commit) or a retro-owned follow-up commit, and the orchestrator picks them up on the next Step 1 scan. Proceed to `ITERATION_SUMMARY` emission regardless of retro findings — retro is non-blocking at the iter-subprocess layer (do not block on retro): if retro fails or surfaces findings, the iteration still returns a summary so the AFK loop does not silently halt on a flaky retro run. (Session-level retro at the orchestrator-main-turn layer per Step 2.4 gate (b) IS load-bearing — distinct surface; see Step 2.4 prose for the orchestrator-layer halt semantics.)
516
516
 
517
517
  **P342 classification taxonomy — retro-surfaced observations.** When the iter-retro's Step 4b Stage 1 surfaces a ticketable observation, the routing depends on classification:
@@ -1023,4 +1023,6 @@ When every skipped ticket is in the `upstream-blocked` category (stop-condition
1023
1023
  - **ADR-022** (`docs/decisions/022-problem-verification-pending.proposed.md`) — iteration outcomes map into the return-summary's `outcome` field (`verifying` for a released fix, `known-error` for a root-cause-confirmed ticket awaiting release, etc.).
1024
1024
  - **ADR-032** (`docs/decisions/032-governance-skill-invocation-patterns.proposed.md`) — pattern taxonomy parent; Step 5 implements the AFK iteration-isolation wrapper — subprocess-boundary variant per the P084 amendment (2026-04-21), refining the P077 Agent-tool amendment. The P077 amendment remains in the ADR as the historical Agent-tool variant; the subprocess variant is the lead for new adopters.
1025
1025
  - **ADR-037** (`docs/decisions/037-skill-testing-strategy.proposed.md`) — doc-lint bats contract-assertion pattern used by `test/work-problems-step-5-delegation.bats`.
1026
- - **JTBD-001**, **JTBD-006**, **JTBD-101**, **JTBD-201** personas whose reliability expectations the iteration-isolation wrapper restores.
1026
+ - **P206** (`docs/problems/known-error/206-work-problems-iter-workers-dont-add-changesets-fix-commits-accumulate-without-release.md`) — driver for Step 5 iter-prompt-body's explicit "if the fix changes shippable code, author a `.changeset/*.md` in the same commit" constraint (composes defence-in-depth with hook P141's `git commit`-time enforcement). Inbound-reported by downstream consumer **bbstats** as their P195 (`**Origin**: inbound-reported (bbstats#195)` per ADR-076 sort tier). Behavioural second-source: `test/work-problems-step-5-iter-changeset-required.bats` (structural-permitted per ADR-052; tdd-review comment in fixture).
1027
+ - **P141** (`docs/problems/verifying/141-iter-prompt-time-reminder-misses-40-percent-of-publishable-iters-hook-level-enforcement.md`) — sibling hook (`packages/itil/hooks/itil-changeset-discipline.sh`) that enforces the changeset-discipline rule at `git commit` time. The Step 5 iter-prompt-body constraint composes-with this hook; the prompt-time rule is load-bearing because plugin-hook execution depends on the marketplace cache carrying the current hook version (a fresh-cache adopter without P141 still gets the constraint via the prompt).
1028
+ - **JTBD-001**, **JTBD-006**, **JTBD-007**, **JTBD-101**, **JTBD-201** — personas whose reliability expectations the iteration-isolation wrapper restores. JTBD-006 (Progress the Backlog While I'm Away) + JTBD-007 (Keep Plugins Current Across Projects) are the load-bearing pair for the P206 changeset-discipline constraint — JTBD-006 requires the audit trail to stay accurate at release boundary; JTBD-007's closure depends on fixes actually shipping to npm.
@@ -0,0 +1,160 @@
1
+ #!/usr/bin/env bats
2
+ # ADR-013 Rule 6 P352 amendment (2026-06-06): queue-and-continue is the
3
+ # universal AFK default when a skill needs user input but AskUserQuestion is
4
+ # unavailable. HALT/SKIP/AUTO-DEFAULT are deviations requiring inline-cited
5
+ # carve-out justification.
6
+ #
7
+ # Structural assertion — Permitted Exception to the source-grep ban (ADR-005 /
8
+ # P011). These assertions are load-bearing-string checks on the ADR + SKILL
9
+ # specification prose. Per P081, structural tests are placeholders for
10
+ # behavioural tests against P012's skill-testing harness; until the harness
11
+ # can exercise AFK fallback shapes, prose assertions on the carve-out audit
12
+ # are the confirmation mechanism named in the amended Rule 6 Confirmation
13
+ # section.
14
+ #
15
+ # tdd-review: structural-permitted (justification: ADR Rule 6 + SKILL.md prose
16
+ # contract assertions for an interaction-pattern contract that has no
17
+ # behavioural skill-runtime harness yet — P012 + P081 Phase 2 bridge window.
18
+ # Isomorphic precedent in this repo: work-problems-above-appetite-remediation.bats,
19
+ # create-adr-substance-confirm-pattern.bats, create-adr-adr-044-contract.bats.)
20
+ #
21
+ # @problem P352 (AFK queue-and-continue is the universal default)
22
+ # @adr ADR-013 (structured user interaction; Rule 6 amended 2026-06-06)
23
+ # @adr ADR-044 (decision-delegation contract; AUTO-DEFAULT lives inside framework-resolution)
24
+ # @adr ADR-052 (behavioural-by-default with structural bridge window)
25
+ # @adr ADR-074 (confirm decision substance before building; authorises HALT carve-outs)
26
+ # @jtbd JTBD-006 (Progress the Backlog While I'm Away — primary persona)
27
+ # @jtbd JTBD-001 (Enforce Governance Without Slowing Down — queue keeps governance on during AFK)
28
+
29
+ setup() {
30
+ REPO_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../../../../.." && pwd)"
31
+ ADR_013="${REPO_ROOT}/docs/decisions/013-structured-user-interaction-for-governance-decisions.proposed.md"
32
+ }
33
+
34
+ # ----------------------------------------------------------------------
35
+ # ADR-013 Rule 6 amendment prose
36
+ # ----------------------------------------------------------------------
37
+
38
+ @test "ADR-013 file exists" {
39
+ [ -f "$ADR_013" ]
40
+ }
41
+
42
+ @test "ADR-013 Rule 6 names queue-and-continue as the universal default (P352 amendment)" {
43
+ # The load-bearing prose: queue-and-continue is THE universal default.
44
+ run grep -nE "queue-and-continue is the universal default" "$ADR_013"
45
+ [ "$status" -eq 0 ]
46
+ }
47
+
48
+ @test "ADR-013 Rule 6 dates the amendment (2026-06-06)" {
49
+ # Date-anchoring lets future readers correlate the prose with P352 timeline.
50
+ run grep -nE "2026-06-06 amendment" "$ADR_013"
51
+ [ "$status" -eq 0 ]
52
+ }
53
+
54
+ @test "ADR-013 Rule 6 names halt-with-directive AND silent-skip as deviations" {
55
+ # The amendment's contract: HALT and SKIP are DEVIATIONS requiring carve-out
56
+ # justification — they are not the default.
57
+ run grep -nE "DEVIATIONS that require an explicit" "$ADR_013"
58
+ [ "$status" -eq 0 ]
59
+ }
60
+
61
+ @test "ADR-013 Rule 6 documents the capture-problem HALT carve-out (ADR-074 authority)" {
62
+ # The amendment must explicitly name the documented HALT carve-outs so
63
+ # readers know the SKILL surfaces that LEGITIMATELY halt and why.
64
+ run grep -nE "capture-problem.*derive-then-ratify HALT" "$ADR_013"
65
+ [ "$status" -eq 0 ]
66
+ }
67
+
68
+ @test "ADR-013 Rule 6 documents the create-adr Step 5 HALT carve-out" {
69
+ run grep -nE "create-adr.*Step 5 substance-confirm HALT" "$ADR_013"
70
+ [ "$status" -eq 0 ]
71
+ }
72
+
73
+ @test "ADR-013 Rule 6 documents the manage-problem create-gate HALT carve-out" {
74
+ run grep -nE "manage-problem.*create-gate HALT" "$ADR_013"
75
+ [ "$status" -eq 0 ]
76
+ }
77
+
78
+ @test "ADR-013 Rule 6 names AUTO-DEFAULT as framework-resolved-only (ADR-044 boundary)" {
79
+ # AUTO-DEFAULT is permitted ONLY when the decision is framework-resolved.
80
+ # Outside the framework-resolution boundary, AUTO-DEFAULT is a defect.
81
+ run grep -nE "AUTO-DEFAULT.*permitted ONLY when the decision is framework-resolved" "$ADR_013"
82
+ [ "$status" -eq 0 ]
83
+ }
84
+
85
+ @test "ADR-013 Rule 6 cites ADR-044 (decision-delegation framework-resolution boundary)" {
86
+ run grep -nE "ADR-044" "$ADR_013"
87
+ [ "$status" -eq 0 ]
88
+ }
89
+
90
+ @test "ADR-013 Rule 6 cites ADR-074 (substance-confirm authority for HALT carve-outs)" {
91
+ run grep -nE "ADR-074" "$ADR_013"
92
+ [ "$status" -eq 0 ]
93
+ }
94
+
95
+ @test "ADR-013 Rule 6 cites JTBD-006 (Progress the Backlog While I'm Away)" {
96
+ run grep -nE "JTBD-006" "$ADR_013"
97
+ [ "$status" -eq 0 ]
98
+ }
99
+
100
+ @test "ADR-013 Rule 6 cites P352 as the originating ticket" {
101
+ run grep -nE "\bP352\b" "$ADR_013"
102
+ [ "$status" -eq 0 ]
103
+ }
104
+
105
+ @test "ADR-013 Rule 6 records the shared-helper extraction as a follow-on (deferred)" {
106
+ # The ratified design explicitly deferred the shared-helper extraction to
107
+ # follow-on. The prose must record the deferral so future readers (and
108
+ # future iter agents) know the interim contract.
109
+ run grep -nE "Shared-helper extraction deferred" "$ADR_013"
110
+ [ "$status" -eq 0 ]
111
+ }
112
+
113
+ # ----------------------------------------------------------------------
114
+ # Per-SKILL carve-out audit annotations
115
+ # ----------------------------------------------------------------------
116
+
117
+ @test "capture-problem SKILL.md carries the P352 carve-out audit (HALT per ADR-074)" {
118
+ SKILL="${REPO_ROOT}/packages/itil/skills/capture-problem/SKILL.md"
119
+ [ -f "$SKILL" ]
120
+ run grep -nE "ADR-013 Rule 6 carve-out audit \(P352" "$SKILL"
121
+ [ "$status" -eq 0 ]
122
+ # And the carve-out must name its authorising ADR
123
+ run grep -nE "authorised by \*\*ADR-074" "$SKILL"
124
+ [ "$status" -eq 0 ]
125
+ }
126
+
127
+ @test "create-adr SKILL.md carries the P352 carve-out audit (Step 1 AUTO-DEFAULT + Step 5 HALT)" {
128
+ SKILL="${REPO_ROOT}/packages/architect/skills/create-adr/SKILL.md"
129
+ [ -f "$SKILL" ]
130
+ run grep -nE "ADR-013 Rule 6 carve-out audit \(P352" "$SKILL"
131
+ [ "$status" -eq 0 ]
132
+ }
133
+
134
+ @test "manage-problem SKILL.md carries the P352 carve-out audit (Step 4b AUTO-DEFAULT)" {
135
+ SKILL="${REPO_ROOT}/packages/itil/skills/manage-problem/SKILL.md"
136
+ [ -f "$SKILL" ]
137
+ run grep -nE "ADR-013 Rule 6 carve-out audit \(P352" "$SKILL"
138
+ [ "$status" -eq 0 ]
139
+ }
140
+
141
+ @test "review-problems SKILL.md cites the P352 amendment at the Step 4.5 AFK branch" {
142
+ SKILL="${REPO_ROOT}/packages/itil/skills/review-problems/SKILL.md"
143
+ [ -f "$SKILL" ]
144
+ run grep -nE "ADR-013 Rule 6 universal default \(P352" "$SKILL"
145
+ [ "$status" -eq 0 ]
146
+ }
147
+
148
+ @test "scaffold-intake SKILL.md cites the P352 amendment as canonical queue-and-continue" {
149
+ SKILL="${REPO_ROOT}/packages/itil/skills/scaffold-intake/SKILL.md"
150
+ [ -f "$SKILL" ]
151
+ run grep -nE "ADR-013 Rule 6 universal default \(P352" "$SKILL"
152
+ [ "$status" -eq 0 ]
153
+ }
154
+
155
+ @test "run-retro SKILL.md cites the P352 amendment at the Step 1.5 AFK branch" {
156
+ SKILL="${REPO_ROOT}/packages/retrospective/skills/run-retro/SKILL.md"
157
+ [ -f "$SKILL" ]
158
+ run grep -nE "ADR-013 Rule 6 universal default \(P352" "$SKILL"
159
+ [ "$status" -eq 0 ]
160
+ }
@@ -0,0 +1,95 @@
1
+ #!/usr/bin/env bats
2
+ # P206 — work-problems Step 5 iteration-prompt-body must EXPLICITLY require
3
+ # AFK iter subprocesses to author a `.changeset/*.md` alongside any fix
4
+ # commit that ships shippable code. Hook P141 (itil-changeset-discipline.sh)
5
+ # enforces this at git-commit time but depends on the plugin marketplace
6
+ # cache being current. The prompt-time constraint composes defence-in-depth
7
+ # with the hook so iter subprocesses self-author the changeset rather than
8
+ # discovering the gap at commit time (or worse — slipping through when the
9
+ # hook is missing from the install).
10
+ #
11
+ # Reported as inbound from downstream consumer bbstats (their P195) on
12
+ # 2026-05-15; covered by ADR-076 Origin field tier.
13
+ #
14
+ # tdd-review: structural-permitted (justification: SKILL.md is the named
15
+ # contract document under ADR-052; behavioural alternative would require a
16
+ # synthetic `claude -p` iter dispatch harness that completes a fix commit
17
+ # and asserts `.changeset/*.md` co-presence — that harness sits outside the
18
+ # skill layer and depends on the Anthropic CLI binary. Same Permitted
19
+ # Exception precedent as `work-problems-step-5-delegation.bats:99-105` and
20
+ # the P083 / P086 / P089 ScheduleWakeup / retro / stdin-redirect fixtures
21
+ # in the same directory).
22
+ #
23
+ # @problem P206
24
+ # @problem P141
25
+ # @jtbd JTBD-006
26
+ # @jtbd JTBD-007
27
+ # @jtbd JTBD-001
28
+ #
29
+ # Cross-reference:
30
+ # P206 — this ticket (work-problems iter workers don't add changesets)
31
+ # P141 — sibling changeset-discipline hook (hook-level enforcement;
32
+ # prompt-time constraint composes defence-in-depth)
33
+ # bbstats#195 — inbound report from downstream consumer
34
+ # ADR-014 (governance skills commit their own work)
35
+ # ADR-018 (inter-iteration release cadence — changesets are the load-
36
+ # bearing input to ADR-020's auto-release path)
37
+ # ADR-052 (behavioural tests default; structural-permitted with comment)
38
+ # ADR-076 (inbound-reported problems rank ahead via sort tier — Origin
39
+ # field stamping)
40
+ # JTBD-006 (Progress the Backlog While I'm Away) — load-bearing
41
+ # JTBD-007 (Keep Plugins Current Across Projects) — closure depends on
42
+ # release actually shipping
43
+
44
+ setup() {
45
+ SKILL_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
46
+ SKILL_FILE="${SKILL_DIR}/SKILL.md"
47
+ }
48
+
49
+ @test "SKILL.md Step 5 iteration-prompt-body names changeset as required when fix changes shippable code (P206)" {
50
+ # The iteration-prompt-body must EXPLICITLY require iter subprocesses to
51
+ # author a `.changeset/*.md` alongside any fix commit that ships shippable
52
+ # code. Without the explicit constraint, iter subprocesses can complete
53
+ # fix commits that the orchestrator's Step 6.5 release-cadence drain
54
+ # then has nothing to release — fixes accumulate without an npm publish.
55
+ # The constraint must name `changeset` AND a "shippable code" qualifier
56
+ # so doc-only and test-only commits are correctly exempted.
57
+ run grep -niE "changeset.{0,200}(shippable|publishable|packages/<plugin>)" "$SKILL_FILE"
58
+ [ "$status" -eq 0 ]
59
+ }
60
+
61
+ @test "SKILL.md Step 5 iteration-prompt-body exempts doc-only and test-only changes from the changeset requirement (P206)" {
62
+ # Doc-only changes (e.g. JTBD edits, ADR edits, retro additions) and
63
+ # test-only changes (under `test/`) ship no behaviour — requiring a
64
+ # changeset for them would author noise CHANGELOG bullets per release.
65
+ # The constraint must name the exemption explicitly so iter subprocesses
66
+ # do not over-apply the rule.
67
+ run grep -niE "(doc.?only|docs.?only|test.?only).{0,80}(omit|may omit|no changeset|not required)|changeset.{0,80}(omit|exempt)" "$SKILL_FILE"
68
+ [ "$status" -eq 0 ]
69
+ }
70
+
71
+ @test "SKILL.md Step 5 iteration-prompt-body cites P141 as the defence-in-depth hook (P206)" {
72
+ # The prompt-time constraint composes with hook P141 (changeset-discipline).
73
+ # Naming P141 inline in the prompt-body makes the defence-in-depth
74
+ # composition self-documenting — a future contributor reading the prompt
75
+ # understands the hook is the second layer, not the only layer.
76
+ run grep -nE "P141" "$SKILL_FILE"
77
+ [ "$status" -eq 0 ]
78
+ }
79
+
80
+ @test "SKILL.md Related section cites P206 (this fix)" {
81
+ # ADR-037 + ADR-052 self-documenting contract: the contract document
82
+ # carries a Related section listing the problem tickets it satisfies.
83
+ # P206 closure depends on this citation landing.
84
+ run grep -nE "P206" "$SKILL_FILE"
85
+ [ "$status" -eq 0 ]
86
+ }
87
+
88
+ @test "SKILL.md Step 5 iteration-prompt-body cites bbstats#195 as the inbound source (P206 + ADR-076 Origin)" {
89
+ # ADR-076 reported-first tier requires the Origin field to be visible at
90
+ # the contract surface so future contributors understand the constraint
91
+ # was driven by external evidence, not internal speculation. The bbstats
92
+ # back-link is the audit anchor.
93
+ run grep -niE "bbstats.{0,20}195|bbstats/.{0,30}195|bbstats#195" "$SKILL_FILE"
94
+ [ "$status" -eq 0 ]
95
+ }