@windyroad/itil 0.56.0-preview.880 → 0.56.0

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.
@@ -20,7 +20,13 @@
20
20
  # - markdown: `human-oversight:` / `oversight-hash:` frontmatter lines
21
21
  # - HTML: <meta name="human-oversight" ...> / <meta name="oversight-hash" ...>
22
22
  oversight_content_hash() {
23
- grep -vE '^(human-oversight|oversight-hash):|<meta[^>]*name="(human-oversight|oversight-hash)"' "$1" \
23
+ # Exclude the marker + lifecycle-`status` lines, and normalize lifecycle-PROGRESS
24
+ # state — acceptance-criterion checkbox ticks and slice `data-status` — so that
25
+ # ONLY a SUBSTANCE change re-opens ratification. Ticking a criterion or advancing
26
+ # status/slice-progress is progress, not a change to what the user ratified; the
27
+ # value statement, criterion TEXT, and structure still drift the hash.
28
+ grep -vE '^(human-oversight|oversight-hash|status):|<meta[^>]*name="(human-oversight|oversight-hash|status)"' "$1" \
29
+ | sed -E 's/- \[[ xX]\]/- [ ]/g; s/data-status="[^"]*"/data-status=""/g' \
24
30
  | shasum -a 256 | awk '{print $1}'
25
31
  }
26
32
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@windyroad/itil",
3
- "version": "0.56.0-preview.880",
3
+ "version": "0.56.0",
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"
@@ -34,6 +34,30 @@ teardown() { rm -rf "$TMPD"; }
34
34
  [ "$before" != "$(oversight_content_hash "$TMPD/f")" ]
35
35
  }
36
36
 
37
+ @test "oversight_content_hash: ticking an acceptance-criterion checkbox does NOT drift (lifecycle progress)" {
38
+ printf -- '---\nstatus: accepted\n---\n- [ ] a criterion\n' > "$TMPD/f"; before="$(oversight_content_hash "$TMPD/f")"
39
+ printf -- '---\nstatus: accepted\n---\n- [x] a criterion\n' > "$TMPD/f"
40
+ [ "$before" = "$(oversight_content_hash "$TMPD/f")" ]
41
+ }
42
+
43
+ @test "oversight_content_hash: advancing frontmatter status: does NOT drift (lifecycle)" {
44
+ printf -- '---\nstatus: accepted\n---\n# body\n' > "$TMPD/f"; before="$(oversight_content_hash "$TMPD/f")"
45
+ printf -- '---\nstatus: done\n---\n# body\n' > "$TMPD/f"
46
+ [ "$before" = "$(oversight_content_hash "$TMPD/f")" ]
47
+ }
48
+
49
+ @test "oversight_content_hash: changing criterion TEXT DOES drift (substance)" {
50
+ printf -- '---\nstatus: accepted\n---\n- [ ] original\n' > "$TMPD/f"; before="$(oversight_content_hash "$TMPD/f")"
51
+ printf -- '---\nstatus: accepted\n---\n- [ ] a DIFFERENT criterion\n' > "$TMPD/f"
52
+ [ "$before" != "$(oversight_content_hash "$TMPD/f")" ]
53
+ }
54
+
55
+ @test "oversight_content_hash: advancing slice data-status does NOT drift (HTML map lifecycle)" {
56
+ printf '<a class="slice" data-story-id="STORY-1" data-status="draft">x</a>\n' > "$TMPD/m.html"; before="$(oversight_content_hash "$TMPD/m.html")"
57
+ printf '<a class="slice" data-story-id="STORY-1" data-status="done">x</a>\n' > "$TMPD/m.html"
58
+ [ "$before" = "$(oversight_content_hash "$TMPD/m.html")" ]
59
+ }
60
+
37
61
  @test "is_story_map_ratified: confirmed + matching hash → ratified (md)" {
38
62
  printf -- '---\nstatus: accepted\n---\n# body\n' > "$TMPD/f"
39
63
  h="$(oversight_content_hash "$TMPD/f")"
@@ -202,6 +202,7 @@ jtbd: [JTBD-<NNN>, JTBD-<NNN>, ...]
202
202
  rfcs: [<RFC-<NNN>, ...> or empty]
203
203
  story-maps: [<STORY-MAP-<NNN>, ...> or empty]
204
204
  estimated-effort: <S|M|L|XL — derived at capture per ADR-067 (real best-effort value, no deferral marker)>
205
+ human-oversight: unconfirmed
205
206
  ---
206
207
 
207
208
  # STORY-<NNN>: <Title>
@@ -244,6 +245,8 @@ estimated-effort: <S|M|L|XL — derived at capture per ADR-067 (real best-effort
244
245
  (captured via /wr-itil:capture-story; expand at next /wr-itil:manage-story invocation)
245
246
  ```
246
247
 
248
+ **Born `human-oversight: unconfirmed` (ADR-090).** A new story is created with `human-oversight: unconfirmed` in its frontmatter — orthogonal to the `status:` lifecycle. It is NOT ratified until a human confirms it via `/wr-itil:manage-story <NNN> ratify` (which writes `confirmed` + an `oversight-hash` fingerprint via `wr-itil-mark-story-oversight-confirmed`). Until then `wr-itil-detect-unratified-stories-maps` surfaces it and an RFC may not reference it (`wr-itil-check-rfc-stories-ratified`). Adding a story also drifts its parent map's fingerprint, re-opening the map's ratification (lazy-fingerprint, ADR-009 lineage). Do NOT hand-write `confirmed` — born-unconfirmed is the load-bearing default.
249
+
247
250
  The deferred-section pattern matches `capture-rfc`'s placeholder approach — the captured story is intentionally minimal; full INVEST shape lands at the manage-story accepted-transition step.
248
251
 
249
252
  ### 6. Single commit — `## Stories` reverse-trace refresh; no stories README refresh
@@ -127,6 +127,7 @@ Same shape as capture-story Step 4 — silent-default when unavailable.
127
127
  <meta name="adrs" content="">
128
128
  <meta name="reported" content="<YYYY-MM-DD>">
129
129
  <meta name="decision-makers" content="<git config user.name>">
130
+ <meta name="human-oversight" content="unconfirmed">
130
131
  <style>
131
132
  body { font-family: system-ui, sans-serif; max-width: 1200px; margin: 1rem auto; padding: 0 1rem; }
132
133
  h1 { font-size: 1.5rem; }
@@ -161,6 +162,8 @@ Same shape as capture-story Step 4 — silent-default when unavailable.
161
162
 
162
163
  Per `docs/STYLE-GUIDE.md`: NO inline `style=""` on `<a class="slice">` or `<h2 data-rib>` data-bearing elements; embedded `<style>` block in `<head>` is the only permitted styling source; `--cols` custom-property on `.backbone` is the layout-container exception.
163
164
 
165
+ **Born `human-oversight: unconfirmed` (ADR-090).** A new map is created with `<meta name="human-oversight" content="unconfirmed">` — orthogonal to the `status:` lifecycle. It is NOT ratified until a human confirms it via `/wr-itil:manage-story-map <NNN> ratify` (which writes `confirmed` + an `oversight-hash` fingerprint via `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`). Any later content edit drifts the fingerprint and silently re-opens ratification (lazy-fingerprint, ADR-009 lineage). Do NOT hand-write `confirmed` here — born-unconfirmed is the load-bearing default.
166
+
164
167
  ### 6. Single commit — `## Story Maps` reverse-trace refresh
165
168
 
166
169
  **Stage list**: new HTML file PLUS driving problem files (refresh `## Story Maps` section via `update-problem-references-section.sh <file> "Story Maps"`) PLUS driving JTBD files (refresh `## Story Maps` section via `update-jtbd-references-section.sh <file> "Story Maps"`). Do NOT stage `docs/story-maps/README.md` (deferred).
@@ -41,6 +41,7 @@ Per ADR-060 Phase 2 amendment 2026-05-10 lines 200-253:
41
41
  /wr-itil:manage-story <STORY-NNN> in-progress # Manual transition (auto-fires on first non-capture commit)
42
42
  /wr-itil:manage-story <STORY-NNN> done # Transition in-progress → done (gates all-criteria-ticked + RFC closed)
43
43
  /wr-itil:manage-story <STORY-NNN> archived # Close without completion
44
+ /wr-itil:manage-story <STORY-NNN> ratify # ADR-090: confirm this story (usually via manage-story-map ratify)
44
45
  /wr-itil:manage-story review # Re-rank all stories + refresh README
45
46
  ```
46
47
 
@@ -173,6 +174,15 @@ done
173
174
 
174
175
  The helpers are idempotent + lazy-empty per the Slice 2a/2b/Slice 11 contract.
175
176
 
177
+ ### 7.5. Ratification flow (`ratify`) — ADR-090 / STORY-022
178
+
179
+ `ratify` confirms human oversight of a single story — **orthogonal to the `status:` lifecycle** and drift-invalidated (any later content edit re-opens it via the `oversight-hash` fingerprint). The primary ratification surface is `/wr-itil:manage-story-map <NNN> ratify` (map first, then its stories); this per-story form is for ratifying a story on its own.
180
+
181
+ 1. **Born-confirmed discipline (P348):** `export CLAUDE_SESSION_ID` first (the marker shim no-ops on an empty SID). Never write `confirmed` without the same-turn confirm below.
182
+ 2. **Brief + confirm:** present the story's `## User value` + `## Acceptance criteria` — substance BEFORE the ID (P350) — then `AskUserQuestion` with two options: **Ratify** / **(type something)**. On **Ratify**: run `wr-itil-mark-story-oversight-confirmed <story-file>` (writes `confirmed` + fingerprint). On free-text: apply the correction as a story edit and re-present (the edit re-opens ratification).
183
+ 3. **AFK (ADR-013 Rule 6):** if `AskUserQuestion` is unavailable, do NOT auto-ratify (hollow marker, P348) — leave it unratified for the `/wr-itil:work-problems` Step 2.4 drain.
184
+ 4. **Single commit** per ADR-014.
185
+
176
186
  ### 8. List flow (`list`)
177
187
 
178
188
  Read all `docs/stories/*/STORY-*.md` files. Extract ID, title, status, traced problems / RFCs / story-maps / JTBDs. Sort by lifecycle state (accepted > in-progress > draft > done > archived) then by `Reported` ASC. Display as markdown tables grouped by state.
@@ -38,6 +38,7 @@ Per ADR-060 amendment 2026-05-10 lines 145-189 + encoding amendment 2026-05-12:
38
38
  /wr-itil:manage-story-map <STORY-MAP-NNN> in-progress # Manual transition
39
39
  /wr-itil:manage-story-map <STORY-MAP-NNN> completed # Transition in-progress → completed
40
40
  /wr-itil:manage-story-map <STORY-MAP-NNN> archived # Close without completion
41
+ /wr-itil:manage-story-map <STORY-MAP-NNN> ratify # ADR-090: confirm the map, then its stories, one at a time
41
42
  /wr-itil:manage-story-map review # Re-validate all maps + refresh README
42
43
  ```
43
44
 
@@ -113,6 +114,32 @@ done
113
114
 
114
115
  Per architect amend finding 2 on Slice 7: story-map HTML files do NOT carry an auto-maintained markdown reverse-trace section themselves (the `<a class="slice">` data-attribute traces are authored manually during backbone design). No reverse-trace refresh on the map itself; reverse-trace only flows OUT to problem + JTBD parents.
115
116
 
117
+ ### 7.5. Ratification flow (`ratify`) — ADR-090 / STORY-022
118
+
119
+ `ratify` is **orthogonal to the status lifecycle** — a map can be ratified at any status. It confirms human oversight of the map + its stories after they are authored or edited. Ratification is **drift-invalidated** (ADR-009 lineage, NOT ADR-066 write-once): any later content edit silently re-opens it (the `oversight-hash` fingerprint stops matching). This is the STORY-022 surface.
120
+
121
+ **Born-confirmed discipline (P348).** 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 P348 bug).
122
+
123
+ **Map first, then stories — one at a time (STORY-022 UX):**
124
+
125
+ 1. **Ratify the map.** Present the map's path/URL + a self-contained briefing of what it is — the JTBD it serves, its backbone activities, its release slices — briefing the substance BEFORE any ID (P350; the user may be on a device with no repo access). Then `AskUserQuestion` with exactly two options:
126
+ - **Ratify** — the map is correct as-is.
127
+ - **(type something)** — free-text; treat the response as a change request, apply it as a map edit, and re-present. Do NOT ratify a map the user just amended — the edit drifts the fingerprint; loop back to re-brief.
128
+
129
+ On **Ratify**: run `wr-itil-mark-story-oversight-confirmed <map-file>` (writes `confirmed` + the fingerprint). The map is now ratified.
130
+
131
+ 2. **Ratify each story, one at a time.** ONLY after the map is ratified, walk the map's `data-story-id` references in order. For each story that is not already ratified (test with `wr-itil-detect-unratified-stories-maps` or the `is_story_map_ratified` lib helper): brief its `## User value` + `## Acceptance criteria` (substance before ID), then the SAME two-option `AskUserQuestion` (**Ratify** / type-something). On **Ratify**: `wr-itil-mark-story-oversight-confirmed <story-file>`. On free-text: apply the correction as a story edit and re-present (the edit re-opens that story only).
132
+
133
+ 3. **AFK / non-interactive (ADR-013 Rule 6).** When `AskUserQuestion` is unavailable, do NOT auto-ratify — that would forge a hollow marker (P348). Leave the artefacts unratified; they surface in the `/wr-itil:work-problems` Step 2.4 drain for the next interactive session.
134
+
135
+ 4. **Single commit** — stage the map + every newly-ratified story + the README refresh; commit per ADR-014.
136
+
137
+ **Why map-first:** an RFC may reference only ratified stories (`wr-itil-check-rfc-stories-ratified`), and a story is only meaningful inside its ratified map — ratifying stories under an unratified map would invert the dependency STORY-022 encodes.
138
+
139
+ **Reuse offers ratified stories only (STORY-024).** When decomposing a fix, existing map stories the fix touches are offered for **reuse** — referenced by an additional slice card / `data-story-id`, NOT duplicated as a new file; the reused story's `rfcs:` reverse-trace picks up the new RFC. Only **ratified** stories (test with `is_story_map_ratified`) are offered for reuse; an unratified story must be ratified (§ 7.5) before an RFC can reference it.
140
+
141
+ **Re-slicing re-opens ratification (STORY-025).** Grouping stories into ordered release slices (Release 1 walking skeleton → Release 2 …) is authored as `data-status` / slice-card edits on the map; deferred phases stay first-class cards (visible, competing for priority), never buried. Because slicing edits the map's content, it drifts the `oversight-hash` and silently re-opens the map's ratification (§ 7.5) — no explicit marker reset needed; the fingerprint handles it.
142
+
116
143
  ### 8. List flow (`list`)
117
144
 
118
145
  Forward-points to `/wr-itil:list-story-maps` (read-only sibling).
@@ -350,7 +350,7 @@ Before the orchestrator emits the final `ALL_DONE` sentinel for the AFK loop, it
350
350
 
351
351
  1. *Outstanding-questions surface.* Read `.afk-run-state/outstanding-questions.jsonl`. If non-empty, invoke Step 2.5b's surfacing routine to present the accumulated queue (via `AskUserQuestion`-when-available-else-table per ADR-013 Rule 1 / Rule 6). On completion, truncate the queue file. If the queue is empty, this sub-surface returns immediately. The surfacing routine is the existing Step 2.5b — Step 2.4 does NOT re-implement; it sequences.
352
352
 
353
- 2. *Oversight-unconfirmed drain.* Run `wr-architect-detect-unoversighted` and `wr-jtbd-detect-unoversighted` (both ADR-049 PATH shims, both always exit 0; output is the list of unoversighted artefact paths). If either lists ≥ 1 artefact whose frontmatter carries `human-oversight: unconfirmed` (the AFK-explicit-deferred state, distinct from the implicit-absent state pre-existing ADR/JTBD files carry), surface a one-line nudge: *"N iter-deferred decision(s)/job(s) carry `human-oversight: unconfirmed`. Run `/wr-architect:review-decisions` and `/wr-jtbd:confirm-jobs-and-personas` to drain."* If `AskUserQuestion` is available (`/wr-itil:work-problems` was invoked interactively before the AFK loop started), surface a 2-option choice — `Drain now` (invokes the appropriate drain skill before `ALL_DONE`) / `Defer to next session` (proceeds to gate (b) with the nudge in the final summary). If `AskUserQuestion` is unavailable, the nudge prints in the final summary table and gate (b) proceeds. The drain is NOT a halt — `unconfirmed` markers are explicit-by-design AFK signals (the iter wrote them KNOWING the user would need to confirm), and the drain is the documented path. Detector difference matters: ADRs/JTBDs that pre-date the ADR-066/ADR-068 marker contract carry NO `human-oversight:` line at all; they fall through to the existing review-decisions/confirm-jobs-and-personas backlog drain (no new surfacing here). The new surfacing fires ONLY on the explicit `unconfirmed` value — the AFK-iter-deferred class P348 introduces.
353
+ 2. *Oversight-unconfirmed drain.* Run `wr-architect-detect-unoversighted`, `wr-jtbd-detect-unoversighted`, and `wr-itil-detect-unratified-stories-maps` (all ADR-049 PATH shims, all always exit 0; output is the list of unoversighted/unratified artefact paths). The story/map detector (**ADR-090**) is **drift-aware**: it lists story maps + stories that are never-ratified, explicitly `unconfirmed`, OR **drift-reopened** — a `confirmed` marker whose `oversight-hash` fingerprint no longer matches the edited content. Re-ratify each via `/wr-itil:manage-story` / `/wr-itil:manage-story-map` (or `wr-itil-mark-story-oversight-confirmed`); the nudge + 2-option `Drain now` / `Defer` surface below applies to this list identically. If either lists ≥ 1 artefact whose frontmatter carries `human-oversight: unconfirmed` (the AFK-explicit-deferred state, distinct from the implicit-absent state pre-existing ADR/JTBD files carry), surface a one-line nudge: *"N iter-deferred decision(s)/job(s) carry `human-oversight: unconfirmed`. Run `/wr-architect:review-decisions` and `/wr-jtbd:confirm-jobs-and-personas` to drain."* If `AskUserQuestion` is available (`/wr-itil:work-problems` was invoked interactively before the AFK loop started), surface a 2-option choice — `Drain now` (invokes the appropriate drain skill before `ALL_DONE`) / `Defer to next session` (proceeds to gate (b) with the nudge in the final summary). If `AskUserQuestion` is unavailable, the nudge prints in the final summary table and gate (b) proceeds. The drain is NOT a halt — `unconfirmed` markers are explicit-by-design AFK signals (the iter wrote them KNOWING the user would need to confirm), and the drain is the documented path. Detector difference matters: ADRs/JTBDs that pre-date the ADR-066/ADR-068 marker contract carry NO `human-oversight:` line at all; they fall through to the existing review-decisions/confirm-jobs-and-personas backlog drain (no new surfacing here). The new surfacing fires ONLY on the explicit `unconfirmed` value — the AFK-iter-deferred class P348 introduces.
354
354
 
355
355
  **Gate (b) — Session-level retro.** Invoke `/wr-retrospective:run-retro` via the Skill tool. This is the **orchestrator-main-turn session-level retro**, distinct from the per-iter retro fired inside each iter subprocess (per P086 / Step 5 retro-on-exit clause). The session-level retro covers cross-iter patterns, friction observations, framework-improvement candidates, and the AFK loop's overall trajectory — surface visible only after multiple iters have completed. Retro commits its own work per ADR-014; any tickets retro creates ride retro's own commit, and the orchestrator picks them up on the *next* invocation of `/wr-itil:work-problems` rather than re-entering the loop here.
356
356