@windyroad/itil 2.0.0 → 2.1.1-preview.1128

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.
Files changed (41) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.codex-plugin/plugin.json +1 -1
  3. package/bin/wr-itil-is-close-blocked +51 -0
  4. package/lib/install-utils.mjs +138 -8
  5. package/package.json +1 -1
  6. package/scripts/is-close-blocked.sh +93 -0
  7. package/skills/manage-problem/SKILL.md +34 -11
  8. package/skills/review-problems/SKILL.md +2 -2
  9. package/skills/transition-problem/SKILL.md +41 -5
  10. package/skills/transition-problems/SKILL.md +17 -3
  11. package/skills/update-upstream/SKILL.md +81 -9
  12. package/skills/work-problems/SKILL.md +52 -10
  13. package/skills-codex/capture-problem/SKILL.md +1 -1
  14. package/skills-codex/capture-rfc/SKILL.md +1 -1
  15. package/skills-codex/capture-story/SKILL.md +1 -1
  16. package/skills-codex/capture-story-map/SKILL.md +1 -1
  17. package/skills-codex/check-upstream-responses/SKILL.md +1 -1
  18. package/skills-codex/close-incident/SKILL.md +1 -1
  19. package/skills-codex/link-incident/SKILL.md +1 -1
  20. package/skills-codex/list-incidents/SKILL.md +1 -1
  21. package/skills-codex/list-problems/SKILL.md +1 -1
  22. package/skills-codex/list-stories/SKILL.md +1 -1
  23. package/skills-codex/list-story-maps/SKILL.md +1 -1
  24. package/skills-codex/manage-incident/SKILL.md +1 -1
  25. package/skills-codex/manage-problem/SKILL.md +35 -12
  26. package/skills-codex/manage-rfc/SKILL.md +1 -1
  27. package/skills-codex/manage-story/SKILL.md +1 -1
  28. package/skills-codex/manage-story-map/SKILL.md +1 -1
  29. package/skills-codex/mitigate-incident/SKILL.md +1 -1
  30. package/skills-codex/reconcile-readme/SKILL.md +1 -1
  31. package/skills-codex/reconcile-stories/SKILL.md +1 -1
  32. package/skills-codex/reconcile-story-maps/SKILL.md +1 -1
  33. package/skills-codex/report-upstream/SKILL.md +1 -1
  34. package/skills-codex/restore-incident/SKILL.md +1 -1
  35. package/skills-codex/review-problems/SKILL.md +3 -3
  36. package/skills-codex/scaffold-intake/SKILL.md +1 -1
  37. package/skills-codex/transition-problem/SKILL.md +42 -6
  38. package/skills-codex/transition-problems/SKILL.md +18 -4
  39. package/skills-codex/update-upstream/SKILL.md +82 -10
  40. package/skills-codex/work-problem/SKILL.md +1 -1
  41. package/skills-codex/work-problems/SKILL.md +70 -17
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:manage-rfc
2
+ name: manage-rfc
3
3
  description: Heavyweight RFC intake + lifecycle management following the "Problem-RFC-Story framework with mandatory problem-trace and unified problem ontology" architecture rule Problem-RFC-Story framework. Creates new RFCs (delegates to /wr-itil:capture-rfc for the lightweight path), updates existing RFCs, transitions through proposed → accepted → in-progress → verifying → closed lifecycle, runs WSJF re-rank reviews, and refreshes docs/rfcs/README.md per the "Problem 062: `manage-problem` does not refresh `docs/problems/README.md` on single-ticket transitions; fast-path cache goes stale silently" problem / the "Problem 094: `/wr-itil:manage-problem` does not refresh `docs/problems/README.md` on ticket creation" problem contract pattern.
4
4
  allowed-tools: Read, Write, Edit, Bash, Grep, Glob, Task
5
5
  ---
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:manage-story
2
+ name: manage-story
3
3
  description: Heavyweight story intake + lifecycle management following the "Problem-RFC-Story framework with mandatory problem-trace and unified problem ontology" architecture rule Phase 2. Creates and updates story tickets, transitions through draft → accepted → in-progress → done → archived lifecycle, enforces I7 + I8 trace-gate at the accepted transition, runs INVEST checks per I10 at acceptance, auto-detects accepted→in-progress on the first implementing commit and in-progress→done on all-criteria-ticked + linked RFC closes (per the "A story cannot be implemented while in draft — implementation requires accepted" architecture rule a draft story is NEVER implementable — draft→in-progress is removed; the itil-no-implement-draft-gate blocks implementing a draft story), and refreshes docs/stories/README.md per the "Problem 062: `manage-problem` does not refresh `docs/problems/README.md` on single-ticket transitions; fast-path cache goes stale silently" problem / the "Problem 094: `/wr-itil:manage-problem` does not refresh `docs/problems/README.md` on ticket creation" problem contract pattern. Companion to /wr-itil:capture-story (lightweight aside surface).
4
4
  allowed-tools: Read, Write, Edit, Bash, Grep, Glob
5
5
  ---
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:manage-story-map
2
+ name: manage-story-map
3
3
  description: Heavyweight story-map intake + lifecycle management following the "Problem-RFC-Story framework with mandatory problem-trace and unified problem ontology" architecture rule Phase 2. Authors backbone × ribs × slices structure on draft maps, transitions through draft → accepted → in-progress → completed → archived, re-validates I3 + I4 invariants at every transition, and refreshes docs/story-maps/README.md per the "Problem 062: `manage-problem` does not refresh `docs/problems/README.md` on single-ticket transitions; fast-path cache goes stale silently" problem / the "Problem 094: `/wr-itil:manage-problem` does not refresh `docs/problems/README.md` on ticket creation" problem contract pattern. Companion to /wr-itil:capture-story-map (lightweight aside surface).
4
4
  allowed-tools: Read, Write, Edit, Bash, Grep, Glob
5
5
  ---
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:mitigate-incident
2
+ name: mitigate-incident
3
3
  description: Record a mitigation attempt against an incident — transitions an investigating incident to mitigating on the first attempt, appends subsequent attempts to the Mitigation attempts timeline. Evidence-first gate enforced per the "Add `manage-incident` Skill to `wr-itil` Plugin" architecture rule.
4
4
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep, request_user_input, Skill
5
5
  ---
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:reconcile-readme
2
+ name: reconcile-readme
3
3
  description: Detect and correct drift between docs/problems/README.md and the on-disk ticket inventory. Wraps the diagnose-only `<itil-plugin-root>/scripts/reconcile-readme.sh` script with an agent-applied-edits pattern that preserves narrative content (the "Last reviewed" prose paragraph and Closed-section closure-via free text). Use when README WSJF Rankings, Verification Queue, or Closed sections drift from filesystem state — typically detected by manage-problem Step 0 preflight or work-problems Step 0 preflight.
4
4
  allowed-tools: Read, Edit, Write, Bash, Grep, Glob
5
5
  ---
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:reconcile-stories
2
+ name: reconcile-stories
3
3
  description: Detect and correct drift between docs/stories/README.md and the on-disk story inventory. Wraps the diagnose-only <itil-plugin-root>/scripts/reconcile-stories.sh script with an agent-applied-edits pattern that preserves narrative content (the "Last reviewed" prose paragraph). Use when docs/stories/README.md Story Rankings or Done sections drift from filesystem state — typically detected by manage-story Step 0 preflight or work-problems preflight on RFC iters with story-tier traces.
4
4
  allowed-tools: Read, Write, Edit, Bash, Grep, Glob
5
5
  ---
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:reconcile-story-maps
2
+ name: reconcile-story-maps
3
3
  description: Detect and correct drift between docs/story-maps/README.md and the on-disk story-map HTML inventory. Wraps the diagnose-only <itil-plugin-root>/scripts/reconcile-story-maps.sh script with an agent-applied-edits pattern preserving narrative content.
4
4
  allowed-tools: Read, Write, Edit, Bash, Grep, Glob
5
5
  ---
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:report-upstream
2
+ name: report-upstream
3
3
  description: Report a local problem ticket as a structured issue against an upstream repository, with bidirectional cross-references and SECURITY.md-aware routing for security-classified tickets. Implements the contract in the "Cross-project problem-reporting contract — `report-upstream` skill in `@windyroad/itil`" architecture rule, with the "Report-upstream classifier is problem-first — supersedes Decision Outcome Steps 3 + 5" architecture rule governing problem-first classifier + default body shape.
4
4
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep, request_user_input, Skill, Agent
5
5
  ---
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:restore-incident
2
+ name: restore-incident
3
3
  description: Mark an incident as service-restored — transitions a mitigating incident to restored, appends a Timeline entry, and hands off to /wr-itil:manage-problem for linked-problem creation or update per the "Add `manage-incident` Skill to `wr-itil` Plugin" architecture rule.
4
4
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep, request_user_input, Skill
5
5
  ---
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:review-problems
2
+ name: review-problems
3
3
  description: Re-assess every open and known-error problem ticket in docs/problems/ — re-read RISK-POLICY.md, re-rate Impact × Likelihood, re-estimate Effort, recalculate WSJF, surface pending verifications, auto-transition Open → Known Error where warranted, and rewrite docs/problems/README.md with the refreshed ranking. Writes to problem files and the README cache; commits the refresh per the "Governance Skills Commit Their Own Completed Work" architecture rule.
4
4
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep, request_user_input, Skill
5
5
  ---
@@ -32,7 +32,7 @@ When referencing problem IDs, ADR IDs, JTBD IDs, or RFC IDs in prose output (the
32
32
  **In scope** (the ": docs/problems/ flat layout migration — per-state subdirs + adopter auto-migration" release design 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):
33
33
 
34
34
  - `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.
35
- - `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).
35
+ - `docs/problems/*.verifying.md` + `docs/problems/verifying/*.md` — surfaced in the Verification Queue and fed to Step 4's verification routing (the Verification Pending → Closed path Bucket 1 closes on evidence, Bucket 2 asks, Bucket 3 flips back).
36
36
  - `docs/problems/*.parked.md` + `docs/problems/parked/*.md` — listed in the Parked section; NOT re-scored (WSJF multiplier is 0).
37
37
  - `docs/problems/README.md` — rewritten with the refreshed WSJF Rankings + Verification Queue + Parked tables; staged and committed with the review.
38
38
 
@@ -124,7 +124,7 @@ Omit an empty section rather than rendering an empty header.
124
124
 
125
125
  Target the dual-tolerant glob `docs/problems/*.verifying.md docs/problems/verifying/*.md` (the ": docs/problems/ flat layout migration — per-state subdirs + adopter auto-migration" release design migration window) — do NOT scan `.known-error.md` bodies for a `## Fix Released` section (per the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule, Verification Pending is a first-class status, not a substring marker). Bucket each verifying ticket by its Step-3 `Likely verified?` cell (the "VQ `Likely verified?` column uses age-based heuristic (≥14 days = yes) instead of session-observed evidence — sibling proxy-for-evidence anti-pattern to" problem evidence-first cell shape: `yes — observed: <evidence>` / `no — not observed` / `no — observed regression`) and route each bucket differently. **Do NOT fire one `request_user_input` per ticket** — the evidence-backed subset closes on evidence; only the unobserved subset asks.
126
126
 
127
- **Bucket 1 — `yes — observed: <evidence>` → close-on-evidence (framework-mediated, silent agent action per the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule + the "Decision-delegation contract — agents over-apply Rule 1's interactive default to framework-resolved decisions; codify the framework-resolution boundary + AFK loop's batched-questions-as-deliverable + lazy-request_user_input measurement" problem).** These rows carry the "Agent output grounding — no fabricated quantitative estimates, cite + persist + uncertainty" architecture rule-grounded cited evidence (a prior Step 4 user confirmation, an in-session test invocation + observable outcome, or a `run-retro` Step 4a close-on-evidence citation — see the Step 3 cell definition). The framework has resolved this decision: a `.verifying.md` ticket with specific cited evidence IS verified per the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule's evidence semantics, so close it mechanically WITHOUT `request_user_input` — mirroring the shipped `run-retro` Step 4a step 5 close-on-evidence. A per-candidate ask here is lazy deferral (sub-contracting a framework-resolved decision back to the user) per the Step 2d Ask Hygiene Pass. For each such ticket: close the problem (`git mv` from `.verifying.md` to `.closed.md`, update Status to "Closed", re-stage per the "Problem 057: `git mv` + Edit + `git add` staging-ordering trap drops content edits from the commit" problem staging trap) and update the `Likely verified?` cell to `yes — observed: closed-on-evidence <YYYY-MM-DD> — <citation>`. Report each closure in the review output with a documented reversible recovery path: `Recovery: rerun /wr-itil:transition-problem <NNN> known-error to reopen` closes are cheap and reversible; user disagreement surfaces via authentic-correction (the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule category 6), not a pre-close consent gate.
127
+ **Bucket 1 — `yes — observed: <evidence>` → close-on-evidence.** Specific observed evidence authorizes a mechanical close without asking again. First run `<itil-plugin-root>/bin/wr-itil-is-close-blocked <NNN> docs/problems`: exit 0 keeps the ticket open and reports the matched marker; exit 2 is a pre-flight failure; exit 1 proceeds. Move the ticket to `.closed.md`, re-stage it, and persist the authority in `**Status**: Closed (closed-on-evidence <YYYY-MM-DD> — <citation>. Recovery: rerun /wr-itil:transition-problem <NNN> known-error to reopen)`. A provenance-proven GitHub issue on this project's tracker receives the gated comment and closes; unresolved or non-issue inbound provenance performs no issue mutation. A foreign issue receives the comment but stays open on local evidence alone, while that upstream party's confirmation may authorize closure. Pull requests remain comment-only. Update the review cell with the same evidence citation and report the reversible recovery path.
128
128
 
129
129
  **Bucket 2 — `no — not observed` → ask (genuine user-authority).** No session-observable evidence yet, so the user may hold out-of-band production knowledge the agent cannot observe — this is the genuine user-input surface. Use `request_user_input` to ask whether the fix has been verified in production. The question MUST include a fix summary extracted from the `## Fix Released` section — inline the first sentence (or first bullet list) of that section in the question body or option description per the brief-before-ID discipline, so the user can answer without reading the full problem file. Do NOT ask with only the problem ID + title + version.
130
130
  - If the user confirms: close the problem (`git mv` from `.verifying.md` to `.closed.md`, update Status to "Closed", re-stage per the "Problem 057: `git mv` + Edit + `git add` staging-ordering trap drops content edits from the commit" problem staging trap). Update the `Likely verified?` cell to `yes — observed: user confirmed <YYYY-MM-DD>`.
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:scaffold-intake
2
+ name: scaffold-intake
3
3
  description: Scaffold the four OSS intake surfaces (.github/ISSUE_TEMPLATE/, SECURITY.md, SUPPORT.md, CONTRIBUTING.md) for a downstream project that adopts @windyroad/itil. Idempotent, foreground-synchronous, and respects the "Gate Marker Lifecycle: TTL + Drift, Not Stop-Hook Reset" architecture rule marker semantics. Implements the contract in the "Scaffold downstream OSS intake — skill + layered triggers" architecture rule.
4
4
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep, request_user_input
5
5
  ---
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:transition-problem
2
+ name: transition-problem
3
3
  description: Advance a problem ticket's lifecycle status — Open → Known Error, Known Error → Verification Pending (verifying), Verification Pending → Closed. Renames the ticket file, updates the Status field, and refreshes docs/problems/README.md in the same commit. Hosts the transition execution inline (pre-flight checks, the "Problem 057: `git mv` + Edit + `git add` staging-ordering trap drops content edits from the commit" problem staging-trap handling, the "Problem 063: manage-problem does not trigger /wr-itil:report-upstream when root cause is external" problem external-root-cause detection, the "Problem 062: `manage-problem` does not refresh `docs/problems/README.md` on single-ticket transitions; fast-path cache goes stale silently" problem README refresh, the "Governance Skills Commit Their Own Completed Work" architecture rule commit) per the "Rename `wr-problem` Plugin to `wr-itil`" architecture rule amended "Split-skill execution ownership". Use when the user asks to "transition", "close", "mark known-error", or "release" a specific ticket.
4
4
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep, request_user_input, Skill
5
5
  ---
@@ -29,7 +29,7 @@ The deprecated `/wr-itil:manage-problem <NNN> known-error` subcommand route rema
29
29
  - `<status>` — the destination status. One of:
30
30
  - `known-error` — Open → Known Error (root cause identified AND workaround documented; fix not yet proposed — per the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule corrected semantics; the fix proposal draws a release row on a story map).
31
31
  - `verifying` — Known Error → Verification Pending (fix released, awaiting user verification per the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule).
32
- - `close` — Verification Pending → Closed (user has confirmed the fix works in production).
32
+ - `close` — Verification Pending → Closed (cited evidence meets the ticket's own close criterion, OR the user has confirmed the fix works in production — see Step 4).
33
33
 
34
34
  The `<NNN>` and `<status>` tokens are **data parameters**, not word-subcommands. Per the "Problem 071: Argument-based skill subcommands are not discoverable in Codex autocomplete" problem split rule (the "Rename `wr-problem` Plugin to `wr-itil`" architecture rule amended), data parameters (IDs, paths, URLs, enum destinations) are permitted; word-subcommands that name distinct user intents are not. This skill's argument shape is `data + data`, which is the same shape as `/wr-itil:report-upstream <NNN>`.
35
35
 
@@ -79,8 +79,12 @@ Check the current filename suffix and verify the destination status is reachable
79
79
  | `.open.md` | `known-error` | yes |
80
80
  | `.known-error.md` | `verifying` | yes |
81
81
  | `.verifying.md` | `close` | yes |
82
+ | `.verifying.md` | `known-error` | yes — **flip-back**: the fix recurred or proved incomplete. Required by `review-problems` Bucket 3, `manage-problem`, and `run-retro` Step 4a, all of which already instruct it. |
83
+ | `.closed.md` | `known-error` | yes — **reopen**: a close was wrong. This is the recovery path every evidence-authorised close reports (the "The Verification Pending → Closed transition is reserved for the maintainer, so evidence-based closure never fires and the verification queue grows without bound" problem), so it has to be reachable or the reversibility that justifies closing without a consent gate is fiction. |
82
84
  | any other pairing | — | no — emit an error and stop |
83
85
 
86
+ The two backward pairings are what make an agent-authorised close safe to make. The argument for closing on evidence without asking is that the close is cheap and reversible; a reopen route the skill refuses would make that argument false. Both are ordinary renames — `git mv` back to `known-error/`, Status field back to `Known Error`, append the recurrence or mis-close citation to the ticket body, refresh the README, one commit per the "Governance Skills Commit Their Own Completed Work" architecture rule — and neither re-runs the Open → Known Error pre-flight, because root cause and workaround were established the first time round. (the "The transition lifecycle table rejects both the fix-on-capture fast path and its own documented recovery path" problem tracks the wider set of missing pairings, including the fix-on-capture fast path.)
87
+
84
88
  If the pairing is invalid, emit a clear message naming the current status, the requested destination, and the valid next step. Do not silently skip or auto-correct — invalid transitions are almost always user typos and a clear error is the cheapest recovery.
85
89
 
86
90
  ### 4. Run pre-flight checks
@@ -128,9 +132,34 @@ Emit a structured report naming each deferred section + the lifted condition + t
128
132
 
129
133
  This check fires BEFORE the "derive-release-vehicle helper requires pre-edit of ticket changeset reference — three-touch when one-touch would suffice" problem Release-vehicle seed step in Step 6 — halt-on-conditional-deferral is the outer gate, seed-and-rename is the inner mechanic.
130
134
 
131
- **Verification Pending → Closed** (`<status>` = `close`) requires:
135
+ **Verification Pending → Closed** (`<status>` = `close`) requires **either** of:
136
+
137
+ - [ ] **Cited evidence** that meets the ticket's own stated close criterion — a test invocation and its outcome, a commit SHA whose diff covers the fix path, a skill or hook invocation that exercised the fix and behaved as the fix contracts, a post-release invocation of the shipped artefact that behaved as the fix contracts, or a `yes — observed: <citation>` cell already carried in the Verification Queue. The agent closes on its own authority and records the citation in the closure. **Mechanical stage — do NOT fire `request_user_input`** (the "Agents over-ask in interactive sessions — conflating mechanical-stages with user-interactive-stages of multi-stage skill contracts (inverse-)" problem / the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule category 4, mirroring the shipped `review-problems` Step 4 Bucket 1 and `run-retro` Step 4a sub-step 5). Surface the recovery path alongside the close: `Recovery: rerun /wr-itil:transition-problem <NNN> known-error to reopen`.
138
+ - [ ] **The user has explicitly confirmed** the fix works in production, or an orchestrator supplied the `close` argument under prior user authorisation.
139
+
140
+ **Never close on inference — absence of evidence is not evidence.** A ticket nobody exercised stays Verification Pending, however old it is and however plausible the fix looks. "The fix is on disk", "it has been months", "that area has been touched a lot" and "the ADR that prescribed it shipped" are inference, not observation — see the "Relevance-close evaluator over-fires — a bare ADR/skill citation is read as "fix shipped", so live tickets return CLOSE-CANDIDATE" problem for what happens when a bare citation is read as proof of shipping. Closing tickets nobody exercised is the opposite failure and is exactly as wrong as never closing any.
141
+
142
+ **Genuine ambiguity stays the user's surface** — contested evidence, a fix that covers only part of the ticket, or a recorded do-not-close marker. Run the mechanical check first; it is a field read, not a judgement:
143
+
144
+ ```bash
145
+ <itil-plugin-root>/bin/wr-itil-is-close-blocked <NNN> docs/problems && close_blocked=1
146
+ ```
147
+
148
+ Exit 0 means **BLOCKED**: the ticket carries a line-anchored `DO NOT CLOSE` marker (`docs/problems/verifying/151-*.md` § "Regression / incomplete observed … DO NOT CLOSE" is the canonical shape). Do NOT close it whatever the evidence says — route it to the `verifying → known-error` flip-back, or queue it for the user. Exit 1 means not blocked. Exit 2 means the ticket ref did not resolve — treat as a pre-flight failure, not as permission.
149
+
150
+ **Evidence-authorised tracker updates.** Write the basis into the ticket's `**Status**:` line alongside the citation (`**Status**: Closed (closed-on-evidence <YYYY-MM-DD> — <citation>. Recovery: rerun /wr-itil:transition-problem <NNN> known-error to reopen)`). A provenance-proven GitHub issue on this project's tracker receives the gated comment and closes; unresolved or non-issue inbound provenance performs no issue mutation. A foreign issue receives the comment but stays open on our evidence alone; that upstream party's confirmation may authorize closure. Pull requests remain comment-only.
132
151
 
133
- - [ ] The user has explicitly confirmed the fix works in production (this skill never auto-closes on inference only on explicit user confirmation or orchestrator-supplied `close` argument)
152
+ Authority: the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule (framework-resolution boundary — evidence-backed close is category 4, silent framework action; contested or absent evidence is category 1, queued not guessed), the "Agent output grounding no fabricated quantitative estimates, cite + persist + uncertainty" architecture rule (cite the evidence, persist it, state the uncertainty), the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 5 (policy-authorised silent proceed), the "Evidence-based relevance-close pass for the problem backlog (Phase 1: file-no-longer-exists; Phase 2: ADR-shipped-confirmed + named-skill-exists + self-marker-in-body + driver-child-closed + Phase 1 false-positive fixes)" architecture rule (evidence-based closure precedent on the open/known-error side of the same lifecycle), the "The Verification Pending → Closed transition is reserved for the maintainer, so evidence-based closure never fires and the verification queue grows without bound" problem (this contract).
153
+
154
+ **Verification Pending → Known Error** (`<status>` = `known-error` — flip-back) requires:
155
+
156
+ - [ ] A recurrence or incompleteness citation: what was observed, and when. Append it to the ticket body; the `Likely verified?` cell becomes `no — observed regression — <one-line citation>`.
157
+
158
+ **Closed → Known Error** (`<status>` = `known-error` — reopen) requires:
159
+
160
+ - [ ] A stated reason the close was wrong. Nothing more — this is the recovery path for an evidence-authorised close and it must stay one command deep, or the reversibility that justifies closing without a consent gate is not real.
161
+
162
+ Neither backward pairing re-runs the Open → Known Error pre-flight above: root cause and workaround were established when the ticket first reached Known Error and are still on the ticket. Neither fires the "Problem 063: manage-problem does not trigger /wr-itil:report-upstream when root cause is external" problem external-root-cause detection (Step 5 is Open → Known Error only).
134
163
 
135
164
  ### 5. External-root-cause detection (the "Problem 063: manage-problem does not trigger /wr-itil:report-upstream when root cause is external" problem — Open → Known Error only)
136
165
 
@@ -206,7 +235,7 @@ git mv docs/problems/known-error/<NNN>-<title>.md docs/problems/verifying/<NNN>-
206
235
  git add docs/problems/verifying/<NNN>-<title>.md
207
236
  ```
208
237
 
209
- The `## Fix Released` section contains: release marker (version, commit SHA, or date), one-sentence fix summary, "Awaiting user verification" line, and any exercise evidence from the releasing session. The `.verifying.md` suffix signals to every downstream consumer (work-problems classifier, review step 9d, README rendering) that the remaining work is user-side verification — no file-body scan needed.
238
+ The `## Fix Released` section contains: release marker (version, commit SHA, or date), one-sentence fix summary, "Awaiting user verification" line, and any exercise evidence from the releasing session. The `.verifying.md` suffix signals to every downstream consumer (work-problems classifier, review step 9d, README rendering) that the remaining work is verification — by evidence or by the user — no file-body scan needed.
210
239
 
211
240
  When this transition is folded into a `fix(<scope>): ... (closes P<NNN>)` commit (the common case), the `git mv` + `Edit` + re-stage + README refresh all join that single commit — never split across commits.
212
241
 
@@ -241,10 +270,17 @@ Use the structured values verbatim when authoring the `## Fix Released` section'
241
270
 
242
271
  ```bash
243
272
  git mv docs/problems/verifying/<NNN>-<title>.md docs/problems/closed/<NNN>-<title>.md
244
- # ... use the Edit tool to update the Status field to "Closed" ...
273
+ # ... use the Edit tool to update the Status field per the shape below ...
245
274
  git add docs/problems/closed/<NNN>-<title>.md
246
275
  ```
247
276
 
277
+ **Write the close's authority basis into the Status field.** The Status line is the only place the basis survives — the `Likely verified?` cell lives in the README's Verification Queue table, and that row is deleted by this very transition, so a downstream reader (Step 7b's upstream leg) would find nothing there. Shape, matching what the 2026-07-15 closes already wrote (`docs/problems/closed/186-*.md:3`):
278
+
279
+ - Evidence-authorised: `**Status**: Closed (closed-on-evidence <YYYY-MM-DD> — <citation>. Recovery: rerun /wr-itil:transition-problem <NNN> known-error to reopen)`
280
+ - User-confirmed: `**Status**: Closed (user-confirmed <YYYY-MM-DD>)`
281
+
282
+ `closed-on-evidence` is what the outbound leg reads to keep a foreign issue open on our evidence alone. The inbound leg uses committed issue-channel provenance instead: ambiguity fails closed before any issue operation.
283
+
248
284
  ### 7. Refresh docs/problems/README.md (the "Problem 062: `manage-problem` does not refresh `docs/problems/README.md` on single-ticket transitions; fast-path cache goes stale silently" problem)
249
285
 
250
286
  Every Step 7 status transition 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.
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:transition-problems
2
+ name: transition-problems
3
3
  description: "Batch-advance multiple problem tickets through the lifecycle in one invocation — Open → Known Error, Known Error → Verification Pending, Verification Pending → Closed. Loops the per-ticket /wr-itil:transition-problem mechanic (rename, Status edit, the "Problem 057: `git mv` + Edit + `git add` staging-ordering trap drops content edits from the commit" problem re-stage, the "Problem 063: manage-problem does not trigger /wr-itil:report-upstream when root cause is external" problem external-root-cause detection, the "Problem 062: `manage-problem` does not refresh `docs/problems/README.md` on single-ticket transitions; fast-path cache goes stale silently" problem README refresh) without paying N× SKILL.md reload latency or violating split-skill execution ownership. Produces ONE shared commit covering all surviving transitions per the "Governance Skills Commit Their Own Completed Work" architecture rule batch-grain. Use when closing the Verification Queue at the end of a `/wr-retrospective:run-retro` Step 4a pass, batch-closing release-aged verifyings during `/wr-itil:work-problems` AFK orchestration, or confirming multiple Step 9d verifications in `/wr-itil:manage-problem review`. Singular sibling — `/wr-itil:transition-problem` (one ticket per invocation)."
4
4
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep, request_user_input, Skill, Agent
5
5
  ---
@@ -46,7 +46,7 @@ A space-separated list of `<NNN> <status>` pairs. Repeating the singular skill's
46
46
  - `<status>` — destination status. One of:
47
47
  - `known-error` — Open → Known Error (root cause + workaround documented).
48
48
  - `verifying` — Known Error → Verification Pending (fix released; awaiting user verification per the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule).
49
- - `close` — Verification Pending → Closed (user has confirmed the fix works in production).
49
+ - `close` — Verification Pending → Closed (cited evidence meets the ticket's own close criterion, OR the user has confirmed the fix works in production — see Step 2c).
50
50
 
51
51
  **Examples:**
52
52
 
@@ -111,13 +111,19 @@ If no file is found OR multiple files are found (suffix-exclusive lifecycle viol
111
111
  | `.open.md` | `known-error` | yes |
112
112
  | `.known-error.md` | `verifying` | yes |
113
113
  | `.verifying.md` | `close` | yes |
114
+ | `.verifying.md` | `known-error` | yes — **flip-back**: the fix recurred or proved incomplete. `review-problems` Bucket 3 already instructs this and had no batch path. |
115
+ | `.closed.md` | `known-error` | yes — **reopen**: a close was wrong. The recovery path every evidence-authorised close reports (the "The Verification Pending → Closed transition is reserved for the maintainer, so evidence-based closure never fires and the verification queue grows without bound" problem). |
114
116
  | any other pairing | — | no — record as `invalid-transition` and continue |
115
117
 
118
+ Lockstep with `/wr-itil:transition-problem` Step 3 per the drift clause below — the singular and plural tables move together or neither moves. The two backward pairings are what make an agent-authorised close safe: the argument for closing on evidence without asking is that the close is cheap and reversible, and a reopen route either skill refuses would make that argument false. Both are ordinary renames; neither re-runs the Open → Known Error pre-flight (root cause and workaround were established the first time round) and neither fires the "Problem 063: manage-problem does not trigger /wr-itil:report-upstream when root cause is external" problem detection at 2d.
119
+
116
120
  **2c. Run pre-flight checks** for the destination (same gating as the singular):
117
121
 
118
122
  - Open → Known Error (`known-error`): root cause documented; ≥ 1 investigation task ticked; reproduction test or reference; workaround documented; effort bucket re-rated if scope shifted (the "Problem 047: WSJF effort buckets are coarse and not re-rated at lifecycle transitions" problem); status multiplier re-rated from Open 1.0 to Known Error 2.0 and WSJF recomputed with the post-transition status and current Effort (the "WSJF uses the pre-transition status multiplier" problem).
119
123
  - Known Error → Verification Pending (`verifying`): fix implemented; release marker available (version, commit SHA, or date) for the `## Fix Released` section.
120
- - Verification Pending → Closed (`close`): user has explicitly confirmed the fix works in production. AFK callers (work-problems orchestrator) MUST supply the close pair via prior user authorisation (e.g. an `request_user_input`-batched closure prompt at the orchestrator layer); this skill never auto-closes on inference.
124
+ - Verification Pending → Closed (`close`): cited observed evidence or explicit user confirmation authorizes closure. Evidence-backed closure is mechanical and does not require another question. Record the citation and recovery path (`/wr-itil:transition-problem <NNN> known-error`) in each ticket's Status line. A provenance-proven GitHub issue on this project's tracker receives the gated comment and closes; unresolved or non-issue inbound provenance performs no issue mutation. A foreign issue receives the comment but stays open on local evidence alone; that upstream party's confirmation may authorize closure. Pull requests remain comment-only.
125
+
126
+ **Never close on inference** — absence of evidence is not evidence. A pair whose ticket carries no citation records as `pre-flight-failed` with reason `no-evidence` and stays Verification Pending; age, plausibility, and "the fix is on disk" are not observations. **Do-not-close marker check** — run `<itil-plugin-root>/bin/wr-itil-is-close-blocked <NNN> docs/problems` per pair before closing. Exit 0 → record the pair as `pre-flight-failed` with reason `close-blocked` plus the matched marker line, and continue to the next pair; do NOT close it whatever the evidence says. Exit 2 (unresolvable ref) is a pre-flight failure, not permission.
121
127
 
122
128
  If any pre-flight fails, record the pair as `pre-flight-failed` with the failed-check list and continue to the next pair.
123
129
 
@@ -162,10 +168,18 @@ git add docs/problems/verifying/<NNN>-<title>.md
162
168
  ```bash
163
169
  # Verification Pending → Closed
164
170
  git mv docs/problems/verifying/<NNN>-<title>.md docs/problems/closed/<NNN>-<title>.md
165
- # Edit Status field to "Closed"
171
+ # Edit Status field per the shape below
166
172
  git add docs/problems/closed/<NNN>-<title>.md
167
173
  ```
168
174
 
175
+ **Write the close's authority basis into the Status field.** The Status line is the only place the basis survives — the `Likely verified?` cell lives in the README's Verification Queue table, and that row is deleted by this very transition, so a downstream reader (Step 7b's upstream leg) would find nothing there. Shape, matching what the 2026-07-15 closes already wrote (`docs/problems/closed/186-*.md:3`):
176
+
177
+ - Evidence-authorised: `**Status**: Closed (closed-on-evidence <YYYY-MM-DD> — <citation>. Recovery: rerun /wr-itil:transition-problem <NNN> known-error to reopen)`
178
+ - User-confirmed: `**Status**: Closed (user-confirmed <YYYY-MM-DD>)`
179
+
180
+ `closed-on-evidence` is what the outbound leg reads to keep a foreign issue open on our evidence alone. The inbound leg uses committed issue-channel provenance instead: ambiguity fails closed before any issue operation.
181
+
182
+
169
183
  If `git mv` or `git add` fails for a pair (e.g. the file has been moved by a parallel process), record the pair as `git-failed` with the error and continue to the next pair. Do NOT attempt to roll back prior pairs' staged renames — those are now part of the in-progress batch.
170
184
 
171
185
  Record each pair's outcome (succeeded / failed-with-reason) for the summary in Step 5.
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:update-upstream
2
+ name: update-upstream
3
3
  description: Post a lifecycle-update comment to an upstream issue when a local problem ticket transitions. Drafts a transition-specific update (root-cause confirmed / fix released / closed), composes the prose through the external-comms risk gate + voice-tone gate, auto-posts within appetite, queues above-appetite. Reciprocal sibling to /wr-itil:report-upstream — initial-filing vs lifecycle-update split per the "Cross-project problem-reporting contract — `report-upstream` skill in `@windyroad/itil`" architecture rule amendment (the "Problem 080: No bidirectional update of upstream-reported problems — local lifecycle transitions never propagate back to the reporter" problem).
4
4
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep, request_user_input, Skill, Agent
5
5
  ---
@@ -178,7 +178,7 @@ Update from <downstream-repo-url>/<local-ticket-relative-path>:
178
178
 
179
179
  <one-sentence summary from the local ticket's ## Fix Released section>
180
180
 
181
- Please upgrade and verify when convenient. We'll close this issue after your confirmation OR after a 14-day quiet period (per the "Problem 048: manage-problem does not surface Fix Released problems as verification candidates when the fix path has been exercised" problem default). Local tracking: P<NNN>.
181
+ Please upgrade and verify when convenient. We'll close this issue after your confirmation. If you'd rather we closed it without one, say so here. Local tracking: P<NNN>.
182
182
  ```
183
183
 
184
184
  #### Verification Pending → Closed template
@@ -186,12 +186,38 @@ Please upgrade and verify when convenient. We'll close this issue after your con
186
186
  ```markdown
187
187
  Update from <downstream-repo-url>/<local-ticket-relative-path>:
188
188
 
189
- **Status**: Closed locally after user-side verification.
189
+ **Status**: Closed locally after verification.
190
190
 
191
- Closing this issue to match. Thanks for the report — your filing is what got this on the queue. Local tracking: P<NNN>.
191
+ Thanks for the report — your filing is what got this on the queue. Local tracking: P<NNN>.
192
192
  ```
193
193
 
194
- After posting the Verifying → Closed comment, the skill also runs `gh issue close <n>` (per Step 5b below) so the upstream tracker matches local state.
194
+ After posting the Verifying → Closed comment, leave the foreign issue open by default. Closing it requires the target-bound upstream-party confirmation below.
195
+
196
+ #### Foreign issues close only on target-bound upstream-party confirmation
197
+
198
+ Local evidence or local user confirmation can close our ticket, but neither decides another maintainer's tracker state. Post the lifecycle comment and **stop there** unless the local ticket's `## Reported Upstream` section carries this durable, target-bound signal:
199
+
200
+ ```markdown
201
+ - **Closure authority**: upstream-confirmed <exact GitHub issue-comment URL>
202
+ ```
203
+
204
+ Before running `gh issue close`, validate that URL read-only: it MUST be an `#issuecomment-<id>` URL on the exact `UPSTREAM_OWNER_REPO/issues/UPSTREAM_ISSUE_NUMBER` target; `gh api repos/<owner>/<repo>/issues/comments/<id>` MUST return that exact issue URL; `author_association` MUST be `OWNER`, `MEMBER`, or `COLLABORATOR`; and the comment body MUST unambiguously authorize closing this issue. A missing marker, URL mismatch, API failure, non-maintainer association, or ambiguous body leaves the issue open. Never infer this authority from a local `user-confirmed` Status marker.
205
+
206
+ Read the Status line, not the README's `Likely verified?` cell: the close deletes that row from the Verification Queue before this step runs, so the cell is gone by the time anything could read it.
207
+
208
+ Confirmation from the upstream party may authorize closing their issue; their word, not our evidence, supplies the missing authority. Do not promise a quiet-period close that no mechanism delivers.
209
+
210
+ When target-bound confirmation is absent, use the evidence-authorised local-close-only variant below and record `posted-comment-local-close-only` in the back-write disclosure path. When validation succeeds, use the ordinary Closed template and record `posted-comment-and-closed`.
211
+
212
+ ```markdown
213
+ Update from <downstream-repo-url>/<local-ticket-relative-path>:
214
+
215
+ **Status**: Closed locally. We verified the fix on our side — <one-line evidence citation>.
216
+
217
+ Leaving this issue open for you. Close it whenever you have confirmed the fix works in your setup. Local tracking: P<NNN>.
218
+ ```
219
+
220
+ On this leg, without validated target-bound confirmation from them: comment, do not close. Pull requests are always comment-only, even if they carry a confirmation marker.
195
221
 
196
222
  #### Template-filling rules
197
223
 
@@ -267,7 +293,7 @@ gh issue comment "${UPSTREAM_ISSUE_NUMBER}" \
267
293
 
268
294
  Capture the returned comment URL (gh prints `https://github.com/<owner>/<repo>/issues/<n>#issuecomment-<id>`).
269
295
 
270
- On the **Verifying → Closed** transition, after posting the comment, also close the upstream issue:
296
+ On the **Verifying → Closed** transition, after posting the comment, close the upstream issue only when the target-bound `Closure authority` validation above passed:
271
297
 
272
298
  ```bash
273
299
  gh issue close "${UPSTREAM_ISSUE_NUMBER}" \
@@ -298,7 +324,7 @@ Append a log entry to the local ticket's `## Upstream Lifecycle Updates` section
298
324
  - **<YYYY-MM-DD>** — Open → Known Error
299
325
  - **Target URL**: <upstream-issue-url>
300
326
  - **Comment URL**: <posted-comment-url> (or "queued — see ## Queued Upstream Update" when above-appetite)
301
- - **Disclosure path**: posted-comment | posted-pr-comment (pull-request target, the "Prefer an upstream pull request over an issue when the upstream accepts pull requests" architecture rule — never closed) | posted-comment-and-closed (Verifying → Closed, issue targets only) | queued-above-appetite | closed-already-upstream | skipped-out-of-band
327
+ - **Disclosure path**: posted-comment | posted-pr-comment (pull-request target — never closed) | posted-comment-and-closed (confirmed Verifying → Closed, issue targets only) | posted-comment-local-close-only (outbound evidence-authorised close) | queued-above-appetite | closed-already-upstream | skipped-out-of-band
302
328
  - **Gate verdict**: external-comms <band/score> + voice-tone <pass|fail>
303
329
 
304
330
  - **<YYYY-MM-DD>** — Known Error → Verification Pending
@@ -317,7 +343,51 @@ This leg runs **in addition to** Steps 2–6 (the outbound `## Reported Upstream
317
343
 
318
344
  #### I1. Parse the inbound origin
319
345
 
320
- From the `**Origin**: inbound-reported (#NN)` field, extract the originating issue number `NN`. Resolve the repo it lives on as **our own repo** — the `gh` default for the current working tree (`gh repo view --json nameWithOwner -q .nameWithOwner`), NOT an external upstream owner/repo. If the `**Origin**` field is `internal` or absent, this leg does not run (the no-op is already handled at Step 1 when both surfaces are absent).
346
+ From the `**Origin**: inbound-reported (#NN)` field, extract the candidate number `NN`. That untyped number is not proof of an issue: issues, discussions, and advisories have distinct mutation paths, and numeric identifiers can collide.
347
+
348
+ Before any inbound `gh issue view`, `gh issue comment`, or `gh issue close`, prove the channel from the committed discovery cache:
349
+
350
+ ```bash
351
+ OWN_OWNER_REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner)
352
+ LOCAL_TICKET_ID="P${LOCAL_ID}"
353
+ ISSUE_CHANNEL="github-issues:${OWN_OWNER_REPO}"
354
+ CACHE_REF="HEAD:docs/problems/.upstream-cache.json"
355
+ CACHE_JSON=$(git show "${CACHE_REF}" 2>/dev/null) || CACHE_JSON='{}'
356
+
357
+ ISSUE_NUMBER_MATCHES=$(printf '%s' "${CACHE_JSON}" | jq \
358
+ --arg channel "${ISSUE_CHANNEL}" \
359
+ --argjson number "${NN}" \
360
+ '[.channels[$channel].reports[]? | select(.number == $number)] | length' \
361
+ 2>/dev/null) || ISSUE_NUMBER_MATCHES=0
362
+
363
+ ISSUE_TICKET_MATCHES=$(printf '%s' "${CACHE_JSON}" | jq \
364
+ --arg channel "${ISSUE_CHANNEL}" \
365
+ --argjson number "${NN}" \
366
+ --arg ticket "${LOCAL_TICKET_ID}" \
367
+ '[.channels[$channel].reports[]? |
368
+ select(.number == $number and .matched_local_ticket == $ticket)] | length' \
369
+ 2>/dev/null) || ISSUE_TICKET_MATCHES=0
370
+
371
+ NON_ISSUE_MATCHES=$(printf '%s' "${CACHE_JSON}" | jq \
372
+ --arg issue_channel "${ISSUE_CHANNEL}" \
373
+ --arg repo_suffix ":${OWN_OWNER_REPO}" \
374
+ --argjson number "${NN}" \
375
+ '[.channels | to_entries[] |
376
+ select(.key != $issue_channel and (.key | endswith($repo_suffix))) |
377
+ .value.reports[]? | select(.number == $number)] | length' \
378
+ 2>/dev/null) || NON_ISSUE_MATCHES=0
379
+
380
+ if [ "${ISSUE_NUMBER_MATCHES}" -ne 1 ] || \
381
+ [ "${ISSUE_TICKET_MATCHES}" -ne 1 ] || \
382
+ [ "${NON_ISSUE_MATCHES}" -ne 0 ]; then
383
+ echo "inbound-channel-unresolved: ${LOCAL_TICKET_ID} #${NN}"
384
+ INBOUND_CHANNEL_RESOLVED=0
385
+ else
386
+ INBOUND_CHANNEL_RESOLVED=1
387
+ fi
388
+ ```
389
+
390
+ When `INBOUND_CHANNEL_RESOLVED=0`, skip I2–I6 and perform no inbound issue operation; an independent outbound leg may still continue. Missing committed cache data, zero or multiple issue matches, a repository mismatch, a wrong `matched_local_ticket`, or a discussion/advisory collision all take this path. If the Origin field is `internal` or absent, this leg does not run.
321
391
 
322
392
  #### I2. Determine the transition (same suffix logic as Step 3)
323
393
 
@@ -441,12 +511,14 @@ Above-appetite handling is identical to Step 5c (silent risk-reduce + re-score;
441
511
  gh issue comment "${NN}" --repo "${OWN_OWNER_REPO}" --body "${INBOUND_BODY}"
442
512
  ```
443
513
 
444
- On the **Verification Pending → Closed** transition, after the comment, also close the originating issue so our own tracker matches the local `.closed.md` state (this addresses the "work-problems orchestrator carries prior-ticket Fix Strategy text into iter dispatch without re-grounding in design intent" problem #97 *silent-and-unclosed* witness):
514
+ On the **Verification Pending → Closed** transition, after the comment, close the provenance-proven issue on this project's tracker whether the local close was confirmed or evidence-authorised:
445
515
 
446
516
  ```bash
447
517
  gh issue close "${NN}" --repo "${OWN_OWNER_REPO}" --comment "" --reason completed
448
518
  ```
449
519
 
520
+ This outbound guard does not apply to a provenance-proven GitHub issue on this project's own repository. After the gated comment, close it whether the local close was evidence-authorised or confirmed; the reporter can reopen it. Unknown or non-issue inbound channels already stopped at the provenance guard.
521
+
450
522
  If the issue is already closed (someone closed it manually), `gh issue close` returns a benign error — record `closed-already` in the disclosure path and continue.
451
523
 
452
524
  #### I6. Back-write to the lifecycle log
@@ -457,7 +529,7 @@ Append to the same `## Upstream Lifecycle Updates` log (Step 6 shape), tagged fo
457
529
  - **<YYYY-MM-DD>** — Known Error → Verification Pending (inbound)
458
530
  - **Target**: inbound #<NN> (own repo <OWN_OWNER_REPO>)
459
531
  - **Comment URL**: <posted-comment-url> (or "skipped — already-posted-inbound" when the idempotency guard matched, or "queued — see ## Queued Upstream Update" when above-appetite)
460
- - **Disclosure path**: posted-inbound-comment | posted-inbound-comment-and-closed (Verifying Closed) | already-posted-inbound | queued-above-appetite | closed-already
532
+ - **Disclosure path**: posted-inbound-comment | posted-inbound-comment-and-closed (proven owned issue, confirmed or evidence-authorised close) | already-posted-inbound | queued-above-appetite | closed-already | inbound-channel-unresolved
461
533
  - **Gate verdict**: external-comms <band/score> + voice-tone <pass|fail>
462
534
  ```
463
535
 
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:work-problem
2
+ name: work-problem
3
3
  description: Pick the highest-WSJF open or known-error problem ticket and work it — investigate, implement, commit, and release per the standard manage-problem workflow. Selection is framework-mediated (WSJF + documented tie-break ladder per the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule); singular variant; distinct from /wr-itil:work-problems (plural AFK orchestrator). Use this when the user asks to "work the next problem", "work the top of the queue", or "grind through one ticket".
4
4
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep, request_user_input, Skill, Agent
5
5
  ---
@@ -1,6 +1,6 @@
1
1
  ---
2
- name: wr-itil:work-problems
3
- description: Drain the ITIL problem backlog in WSJF order using native Codex subagents, governed commits, pushes, and releases.
2
+ name: work-problems
3
+ description: Drain the ITIL problem backlog in WSJF order using isolated Codex CLI iterations, governed commits, pushes, and releases.
4
4
  ---
5
5
 
6
6
  <!-- Generated from the runtime-neutral skill source. Do not edit. -->
@@ -16,32 +16,85 @@ description: Drain the ITIL problem backlog in WSJF order using native Codex sub
16
16
 
17
17
  # Work Problems in Codex
18
18
 
19
- Continuously work the highest-priority actionable problem until the backlog is drained, the user stops, or a real governance dependency requires human direction. Use Codex's native subagent tools. Never invoke `codex exec`, start a nested Codex CLI, or implement process/PID polling.
19
+ Continuously work the highest-priority actionable problem until the backlog is drained, the user stops, or a real governance dependency requires human direction. Run each selected problem in one fresh `codex exec` process and consume its structured result before continuing.
20
20
 
21
21
  ## Preflight
22
22
 
23
23
  1. If `docs/problems/` is absent, direct the user to `/wr-itil:scaffold-intake` and stop.
24
24
  2. Run the installed ITIL maintenance commands required by the repository, including layout migration, README reconciliation, catch-up scanning, stale upstream-cache checks, and unresolved-response checks. Resolve them from the plugin's bundled `bin/`; do not use source-repository paths.
25
- 3. Preserve unrelated working-tree changes. Revert only changes created by a failed preflight.
26
- 4. If the task has a persistent Codex goal, keep it active until this drain reaches a genuine terminal state. A slow tool or subagent is not a blocker.
25
+ 3. Resolve the exact checkout with `git rev-parse --show-toplevel`. Preserve unrelated working-tree changes and record the pre-iteration status. Revert only paths proven to have been created by a failed iteration.
26
+ 4. If the task has a persistent Codex goal, keep it active until this drain reaches a genuine terminal state. A slow process is not a blocker.
27
27
 
28
28
  ## Loop
29
29
 
30
30
  1. Read the problem index and current ticket files. Select the highest WSJF problem in the highest non-empty actionable tier. Use the documented tie-break rules.
31
31
  2. Skip tickets whose required JTBD, decision, risk, or story-map oversight is unconfirmed. Record one structured outstanding question for each genuinely user-answerable dependency; do not ask mid-loop.
32
32
  3. Run the relevance and stop-condition checks. Before declaring `ALL_DONE`, run the repository's unconditional pre-completion gates and rescan the backlog.
33
- 4. Spawn one native Codex subagent for the selected ticket. Give it the exact checkout, ticket, applicable decisions, and this contract:
34
- - invoke `/wr-itil:manage-problem` for the ticket and follow its lifecycle rules;
35
- - make only in-scope changes and preserve unrelated work;
36
- - run focused tests and the required architecture/risk checks;
37
- - create the required changeset for shippable plugin behavior;
38
- - commit the completed iteration, but do not push or release;
39
- - return one `ITERATION_SUMMARY` JSON object containing ticket, action, commits, tests, risks, outstanding questions, and remaining work.
40
- 5. Wait for that same subagent. Do not cancel, replace, retry, or fan out merely because Cruise or normal model execution makes the call slow. When it completes, consume its summary and close it.
41
- 6. Validate the summary with `<itil-plugin-root>/bin/wr-itil-verify-iter-summary`. If the subagent failed after changing the checkout, inspect and safely complete or revert only its own partial work before continuing.
33
+ 4. Dispatch exactly the selected ticket through the isolated Codex command below. Do not select or work a second ticket inside that process.
34
+ 5. Wait for that same process. Do not cancel, replace, retry, or fan out merely because normal model execution is slow.
35
+ 6. Classify the exit and JSONL metadata before reading the final-output file. On success, validate the summary with `<itil-plugin-root>/bin/wr-itil-verify-iter-summary` and consume it. On failure, apply the recovery contract below and halt.
42
36
  7. Run inter-iteration verification. If the iteration produced committed shippable work, complete the repository's governed push and release cadence when risk is within appetite. Above-appetite risk is a remediation instruction: reduce scope or split the change; never ask the user to approve risk above appetite.
43
37
  8. Report only material progress, then rescan and repeat.
44
38
 
39
+ ## Isolated Codex iteration
40
+
41
+ Build a self-contained prompt containing the selected ticket ID and title, the exact checkout, applicable confirmed decisions, and these requirements:
42
+
43
+ - invoke `/wr-itil:manage-problem <number>` and work only that problem;
44
+ - preserve unrelated work and use path-scoped staging;
45
+ - load and obey the installed governance skills, agents, and hooks;
46
+ - run focused tests and required architecture, JTBD, voice, accessibility, and risk checks when their gates apply;
47
+ - add a changeset for shippable package behavior;
48
+ - commit completed iteration work, but do not push or release;
49
+ - invoke `/wr-retrospective:run-retro` before the final response, commit any retro-owned briefing refresh through its governed path, and continue to the summary even if retro reports a non-blocking failure;
50
+ - end with one `ITERATION_SUMMARY` containing ticket, action, outcome, commit state, tests, risks, outstanding questions, remaining work, and notes.
51
+
52
+ Run the nested process in the outer session's installed Codex environment. Do not replace `CODEX_HOME` or ignore user configuration: the inherited plugin registry and hooks are the governance surface. Export the three AFK guards so pending interactive questions, oversight nudges, and machine-authored correction text do not leak into the isolated turn.
53
+
54
+ ```bash
55
+ ITERATION_CHECKOUT="$(git rev-parse --show-toplevel)"
56
+ ITERATION_JSONL="$(mktemp)"
57
+ ITERATION_FINAL="$(mktemp)"
58
+
59
+ export WR_SUPPRESS_PENDING_QUESTIONS=1
60
+ export WR_SUPPRESS_OVERSIGHT_NUDGE=1
61
+ export WR_SUPPRESS_CORRECTION_DETECT=1
62
+
63
+ codex exec \
64
+ --ephemeral \
65
+ --dangerously-bypass-approvals-and-sandbox \
66
+ --dangerously-bypass-hook-trust \
67
+ --cd "$ITERATION_CHECKOUT" \
68
+ --json \
69
+ --output-last-message "$ITERATION_FINAL" \
70
+ "$ITERATION_PROMPT" \
71
+ >"$ITERATION_JSONL" 2>&1
72
+ ITERATION_EXIT=$?
73
+ ```
74
+
75
+ The two output channels are load-bearing and must stay separate:
76
+
77
+ - `ITERATION_JSONL` carries progress and error metadata only. Parse it as JSONL; never scrape the final agent message from this stream.
78
+ - `ITERATION_FINAL` carries the final agent message. Read `ITERATION_SUMMARY` only from this file after the exit and metadata checks pass.
79
+
80
+ Always remove both temporary files after their contents have been classified and consumed.
81
+
82
+ ## Error classification and recovery
83
+
84
+ Classify in this order:
85
+
86
+ 1. A non-zero process exit halts the loop. Use the exit code plus JSONL error messages to report `quota exhausted`, `rate limited`, `authentication failed`, `service overloaded`, or `execution failed`; do not call a quota failure merely unavailable.
87
+ 2. Exit zero with a JSONL `error` or `turn.failed` event also halts before summary parsing. Apply the same message classification. A final-output file does not override an error event.
88
+ 3. Exit zero without an error event permits final-output parsing. The file must contain exactly one valid `ITERATION_SUMMARY` for the selected ticket; otherwise halt as `invalid iteration summary`.
89
+
90
+ After every exit, record the checkout delta against the pre-iteration status for diagnosis, without mutation. Recovery may begin only after exit zero, error-free JSONL, and exactly one valid `ITERATION_SUMMARY` for the selected ticket. Missing, multiple, or wrong-ticket summaries halt without recovery. Then compare the checkout with the recorded pre-iteration status:
91
+
92
+ - A clean checkout proceeds normally.
93
+ - A coherent commit named by the valid summary proceeds to inter-iteration verification.
94
+ - Coherent staged work attributable only to the selected ticket may be recovered only after its focused tests and governance gates pass again in the outer session.
95
+ - Ambiguous, unstaged, or unrelated changes hard-block recovery. Report their paths and halt without mutation.
96
+ - When a failed iteration created known disposable paths, restore only the explicit verified path list with path-scoped Git commands. Never use a broad reset, clean, checkout, restore, or stash operation.
97
+
45
98
  ## Fix Proposal Rule
46
99
 
47
100
  A fix proposal is a release row on an existing story map, never a new file under `docs/rfcs/`. The row has an identity from `<itil-plugin-root>/bin/wr-itil-next-rfc-id`, at least one story card, and a story whose `problems:` list names the driving problem. Creating a new map, activity column, job, or uncovered architectural choice requires a queued human decision rather than a silent edit.
@@ -50,9 +103,9 @@ A fix proposal is a release row on an existing story map, never a new file under
50
103
 
51
104
  - Batch outstanding questions at loop end with `request_user_input`, no more than four per call. Brief substance before IDs.
52
105
  - Continue past skipped tickets when another actionable ticket exists.
53
- - Stop only for an explicit user stop, a fully drained backlog, a governance dependency that blocks every remaining ticket, or an unrecoverable tool/repository failure.
54
- - Never describe a delayed native tool or subagent as unavailable, hung, or blocked without an actual error or terminal failure.
106
+ - Stop only for an explicit user stop, a fully drained backlog, a governance dependency that blocks every remaining ticket, confirmed quota exhaustion, or an unrecoverable process or repository failure.
107
+ - Never describe a delayed process as unavailable, hung, or blocked without an actual error or terminal failure.
55
108
 
56
109
  ## Final Report
57
110
 
58
- Report completed and skipped tickets, commits, tests, push/release outcomes, remaining backlog, and outstanding design questions. Preserve the distinction between committed, pushed, released, and production-verified states.
111
+ Report completed and skipped tickets, commits, tests, push and release outcomes, remaining backlog, and outstanding design questions. Preserve the distinction between committed, pushed, released, and production-verified states.