@windyroad/itil 2.1.4 → 2.1.5

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.1.4"
500
+ "version": "2.1.5"
501
501
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wr-itil",
3
- "version": "2.1.4",
3
+ "version": "2.1.5",
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.1.4",
3
+ "version": "2.1.5",
4
4
  "description": "ITIL-aligned IT service management for Claude Code and Codex",
5
5
  "bin": {
6
6
  "windyroad-itil": "./bin/install.mjs"
@@ -43,7 +43,8 @@ Positional grammar mirrors `/wr-itil:capture-story` shape (footnote per the "Pro
43
43
  | JTBD-trace presence | I4 hard-block — refuse on missing trace; emit deny log + halt | direction-setting |
44
44
  | JTBD-trace validation | Mechanical: each `JTBD-<NNN>` resolves to a file in `docs/jtbd/` | silent-mechanical |
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
- | Title kebab-slug | Mechanical: first 8-10 non-stopword tokens of description | silent-mechanical |
46
+ | Persona journey derivation | Mechanical: read the persona + JTBD and derive the ordered steps they walk before authoring | silent-mechanical |
47
+ | Title kebab-slug | Mechanical: short outcome phrase naming the derived journey, then kebab-case | silent-mechanical |
47
48
  | Title prose refinement | Optional taste AskUserQuestion; silent-default to derived form | taste |
48
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 |
49
50
  | Reverse-trace `## Story Maps` refresh | Mechanical: inline on driving problem + JTBD files via Slice 2a/2b helpers | silent-mechanical |
@@ -70,8 +71,6 @@ description="$*"
70
71
 
71
72
  Validate `$problem_trace` matches `^P[0-9]{3}(,P[0-9]{3})*$`. Validate `$jtbd_trace` matches `^JTBD-[0-9]{3}(,JTBD-[0-9]{3})*$`. If `$description` is empty, halt with empty-arguments directive.
72
73
 
73
- Derive kebab-case title slug from first 8-10 non-stopword tokens of `$description`.
74
-
75
74
  ### 2. Validate problem trace + I3 hard-block
76
75
 
77
76
  For each `P<NNN>`:
@@ -93,6 +92,12 @@ jtbd_file=$(ls docs/jtbd/*/JTBD-<NNN>-*.md 2>/dev/null | head -1)
93
92
 
94
93
  **I4 hard-block** (the "Problem-RFC-Story framework with mandatory problem-trace and unified problem ontology" architecture rule, the story-map schema's `jtbd:` field): trace absent / malformed / unresolved → emit deny log + halt. Story-maps without JTBD trace are structurally meaningless per the "Problem-RFC-Story framework with mandatory problem-trace and unified problem ontology" architecture rule ("a map with no JTBD trace is structurally meaningless"; Patton's central thesis is journey-around-user-value).
95
94
 
95
+ ### 2.6. Derive the persona journey
96
+
97
+ Derive the journey before the title or backbone. Read the persona and JTBD, then write the ordered steps the persona walks from trigger to outcome. Derive the map title and backbone from that journey, not from the change description.
98
+
99
+ Use a short outcome phrase naming that journey for the title, then convert it to a kebab-case slug. Do not reuse the first tokens of `$description`: the description names the work that triggered capture, not the journey the map approves.
100
+
96
101
  ### 3. Compute next STORY-MAP ID
97
102
 
98
103
  Inline `max(local, origin, history) + 1` per the "AFK orchestrator preflight: get the repo into a clean state before starting" architecture rule collision-guard (architect Slice 3 design review option a — inline-only path, mirrors capture-rfc + capture-story precedent). Git history keeps deleted IDs retired without adding tombstone files:
@@ -104,9 +109,9 @@ history_max=$(git log --all --name-only --format= -- docs/story-maps/ 2>/dev/nul
104
109
  next=$(printf '%03d' $(( 10#$(printf '%s\n' "${local_max:-0}" "${origin_max:-0}" "${history_max:-0}" | sort -n | tail -1) + 1 )))
105
110
  ```
106
111
 
107
- ### 4. Optional taste prompt for title
112
+ ### 4. Optional taste prompt for the derived journey title
108
113
 
109
- Same shape as capture-story Step 4 — silent-default when unavailable.
114
+ Same shape as capture-story Step 4 — offer the journey-derived title, not the change description, and silent-default when unavailable.
110
115
 
111
116
  ### 5. Write the story-map JSON, then render it
112
117
 
@@ -163,7 +168,8 @@ appear here changes what that test asserts, and that binding is deliberate.
163
168
 
164
169
  **Authoring rules:**
165
170
 
166
- - **The backbone must be a journey, not a list of invariants.** Activities are steps the persona walks through in sequence. "Finish a changeget it assessedpush itget through CIrelease it" is a backbone. "Leave no unscored way out", "score this change not the last one" are invariants, and a column of them is not a map.
171
+ - **The title and backbone name the persona's journey, not the work.** GOOD — developer: "Take a problem from noticed to resolved"; Notice and capture → Find the cause Decompose the fix → Implement the changes → Land, release and verify. GOOD — plugin user: "Close the loop with someone who reported a problem"; Report it Hear it landedFind out what will happen Get kept postedGet a real outcome. BAD — "Convert source-inspection pins to behavioural tests" with "Conversion technique backbone ordered by tractability"; both describe the work, not the persona's journey.
172
+ - **Check the shape before writing.** Re-derive the journey if the title restates `$description`, if the backbone has one column, or if its columns name techniques, phases, invariants, or implementation tasks rather than ordered persona actions. "Finish a change → get it assessed → push it → get through CI → release it" is a backbone. "Leave no unscored way out", "score this change not the last one" are invariants, and a column of them is not a map.
167
173
  - At capture a map may legitimately have **columns and rows but empty cells**. That is the honest state of unbuilt work, and the renderer says so in place — a wholly empty band carries its own sentence. Do not add prose at the top explaining it.
168
174
  - **Composing a row asks two questions, in order.** A row is a release, so putting two stories in one is a claim that they ship together. Answer both before drawing it.
169
175
 
@@ -82,7 +82,7 @@ Parse `<meta>` block (problems, rfcs, jtbd, status, reported, decision-makers)
82
82
 
83
83
  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
84
 
85
- Use AskUserQuestion for backbone authoring direction (taste class); silent-mechanical for housekeeping (status normalisation).
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
86
 
87
87
  ### 7. Status transitions
88
88
 
@@ -54,7 +54,8 @@ Positional grammar mirrors `/wr-itil:capture-story` shape (footnote per the "Pro
54
54
  | JTBD-trace presence | I4 hard-block — refuse on missing trace; emit deny log + halt | direction-setting |
55
55
  | JTBD-trace validation | Mechanical: each `JTBD-<NNN>` resolves to a file in `docs/jtbd/` | silent-mechanical |
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
- | Title kebab-slug | Mechanical: first 8-10 non-stopword tokens of description | silent-mechanical |
57
+ | Persona journey derivation | Mechanical: read the persona + JTBD and derive the ordered steps they walk before authoring | silent-mechanical |
58
+ | Title kebab-slug | Mechanical: short outcome phrase naming the derived journey, then kebab-case | silent-mechanical |
58
59
  | Title prose refinement | Optional taste request_user_input; silent-default to derived form | taste |
59
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 |
60
61
  | Reverse-trace `## Story Maps` refresh | Mechanical: inline on driving problem + JTBD files via Slice 2a/2b helpers | silent-mechanical |
@@ -81,8 +82,6 @@ description="$*"
81
82
 
82
83
  Validate `$problem_trace` matches `^P[0-9]{3}(,P[0-9]{3})*$`. Validate `$jtbd_trace` matches `^JTBD-[0-9]{3}(,JTBD-[0-9]{3})*$`. If `$description` is empty, halt with empty-arguments directive.
83
84
 
84
- Derive kebab-case title slug from first 8-10 non-stopword tokens of `$description`.
85
-
86
85
  ### 2. Validate problem trace + I3 hard-block
87
86
 
88
87
  For each `P<NNN>`:
@@ -104,6 +103,12 @@ jtbd_file=$(ls docs/jtbd/*/JTBD-<NNN>-*.md 2>/dev/null | head -1)
104
103
 
105
104
  **I4 hard-block** (the "Problem-RFC-Story framework with mandatory problem-trace and unified problem ontology" architecture rule, the story-map schema's `jtbd:` field): trace absent / malformed / unresolved → emit deny log + halt. Story-maps without JTBD trace are structurally meaningless per the "Problem-RFC-Story framework with mandatory problem-trace and unified problem ontology" architecture rule ("a map with no JTBD trace is structurally meaningless"; Patton's central thesis is journey-around-user-value).
106
105
 
106
+ ### 2.6. Derive the persona journey
107
+
108
+ Derive the journey before the title or backbone. Read the persona and JTBD, then write the ordered steps the persona walks from trigger to outcome. Derive the map title and backbone from that journey, not from the change description.
109
+
110
+ Use a short outcome phrase naming that journey for the title, then convert it to a kebab-case slug. Do not reuse the first tokens of `$description`: the description names the work that triggered capture, not the journey the map approves.
111
+
107
112
  ### 3. Compute next STORY-MAP ID
108
113
 
109
114
  Inline `max(local, origin, history) + 1` per the "AFK orchestrator preflight: get the repo into a clean state before starting" architecture rule collision-guard (architect Slice 3 design review option a — inline-only path, mirrors capture-rfc + capture-story precedent). Git history keeps deleted IDs retired without adding tombstone files:
@@ -115,9 +120,9 @@ history_max=$(git log --all --name-only --format= -- docs/story-maps/ 2>/dev/nul
115
120
  next=$(printf '%03d' $(( 10#$(printf '%s\n' "${local_max:-0}" "${origin_max:-0}" "${history_max:-0}" | sort -n | tail -1) + 1 )))
116
121
  ```
117
122
 
118
- ### 4. Optional taste prompt for title
123
+ ### 4. Optional taste prompt for the derived journey title
119
124
 
120
- Same shape as capture-story Step 4 — silent-default when unavailable.
125
+ Same shape as capture-story Step 4 — offer the journey-derived title, not the change description, and silent-default when unavailable.
121
126
 
122
127
  ### 5. Write the story-map JSON, then render it
123
128
 
@@ -174,7 +179,8 @@ appear here changes what that test asserts, and that binding is deliberate.
174
179
 
175
180
  **Authoring rules:**
176
181
 
177
- - **The backbone must be a journey, not a list of invariants.** Activities are steps the persona walks through in sequence. "Finish a changeget it assessedpush itget through CIrelease it" is a backbone. "Leave no unscored way out", "score this change not the last one" are invariants, and a column of them is not a map.
182
+ - **The title and backbone name the persona's journey, not the work.** GOOD — developer: "Take a problem from noticed to resolved"; Notice and capture → Find the cause Decompose the fix → Implement the changes → Land, release and verify. GOOD — plugin user: "Close the loop with someone who reported a problem"; Report it Hear it landedFind out what will happen Get kept postedGet a real outcome. BAD — "Convert source-inspection pins to behavioural tests" with "Conversion technique backbone ordered by tractability"; both describe the work, not the persona's journey.
183
+ - **Check the shape before writing.** Re-derive the journey if the title restates `$description`, if the backbone has one column, or if its columns name techniques, phases, invariants, or implementation tasks rather than ordered persona actions. "Finish a change → get it assessed → push it → get through CI → release it" is a backbone. "Leave no unscored way out", "score this change not the last one" are invariants, and a column of them is not a map.
178
184
  - At capture a map may legitimately have **columns and rows but empty cells**. That is the honest state of unbuilt work, and the renderer says so in place — a wholly empty band carries its own sentence. Do not add prose at the top explaining it.
179
185
  - **Composing a row asks two questions, in order.** A row is a release, so putting two stories in one is a claim that they ship together. Answer both before drawing it.
180
186
 
@@ -93,7 +93,7 @@ Parse `<meta>` block (problems, rfcs, jtbd, status, reported, decision-makers)
93
93
 
94
94
  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
95
 
96
- Use request_user_input for backbone authoring direction (taste class); silent-mechanical for housekeeping (status normalisation).
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
97
 
98
98
  ### 7. Status transitions
99
99