@windyroad/itil 0.14.0 → 0.15.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.
@@ -0,0 +1,81 @@
1
+ ---
2
+ name: wr-itil:list-incidents
3
+ description: List active incidents from docs/incidents/ sorted by severity. Read-only display of the incident backlog — no edits, no interaction. Shown as a markdown table with ID, title, severity, and status columns.
4
+ allowed-tools: Read, Bash, Grep, Glob
5
+ ---
6
+
7
+ # List Incidents
8
+
9
+ Display the active incident backlog — investigating, mitigating, and restored incidents — sorted by severity (highest first). This skill is a pure read-only view of `docs/incidents/`; it does not edit, transition, close, or create incidents. For those operations, use the dedicated skills (`/wr-itil:manage-incident` to declare / update / mitigate / restore / close / link).
10
+
11
+ This skill is the P071 phased-landing split of `/wr-itil:manage-incident list` per ADR-010 amended Skill Granularity rule: one skill per distinct user intent. The original `/wr-itil:manage-incident list` subcommand route remains as a thin-router forwarder during the deprecation window but is scheduled for removal in `@windyroad/itil`'s next major version.
12
+
13
+ ## Scope
14
+
15
+ Included in the ranking table:
16
+ - `docs/incidents/*.investigating.md` — symptoms reported, scope being established
17
+ - `docs/incidents/*.mitigating.md` — mitigation(s) in flight
18
+ - `docs/incidents/*.restored.md` — service verified restored, awaiting close gate
19
+
20
+ `docs/incidents/*.closed.md` is omitted entirely (the view is of active incidents, not the closed archive). Closed incidents remain readable by filename convention; this skill does not index them.
21
+
22
+ **Severity, not WSJF** — per ADR-011: incidents are time-bound events where the WSJF "effort" divisor is meaningless during a live event. Severity uses Impact × Likelihood from `RISK-POLICY.md`, interpreted as "right now, what's the live business impact?". The skill surfaces the severity score from each incident file's frontmatter directly — no re-scoring, no auto-transitioning.
23
+
24
+ ## Steps
25
+
26
+ ### 1. Live scan
27
+
28
+ Enumerate the active incident files via glob:
29
+
30
+ ```bash
31
+ ls docs/incidents/*.investigating.md docs/incidents/*.mitigating.md docs/incidents/*.restored.md 2>/dev/null
32
+ ```
33
+
34
+ If the `docs/incidents/` directory does not exist or no active incidents are present, report "No active incidents." and exit.
35
+
36
+ For each matched file, read the `**Status**`, `**Severity**`, and the first-line `# Incident <I###>: <Title>` header. The severity line shape is:
37
+
38
+ ```
39
+ **Severity**: <score> (<label>) — Impact: <label> (<n>) x Likelihood: <label> (<n>)
40
+ ```
41
+
42
+ Extract the numeric `<score>` for sorting. If severity is missing, treat the incident as severity 0 and flag it so the user knows the incident file is incomplete.
43
+
44
+ ### 2. Display
45
+
46
+ Render one section:
47
+
48
+ **Active Incidents** — sorted by severity descending:
49
+
50
+ ```
51
+ | Severity | ID | Title | Status |
52
+ |----------|------|-------|--------|
53
+ | <score> | I<NNN> | <title> | <status> |
54
+ ```
55
+
56
+ If the section is empty (no active incidents), omit the table and print "No active incidents." instead.
57
+
58
+ ### 3. Trailing suggestions
59
+
60
+ After the table, print one short pointer depending on what the output showed:
61
+
62
+ - When the table is non-empty: `Run /wr-itil:manage-incident <I###> to update a specific incident, or /wr-itil:manage-incident <I###> mitigate / restored / close to advance its lifecycle.`
63
+ - When the table is empty: (no pointer needed).
64
+
65
+ ## Ownership boundary
66
+
67
+ `list-incidents` is read-only — it does not modify, rename, or commit any files. There is no README cache for incidents (unlike `docs/problems/README.md` which the `review-problems` skill maintains). Every invocation runs a live scan. If the output seems wrong, check the incident file frontmatter directly; there is no cache to refresh.
68
+
69
+ ## Related
70
+
71
+ - **P071** (`docs/problems/071-argument-based-skill-subcommands-are-not-discoverable.open.md`) — originating ticket. This skill is slice 5 of the P071 phased-landing plan.
72
+ - **ADR-010 amended** (`docs/decisions/010-rename-wr-problem-to-wr-itil.proposed.md` — Skill Granularity section) — canonical skill-split naming + forwarder contract + `deprecated-arguments: true` frontmatter flag.
73
+ - **ADR-011** (`docs/decisions/011-manage-incident-skill-wrapping.proposed.md`) — incident lifecycle file-suffix conventions (`.investigating.md` / `.mitigating.md` / `.restored.md` / `.closed.md`) + "Severity, not WSJF" rule.
74
+ - **ADR-037** (`docs/decisions/037-skill-testing-strategy.proposed.md`) — contract-assertion bats pattern applied to this skill.
75
+ - **JTBD-001** (`docs/jtbd/solo-developer/JTBD-001-enforce-governance.proposed.md`) — discoverable surface via `/wr-itil:` autocomplete.
76
+ - **JTBD-101** (`docs/jtbd/plugin-developer/JTBD-101-extend-suite.proposed.md`) — one skill per distinct user intent.
77
+ - **JTBD-201** (`docs/jtbd/tech-lead/JTBD-201-restore-service-fast.proposed.md`) — incident status visibility for audit trail.
78
+ - `packages/itil/skills/manage-incident/SKILL.md` — hosts the thin-router forwarder for the deprecated `manage-incident list` form.
79
+ - `packages/itil/skills/list-problems/SKILL.md` — slice 1 precedent; this skill mirrors its read-only display shape.
80
+
81
+ $ARGUMENTS
@@ -0,0 +1,115 @@
1
+ #!/usr/bin/env bats
2
+ # Contract assertions for /wr-itil:list-incidents (P071 split slice 5).
3
+ #
4
+ # This skill hosts the "list active incidents" user intent previously
5
+ # hidden behind /wr-itil:manage-incident list. It is a pure read-only
6
+ # display skill — no branching, no interaction, no file edits.
7
+ #
8
+ # Structural assertion — Permitted Exception to the source-grep ban
9
+ # (ADR-005 / P011 / ADR-037 contract-assertion pattern).
10
+ #
11
+ # @problem P071
12
+ # @jtbd JTBD-001 (enforce governance without slowing down — discoverable surface)
13
+ # @jtbd JTBD-101 (extend the suite with clear patterns — one skill per distinct user intent)
14
+ # @jtbd JTBD-201 (restore service fast with an audit trail — incident status visibility)
15
+ #
16
+ # Cross-reference:
17
+ # P071: docs/problems/071-argument-based-skill-subcommands-are-not-discoverable.open.md
18
+ # ADR-010 amended (Skill Granularity section) — split naming + forwarder contract
19
+ # ADR-011 — manage-incident skill-wrapping precedent (list-incidents mirrors its file conventions)
20
+ # ADR-037 — contract-assertion bats pattern
21
+
22
+ setup() {
23
+ SKILL_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
24
+ SKILL_FILE="${SKILL_DIR}/SKILL.md"
25
+ }
26
+
27
+ @test "SKILL.md exists and has frontmatter" {
28
+ [ -f "$SKILL_FILE" ]
29
+ run head -1 "$SKILL_FILE"
30
+ [ "$status" -eq 0 ]
31
+ [ "$output" = "---" ]
32
+ }
33
+
34
+ @test "SKILL.md frontmatter name is wr-itil:list-incidents (P071 + ADR-010 amended)" {
35
+ # Split naming convention per ADR-010 amendment: <verb>-<object> pair.
36
+ # The new skill's name must match the phased-landing plan pinned in P071.
37
+ run grep -n "^name: wr-itil:list-incidents$" "$SKILL_FILE"
38
+ [ "$status" -eq 0 ]
39
+ }
40
+
41
+ @test "SKILL.md frontmatter description names the list intent (P071)" {
42
+ # Description must name "list" and "incident" so Claude Code autocomplete
43
+ # surfaces the user intent rather than a generic name.
44
+ run grep -inE "^description:.*list.*incident|^description:.*incident.*list" "$SKILL_FILE"
45
+ [ "$status" -eq 0 ]
46
+ }
47
+
48
+ @test "SKILL.md frontmatter allowed-tools is read-only (P071 — read-only list display)" {
49
+ # Pure read-only list display (mirrors list-problems slice 1). No Write,
50
+ # no Edit, no AskUserQuestion. This assertion is the enforceable contract —
51
+ # future maintainers cannot accidentally grow the tool surface past the
52
+ # intent.
53
+ run grep -nE "^allowed-tools:" "$SKILL_FILE"
54
+ [ "$status" -eq 0 ]
55
+ run grep -E "^allowed-tools:.*(Write|Edit|AskUserQuestion)" "$SKILL_FILE"
56
+ [ "$status" -ne 0 ]
57
+ }
58
+
59
+ @test "SKILL.md documents the read-only scan scope (P071 + ADR-011)" {
60
+ # The skill reads the three active incident statuses per ADR-011:
61
+ # .investigating.md, .mitigating.md, and .restored.md. Closed incidents
62
+ # are omitted (the view is active backlog, not archive). The SKILL.md
63
+ # must name all three glob patterns explicitly so the contract is
64
+ # legible.
65
+ run grep -inE "\.investigating\.md" "$SKILL_FILE"
66
+ [ "$status" -eq 0 ]
67
+ run grep -inE "\.mitigating\.md" "$SKILL_FILE"
68
+ [ "$status" -eq 0 ]
69
+ run grep -inE "\.restored\.md" "$SKILL_FILE"
70
+ [ "$status" -eq 0 ]
71
+ }
72
+
73
+ @test "SKILL.md documents severity-sorted output (P071 + ADR-011)" {
74
+ # Unlike list-problems (WSJF-sorted), list-incidents is severity-sorted
75
+ # per ADR-011 "Severity, not WSJF" — incidents are time-bound events
76
+ # where effort divisor is meaningless. The SKILL.md must name severity
77
+ # as the sort key.
78
+ run grep -inE "severity" "$SKILL_FILE"
79
+ [ "$status" -eq 0 ]
80
+ }
81
+
82
+ @test "SKILL.md cites P071 and ADR-010 amended (P071 + ADR-025)" {
83
+ # ADR-025 inheritance per ADR-037: contract-assertion bats should reflect
84
+ # traceability cites on the skill spec document.
85
+ run grep -inE "P071|ADR-010" "$SKILL_FILE"
86
+ [ "$status" -eq 0 ]
87
+ }
88
+
89
+ @test "SKILL.md does not carry a deprecated-arguments frontmatter flag (clean-split skill)" {
90
+ # list-incidents is a clean-split skill with no argument-subcommands
91
+ # itself. ADR-010 amendment's `deprecated-arguments: true` flag is only
92
+ # valid on host skills with forwarder routes — list-incidents is the
93
+ # forwarder TARGET, not the host. It must NOT carry the flag.
94
+ run grep -E "^deprecated-arguments:" "$SKILL_FILE"
95
+ [ "$status" -ne 0 ]
96
+ }
97
+
98
+ @test "SKILL.md does not use word-argument subcommand branching (P071 regression guard)" {
99
+ # The whole point of P071: Claude Code autocomplete does not surface
100
+ # arguments. A clean-split skill must not reintroduce word-arg subcommand
101
+ # routing. The SKILL.md must not contain `If arguments start with "list"`
102
+ # / `If arguments contain "mitigate"` / etc. patterns.
103
+ run grep -inE "If arguments start with|If arguments contain" "$SKILL_FILE"
104
+ [ "$status" -ne 0 ]
105
+ }
106
+
107
+ @test "SKILL.md documents the ownership boundary — no README rewrite (P071)" {
108
+ # list-incidents displays active incidents but does NOT maintain a README
109
+ # cache (unlike list-problems which reads a README written by review-problems).
110
+ # For incidents, there is no README cache — the skill always runs a live
111
+ # scan. The SKILL.md must explicitly name the "read-only / no-edit" stance
112
+ # so the ownership boundary is legible to future maintainers.
113
+ run grep -inE "read-only|does not (edit|modify|rewrite|commit)" "$SKILL_FILE"
114
+ [ "$status" -eq 0 ]
115
+ }
@@ -2,6 +2,7 @@
2
2
  name: wr-itil:manage-incident
3
3
  description: Declare, triage, mitigate, and close an incident using an evidence-first workflow. Restores service first, then hands off to manage-problem for root-cause work.
4
4
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep, AskUserQuestion, Skill
5
+ deprecated-arguments: true
5
6
  ---
6
7
 
7
8
  # Incident Management Skill
@@ -71,10 +72,58 @@ Severity uses the Impact × Likelihood matrix from `RISK-POLICY.md`, interpreted
71
72
 
72
73
  Determine the operation from `$ARGUMENTS`:
73
74
 
74
- - If arguments start with "list" → show active incidents summary
75
- - If arguments start with `I<NNN>` or a bare number this is an update, mitigate, restore, close, or link
75
+ - If arguments start with "list" → **delegate to `/wr-itil:list-incidents`** via the Skill tool. See "Deprecated-argument forwarders" below.
76
+ - If arguments match `<I###> mitigate <action>` **delegate to `/wr-itil:mitigate-incident <I###> <action>`** via the Skill tool. See "Deprecated-argument forwarders" below.
77
+ - If arguments match `<I###> restored` → **delegate to `/wr-itil:restore-incident <I###>`** via the Skill tool. See "Deprecated-argument forwarders" below.
78
+ - If arguments match `<I###> close` → **delegate to `/wr-itil:close-incident <I###>`** via the Skill tool. See "Deprecated-argument forwarders" below.
79
+ - If arguments match `<I###> link P<MMM>` → **delegate to `/wr-itil:link-incident <I###> P<MMM>`** via the Skill tool. See "Deprecated-argument forwarders" below.
80
+ - If arguments start with `I<NNN>` or a bare number → this is an update
76
81
  - Otherwise → declare a new incident
77
82
 
83
+ #### Deprecated-argument forwarders (ADR-010 amended + P071)
84
+
85
+ Per ADR-010's amended Skill Granularity section, word-argument subcommands that name distinct user intents are being split into their own named skills. During the deprecation window, this skill's Step 1 parser retains the legacy argument routes as **thin-router forwarders** that re-invoke the new named skill via the Skill tool AND emit a one-line systemMessage with the canonical deprecation notice so the user learns the new invocation shape.
86
+
87
+ **Forwarder for `list`** (P071 split slice 5 — new skill `/wr-itil:list-incidents`):
88
+
89
+ When `$ARGUMENTS` contains the word `list` as a top-level argument (not inside an incident body edit), delegate to `/wr-itil:list-incidents` via the Skill tool and emit this systemMessage verbatim:
90
+
91
+ > `/wr-itil:manage-incident list is deprecated; use /wr-itil:list-incidents directly. This forwarder will be removed in @windyroad/itil's next major version.`
92
+
93
+ The forwarder does NOT re-implement the list logic locally — it invokes the Skill tool with `wr-itil:list-incidents` and returns the new skill's output verbatim. Duplicating the scan logic would harden the deprecation window into a permanent fork.
94
+
95
+ **Forwarder for `<I###> mitigate <action>`** (P071 split slice 6a — new skill `/wr-itil:mitigate-incident`):
96
+
97
+ When `$ARGUMENTS` matches the shape `<I###> mitigate <action>` (an incident ID followed by the literal word `mitigate` followed by a free-text action), delegate to `/wr-itil:mitigate-incident <I###> <action>` via the Skill tool and emit this systemMessage verbatim:
98
+
99
+ > `/wr-itil:manage-incident <I###> mitigate <action> is deprecated; use /wr-itil:mitigate-incident <I###> <action> directly. This forwarder will be removed in @windyroad/itil's next major version.`
100
+
101
+ The forwarder does NOT re-implement the mitigation logic locally — it invokes the Skill tool with `wr-itil:mitigate-incident`, passes `<I###> <action>` through as the data parameters, and returns the new skill's output verbatim. Duplicating the rename + evidence-gate + timeline-append logic would harden the deprecation window into a permanent fork. The data-parameter shape `<I###> <action>` is permitted under ADR-010 amended — only the verb word `mitigate` is being split out.
102
+
103
+ **Forwarder for `<I###> restored`** (P071 split slice 6b — new skill `/wr-itil:restore-incident`):
104
+
105
+ When `$ARGUMENTS` matches the shape `<I###> restored` (an incident ID followed by the literal word `restored`), delegate to `/wr-itil:restore-incident <I###>` via the Skill tool and emit this systemMessage verbatim:
106
+
107
+ > `/wr-itil:manage-incident <I###> restored is deprecated; use /wr-itil:restore-incident <I###> directly. This forwarder will be removed in @windyroad/itil's next major version.`
108
+
109
+ The forwarder does NOT re-implement the restore logic locally — it invokes the Skill tool with `wr-itil:restore-incident`, passes `<I###>` through as the data parameter, and returns the new skill's output verbatim. Duplicating the rename + verification-signal prompt + manage-problem handoff logic would harden the deprecation window into a permanent fork.
110
+
111
+ **Forwarder for `<I###> close`** (P071 split slice 6c — new skill `/wr-itil:close-incident`):
112
+
113
+ When `$ARGUMENTS` matches the shape `<I###> close` (an incident ID followed by the literal word `close`), delegate to `/wr-itil:close-incident <I###>` via the Skill tool and emit this systemMessage verbatim:
114
+
115
+ > `/wr-itil:manage-incident <I###> close is deprecated; use /wr-itil:close-incident <I###> directly. This forwarder will be removed in @windyroad/itil's next major version.`
116
+
117
+ The forwarder does NOT re-implement the close logic locally — it invokes the Skill tool with `wr-itil:close-incident`, passes `<I###>` through as the data parameter, and returns the new skill's output verbatim. Duplicating the linked-problem gate + rename logic would harden the deprecation window into a permanent fork.
118
+
119
+ **Forwarder for `<I###> link P<MMM>`** (P071 split slice 6d — new skill `/wr-itil:link-incident`):
120
+
121
+ When `$ARGUMENTS` matches the shape `<I###> link P<MMM>` (an incident ID followed by the literal word `link` followed by a problem ID), delegate to `/wr-itil:link-incident <I###> P<MMM>` via the Skill tool and emit this systemMessage verbatim:
122
+
123
+ > `/wr-itil:manage-incident <I###> link P<MMM> is deprecated; use /wr-itil:link-incident <I###> P<MMM> directly. This forwarder will be removed in @windyroad/itil's next major version.`
124
+
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
+
78
127
  ### 2. For new incidents: Check for duplicates FIRST
79
128
 
80
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.
@@ -158,79 +207,33 @@ ls docs/incidents/<I###>-*.md 2>/dev/null
158
207
 
159
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.
160
209
 
161
- ### 7. For mitigate: Record and transition to mitigating
162
-
163
- When the first mitigation attempt is made:
164
-
165
- 1. `git mv docs/incidents/<I###>-<title>.investigating.md docs/incidents/<I###>-<title>.mitigating.md`
166
- 2. Update the **Status** field to "Mitigating"
167
- 3. Append to **Mitigation attempts**: `[<timestamp> UTC] <action> → <outcome>` (outcome may be "pending verification" initially; update once the verification signal is known)
210
+ ### 7. For mitigate: delegate to `/wr-itil:mitigate-incident` (P071 split slice 6a)
168
211
 
169
- Pre-flight check before first mitigation: the file must contain at least one hypothesis with cited evidence. If not, block the transition and ask the user what evidence supports the chosen action.
212
+ The `mitigate` subcommand is now hosted by the `/wr-itil:mitigate-incident` skill. This step exists as a thin-router forwarder — the Step 1 parser recognises the `<I###> mitigate <action>` shape and delegates via the Skill tool. This body is intentionally empty of implementation logic; the canonical documentation of the rename, Status update, evidence-gate pre-flight, and Mitigation attempts append lives in `/wr-itil:mitigate-incident`.
170
213
 
171
- ### 8. For restore: Transition and hand off to manage-problem
214
+ Do not re-implement the rename or the evidence gate here — delegate. See "Deprecated-argument forwarders" under Step 1 for the canonical systemMessage.
172
215
 
173
- Pre-flight checks before restore:
216
+ ### 8. For restore: delegate to `/wr-itil:restore-incident` (P071 split slice 6b)
174
217
 
175
- - [ ] At least one mitigation attempt is recorded with outcome
176
- - [ ] A verification signal is captured (e.g., "error rate back to baseline per Datadog", "user reports normal", "synthetic probe passing")
218
+ The `restored` subcommand is now hosted by the `/wr-itil:restore-incident` skill. This step exists as a thin-router forwarder — the Step 1 parser recognises the `<I###> restored` shape and delegates via the Skill tool. This body is intentionally empty of implementation logic; the canonical documentation of the pre-flight checks, rename, Status update, Timeline append, and manage-problem handoff lives in `/wr-itil:restore-incident`.
177
219
 
178
- If checks pass:
179
-
180
- 1. `git mv docs/incidents/<I###>-<title>.mitigating.md docs/incidents/<I###>-<title>.restored.md`
181
- 2. Update the **Status** field to "Restored"
182
- 3. Append to **Timeline**: `[<timestamp> UTC] Service restored — <verification signal>`
183
-
184
- Then perform the **handoff to problem management**:
185
-
186
- 1. Ask via `AskUserQuestion`: "Service restored. Should I create or update a problem record for the root cause? (a) yes — recommended, (b) no — document why (trivial/one-off)"
187
- 2. If yes, construct a handoff payload:
188
- - Incident ID and title
189
- - Timeline summary
190
- - Top-ranked hypothesis + cited evidence
191
- - Mitigation applied + verification signal
192
- 3. Invoke `wr-itil:manage-problem` via the `Skill` tool with the payload as arguments. The problem skill's existing dedupe flow handles new-vs-update.
193
- 4. Capture the returned `P<NNN>` and write a **Linked Problem** section into the incident file:
194
- ```markdown
195
- ## Linked Problem
196
- P<NNN> (<title>) — <status>
197
- ```
198
- 5. If the user chose "no", write a **No Problem** section with the justification and skip the handoff:
199
- ```markdown
200
- ## No Problem
201
- <reason — e.g. "one-off cosmic-bit-flip; not reproducible">
202
- ```
203
-
204
- ### 9. For close: Gate on linked problem status
205
-
206
- The close operation checks the linked problem's file suffix:
207
-
208
- ```bash
209
- linked_id=<extracted from Linked Problem section>
210
- linked_file=$(ls docs/problems/${linked_id}-*.md 2>/dev/null | head -1)
211
- ```
220
+ Do not re-implement the rename or the problem handoff here — delegate. See "Deprecated-argument forwarders" under Step 1 for the canonical systemMessage.
212
221
 
213
- - If `linked_file` ends with `.known-error.md`, `.verifying.md`, or `.closed.md` → close is allowed (per ADR-022: `.verifying.md` means root cause is confirmed AND fix has been released, which satisfies the "Restored → Closed" handoff at least as well as Known Error did under the old contract)
214
- - If `linked_file` ends with `.open.md` → close is blocked; report "Linked problem ${linked_id} is still Open. Transition it to Known Error first, or update the Linked Problem reference."
215
- - If no linked problem and the file has a **No Problem** section → close is allowed
222
+ ### 9. For close: delegate to `/wr-itil:close-incident` (P071 split slice 6c)
216
223
 
217
- On close:
224
+ The `close` subcommand is now hosted by the `/wr-itil:close-incident` skill. This step exists as a thin-router forwarder — the Step 1 parser recognises the `<I###> close` shape and delegates via the Skill tool. This body is intentionally empty of implementation logic; the canonical documentation of the Linked-Problem gate (accepting `.known-error.md`, `.verifying.md`, and `.closed.md`), the No Problem bypass, and the rename lives in `/wr-itil:close-incident`.
218
225
 
219
- 1. `git mv docs/incidents/<I###>-<title>.restored.md docs/incidents/<I###>-<title>.closed.md`
220
- 2. Update the **Status** field to "Closed"
221
- 3. Append to **Timeline**: `[<timestamp> UTC] Incident closed`
226
+ Do not re-implement the close gate or the rename here — delegate. See "Deprecated-argument forwarders" under Step 1 for the canonical systemMessage.
222
227
 
223
228
  ### 10. For list: Show active incidents
224
229
 
225
230
  Read all `.investigating.md`, `.mitigating.md`, and `.restored.md` files in `docs/incidents/`. Extract ID, title, severity, and status. Sort by severity (highest first). Display as a markdown table.
226
231
 
227
- ### 11. For link: Attach a problem
232
+ ### 11. For link: delegate to `/wr-itil:link-incident` (P071 split slice 6d)
228
233
 
229
- When the user runs `incident <I###> link P<MMM>`:
234
+ The `link` subcommand is now hosted by the `/wr-itil:link-incident` skill. This step exists as a thin-router forwarder — the Step 1 parser recognises the `<I###> link P<MMM>` shape and delegates via the Skill tool. This body is intentionally empty of implementation logic; the canonical documentation of the problem-file lookup and the `## Linked Problem` section write (including the retroactive-link-from-No-Problem case) lives in `/wr-itil:link-incident`.
230
235
 
231
- 1. Verify `docs/problems/P<MMM>-*.md` exists
232
- 2. Read or add the **Linked Problem** section with `P<MMM> (<title>) — <status>`
233
- 3. Report the link
236
+ Do not re-implement the link logic here — delegate. See "Deprecated-argument forwarders" under Step 1 for the canonical systemMessage.
234
237
 
235
238
  ### 12. Edge cases
236
239
 
@@ -0,0 +1,67 @@
1
+ #!/usr/bin/env bats
2
+ # Contract assertions for manage-incident's `close` subcommand forwarder (P071 split slice 6c).
3
+ #
4
+ # Per ADR-010 amended (Skill Granularity section) + P071 phased plan:
5
+ # `/wr-itil:manage-incident <I> close` delegates to the new
6
+ # `/wr-itil:close-incident <I>` skill via a thin-router forwarder.
7
+ # Original skill already carries `deprecated-arguments: true` frontmatter
8
+ # (slice 5); forwarder emits a canonical one-line systemMessage
9
+ # deprecation notice.
10
+ #
11
+ # Structural assertion — Permitted Exception to the source-grep ban
12
+ # (ADR-005 / P011 / ADR-037 contract-assertion pattern).
13
+ #
14
+ # @problem P071
15
+ # @jtbd JTBD-001 (enforce governance without slowing down)
16
+ # @jtbd JTBD-101 (extend the suite with clear patterns)
17
+ # @jtbd JTBD-201 (restore service fast with an audit trail)
18
+ #
19
+ # Cross-reference:
20
+ # P071: docs/problems/071-argument-based-skill-subcommands-are-not-discoverable.open.md
21
+ # ADR-010 amended — split naming + forwarder contract + deprecated-arguments flag
22
+ # ADR-011 — manage-incident skill-wrapping precedent (close gate on linked problem)
23
+ # ADR-022 — problem lifecycle verification-pending status (.verifying.md allowance)
24
+ # ADR-013 Rule 1 — structured user interaction (forwarder emits systemMessage, not AskUserQuestion)
25
+ # ADR-037 — contract-assertion bats pattern
26
+
27
+ setup() {
28
+ SKILL_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
29
+ SKILL_FILE="${SKILL_DIR}/SKILL.md"
30
+ }
31
+
32
+ @test "manage-incident SKILL.md frontmatter has deprecated-arguments: true (ADR-010 amended)" {
33
+ # Already pinned by slice 5; slice 6c inherits. Guard against regression.
34
+ run grep -nE "^deprecated-arguments:[[:space:]]*true[[:space:]]*$" "$SKILL_FILE"
35
+ [ "$status" -eq 0 ]
36
+ }
37
+
38
+ @test "manage-incident Step 1 forwards 'close' argument to /wr-itil:close-incident (P071)" {
39
+ # The forwarder names the target skill explicitly so the router is legible
40
+ # at the contract level. ADR-010's canonical shape: "invokes the new
41
+ # named skill via the Skill tool, not via re-prompting the user".
42
+ run grep -inE "/wr-itil:close-incident" "$SKILL_FILE"
43
+ [ "$status" -eq 0 ]
44
+ }
45
+
46
+ @test "manage-incident Step 1 emits the canonical close deprecation notice (ADR-010 amended)" {
47
+ # ADR-010's canonical deprecation-notice template:
48
+ # "/wr-<plugin>:<old> <arg> is deprecated; use /wr-<plugin>:<new>
49
+ # directly. This forwarder will be removed in <plugin>'s next major
50
+ # version."
51
+ # The notice MUST be emitted as a systemMessage (not AskUserQuestion)
52
+ # because deprecation is informational, not decisional (ADR-013 Rule 1
53
+ # structured-interaction scope).
54
+ run grep -inE "is deprecated.*use /wr-itil:close-incident|deprecated.*close-incident|close.*removed in .* next major version" "$SKILL_FILE"
55
+ [ "$status" -eq 0 ]
56
+ }
57
+
58
+ @test "manage-incident Step 1 close forwarder delegates via Skill tool (P071 regression guard)" {
59
+ # The forwarder must not duplicate the close logic — it must delegate.
60
+ # Per ADR-010: "thin-router forwarder re-invokes the new named skill
61
+ # via the Skill tool". If the forwarder grows its own gate + rename
62
+ # logic, the deprecation window will harden into a permanent fork.
63
+ # Guard against this by asserting the forwarder block mentions "delegate"
64
+ # or "Skill tool" language near the close-incident reference.
65
+ run grep -inE "delegate.*close-incident|Skill tool.*close-incident|close-incident.*Skill tool" "$SKILL_FILE"
66
+ [ "$status" -eq 0 ]
67
+ }
@@ -0,0 +1,67 @@
1
+ #!/usr/bin/env bats
2
+ # Contract assertions for manage-incident's `link` subcommand forwarder (P071 split slice 6d).
3
+ #
4
+ # Per ADR-010 amended (Skill Granularity section) + P071 phased plan:
5
+ # `/wr-itil:manage-incident <I> link P<M>` delegates to the new
6
+ # `/wr-itil:link-incident <I> P<M>` skill via a thin-router forwarder.
7
+ # Original skill already carries `deprecated-arguments: true` frontmatter
8
+ # (slice 5); forwarder emits a canonical one-line systemMessage
9
+ # deprecation notice.
10
+ #
11
+ # Structural assertion — Permitted Exception to the source-grep ban
12
+ # (ADR-005 / P011 / ADR-037 contract-assertion pattern).
13
+ #
14
+ # @problem P071
15
+ # @jtbd JTBD-001 (enforce governance without slowing down)
16
+ # @jtbd JTBD-101 (extend the suite with clear patterns)
17
+ # @jtbd JTBD-201 (restore service fast with an audit trail)
18
+ #
19
+ # Cross-reference:
20
+ # P071: docs/problems/071-argument-based-skill-subcommands-are-not-discoverable.open.md
21
+ # ADR-010 amended — split naming + forwarder contract + deprecated-arguments flag
22
+ # ADR-011 — manage-incident skill-wrapping precedent (Linked Problem section)
23
+ # ADR-013 Rule 1 — structured user interaction (forwarder emits systemMessage, not AskUserQuestion)
24
+ # ADR-037 — contract-assertion bats pattern
25
+
26
+ setup() {
27
+ SKILL_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
28
+ SKILL_FILE="${SKILL_DIR}/SKILL.md"
29
+ }
30
+
31
+ @test "manage-incident SKILL.md frontmatter has deprecated-arguments: true (ADR-010 amended)" {
32
+ # Already pinned by slice 5; slice 6d inherits. Guard against regression.
33
+ run grep -nE "^deprecated-arguments:[[:space:]]*true[[:space:]]*$" "$SKILL_FILE"
34
+ [ "$status" -eq 0 ]
35
+ }
36
+
37
+ @test "manage-incident Step 1 forwards 'link' argument to /wr-itil:link-incident (P071)" {
38
+ # The forwarder names the target skill explicitly so the router is legible
39
+ # at the contract level. ADR-010's canonical shape: "invokes the new
40
+ # named skill via the Skill tool, not via re-prompting the user".
41
+ run grep -inE "/wr-itil:link-incident" "$SKILL_FILE"
42
+ [ "$status" -eq 0 ]
43
+ }
44
+
45
+ @test "manage-incident Step 1 emits the canonical link deprecation notice (ADR-010 amended)" {
46
+ # ADR-010's canonical deprecation-notice template:
47
+ # "/wr-<plugin>:<old> <arg> is deprecated; use /wr-<plugin>:<new>
48
+ # directly. This forwarder will be removed in <plugin>'s next major
49
+ # version."
50
+ # The notice MUST be emitted as a systemMessage (not AskUserQuestion)
51
+ # because deprecation is informational, not decisional (ADR-013 Rule 1
52
+ # structured-interaction scope).
53
+ run grep -inE "is deprecated.*use /wr-itil:link-incident|deprecated.*link-incident|link.*removed in .* next major version" "$SKILL_FILE"
54
+ [ "$status" -eq 0 ]
55
+ }
56
+
57
+ @test "manage-incident Step 1 link forwarder delegates via Skill tool (P071 regression guard)" {
58
+ # The forwarder must not duplicate the link logic — it must delegate.
59
+ # Per ADR-010: "thin-router forwarder re-invokes the new named skill
60
+ # via the Skill tool". If the forwarder grows its own problem-file-lookup
61
+ # + Linked Problem write logic, the deprecation window will harden into
62
+ # a permanent fork. Guard against this by asserting the forwarder block
63
+ # mentions "delegate" or "Skill tool" language near the link-incident
64
+ # reference.
65
+ run grep -inE "delegate.*link-incident|Skill tool.*link-incident|link-incident.*Skill tool" "$SKILL_FILE"
66
+ [ "$status" -eq 0 ]
67
+ }
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env bats
2
+ # Contract assertions for manage-incident's `list` subcommand forwarder (P071 split slice 5).
3
+ #
4
+ # Per ADR-010 amended (Skill Granularity section) + P071 phased plan:
5
+ # `/wr-itil:manage-incident list` delegates to the new `/wr-itil:list-incidents`
6
+ # skill via a thin-router forwarder. Original skill carries
7
+ # `deprecated-arguments: true` frontmatter; forwarder emits a
8
+ # canonical one-line systemMessage deprecation notice.
9
+ #
10
+ # Structural assertion — Permitted Exception to the source-grep ban
11
+ # (ADR-005 / P011 / ADR-037 contract-assertion pattern).
12
+ #
13
+ # @problem P071
14
+ # @jtbd JTBD-001 (enforce governance without slowing down)
15
+ # @jtbd JTBD-101 (extend the suite with clear patterns)
16
+ # @jtbd JTBD-201 (restore service fast with an audit trail)
17
+ #
18
+ # Cross-reference:
19
+ # P071: docs/problems/071-argument-based-skill-subcommands-are-not-discoverable.open.md
20
+ # ADR-010 amended — split naming + forwarder contract + deprecated-arguments flag
21
+ # ADR-011 — manage-incident skill-wrapping precedent
22
+ # ADR-013 Rule 1 — structured user interaction (forwarder emits systemMessage, not AskUserQuestion)
23
+ # ADR-037 — contract-assertion bats pattern
24
+
25
+ setup() {
26
+ SKILL_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
27
+ SKILL_FILE="${SKILL_DIR}/SKILL.md"
28
+ }
29
+
30
+ @test "manage-incident SKILL.md frontmatter has deprecated-arguments: true (ADR-010 amended)" {
31
+ # ADR-010 amendment pins the frontmatter flag name as `deprecated-arguments`.
32
+ # The host skill of any forwarder route must carry this flag so ADR-037
33
+ # cross-plugin contract assertions can find the opt-in during the
34
+ # deprecation window.
35
+ run grep -nE "^deprecated-arguments:[[:space:]]*true[[:space:]]*$" "$SKILL_FILE"
36
+ [ "$status" -eq 0 ]
37
+ }
38
+
39
+ @test "manage-incident Step 1 forwards 'list' argument to /wr-itil:list-incidents (P071)" {
40
+ # The forwarder names the target skill explicitly so the router is legible
41
+ # at the contract level. ADR-010's canonical shape: "invokes the new
42
+ # named skill via the Skill tool, not via re-prompting the user".
43
+ run grep -inE "/wr-itil:list-incidents" "$SKILL_FILE"
44
+ [ "$status" -eq 0 ]
45
+ }
46
+
47
+ @test "manage-incident Step 1 emits the canonical deprecation notice (ADR-010 amended)" {
48
+ # ADR-010's canonical deprecation-notice template:
49
+ # "/wr-<plugin>:<old> <arg> is deprecated; use /wr-<plugin>:<new>
50
+ # directly. This forwarder will be removed in <plugin>'s next major
51
+ # version."
52
+ # The notice MUST be emitted as a systemMessage (not AskUserQuestion)
53
+ # because deprecation is informational, not decisional (ADR-013 Rule 1
54
+ # structured-interaction scope).
55
+ run grep -inE "is deprecated.*use /wr-itil:list-incidents|deprecated.*list-incidents|removed in .* next major version" "$SKILL_FILE"
56
+ [ "$status" -eq 0 ]
57
+ }
58
+
59
+ @test "manage-incident Step 1 forwarder does not re-implement the list logic (P071 regression guard)" {
60
+ # The forwarder must not duplicate the list logic — it must delegate.
61
+ # Per ADR-010: "thin-router forwarder re-invokes the new named skill
62
+ # via the Skill tool". If the forwarder grows its own scan logic, the
63
+ # deprecation window will harden into a permanent fork. Guard against
64
+ # this by asserting the forwarder block mentions "delegate" or
65
+ # "Skill tool" language near the list-incidents reference.
66
+ run grep -inE "delegate.*list-incidents|Skill tool.*list-incidents|list-incidents.*Skill tool" "$SKILL_FILE"
67
+ [ "$status" -eq 0 ]
68
+ }
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/env bats
2
+ # Contract assertions for manage-incident's `mitigate` subcommand forwarder (P071 split slice 6a).
3
+ #
4
+ # Per ADR-010 amended (Skill Granularity section) + P071 phased plan:
5
+ # `/wr-itil:manage-incident <I> mitigate <action>` delegates to the new
6
+ # `/wr-itil:mitigate-incident <I> <action>` skill via a thin-router
7
+ # forwarder. Original skill already carries `deprecated-arguments: true`
8
+ # frontmatter (slice 5); forwarder emits a canonical one-line systemMessage
9
+ # deprecation notice.
10
+ #
11
+ # Structural assertion — Permitted Exception to the source-grep ban
12
+ # (ADR-005 / P011 / ADR-037 contract-assertion pattern).
13
+ #
14
+ # @problem P071
15
+ # @jtbd JTBD-001 (enforce governance without slowing down)
16
+ # @jtbd JTBD-101 (extend the suite with clear patterns)
17
+ # @jtbd JTBD-201 (restore service fast with an audit trail)
18
+ #
19
+ # Cross-reference:
20
+ # P071: docs/problems/071-argument-based-skill-subcommands-are-not-discoverable.open.md
21
+ # ADR-010 amended — split naming + forwarder contract + deprecated-arguments flag
22
+ # ADR-011 — manage-incident skill-wrapping precedent
23
+ # ADR-013 Rule 1 — structured user interaction (forwarder emits systemMessage, not AskUserQuestion)
24
+ # ADR-037 — contract-assertion bats pattern
25
+
26
+ setup() {
27
+ SKILL_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
28
+ SKILL_FILE="${SKILL_DIR}/SKILL.md"
29
+ }
30
+
31
+ @test "manage-incident SKILL.md frontmatter has deprecated-arguments: true (ADR-010 amended)" {
32
+ # Already pinned by slice 5; slice 6a inherits. Guard against regression.
33
+ run grep -nE "^deprecated-arguments:[[:space:]]*true[[:space:]]*$" "$SKILL_FILE"
34
+ [ "$status" -eq 0 ]
35
+ }
36
+
37
+ @test "manage-incident Step 1 forwards 'mitigate' argument to /wr-itil:mitigate-incident (P071)" {
38
+ # The forwarder names the target skill explicitly so the router is legible
39
+ # at the contract level. ADR-010's canonical shape: "invokes the new
40
+ # named skill via the Skill tool, not via re-prompting the user".
41
+ run grep -inE "/wr-itil:mitigate-incident" "$SKILL_FILE"
42
+ [ "$status" -eq 0 ]
43
+ }
44
+
45
+ @test "manage-incident Step 1 emits the canonical mitigate deprecation notice (ADR-010 amended)" {
46
+ # ADR-010's canonical deprecation-notice template:
47
+ # "/wr-<plugin>:<old> <arg> is deprecated; use /wr-<plugin>:<new>
48
+ # directly. This forwarder will be removed in <plugin>'s next major
49
+ # version."
50
+ # The notice MUST be emitted as a systemMessage (not AskUserQuestion)
51
+ # because deprecation is informational, not decisional (ADR-013 Rule 1
52
+ # structured-interaction scope).
53
+ run grep -inE "is deprecated.*use /wr-itil:mitigate-incident|deprecated.*mitigate-incident|mitigate.*removed in .* next major version" "$SKILL_FILE"
54
+ [ "$status" -eq 0 ]
55
+ }
56
+
57
+ @test "manage-incident Step 1 mitigate forwarder delegates via Skill tool (P071 regression guard)" {
58
+ # The forwarder must not duplicate the mitigate logic — it must delegate.
59
+ # Per ADR-010: "thin-router forwarder re-invokes the new named skill
60
+ # via the Skill tool". If the forwarder grows its own rename + evidence-gate
61
+ # logic, the deprecation window will harden into a permanent fork.
62
+ # Guard against this by asserting the forwarder block mentions "delegate"
63
+ # or "Skill tool" language near the mitigate-incident reference.
64
+ run grep -inE "delegate.*mitigate-incident|Skill tool.*mitigate-incident|mitigate-incident.*Skill tool" "$SKILL_FILE"
65
+ [ "$status" -eq 0 ]
66
+ }