@windyroad/itil 0.26.0 → 0.27.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.
@@ -306,8 +306,15 @@ Before creating, search existing problems for similar issues. The user may not k
306
306
  Compute the next ID as the **max of the local and origin highest IDs**, plus one, zero-padded to 3 digits. Comparing against `origin/<base>` is required by ADR-019 (confirmation criterion 2): without it, parallel sessions can mint the same ID for different problems and force a destructive surgical rebase on push (P040 incident).
307
307
 
308
308
  ```bash
309
- # Local-max ID
310
- local_max=$(ls docs/problems/*.md 2>/dev/null | sed 's/.*\///' | grep -oE '^[0-9]+' | sort -n | tail -1)
309
+ # Local-max ID — dual-tolerant enumeration covers BOTH the flat
310
+ # `docs/problems/<NNN>-<title>.<state>.md` layout AND the per-state
311
+ # subdir `docs/problems/<state>/<NNN>-<title>.md` layout per RFC-002
312
+ # migration window. Both halves contribute to next-ID compute so a
313
+ # pre-migration ticket at flat-104 and a post-migration ticket at
314
+ # per-state-204 BOTH appear in `local_max` — never re-allocates an
315
+ # already-taken ID. `sed 's|.*/||'` strips ALL leading path components
316
+ # (works for both `100-foo.open.md` flat and `open/200-foo.md` per-state).
317
+ local_max=$(ls docs/problems/*.md docs/problems/*/*.md 2>/dev/null | sed 's|.*/||' | grep -oE '^[0-9]+' | sort -n | tail -1)
311
318
 
312
319
  # Origin-max ID — `git ls-tree origin/<base>` reads remote-tracking ref
313
320
  # without requiring a fetch in this step (Step 0 preflight is the place
@@ -317,9 +324,11 @@ local_max=$(ls docs/problems/*.md 2>/dev/null | sed 's/.*\///' | grep -oE '^[0-9
317
324
  # `--name-only` is required (P056): without it, each ls-tree line is
318
325
  # `<mode> <type> <sha>\t<path>` and the 40-char blob SHA can contain
319
326
  # three-digit runs that `grep -oE '[0-9]{3}'` false-matches (observed
320
- # `origin_max=997` on 2026-04-20 opening P055). `sed` strips the path
321
- # prefix so the anchored `grep -oE '^[0-9]+'` only picks up filename IDs.
322
- origin_max=$(git ls-tree --name-only origin/main docs/problems/ 2>/dev/null | sed 's|^docs/problems/||' | grep -oE '^[0-9]+' | sort -n | tail -1)
327
+ # `origin_max=997` on 2026-04-20 opening P055). `-r` recurses into
328
+ # the per-state subdirs introduced by RFC-002. `sed 's|.*/||'` strips
329
+ # all leading path components so the anchored `grep -oE '^[0-9]+'`
330
+ # picks up filename IDs in both layouts.
331
+ origin_max=$(git ls-tree --name-only -r origin/main docs/problems/ 2>/dev/null | sed 's|.*/||' | grep -oE '^[0-9]+' | sort -n | tail -1)
323
332
 
324
333
  # Take the max of the two and increment.
325
334
  next=$(printf '%03d' $(( $(echo -e "${local_max:-0}\n${origin_max:-0}" | sort -n | tail -1) + 1 )))
@@ -467,9 +476,9 @@ The "Last reviewed" line (line 3 of `docs/problems/README.md`) was designed as a
467
476
 
468
477
  ### 6. For updates: Edit the existing file
469
478
 
470
- Find the file matching the problem ID:
479
+ Find the file matching the problem ID. Dual-tolerant lookup spans the flat layout AND the per-state subdir layout per RFC-002 migration window:
471
480
  ```bash
472
- ls docs/problems/<NNN>-*.md 2>/dev/null
481
+ ls docs/problems/<NNN>-*.md docs/problems/*/<NNN>-*.md 2>/dev/null
473
482
  ```
474
483
 
475
484
  Apply the update — this could be:
@@ -597,7 +606,7 @@ Update the "Status" field to "Closed". Reference the problem ID in the closure c
597
606
 
598
607
  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.
599
608
 
600
- 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.
609
+ The refresh uses the same rendering rules as Step 9e (dual-tolerant glob per RFC-002 migration window: `docs/problems/*.open.md docs/problems/open/*.md` / `*.known-error.md` + `known-error/*.md` / `*.verifying.md` + `verifying/*.md` / `*.parked.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.
601
610
 
602
611
  **WSJF Rankings tie-break sort (P138)**: rows in the WSJF Rankings table are sorted by the multi-key `(WSJF desc, Known-Error-first, Effort-divisor asc, Reported-date asc, ID asc)` so the rendered top-to-bottom row order matches `/wr-itil:work-problems` SKILL.md Step 3's tie-break selection 1:1. Within each WSJF tier, rows are ordered by the canonical tie-break ladder: Known Error before Open, smaller Effort before larger, older Reported date before newer. The table MUST include a `Reported` column so the third tie-break input is visible to README readers. <!-- TIE-BREAK-LADDER-SOURCE: /wr-itil:work-problems SKILL.md Step 3 --> Any future change to the tie-break ladder MUST update this render block, the Step 5 P094 block, the Step 9e template, AND `/wr-itil:review-problems` SKILL.md Step 3 / Step 5 — drift here re-opens P138.
603
612
 
@@ -617,7 +626,7 @@ The refresh uses the same rendering rules as Step 9e (glob `docs/problems/*.open
617
626
 
618
627
  ### 8. For list: Show summary
619
628
 
620
- 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.
629
+ Read all open + known-error tickets via the dual-tolerant glob `ls docs/problems/*.open.md docs/problems/*.known-error.md docs/problems/open/*.md docs/problems/known-error/*.md 2>/dev/null` (RFC-002 migration window). Extract ID, title, priority, and status. Sort by priority (highest first). Display as a markdown table.
621
630
 
622
631
  ### 9. For review: Re-assess all open problems
623
632
 
@@ -629,9 +638,12 @@ Before running the full review, check whether `docs/problems/README.md` exists a
629
638
 
630
639
  ```bash
631
640
  readme_commit=$(git log -1 --format=%H -- docs/problems/README.md 2>/dev/null)
632
- # Cache is stale if: no README commit, OR problem files committed since README, OR uncommitted problem file changes
641
+ # Cache is stale if: no README commit, OR problem files committed since README, OR uncommitted problem file changes.
642
+ # Pathspec pair `'docs/problems/*.md' 'docs/problems/*/*.md'` is the
643
+ # RFC-002 dual-tolerant transitional shape — covers BOTH the flat
644
+ # layout AND the per-state subdir layout. T6 drops the flat half post-T5.
633
645
  if [ -z "$readme_commit" ] || \
634
- git log --oneline "${readme_commit}..HEAD" -- 'docs/problems/*.md' ':!docs/problems/README.md' 2>/dev/null | grep -q .; then
646
+ git log --oneline "${readme_commit}..HEAD" -- 'docs/problems/*.md' 'docs/problems/*/*.md' ':!docs/problems/README.md' 2>/dev/null | grep -q .; then
635
647
  echo "stale"
636
648
  fi
637
649
  ```
@@ -649,9 +661,9 @@ If the command prints "stale", or `README.md` does not exist in git, run the ful
649
661
 
650
662
  Read `RISK-POLICY.md` to get the current impact levels (1-5), likelihood levels (1-5), risk matrix, and label bands. These are the authoritative definitions — do not use outdated scales.
651
663
 
652
- **Step 9b: For each open/known-error problem (skip `.parked.md` and `.verifying.md` files entirely):**
664
+ **Step 9b: For each open/known-error problem (skip parked / verifying tickets entirely):**
653
665
 
654
- Parked problems and Verification Pending problems are excluded from WSJF ranking — do not read, score, or update them in this step. Parked tickets are shown in a dedicated Parked section in step 9c; Verification Pending tickets are shown in a dedicated Verification Queue section in step 9c (ranked by release age, not WSJF — per ADR-022).
666
+ Enumerate via dual-tolerant glob `docs/problems/*.open.md docs/problems/*.known-error.md docs/problems/open/*.md docs/problems/known-error/*.md` per RFC-002 migration window. Parked problems and Verification Pending problems are excluded from WSJF ranking — do not read, score, or update them in this step. Parked tickets are shown in a dedicated Parked section in step 9c; Verification Pending tickets are shown in a dedicated Verification Queue section in step 9c (ranked by release age, not WSJF — per ADR-022).
655
667
 
656
668
  1. Read the problem file
657
669
  2. Read the codebase context — check if the problem's root cause has been investigated, if there are related fixes in git history, or if the problem is stale
@@ -140,7 +140,10 @@ For each `P<NNN>` in the transitioned RFC's frontmatter `problems:` list:
140
140
  ```bash
141
141
  for pid_token in $(awk '/^problems:/{gsub(/[][]/,"");gsub(/,/,"\n");for(i=2;i<=NF;i++)print $i;exit}' "$rfc_file"); do
142
142
  pid_num="${pid_token#P}"
143
- problem_file=$(ls docs/problems/${pid_num}-*.md 2>/dev/null | head -1)
143
+ # Dual-tolerant ticket discovery RFC-002 migration window covers
144
+ # BOTH flat (`docs/problems/<NNN>-<title>.<state>.md`) AND per-state
145
+ # subdir (`docs/problems/<state>/<NNN>-<title>.md`) layouts.
146
+ problem_file=$(ls docs/problems/${pid_num}-*.md docs/problems/*/${pid_num}-*.md 2>/dev/null | head -1)
144
147
  [ -z "$problem_file" ] && continue
145
148
  bash "$(wr-itil-script-path 2>/dev/null || echo packages/itil/scripts)/update-problem-rfcs-section.sh" "$problem_file" docs/rfcs
146
149
  git add "$problem_file"
@@ -58,8 +58,10 @@ If `wr-voice-tone:agent` is not installed in the project, the gate is dormant an
58
58
 
59
59
  ### 1. Read the local problem ticket
60
60
 
61
+ Dual-tolerant lookup spans flat layout AND per-state subdir layout (RFC-002 migration window):
62
+
61
63
  ```bash
62
- LOCAL_TICKET=$(ls docs/problems/${LOCAL_ID}-*.{open,known-error,verifying,closed}.md 2>/dev/null | head -1)
64
+ LOCAL_TICKET=$(ls docs/problems/${LOCAL_ID}-*.{open,known-error,verifying,closed}.md docs/problems/*/${LOCAL_ID}-*.md 2>/dev/null | head -1)
63
65
  [ -n "$LOCAL_TICKET" ] || { echo "Error: local ticket P${LOCAL_ID} not found in docs/problems/"; exit 1; }
64
66
  ```
65
67
 
@@ -12,10 +12,11 @@ This skill is the P071 phased-landing split of `/wr-itil:manage-problem review`
12
12
 
13
13
  ## Scope
14
14
 
15
- **In scope:**
16
- - `docs/problems/*.open.md` and `docs/problems/*.known-error.md` — re-scored (Impact × Likelihood × Effort → WSJF); Priority + Effort + WSJF lines updated when they change.
17
- - `docs/problems/*.verifying.md` surfaced in the Verification Queue and fed to Step 4's verification prompt (Known Error Closed path when the user confirms).
18
- - `docs/problems/*.parked.md` — listed in the Parked section; NOT re-scored (WSJF multiplier is 0).
15
+ **In scope** (RFC-002 migration window — each glob is dual-tolerant, covering BOTH the flat `docs/problems/<NNN>-<title>.<state>.md` filename-suffix layout AND the per-state subdir `docs/problems/<state>/<NNN>-<title>.md` layout):
16
+
17
+ - `docs/problems/*.open.md` + `docs/problems/open/*.md` and `docs/problems/*.known-error.md` + `docs/problems/known-error/*.md` re-scored (Impact × Likelihood × Effort WSJF); Priority + Effort + WSJF lines updated when they change.
18
+ - `docs/problems/*.verifying.md` + `docs/problems/verifying/*.md` surfaced in the Verification Queue and fed to Step 4's verification prompt (Known Error Closed path when the user confirms).
19
+ - `docs/problems/*.parked.md` + `docs/problems/parked/*.md` — listed in the Parked section; NOT re-scored (WSJF multiplier is 0).
19
20
  - `docs/problems/README.md` — rewritten with the refreshed WSJF Rankings + Verification Queue + Parked tables; staged and committed with the review.
20
21
 
21
22
  **Out of scope:**
@@ -32,7 +33,7 @@ Read `RISK-POLICY.md` to get the current Impact levels (1-5), Likelihood levels
32
33
 
33
34
  ### 2. Re-score every open / known-error ticket
34
35
 
35
- For each `docs/problems/*.open.md` and `docs/problems/*.known-error.md` file (skip `.parked.md` and `.verifying.md` files entirely — their WSJF multiplier is 0 and they have dedicated sections in Step 3):
36
+ For each open / known-error ticket (dual-tolerant enumeration spans `docs/problems/*.open.md docs/problems/*.known-error.md docs/problems/open/*.md docs/problems/known-error/*.md` per RFC-002 migration window; skip `.parked.md` / `.verifying.md` and their per-state-subdir equivalents `docs/problems/parked/*.md` / `docs/problems/verifying/*.md` entirely — their WSJF multiplier is 0 and they have dedicated sections in Step 3):
36
37
 
37
38
  1. Read the problem file.
38
39
  2. Read the codebase context — check if the root cause has been investigated since the last review, whether there are related fixes in git history, or whether the problem is stale.
@@ -97,7 +98,7 @@ Omit an empty section rather than rendering an empty header.
97
98
 
98
99
  ### 4. Verification prompt (Verification Pending → Closed)
99
100
 
100
- Target `docs/problems/*.verifying.md` via glob — do NOT scan `.known-error.md` bodies for a `## Fix Released` section (per ADR-022, Verification Pending is a first-class status, not a substring marker). For each `.verifying.md` file, use `AskUserQuestion` to ask whether the fix has been verified in production.
101
+ Target the dual-tolerant glob `docs/problems/*.verifying.md docs/problems/verifying/*.md` (RFC-002 migration window) — do NOT scan `.known-error.md` bodies for a `## Fix Released` section (per ADR-022, Verification Pending is a first-class status, not a substring marker). For each verifying ticket file, use `AskUserQuestion` to ask whether the fix has been verified in production.
101
102
 
102
103
  The question MUST include a fix summary extracted from the `## Fix Released` section — include the first sentence (or first bullet list) of that section in the question body or as the option description, so the user can answer without reading the full problem file. Do NOT ask with only the problem ID + title + version.
103
104
 
@@ -128,7 +129,7 @@ Dev-work queue only. Verification Pending (`.verifying.md`, WSJF multiplier 0) a
128
129
 
129
130
  ## Verification Queue
130
131
 
131
- Fix released, awaiting user verification (driven off `docs/problems/*.verifying.md` via glob per ADR-022). Sorted by `Released date ASC` (oldest at row 1; same-day releases tiebreak by ID ASC). <!-- VQ-SORT-DIRECTION: oldest-first per ADR-022 --> `Likely verified?` column marks tickets ≥14 days old (P048 Candidate 4 default).
132
+ Fix released, awaiting user verification (driven off the dual-tolerant glob `docs/problems/*.verifying.md docs/problems/verifying/*.md` per ADR-022 + RFC-002 migration window). Sorted by `Released date ASC` (oldest at row 1; same-day releases tiebreak by ID ASC). <!-- VQ-SORT-DIRECTION: oldest-first per ADR-022 --> `Likely verified?` column marks tickets ≥14 days old (P048 Candidate 4 default).
132
133
 
133
134
  | ID | Title | Released | Likely verified? |
134
135
  |----|-------|----------|------------------|
@@ -49,10 +49,10 @@ Usage: /wr-itil:transition-problem <NNN> <status>
49
49
 
50
50
  ### 2. Discover the ticket file
51
51
 
52
- Locate the ticket file by ID:
52
+ Locate the ticket file by ID — dual-tolerant lookup spans both the flat layout (`docs/problems/<NNN>-<title>.<state>.md`) AND the per-state subdir layout (`docs/problems/<state>/<NNN>-<title>.md`) per RFC-002 migration window:
53
53
 
54
54
  ```bash
55
- ls docs/problems/<NNN>-*.md 2>/dev/null
55
+ ls docs/problems/<NNN>-*.md docs/problems/*/<NNN>-*.md 2>/dev/null
56
56
  ```
57
57
 
58
58
  If no file is found, emit: `No ticket found for ID <NNN>` and stop.
@@ -207,7 +207,7 @@ Release draining is owned by the caller — `/wr-itil:manage-problem` Step 12 (i
207
207
 
208
208
  `transition-problem` owns (for the user-initiated transition path):
209
209
  - Argument parsing (`<NNN> <status>`).
210
- - Ticket-file discovery via `ls docs/problems/<NNN>-*.md`.
210
+ - Ticket-file discovery via the dual-tolerant lookup `ls docs/problems/<NNN>-*.md docs/problems/*/<NNN>-*.md` (RFC-002 transitional shape; both layouts).
211
211
  - Destination-reachability validation (Open → Known Error → Verification Pending → Closed, one step at a time).
212
212
  - Pre-flight checks for the supplied destination.
213
213
  - P063 external-root-cause detection (Open → Known Error only) — including the AFK fallback that appends the stable `- **Upstream report pending** —` marker.
@@ -85,10 +85,10 @@ If parsing fails at this stage, NO git operations have run. The user can re-invo
85
85
 
86
86
  For each pair `(NNN, status)` in argument order:
87
87
 
88
- **2a. Discover the ticket file.**
88
+ **2a. Discover the ticket file.** Dual-tolerant lookup spans flat layout AND per-state subdir layout per RFC-002 migration window:
89
89
 
90
90
  ```bash
91
- ls docs/problems/<NNN>-*.md 2>/dev/null
91
+ ls docs/problems/<NNN>-*.md docs/problems/*/<NNN>-*.md 2>/dev/null
92
92
  ```
93
93
 
94
94
  If no file is found OR multiple files are found (suffix-exclusive lifecycle violation), record the pair as a failure with reason `discovery-failed` and continue to the next pair. Do NOT touch git.
@@ -41,7 +41,12 @@ Check the `docs/problems/README.md` cache with the same git-history-based freshn
41
41
  ```bash
42
42
  readme_commit=$(git log -1 --format=%H -- docs/problems/README.md 2>/dev/null)
43
43
  if [ -z "$readme_commit" ] || \
44
- git log --oneline "${readme_commit}..HEAD" -- 'docs/problems/*.md' ':!docs/problems/README.md' 2>/dev/null | grep -q .; then
44
+ git log --oneline "${readme_commit}..HEAD" -- 'docs/problems/*.md' 'docs/problems/*/*.md' ':!docs/problems/README.md' 2>/dev/null | grep -q .; then
45
+ # Pathspec pair `'docs/problems/*.md' 'docs/problems/*/*.md'` is the
46
+ # RFC-002 dual-tolerant transitional shape — covers BOTH the flat
47
+ # layout (`docs/problems/<NNN>-<title>.<state>.md`) AND the per-state
48
+ # subdir layout (`docs/problems/<state>/<NNN>-<title>.md`). T6 drops
49
+ # the flat half post-T5 verification.
45
50
  echo "stale"
46
51
  fi
47
52
  ```
@@ -124,7 +124,7 @@ This is a robustness layer ON TOP of P094 + P062, not a supersession — both pe
124
124
 
125
125
  ### Step 1: Scan the backlog
126
126
 
127
- Read `docs/problems/README.md` if it exists and is fresh (check via git history — see manage-problem step 9 for the cache freshness check). If stale or missing, scan all `.open.md` and `.known-error.md` files in `docs/problems/`, extract their WSJF scores, and rank them.
127
+ Read `docs/problems/README.md` if it exists and is fresh (check via git history — see manage-problem step 9 for the cache freshness check). If stale or missing, scan all open + known-error tickets via the dual-tolerant pattern `ls docs/problems/*.open.md docs/problems/*.known-error.md docs/problems/open/*.md docs/problems/known-error/*.md 2>/dev/null` (RFC-002 migration window — covers BOTH the flat `<NNN>-<title>.<state>.md` filename-suffix layout AND the per-state subdir `<state>/<NNN>-<title>.md` layout), extract their WSJF scores, and rank them.
128
128
 
129
129
  **README row order matches Step 3 tie-break selection (P138)**: as of P138, the README's WSJF Rankings table is rendered with the multi-key sort `(WSJF desc, Known-Error-first, Effort-divisor asc, Reported-date asc, ID asc)`. The cache-fresh path can therefore read the rendered table top-to-bottom and the first row is the orchestrator's pick — no in-memory tie-break re-application needed. The slow path scan must apply the same multi-key sort. <!-- TIE-BREAK-LADDER-SOURCE: /wr-itil:work-problems SKILL.md Step 3 -->
130
130