@windyroad/itil 0.21.5 → 0.21.6

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.
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "wr-itil",
3
- "version": "0.21.5",
3
+ "version": "0.21.6",
4
4
  "description": "ITIL-aligned IT service management for Claude Code"
5
5
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@windyroad/itil",
3
- "version": "0.21.5",
3
+ "version": "0.21.6",
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"
@@ -124,16 +124,22 @@ When `$ARGUMENTS` matches the shape `<I###> link P<MMM>` (an incident ID followe
124
124
 
125
125
  The forwarder does NOT re-implement the link logic locally — it invokes the Skill tool with `wr-itil:link-incident`, passes `<I###> P<MMM>` through as the data parameters, and returns the new skill's output verbatim. Duplicating the problem-file-lookup + Linked Problem section write logic would harden the deprecation window into a permanent fork. The data-parameter shape `<I###> P<MMM>` is permitted under ADR-010 amended — only the verb word `link` is being split out.
126
126
 
127
- ### 2. For new incidents: Check for duplicates FIRST
127
+ ### 2. For new incidents: Check for duplicates FIRST (ADR-044 category-1 direction-setting)
128
128
 
129
129
  Before creating, search `docs/incidents/` for active (non-closed) incidents with overlapping symptoms or scope. The user may already have an incident open for this outage.
130
130
 
131
- 1. Extract keywords from the description (e.g., "500 errors", "checkout", "login")
132
- 2. `grep -l` the keywords across `docs/incidents/*.{investigating,mitigating,restored}.md`
133
- 3. If matches are found, present them via `AskUserQuestion`:
134
- - "I found active incidents that may be related: I003 (checkout 500s, mitigating), I007 (login slowness, investigating). Would you like to (a) update an existing incident, (b) declare a new incident anyway, or (c) cancel?"
135
- 4. If the user chooses to update, switch to the update flow for that incident ID
136
- 5. If no matches, proceed to create
131
+ 1. Extract keywords from the description (e.g., "500 errors", "checkout", "login").
132
+ 2. `grep -l` the keywords across `docs/incidents/*.{investigating,mitigating,restored}.md`.
133
+ 3. If matches are found, present them via `AskUserQuestion` (this is the ADR-044 **category-1 (direction-setting)** surface — only the user knows whether the new symptoms describe the same outage as an existing ticket; the framework cannot resolve semantic similarity deterministically). Construct the call as:
134
+ - `header: "Active incidents found"`
135
+ - `multiSelect: false`
136
+ - `question` body (plain prose, no parenthetical option-letters and no prose-ask phrasing per ADR-013 Confirmation criterion #1; the structured `options[]` below replaces both): `"I found active incidents that may be related: I003 (checkout 500s, mitigating), I007 (login slowness, investigating). Choose how to proceed:"`
137
+ - `options[]`:
138
+ 1. `Update an existing incident` — description: "Switch to the update flow for the chosen incident ID; you'll name the ID in the next step."
139
+ 2. `Declare a new incident anyway` — description: "Proceed to Step 3 (assign next ID) and treat this as a distinct event."
140
+ 3. `Cancel` — description: "Exit without creating or modifying any incident."
141
+ 4. If the user chooses **Update an existing incident**, switch to the update flow for the user-named incident ID.
142
+ 5. If no matches, proceed to create.
137
143
 
138
144
  ### 3. For new incidents: Assign the next ID
139
145
 
@@ -146,9 +152,9 @@ next=$(printf 'I%03d' $((10#${last:-0} + 1)))
146
152
  echo "$next"
147
153
  ```
148
154
 
149
- ### 4. For new incidents: Gather information
155
+ ### 4. For new incidents: Gather information (ADR-044 category-1 direction-setting)
150
156
 
151
- Use `AskUserQuestion` for anything not in `$ARGUMENTS`:
157
+ Use `AskUserQuestion` for anything not in `$ARGUMENTS`. Incident-declaration inputs are user-knowledge that the framework cannot infer (only the user observed the symptoms / knows the scope / can rate live business impact); this is the canonical ADR-044 **category-1 (direction-setting)** surface — *"only the user knows the goals that haven't been written down yet."*
152
158
 
153
159
  - **Title**: short kebab-case-friendly description
154
160
  - **Symptoms**: what is observable (errors, latency, missing data)?
@@ -197,7 +203,7 @@ Do not ask for fields that can be inferred:
197
203
  *(none yet — added on restore transition)*
198
204
  ```
199
205
 
200
- ### 6. For updates: Edit the existing file
206
+ ### 6. For updates: Edit the existing file (evidence gate is ADR-044 category-2 deviation-approval)
201
207
 
202
208
  Find the file by ID:
203
209
 
@@ -205,7 +211,19 @@ Find the file by ID:
205
211
  ls docs/incidents/<I###>-*.md 2>/dev/null
206
212
  ```
207
213
 
208
- Append new observations, hypotheses, or timeline entries. **Every hypothesis must cite evidence.** If the user proposes a hypothesis without evidence, ask via `AskUserQuestion` what evidence supports it before writing.
214
+ Append new observations, hypotheses, or timeline entries. **Every hypothesis must cite evidence.** If the user proposes a hypothesis without evidence, fire the **3-option evidence gate** — same shape as `/wr-itil:mitigate-incident` Step 3, for cross-skill cool-headed-commitment consistency. This is the ADR-044 **category-2 (deviation-approval)** surface: ADR-011's evidence-first rule is the existing decision; "Record anyway" is the user-approved deviation in this specific case. The user is the right authority for the bypass shape.
215
+
216
+ Construct the `AskUserQuestion` call as:
217
+
218
+ - `header: "Evidence gate"`
219
+ - `multiSelect: false`
220
+ - `question` body: `"Hypothesis '<one-line summary>' has no cited evidence reference. Per ADR-011 evidence-first rule, every hypothesis must cite a log / repro / diff / metric reference. Choose how to proceed:"`
221
+ - `options[]`:
222
+ 1. `Add evidence now` — description: "Provide the evidence reference (log line, dashboard URL, repro steps, diff hash, etc.); the hypothesis lands with the cited evidence."
223
+ 2. `Record anyway with audit-trail bypass` — description: "Land the hypothesis without cited evidence; agent appends `[<timestamp> UTC] Evidence-gate bypassed by user — reason: <justification>` to the incident file's `## Audit trail` section."
224
+ 3. `Cancel` — description: "Discard the hypothesis; do not write it to the file."
225
+
226
+ On option 2 (bypass), append the `Evidence-gate bypassed by user — reason: <justification>` line to the `## Audit trail` section of the incident file before writing the hypothesis. If the section does not exist, create it. The bypass-marker prose is fixed verbatim so post-incident review can locate every bypassed gate via grep.
209
227
 
210
228
  ### 7. For mitigate: delegate to `/wr-itil:mitigate-incident` (P071 split slice 6a)
211
229
 
@@ -253,7 +271,7 @@ After any operation, verify:
253
271
  - **Evidence discipline**: every Hypothesis has a cited evidence reference
254
272
  - **Linked Problem** section present and consistent (or **No Problem** with justification) once the incident reaches Restored
255
273
 
256
- ### 14. Report
274
+ ### 14. Report (risk-above-appetite commit is ADR-044 category-3 one-time-override)
257
275
 
258
276
  After any operation, report:
259
277
 
@@ -271,7 +289,7 @@ Commit the completed work per ADR-014 (governance skills commit their own work):
271
289
  - Incident mitigated: `docs(incidents): I<NNN> mitigated — <mitigation summary>`
272
290
  - Incident restored: `docs(incidents): I<NNN> restored — <action>`
273
291
  - Incident closed: `docs(incidents): close I<NNN>`
274
- 4. If risk is above appetite: use `AskUserQuestion` to ask whether to commit anyway, remediate first, or park the work. If `AskUserQuestion` is unavailable, skip the commit and report the uncommitted state clearly.
292
+ 4. If risk is above appetite: use `AskUserQuestion` to ask whether to commit anyway, remediate first, or park the work. This is the ADR-044 **category-3 (one-time-override)** surface — in incident-mitigation context the tech lead may need to ship a fix despite higher residual risk to restore service fast (JTBD-201); the rule (RISK-POLICY appetite) still stands but this specific case warrants an exception. The 3-option vocabulary (commit anyway / remediate / park) is the genuine category-3 surface. If `AskUserQuestion` is unavailable, skip the commit and report the uncommitted state clearly per ADR-013 Rule 6.
275
293
 
276
294
  ### 15. Auto-release when changesets are queued (ADR-020)
277
295
 
@@ -310,4 +328,22 @@ Otherwise, after the commit in step 14 lands, drain the release queue so the fix
310
328
 
311
329
  `push:watch` and `release:watch` are policy-authorised actions when residual risk is within appetite per RISK-POLICY.md, so no `AskUserQuestion` is required for the drain itself (ADR-013 Rule 5). Auto-apply actions under Rules 2–7 are also policy-authorised per ADR-013 Rule 5.
312
330
 
331
+ ## Related
332
+
333
+ - **P136** (`docs/problems/136-adr-044-alignment-audit-master.open.md`) — ADR-044 alignment audit master. This skill is the third high-ask SKILL audited under Phase 2 (after work-problem singular and mitigate-incident).
334
+ - **ADR-044** (`docs/decisions/044-decision-delegation-contract.proposed.md`) — Decision-Delegation Contract. All four AskUserQuestion surfaces in this skill align with the 6-class authority taxonomy: Step 2 duplicate-check is **category-1 (direction-setting)**; Step 4 gather-info is **category-1 (direction-setting)**; Step 6 evidence-gate is **category-2 (deviation-approval)**; Step 14 risk-above-appetite is **category-3 (one-time-override)**.
335
+ - **ADR-013 amended Rule 1** (`docs/decisions/013-structured-user-interaction-for-governance-decisions.proposed.md`) — structured user interaction; narrowed in P135 to defer to ADR-044 for framework-resolution boundary. All four surfaces retain `AskUserQuestion` as genuine user-authority surfaces under categories enumerated in ADR-044.
336
+ - **ADR-013 Confirmation criterion #1** — `grep -inE "Options:.*\(a\)\|Your call:\|which would you like\|which way?"` returns zero matches. Step 2's prior prompt body violated this with `Would you like to (a) update...` phrasing; the P136 Phase 2 refactor (2026-04-28) closed the regression by lifting options into the `AskUserQuestion` `options[]` mechanism.
337
+ - **ADR-011** (`docs/decisions/011-manage-incident-skill.proposed.md`) — incident lifecycle; evidence-first workflow; reversible-mitigation preference; Sev 4-5 lightweight path. Step 6's evidence-gate refactor (2026-04-28) extends ADR-011's evidence-first rule with the documented `Record anyway` audit-trail bypass that mitigate-incident already used (cool-headed-commitment consistency across the two incident skills).
338
+ - **ADR-014** — governance skills commit their own work. Step 14 unchanged.
339
+ - **ADR-015** — release scorer delegation pattern. Step 15 unchanged.
340
+ - **ADR-018** + **ADR-020** — release cadence. Step 15 unchanged.
341
+ - **ADR-026** — cost-source grounding. Step 6's audit-trail bypass note preserves grounding by capturing the user's justification at deviation time.
342
+ - **ADR-042** — auto-apply scorer remediations. Step 15 above-appetite branch unchanged.
343
+ - **P071** — skill-split origin (slice 6 — manage-incident is the host with thin-router forwarders for `list`, `mitigate`, `restored`, `close`, `link`).
344
+ - **P081** — structural-grep retrofit; the `manage-incident-adr-044-contract.bats` companion test file carries the `tdd-review: structural-permitted` marker as the bridge until P081 Phase 2 retrofit lands.
345
+ - **JTBD-001** (`docs/jtbd/solo-developer/JTBD-001-enforce-governance.proposed.md`) — Surface 1 refactor preserves the duplicate-check governance gate while removing the prose-ask compliance gap; Surfaces 2 + 3 + 4 retain genuine consent-gate-for-the-genuinely-direction-setting / deviation-approval / one-time-override.
346
+ - **JTBD-101** (`docs/jtbd/plugin-developer/JTBD-101-extend-suite.proposed.md`) — Step 6 evidence-gate refactor brings manage-incident into pattern parity with mitigate-incident's slice-6a evidence-gate. Adopters get one consistent evidence-gate pattern across both incident skills.
347
+ - **JTBD-201** (`docs/jtbd/tech-lead/JTBD-201-restore-service-fast.proposed.md`) — Step 6 explicit `Record anyway` bypass strengthens the audit-trail outcome (implicit-bypass becomes explicit-bypass-with-permanent-trail) without weakening the cool-headed-commitment outcome (`Add evidence` remains the friction-free default; bypass requires conscious second choice).
348
+
313
349
  $ARGUMENTS
@@ -0,0 +1,138 @@
1
+ #!/usr/bin/env bats
2
+ # ADR-044 alignment contract assertions for manage-incident SKILL.md
3
+ # (P136 Phase 2 sub-task 3 — added 2026-04-28).
4
+ #
5
+ # tdd-review: structural-permitted (justification: SKILL.md prose contract
6
+ # assertions; behavioural skill-runtime harness pending P012 + P081 Phase 2;
7
+ # expected to migrate to behavioural form once the harness exists. Added
8
+ # during P136 Phase 2 ADR-044 alignment audit per the inline plan's
9
+ # bridge-marker rule.)
10
+ #
11
+ # Note: the sibling file manage-incident.bats deliberately avoids structural-
12
+ # grep on SKILL.md prose (P011 ban; functional/behavioural-by-default). This
13
+ # file is the dedicated structural-grep-permitted home for the ADR-044
14
+ # alignment contract during the bridge window. After P081 Phase 2 retrofits
15
+ # the project's structural-grep tests to behavioural form, this file's
16
+ # assertions migrate too.
17
+ #
18
+ # @problem P136 (ADR-044 alignment audit master — Phase 2 manage-incident)
19
+ # @adr ADR-044 (Decision-Delegation Contract)
20
+ # @adr ADR-013 amended Rule 1 (structured user interaction)
21
+ # @adr ADR-013 Confirmation criterion #1 (no prose-ask vocabulary)
22
+ # @adr ADR-011 (evidence-first workflow)
23
+ # @jtbd JTBD-201 (restore service fast with audit trail)
24
+ # @jtbd JTBD-001 (enforce governance without slowing down)
25
+ # @jtbd JTBD-101 (extend the suite with consistent patterns)
26
+
27
+ setup() {
28
+ SKILL_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
29
+ SKILL_FILE="${SKILL_DIR}/SKILL.md"
30
+ [ -f "$SKILL_FILE" ]
31
+ }
32
+
33
+ # ----------------------------------------------------------------------
34
+ # Surface 1 — Step 2 duplicate-check (cat-1 direction-setting; refactor)
35
+ # ----------------------------------------------------------------------
36
+
37
+ @test "SKILL.md Step 2 duplicate-check prompt does NOT use 'would you like' (ADR-013 Confirmation #1)" {
38
+ # Refactor closes ADR-013 Confirmation criterion #1 regression at line 134.
39
+ # The duplicate-check AskUserQuestion options are now structured via the
40
+ # tool's options[] mechanism, not inlined as prose '(a)/(b)/(c)'.
41
+ run awk '/^### 2\. /,/^### 3\. /' "$SKILL_FILE"
42
+ [ "$status" -eq 0 ]
43
+ ! echo "$output" | grep -qiE "would you like"
44
+ }
45
+
46
+ @test "SKILL.md Step 2 duplicate-check prompt does NOT use parenthetical (a)/(b)/(c)" {
47
+ run awk '/^### 2\. /,/^### 3\. /' "$SKILL_FILE"
48
+ [ "$status" -eq 0 ]
49
+ ! echo "$output" | grep -qE "\(a\) update|\(b\) declare|\(c\) cancel"
50
+ }
51
+
52
+ @test "SKILL.md Step 2 duplicate-check cross-references ADR-044 category-1 (direction-setting)" {
53
+ run awk '/^### 2\. /,/^### 3\. /' "$SKILL_FILE"
54
+ [ "$status" -eq 0 ]
55
+ [[ "$output" == *"ADR-044"* ]]
56
+ [[ "$output" == *"direction-setting"* ]] || [[ "$output" == *"category 1"* ]] || [[ "$output" == *"category-1"* ]]
57
+ }
58
+
59
+ @test "SKILL.md Step 2 still presents 3 options (update / declare / cancel) for AskUserQuestion" {
60
+ # Negative-of-negative guard — the gate must REMAIN. Refactor changes the
61
+ # SHAPE (options[] vs prose), not the existence of the 3 user choices.
62
+ run awk '/^### 2\. /,/^### 3\. /' "$SKILL_FILE"
63
+ [ "$status" -eq 0 ]
64
+ [[ "$output" == *"Update"* ]] || [[ "$output" == *"update"* ]]
65
+ [[ "$output" == *"Declare"* ]] || [[ "$output" == *"declare"* ]]
66
+ [[ "$output" == *"Cancel"* ]] || [[ "$output" == *"cancel"* ]]
67
+ }
68
+
69
+ # ----------------------------------------------------------------------
70
+ # Surface 2 — Step 4 gather info (cat-1 cosmetic cross-ref)
71
+ # ----------------------------------------------------------------------
72
+
73
+ @test "SKILL.md Step 4 gather-info cross-references ADR-044 category-1 (direction-setting)" {
74
+ run awk '/^### 4\. /,/^### 5\. /' "$SKILL_FILE"
75
+ [ "$status" -eq 0 ]
76
+ [[ "$output" == *"ADR-044"* ]]
77
+ [[ "$output" == *"direction-setting"* ]] || [[ "$output" == *"category 1"* ]] || [[ "$output" == *"category-1"* ]]
78
+ }
79
+
80
+ # ----------------------------------------------------------------------
81
+ # Surface 3 — Step 6 evidence-first gate refactor (cat-2; align with mitigate-incident)
82
+ # ----------------------------------------------------------------------
83
+
84
+ @test "SKILL.md Step 6 evidence-first gate uses 3-option pattern (Add / Record-anyway / Cancel)" {
85
+ run awk '/^### 6\. /,/^### 7\. /' "$SKILL_FILE"
86
+ [ "$status" -eq 0 ]
87
+ [[ "$output" == *"Add evidence"* ]]
88
+ [[ "$output" == *"Record"* ]]
89
+ [[ "$output" == *"audit trail"* ]] || [[ "$output" == *"Audit trail"* ]]
90
+ [[ "$output" == *"Cancel"* ]] || [[ "$output" == *"cancel"* ]]
91
+ }
92
+
93
+ @test "SKILL.md Step 6 evidence-first gate cross-references ADR-044 category-2 (deviation-approval)" {
94
+ run awk '/^### 6\. /,/^### 7\. /' "$SKILL_FILE"
95
+ [ "$status" -eq 0 ]
96
+ [[ "$output" == *"ADR-044"* ]]
97
+ [[ "$output" == *"deviation-approval"* ]] || [[ "$output" == *"category 2"* ]] || [[ "$output" == *"category-2"* ]]
98
+ }
99
+
100
+ @test "SKILL.md Step 6 evidence-first gate documents the bypass-marker (audit-trail consistency)" {
101
+ # Aligns with mitigate-incident Step 3 (line 87): on bypass, append
102
+ # 'Evidence-gate bypassed by user — reason: <justification>' to the
103
+ # ## Audit trail section. Cross-skill consistency.
104
+ run awk '/^### 6\. /,/^### 7\. /' "$SKILL_FILE"
105
+ [ "$status" -eq 0 ]
106
+ [[ "$output" == *"bypass"* ]] || [[ "$output" == *"bypassed"* ]]
107
+ }
108
+
109
+ # ----------------------------------------------------------------------
110
+ # Surface 4 — Step 14 risk-above-appetite (cat-3 cosmetic cross-ref)
111
+ # ----------------------------------------------------------------------
112
+
113
+ @test "SKILL.md Step 14 risk-above-appetite cross-references ADR-044 category-3 (one-time-override)" {
114
+ run awk '/^### 14\. /,/^### 15\. /' "$SKILL_FILE"
115
+ [ "$status" -eq 0 ]
116
+ [[ "$output" == *"ADR-044"* ]]
117
+ [[ "$output" == *"one-time-override"* ]] || [[ "$output" == *"category 3"* ]] || [[ "$output" == *"category-3"* ]]
118
+ }
119
+
120
+ # ----------------------------------------------------------------------
121
+ # P081 + P136 bridge marker
122
+ # ----------------------------------------------------------------------
123
+
124
+ @test "bats file carries the tdd-review: structural-permitted marker" {
125
+ run grep -nE "tdd-review:[[:space:]]+structural-permitted" "${BATS_TEST_FILENAME}"
126
+ [ "$status" -eq 0 ]
127
+ }
128
+
129
+ # ----------------------------------------------------------------------
130
+ # Cross-reference: P136 audit citation in SKILL.md (Related or inline)
131
+ # ----------------------------------------------------------------------
132
+
133
+ @test "SKILL.md cites P136 + ADR-044 (audit traceability)" {
134
+ run grep -nE "P136" "$SKILL_FILE"
135
+ [ "$status" -eq 0 ]
136
+ run grep -nE "ADR-044" "$SKILL_FILE"
137
+ [ "$status" -eq 0 ]
138
+ }