@windyroad/itil 0.8.0 → 0.9.0-preview.142

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.8.0",
3
+ "version": "0.9.0",
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.8.0",
3
+ "version": "0.9.0-preview.142",
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"
@@ -39,9 +39,10 @@ The `.verifying.md` suffix distinguishes "fix released, awaiting user verificati
39
39
  | **Closed** | `.closed.md` | Fix verified in production | User explicitly confirms the released fix works |
40
40
 
41
41
  **Parked problems** are excluded from WSJF ranking and work selection. They are listed separately in review output so users can see them without them polluting the backlog. To park a problem:
42
- 1. `git mv docs/problems/<NNN>-<title>.<current>.md docs/problems/<NNN>-<title>.parked.md`
43
- 2. Update the Status field to "Parked"
44
- 3. Add a `## Parked` section with: reason for parking, expected trigger to un-park, date parked
42
+ 1. **If the park reason is `upstream-blocked`**, run the external-root-cause detection block at Step 7 first (see "External-root-cause detection (P063)"). Park without recording the upstream dependency in `## Related` would be the canonical audit-trail gap this block closes.
43
+ 2. `git mv docs/problems/<NNN>-<title>.<current>.md docs/problems/<NNN>-<title>.parked.md`
44
+ 3. Update the Status field to "Parked"
45
+ 4. Add a `## Parked` section with: reason for parking, expected trigger to un-park, date parked
45
46
 
46
47
  To un-park: `git mv` back to `.open.md` (or `.known-error.md` if root cause is confirmed), update Status, remove `## Parked` section.
47
48
 
@@ -279,6 +280,45 @@ Pre-flight checks before allowing transition:
279
280
 
280
281
  If any check fails, report which checks failed and ask the user to address them before transitioning.
281
282
 
283
+ #### External-root-cause detection (P063)
284
+
285
+ Before renaming the file, scan the ticket's Root Cause Analysis section for external-root-cause markers. The same detection fires when parking a ticket with the `upstream-blocked` reason (see the Parked lifecycle entry at the top of this skill — it routes back to this block).
286
+
287
+ **Strict detection tokens** (any of the following within the Root Cause Analysis section counts as a hit):
288
+
289
+ - Literal label words: `upstream`, `third-party`, `external`, `vendor`.
290
+ - Scoped npm package pattern: `@[\w-]+/[\w-]+` (e.g. `@anthropic/claude-code`, `@windyroad/itil`).
291
+
292
+ Bash heuristic:
293
+
294
+ ```bash
295
+ if grep -iE '\b(upstream|third-party|external|vendor)\b|@[[:alnum:]_-]+/[[:alnum:]_-]+' "$problem_file"; then
296
+ external_root_cause_detected=1
297
+ fi
298
+ ```
299
+
300
+ Detection is intentionally **strict** (explicit label or scoped-npm package only) to avoid prompt fatigue (P063 Direction decision). A passing reference to a bare package name (`gh`, `npm`) does NOT trigger the prompt.
301
+
302
+ **Already-noted check** — before firing the prompt, grep the ticket for the stable marker `- **Upstream report pending** —` (written by option 2 / the AFK fallback below) or `- **Reported Upstream:**` / a `## Reported Upstream` section (written by `/wr-itil:report-upstream` Step 7 back-write per ADR-024 Confirmation criterion 3a). If any of those are already present, skip the prompt — the detection has already fired on a prior run.
303
+
304
+ **If the detection fires and nothing has been noted yet**, use `AskUserQuestion`:
305
+
306
+ - `header: "External root cause detected"`
307
+ - `multiSelect: false`
308
+ - Options:
309
+ 1. `Invoke /wr-itil:report-upstream now` — halt the transition; the skill runs (it writes the `## Reported Upstream` appendage per ADR-024 Confirmation criterion 3a); the transition resumes afterwards.
310
+ 2. `Defer and note in ticket` — append a pending-upstream-report line to the ticket's `## Related` section using the stable marker `- **Upstream report pending** — external dependency identified; invoke /wr-itil:report-upstream when ready`. The marker wording is fixed so subsequent runs (and the work-problems `upstream-blocked` skip path) can detect "already noted" without re-firing.
311
+ 3. `Not actually upstream` — proceed without invocation; append the same marker with text `- **Upstream report pending** — false positive; detection misfire` so the prompt does not re-fire on later reviews.
312
+
313
+ **Non-interactive (AFK) branch** (per ADR-013 Rule 6): when `AskUserQuestion` is unavailable, default to option 2 — append the pending-upstream-report line with the stable `- **Upstream report pending** —` marker. Do NOT auto-invoke `/wr-itil:report-upstream`; its Step 6 security-path branch is interactive and would halt the orchestrator anyway (per ADR-024 Consequences). The appended line lets the user see the deferred action when they return.
314
+
315
+ **Scope**: this detection block fires at two points —
316
+
317
+ - **Open → Known Error transition** (this step, primary insertion point).
318
+ - **Parking path with `upstream-blocked` reason** — the parking workflow runs the same detection before `git mv` to `.parked.md`. Parking an upstream-blocked ticket without having noted (or reported) the upstream dependency is the canonical audit-trail gap this block closes.
319
+
320
+ The work-problems orchestrator's `upstream-blocked` skip path (see `packages/itil/skills/work-problems/SKILL.md` classifier table) runs the AFK fallback before skipping, so ticket bodies accumulate the marker even when the orchestrator never invokes `manage-problem` on them.
321
+
282
322
  > **Staging trap (P057).** `git mv` stages only the rename — it does NOT pick up subsequent `Edit`-tool content changes. After the `Edit` tool modifies the renamed file (Status field, `## Fix Released` section, etc.), re-stage it explicitly: `git add <new>`. Without the explicit re-stage, the transition commit captures the rename-only change and the content edit leaks into the next commit, corrupting the audit trail. This rule applies to every `git mv` block below (Open → Known Error, Known Error → Verification Pending, Verification Pending → Closed) and to the supersession rename in `create-adr` Step 6.
283
323
 
284
324
  ```bash
@@ -319,6 +359,24 @@ git add docs/problems/<NNN>-<title>.closed.md
319
359
 
320
360
  Update the "Status" field to "Closed". Reference the problem ID in the closure commit message (e.g., "Closes P008"). Step 9d's verification prompt is the structured path that fires this transition during `manage-problem review`. Re-stage the `.closed.md` file explicitly after the Edit (P057 staging trap).
321
361
 
362
+ #### README.md refresh on every transition (P062)
363
+
364
+ Every Step 7 status transition (Open → Known Error, Known Error → Verification Pending, Verification Pending → Closed, Parked — regardless of source or destination suffix) regenerates `docs/problems/README.md` and stages it in the same commit so the dev-work table, Verification Queue, Parked section, and "Last reviewed" line never lag the on-disk ticket inventory. Without this step, README.md accumulates staleness between `review` invocations; the next `work` fast-path check correctly detects the lag and forces a full rescan (self-healing but wasteful), and any human browsing the file between transitions sees outdated rankings.
365
+
366
+ The refresh uses the same rendering rules as Step 9e (glob `docs/problems/*.open.md` / `*.known-error.md` / `*.verifying.md` / `*.parked.md`; rank open/known-error by WSJF; list verifyings in the Verification Queue ordered by release age; list parkeds in the Parked section) but skips the full re-scoring pass — existing WSJF values on the ticket files are trusted. The refresh is a render, not a re-rank.
367
+
368
+ **Mechanism:**
369
+
370
+ 1. After renaming + Editing + `git add`-ing the transitioned ticket file (per the staging-trap rule above), regenerate `docs/problems/README.md` in-place reflecting the new filename set and the transitioned ticket's new Status.
371
+ 2. `git add docs/problems/README.md` — stage the refreshed README with the same commit as the transition.
372
+ 3. Update the "Last reviewed" line's parenthetical to name the transition (e.g. `P<NNN> <status> — <one-line fix summary>`) so the next session's fast-path check has a human-readable audit marker alongside the git-history staleness test.
373
+
374
+ **Scope**: fires for every Step 7 rename. Applies equally to:
375
+ - Standalone transition commits (e.g. `docs(problems): P<NNN> known error — <summary>`).
376
+ - **Folded-fix commits** where the `.verifying.md` transition rides with the fix implementation commit (e.g. `fix(<scope>): <description> (closes P<NNN>)` — per Step 11's convention for Known Error → Verification Pending). In both cases the refreshed README.md joins the same commit as the rename + content edit; never split across commits.
377
+
378
+ **Fast-path interaction**: the Step 9 fast-path freshness check (`git log -1 --format=%H -- docs/problems/README.md` followed by `git log --oneline "${readme_commit}..HEAD" -- 'docs/problems/*.md'`) remains the authoritative staleness test. When this refresh fires on every transition, that check should return empty on any subsequent invocation — the cache stays fresh by construction. If the check still reports "stale", something skipped the refresh (bug) and the slow-path is the correct recovery.
379
+
322
380
  ### 8. For list: Show summary
323
381
 
324
382
  Read all `.open.md` and `.known-error.md` files in `docs/problems/`. Extract ID, title, priority, and status. Sort by priority (highest first). Display as a markdown table.
@@ -480,7 +538,7 @@ After any operation, report:
480
538
  - Any quality check warnings
481
539
 
482
540
  Commit the completed work per ADR-014 (governance skills commit their own work):
483
- 1. `git add` all created/modified files for this operation — **including any file renamed via `git mv` that was then modified by the `Edit` tool** (P057 staging trap — `git mv` alone stages only the rename, not the subsequent content edit). `git add -u` is a safe catch-all for tracked modifications.
541
+ 1. `git add` all created/modified files for this operation — **including any file renamed via `git mv` that was then modified by the `Edit` tool** (P057 staging trap — `git mv` alone stages only the rename, not the subsequent content edit). `git add -u` is a safe catch-all for tracked modifications. **For any Step 7 status transition** (Open → Known Error, Known Error → Verification Pending, Verification Pending → Closed, or Parked) — including folded-fix commits where the `.verifying.md` transition rides with a `fix(<scope>): ...` commit — the stage list MUST include `docs/problems/README.md` refreshed per Step 7's "README.md refresh on every transition" block (P062). Skipping the refresh leaks staleness to the next session's fast-path.
484
542
  2. Satisfy the commit gate — two paths are valid (either produces a bypass marker):
485
543
  - **Primary**: delegate to the `wr-risk-scorer:pipeline` subagent-type via the Agent tool (subagent_type: `wr-risk-scorer:pipeline`)
486
544
  - **Fallback**: if the `wr-risk-scorer:pipeline` subagent-type is not available in the current tool set (e.g., this skill is itself running inside a spawned subagent), invoke the `/wr-risk-scorer:assess-release` skill via the Skill tool. Per ADR-015 it wraps the same pipeline subagent and the `PostToolUse:Agent` hook writes an equivalent bypass marker. Do not silently skip the gate because the primary path is unavailable — the fallback exists specifically to close this gap (see P035).
@@ -0,0 +1,98 @@
1
+ #!/usr/bin/env bats
2
+
3
+ # P063: manage-problem SKILL.md documents the external-root-cause
4
+ # detection block that triggers /wr-itil:report-upstream (ADR-024)
5
+ # when root cause is external.
6
+ #
7
+ # Doc-lint structural test (Permitted Exception per ADR-005) — asserts
8
+ # SKILL.md wording for detection tokens, AskUserQuestion three-option
9
+ # prompt, AFK fallback, and the stable `- **Upstream report pending** —`
10
+ # marker. Mirrors work-problems-release-cadence.bats and
11
+ # report-upstream-contract.bats patterns.
12
+
13
+ setup() {
14
+ REPO_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../../../../.." && pwd)"
15
+ MP_SKILL="$REPO_ROOT/packages/itil/skills/manage-problem/SKILL.md"
16
+ WP_SKILL="$REPO_ROOT/packages/itil/skills/work-problems/SKILL.md"
17
+ }
18
+
19
+ @test "manage-problem: SKILL.md contains the External-root-cause detection block (P063)" {
20
+ run grep -F 'External-root-cause detection (P063)' "$MP_SKILL"
21
+ [ "$status" -eq 0 ]
22
+ }
23
+
24
+ @test "manage-problem: SKILL.md documents strict detection tokens (upstream, third-party, external, vendor)" {
25
+ run grep -F '`upstream`, `third-party`, `external`, `vendor`' "$MP_SKILL"
26
+ [ "$status" -eq 0 ]
27
+ }
28
+
29
+ @test "manage-problem: SKILL.md documents the scoped-npm detection pattern" {
30
+ run grep -F '@[\w-]+/[\w-]+' "$MP_SKILL"
31
+ [ "$status" -eq 0 ]
32
+ }
33
+
34
+ @test "manage-problem: SKILL.md documents the three AskUserQuestion options (invoke / defer / false positive)" {
35
+ run grep -F 'Invoke /wr-itil:report-upstream now' "$MP_SKILL"
36
+ [ "$status" -eq 0 ]
37
+ run grep -F 'Defer and note in ticket' "$MP_SKILL"
38
+ [ "$status" -eq 0 ]
39
+ run grep -F 'Not actually upstream' "$MP_SKILL"
40
+ [ "$status" -eq 0 ]
41
+ }
42
+
43
+ @test "manage-problem: SKILL.md defines the stable Upstream report pending marker with fixed wording" {
44
+ run grep -F -- '- **Upstream report pending** — external dependency identified; invoke /wr-itil:report-upstream when ready' "$MP_SKILL"
45
+ [ "$status" -eq 0 ]
46
+ }
47
+
48
+ @test "manage-problem: SKILL.md documents the AFK non-interactive fallback (option 2, append marker, no auto-invoke)" {
49
+ run grep -iE 'non-interactive.*afk|afk.*fallback' "$MP_SKILL"
50
+ [ "$status" -eq 0 ]
51
+ # Explicit ban on auto-invoke
52
+ run grep -F 'Do NOT auto-invoke' "$MP_SKILL"
53
+ [ "$status" -eq 0 ]
54
+ }
55
+
56
+ @test "manage-problem: SKILL.md documents the already-noted check to avoid duplicate prompts" {
57
+ run grep -F 'Already-noted check' "$MP_SKILL"
58
+ [ "$status" -eq 0 ]
59
+ }
60
+
61
+ @test "manage-problem: SKILL.md documents both insertion points (Open → Known Error AND upstream-blocked park)" {
62
+ run grep -F 'Open → Known Error transition' "$MP_SKILL"
63
+ [ "$status" -eq 0 ]
64
+ run grep -F 'Parking path with `upstream-blocked` reason' "$MP_SKILL"
65
+ [ "$status" -eq 0 ]
66
+ }
67
+
68
+ @test "manage-problem: Parked lifecycle entry cross-references the external-root-cause detection block" {
69
+ run grep -F 'If the park reason is `upstream-blocked`' "$MP_SKILL"
70
+ [ "$status" -eq 0 ]
71
+ }
72
+
73
+ @test "manage-problem: SKILL.md references ADR-024 and ADR-013 Rule 6 in the detection block" {
74
+ run grep -F 'ADR-024 Confirmation criterion 3a' "$MP_SKILL"
75
+ [ "$status" -eq 0 ]
76
+ run grep -F 'ADR-013 Rule 6' "$MP_SKILL"
77
+ [ "$status" -eq 0 ]
78
+ }
79
+
80
+ @test "work-problems: upstream-blocked skip row runs the AFK fallback before skipping" {
81
+ run grep -F 'append the pending-upstream-report marker' "$WP_SKILL"
82
+ [ "$status" -eq 0 ]
83
+ }
84
+
85
+ @test "work-problems: upstream-blocked taxonomy entry documents the AFK fallback" {
86
+ run grep -F 'Before skipping, run the manage-problem external-root-cause detection AFK fallback' "$WP_SKILL"
87
+ [ "$status" -eq 0 ]
88
+ }
89
+
90
+ @test "work-problems: Non-Interactive Decision Making table has the external-root-cause row (P063)" {
91
+ run grep -F 'External root cause detected at Open → Known Error' "$WP_SKILL"
92
+ [ "$status" -eq 0 ]
93
+ }
94
+
95
+ @test "work-problems: uses the same stable marker wording as manage-problem" {
96
+ run grep -F -- '- **Upstream report pending** — external dependency identified; invoke /wr-itil:report-upstream when ready' "$WP_SKILL"
97
+ [ "$status" -eq 0 ]
98
+ }
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env bats
2
+
3
+ # P062: manage-problem SKILL.md documents that every Step 7 status
4
+ # transition refreshes docs/problems/README.md and stages it in the
5
+ # same commit — including folded-fix commits that ride with `fix(...)`.
6
+ #
7
+ # Doc-lint structural test (Permitted Exception per ADR-005). Asserts
8
+ # SKILL.md wording for the refresh block, the four transition scopes,
9
+ # the folded-fix-commit case, the fast-path interaction, and the
10
+ # Step 11 commit convention's stage-list requirement.
11
+
12
+ setup() {
13
+ REPO_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../../../../.." && pwd)"
14
+ SKILL_MD="$REPO_ROOT/packages/itil/skills/manage-problem/SKILL.md"
15
+ }
16
+
17
+ @test "manage-problem: SKILL.md contains the README.md refresh block (P062)" {
18
+ run grep -F 'README.md refresh on every transition (P062)' "$SKILL_MD"
19
+ [ "$status" -eq 0 ]
20
+ }
21
+
22
+ @test "manage-problem: the refresh block lists all four transition scopes" {
23
+ run grep -F 'Open → Known Error, Known Error → Verification Pending, Verification Pending → Closed, Parked' "$SKILL_MD"
24
+ [ "$status" -eq 0 ]
25
+ }
26
+
27
+ @test "manage-problem: the refresh block covers folded-fix commits explicitly" {
28
+ run grep -F '**Folded-fix commits**' "$SKILL_MD"
29
+ [ "$status" -eq 0 ]
30
+ }
31
+
32
+ @test "manage-problem: the refresh block says refresh is a render not a re-rank" {
33
+ run grep -F 'The refresh is a render, not a re-rank' "$SKILL_MD"
34
+ [ "$status" -eq 0 ]
35
+ }
36
+
37
+ @test "manage-problem: the refresh block stages README.md in the same commit" {
38
+ run grep -F 'git add docs/problems/README.md' "$SKILL_MD"
39
+ [ "$status" -eq 0 ]
40
+ }
41
+
42
+ @test "manage-problem: Step 11 commit convention requires README.md in the stage list on transitions (P062)" {
43
+ run grep -F 'stage list MUST include `docs/problems/README.md`' "$SKILL_MD"
44
+ [ "$status" -eq 0 ]
45
+ }
46
+
47
+ @test "manage-problem: Step 11 references Step 7's refresh block from the stage-list requirement" {
48
+ run grep -F "Step 7's \"README.md refresh on every transition\" block (P062)" "$SKILL_MD"
49
+ [ "$status" -eq 0 ]
50
+ }
51
+
52
+ @test "manage-problem: refresh block describes the fast-path interaction" {
53
+ run grep -F 'Fast-path interaction' "$SKILL_MD"
54
+ [ "$status" -eq 0 ]
55
+ run grep -F 'cache stays fresh by construction' "$SKILL_MD"
56
+ [ "$status" -eq 0 ]
57
+ }
58
+
59
+ @test "manage-problem: refresh block describes Last reviewed line update" {
60
+ run grep -F 'Update the "Last reviewed" line' "$SKILL_MD"
61
+ [ "$status" -eq 0 ]
62
+ }
@@ -100,7 +100,7 @@ Read the problem file and apply these deterministic rules:
100
100
  | Problem previously attempted twice without progress in this session | **Skip** — mark as stuck, needs interactive attention | user-answerable (direction) |
101
101
  | Open problem with outstanding user-answerable design question (naming, direction, pacing, scope) | **Skip** — surface the question at stop (Step 2.5) | user-answerable (design) |
102
102
  | Open problem needing architect design judgment (new-ADR-level question) | **Skip** — note the architect-design blocker; Step 2.5 may elevate via a pre-triggered architect call in `--deep-stop` mode | architect-design |
103
- | Open problem blocked on upstream dependency or Claude Code capability gap | **Skip** — record the upstream-blocked reason | upstream-blocked |
103
+ | Open problem blocked on upstream dependency or Claude Code capability gap | **Skip** — but first append the pending-upstream-report marker to the ticket's `## Related` section (see P063 — run the manage-problem SKILL.md external-root-cause detection AFK fallback before skipping). The marker wording is fixed: `- **Upstream report pending** — external dependency identified; invoke /wr-itil:report-upstream when ready`. Use the already-noted check to avoid duplicates. | upstream-blocked |
104
104
 
105
105
  The default is to work the problem. Only skip when the rule explicitly says so. This is an AFK loop — forward progress matters more than avoiding dead ends, because dead ends are cheap (findings are saved) and interactive input is expensive (user is absent).
106
106
 
@@ -108,7 +108,7 @@ The default is to work the problem. Only skip when the rule explicitly says so.
108
108
 
109
109
  - **user-answerable** — the user can answer directly (verification, naming, direction, pacing, scope). Step 2.5 surfaces these as questions (interactive) or in the Outstanding Design Questions table (non-interactive / AFK).
110
110
  - **architect-design** — requires architect judgment first; may escalate to a new ADR. Step 2.5 can optionally pre-trigger the architect agent in `--deep-stop` mode to produce a concrete user-answerable question. Otherwise noted as "pending architect review".
111
- - **upstream-blocked** — external dependency, Claude Code capability gap, or waiting on third-party fix. Truly terminal for this loop — no user question would change anything. Report the blocker and move on.
111
+ - **upstream-blocked** — external dependency, Claude Code capability gap, or waiting on third-party fix. Truly terminal for this loop — no user question would change anything. Report the blocker and move on. **Before skipping, run the manage-problem external-root-cause detection AFK fallback** (per P063): grep the ticket for the stable marker `- **Upstream report pending** —` or `- **Reported Upstream:**` / a `## Reported Upstream` section; if none is present, append `- **Upstream report pending** — external dependency identified; invoke /wr-itil:report-upstream when ready` to the ticket's `## Related` section. This preserves the outbound audit trail across AFK iterations so the user can see the deferred action on return.
112
112
 
113
113
  Record the category alongside the skip reason in the iteration report so Step 2.5 can read the categories deterministically.
114
114
 
@@ -208,6 +208,7 @@ When `AskUserQuestion` is unavailable or the user is AFK, the skill (and the del
208
208
  | Fix verification needed | Skip problem, add to "needs verification" list |
209
209
  | Stop-condition #2 with user-answerable skip-reasons | Emit Outstanding Design Questions table in summary (do NOT call AskUserQuestion). The persona is AFK by definition — per JTBD-006 and ADR-013 Rule 6 — so the table is the default. Interactive invocations may batch up to 4 questions through AskUserQuestion instead — per ADR-013 Rule 1 (Step 2.5). |
210
210
  | Unexpected dirty state between iterations | Halt the loop. Report the `git status --porcelain` output, the last iteration's reported outcome, and the divergence — per P036 (Step 6.75). Do NOT attempt non-interactive recovery. |
211
+ | External root cause detected at Open → Known Error, or at park with `upstream-blocked` reason | Append the stable `- **Upstream report pending** — external dependency identified; invoke /wr-itil:report-upstream when ready` marker to the ticket's `## Related` section; do NOT auto-invoke `/wr-itil:report-upstream` (Step 6 security-path branch is interactive — per ADR-024 Consequences). Use the already-noted grep check to avoid duplicate lines. Per P063 + ADR-013 Rule 6. |
211
212
 
212
213
  ## Edge Cases
213
214