@windyroad/itil 0.35.16-preview.432 → 0.36.0-preview.436

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.
@@ -484,5 +484,5 @@
484
484
  }
485
485
  },
486
486
  "name": "wr-itil",
487
- "version": "0.35.16"
487
+ "version": "0.36.0"
488
488
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@windyroad/itil",
3
- "version": "0.35.16-preview.432",
3
+ "version": "0.36.0-preview.436",
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"
@@ -195,6 +195,7 @@ Log the renumber decision in the operation report if origin and local diverged.
195
195
  **Status**: Open
196
196
  **Reported**: <YYYY-MM-DD>
197
197
  **Priority**: 3 (Medium) — Impact: 3 x Likelihood: 1 (deferred — re-rate at next /wr-itil:review-problems)
198
+ **Origin**: internal
198
199
  **Effort**: M (deferred — re-rate at next /wr-itil:review-problems)
199
200
  **Type**: <type_value>
200
201
  **JTBD**: <jtbd_trace_value_as_comma_separated_list_OR_omit_line_when_empty>
@@ -453,6 +453,7 @@ Before writing the problem file, perform a concern-boundary analysis on the gath
453
453
  **Status**: Open
454
454
  **Reported**: <YYYY-MM-DD>
455
455
  **Priority**: <score> (<label>) — Impact: <label> (<n>) x Likelihood: <label> (<n>)
456
+ **Origin**: internal
456
457
 
457
458
  ## Description
458
459
 
@@ -492,6 +493,11 @@ Before writing the problem file, perform a concern-boundary analysis on the gath
492
493
  <links to related files, problems, ADRs>
493
494
  ```
494
495
 
496
+ **`**Origin**` field (ADR-076)** records where the problem came from and is an authoritative input to the ADR-076 reported-first ranking tier. Two values:
497
+
498
+ - `internal` — internally discovered (the default for tickets created by hand or by an internal observation).
499
+ - `inbound-reported (#NN)` — reported to us by an external user via an upstream channel, where `#NN` is the upstream issue/discussion number. Written by ADR-062's inbound-discovery safe-and-valid branch at ticket creation. This is the **inbound** direction and is distinct from the `## Reported Upstream` section (which records the **outbound** direction — a ticket *we* reported up to someone else). The `**Origin**` field, not the regenerable `.upstream-cache.json`, is the rank-determining source of truth (ADR-076). When backfilling existing tickets during a review, stamp reported ones with `inbound-reported (#NN)`; leave the rest `internal`.
500
+
495
501
  The `## Dependencies` section uses **bare ticket IDs** (`P038`, not `[P038](./038-...)` link syntax) — review output renders to links on demand. An empty row is valid and explicit: `- **Blocked by**: (none)` reads better than omitting the row. The transitive-effort rule in the WSJF Prioritisation section consumes this section at review time.
496
502
 
497
503
  **Concrete example** (for P073 referencing two upstreams):
@@ -510,7 +516,7 @@ After writing the new `.open.md` file, regenerate `docs/problems/README.md` to i
510
516
 
511
517
  **Mechanism**: use the same rendering rules as Step 7's P062 block (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). The refresh is a **render, not a re-rank** — existing WSJF values on the other ticket files are trusted per P062's established discipline. Only the new ticket's own WSJF is consumed from its freshly-written file.
512
518
 
513
- **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. The first key (WSJF desc) sets the tier; within a tier the next three keys are the canonical tie-break ladder (Known Error before Open; smaller effort before larger; older Reported date before newer); ID asc is the deterministic final tiebreaker for full-tie cases. The table MUST include a `Reported` column so the third tie-break input is visible to README readers — without it, users cannot reconcile the rendered order against the orchestrator's selection. <!-- 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 7 P062 block, the Step 9e template, AND `/wr-itil:review-problems` SKILL.md Step 3 / Step 5 — drift here re-opens P138.
519
+ **WSJF Rankings tier + tie-break sort (P138 + ADR-076)**: rows render **tier-first** Tier 0 Critical-bypass (Severity Very High ≥17 OR security-classified OR incident-linked) → Tier 1 Inbound-reported (`**Origin**: inbound-reported`) → Tier 2 Internal — and **within each tier** 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 selection 1:1. The ADR-076 tier partition sets the top-level order; within a tier WSJF desc sets the band, then the next three keys are the canonical tie-break ladder (Known Error before Open; smaller effort before larger; older Reported date before newer); ID asc is the deterministic final tiebreaker for full-tie cases. The table MUST include a `Reported` column so the third tie-break input is visible, and an `Origin` column so the Tier 1 partition is visible — without them, users cannot reconcile the rendered order against the orchestrator's selection. <!-- REPORTED-FIRST-TIER-SOURCE: /wr-itil:work-problems SKILL.md Step 3 (ADR-076) --> <!-- TIE-BREAK-LADDER-SOURCE: /wr-itil:work-problems SKILL.md Step 3 --> Any future change to the tie-break ladder OR the reported-first tier MUST update this render block, the Step 7 P062 block, the Step 9e template, AND `/wr-itil:review-problems` SKILL.md Step 3 / Step 5 — drift here re-opens P138 / ADR-076.
514
520
 
515
521
  **Verification Queue sort direction (P150)**: rows in the Verification Queue table are sorted by `Released date ASC` (oldest at row 1; same-day releases tiebreak by ID ASC) per ADR-022 + P048 user-task semantics — older entries are the most likely-verified candidates the user wants to surface first when closing the queue. Newest-first ordering pushes those actionable closure candidates below the fold and contradicts the section header. <!-- VQ-SORT-DIRECTION: oldest-first per ADR-022 --> Any future change to the VQ sort direction MUST update this render block, the Step 7 P062 block, the Step 9c presentation block, the Step 9e template, AND `/wr-itil:review-problems` + `/wr-itil:transition-problem` + `/wr-itil:transition-problems` + `/wr-itil:reconcile-readme` + `/wr-itil:list-problems` — drift here re-opens P150.
516
522
 
@@ -679,7 +685,7 @@ Every Step 7 status transition (Open → Known Error, Known Error → Verificati
679
685
 
680
686
  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.
681
687
 
682
- **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.
688
+ **WSJF Rankings tier + tie-break sort (P138 + ADR-076)**: rows render **tier-first** Tier 0 Critical-bypass (Severity Very High ≥17 OR security-classified OR incident-linked) → Tier 1 Inbound-reported (`**Origin**: inbound-reported`) → Tier 2 Internal — and **within each tier** 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 selection 1:1. Within each 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, and an `Origin` column so the Tier 1 partition is visible. <!-- REPORTED-FIRST-TIER-SOURCE: /wr-itil:work-problems SKILL.md Step 3 (ADR-076) --> <!-- TIE-BREAK-LADDER-SOURCE: /wr-itil:work-problems SKILL.md Step 3 --> Any future change to the tie-break ladder OR the reported-first tier 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 / ADR-076.
683
689
 
684
690
  **Verification Queue sort direction (P150)**: rows in the Verification Queue table are sorted by `Released date ASC` (oldest at row 1; same-day releases tiebreak by ID ASC) per ADR-022 + P048 user-task semantics — older entries are the most likely-verified candidates the user wants to surface first when closing the queue. Newest-first ordering pushes those actionable closure candidates below the fold and contradicts the section header. <!-- VQ-SORT-DIRECTION: oldest-first per ADR-022 --> Any future change to the VQ sort direction MUST update this render block, the Step 5 P094 block, the Step 9c presentation block, the Step 9e template, AND `/wr-itil:review-problems` + `/wr-itil:transition-problem` + `/wr-itil:transition-problems` + `/wr-itil:reconcile-readme` + `/wr-itil:list-problems` — drift here re-opens P150.
685
691
 
@@ -775,10 +781,10 @@ The re-rate pass is part of Step 9b's output — a re-rate row appears in the st
775
781
 
776
782
  **Step 9c: Present summary and select problem to work**
777
783
 
778
- After reviewing all problems, present a WSJF-ranked table for open/known-error problems (the main dev-work queue). Sort rows by `(WSJF desc, Known-Error-first, Effort-divisor asc, Reported-date asc, ID asc)` so row order matches `/wr-itil:work-problems` Step 3 tie-break selection 1:1 (P138):
784
+ After reviewing all problems, present a WSJF-ranked table for open/known-error problems (the main dev-work queue). Sort rows **tier-first** (Tier 0 Critical-bypass [Severity Very High ≥17 OR security-classified OR incident-linked] → Tier 1 Inbound-reported [`**Origin**: inbound-reported`] → Tier 2 Internal), then within each tier by `(WSJF desc, Known-Error-first, Effort-divisor asc, Reported-date asc, ID asc)` so row order matches `/wr-itil:work-problems` Step 3 selection 1:1 (P138 + ADR-076): <!-- REPORTED-FIRST-TIER-SOURCE: /wr-itil:work-problems SKILL.md Step 3 (ADR-076) -->
779
785
 
780
- | WSJF | ID | Title | Severity | Status | Effort | Reported | Notes |
781
- |------|-----|-------|----------|--------|--------|----------|-------|
786
+ | WSJF | ID | Title | Severity | Status | Effort | Reported | Origin | Notes |
787
+ |------|-----|-------|----------|--------|--------|----------|--------|-------|
782
788
 
783
789
  Then present a separate **Verification Queue** section for `.verifying.md` files (per ADR-022 — ranked by release age, oldest first; no WSJF because the multiplier is 0). Sort key + direction is the canonical `Released date ASC` (oldest at row 1; same-day releases tiebreak by ID ASC) — drift here re-opens P150. <!-- VQ-SORT-DIRECTION: oldest-first per ADR-022 --> The final `Likely verified?` column carries an **evidence-first** cell (per P186 — supersedes the original P048 Candidate 4 14-day heuristic). <!-- LIKELY-VERIFIED-CELL-SHAPE: evidence-based per P186 --> Three canonical values:
784
790
 
@@ -824,7 +830,7 @@ When evidence is **ambiguous, contested, or absent** (no specific in-session cit
824
830
 
825
831
  Edit each problem file where the priority changed. Then write/overwrite `docs/problems/README.md` with the current ranked table so future `work` invocations can skip the full re-scan.
826
832
 
827
- **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 a 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 `Reported` column MUST appear 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 template, the Step 5 P094 block, the Step 7 P062 block, AND `/wr-itil:review-problems` SKILL.md Step 3 / Step 5 — drift here re-opens P138.
833
+ **WSJF Rankings tier + tie-break sort (P138 + ADR-076)**: rows render **tier-first** Tier 0 Critical-bypass (Severity Very High ≥17 OR security-classified OR incident-linked) → Tier 1 Inbound-reported (`**Origin**: inbound-reported`) → Tier 2 Internal — and **within each tier** 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 selection 1:1. Within a tier, rows are ordered by the canonical tie-break ladder: Known Error before Open, smaller Effort before larger, older Reported date before newer. The `Reported` column MUST appear so the third tie-break input is visible, and an `Origin` column so the Tier 1 partition is visible. <!-- REPORTED-FIRST-TIER-SOURCE: /wr-itil:work-problems SKILL.md Step 3 (ADR-076) --> <!-- TIE-BREAK-LADDER-SOURCE: /wr-itil:work-problems SKILL.md Step 3 --> Any future change to the tie-break ladder OR the reported-first tier MUST update this template, the Step 5 P094 block, the Step 7 P062 block, AND `/wr-itil:review-problems` SKILL.md Step 3 / Step 5 — drift here re-opens P138 / ADR-076.
828
834
 
829
835
  ```markdown
830
836
  # Problem Backlog
@@ -834,9 +840,9 @@ Edit each problem file where the priority changed. Then write/overwrite `docs/pr
834
840
 
835
841
  ## WSJF Rankings
836
842
 
837
- | WSJF | ID | Title | Severity | Status | Effort | Reported |
838
- |------|-----|-------|----------|--------|--------|----------|
839
- | <score> | P<NNN> | <title> | <severity> | <status> | <effort> | <YYYY-MM-DD> |
843
+ | WSJF | ID | Title | Severity | Status | Effort | Reported | Origin |
844
+ |------|-----|-------|----------|--------|--------|----------|--------|
845
+ | <score> | P<NNN> | <title> | <severity> | <status> | <effort> | <YYYY-MM-DD> | <internal / inbound-reported (#NN)> |
840
846
  ...
841
847
 
842
848
  ## Verification Queue
@@ -5,6 +5,14 @@
5
5
  # the table must include a Reported date column so the third tie-break
6
6
  # input is visible to README readers.
7
7
  #
8
+ # ADR-076: selection partitions into three tiers ABOVE the WSJF ladder —
9
+ # Tier 0 Critical-bypass (Severity >=17 OR security OR incident-linked)
10
+ # Tier 1 Inbound-reported (**Origin**: inbound-reported)
11
+ # Tier 2 Internal
12
+ # The tier dominates WSJF; within each tier the existing P138 ladder
13
+ # applies unchanged. Each render site carries a REPORTED-FIRST-TIER-SOURCE
14
+ # marker and an Origin column. Drift re-opens P138 / ADR-076.
15
+ #
8
16
  # Hybrid coverage per ADR-005 + ADR-037:
9
17
  # - Structural contract-assertions (Permitted Exception per ADR-005 /
10
18
  # contract-assertion pattern per ADR-037): each of the five render-
@@ -214,3 +222,97 @@ EOF
214
222
  T_low: KE M low-WSJF"
215
223
  [ "$sorted" = "$expected" ]
216
224
  }
225
+
226
+ # ---------------------------------------------------------------------------
227
+ # ADR-076 structural contract-assertions — reported-first tier
228
+ # ---------------------------------------------------------------------------
229
+
230
+ @test "manage-problem render blocks carry the REPORTED-FIRST-TIER-SOURCE marker (ADR-076)" {
231
+ # Each WSJF Rankings render block must carry the greppable tier marker
232
+ # pointing back to /wr-itil:work-problems Step 3 (the canonical tier
233
+ # source). Drift across render sites re-opens ADR-076.
234
+ run grep -F '<!-- REPORTED-FIRST-TIER-SOURCE: /wr-itil:work-problems SKILL.md Step 3 (ADR-076) -->' "$MANAGE_SKILL"
235
+ [ "$status" -eq 0 ]
236
+ # Step 5 P094, Step 7 P062, Step 9c presentation, Step 9e template.
237
+ count=$(grep -c -F '<!-- REPORTED-FIRST-TIER-SOURCE: /wr-itil:work-problems SKILL.md Step 3 (ADR-076) -->' "$MANAGE_SKILL")
238
+ [ "$count" -ge 3 ]
239
+ }
240
+
241
+ @test "review-problems carries the REPORTED-FIRST-TIER-SOURCE marker (ADR-076)" {
242
+ run grep -F '<!-- REPORTED-FIRST-TIER-SOURCE: /wr-itil:work-problems SKILL.md Step 3 (ADR-076) -->' "$REVIEW_SKILL"
243
+ [ "$status" -eq 0 ]
244
+ }
245
+
246
+ @test "work-problems carries the REPORTED-FIRST-TIER-SOURCE marker (ADR-076)" {
247
+ run grep -F '<!-- REPORTED-FIRST-TIER-SOURCE: /wr-itil:work-problems SKILL.md Step 3 (ADR-076) -->' "$WORK_SKILL"
248
+ [ "$status" -eq 0 ]
249
+ }
250
+
251
+ @test "manage-problem + review-problems README templates include the Origin column (ADR-076)" {
252
+ # Tier 1 (inbound-reported) membership must be visible to README readers,
253
+ # mirroring the Reported-column rationale for the third tie-break level.
254
+ run grep -F '| WSJF | ID | Title | Severity | Status | Effort | Reported | Origin |' "$MANAGE_SKILL"
255
+ [ "$status" -eq 0 ]
256
+ run grep -F '| WSJF | ID | Title | Severity | Status | Effort | Reported | Origin |' "$REVIEW_SKILL"
257
+ [ "$status" -eq 0 ]
258
+ }
259
+
260
+ @test "manage-problem ticket template defines the Origin field (ADR-076)" {
261
+ run grep -F '**Origin**: internal' "$MANAGE_SKILL"
262
+ [ "$status" -eq 0 ]
263
+ }
264
+
265
+ @test "render blocks warn that drift re-opens ADR-076" {
266
+ count=$(grep -c -F 're-opens P138 / ADR-076' "$MANAGE_SKILL")
267
+ [ "$count" -ge 3 ]
268
+ }
269
+
270
+ # ---------------------------------------------------------------------------
271
+ # ADR-076 behavioural fixture: tier partition dominates the WSJF ladder
272
+ # ---------------------------------------------------------------------------
273
+
274
+ @test "behavioural: tier partition outranks WSJF — critical-bypass + reported beat higher-WSJF internal" {
275
+ # Fixture columns: tier WSJF KE_flag Effort Reported ID Title
276
+ # tier: 0=critical-bypass, 1=inbound-reported, 2=internal
277
+ #
278
+ # The full selection key is tier ASC (k1) dominating, then the existing
279
+ # P138 ladder within tier: WSJF desc (k2), KE-first (k3), Effort asc (k4),
280
+ # Reported asc (k5), ID asc (k6).
281
+ #
282
+ # Tickets:
283
+ # C: critical-bypass, WSJF 2.0 (Severity 20 Open XL) — lowest WSJF
284
+ # R: inbound-reported, WSJF 3.0 (Severity 6 Open M)
285
+ # I: internal, WSJF 16.0 (Severity 8 KE S) — highest WSJF
286
+ #
287
+ # Without the tier, I (WSJF 16.0) would top the queue. With ADR-076 the
288
+ # tier dominates: C → R → I. This is the regression guard that the most
289
+ # critical issues come first and reported beats internal regardless of WSJF.
290
+ fixture_in="$TEST_TMP/fixture-tier.tsv"
291
+ cat >"$fixture_in" <<'EOF'
292
+ 2 16.0 0 1 2026-05-20 502 I: internal high-WSJF
293
+ 0 2.0 1 8 2026-05-10 501 C: critical low-WSJF
294
+ 1 3.0 1 2 2026-05-15 503 R: reported mid-WSJF
295
+ EOF
296
+
297
+ # k1 tier asc; k2 WSJF desc; k3 KE_flag asc; k4 Effort asc; k5 Reported asc; k6 ID asc
298
+ sorted=$(sort -t$'\t' -k1,1n -k2,2nr -k3,3n -k4,4n -k5,5 -k6,6n "$fixture_in" | cut -f7)
299
+ expected="C: critical low-WSJF
300
+ R: reported mid-WSJF
301
+ I: internal high-WSJF"
302
+ [ "$sorted" = "$expected" ]
303
+ }
304
+
305
+ @test "behavioural: within a tier, the existing WSJF + tie-break ladder still applies (ADR-076)" {
306
+ # Two inbound-reported tickets in the same tier must order by the
307
+ # unchanged within-tier ladder: higher WSJF first, then KE-first.
308
+ fixture_in="$TEST_TMP/fixture-within-tier.tsv"
309
+ cat >"$fixture_in" <<'EOF'
310
+ 1 6.0 1 1 2026-05-12 601 R_low: reported WSJF 6
311
+ 1 12.0 0 2 2026-05-11 602 R_high: reported WSJF 12
312
+ EOF
313
+
314
+ sorted=$(sort -t$'\t' -k1,1n -k2,2nr -k3,3n -k4,4n -k5,5 -k6,6n "$fixture_in" | cut -f7)
315
+ expected="R_high: reported WSJF 12
316
+ R_low: reported WSJF 6"
317
+ [ "$sorted" = "$expected" ]
318
+ }
@@ -38,7 +38,7 @@ For each open / known-error ticket (dual-tolerant enumeration spans `docs/proble
38
38
  1. Read the problem file.
39
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.
40
40
  3. **Re-assess Impact (1-5)** using the product-specific impact levels from `RISK-POLICY.md`. Ask: "If this problem occurs in production, what is the worst business consequence?"
41
- 4. **Re-assess Likelihood (1-5)** using the likelihood levels from `RISK-POLICY.md`. Ask: "Given the current codebase, how likely is this to affect the user?"
41
+ 4. **Re-assess Likelihood (1-5)** using the likelihood levels from `RISK-POLICY.md`. Ask: "Given the current codebase, how likely is this to affect the user?" **Inbound-report evidence (ADR-076):** if the ticket carries `**Origin**: inbound-reported`, an external user actually hit this failure — that is legitimate "previously observed failure mode" evidence and may justify Likelihood up to level 5 *on its own merits*. This is honest risk-keeping, **NOT a ranking lever**: do not inflate Likelihood to push reported tickets up the queue. The reported-first **tier** in Step 3 does the prioritisation; the risk axes stay honest because the risk-scorer release-risk gate reads the same Likelihood scale (ADR-026 grounding).
42
42
  5. **Calculate Severity** = Impact × Likelihood.
43
43
  6. **Look up Label** from the risk matrix label bands.
44
44
  7. **Re-estimate Effort** (S / M / L / XL) by reading the Root Cause Analysis and Candidate Fix sections. Consider: how many files, how complex, does it need planning, is it cross-package or migration-heavy (XL territory)? If the bucket has changed since the last review, update the Effort line in the problem file and note the reason in a short parenthetical (e.g. "L → XL — architect review added ADR + migration script"). P047.
@@ -49,6 +49,7 @@ For each open / known-error ticket (dual-tolerant enumeration spans `docs/proble
49
49
  - Update the Status field to "Known Error".
50
50
  - Re-stage explicitly per the P057 staging trap: `git add <new-path>` after the Edit.
51
51
  - This happens automatically — do not ask the user. The transition's fix-strategy is documented; only the shipping is outstanding.
52
+ 11. **Confirm the `**Origin**` field (ADR-076)** — this is where "checking for items reported upstream to us" lands during a review. If the ticket originated from an external inbound report, set `**Origin**: inbound-reported (#NN)` (NN = the upstream issue/discussion number); cross-check `docs/problems/.upstream-cache.json` (`matched_local_ticket`) and any acknowledgement comment to confirm. Otherwise set/leave `**Origin**: internal`. Tickets predating ADR-076 carry no Origin field and default to `internal` until stamped here. This field — not the regenerable cache — drives the Step 3 reported-first tier, so stamping it during the review is what makes reported tickets rank ahead on the refreshed ranking.
52
53
 
53
54
  ### 2.5. Dependency-graph traversal — propagate transitive effort (P076)
54
55
 
@@ -66,11 +67,11 @@ Re-read the WSJF Prioritisation → "Transitive dependencies (P076)" subsection
66
67
 
67
68
  After re-scoring, present three sections matching the README.md format (same rendering used by `/wr-itil:list-problems` and by the README cache — Step 5 writes the same layout):
68
69
 
69
- **WSJF Rankings** — dev-work queue (open + known-error), sorted by the multi-key `(WSJF desc, Known-Error-first, Effort-divisor asc, Reported-date asc, ID asc)` so rendered top-to-bottom row order matches `/wr-itil:work-problems` SKILL.md Step 3 tie-break selection 1:1 (P138). Within each WSJF tier, rows follow the canonical tie-break ladder: Known Error before Open, smaller Effort before larger, older Reported date before newer. The `Reported` column MUST appear so the third tie-break input is visible to README readers. <!-- TIE-BREAK-LADDER-SOURCE: /wr-itil:work-problems SKILL.md Step 3 --> Any change to the tie-break ladder MUST update this rendering block, Step 5's README template, AND `/wr-itil:manage-problem` SKILL.md Step 5 P094 / Step 7 P062 / Step 9e — drift re-opens P138.
70
+ **WSJF Rankings** — dev-work queue (open + known-error), rendered **tier-first** — Tier 0 Critical-bypass (Severity Very High ≥17 OR security-classified OR incident-linked) → Tier 1 Inbound-reported (`**Origin**: inbound-reported`) → Tier 2 Internal — and **within each tier** by the multi-key `(WSJF desc, Known-Error-first, Effort-divisor asc, Reported-date asc, ID asc)` so rendered top-to-bottom row order matches `/wr-itil:work-problems` SKILL.md Step 3 selection 1:1 (P138 + ADR-076). Within each tier, rows follow the canonical tie-break ladder: Known Error before Open, smaller Effort before larger, older Reported date before newer. The `Reported` column MUST appear so the third tie-break input is visible, and an `Origin` column so the Tier 1 partition is visible. <!-- REPORTED-FIRST-TIER-SOURCE: /wr-itil:work-problems SKILL.md Step 3 (ADR-076) --> <!-- TIE-BREAK-LADDER-SOURCE: /wr-itil:work-problems SKILL.md Step 3 --> Any change to the tie-break ladder OR the reported-first tier MUST update this rendering block, Step 5's README template, AND `/wr-itil:manage-problem` SKILL.md Step 5 P094 / Step 7 P062 / Step 9e — drift re-opens P138 / ADR-076.
70
71
 
71
72
  ```
72
- | WSJF | ID | Title | Severity | Status | Effort | Reported | Notes |
73
- |------|-----|-------|----------|--------|--------|----------|-------|
73
+ | WSJF | ID | Title | Severity | Status | Effort | Reported | Origin | Notes |
74
+ |------|-----|-------|----------|--------|--------|----------|--------|-------|
74
75
  ```
75
76
 
76
77
  **Verification Queue** — `.verifying.md` tickets, sorted by `Released date ASC` (oldest at row 1; same-day releases tiebreak by ID ASC) per ADR-022 + P048 user-task semantics. Older entries are the most likely-verified candidates the user wants to surface first when closing the queue; newest-first ordering pushes those actionable closure candidates below the fold and contradicts the section header. <!-- VQ-SORT-DIRECTION: oldest-first per ADR-022 --> Any change to the VQ sort direction MUST update this rendering block, Step 5's README template, AND `/wr-itil:manage-problem` SKILL.md Step 5 P094 / Step 7 P062 / Step 9c / Step 9e + `/wr-itil:transition-problem` + `/wr-itil:transition-problems` + `/wr-itil:reconcile-readme` + `/wr-itil:list-problems` — drift re-opens P150. The `Likely verified?` column carries an **evidence-first** cell (per P186 — supersedes the age-based heuristic). <!-- LIKELY-VERIFIED-CELL-SHAPE: evidence-based per P186 --> Three canonical values:
@@ -189,7 +190,7 @@ For each unmatched fresh report, run these steps in order; record the outcome in
189
190
 
190
191
  5. **Clear-malicious branch**: post a brief gated verdict comment (JTBD-301 acknowledgement contract — silent close is forbidden per ADR-062 Decision Drivers row 1). Comment body names the policy-violation classification verbatim from the `wr-risk-scorer:inbound-report` verdict. External-comms gates ride. Then close the upstream issue via `gh issue close <id>`. Append the reporter handle + classification to `docs/audits/inbound-discovery-log.md` for P123 block-list consumption when that ticket lands. Cache entry classification: `clear-malicious-closed`. **Gate-denial sub-branch**: if the verdict-comment gate denies, record `cache_audit_note: gate-denied-clear-malicious-pre-close` and do NOT close the upstream issue (silent close is forbidden — preserve the report for the next pass).
191
192
 
192
- 6. **Safe-and-valid branch**: invoke `/wr-itil:capture-problem --no-prompt <report-body-verbatim>` to create the local ticket. The `--no-prompt` flag defaults to `type=technical`; the maintainer re-classifies at next interactive `review-problems` re-rate. Rationale: a default of `user-business` would mis-classify security-advisory-channel reports as user-business when they're often deep technical bugs; the maintainer-re-classify path is the safety net. Verbatim body preservation honors JTBD-301 persona constraint "capture context faithfully without cognitive re-shaping" and JTBD-201 audit-trail fidelity. Then post a gated `gh issue comment` acknowledgement carrying the new local-ticket reference. Cache entry classification: `safe-and-valid-local-ticket-created`; populate `matched_local_ticket: P<NNN>` with the freshly-allocated ID. **Gate-denial sub-branch**: if the acknowledgement comment gate denies, the local ticket already exists — record `cache_audit_note: gate-denied-safe-and-valid-acknowledgement` and continue. The acknowledgement comment will retry on the next discovery pass.
193
+ 6. **Safe-and-valid branch**: invoke `/wr-itil:capture-problem --no-prompt <report-body-verbatim>` to create the local ticket. The `--no-prompt` flag defaults to `type=technical`; the maintainer re-classifies at next interactive `review-problems` re-rate. **Stamp the inbound origin (ADR-076)**: the skeleton writes `**Origin**: internal` by default — Edit it on the freshly-created ticket to `**Origin**: inbound-reported (#<id>)` (the upstream issue/discussion `<id>` polled this pass) so the ADR-076 reported-first tier ranks it ahead of internal tickets. The on-ticket `**Origin**` field, not the regenerable cache, is the authoritative rank input (ADR-076); the cache's `matched_local_ticket` remains the audit/replay record. Rationale: a default of `user-business` would mis-classify security-advisory-channel reports as user-business when they're often deep technical bugs; the maintainer-re-classify path is the safety net. Verbatim body preservation honors JTBD-301 persona constraint "capture context faithfully without cognitive re-shaping" and JTBD-201 audit-trail fidelity. Then post a gated `gh issue comment` acknowledgement carrying the new local-ticket reference. Cache entry classification: `safe-and-valid-local-ticket-created`; populate `matched_local_ticket: P<NNN>` with the freshly-allocated ID. **Gate-denial sub-branch**: if the acknowledgement comment gate denies, the local ticket already exists — record `cache_audit_note: gate-denied-safe-and-valid-acknowledgement` and continue. The acknowledgement comment will retry on the next discovery pass.
193
194
 
194
195
  #### 4.5f. Audit-log append
195
196
 
@@ -219,11 +220,11 @@ Write / overwrite `docs/problems/README.md` with the refreshed ranking so future
219
220
 
220
221
  ## WSJF Rankings
221
222
 
222
- Dev-work queue only. Verification Pending (`.verifying.md`, WSJF multiplier 0) and Parked (`.parked.md`, multiplier 0) tickets are excluded per ADR-022 — surfaced in their own sections below. Rows sort by `(WSJF desc, Known-Error-first, Effort-divisor asc, Reported-date asc, ID asc)` so top-to-bottom order matches `/wr-itil:work-problems` Step 3 tie-break selection 1:1 (P138). The `Reported` column MUST appear.
223
+ Dev-work queue only. Verification Pending (`.verifying.md`, WSJF multiplier 0) and Parked (`.parked.md`, multiplier 0) tickets are excluded per ADR-022 — surfaced in their own sections below. Rows render **tier-first** (Tier 0 Critical-bypass [Severity Very High ≥17 OR security-classified OR incident-linked] → Tier 1 Inbound-reported [`**Origin**: inbound-reported`] → Tier 2 Internal), then within each tier by `(WSJF desc, Known-Error-first, Effort-divisor asc, Reported-date asc, ID asc)` so top-to-bottom order matches `/wr-itil:work-problems` Step 3 selection 1:1 (P138 + ADR-076). The `Reported` and `Origin` columns MUST appear. <!-- REPORTED-FIRST-TIER-SOURCE: /wr-itil:work-problems SKILL.md Step 3 (ADR-076) -->
223
224
 
224
- | WSJF | ID | Title | Severity | Status | Effort | Reported |
225
- |------|-----|-------|----------|--------|--------|----------|
226
- | <score> | P<NNN> | <title> | <severity> | <status> | <effort> | <YYYY-MM-DD> |
225
+ | WSJF | ID | Title | Severity | Status | Effort | Reported | Origin |
226
+ |------|-----|-------|----------|--------|--------|----------|--------|
227
+ | <score> | P<NNN> | <title> | <severity> | <status> | <effort> | <YYYY-MM-DD> | <internal / inbound-reported (#NN)> |
227
228
  ...
228
229
 
229
230
  ## Verification Queue
@@ -6,7 +6,7 @@ allowed-tools: Read, Write, Edit, Bash, Glob, Grep, AskUserQuestion, Skill, Agen
6
6
 
7
7
  # Work Problem — Pick-and-Run
8
8
 
9
- Pick the highest-WSJF ticket from the current backlog and work it end-to-end. This is the **singular** entry point — one ticket per invocation. Selection is **framework-mediated** per ADR-044's Framework-Mediated Surface (Prioritisation row): the agent applies the WSJF formula + documented tie-break ladder mechanically and reports the chosen ticket + the rung that decided. The user retains direct override via `/wr-itil:work-problem <NNN>` invocation and via mid-flow correction (ADR-044 category 6).
9
+ Pick the highest-WSJF ticket from the current backlog and work it end-to-end. This is the **singular** entry point — one ticket per invocation. Selection is **framework-mediated** per ADR-044's Framework-Mediated Surface (Prioritisation row): the agent applies the ADR-076 tier partition (Critical-bypass → Inbound-reported → Internal) then the WSJF formula + documented within-tier tie-break ladder mechanically, and reports the chosen ticket + its tier + the rung that decided. The user retains direct override via `/wr-itil:work-problem <NNN>` invocation and via mid-flow correction (ADR-044 category 6).
10
10
 
11
11
  This skill is the P071 phased-landing split of `/wr-itil:manage-problem work` per ADR-010 amended Skill Granularity rule: one skill per distinct user intent. The original `/wr-itil:manage-problem work` 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
12
 
@@ -21,7 +21,7 @@ Both names coexist intentionally per P071's out-of-scope note on the naming coex
21
21
 
22
22
  **In scope:**
23
23
  - Read `docs/problems/README.md` when fresh; otherwise delegate the refresh to `/wr-itil:review-problems` first (never re-implement the re-scoring logic locally — same anti-fork discipline as the list-problems cache path).
24
- - Pick the highest-WSJF ticket via the framework-mediated tie-break ladder (Known Error > Open; smaller effort first; older reported date; ticket number ascending) per ADR-044 Framework-Mediated Surface. Report the chosen ticket + the rung that decided. No `AskUserQuestion` fires for selection.
24
+ - Pick the highest-priority ticket via the framework-mediated selection: first by ADR-076 **tier** (Tier 0 Critical-bypass [Severity Very High ≥17 OR security-classified OR incident-linked] → Tier 1 Inbound-reported [`**Origin**: inbound-reported`] → Tier 2 Internal), then within the highest non-empty tier by the tie-break ladder (Known Error > Open; smaller effort first; older reported date; ticket number ascending) per ADR-044 Framework-Mediated Surface. Report the chosen ticket + its tier + the rung that decided. No `AskUserQuestion` fires for selection.
25
25
  - Honour the user-override path `/wr-itil:work-problem <NNN>` — when the user names a ticket directly, skip the ladder and proceed to Step 3 with the named ticket.
26
26
  - Delegate the actual work to `/wr-itil:manage-problem <NNN>` via the Skill tool so the investigation / known-error transition / fix / closure flow stays hosted on a single authoritative workflow (ADR-010 thin-router discipline applied to the work path).
27
27
  - Scope-expansion prompt (ADR-013 Rule 1; ADR-044 category-2 deviation-approval surface) when the selected ticket's effort grows during work — same three-option structure as `/wr-itil:manage-problem`'s Working a Problem section.
@@ -192,7 +192,7 @@ After Step 0b completes (whether dispatched or silent-passed), proceed to Step 1
192
192
 
193
193
  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.
194
194
 
195
- **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 -->
195
+ **README row order matches Step 3 tier + tie-break selection (P138 + ADR-076)**: the README's WSJF Rankings table is rendered tier-first — rows partition into Tier 0 Critical-bypass (Severity ≥17 OR security-classified OR incident-linked) → Tier 1 Inbound-reported (`**Origin**: inbound-reported`) → Tier 2 Internal, and within each tier by 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 tier/tie-break re-application needed. The slow path scan must apply the same tier partition then multi-key sort. <!-- REPORTED-FIRST-TIER-SOURCE: /wr-itil:work-problems SKILL.md Step 3 (ADR-076) --> <!-- TIE-BREAK-LADDER-SOURCE: /wr-itil:work-problems SKILL.md Step 3 -->
196
196
 
197
197
  Exclude:
198
198
  - `.closed.md` files (done)
@@ -253,12 +253,21 @@ Step 2.5b is the single source of truth for routing accumulated user-answerable
253
253
 
254
254
  **Cross-skill principle (architect FLAG, P122 + P126)**: orchestrator main turns default to `AskUserQuestion` when available; the AFK persona (JTBD-006) is served by the **subprocess-boundary contract under ADR-032** (iteration subprocess workers are AFK by construction via `claude -p` — they exit at `ITERATION_SUMMARY` and never reach the orchestrator's stop or halt surfaces), NOT by suppressing `AskUserQuestion` at the orchestrator layer. Step 5's iteration-prompt template carries the per-subprocess AFK contract (constraint: "Do not call `AskUserQuestion`"); the orchestrator's stop and halt surfaces fire only in the main turn where the user is presumed present. P122 established this principle at Step 2.5; P126 extends it to every halt path that emits a final AFK summary (the principle: **halt-paths-must-route-design-questions-through-Step-2.5b** — every halt path that fires after iters have accumulated user-answerable skips MUST run Step 2.5b before emitting its summary).
255
255
 
256
- ### Step 3: Pick the highest-WSJF problem
256
+ ### Step 3: Pick the highest-WSJF problem in the highest non-empty tier
257
257
 
258
- Select the problem with the highest WSJF score. If there's a tie, prefer:
258
+ Selection partitions the backlog into three **tiers** and works the highest non-empty tier first; the WSJF tie-break ladder applies **within** a tier, not across tiers. Tiers, highest first (ADR-076):
259
+
260
+ 1. **Tier 0 — Critical bypass**: Severity Very High (≥17) OR security-classified OR incident-linked. The most critical issues always come first, regardless of origin.
261
+ 2. **Tier 1 — Inbound-reported**: ticket carries `**Origin**: inbound-reported` (reported to us by an external user; ADR-062). Worked ahead of internal tickets — customer-service / feedback-signal preservation: ignored reporters stop reporting and churn.
262
+ 3. **Tier 2 — Internal**: everything else (`**Origin**: internal` or no Origin field).
263
+
264
+ Within the highest non-empty tier, select the problem with the highest WSJF score. If there's a tie, prefer:
259
265
  1. Known Errors over Open problems (they have a confirmed fix path — less risk of wasted effort)
260
266
  2. Smaller effort over larger (faster throughput)
261
267
  3. Older reported date (longer wait = higher urgency)
268
+ 4. Lower ID (deterministic final tiebreaker)
269
+
270
+ The full selection order is therefore: **tier** (Critical-bypass → Inbound-reported → Internal), then the within-tier ladder `(WSJF desc, Known-Error-first, Effort-divisor asc, Reported-date asc, ID asc)`. <!-- REPORTED-FIRST-TIER-SOURCE: /wr-itil:work-problems SKILL.md Step 3 (ADR-076) -->
262
271
 
263
272
  ### Step 4: Classify each problem
264
273