@windyroad/itil 2.4.4-preview.1255 → 2.5.0-preview.1259

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": "2.4.4"
500
+ "version": "2.5.0"
501
501
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wr-itil",
3
- "version": "2.4.4",
3
+ "version": "2.5.0",
4
4
  "description": "ITIL problem-management workflows for AI coding agents",
5
5
  "author": {
6
6
  "name": "Windy Road Technology",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@windyroad/itil",
3
- "version": "2.4.4-preview.1255",
3
+ "version": "2.5.0-preview.1259",
4
4
  "description": "ITIL-aligned IT service management for Claude Code and Codex",
5
5
  "bin": {
6
6
  "windyroad-itil": "./bin/install.mjs"
@@ -51,10 +51,9 @@
51
51
  # a re-render. MECHANICAL, no person: a renderer clears this condition, so
52
52
  # the caller re-renders and asks again, and escalates only if a clean
53
53
  # re-render still reports it.
54
- # - The repository holds no story maps at all → exit 3, directive naming the
55
- # one thing a person has to do — draw the first map for this journey, which
56
- # is new substance nothing may mint on their behalf. The caller records that
57
- # single item and moves to the next problem; it does not stop.
54
+ # - The repository holds no story maps at all → exit 3, directive telling the
55
+ # caller to author the complete unconfirmed proposal without permission,
56
+ # then ask only for ratification. Dependent implementation stays blocked.
58
57
  # - Missing problem file / no args → exit 2 (caller misuse), stderr usage.
59
58
  #
60
59
  # Exit 3 is a refusal the caller can act on without reading prose, and is
@@ -62,8 +61,7 @@
62
61
  #
63
62
  # @adr a-fix-proposal-draws-a-release-row-never-a-document-architecture-rule (a fix proposal draws a release row, never a document; the reader
64
63
  # is repointed ahead of the writer and fails closed during the window)
65
- # @adr a-release-row-is-the-rfc-and-the-map-is-the-approval-surface-architecture-rule (a release row is the RFC; the map is the approval surface, and
66
- # a proposal needing a new map queues for a person)
64
+ # @adr new-story-maps-are-authored-before-ratification-architecture-rule (a new map proposal is authored before ratification)
67
65
  # @adr every-fix-goes-through-an-rfc-architecture-rule (every fix goes through an RFC — unconditional, no carve-out)
68
66
  # @adr problem-rfc-story-framework-with-mandatory-problem-trace-and-unified-problem-ontology-architecture-rule (I1 load-bearing-from-the-start; I13 fix-proposal invariant)
69
67
  # @adr plugin-bundled-scripts-invoked-from-skill-md-resolve-via-bin-on-path-architecture-rule (invoked via the wr-itil-check-fix-rfc-trace bin shim on
@@ -169,7 +167,7 @@ if [ -n "${stale_maps// /}" ]; then
169
167
  fi
170
168
 
171
169
  if [ "$map_count" -eq 0 ]; then
172
- printf 'no-rfc-trace: %s — a fix is proposed as a release row on a story map, and this repository has no story maps yet. Drawing the first map for a journey decides what that journey is, so it needs a person and must not be created automatically. Record one item for the maintainer — draw a story map covering this work — and carry on to the next problem rather than stopping.\n' \
170
+ printf 'no-rfc-trace: %s — a fix is proposed as a release row on a story map, and this repository has no story maps yet. Author a complete unconfirmed story-map proposal without asking permission, including its initial activities, release row, cards, and story files, then ask only for ratification after the completed proposal exists. Do not implement its stories until the map is ratified; continue only with independent work.\n' \
173
171
  "$PID"
174
172
  exit 3
175
173
  fi
@@ -6,7 +6,7 @@ allowed-tools: Read, Write, Edit, Bash, Grep, Glob, Skill, AskUserQuestion
6
6
 
7
7
  # Capture RFC
8
8
 
9
- Draw a lightweight RFC release row on an existing story map. An RFC is a planning row, not a standalone document.
9
+ Draw a lightweight RFC release row on a story map. An RFC is a planning row, not a standalone document.
10
10
 
11
11
  ## Arguments
12
12
 
@@ -19,13 +19,14 @@ Draw a lightweight RFC release row on an existing story map. An RFC is a plannin
19
19
  ## Workflow
20
20
 
21
21
  1. Require every problem trace to resolve under `docs/problems/`. If a trace is missing, stop and direct the caller to `/wr-itil:capture-problem`; never infer or create a problem silently.
22
- 2. Reuse the existing delivery-planning vehicle. Prefer the supplied `--story-map`; otherwise select an approved story map whose journey contains the fix. Never create a duplicate vehicle.
23
- 3. If no existing map, activity, job, or ratified decision can carry the proposed work, brief the missing substance and use `AskUserQuestion`. In unattended work, queue the question and continue with other actionable work. Do not create a row until the direction is supplied.
24
- 4. Allocate the RFC identity mechanically with `wr-itil-next-rfc-id`; never scan one directory or reuse a retired identity.
25
- 5. Reuse the ordered stories supplied by `--stories`, or capture the smallest delivery stories needed for the fix. Every story must name the driving problem trace.
26
- 6. Run `wr-itil-story-map add-band` to add one release row and `wr-itil-story-map add-card` for each story. The row must include the RFC identity, description, problem trace, and ordered story identifiers.
27
- 7. Render the story map, update the driving problem's RFC references, and run the relevant reconciliation checks.
28
- 8. Commit the map, stories, problem references, and regenerated render together in one focused commit.
22
+ 2. Reuse an existing delivery-planning vehicle when one covers the journey. Prefer the supplied `--story-map`; otherwise select an approved matching map. Never create a duplicate vehicle.
23
+ 3. If no story map exists for the journey, invoke `/wr-itil:capture-story-map` without asking permission, then complete the unconfirmed proposal: initial backbone activities, the release row, its cards, and the corresponding story files. The problem, ratified job, persona, and ratified decisions supply the derivation context. Do not call `AskUserQuestion` to authorize this authoring step.
24
+ 4. If the fix instead needs a new decision, a new job, or a substantive change to an already-ratified map, preserve that existing human gate: brief and ask interactively, or queue one question unattended. Do not invent that missing substance.
25
+ 5. Allocate the RFC identity mechanically with `wr-itil-next-rfc-id`; never scan one directory or reuse a retired identity.
26
+ 6. Reuse the ordered stories supplied by `--stories`, or capture the smallest delivery stories needed for the fix. Every story must name the driving problem trace.
27
+ 7. Run `wr-itil-story-map add-band` to add one release row and `wr-itil-story-map add-card` for each story. The row must include the RFC identity, description, problem trace, and ordered story identifiers.
28
+ 8. Render the story map, update the driving problem's RFC references, and run the relevant reconciliation checks.
29
+ 9. Commit the map, stories, problem references, and regenerated render together in one focused commit. Present the completed new map for ratification; in unattended work queue exactly that ratification. Source changes and story implementation remain blocked until the map is ratified.
29
30
 
30
31
  ## Prohibitions
31
32
 
@@ -45,7 +45,7 @@ Positional grammar mirrors `/wr-itil:capture-story` shape (footnote per the "Pro
45
45
  | STORY-MAP ID allocation | Mechanical: `max(local, origin, history) + 1` enumerating `docs/story-maps/*/STORY-MAP-*.html` (the "AFK orchestrator preflight: get the repo into a clean state before starting" architecture rule inline collision-guard) | silent-mechanical |
46
46
  | Persona journey derivation | Mechanical: read the persona + JTBD and derive the ordered steps they walk before authoring | silent-mechanical |
47
47
  | Title kebab-slug | Mechanical: short outcome phrase naming the derived journey, then kebab-case | silent-mechanical |
48
- | Title prose refinement | Optional taste AskUserQuestion; silent-default to derived form | taste |
48
+ | Title prose refinement | Mechanical: use the journey-derived title without a permission or taste prompt | silent-mechanical |
49
49
  | HTML file write | Mechanical: schema per the "Problem-RFC-Story framework with mandatory problem-trace and unified problem ontology" architecture rule § Phase 2 encoding amendment 2026-05-12 lines 381-435 | silent-mechanical |
50
50
  | Reverse-trace `## Story Maps` refresh | Mechanical: inline on driving problem + JTBD files via Slice 2a/2b helpers | silent-mechanical |
51
51
  | README refresh | Mechanical: deferred to `/wr-itil:manage-story-map review` or `wr-itil-reconcile-story-maps` | silent-mechanical |
@@ -109,9 +109,9 @@ history_max=$(git log --all --name-only --format= -- docs/story-maps/ 2>/dev/nul
109
109
  next=$(printf '%03d' $(( 10#$(printf '%s\n' "${local_max:-0}" "${origin_max:-0}" "${history_max:-0}" | sort -n | tail -1) + 1 )))
110
110
  ```
111
111
 
112
- ### 4. Optional taste prompt for the derived journey title
112
+ ### 4. Use the derived journey title
113
113
 
114
- Same shape as capture-story Step 4 — offer the journey-derived title, not the change description, and silent-default when unavailable.
114
+ Use the journey-derived title without `AskUserQuestion` or a permission prompt. Ratification reviews the completed map; creation itself is mechanical under the "New story maps are authored before ratification" architecture rule.
115
115
 
116
116
  ### 5. Write the story-map JSON, then render it
117
117
 
@@ -209,7 +209,9 @@ Hand-editing the island still works — the renderer reads whatever is there —
209
209
  - Presentation is not yours to set. There is no CSS in the JSON and no inline `style` anywhere; the template is the only styling source.
210
210
  - Escape a literal `<` in any string as `\\u003c`. A raw `</script>` inside the island terminates the block early — in the renderer and in a browser — and the renderer will refuse the file rather than emit a truncated map.
211
211
 
212
- **Born unconfirmed (the "Story maps and stories carry a drift-invalidated human-oversight marker" architecture rule).** Do NOT author `humanOversight` at all: the renderer treats an absent field as `unconfirmed`, so writing it is writing the default, and the field exists so that `wr-itil-mark-story-oversight-confirmed` can set `confirmed` — which an agent must never hand-write (the "iter subprocesses set `human-oversight: confirmed` marker on ADRs / personas / JTBDs without an actual user-confirmation event" problem). The `<meta name="human-oversight">` tag is a projection the renderer regenerates from the island; never author it directly (the "Story maps render from JSON through a canonical template" architecture rule). The map is NOT ratified until a human confirms it via `/wr-itil:manage-story-map <NNN> ratify`, which writes `confirmed` + an `oversight-hash` fingerprint through `wr-itil-mark-story-oversight-confirmed`. Until then `wr-itil-detect-unratified-stories-maps` surfaces it and an RFC may not reference its stories (`wr-itil-check-rfc-stories-ratified`).
212
+ **Born unconfirmed (the "Story maps and stories carry a drift-invalidated human-oversight marker" architecture rule).** Do NOT author `humanOversight` at all: the renderer treats an absent field as `unconfirmed`, so writing it is writing the default, and the field exists so that `wr-itil-mark-story-oversight-confirmed` can set `confirmed` — which an agent must never hand-write (the "iter subprocesses set `human-oversight: confirmed` marker on ADRs / personas / JTBDs without an actual user-confirmation event" problem). The `<meta name="human-oversight">` tag is a projection the renderer regenerates from the island; never author it directly (the "Story maps render from JSON through a canonical template" architecture rule). The map is NOT ratified until a human confirms it via `/wr-itil:manage-story-map <NNN> ratify`, which writes `confirmed` + an `oversight-hash` fingerprint through `wr-itil-mark-story-oversight-confirmed`. Until then `wr-itil-detect-unratified-stories-maps` surfaces it and `wr-itil-check-rfc-stories-ratified` blocks dependent implementation; the "New story maps are authored before ratification" architecture rule still permits the proposal's initial row, cards, and story files to be authored for review.
213
+
214
+ **Author before ratifying (the "New story maps are authored before ratification" architecture rule).** Create the initial map without `AskUserQuestion` or permission. A fix workflow may complete the proposal with its initial activities, release row, cards, and story files while the map is unconfirmed. Present that completed proposal for ratification afterward. Source changes and story implementation remain blocked until ratification; only the ratification flow writes confirmation.
213
215
 
214
216
  **What re-opens ratification, and what does not (the "A release row is the RFC, and the map is the approval surface" architecture rule).** A later edit to the map's SUBSTANCE — the map's own substance as the "Story maps and stories carry a drift-invalidated human-oversight marker" architecture rule defines it — its journey, its identity, and what it traces to; `oversight_map_substance_keys()` is the field list — drifts the fingerprint and silently re-opens ratification. Release rows and the cards in them sit OUTSIDE the basis, so drawing a row or adding a story to one changes nothing. Presentation is outside it too: restyling the shared template cannot revoke an approval. Do NOT hand-write `confirmed` — born-unconfirmed is the load-bearing default.
215
217
 
@@ -196,7 +196,7 @@ wr-itil-check-fix-rfc-trace <problem-file>
196
196
  - **Exit 0, empty stdout** (something already proposes a fix for this problem — a release row, or a legacy document whose `problems:` array names it): proceed to the traversal below.
197
197
  - **Exit 3** (the predicate refuses to answer, and says which of two reasons on stdout):
198
198
  - **A map was edited without being re-rendered.** Mechanical, and nobody is asked about it: re-render the maps the directive names with `wr-itil-render-story-map <map.html>`, then run the predicate again. Escalate only if a clean re-render still refuses.
199
- - **The repository holds no story maps at all.** Drawing the first map for a journey decides what that journey *is*, so it needs a person and must not be created automatically. Record **one** item — draw a story map covering this work — and carry on to the next problem. Interactively that is an `AskUserQuestion`; under the AFK orchestrator it is a single `outstanding_questions` entry. Do not stop the loop.
199
+ - **The repository holds no story maps at all.** Author the complete map proposal now through `/wr-itil:capture-story-map` and `/wr-itil:capture-rfc`: derive the journey and initial activities, then add the identified release row, its cards, and their story files. Do not call `AskUserQuestion` or ask permission before authoring. Leave the map unconfirmed. Interactively, present the completed proposal for ratification; under the AFK orchestrator, queue exactly one `outstanding_questions` entry to ratify that completed proposal. Source changes and story implementation remain blocked until ratification, but independent work continues.
200
200
  - **Exit 0, non-empty stdout** (directive `no-rfc-trace: P<NNN> …`): nothing proposes a fix yet. The predicate has confirmed only that *no row and no document names this PID* — it has NOT decided that no fix vehicle exists. Distinguish **two sub-cases** before acting (the "manage-problem I13 propose-fix gate auto-creates a new RFC instead of wiring an existing fix-vehicle's trace edge" problem — the auto-draw below is intended ONLY when no fix vehicle exists, NOT when an existing vehicle merely lacks the trace edge — architect-confirmed):
201
201
  - **(a) Existing-vehicle-untraced — a vehicle is already this ticket's fix 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 vehicle's remaining tasks, so that vehicle's trace 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 trace. If a genuine existing fix vehicle is found:
202
202
  - **If it is a release row**, add a story card to that row for this ticket's fix and make the card's story file name `P<NNN>` in its own `problems:` list. That card IS the trace edge; the link from a row to a problem is read through its cards, so there is nothing else to wire.
@@ -216,11 +216,12 @@ wr-itil-check-fix-rfc-trace <problem-file>
216
216
  The card's story is captured through `/wr-itil:capture-story` as normal, and **its frontmatter `problems:` list must name `P<NNN>`** — the link from a row to a problem is read through its cards, so a row without that card will still read as untraced and this gate will loop. A row carrying an identity with no card is a defect on the same footing as an untraced one.
217
217
  4. Re-run the predicate (now empty) and proceed. Structured-log the draw event to the iter summary `notes`.
218
218
 
219
- **Queue for a person instead — minting nothing — in either of these cases.**
220
- - **The draw would change what the map's approval covers.** The keys that decide a map's ratification are enumerated in exactly one place, `oversight_map_substance_keys()` in `lib/story-oversight.sh`; adding a release row and a card touches none of them, which is precisely why the row inherits approval. If drawing this row would instead need a **new map**, a **new activity column**, or a **new job on the map's traces** — a map that covers the journey but does not trace the job this fix's story serves — then it changes substance a person approved, and doing it silently would void the very approval it was relying on. Derive this from that one function rather than restating its members here, so an amendment to the tuple cannot leave this gate behind.
219
+ **Handle missing planning substance by its actual boundary.**
220
+ - **No suitable map exists.** Author the complete unconfirmed map proposal without asking permission: derive its journey and initial activities, then add the identified release row, cards, and story files. Present the completed proposal for ratification interactively, or queue exactly that ratification under the AFK orchestrator. Dependent implementation stays blocked until ratification; independent work continues.
221
+ - **An existing ratified map would need a new activity column or a new job on its traces.** That changes what its approval covers. The authoritative keys live in `oversight_map_substance_keys()` in `lib/story-oversight.sh`; queue that substantive refinement instead of silently editing the approved map.
221
222
  - **The fix approach is a choice no existing decision record covers.** Recording a new decision is a person's call, not a byproduct of working a ticket.
222
223
 
223
- Interactively, surface the queued item via `AskUserQuestion`. Under the AFK orchestrator, queue it at `outstanding_questions` and move to the next problem — never ask mid-loop.
224
+ Interactively, use `AskUserQuestion` only for the existing-map refinement, uncovered decision, or completed-map ratification. Under the AFK orchestrator, queue the same single item at `outstanding_questions` and move to the next problem — never ask mid-loop.
224
225
 
225
226
  The predicate is the load-bearing detection half (committed shell + behavioural bats per the "Behavioural-tests-default for skill testing" architecture rule: `packages/itil/scripts/test/check-fix-rfc-trace.bats`), and it reads BOTH tiers — a release row's cards and a legacy document's `problems:` array — so repointing it cannot hard-stop work that used to proceed. 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.
226
227
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: wr-itil:manage-story-map
3
3
  description: "Heavyweight story-map intake + lifecycle management following the \"Problem-RFC-Story framework with mandatory problem-trace and unified problem ontology\" architecture rule Phase 2. Authors backbone × ribs × slices structure on draft maps, transitions through draft → accepted → in-progress → completed → archived, re-validates I3 + I4 invariants at every transition, and refreshes docs/story-maps/README.md per the \"Problem 062: `manage-problem` does not refresh `docs/problems/README.md` on single-ticket transitions; fast-path cache goes stale silently\" problem / the \"Problem 094: `/wr-itil:manage-problem` does not refresh `docs/problems/README.md` on ticket creation\" problem contract pattern. Companion to /wr-itil:capture-story-map (lightweight aside surface)."
4
- allowed-tools: Read, Write, Edit, Bash, Grep, Glob
4
+ allowed-tools: Read, Write, Edit, Bash, Grep, Glob, AskUserQuestion
5
5
  ---
6
6
 
7
7
  # Manage Story Map Skill
@@ -49,6 +49,7 @@ No WSJF token in any grammar form (I5 invariant).
49
49
  | Decision | Resolution | Authority class |
50
50
  |----------|-----------|-----------------|
51
51
  | Story-map ID resolution | Mechanical: regex match `^STORY-MAP-[0-9]{3}$` against `docs/story-maps/*/STORY-MAP-<NNN>-*.html` | silent-mechanical |
52
+ | Initial map proposal authoring | Mechanical: author the unconfirmed map, initial activities, row, cards, and story files without permission | silent-mechanical |
52
53
  | Lifecycle transition validation | Mechanical state machine | silent-mechanical |
53
54
  | Backbone/ribs/slices authoring | AskUserQuestion (taste) at accepted; agent applies user input as HTML edits | taste |
54
55
  | `<meta>` block updates | Mechanical: update status `<meta>` on transitions; preserve all other meta | silent-mechanical |
@@ -82,7 +83,7 @@ Parse `<meta>` block (problems, rfcs, jtbd, status, reported, decision-makers)
82
83
 
83
84
  Display current map state. Surface gaps: missing backbone ribs, slices with unresolved `data-story-id` references, mismatched `<meta name="status">` vs filename `<state>` subdir.
84
85
 
85
- Before asking about backbone authoring direction, apply `/wr-itil:capture-story-map`'s journey-derivation and title/backbone shape checks. Present that derived persona journey for taste-class refinement; use silent-mechanical resolution for housekeeping (status normalisation).
86
+ For a newly captured, unconfirmed map, apply `/wr-itil:capture-story-map`'s journey-derivation and title/backbone shape checks and author the initial complete proposal without `AskUserQuestion` or permission. Present the result only at the ratification flow below. For later substantive refinement of an existing map, retain the taste-class direction prompt; use silent-mechanical resolution for housekeeping such as status normalisation.
86
87
 
87
88
  ### 7. Status transitions
88
89
 
@@ -118,6 +119,8 @@ Per architect amend finding 2 on Slice 7: story-map HTML files do NOT carry an a
118
119
 
119
120
  `ratify` is **orthogonal to the status lifecycle** — a map can be ratified at any status. It confirms human oversight of **the map**, and under the "A release row is the RFC, and the map is the approval surface" architecture rule that approves every ordinary story on it, including stories added later; stories are never ratified individually. Ratification is **drift-invalidated** (the "Gate Marker Lifecycle: TTL + Drift, Not Stop-Hook Reset" architecture rule lineage, NOT the ": Human-oversight marker + `/wr-architect:review-decisions` drain for recorded decisions" architecture rule write-once), but only a **substance** edit re-opens it: the map's own substance as the "Story maps and stories carry a drift-invalidated human-oversight marker" architecture rule defines it — its journey, its identity, what it traces to, and any manifest-bound historical projection. `oversight_map_substance_keys()` is the authoritative field list; this page deliberately does not restate it. Ordinary release rows and cards, story-body edits and template restyling sit outside the fingerprint basis and change nothing. Historical projections are the narrow exception and may be added only through `/wr-itil:migrate-story-map` under exact confirmed adopter authority. This is the ": Ratify the story map and its stories after any change" delivery story surface.
120
121
 
122
+ Under the "New story maps are authored before ratification" architecture rule, creation asks nothing: author the complete unconfirmed proposal first, including its initial activities, release row, cards, and story files. This `ratify` flow is the only human approval in the new-map workflow. Source changes and story implementation depending on the map are blocked until ratification completes; proposal authoring itself is allowed.
123
+
121
124
  **Born-confirmed discipline (the "iter subprocesses set `human-oversight: confirmed` marker on ADRs / personas / JTBDs without an actual user-confirmation event" problem).** Before any marker write, `export CLAUDE_SESSION_ID` from the transcript path — the marker shim silently no-ops on an empty SID. Every `confirmed` marker MUST be backed by a same-turn human confirm event; never write `confirmed` without the `AskUserQuestion` below (a hollow marker is the "iter subprocesses set `human-oversight: confirmed` marker on ADRs / personas / JTBDs without an actual user-confirmation event" problem bug).
122
125
 
123
126
  **Ratify the map; its stories follow (the ": Ratify the story map and its stories after any change" delivery story UX, amended by the "A release row is the RFC, and the map is the approval surface" architecture rule):**
@@ -728,7 +728,8 @@ rm -f "$ITER_JSON" "$ITERATION_PROMPT_FILE"
728
728
 
729
729
  1. **Context (the unattended declaration — load-bearing carrier per the "Per-ticket goal anchors each AFK iteration" architecture rule)**: this is one iteration of the AFK work-problems loop. <!-- UNATTENDED-DECLARATION-SOURCE --> **The user is AFK and this run is unattended.** The orchestrator selected `P<NNN> (<title>)` as the highest-WSJF actionable ticket. This sentence is the **discriminator** the singular skill keys its pinned short-circuit on (`/wr-itil:work-problem` Step 1): prose cannot observe a TTY and a `claude -p` subprocess offers nothing to sniff, so the unattended state is **declared by the dispatcher**, never detected by the skill. Do not drop or reword the declaration — a rule keyed on something the skill cannot observe silently collapses to always or never.
730
730
  2. **Task**: run `/wr-itil:work-problem P<NNN>` — the singular skill, pinned to the ticket the orchestrator already selected. It is the loop's per-iteration execution unit (both SKILLs have long documented this; the "Per-ticket goal anchors each AFK iteration" architecture rule makes the dispatch match). It delegates the actual work to `/wr-itil:manage-problem <NNN>`, so the manage-problem workflow still runs verbatim — architect / jtbd / style-guide / voice-tone gate reviews and the commit gate (manage-problem Step 11) all apply. Because this subprocess has the Agent tool in its own surface, the normal review-via-subagent paths work — no inline-verdict fallback needed. Because the dispatch is pinned AND declares the run unattended, the singular skill skips its ranking-freshness check (it must not delegate a README refresh, must not prompt, must not commit a ranking rewrite inside this per-ticket unit of work).
731
- 3. **Constraints**: commit the completed work per the "Governance Skills Commit Their Own Completed Work" architecture rule. 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 — the "Governance skill invocation patterns — foreground + background with deferred-question resumption" architecture rule), **EXCEPT** (a) **retro-surfaced observations of recurring class-of-behaviour** — those route to `/wr-itil:capture-problem` per the **the "Iter retros queue their own observations as `outstanding-questions.jsonl` entries for user-direction triage instead of auto-ticketing — same trust-boundary as `/wr-retrospective:run-retro` Step 4a" problem 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 — the "Iter retros queue their own observations as `outstanding-questions.jsonl` entries for user-direction triage instead of auto-ticketing — same trust-boundary as `/wr-retrospective:run-retro` Step 4a" problem); and (b) **the I13 fix-time row draw** — when the propose-fix gate inside the delegated `/wr-itil:manage-problem` traversal detects a Known Error nothing yet proposes a fix for (`wr-itil-check-fix-rfc-trace` emits a `no-rfc-trace:` directive), the iter **draws a release row on a story map that already covers the journey**, gives it at least one story card, and makes that card's story name the problem in its own `problems:` list — then proceeds. **A fix proposal is a release row; it is never a new document under `docs/rfcs/`.** Take the identity from the directive, which comes from `wr-itil-next-rfc-id` — the single rule that sees rows, documents and git history at once, and the only one that will not re-issue an identity a row already holds. **UNLESS** an existing vehicle cited in the ticket is already this ticket's fix and merely lacks the trace edge, in which case the iter **wires** that edge — a card on the existing row, or the `problems:` array of a legacy document — rather than drawing a duplicate that fragments the fix across two vehicles (the "manage-problem I13 propose-fix gate auto-creates a new RFC instead of wiring an existing fix-vehicle's trace edge" problem; existing-vehicle-untraced sub-case; vehicle-vs-merely-related is a judgement read of citation context, structured-logged as `I13: wired P<NNN> trace edge into existing fix vehicle <ID>`; the load-bearing branch prose lives in the delegated `/wr-itil:manage-problem` I13 gate). This is NOT an aside-capture distraction: the row is the **mandatory vehicle for THIS iter’s own fix** (the "Every fix goes through an RFC" architecture rule), not a tangential observation — it is in-scope working of the current ticket, framework-mediated (NOT cat-1 direction-setting → NO `AskUserQuestion`, the "Agents over-ask in interactive sessions — conflating mechanical-stages with user-interactive-stages of multi-stage skill contracts (inverse-)" problem), and drawing a row onto a map a person has already approved inherits that approval rather than needing a fresh one. **Two things the iter must NOT do silently**: draw a row whose creation would change what the map’s approval covers — a new map, a new activity column, or a new job on the map’s traces, judged from `oversight_map_substance_keys()` in `lib/story-oversight.sh`, the one place those keys are enumerated — or pick a fix approach no existing decision record covers. Either of those queues ONE entry at `outstanding_questions` and the iter moves to the next problem; the loop is never stopped for it. The predicate can also refuse outright (exit 3), and the two refusals are handled differently: a map edited without being re-rendered is **mechanical** — re-render it with `wr-itil-render-story-map` and ask again, asking nobody — while a repository with no story maps at all queues ONE entry (draw a story map covering this work) and the iter carries on to the next problem rather than halting. Structured-log the draw event to the iter summary (`notes`) per the ": Progress the Backlog While I'm Away" user outcome audit-trail. Do NOT use `ScheduleWakeup` under any circumstance (the "Problem 083: work-problems Step 5 iteration-worker prompt does not forbid ScheduleWakeup / time-deferring primitives — subagent can abandon synchronous-completion contract" problem — iteration workers must not self-reschedule). **NEVER call `AskUserQuestion` mid-loop in AFK** (the "Decision-delegation contract — agents over-apply Rule 1's interactive default to framework-resolved decisions; codify the framework-resolution boundary + AFK loop's batched-questions-as-deliverable + lazy-AskUserQuestion measurement" problem / the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule): 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 (the ": Confirm a decision's substance before building dependent work on it" architecture rule (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 "Agent implements dependent work on genuine new decisions before human-confirming their SUBSTANCE — surfaces only meta-questions" problem 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 (the ": Confirm a decision's substance before building dependent work on it" architecture rule 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 the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6 + the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule's framework-resolution boundary. **Treat the user as transient** (the "`/wr-itil:work-problems` orchestrator defaults to subprocess dispatch even when the user is observably interactive — loses real-time presence advantage" problem): 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** (the "AFK iteration subprocess `bash until`-loop polls bats-output file with bats-console regex against TAP-format output — deadlocks indefinitely, manual SIGTERM required, JSON metadata lost" problem — 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 "AFK iteration subprocess `bash until`-loop polls bats-output file with bats-console regex against TAP-format output — deadlocks indefinitely, manual SIGTERM required, JSON metadata lost" problem/the "SIGTERM-clean-flush guarantee is conditional on subprocess having emitted ITERATION_SUMMARY before going idle — needs SKILL.md caveat + behavioural-test second-source for stuck-before-emit subclass" problem 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** (the "bash until-loop with `pgrep -f 'bats --recursive'` self-references the polling loop's own command line — new variant of stuck-before-emit deadlock; SKILL.md prompt warning insufficient" problem — self-referential pgrep deadlock; sibling variant of the "AFK iteration subprocess `bash until`-loop polls bats-output file with bats-console regex against TAP-format output — deadlocks indefinitely, manual SIGTERM required, JSON metadata lost" problem). `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 the "bash until-loop with `pgrep -f 'bats --recursive'` self-references the polling loop's own command line — new variant of stuck-before-emit deadlock; SKILL.md prompt warning insufficient" problem 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 the "AFK iteration subprocess `bash until`-loop polls bats-output file with bats-console regex against TAP-format output — deadlocks indefinitely, manual SIGTERM required, JSON metadata lost" problem: 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. **Do NOT leave a backgrounded task unreaped at turn-end** (`run_in_background: true` on an Agent or Bash tool call, or a `&`-detached shell job, whose completion you intend to observe in a *later* turn) inside iter dispatch contexts (the "Iter subprocess ends its turn waiting on a backgrounded task and never resumes — `claude -p` has no auto-resume; commit-bearing work is lost" problem — turn-end-mid-background work-loss; sibling-class to the "Problem 083: work-problems Step 5 iteration-worker prompt does not forbid ScheduleWakeup / time-deferring primitives — subagent can abandon synchronous-completion contract" problem / the "AFK iteration subprocess `bash until`-loop polls bats-output file with bats-console regex against TAP-format output — deadlocks indefinitely, manual SIGTERM required, JSON metadata lost" problem / the "bash until-loop with `pgrep -f 'bats --recursive'` self-references the polling loop's own command line — new variant of stuck-before-emit deadlock; SKILL.md prompt warning insufficient" problem). The iter subprocess is dispatched via `claude -p`, a single-shot CLI invocation with NO auto-resume affordance: its turn boundary IS its process boundary. A background task that outlives the turn never resumes — the iter exits at turn-end with the task incomplete and its own work staged but uncommitted (witnessed: iter 11 of a prior loop — $8.02 / 17 min / 8 staged files / 11 GREEN bats / ZERO commits; recovery required orchestrator main-turn salvage). **The prohibition is on the cross-turn / turn-end-survivor shape, NOT on backgrounding per se:** the "AFK iteration subprocess `bash until`-loop polls bats-output file with bats-console regex against TAP-format output — deadlocks indefinitely, manual SIGTERM required, JSON metadata lost" problem/the "bash until-loop with `pgrep -f 'bats --recursive'` self-references the polling loop's own command line — new variant of stuck-before-emit deadlock; SKILL.md prompt warning insufficient" problem-sanctioned idiom of launching `run_in_background=true` + `BashOutput`-poll-then-`wait $bg_pid` (or plain `wait $bg_pid` on a `&` job) **within the same turn** is fine — it reaps the task before turn-end. Use foreground-synchronous invocation instead: the Agent tool WITHOUT `run_in_background: true` (the result returns in-turn, so the commit step is reached), or intra-turn background that you `wait` on before the turn closes. The distinction from the "AFK iteration subprocess `bash until`-loop polls bats-output file with bats-console regex against TAP-format output — deadlocks indefinitely, manual SIGTERM required, JSON metadata lost" problem/the "bash until-loop with `pgrep -f 'bats --recursive'` self-references the polling loop's own command line — new variant of stuck-before-emit deadlock; SKILL.md prompt warning insufficient" problem polling antipatterns: those forbid *how* you wait (regex / pgrep poll loops); this forbids *deferring a task's completion past the turn boundary*, where `claude -p` has no notification re-entry to bring you back. The interactive Claude Code session masks this hazard (notification-driven re-entry); the AFK iter subprocess does not. **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 the "Governance Skills Commit Their Own Completed Work" architecture rule-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 the ": Progress the Backlog While I'm Away" user outcome's audit-trail expectation + the ": Keep Plugins Current Across Projects" user outcome's "Keep Plugins Current" closure dependency). Hook `packages/itil/hooks/itil-changeset-discipline.sh` (the "AFK iter `packages/<plugin>/` commits without changesets — orchestrator-main-turn back-fill is fragile recovery, hook-level enforcement preferable" problem) 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 the "Briefing Tier 3 rotation repeat-deferral — 13 of 14 topic files over budget with 2 in MUST_SPLIT (≥2× ceiling) branch" problem — see [Related](#related) for `**Origin**: inbound-reported (bbstats#195)` per the "Inbound-reported problems rank ahead of internally-discovered problems via a sort tier" architecture rule. **`@jtbd the ": Progress the Backlog While I'm Away" user outcome`** (load-bearing) **`@jtbd the ": Keep Plugins Current Across Projects" user outcome`** (closure-dependent).
731
+ 3. **Constraints**: commit the completed work per the "Governance Skills Commit Their Own Completed Work" architecture rule. 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 — the "Governance skill invocation patterns — foreground + background with deferred-question resumption" architecture rule), **EXCEPT** (a) **retro-surfaced observations of recurring class-of-behaviour** — those route to `/wr-itil:capture-problem` per the **the "Iter retros queue their own observations as `outstanding-questions.jsonl` entries for user-direction triage instead of auto-ticketing — same trust-boundary as `/wr-retrospective:run-retro` Step 4a" problem 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 — the "Iter retros queue their own observations as `outstanding-questions.jsonl` entries for user-direction triage instead of auto-ticketing — same trust-boundary as `/wr-retrospective:run-retro` Step 4a" problem); and (b) **the I13 fix-time row draw** — when the propose-fix gate inside the delegated `/wr-itil:manage-problem` traversal detects a Known Error nothing yet proposes a fix for (`wr-itil-check-fix-rfc-trace` emits a `no-rfc-trace:` directive), the iter **draws a release row on a story map that already covers the journey**, gives it at least one story card, and makes that card's story name the problem in its own `problems:` list — then proceeds. **A fix proposal is a release row; it is never a new document under `docs/rfcs/`.** Take the identity from the directive, which comes from `wr-itil-next-rfc-id` — the single rule that sees rows, documents and git history at once, and the only one that will not re-issue an identity a row already holds. **UNLESS** an existing vehicle cited in the ticket is already this ticket's fix and merely lacks the trace edge, in which case the iter **wires** that edge — a card on the existing row, or the `problems:` array of a legacy document — rather than drawing a duplicate that fragments the fix across two vehicles (the "manage-problem I13 propose-fix gate auto-creates a new RFC instead of wiring an existing fix-vehicle's trace edge" problem; existing-vehicle-untraced sub-case; vehicle-vs-merely-related is a judgement read of citation context, structured-logged as `I13: wired P<NNN> trace edge into existing fix vehicle <ID>`; the load-bearing branch prose lives in the delegated `/wr-itil:manage-problem` I13 gate). This is NOT an aside-capture distraction: the row is the **mandatory vehicle for THIS iter’s own fix** (the "Every fix goes through an RFC" architecture rule), not a tangential observation — it is in-scope working of the current ticket, framework-mediated (NOT cat-1 direction-setting → NO `AskUserQuestion`, the "Agents over-ask in interactive sessions — conflating mechanical-stages with user-interactive-stages of multi-stage skill contracts (inverse-)" problem), and drawing a row onto a map a person has already approved inherits that approval rather than needing a fresh one. **Two things the iter must NOT do silently**: change an existing map in a way that would alter what its approval covers — a new activity column or a new job on the map’s traces, judged from `oversight_map_substance_keys()` in `lib/story-oversight.sh`, the one place those keys are enumerated — or pick a fix approach no existing decision record covers. Either of those queues ONE entry at `outstanding_questions` and the iter moves to the next problem; the loop is never stopped for it. The predicate can also refuse outright (exit 3), and the two refusals are handled differently: a map edited without being re-rendered is **mechanical** — re-render it with `wr-itil-render-story-map` and ask again, asking nobody — while a repository with no story maps at all triggers complete unconfirmed proposal authoring through `/wr-itil:capture-story-map` and `/wr-itil:capture-rfc`, without `AskUserQuestion`. The iter creates the initial activities, identified release row, cards, and story files; queues exactly one `outstanding_questions` item to ratify the completed map; blocks source and story implementation until ratification; and continues independent work. Structured-log the draw event to the iter summary (`notes`) per the ": Progress the Backlog While I'm Away" user outcome audit-trail. Do NOT use `ScheduleWakeup` under any circumstance (the "Problem 083: work-problems Step 5 iteration-worker prompt does not forbid ScheduleWakeup / time-deferring primitives — subagent can abandon synchronous-completion contract" problem — iteration workers must not self-reschedule). **NEVER call `AskUserQuestion` mid-loop in AFK** (the "Decision-delegation contract — agents over-apply Rule 1's interactive default to framework-resolved decisions; codify the framework-resolution boundary + AFK loop's batched-questions-as-deliverable + lazy-AskUserQuestion measurement" problem / the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule): 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 (the ": Confirm a decision's substance before building dependent work on it" architecture rule (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 "Agent implements dependent work on genuine new decisions before human-confirming their SUBSTANCE — surfaces only meta-questions" problem 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 (the ": Confirm a decision's substance before building dependent work on it" architecture rule 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 the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6 + the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule's framework-resolution boundary. **Treat the user as transient** (the "`/wr-itil:work-problems` orchestrator defaults to subprocess dispatch even when the user is observably interactive — loses real-time presence advantage" problem): 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** (the "AFK iteration subprocess `bash until`-loop polls bats-output file with bats-console regex against TAP-format output — deadlocks indefinitely, manual SIGTERM required, JSON metadata lost" problem — 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 "AFK iteration subprocess `bash until`-loop polls bats-output file with bats-console regex against TAP-format output — deadlocks indefinitely, manual SIGTERM required, JSON metadata lost" problem/the "SIGTERM-clean-flush guarantee is conditional on subprocess having emitted ITERATION_SUMMARY before going idle — needs SKILL.md caveat + behavioural-test second-source for stuck-before-emit subclass" problem 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** (the "bash until-loop with `pgrep -f 'bats --recursive'` self-references the polling loop's own command line — new variant of stuck-before-emit deadlock; SKILL.md prompt warning insufficient" problem — self-referential pgrep deadlock; sibling variant of the "AFK iteration subprocess `bash until`-loop polls bats-output file with bats-console regex against TAP-format output — deadlocks indefinitely, manual SIGTERM required, JSON metadata lost" problem). `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 the "bash until-loop with `pgrep -f 'bats --recursive'` self-references the polling loop's own command line — new variant of stuck-before-emit deadlock; SKILL.md prompt warning insufficient" problem 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 the "AFK iteration subprocess `bash until`-loop polls bats-output file with bats-console regex against TAP-format output — deadlocks indefinitely, manual SIGTERM required, JSON metadata lost" problem: 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. **Do NOT leave a backgrounded task unreaped at turn-end** (`run_in_background: true` on an Agent or Bash tool call, or a `&`-detached shell job, whose completion you intend to observe in a *later* turn) inside iter dispatch contexts (the "Iter subprocess ends its turn waiting on a backgrounded task and never resumes — `claude -p` has no auto-resume; commit-bearing work is lost" problem — turn-end-mid-background work-loss; sibling-class to the "Problem 083: work-problems Step 5 iteration-worker prompt does not forbid ScheduleWakeup / time-deferring primitives — subagent can abandon synchronous-completion contract" problem / the "AFK iteration subprocess `bash until`-loop polls bats-output file with bats-console regex against TAP-format output — deadlocks indefinitely, manual SIGTERM required, JSON metadata lost" problem / the "bash until-loop with `pgrep -f 'bats --recursive'` self-references the polling loop's own command line — new variant of stuck-before-emit deadlock; SKILL.md prompt warning insufficient" problem). The iter subprocess is dispatched via `claude -p`, a single-shot CLI invocation with NO auto-resume affordance: its turn boundary IS its process boundary. A background task that outlives the turn never resumes — the iter exits at turn-end with the task incomplete and its own work staged but uncommitted (witnessed: iter 11 of a prior loop — $8.02 / 17 min / 8 staged files / 11 GREEN bats / ZERO commits; recovery required orchestrator main-turn salvage). **The prohibition is on the cross-turn / turn-end-survivor shape, NOT on backgrounding per se:** the "AFK iteration subprocess `bash until`-loop polls bats-output file with bats-console regex against TAP-format output — deadlocks indefinitely, manual SIGTERM required, JSON metadata lost" problem/the "bash until-loop with `pgrep -f 'bats --recursive'` self-references the polling loop's own command line — new variant of stuck-before-emit deadlock; SKILL.md prompt warning insufficient" problem-sanctioned idiom of launching `run_in_background=true` + `BashOutput`-poll-then-`wait $bg_pid` (or plain `wait $bg_pid` on a `&` job) **within the same turn** is fine — it reaps the task before turn-end. Use foreground-synchronous invocation instead: the Agent tool WITHOUT `run_in_background: true` (the result returns in-turn, so the commit step is reached), or intra-turn background that you `wait` on before the turn closes. The distinction from the "AFK iteration subprocess `bash until`-loop polls bats-output file with bats-console regex against TAP-format output — deadlocks indefinitely, manual SIGTERM required, JSON metadata lost" problem/the "bash until-loop with `pgrep -f 'bats --recursive'` self-references the polling loop's own command line — new variant of stuck-before-emit deadlock; SKILL.md prompt warning insufficient" problem polling antipatterns: those forbid *how* you wait (regex / pgrep poll loops); this forbids *deferring a task's completion past the turn boundary*, where `claude -p` has no notification re-entry to bring you back. The interactive Claude Code session masks this hazard (notification-driven re-entry); the AFK iter subprocess does not. **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 the "Governance Skills Commit Their Own Completed Work" architecture rule-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 the ": Progress the Backlog While I'm Away" user outcome's audit-trail expectation + the ": Keep Plugins Current Across Projects" user outcome's "Keep Plugins Current" closure dependency). Hook `packages/itil/hooks/itil-changeset-discipline.sh` (the "AFK iter `packages/<plugin>/` commits without changesets — orchestrator-main-turn back-fill is fragile recovery, hook-level enforcement preferable" problem) 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 the "Briefing Tier 3 rotation repeat-deferral — 13 of 14 topic files over budget with 2 in MUST_SPLIT (≥2× ceiling) branch" problem — see [Related](#related) for `**Origin**: inbound-reported (bbstats#195)` per the "Inbound-reported problems rank ahead of internally-discovered problems via a sort tier" architecture rule. **`@jtbd the ": Progress the Backlog While I'm Away" user outcome`** (load-bearing) **`@jtbd the ": Keep Plugins Current Across Projects" user outcome`** (closure-dependent).
732
+
732
733
  4. **Retro-on-exit (the "Problem 086: AFK iteration subprocess does not run retro before returning — per-iteration lessons learnt are lost when the subprocess exits" problem) + retro-surfaced observation classification (the "Iter retros queue their own observations as `outstanding-questions.jsonl` entries for user-direction triage instead of auto-ticketing — same trust-boundary as `/wr-retrospective:run-retro` Step 4a" problem) + iter-owned BRIEFING commit (the "work-problems iteration boundary leaves run-retro BRIEFING.md edits uncommitted" problem)**: 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 the "Governance Skills Commit Their Own Completed Work" architecture rule 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.
733
734
 
734
735
  **BRIEFING.md commit responsibility — iter owns, run-retro does not (the "work-problems iteration boundary leaves run-retro BRIEFING.md edits uncommitted" problem).** run-retro is explicitly out-of-scope for self-commit per the "Governance Skills Commit Their Own Completed Work" architecture rule'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:
@@ -17,7 +17,7 @@ allowed-tools: Read, Write, Edit, Bash, Grep, Glob, Skill, request_user_input
17
17
 
18
18
  # Capture RFC
19
19
 
20
- Draw a lightweight RFC release row on an existing story map. An RFC is a planning row, not a standalone document.
20
+ Draw a lightweight RFC release row on a story map. An RFC is a planning row, not a standalone document.
21
21
 
22
22
  ## Arguments
23
23
 
@@ -30,13 +30,14 @@ Draw a lightweight RFC release row on an existing story map. An RFC is a plannin
30
30
  ## Workflow
31
31
 
32
32
  1. Require every problem trace to resolve under `docs/problems/`. If a trace is missing, stop and direct the caller to `/wr-itil:capture-problem`; never infer or create a problem silently.
33
- 2. Reuse the existing delivery-planning vehicle. Prefer the supplied `--story-map`; otherwise select an approved story map whose journey contains the fix. Never create a duplicate vehicle.
34
- 3. If no existing map, activity, job, or ratified decision can carry the proposed work, brief the missing substance and use `request_user_input`. In unattended work, queue the question and continue with other actionable work. Do not create a row until the direction is supplied.
35
- 4. Allocate the RFC identity mechanically with `<itil-plugin-root>/bin/wr-itil-next-rfc-id`; never scan one directory or reuse a retired identity.
36
- 5. Reuse the ordered stories supplied by `--stories`, or capture the smallest delivery stories needed for the fix. Every story must name the driving problem trace.
37
- 6. Run `<itil-plugin-root>/bin/wr-itil-story-map add-band` to add one release row and `<itil-plugin-root>/bin/wr-itil-story-map add-card` for each story. The row must include the RFC identity, description, problem trace, and ordered story identifiers.
38
- 7. Render the story map, update the driving problem's RFC references, and run the relevant reconciliation checks.
39
- 8. Commit the map, stories, problem references, and regenerated render together in one focused commit.
33
+ 2. Reuse an existing delivery-planning vehicle when one covers the journey. Prefer the supplied `--story-map`; otherwise select an approved matching map. Never create a duplicate vehicle.
34
+ 3. If no story map exists for the journey, invoke `/wr-itil:capture-story-map` without asking permission, then complete the unconfirmed proposal: initial backbone activities, the release row, its cards, and the corresponding story files. The problem, ratified job, persona, and ratified decisions supply the derivation context. Do not call `request_user_input` to authorize this authoring step.
35
+ 4. If the fix instead needs a new decision, a new job, or a substantive change to an already-ratified map, preserve that existing human gate: brief and ask interactively, or queue one question unattended. Do not invent that missing substance.
36
+ 5. Allocate the RFC identity mechanically with `<itil-plugin-root>/bin/wr-itil-next-rfc-id`; never scan one directory or reuse a retired identity.
37
+ 6. Reuse the ordered stories supplied by `--stories`, or capture the smallest delivery stories needed for the fix. Every story must name the driving problem trace.
38
+ 7. Run `<itil-plugin-root>/bin/wr-itil-story-map add-band` to add one release row and `<itil-plugin-root>/bin/wr-itil-story-map add-card` for each story. The row must include the RFC identity, description, problem trace, and ordered story identifiers.
39
+ 8. Render the story map, update the driving problem's RFC references, and run the relevant reconciliation checks.
40
+ 9. Commit the map, stories, problem references, and regenerated render together in one focused commit. Present the completed new map for ratification; in unattended work queue exactly that ratification. Source changes and story implementation remain blocked until the map is ratified.
40
41
 
41
42
  ## Prohibitions
42
43
 
@@ -56,7 +56,7 @@ Positional grammar mirrors `/wr-itil:capture-story` shape (footnote per the "Pro
56
56
  | STORY-MAP ID allocation | Mechanical: `max(local, origin, history) + 1` enumerating `docs/story-maps/*/STORY-MAP-*.html` (the "AFK orchestrator preflight: get the repo into a clean state before starting" architecture rule inline collision-guard) | silent-mechanical |
57
57
  | Persona journey derivation | Mechanical: read the persona + JTBD and derive the ordered steps they walk before authoring | silent-mechanical |
58
58
  | Title kebab-slug | Mechanical: short outcome phrase naming the derived journey, then kebab-case | silent-mechanical |
59
- | Title prose refinement | Optional taste request_user_input; silent-default to derived form | taste |
59
+ | Title prose refinement | Mechanical: use the journey-derived title without a permission or taste prompt | silent-mechanical |
60
60
  | HTML file write | Mechanical: schema per the "Problem-RFC-Story framework with mandatory problem-trace and unified problem ontology" architecture rule § Phase 2 encoding amendment 2026-05-12 lines 381-435 | silent-mechanical |
61
61
  | Reverse-trace `## Story Maps` refresh | Mechanical: inline on driving problem + JTBD files via Slice 2a/2b helpers | silent-mechanical |
62
62
  | README refresh | Mechanical: deferred to `/wr-itil:manage-story-map review` or `<itil-plugin-root>/bin/wr-itil-reconcile-story-maps` | silent-mechanical |
@@ -120,9 +120,9 @@ history_max=$(git log --all --name-only --format= -- docs/story-maps/ 2>/dev/nul
120
120
  next=$(printf '%03d' $(( 10#$(printf '%s\n' "${local_max:-0}" "${origin_max:-0}" "${history_max:-0}" | sort -n | tail -1) + 1 )))
121
121
  ```
122
122
 
123
- ### 4. Optional taste prompt for the derived journey title
123
+ ### 4. Use the derived journey title
124
124
 
125
- Same shape as capture-story Step 4 — offer the journey-derived title, not the change description, and silent-default when unavailable.
125
+ Use the journey-derived title without `request_user_input` or a permission prompt. Ratification reviews the completed map; creation itself is mechanical under the "New story maps are authored before ratification" architecture rule.
126
126
 
127
127
  ### 5. Write the story-map JSON, then render it
128
128
 
@@ -220,7 +220,9 @@ Hand-editing the island still works — the renderer reads whatever is there —
220
220
  - Presentation is not yours to set. There is no CSS in the JSON and no inline `style` anywhere; the template is the only styling source.
221
221
  - Escape a literal `<` in any string as `\\u003c`. A raw `</script>` inside the island terminates the block early — in the renderer and in a browser — and the renderer will refuse the file rather than emit a truncated map.
222
222
 
223
- **Born unconfirmed (the "Story maps and stories carry a drift-invalidated human-oversight marker" architecture rule).** Do NOT author `humanOversight` at all: the renderer treats an absent field as `unconfirmed`, so writing it is writing the default, and the field exists so that `<itil-plugin-root>/bin/wr-itil-mark-story-oversight-confirmed` can set `confirmed` — which an agent must never hand-write (the "iter subprocesses set `human-oversight: confirmed` marker on ADRs / personas / JTBDs without an actual user-confirmation event" problem). The `<meta name="human-oversight">` tag is a projection the renderer regenerates from the island; never author it directly (the "Story maps render from JSON through a canonical template" architecture rule). The map is NOT ratified until a human confirms it via `/wr-itil:manage-story-map <NNN> ratify`, which writes `confirmed` + an `oversight-hash` fingerprint through `<itil-plugin-root>/bin/wr-itil-mark-story-oversight-confirmed`. Until then `<itil-plugin-root>/bin/wr-itil-detect-unratified-stories-maps` surfaces it and an RFC may not reference its stories (`<itil-plugin-root>/bin/wr-itil-check-rfc-stories-ratified`).
223
+ **Born unconfirmed (the "Story maps and stories carry a drift-invalidated human-oversight marker" architecture rule).** Do NOT author `humanOversight` at all: the renderer treats an absent field as `unconfirmed`, so writing it is writing the default, and the field exists so that `<itil-plugin-root>/bin/wr-itil-mark-story-oversight-confirmed` can set `confirmed` — which an agent must never hand-write (the "iter subprocesses set `human-oversight: confirmed` marker on ADRs / personas / JTBDs without an actual user-confirmation event" problem). The `<meta name="human-oversight">` tag is a projection the renderer regenerates from the island; never author it directly (the "Story maps render from JSON through a canonical template" architecture rule). The map is NOT ratified until a human confirms it via `/wr-itil:manage-story-map <NNN> ratify`, which writes `confirmed` + an `oversight-hash` fingerprint through `<itil-plugin-root>/bin/wr-itil-mark-story-oversight-confirmed`. Until then `<itil-plugin-root>/bin/wr-itil-detect-unratified-stories-maps` surfaces it and `<itil-plugin-root>/bin/wr-itil-check-rfc-stories-ratified` blocks dependent implementation; the "New story maps are authored before ratification" architecture rule still permits the proposal's initial row, cards, and story files to be authored for review.
224
+
225
+ **Author before ratifying (the "New story maps are authored before ratification" architecture rule).** Create the initial map without `request_user_input` or permission. A fix workflow may complete the proposal with its initial activities, release row, cards, and story files while the map is unconfirmed. Present that completed proposal for ratification afterward. Source changes and story implementation remain blocked until ratification; only the ratification flow writes confirmation.
224
226
 
225
227
  **What re-opens ratification, and what does not (the "A release row is the RFC, and the map is the approval surface" architecture rule).** A later edit to the map's SUBSTANCE — the map's own substance as the "Story maps and stories carry a drift-invalidated human-oversight marker" architecture rule defines it — its journey, its identity, and what it traces to; `oversight_map_substance_keys()` is the field list — drifts the fingerprint and silently re-opens ratification. Release rows and the cards in them sit OUTSIDE the basis, so drawing a row or adding a story to one changes nothing. Presentation is outside it too: restyling the shared template cannot revoke an approval. Do NOT hand-write `confirmed` — born-unconfirmed is the load-bearing default.
226
228
 
@@ -207,7 +207,7 @@ Run the load-bearing predicate (the "Plugin-bundled scripts invoked from SKILL.m
207
207
  - **Exit 0, empty stdout** (something already proposes a fix for this problem — a release row, or a legacy document whose `problems:` array names it): proceed to the traversal below.
208
208
  - **Exit 3** (the predicate refuses to answer, and says which of two reasons on stdout):
209
209
  - **A map was edited without being re-rendered.** Mechanical, and nobody is asked about it: re-render the maps the directive names with `<itil-plugin-root>/bin/wr-itil-render-story-map <map.html>`, then run the predicate again. Escalate only if a clean re-render still refuses.
210
- - **The repository holds no story maps at all.** Drawing the first map for a journey decides what that journey *is*, so it needs a person and must not be created automatically. Record **one** item — draw a story map covering this work — and carry on to the next problem. Interactively that is an `request_user_input`; under the AFK orchestrator it is a single `outstanding_questions` entry. Do not stop the loop.
210
+ - **The repository holds no story maps at all.** Author the complete map proposal now through `/wr-itil:capture-story-map` and `/wr-itil:capture-rfc`: derive the journey and initial activities, then add the identified release row, its cards, and their story files. Do not call `request_user_input` or ask permission before authoring. Leave the map unconfirmed. Interactively, present the completed proposal for ratification; under the AFK orchestrator, queue exactly one `outstanding_questions` entry to ratify that completed proposal. Source changes and story implementation remain blocked until ratification, but independent work continues.
211
211
  - **Exit 0, non-empty stdout** (directive `no-rfc-trace: P<NNN> …`): nothing proposes a fix yet. The predicate has confirmed only that *no row and no document names this PID* — it has NOT decided that no fix vehicle exists. Distinguish **two sub-cases** before acting (the "manage-problem I13 propose-fix gate auto-creates a new RFC instead of wiring an existing fix-vehicle's trace edge" problem — the auto-draw below is intended ONLY when no fix vehicle exists, NOT when an existing vehicle merely lacks the trace edge — architect-confirmed):
212
212
  - **(a) Existing-vehicle-untraced — a vehicle is already this ticket's fix 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 vehicle's remaining tasks, so that vehicle's trace 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 trace. If a genuine existing fix vehicle is found:
213
213
  - **If it is a release row**, add a story card to that row for this ticket's fix and make the card's story file name `P<NNN>` in its own `problems:` list. That card IS the trace edge; the link from a row to a problem is read through its cards, so there is nothing else to wire.
@@ -227,11 +227,12 @@ Run the load-bearing predicate (the "Plugin-bundled scripts invoked from SKILL.m
227
227
  The card's story is captured through `/wr-itil:capture-story` as normal, and **its frontmatter `problems:` list must name `P<NNN>`** — the link from a row to a problem is read through its cards, so a row without that card will still read as untraced and this gate will loop. A row carrying an identity with no card is a defect on the same footing as an untraced one.
228
228
  4. Re-run the predicate (now empty) and proceed. Structured-log the draw event to the iter summary `notes`.
229
229
 
230
- **Queue for a person instead — minting nothing — in either of these cases.**
231
- - **The draw would change what the map's approval covers.** The keys that decide a map's ratification are enumerated in exactly one place, `oversight_map_substance_keys()` in `lib/story-oversight.sh`; adding a release row and a card touches none of them, which is precisely why the row inherits approval. If drawing this row would instead need a **new map**, a **new activity column**, or a **new job on the map's traces** — a map that covers the journey but does not trace the job this fix's story serves — then it changes substance a person approved, and doing it silently would void the very approval it was relying on. Derive this from that one function rather than restating its members here, so an amendment to the tuple cannot leave this gate behind.
230
+ **Handle missing planning substance by its actual boundary.**
231
+ - **No suitable map exists.** Author the complete unconfirmed map proposal without asking permission: derive its journey and initial activities, then add the identified release row, cards, and story files. Present the completed proposal for ratification interactively, or queue exactly that ratification under the AFK orchestrator. Dependent implementation stays blocked until ratification; independent work continues.
232
+ - **An existing ratified map would need a new activity column or a new job on its traces.** That changes what its approval covers. The authoritative keys live in `oversight_map_substance_keys()` in `lib/story-oversight.sh`; queue that substantive refinement instead of silently editing the approved map.
232
233
  - **The fix approach is a choice no existing decision record covers.** Recording a new decision is a person's call, not a byproduct of working a ticket.
233
234
 
234
- Interactively, surface the queued item via `request_user_input`. Under the AFK orchestrator, queue it at `outstanding_questions` and move to the next problem — never ask mid-loop.
235
+ Interactively, use `request_user_input` only for the existing-map refinement, uncovered decision, or completed-map ratification. Under the AFK orchestrator, queue the same single item at `outstanding_questions` and move to the next problem — never ask mid-loop.
235
236
 
236
237
  The predicate is the load-bearing detection half (committed shell + behavioural bats per the "Behavioural-tests-default for skill testing" architecture rule: `<itil-plugin-root>/scripts/test/check-fix-rfc-trace.bats`), and it reads BOTH tiers — a release row's cards and a legacy document's `problems:` array — so repointing it cannot hard-stop work that used to proceed. 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.
237
238
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: manage-story-map
3
3
  description: "Heavyweight story-map intake + lifecycle management following the \"Problem-RFC-Story framework with mandatory problem-trace and unified problem ontology\" architecture rule Phase 2. Authors backbone × ribs × slices structure on draft maps, transitions through draft → accepted → in-progress → completed → archived, re-validates I3 + I4 invariants at every transition, and refreshes docs/story-maps/README.md per the \"Problem 062: `manage-problem` does not refresh `docs/problems/README.md` on single-ticket transitions; fast-path cache goes stale silently\" problem / the \"Problem 094: `/wr-itil:manage-problem` does not refresh `docs/problems/README.md` on ticket creation\" problem contract pattern. Companion to /wr-itil:capture-story-map (lightweight aside surface)."
4
- allowed-tools: Read, Write, Edit, Bash, Grep, Glob
4
+ allowed-tools: Read, Write, Edit, Bash, Grep, Glob, request_user_input
5
5
  ---
6
6
 
7
7
  <!-- Generated from the runtime-neutral skill source. Do not edit. -->
@@ -60,6 +60,7 @@ No WSJF token in any grammar form (I5 invariant).
60
60
  | Decision | Resolution | Authority class |
61
61
  |----------|-----------|-----------------|
62
62
  | Story-map ID resolution | Mechanical: regex match `^STORY-MAP-[0-9]{3}$` against `docs/story-maps/*/STORY-MAP-<NNN>-*.html` | silent-mechanical |
63
+ | Initial map proposal authoring | Mechanical: author the unconfirmed map, initial activities, row, cards, and story files without permission | silent-mechanical |
63
64
  | Lifecycle transition validation | Mechanical state machine | silent-mechanical |
64
65
  | Backbone/ribs/slices authoring | request_user_input (taste) at accepted; agent applies user input as HTML edits | taste |
65
66
  | `<meta>` block updates | Mechanical: update status `<meta>` on transitions; preserve all other meta | silent-mechanical |
@@ -93,7 +94,7 @@ Parse `<meta>` block (problems, rfcs, jtbd, status, reported, decision-makers)
93
94
 
94
95
  Display current map state. Surface gaps: missing backbone ribs, slices with unresolved `data-story-id` references, mismatched `<meta name="status">` vs filename `<state>` subdir.
95
96
 
96
- Before asking about backbone authoring direction, apply `/wr-itil:capture-story-map`'s journey-derivation and title/backbone shape checks. Present that derived persona journey for taste-class refinement; use silent-mechanical resolution for housekeeping (status normalisation).
97
+ For a newly captured, unconfirmed map, apply `/wr-itil:capture-story-map`'s journey-derivation and title/backbone shape checks and author the initial complete proposal without `request_user_input` or permission. Present the result only at the ratification flow below. For later substantive refinement of an existing map, retain the taste-class direction prompt; use silent-mechanical resolution for housekeeping such as status normalisation.
97
98
 
98
99
  ### 7. Status transitions
99
100
 
@@ -129,6 +130,8 @@ Per architect amend finding 2 on Slice 7: story-map HTML files do NOT carry an a
129
130
 
130
131
  `ratify` is **orthogonal to the status lifecycle** — a map can be ratified at any status. It confirms human oversight of **the map**, and under the "A release row is the RFC, and the map is the approval surface" architecture rule that approves every ordinary story on it, including stories added later; stories are never ratified individually. Ratification is **drift-invalidated** (the "Gate Marker Lifecycle: TTL + Drift, Not Stop-Hook Reset" architecture rule lineage, NOT the ": Human-oversight marker + `/wr-architect:review-decisions` drain for recorded decisions" architecture rule write-once), but only a **substance** edit re-opens it: the map's own substance as the "Story maps and stories carry a drift-invalidated human-oversight marker" architecture rule defines it — its journey, its identity, what it traces to, and any manifest-bound historical projection. `oversight_map_substance_keys()` is the authoritative field list; this page deliberately does not restate it. Ordinary release rows and cards, story-body edits and template restyling sit outside the fingerprint basis and change nothing. Historical projections are the narrow exception and may be added only through `/wr-itil:migrate-story-map` under exact confirmed adopter authority. This is the ": Ratify the story map and its stories after any change" delivery story surface.
131
132
 
133
+ Under the "New story maps are authored before ratification" architecture rule, creation asks nothing: author the complete unconfirmed proposal first, including its initial activities, release row, cards, and story files. This `ratify` flow is the only human approval in the new-map workflow. Source changes and story implementation depending on the map are blocked until ratification completes; proposal authoring itself is allowed.
134
+
132
135
  **Born-confirmed discipline (the "iter subprocesses set `human-oversight: confirmed` marker on ADRs / personas / JTBDs without an actual user-confirmation event" problem).** Before any marker write, `export CODEX_THREAD_ID` from the transcript path — the marker shim silently no-ops on an empty SID. Every `confirmed` marker MUST be backed by a same-turn human confirm event; never write `confirmed` without the `request_user_input` below (a hollow marker is the "iter subprocesses set `human-oversight: confirmed` marker on ADRs / personas / JTBDs without an actual user-confirmation event" problem bug).
133
136
 
134
137
  **Ratify the map; its stories follow (the ": Ratify the story map and its stories after any change" delivery story UX, amended by the "A release row is the RFC, and the map is the approval surface" architecture rule):**
@@ -115,7 +115,7 @@ Never retry a failed or telemetry-inconclusive worker automatically. It may alre
115
115
 
116
116
  ## Fix Proposal Rule
117
117
 
118
- A fix proposal is a release row on an existing story map, never a new file under `docs/rfcs/`. The row has an identity from `<itil-plugin-root>/bin/wr-itil-next-rfc-id`, at least one story card, and a story whose `problems:` list names the driving problem. Creating a new map, activity column, job, or uncovered architectural choice requires a queued human decision rather than a silent edit.
118
+ A fix proposal is a release row on a story map, never a new file under `docs/rfcs/`. The row has an identity from `<itil-plugin-root>/bin/wr-itil-next-rfc-id`, at least one story card, and a story whose `problems:` list names the driving problem. When no story map exists, author the complete unconfirmed proposal without asking permission: initial activities, identified release row, cards, and story files. Queue exactly one human decision to ratify the completed map, block dependent implementation until ratification, and continue independent work. A substantive change to an existing map, a new job, or an uncovered architectural choice still requires its existing human gate.
119
119
 
120
120
  ## Questions and Stop Conditions
121
121