@windyroad/itil 1.2.0 → 2.0.0-preview.1111

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 (266) hide show
  1. package/.agents/plugins/marketplace.json +12 -0
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.codex-plugin/plugin.json +42 -0
  4. package/README.md +34 -25
  5. package/agents/hang-off-check.md +34 -34
  6. package/bin/install.mjs +71 -5
  7. package/bin/wr-itil-catchup-scan +4 -4
  8. package/bin/wr-itil-check-deferred-placeholder-staleness +4 -4
  9. package/bin/wr-itil-check-fail-soft-skip-discipline +4 -4
  10. package/bin/wr-itil-check-fix-rfc-trace +4 -4
  11. package/bin/wr-itil-check-locale-discipline +4 -4
  12. package/bin/wr-itil-check-outbound-responses-staleness +4 -4
  13. package/bin/wr-itil-check-problems-readme-budget +4 -4
  14. package/bin/wr-itil-check-rfc-has-stories +4 -4
  15. package/bin/wr-itil-check-rfc-stories-ratified +4 -4
  16. package/bin/wr-itil-check-ticket-jtbd-ratification +4 -4
  17. package/bin/wr-itil-check-upstream-cache-staleness +4 -4
  18. package/bin/wr-itil-check-upstream-responses +4 -4
  19. package/bin/wr-itil-classify-readme-drift +4 -4
  20. package/bin/wr-itil-derive-release-vehicle +4 -4
  21. package/bin/wr-itil-detect-unratified-stories-maps +4 -4
  22. package/bin/wr-itil-effort-tally +4 -4
  23. package/bin/wr-itil-enumerate-postrelease-kv-candidates +4 -4
  24. package/bin/wr-itil-evaluate-relevance +4 -4
  25. package/bin/wr-itil-mark-create-gate +4 -4
  26. package/bin/wr-itil-mark-story-oversight-confirmed +4 -4
  27. package/bin/wr-itil-migrate-problems-layout +4 -4
  28. package/bin/wr-itil-migrate-story-status-mirror +4 -4
  29. package/bin/wr-itil-next-rfc-id +4 -4
  30. package/bin/wr-itil-plugin-exercise-index +4 -4
  31. package/bin/wr-itil-plugin-maturity-populate +4 -4
  32. package/bin/wr-itil-plugin-maturity-render +4 -4
  33. package/bin/wr-itil-plugin-validate-ci-gate +4 -4
  34. package/bin/wr-itil-reconcile-readme +4 -4
  35. package/bin/wr-itil-reconcile-rfcs +4 -4
  36. package/bin/wr-itil-reconcile-stories +4 -4
  37. package/bin/wr-itil-reconcile-story-maps +4 -4
  38. package/bin/wr-itil-render-story-map +4 -4
  39. package/bin/wr-itil-resolve-governance-plugin-dirs +4 -4
  40. package/bin/wr-itil-skill-invocations +4 -4
  41. package/bin/wr-itil-story-map-edit +4 -4
  42. package/bin/wr-itil-story-map-query +4 -4
  43. package/bin/wr-itil-update-jtbd-references-section +4 -4
  44. package/bin/wr-itil-update-problem-references-section +4 -4
  45. package/bin/wr-itil-update-problem-rfcs-section +4 -4
  46. package/bin/wr-itil-update-rfc-commits-section +4 -4
  47. package/bin/wr-itil-update-rfc-references-section +4 -4
  48. package/bin/wr-itil-verify-iter-summary +4 -4
  49. package/hooks/itil-assistant-output-gate.sh +3 -3
  50. package/hooks/itil-assistant-output-review.sh +5 -5
  51. package/hooks/itil-bash-polling-antipattern-detect.sh +11 -11
  52. package/hooks/itil-changeset-discipline.sh +24 -24
  53. package/hooks/itil-claude-space-protection.sh +21 -14
  54. package/hooks/itil-codex-dispatch.sh +164 -0
  55. package/hooks/itil-commit-trailer-transition-advisory.sh +11 -11
  56. package/hooks/itil-correction-detect.sh +8 -8
  57. package/hooks/itil-deferral-cadence-gate.sh +23 -23
  58. package/hooks/itil-fictional-defer-detect.sh +16 -16
  59. package/hooks/itil-fix-title-lifecycle-advisory.sh +11 -11
  60. package/hooks/itil-mid-loop-ask-detect.sh +14 -14
  61. package/hooks/itil-no-implement-draft-gate.sh +18 -18
  62. package/hooks/itil-pending-questions-surface.sh +11 -11
  63. package/hooks/itil-readme-refresh-discipline.sh +27 -27
  64. package/hooks/itil-rfc-oversight-nudge.sh +7 -7
  65. package/hooks/itil-rfc-trailer-advisory.sh +28 -28
  66. package/hooks/itil-runtime-sid-marker.sh +11 -11
  67. package/hooks/itil-story-mirror-migration-nudge.sh +7 -7
  68. package/hooks/lib/block-list.sh +17 -17
  69. package/hooks/lib/changeset-detect.sh +27 -27
  70. package/hooks/lib/claude-space-gate.sh +23 -15
  71. package/hooks/lib/command-detect.sh +12 -12
  72. package/hooks/lib/create-gate.sh +9 -39
  73. package/hooks/lib/detectors.sh +12 -12
  74. package/hooks/lib/readme-refresh-detect.sh +51 -51
  75. package/hooks/lib/runtime-sid.sh +12 -12
  76. package/hooks/lib/session-id.sh +28 -28
  77. package/hooks/lib/session-marker.sh +1 -1
  78. package/hooks/lib/staging-detect.sh +13 -13
  79. package/hooks/manage-problem-enforce-create.sh +16 -27
  80. package/hooks/p057-staging-trap-detect.sh +18 -18
  81. package/hooks/pre-publish-intake-gate.sh +5 -5
  82. package/hooks/staleness-check.sh +6 -6
  83. package/hooks-codex/hooks.json +57 -0
  84. package/lib/check-deferred-placeholder-staleness.sh +10 -10
  85. package/lib/check-outbound-responses-staleness.sh +2 -2
  86. package/lib/check-upstream-cache-staleness.sh +2 -2
  87. package/lib/derive-first-dispatch.sh +19 -19
  88. package/lib/enumerate-postrelease-kv-candidates.sh +18 -18
  89. package/lib/migrate-problems-layout.sh +12 -12
  90. package/lib/story-oversight.sh +27 -27
  91. package/package.json +16 -3
  92. package/scripts/catchup-scan.sh +25 -25
  93. package/scripts/check-fail-soft-skip-discipline.sh +10 -10
  94. package/scripts/check-fix-rfc-trace.sh +8 -8
  95. package/scripts/check-locale-discipline.sh +13 -13
  96. package/scripts/check-problems-readme-budget.sh +12 -12
  97. package/scripts/check-rfc-has-stories.sh +7 -7
  98. package/scripts/check-rfc-rejected-alternatives.sh +11 -11
  99. package/scripts/check-rfc-stories-ratified.sh +9 -9
  100. package/scripts/check-ticket-jtbd-ratification.sh +10 -10
  101. package/scripts/check-upstream-responses.sh +22 -22
  102. package/scripts/classify-readme-drift.sh +13 -13
  103. package/scripts/codex-agent.mjs +104 -0
  104. package/scripts/derive-release-vehicle.sh +23 -23
  105. package/scripts/detect-unoversighted-rfcs.sh +3 -3
  106. package/scripts/detect-unratified-stories-maps.sh +5 -5
  107. package/scripts/effort-tally.sh +10 -10
  108. package/scripts/evaluate-relevance.sh +16 -16
  109. package/scripts/mark-create-gate.sh +4 -4
  110. package/scripts/mark-story-oversight-confirmed.sh +14 -14
  111. package/scripts/migrate-story-status-mirror.sh +6 -6
  112. package/scripts/next-rfc-id.sh +5 -5
  113. package/scripts/plugin-exercise-index.sh +26 -26
  114. package/scripts/plugin-maturity-populate.sh +38 -38
  115. package/scripts/plugin-maturity-render.sh +26 -26
  116. package/scripts/plugin-validate-ci-gate.sh +14 -14
  117. package/scripts/reconcile-readme.sh +23 -23
  118. package/scripts/reconcile-rfcs.sh +13 -13
  119. package/scripts/reconcile-stories.sh +12 -12
  120. package/scripts/reconcile-story-maps.sh +6 -6
  121. package/scripts/render-story-map.mjs +24 -24
  122. package/scripts/render-story-map.sh +3 -3
  123. package/scripts/resolve-governance-plugin-dirs.sh +10 -10
  124. package/scripts/run-check-deferred-placeholder-staleness.sh +3 -3
  125. package/scripts/run-check-outbound-responses-staleness.sh +3 -3
  126. package/scripts/run-check-upstream-cache-staleness.sh +3 -3
  127. package/scripts/run-enumerate-postrelease-kv-candidates.sh +3 -3
  128. package/scripts/run-migrate-problems-layout.sh +3 -3
  129. package/scripts/skill-invocations.sh +29 -29
  130. package/scripts/story-map-edit.mjs +6 -6
  131. package/scripts/story-map-edit.sh +3 -3
  132. package/scripts/story-map-query.mjs +8 -8
  133. package/scripts/story-map-query.sh +3 -3
  134. package/scripts/update-jtbd-references-section.sh +8 -8
  135. package/scripts/update-problem-references-section.sh +12 -12
  136. package/scripts/update-problem-rfcs-section.sh +9 -9
  137. package/scripts/update-rfc-commits-section.sh +7 -7
  138. package/scripts/update-rfc-references-section.sh +3 -3
  139. package/scripts/update-story-references-section.sh +5 -5
  140. package/scripts/verify-iter-summary.sh +3 -3
  141. package/skills/capture-problem/REFERENCE.md +33 -33
  142. package/skills/capture-problem/SKILL.md +108 -108
  143. package/skills/capture-problem/agents/openai.yaml +3 -0
  144. package/skills/capture-rfc/SKILL.md +21 -323
  145. package/skills/capture-rfc/agents/openai.yaml +3 -0
  146. package/skills/capture-story/SKILL.md +65 -65
  147. package/skills/capture-story/agents/openai.yaml +3 -0
  148. package/skills/capture-story-map/SKILL.md +31 -31
  149. package/skills/capture-story-map/agents/openai.yaml +3 -0
  150. package/skills/check-upstream-responses/SKILL.md +38 -38
  151. package/skills/check-upstream-responses/agents/openai.yaml +3 -0
  152. package/skills/close-incident/SKILL.md +25 -25
  153. package/skills/close-incident/agents/openai.yaml +3 -0
  154. package/skills/link-incident/SKILL.md +22 -22
  155. package/skills/link-incident/agents/openai.yaml +3 -0
  156. package/skills/list-incidents/SKILL.md +9 -9
  157. package/skills/list-incidents/agents/openai.yaml +3 -0
  158. package/skills/list-problems/SKILL.md +17 -17
  159. package/skills/list-problems/agents/openai.yaml +3 -0
  160. package/skills/list-stories/SKILL.md +23 -23
  161. package/skills/list-stories/agents/openai.yaml +3 -0
  162. package/skills/list-story-maps/SKILL.md +9 -9
  163. package/skills/list-story-maps/agents/openai.yaml +3 -0
  164. package/skills/manage-incident/SKILL.md +59 -59
  165. package/skills/manage-incident/agents/openai.yaml +3 -0
  166. package/skills/manage-problem/SKILL.md +222 -222
  167. package/skills/manage-problem/agents/openai.yaml +3 -0
  168. package/skills/manage-rfc/SKILL.md +62 -62
  169. package/skills/manage-rfc/agents/openai.yaml +3 -0
  170. package/skills/manage-story/SKILL.md +49 -49
  171. package/skills/manage-story/agents/openai.yaml +3 -0
  172. package/skills/manage-story-map/SKILL.md +30 -30
  173. package/skills/manage-story-map/agents/openai.yaml +3 -0
  174. package/skills/mitigate-incident/SKILL.md +40 -40
  175. package/skills/mitigate-incident/agents/openai.yaml +3 -0
  176. package/skills/reconcile-readme/SKILL.md +28 -28
  177. package/skills/reconcile-readme/agents/openai.yaml +3 -0
  178. package/skills/reconcile-stories/SKILL.md +17 -17
  179. package/skills/reconcile-stories/agents/openai.yaml +3 -0
  180. package/skills/reconcile-story-maps/SKILL.md +11 -11
  181. package/skills/reconcile-story-maps/agents/openai.yaml +3 -0
  182. package/skills/report-upstream/SKILL.md +73 -73
  183. package/skills/report-upstream/agents/openai.yaml +3 -0
  184. package/skills/restore-incident/SKILL.md +28 -28
  185. package/skills/restore-incident/agents/openai.yaml +3 -0
  186. package/skills/review-problems/SKILL.md +129 -129
  187. package/skills/review-problems/agents/openai.yaml +3 -0
  188. package/skills/scaffold-intake/SKILL.md +26 -26
  189. package/skills/scaffold-intake/agents/openai.yaml +3 -0
  190. package/skills/transition-problem/SKILL.md +85 -85
  191. package/skills/transition-problem/agents/openai.yaml +3 -0
  192. package/skills/transition-problems/SKILL.md +69 -69
  193. package/skills/transition-problems/agents/openai.yaml +3 -0
  194. package/skills/update-upstream/SKILL.md +97 -97
  195. package/skills/update-upstream/agents/openai.yaml +3 -0
  196. package/skills/work-problem/SKILL.md +42 -42
  197. package/skills/work-problem/agents/openai.yaml +3 -0
  198. package/skills/work-problems/SKILL.md +327 -327
  199. package/skills/work-problems/agents/openai.yaml +3 -0
  200. package/skills-codex/capture-problem/REFERENCE.md +139 -0
  201. package/skills-codex/capture-problem/SKILL.md +438 -0
  202. package/skills-codex/capture-problem/agents/openai.yaml +3 -0
  203. package/skills-codex/capture-rfc/SKILL.md +45 -0
  204. package/skills-codex/capture-rfc/agents/openai.yaml +3 -0
  205. package/skills-codex/capture-story/SKILL.md +407 -0
  206. package/skills-codex/capture-story/agents/openai.yaml +3 -0
  207. package/skills-codex/capture-story-map/SKILL.md +286 -0
  208. package/skills-codex/capture-story-map/agents/openai.yaml +3 -0
  209. package/skills-codex/check-upstream-responses/SKILL.md +160 -0
  210. package/skills-codex/check-upstream-responses/agents/openai.yaml +3 -0
  211. package/skills-codex/close-incident/SKILL.md +192 -0
  212. package/skills-codex/close-incident/agents/openai.yaml +3 -0
  213. package/skills-codex/link-incident/SKILL.md +173 -0
  214. package/skills-codex/link-incident/agents/openai.yaml +3 -0
  215. package/skills-codex/list-incidents/SKILL.md +92 -0
  216. package/skills-codex/list-incidents/agents/openai.yaml +3 -0
  217. package/skills-codex/list-problems/SKILL.md +126 -0
  218. package/skills-codex/list-problems/agents/openai.yaml +3 -0
  219. package/skills-codex/list-stories/SKILL.md +170 -0
  220. package/skills-codex/list-stories/agents/openai.yaml +3 -0
  221. package/skills-codex/list-story-maps/SKILL.md +104 -0
  222. package/skills-codex/list-story-maps/agents/openai.yaml +3 -0
  223. package/skills-codex/manage-incident/SKILL.md +378 -0
  224. package/skills-codex/manage-incident/agents/openai.yaml +3 -0
  225. package/skills-codex/manage-problem/SKILL.md +1180 -0
  226. package/skills-codex/manage-problem/agents/openai.yaml +3 -0
  227. package/skills-codex/manage-rfc/SKILL.md +314 -0
  228. package/skills-codex/manage-rfc/agents/openai.yaml +3 -0
  229. package/skills-codex/manage-story/SKILL.md +284 -0
  230. package/skills-codex/manage-story/agents/openai.yaml +3 -0
  231. package/skills-codex/manage-story-map/SKILL.md +198 -0
  232. package/skills-codex/manage-story-map/agents/openai.yaml +3 -0
  233. package/skills-codex/mitigate-incident/SKILL.md +239 -0
  234. package/skills-codex/mitigate-incident/agents/openai.yaml +3 -0
  235. package/skills-codex/reconcile-readme/SKILL.md +175 -0
  236. package/skills-codex/reconcile-readme/agents/openai.yaml +3 -0
  237. package/skills-codex/reconcile-stories/SKILL.md +124 -0
  238. package/skills-codex/reconcile-stories/agents/openai.yaml +3 -0
  239. package/skills-codex/reconcile-story-maps/SKILL.md +81 -0
  240. package/skills-codex/reconcile-story-maps/agents/openai.yaml +3 -0
  241. package/skills-codex/report-upstream/SKILL.md +716 -0
  242. package/skills-codex/report-upstream/agents/openai.yaml +3 -0
  243. package/skills-codex/restore-incident/SKILL.md +216 -0
  244. package/skills-codex/restore-incident/agents/openai.yaml +3 -0
  245. package/skills-codex/review-problems/SKILL.md +524 -0
  246. package/skills-codex/review-problems/agents/openai.yaml +3 -0
  247. package/skills-codex/scaffold-intake/SKILL.md +209 -0
  248. package/skills-codex/scaffold-intake/agents/openai.yaml +3 -0
  249. package/skills-codex/scaffold-intake/templates/CONTRIBUTING.md.tmpl +31 -0
  250. package/skills-codex/scaffold-intake/templates/SECURITY.md.tmpl +39 -0
  251. package/skills-codex/scaffold-intake/templates/SUPPORT.md.tmpl +32 -0
  252. package/skills-codex/scaffold-intake/templates/config.yml.tmpl +8 -0
  253. package/skills-codex/scaffold-intake/templates/problem-report.yml.tmpl +114 -0
  254. package/skills-codex/transition-problem/SKILL.md +371 -0
  255. package/skills-codex/transition-problem/agents/openai.yaml +3 -0
  256. package/skills-codex/transition-problems/SKILL.md +310 -0
  257. package/skills-codex/transition-problems/agents/openai.yaml +3 -0
  258. package/skills-codex/update-upstream/SKILL.md +583 -0
  259. package/skills-codex/update-upstream/agents/openai.yaml +3 -0
  260. package/skills-codex/work-problem/SKILL.md +160 -0
  261. package/skills-codex/work-problem/agents/openai.yaml +3 -0
  262. package/skills-codex/work-problems/SKILL.md +58 -0
  263. package/skills-codex/work-problems/agents/openai.yaml +3 -0
  264. package/templates/story-map.css +1 -1
  265. package/bin/wr-itil-mark-rfc-capture-gate +0 -51
  266. package/scripts/mark-rfc-capture-gate.sh +0 -32
@@ -0,0 +1,1180 @@
1
+ ---
2
+ name: wr-itil:manage-problem
3
+ description: Create, update, or transition a problem ticket using an ITIL-aligned problem management workflow with WSJF prioritisation. Supports creating new problems, updating root cause analysis, transitioning status, and closing problems.
4
+ allowed-tools: Read, Write, Edit, Bash, Glob, Grep, request_user_input, Skill
5
+ deprecated-arguments: true
6
+ ---
7
+
8
+ <!-- Generated from the runtime-neutral skill source. Do not edit. -->
9
+
10
+ > Codex runtime note: use `request_user_input` only where this contract
11
+ > explicitly requires a human decision. Resolve `<itil-plugin-root>` from
12
+ > this installed `SKILL.md`: it is two directories above the skill
13
+ > directory. Run bundled commands from `<itil-plugin-root>/bin/`; do not
14
+ > search the adopter repository or rely on those commands being on `PATH`.
15
+ > Spawn `wr-itil:hang-off-check` with the native Codex subagent tool, wait
16
+ > for it, and close that same agent.
17
+
18
+
19
+ # Problem Management Skill
20
+
21
+ Create, update, or transition problem tickets following an ITIL-aligned problem management process. This skill is the authoritative definition of the problem management workflow — no separate process document is needed.
22
+
23
+ ## Output Formatting
24
+
25
+ When referencing problem IDs, ADR IDs, or JTBD IDs in prose output, always include the human-readable title on first mention. Use the format `the "Problem 029: Edit gate overhead disproportionate for governance documentation changes" problem (Edit gate overhead for governance docs)`, not bare `the "Problem 029: Edit gate overhead disproportionate for governance documentation changes" problem`. Tables with separate ID and Title columns are fine as-is.
26
+
27
+ **Brief-before-ID discipline at `request_user_input` surfaces (the "agent surfaces decisions to user using opaque IDs (P-numbers, ADR-numbers, JTBD-numbers) without explaining what they mean — empathy gap" problem).** Title-on-first-mention is the minimum for prose output. For `request_user_input` question/option/description text the rule is stricter: brief the artefact's purpose and substance BEFORE naming it by ID. `P-NNN` / `ADR-NNN` / `JTBD-NNN` / `RFC-NNN` references are audit-trail annotations, NEVER carriers of meaning — the user reads the prompt without project filesystem access (mobile clients, accessibility tooling, notification surfaces) and cannot follow links. Every option's substance MUST be self-contained in the briefing prose + the option `label` and `description`; IDs may appear ONLY after a self-contained explanation. Mirrors the canonical `/wr-architect:create-adr` Step 5 § 5a Rule 3 ("No IDs as explainers"). Applies to Step 4b's fix-strategy and verification dispatches and any other `request_user_input` site emitted by this skill. See also session memory `feedback_brief_before_id.md`.
28
+
29
+ ## First-run intake-scaffold pointer (the "Problem 065: No skill scaffolds intake files (ISSUE_TEMPLATE, SECURITY.md, CONTRIBUTING.md, SUPPORT.md) in downstream projects" problem / the "Scaffold downstream OSS intake — skill + layered triggers" architecture rule)
30
+
31
+ This skill is one of the two host skills wired to surface the [`/wr-itil:scaffold-intake`](../scaffold-intake/SKILL.md) skill on first invocation in a project that has not yet adopted the OSS intake surface. The contract is documented in [the "Scaffold downstream OSS intake — skill + layered triggers" architecture rule](../../../../docs/decisions/036-scaffold-downstream-oss-intake.proposed.md) (Scaffold downstream OSS intake — skill + layered triggers).
32
+
33
+ **Preamble check** (run before Step 0 of any operation):
34
+
35
+ 1. Look for the four intake paths: `.github/ISSUE_TEMPLATE/config.yml`, `.github/ISSUE_TEMPLATE/problem-report.yml`, `SECURITY.md`, `SUPPORT.md`, `CONTRIBUTING.md`.
36
+ 2. Look for `.codex/.intake-scaffold-declined` (explicit decline marker — never re-prompt).
37
+ 3. Look for `.codex/.intake-scaffold-done` (done marker — already scaffolded).
38
+
39
+ If any intake file is missing AND both markers are absent, surface the scaffold-intake skill:
40
+
41
+ | Mode | Behaviour |
42
+ |---|---|
43
+ | **Foreground (interactive)** | Fire one-shot `request_user_input` per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 1: header `"Scaffold OSS intake?"`, three options — **Scaffold now** (delegate to `/wr-itil:scaffold-intake`), **Not now (ask again next session)** (no marker; re-prompt next time), **Decline (never prompt in this project)** (write `.codex/.intake-scaffold-declined`). |
44
+ | **AFK orchestrator (Rule 6 fail-safe)** | Do **not** fire `request_user_input`. Append a one-line `"pending intake scaffold"` note to the iteration's `ITERATION_SUMMARY` notes field. Do **not** auto-scaffold — the ": Progress the Backlog While I'm Away" user outcome forbids the agent from making this judgement call. The user catches up on next interactive session. |
45
+
46
+ The preamble check is a one-shot; the `.intake-scaffold-done` and `.intake-scaffold-declined` markers (the "Gate Marker Lifecycle: TTL + Drift, Not Stop-Hook Reset" architecture rule persistent-marker semantics) suppress re-prompts in subsequent sessions without TTL expiry.
47
+
48
+ ## Operations
49
+
50
+ - **Create**: `problem <title or description>` — creates a new open problem
51
+ - **Update**: `problem <NNN> <update details>` — updates an existing problem (add root cause, evidence, fix strategy)
52
+ - **Transition**: `problem <NNN> known-error` — moves to known-error when root cause is confirmed
53
+ - **List**: `problem list` — shows all open problems sorted by priority
54
+ - **Work**: `problem work` — runs a review first, then begins working the highest-WSJF problem
55
+ - **Review**: `problem review` — re-assess all open problems: update priorities per RISK-POLICY.md, estimate effort, calculate WSJF, and update files
56
+
57
+ **Closing problems:** Problems are closed ONLY after the user verifies the fix in production — not when the fix is committed or released. The workflow (per the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule):
58
+ 1. When the fix is released: `git mv` the file from `.known-error.md` to `.verifying.md`, update the Status field to "Verification Pending", AND add a `## Fix Released` section (e.g., `Deployed in v0.26.X. Awaiting user verification.`). All three edits land in the same commit per the "Governance Skills Commit Their Own Completed Work" architecture rule.
59
+ 2. When the user explicitly confirms ("it's fixed", "verified", "working"): `git mv` from `.verifying.md` to `.closed.md`, update the Status field to "Closed", and reference the problem in the commit message (e.g., "Closes the "Problem 008: request_user_input Unavailable When --channels Is Active" problem").
60
+ 3. Never assume the fix works — always wait for explicit user confirmation before closing.
61
+
62
+ The `.verifying.md` suffix distinguishes "fix released, awaiting user verification" from "root cause identified AND workaround documented; fix not yet proposed" (the Known Error meaning per the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule corrected semantics, 2026-06-08 amendment; the fix proposal happens AFTER Known Error and draws a release row on a story map). See the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule for rationale.
63
+
64
+ ## Problem Lifecycle
65
+
66
+ | Status | File suffix | Meaning | Entry criteria |
67
+ |--------|-----------|---------|----------------|
68
+ | **Open** | `.open.md` | Reported, under investigation | New problem identified |
69
+ | **Known Error** | `.known-error.md` | Root cause identified AND workaround documented; **fix not yet proposed** (the fix proposal draws a release row on a story map) | Root cause documented, reproduction test exists, workaround in place |
70
+ | **Verification Pending** | `.verifying.md` | Fix released, awaiting user verification (the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule) | Fix shipped; `## Fix Released` section written; user action remaining |
71
+ | **Parked** | `.parked.md` | Blocked on upstream or suspended by user decision | Upstream blocker identified, or user explicitly suspends; reason and un-park trigger documented |
72
+ | **Closed** | `.closed.md` | Fix verified in production OR ticket determined no longer relevant via evidence | (a) User explicitly confirms the released fix works (canonical Verifying → Closed path), OR (b) auto-closed by `/wr-itil:review-problems` Step 4.6 relevance-close pass per 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 Phase 1 + Phase 2 evidence shapes — `file-no-longer-exists` / `ADR-shipped-confirmed` / `named-skill-or-feature-exists` / `self-marker-in-body` / `driver-child-ticket-closed` (cumulative; multi-shape matches emit comma-joined) with `## Closed as no longer relevant` audit section per the "Agent output grounding — no fabricated quantitative estimates, cite + persist + uncertainty" architecture rule grounding (extends the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule lifecycle: Open\|Known Error → Closed bypasses Verifying when no fix was released). Partial-scope umbrellas emit `CLOSE-CANDIDATE-WITH-CAVEAT` and ride the maintainer's `request_user_input` surface-batch-confirm path. |
73
+
74
+ **Parked problems** are excluded from WSJF ranking and work selection. They are listed separately in review output so users can see them without them polluting the backlog. To park a problem:
75
+ 1. **If the park reason is `upstream-blocked`**, run the external-root-cause detection block at Step 7 first (see "External-root-cause detection (the "Problem 063: manage-problem does not trigger /wr-itil:report-upstream when root cause is external" problem)"). Park without recording the upstream dependency in `## Related` would be the canonical audit-trail gap this block closes.
76
+ 2. `git mv docs/problems/<current>/<NNN>-<title>.md docs/problems/parked/<NNN>-<title>.md`
77
+ 3. Update the Status field to "Parked"
78
+ 4. Add a `## Parked` section with: reason for parking, expected trigger to un-park, date parked
79
+
80
+ To un-park: `git mv` back to `docs/problems/open/<NNN>-<title>.md` (or `docs/problems/known-error/<NNN>-<title>.md` if root cause is confirmed), update Status, remove `## Parked` section.
81
+
82
+ **Verification Pending problems** are also excluded from WSJF ranking — their remaining work is user-side verification, not dev effort. They appear in a dedicated "Verification Queue" section in review output so the user can see what's waiting on them without mixing with dev-work ranking. See step 9c for the queue layout.
83
+
84
+ **Allowed optional appendages**: a problem ticket file may carry a `## Reported Upstream` section appended after the standard sections. This is written by the `/wr-itil:report-upstream` skill (per the "Cross-project problem-reporting contract — `report-upstream` skill in `@windyroad/itil`" architecture rule Confirmation criterion 3a) and records the upstream URL — an issue, a pull request (per the "Prefer an upstream pull request over an issue when the upstream accepts pull requests" architecture rule), or an advisory — plus the matched template and the disclosure path. The presence or absence of this section does not affect WSJF ranking or status transitions.
85
+
86
+ **Test-driven resolution:** When root cause is identified, create a failing test that reproduces the problem. Skip/disable the test if a feature-disabling workaround is applied. Re-enable the test when the permanent fix is implemented — the test passing confirms resolution.
87
+
88
+ ## WSJF Prioritisation
89
+
90
+ Problems are ranked using Weighted Shortest Job First (WSJF):
91
+
92
+ **WSJF = (Severity × Status Multiplier) / Effort**
93
+
94
+ **Severity** = Impact × Likelihood (1-25) from `RISK-POLICY.md`. Read the impact levels, likelihood levels, and risk matrix from the policy — do not hardcode them here.
95
+
96
+ **Status Multiplier** (known-errors have identified root cause AND documented workaround — ready for fix proposal; higher value per unit of work because the diagnostic uncertainty is resolved):
97
+
98
+ | Status | Multiplier |
99
+ |--------|-----------|
100
+ | Known Error | 2.0 |
101
+ | Open | 1.0 |
102
+ | Verification Pending | 0 (excluded) |
103
+ | Parked | 0 (excluded) |
104
+
105
+ `Verification Pending` and `Parked` tickets are excluded from the main dev-work ranking per the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule (verification) and the Parked policy above. `Verification Pending` remaining work is user-side confirmation, not dev effort, so mixing it into the dev-work queue would distort WSJF. Both are surfaced in dedicated sections (see step 9c) — not in the ranked table.
106
+
107
+ **Effort** (estimated fix size — smaller effort = higher priority):
108
+
109
+ | Effort | Divisor | Description |
110
+ |--------|---------|-------------|
111
+ | S | 1 | < 1 hour, single file, quick fix |
112
+ | M | 2 | 1-4 hours, few files, moderate change |
113
+ | L | 4 | 4 hours – 1 day, multiple files, significant change within a single plugin |
114
+ | XL | 8 | > 1 day, multi-day or cross-package work (multiple plugins, migration, new ADR required) |
115
+
116
+ **Example**: A Known Error with severity 8 (Impact 4 × Likelihood 2) and Small effort:
117
+ WSJF = (8 × 2.0) / 1 = **16.0** — do this first.
118
+
119
+ An Open problem with severity 6 (Impact 3 × Likelihood 2) and Large effort:
120
+ WSJF = (6 × 1.0) / 4 = **1.5** — lower priority despite medium severity.
121
+
122
+ An Open problem with severity 8 (Impact 2 × Likelihood 4) and Extra-Large effort (multi-day, cross-package):
123
+ WSJF = (8 × 1.0) / 8 = **1.0** — defer until severity climbs or scope shrinks.
124
+
125
+ When estimating effort, read the problem's root cause analysis and fix strategy. If effort is unknown, default to M (2). Effort is a **live estimate**, not a set-once label: re-rate it when root cause is confirmed, when architect review narrows or expands scope, and during each `manage-problem review`. A note capturing the reason for any bucket change makes the ranking audit-able (see steps 7 and 9b).
126
+
127
+ ### Transitive dependencies (the "Problem 076: WSJF scoring in manage-problem does not model transitive dependencies" problem)
128
+
129
+ > **Serves**: the ": Enforce Governance Without Slowing Down" user outcome (enforce governance without slowing down — queue must not lie), the ": Progress the Backlog While I'm Away" user outcome (progress the backlog while I'm away — AFK orchestrator iterates top-down on a trustworthy rank), the "Restore Service Fast with an Audit Trail" user outcome (restore service fast with an audit trail — ranking decisions must be defensible post-hoc).
130
+
131
+ Effort is scored per-ticket as a **marginal** estimate (the work this ticket adds on top of its upstream dependencies). When a ticket has upstream dependencies — other tickets that must close first before this one can reach "done" — the ticket's effective effort for WSJF purposes is the **transitive closure** of its marginal effort plus all blocking upstreams, not the marginal alone.
132
+
133
+ **Rule**:
134
+
135
+ ```
136
+ Effort(T)_transitive = max(
137
+ Effort(T)_marginal,
138
+ max{ Effort(U)_transitive | U ∈ Blocked_by(T) }
139
+ )
140
+
141
+ WSJF(T) = (Severity(T) × StatusMultiplier(T)) / Effort(T)_transitive
142
+ ```
143
+
144
+ A dependent ticket cannot reach its "done" state without the upstream work happening first. Scoring the dependent at its marginal-only effort lies about what it costs to deliver — the **queue** would rank it higher than its blocker even though the blocker's work is strictly contained within it.
145
+
146
+ **Dependency signal**: drive the closure from the ticket's `## Dependencies` section (see the Step 5 template). Only `**Blocked by**` entries propagate effort; `**Composes with**` does NOT propagate — compositional overlap shares surface but neither side strictly blocks.
147
+
148
+ **Upstream status carve-out**: an upstream ticket in `.closed.md`, `.verifying.md`, or `.parked.md` contributes **0** to the transitive closure. Closed upstream work is done; verifying upstream work is user-side (not dev effort and excluded from dev ranking per the WSJF multiplier table); parked upstream work is suspended (excluded from ranking until un-parked). Without this carve-out, a ticket blocked by a closed ticket would inherit XL forever.
149
+
150
+ **Cycle handling**: when two or more tickets mutually block each other (e.g., shared gate-surface tickets that each list the other under `**Blocked by**`), treat the strongly-connected component as a **bundle**. The bundle's effective effort is `max{ marginal | members }`. All bundle members surface the same WSJF in review output — the shared WSJF is a **computed artefact** of the rendering, not written as a field into individual ticket files. Bundle members retain their individual Status suffixes and individual ticket files (the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule suffix-based lifecycle).
151
+
152
+ **Re-rate on upstream status change**: when a dependency transitions to `.closed.md` / `.verifying.md` / `.parked.md`, the dependent ticket's transitive closure shrinks and the effort drops accordingly. Step 9b catches this automatically — no transition-time graph re-walk is required.
153
+
154
+ **Worked example**: the "Problem 073: No voice-and-tone check or risk assessment on changeset bodies (which populate CHANGELOG.md, Release PRs, GitHub Releases, and npm release notes)" problem has marginal effort S (one surface-row add). the "Problem 073: No voice-and-tone check or risk assessment on changeset bodies (which populate CHANGELOG.md, Release PRs, GitHub Releases, and npm release notes)" problem is blocked by the "Problem 038: No voice-and-tone gate on external communications" problem (XL). Then:
155
+
156
+ ```
157
+ Effort(the "Problem 073: No voice-and-tone check or risk assessment on changeset bodies (which populate CHANGELOG.md, Release PRs, GitHub Releases, and npm release notes)" problem)_transitive = max(S=1, Effort(the "Problem 038: No voice-and-tone gate on external communications" problem)_transitive) = max(1, 8) = 8
158
+ WSJF(the "Problem 073: No voice-and-tone check or risk assessment on changeset bodies (which populate CHANGELOG.md, Release PRs, GitHub Releases, and npm release notes)" problem) = (Severity(the "Problem 073: No voice-and-tone check or risk assessment on changeset bodies (which populate CHANGELOG.md, Release PRs, GitHub Releases, and npm release notes)" problem) × 1.0) / 8 = 12 / 8 = 1.5
159
+ ```
160
+
161
+ the "Problem 073: No voice-and-tone check or risk assessment on changeset bodies (which populate CHANGELOG.md, Release PRs, GitHub Releases, and npm release notes)" problem's WSJF matches the "Problem 038: No voice-and-tone gate on external communications" problem's by construction — the "Problem 073: No voice-and-tone check or risk assessment on changeset bodies (which populate CHANGELOG.md, Release PRs, GitHub Releases, and npm release notes)" problem cannot out-rank the ticket whose work is strictly contained within it. Contrast with the marginal-only (incorrect) computation: `12 / 2 = 6.0`, which would mis-rank the "Problem 073: No voice-and-tone check or risk assessment on changeset bodies (which populate CHANGELOG.md, Release PRs, GitHub Releases, and npm release notes)" problem as "top of queue" despite being blocked.
162
+
163
+ **Determinism**: the rule is deterministic from the graph — no `request_user_input` branch is required when Step 9b re-rates a ticket. The re-rate fires silently and is logged in the review output per the Step 9b re-rate message format.
164
+
165
+ **Reassessment criteria**: this rule lives inline in manage-problem's SKILL.md (following the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule's precedent for inline WSJF additions). If a second skill (e.g., manage-incident or a future cross-plugin `work-backlog` orchestrator) adopts the `## Dependencies` section and the transitive-effort rule, extract to a sibling ADR at that point — wider adoption justifies the ADR cost that today's single-skill scope does not.
166
+
167
+ ## Working a Problem
168
+
169
+ What "work" means depends on the problem's status:
170
+
171
+ **Open problem (no confirmed root cause):**
172
+ 1. Read the problem description and any preliminary hypotheses
173
+ 2. Investigate the root cause — read relevant source code, run experiments, query prod data. Do NOT guess.
174
+ 3. Document findings in the Root Cause Analysis section with evidence
175
+ 4. Create a failing reproduction test (can be skipped/disabled)
176
+ 5. Identify a workaround (even "delete and re-enter" counts)
177
+ 6. Update the problem file with all findings
178
+ 7. **Transition to Known Error immediately** — once root cause and workaround are documented, `git mv` the file to `.known-error.md` and update the Status field. Do not wait for a separate review.
179
+ 8. If the fix is small enough, continue straight to implementing it (becoming a Known Error → Closed flow in one session)
180
+
181
+ **Known Error (root cause identified AND workaround documented; ready for fix proposal):**
182
+
183
+ **Substance-confirm-before-build guard (the ": Confirm a decision's substance before building dependent work on it" architecture rule — propose-fix surface, the "Problem-RFC-Story framework with mandatory problem-trace and unified problem ontology" architecture rule I13).** BEFORE implementing any fix step below, check whether the fix builds on a genuine decision whose **substance is unconfirmed**. This closes the "Agent implements dependent work on genuine new decisions before human-confirming their SUBSTANCE — surfaces only meta-questions" problem (dependent work built on a born-`proposed` decision the user later rejects):
184
+
185
+ 1. Collect the decisions this fix builds on: the `ADR-NNN` references in the problem's `## Fix Strategy` section PLUS the `adrs:` frontmatter array (and body `ADR-NNN` mentions) of each referenced RFC.
186
+ 2. For each, run the predicate (PATH shim per the "Plugin-bundled scripts invoked from SKILL.md resolve via `bin/` on `$PATH`" architecture rule — adopter-safe, never source repo-relative lib files):
187
+ ```bash
188
+ wr-architect-is-decision-unconfirmed ADR-<NNN> docs/decisions
189
+ ```
190
+ Exit 0 = unconfirmed (born without `human-oversight: confirmed`, not superseded) → the guard fires for that ADR. Exit 1 = confirmed or superseded → OK to build. Exit 2 = not found → treat as not-a-blocker (surface in the report).
191
+ 3. **If any referenced decision is unconfirmed**: do NOT implement yet. Surface its **substance** (the chosen option the ADR records — not a grain/meta question) for human confirmation:
192
+ - **Interactive**: `request_user_input` presenting the ADR's Decision Outcome + Considered Options so the user confirms / amends / rejects the substantive choice. On confirm, the recording skill writes the `human-oversight: confirmed` marker (the ": Human-oversight marker + `/wr-architect:review-decisions` drain for recorded decisions" architecture rule) before the build proceeds.
193
+ - **AFK** (`/wr-itil:work-problems` orchestrator): NEVER ask mid-loop — queue the substance to the iteration's `outstanding_questions` (the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule AFK carve-out) and skip the build; do not guess. This is the **queue-and-continue** universal default per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6 (the "AFK iter default when a skill needs to ask a question and request_user_input is unavailable — should queue the question and move to the next iteration (not halt, not silently skip)" problem, 2026-06-06 amendment): the iter queues the substance + advances; the orchestrator main turn surfaces the queued question at loop end via the Step 2.5 batched request_user_input.
194
+ 4. This ask is **the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule category-1 direction-setting** and is EXCLUDED from the lazy-request_user_input regression metric (it is legitimate, not lazy). The trigger is narrow — detection is mechanical (the predicate); only genuine unconfirmed decisions about to be built on fire it. Do NOT over-fire on confirmed/superseded/obvious decisions (inverse-the "Problem 078: Assistant does not offer to capture a problem ticket when the user delivers strong-signal correction" problem / the "Agents over-ask in interactive sessions — conflating mechanical-stages with user-interactive-stages of multi-stage skill contracts (inverse-)" problem guard). A born-`proposed` marker is fine for *recording*; it is not a licence to *build* (the ": Human-oversight marker + `/wr-architect:review-decisions` drain for recorded decisions" architecture rule carve-out).
195
+
196
+ **I13 propose-fix trace gate (the ": RFC-first trace invariant not enforced at fix-time" release design B3/B4).** BEFORE the traversal below, enforce the fix-time trace invariant: a fix proposed on a Known Error requires a fix vehicle that traces the problem (the "Every fix goes through an RFC" architecture rule unconditional; the "RFC required at the propose-fix step on a Known Error" architecture rule places the gate here, conforming to the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule Known Error semantics — the fix is proposed *after* Known Error).
197
+
198
+ **A fix proposal is a release row on a story map. It is never a new document under `docs/rfcs/`.** The row carries the RFC identity, and the map is where a person approves the work; a fix written up as its own document reaches neither. The documents already on disk stay readable and keep working — they simply stop being the thing a fix proposal creates, and each converts to a row when its own problem is next worked.
199
+
200
+ Run the load-bearing predicate (the "Plugin-bundled scripts invoked from SKILL.md resolve via `bin/` on `$PATH`" architecture rule `$PATH` shim — never repo-relative from a SKILL):
201
+
202
+ ```bash
203
+ <itil-plugin-root>/bin/wr-itil-check-fix-rfc-trace <problem-file>
204
+ ```
205
+
206
+ - **Exit 0, empty stdout** (something already proposes a fix for this problem — a release row, or a legacy document whose `problems:` array names it): proceed to the traversal below.
207
+ - **Exit 3** (the predicate refuses to answer, and says which of two reasons on stdout):
208
+ - **A map was edited without being re-rendered.** Mechanical, and nobody is asked about it: re-render the maps the directive names with `<itil-plugin-root>/bin/wr-itil-render-story-map <map.html>`, then run the predicate again. Escalate only if a clean re-render still refuses.
209
+ - **The repository holds no story maps at all.** Drawing the first map for a journey decides what that journey *is*, so it needs a person and must not be created automatically. Record **one** item — draw a story map covering this work — and carry on to the next problem. Interactively that is an `request_user_input`; under the AFK orchestrator it is a single `outstanding_questions` entry. Do not stop the loop.
210
+ - **Exit 0, non-empty stdout** (directive `no-rfc-trace: P<NNN> …`): nothing proposes a fix yet. The predicate has confirmed only that *no row and no document names this PID* — it has NOT decided that no fix vehicle exists. Distinguish **two sub-cases** before acting (the "manage-problem I13 propose-fix gate auto-creates a new RFC instead of wiring an existing fix-vehicle's trace edge" problem — the auto-draw below is intended ONLY when no fix vehicle exists, NOT when an existing vehicle merely lacks the trace edge — architect-confirmed):
211
+ - **(a) Existing-vehicle-untraced — a vehicle is already this ticket's fix but just hasn't wired the trace edge.** Read the ticket's `## Fix Strategy` / `## Resolution` / `## Dependencies` / `## Related` sections for an RFC cited as the **fix vehicle** — i.e. the fix IS that RFC's task set (the recurring shape: a rework / follow-on Known Error whose fix is an existing vehicle's remaining tasks, so that vehicle's trace names the *original driver* problem, not this ticket). This is a **judgement read of the citation context, NOT a blind "any cited RFC" match**: an RFC named only as context / `composes with` / `**Related**` background is NOT a fix vehicle — wiring its trace edge would pollute its trace. If a genuine existing fix vehicle is found:
212
+ - **If it is a release row**, add a story card to that row for this ticket's fix and make the card's story file name `P<NNN>` in its own `problems:` list. That card IS the trace edge; the link from a row to a problem is read through its cards, so there is nothing else to wire.
213
+ - **If it is a legacy document**, wire this problem into its frontmatter `problems:` array (Edit the `problems: [...]` line to include `P<NNN>` + a short inline `**Problems**:` body annotation noting the edge was wired because the vehicle already exists). This is the one edit a legacy document still takes, and only because the vehicle predates the row model; do not author new scope into it.
214
+ Then run `<itil-plugin-root>/bin/wr-itil-update-problem-rfcs-section <problem-file>` so the ticket's derived `## RFCs` section reflects the wired trace, re-run the predicate (now empty) and proceed. Do **NOT** draw a second vehicle — a duplicate fragments the fix across two traces (the exact the "manage-problem I13 propose-fix gate auto-creates a new RFC instead of wiring an existing fix-vehicle's trace edge" problem defect). Structured-log the wire event (e.g. `I13: wired P<NNN> trace edge into existing fix vehicle <ID>`) to the iter summary `notes` for the ": Progress the Backlog While I'm Away" user outcome audit trail.
215
+ - **(b) No-vehicle — nothing is this ticket's fix vehicle yet. Draw the release row.** Do NOT block, do NOT skip, and do NOT ask: this is framework-mediated, not direction-setting, and drawing a row onto a map a person has already approved inherits that approval rather than needing a fresh one. NO `request_user_input` consent gate fires on this path (the "Agents over-ask in interactive sessions — conflating mechanical-stages with user-interactive-stages of multi-stage skill contracts (inverse-)" problem / inverse-the "Problem 078: Assistant does not offer to capture a problem ticket when the user delivers strong-signal correction" problem; the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule framework-resolution boundary).
216
+
217
+ 1. Pick a story map that **already covers this journey** — right persona, and its job traces already include the job this fix's story serves.
218
+ 2. Take the identity the predicate's directive named. Do not compute one yourself: `<itil-plugin-root>/bin/wr-itil-next-rfc-id` is the single definition, and it is the only rule that sees rows, documents and git history at once. A rule that reads only the document directory re-issues an identity a row already holds.
219
+ 3. Draw the row and give it at least one card:
220
+
221
+ ```bash
222
+ <itil-plugin-root>/bin/wr-itil-story-map-edit <map.html> add-band --id rfc-<nnn> --name "<what shipping this row gets the user>" --rfc RFC-<NNN>
223
+ <itil-plugin-root>/bin/wr-itil-story-map-edit <map.html> add-card --story STORY-<NNN> --activity <existing-activity-id> --release rfc-<nnn> --title "<the story's title>"
224
+ ```
225
+
226
+ The card's story is captured through `/wr-itil:capture-story` as normal, and **its frontmatter `problems:` list must name `P<NNN>`** — the link from a row to a problem is read through its cards, so a row without that card will still read as untraced and this gate will loop. A row carrying an identity with no card is a defect on the same footing as an untraced one.
227
+ 4. Re-run the predicate (now empty) and proceed. Structured-log the draw event to the iter summary `notes`.
228
+
229
+ **Queue for a person instead — minting nothing — in either of these cases.**
230
+ - **The draw would change what the map's approval covers.** The keys that decide a map's ratification are enumerated in exactly one place, `oversight_map_substance_keys()` in `lib/story-oversight.sh`; adding a release row and a card touches none of them, which is precisely why the row inherits approval. If drawing this row would instead need a **new map**, a **new activity column**, or a **new job on the map's traces** — a map that covers the journey but does not trace the job this fix's story serves — then it changes substance a person approved, and doing it silently would void the very approval it was relying on. Derive this from that one function rather than restating its members here, so an amendment to the tuple cannot leave this gate behind.
231
+ - **The fix approach is a choice no existing decision record covers.** Recording a new decision is a person's call, not a byproduct of working a ticket.
232
+
233
+ Interactively, surface the queued item via `request_user_input`. Under the AFK orchestrator, queue it at `outstanding_questions` and move to the next problem — never ask mid-loop.
234
+
235
+ The predicate is the load-bearing detection half (committed shell + behavioural bats per the "Behavioural-tests-default for skill testing" architecture rule: `<itil-plugin-root>/scripts/test/check-fix-rfc-trace.bats`), and it reads BOTH tiers — a release row's cards and a legacy document's `problems:` array — so repointing it cannot hard-stop work that used to proceed. This gate fires at **every** fix-time surface; the AFK `/wr-itil:work-problems` orchestrator dispatches its fix work *through this same manage-problem traversal*, so the gate covers the AFK surface transitively.
236
+
237
+ The Phase 2 working-the-problem traversal makes "implement the fix" concretely traceable via stories (per the "Problem-RFC-Story framework with mandatory problem-trace and unified problem ontology" architecture rule lines 300-320). Replaces the prior vague "implement the fix following the project's development workflow" with a deterministic problem → RFC → story dispatch:
238
+
239
+ 1. **Read the problem's `## Fix Strategy` section** — extract referenced RFC IDs (anchor links / inline references like `RFC-NNN`). The I13 gate above has already guaranteed a vehicle traces the problem; if the `## Fix Strategy` prose itself references none (a row drawn moments ago may not yet be cited inline), fall through to the legacy direct-implementation path (step 6 below) using the row the gate just drew, or the vehicle it found.
240
+ 2. **For each referenced RFC** (in the order they appear in the Fix Strategy section), read its frontmatter `stories:` array (per the "Problem-RFC-Story framework with mandatory problem-trace and unified problem ontology" architecture rule line 259, the array is ORDERED — array position IS execution sequence):
241
+ - **Non-empty `stories:` array** (story-decomposed RFC): pick the first story whose lifecycle status is `accepted` or `in-progress` — skip `done` stories that already shipped, skip `draft` stories that aren't ready (the `manage-story <NNN> accepted` gate enforces INVEST shape; a draft story is structurally unready). Continue to step 3.
242
+ - **Empty `stories: []`** (a **legacy** pre-the "Every RFC has at least one story" architecture rule RFC, or one not yet decomposed): per **the "Every RFC has at least one story" architecture rule** every RFC has ≥1 story — an empty `stories:` is a **back-fill** state, NOT a legitimate atomic shape. Back-fill the fix's story onto the RFC's story map (add ≥1 story, transition it `accepted` via `manage-story`), then re-traverse from step 2. The empty-stories atomic fallback is removed — do NOT close the problem on a story-less RFC.
243
+ 3. **Read the picked story's body** — `## User value` statement (INVEST Valuable), `## Acceptance criteria` (INVEST Testable observable behaviours), `## Implementation notes` (architecture sketches, library decisions). The story's frontmatter `estimated-effort` field (set at `manage-story accepted` transition per I10 INVEST Estimable) sets the appetite for the iteration.
244
+ 4. **Implement the story scope** — follow the project's standard development workflow (plan if needed, architect/JTBD review, behavioural tests per the "Behavioural-tests-default for skill testing" architecture rule, single-commit grain per the "Governance Skills Commit Their Own Completed Work" architecture rule). Confine the implementation to the picked story's acceptance criteria; deviating into adjacent unscoped work is a scope-expansion signal — surface it via the `## Scope expansion` request_user_input below.
245
+ 5. **Commit with the `Refs: STORY-<NNN>` trailer** (single-trailer vocabulary per the "Problem-RFC-Story framework with mandatory problem-trace and unified problem ontology" architecture rule line 307 + amendment 2026-05-10 nitpick N2 — same trailer verb whether the commit is the story's first implementation commit or a continuation). On the FIRST commit AFTER the capture commit (subject prefix discriminates: `feat(itil): capture STORY-NNN ...` is the capture; any other subject prefix is an implementation commit), `/wr-itil:manage-story` auto-transitions the story `draft → in-progress`. As acceptance criteria checkboxes are ticked across multiple commits, the same trailer continues to attribute the work.
246
+ 6. **Story `done` auto-transition**: when ALL acceptance-criteria checkboxes in the story body are ticked AND the linked RFC reaches `closed`, `/wr-itil:manage-story` auto-transitions the story `in-progress → done`. (When a story's RFC is still `in-progress` but the acceptance criteria are all ticked, the story stays at `in-progress` until the RFC closes — this preserves the trace coupling per the "Problem-RFC-Story framework with mandatory problem-trace and unified problem ontology" architecture rule line 309.)
247
+ 7. **Pick the next not-done story** from the RFC's `stories:` array. Repeat from step 3.
248
+ 8. **When all stories under all referenced RFCs are done** — the problem is fix-released. Include the problem doc closure in the final commit (`git mv` to `.verifying.md`, update Status) per the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule. Push, create changeset, release per the lean release principle.
249
+
250
+ **Legacy empty-stories back-fill (per the "Every RFC has at least one story" architecture rule)**: a pre-the "Every RFC has at least one story" architecture rule RFC whose `stories:` is empty is a **back-fill** case, not an atomic fallback — the "Every RFC has at least one story" architecture rule requires ≥1 story, so the empty-stories atomic dispatch is removed. Decompose the fix into ≥1 story on the RFC's story map (add the story, transition it `accepted`), then traverse it via the normal story path above. The `Refs: RFC-<NNN>` trailer remains valid for **cross-cutting RFC work with no single story** (e.g. an RFC-level enforcement change spanning several files); it is no longer an atomic-empty-stories fallback. Legacy on-disk RFCs still carrying `stories: []` are surfaced for back-fill by `<itil-plugin-root>/bin/wr-itil-check-rfc-has-stories` at their next `manage-rfc accepted` transition.
251
+
252
+ **Legacy direct-implementation path** (step 1 no-RFCs case): a Phase 1-shape Known Error whose Fix Strategy references no RFCs continues to work via the pre-Phase-2 flow — read the root cause analysis and fix strategy, implement the fix following the project's development workflow, include the problem doc closure in the fix commit (`git mv` to `.verifying.md`, update Status), push + changeset + release. This preserves backwards compatibility with all existing Known Error problems (which were captured before the RFC framework was Phase-1-graduated).
253
+
254
+ **Scope expansion during work:** If investigation or architect review reveals that the problem's scope has grown significantly (e.g., effort re-sized from S to L, additional files discovered), use `request_user_input` before continuing:
255
+ - Option 1: `Continue with expanded scope` — keep working this problem at its new size
256
+ - Option 2: `Update problem and re-rank` — save findings to the problem file, re-score WSJF, and re-run the work selection to let the user pick from the updated queue
257
+ - Option 3: `Pick a different problem` — park this one and work something else
258
+ - Use `header: "Scope change"` and `multiSelect: false`
259
+
260
+ **In both cases:** After completing work on one problem, run `problem work` again to pick up the next highest-WSJF problem. Keep going until the user says stop or no more problems are actionable.
261
+
262
+ ## Steps
263
+
264
+ ### 0a. Auto-migrate adopter layout (the "Problem tickets strain as fixes decompose into multiple coordinated changes — need an RFC framework that ties all changes back to problems (and unifies technical with user/business problems)" problem / the ": docs/problems/ flat layout migration — per-state subdirs + adopter auto-migration" release design / the "Problem-ticket directory layout — per-state subdirectories under `docs/problems/`" architecture rule)
265
+
266
+ Before the README-reconciliation preflight (Step 0) and any other layout-dependent logic, source the shared shell migration routine and call the idempotent entrypoint:
267
+
268
+ ```bash
269
+ <itil-plugin-root>/bin/wr-itil-migrate-problems-layout "$PWD"
270
+ ```
271
+
272
+ `<itil-plugin-root>/bin/wr-itil-migrate-problems-layout` is the "Plugin-bundled scripts invoked from SKILL.md resolve via `bin/` on `$PATH`" architecture rule `$PATH` shim (adopter-safe — resolves the canonical `lib/migrate-problems-layout.sh` relative to the script, NOT cwd; the "capture-problem / capture-rfc / manage-problem Step 2 create-gate marker step sources repo-relative `<itil-plugin-root>/hooks/lib/*.sh` — fails in adopter installs (recurring published-path class: //)" problem/the ": Adopter-safe path resolution in shipped SKILLs ( — 24 repo-relative references)" release design) that internalises the former inline `source <itil-plugin-root>/lib/migrate-problems-layout.sh; migrate_problems_to_per_state_layout "$PWD"`. NEVER `source packages/...` repo-relative from a SKILL — those paths only resolve in the source monorepo, not adopter installs.
273
+
274
+ The routine is **idempotent and partial-migration-safe**. It no-ops when no flat-layout files (`docs/problems/*.<state>.md` at the top level of `docs/problems/`) are detected — the common case in this monorepo (post-Slice-5 T5a 2026-05-10) and in freshly-migrated adopter repos.
275
+
276
+ On a flat-layout adopter repo (first invocation post-update — the "Extend the Suite with New Plugins" user outcome plugin-developer auto-migration path), the routine:
277
+
278
+ 1. Creates the five state subdirectories (`docs/problems/open/`, `/known-error/`, `/verifying/`, `/parked/`, `/closed/`).
279
+ 2. Runs `git mv docs/problems/<NNN>-<slug>.<state>.md docs/problems/<state>/<NNN>-<slug>.md` for every existing ticket. `nullglob` is enabled so partial-migration tails don't trip on literal-glob expansion.
280
+ 3. Emits a standalone commit (per the "Problem-ticket directory layout — per-state subdirectories under `docs/problems/`" architecture rule § Backward Compatibility line 124 "not folded into other work — so adopters can audit / revert in isolation") with subject `docs(problems): auto-migrate to per-state subdirectory layout (the "Problem-ticket directory layout — per-state subdirectories under `docs/problems/`" architecture rule)` and footer trailer `RISK_BYPASS: adr-031-migration` (recognised by the commit-gate hook per T11; allows the migration to skip the full risk-score overhead while preserving the audit trail).
281
+
282
+ **AFK authorisation per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6**: this fires unconditionally even in AFK / non-interactive / orchestrated mode. Pure-rename + pure-mkdir + standalone-commit actions are policy-authorised under the "AFK orchestrator preflight: get the repo into a clean state before starting" architecture rule precedent — they are fully reversible (`git revert`), have no external-comms surface, no secrets, no destructive overwrite. No `request_user_input` gate.
283
+
284
+ **First-fire signal (the ": Progress the Backlog While I'm Away" user outcome AFK transparency per T8 jtbd-review nitpick c)**: the routine emits a single stderr line `migrate-problems-layout: relocated N tickets to per-state subdirs (the "Problem-ticket directory layout — per-state subdirectories under `docs/problems/`" architecture rule)` on the migrating invocation; silent on no-op re-invocations.
285
+
286
+ After Step 0a completes (whether no-op or migration), proceed to Step 0 README reconciliation preflight. The reconcile-readme script reads the post-migration layout; the in-flow Step 5 / Step 7 README refresh paths re-render the README from the per-state subdir shape.
287
+
288
+ ### 0. README reconciliation preflight (the "`docs/problems/README.md` drifts from filesystem truth across sessions despite (refresh-on-create) and (refresh-on-transition) both Closed" problem)
289
+
290
+ Before parsing the request, run the diagnose-only reconciliation check. The contract here catches **cross-session drift** that per-operation refresh paths (the "Problem 094: `/wr-itil:manage-problem` does not refresh `docs/problems/README.md` on ticket creation" problem refresh-on-create + the "Problem 062: `manage-problem` does not refresh `docs/problems/README.md` on single-ticket transitions; fast-path cache goes stale silently" problem refresh-on-transition) cannot retroactively see — if any past session committed a ticket change without staging the README refresh, the next manage-problem invocation reads a stale README that lies about what is open / verifying / closed.
291
+
292
+ ```bash
293
+ <itil-plugin-root>/bin/wr-itil-reconcile-readme docs/problems
294
+ ```
295
+
296
+ The `<itil-plugin-root>/bin/wr-itil-reconcile-readme` command is a `$PATH`-resolved shim shipped in `<itil-plugin-root>/bin/` that dispatches the canonical `<itil-plugin-root>/scripts/reconcile-readme.sh` body. the "Plugin-bundled scripts invoked from SKILL.md resolve via `bin/` on `$PATH`" architecture rule — never invoke the canonical script via repo-relative path; the path does not resolve in adopter trees.
297
+
298
+ Exit-code routing:
299
+ - **Exit 0 (clean)**: continue to Step 1.
300
+ - **Exit 1 (drift detected)**: structured diff lines printed to stdout, one per drift entry (≤150 bytes per the "Progressive disclosure + once-per-session budget for UserPromptSubmit governance prose" architecture rule progressive-disclosure budget). Capture stdout to a temp file and classify the drift via the **uncommitted-rename carve-out** (the "`/wr-itil:manage-problem` Step 0 reconcile halt-on-drift directive doesn't distinguish uncommitted-rename-rooted drift (same-session pending) from committed cross-session drift — should refresh inline rather than halt for the former case" problem) before halt-routing — see "Drift classification carve-out" immediately below.
301
+ - **Exit 2 (parse error)**: README missing or malformed. Halt with the parse-error message; this needs investigation, not mechanical reconciliation. AFK orchestrators halt-with-report per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6.
302
+
303
+ #### Drift classification carve-out (the "`/wr-itil:manage-problem` Step 0 reconcile halt-on-drift directive doesn't distinguish uncommitted-rename-rooted drift (same-session pending) from committed cross-session drift — should refresh inline rather than halt for the former case" problem)
304
+
305
+ The Exit 1 halt-and-route path is correct for **committed cross-session drift** — a past session committed a ticket transition without staging the README refresh, and proceeding now would re-encode the drift into the post-operation refresh and propagate the lie. It is **wrong for uncommitted-rename-rooted drift** — when the current working tree carries a staged ticket rename (a same-session `git mv` that the in-flow the "Problem 094: `/wr-itil:manage-problem` does not refresh `docs/problems/README.md` on ticket creation" problem / the "Problem 062: `manage-problem` does not refresh `docs/problems/README.md` on single-ticket transitions; fast-path cache goes stale silently" problem refresh at Step 5 / Step 7 will reconcile in the upcoming commit per the "Governance Skills Commit Their Own Completed Work" architecture rule's single-commit grain). Halting in the latter case forces a separate `/wr-itil:reconcile-readme` commit, splitting one logical change across two commits and violating the "Governance Skills Commit Their Own Completed Work" architecture rule grain.
306
+
307
+ Run the classifier on Exit 1 to distinguish the two cases:
308
+
309
+ ```bash
310
+ <itil-plugin-root>/bin/wr-itil-reconcile-readme docs/problems > /tmp/wr-itil-drift-$$.txt
311
+ reconcile_exit=$?
312
+ if [ "$reconcile_exit" -eq 1 ]; then
313
+ <itil-plugin-root>/bin/wr-itil-classify-readme-drift /tmp/wr-itil-drift-$$.txt docs/problems
314
+ classify_exit=$?
315
+ rm -f /tmp/wr-itil-drift-$$.txt
316
+ fi
317
+ ```
318
+
319
+ The `<itil-plugin-root>/bin/wr-itil-classify-readme-drift` command is a `$PATH`-resolved shim (the "Plugin-bundled scripts invoked from SKILL.md resolve via `bin/` on `$PATH`" architecture rule naming grammar) dispatching `<itil-plugin-root>/scripts/classify-readme-drift.sh`. It cross-references the drifting IDs from the script's stdout against `git status --porcelain docs/problems/` filtered for staged rename (`R`) entries — the destination path's ticket ID is the post-rename status the in-flow refresh will reconcile.
320
+
321
+ Classifier exit-code routing:
322
+
323
+ - **`classify_exit == 0` (INLINE_REFRESH)**: every drifting ID is the destination of a staged rename in the working tree. Log a one-line note ("Step 0 reconcile drift covered by N staged rename(s); deferring README refresh to in-flow Step 5 / Step 7 per the "Problem 094: `/wr-itil:manage-problem` does not refresh `docs/problems/README.md` on ticket creation" problem / the "Problem 062: `manage-problem` does not refresh `docs/problems/README.md` on single-ticket transitions; fast-path cache goes stale silently" problem + the "Governance Skills Commit Their Own Completed Work" architecture rule single-commit grain") and continue to Step 1. Do NOT invoke `/wr-itil:reconcile-readme` — the in-flow refresh will land the README correction in the same commit as the ticket work.
324
+ - **`classify_exit == 1` (HALT_ROUTE_RECONCILE)**: at least one drifting ID is NOT covered by a staged rename — committed cross-session drift OR mixed (some IDs in working tree, some committed-only). **Halt this invocation** with a directive to invoke `/wr-itil:reconcile-readme` (interactive mode) or auto-route through the same skill in non-interactive mode (per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6, AFK orchestrator). The reconciliation must complete and commit before this manage-problem invocation proceeds. Mixed routes to halt because `/wr-itil:reconcile-readme` resolves both classes safely; the in-flow refresh only handles the rename'd subset.
325
+ - **`classify_exit == 2` (parse error)**: classifier received empty / missing drift input — contract violation upstream. Fall back to the conservative halt-and-route path.
326
+
327
+ This is a **preflight CHECK only** — manage-problem does NOT itself apply edits. The edit application lives in `/wr-itil:reconcile-readme`'s Step 4 with narrative preservation. Per architect verdict on the "`docs/problems/README.md` drifts from filesystem truth across sessions despite (refresh-on-create) and (refresh-on-transition) both Closed" problem (Q3): manage-problem and work-problems Step 0 invoke the script (cheap mechanical check); transition-problem does NOT (the "Problem 062: `manage-problem` does not refresh `docs/problems/README.md` on single-ticket transitions; fast-path cache goes stale silently" problem already covers transition-time refresh inside the same commit, redundant preflight there would pay the cost on every transition).
328
+
329
+ This step is a robustness layer ON TOP of the "Problem 094: `/wr-itil:manage-problem` does not refresh `docs/problems/README.md` on ticket creation" problem + the "Problem 062: `manage-problem` does not refresh `docs/problems/README.md` on single-ticket transitions; fast-path cache goes stale silently" problem, not a supersession of either — both per-operation contracts remain in force at Step 5 (creation refresh) and Step 7 (transition refresh).
330
+
331
+ ### 0.5. Deferred-placeholder + README-cadence advisory (per the "`/wr-itil:review-problems` not auto-fired when needed — user has to remember to run it" problem)
332
+
333
+ After Step 0's README reconciliation preflight and before Step 1's request parsing, check whether the deferred-placeholder backlog has accumulated past threshold AND the `docs/problems/README.md` "Last reviewed" cadence has slipped. This is the **interactive** sibling of `/wr-itil:work-problems` Step 0c. At an interactive `manage-problem` surface the right shape per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 1 is **advisory not auto-dispatch** — the user is at the keyboard; the advisory is the surface; the user invokes `/wr-itil:review-problems` directly if they want the heavyweight re-rate pass. Auto-dispatching a heavyweight skill mid-interactive-session would break the ": Enforce Governance Without Slowing Down" user outcome's "Reviews complete in under 60 seconds so they don't break flow" outcome.
334
+
335
+ **Mechanism:**
336
+
337
+ ```bash
338
+ preflight_reason="$(<itil-plugin-root>/bin/wr-itil-check-deferred-placeholder-staleness "$PWD")"
339
+ ```
340
+
341
+ The helper is the same one Step 0c (work-problems) uses — single source of truth for the two-axis trigger rule (count ≥ 3 deferred placeholders AND README age > 7 days). See `/wr-itil:work-problems` SKILL.md Step 0c for the canonical contract; the threshold constants live in the helper. <!-- DEFERRED-PLACEHOLDER-STALENESS-CONTRACT-SOURCE: <itil-plugin-root>/lib/check-deferred-placeholder-staleness.sh -->
342
+
343
+ Routing on the helper's five-outcome enum:
344
+
345
+ | `preflight_reason` | Action |
346
+ |----------------------------------------------------------|--------------------------------------------------------------------------------------------------------|
347
+ | `no-deferred-placeholders` | Silent-pass. Proceed to Step 1. |
348
+ | `below-threshold count=<N> threshold=3` | Silent-pass. Proceed to Step 1. |
349
+ | `fresh-readme count=<N> age=<X>s threshold=<Y>s` | Silent-pass per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 5 — the cadence is in spec. |
350
+ | `no-readme count=<N>` | Emit an **advisory note** to stdout (visible to the interactive maintainer) naming the placeholder count + a directive: *"`<N>` deferred-placeholder ticket(s) accumulated AND `docs/problems/README.md` is missing/malformed; run `/wr-itil:review-problems` to re-rate and rebuild the README."* Then proceed to Step 1. |
351
+ | `stale-readme count=<N> age=<X>s threshold=<Y>s` | Emit an **advisory note** naming the placeholder count + readable age: *"`<N>` deferred-placeholder ticket(s) accumulated AND the WSJF Rankings cadence is `<X>` days stale (> 7-day threshold); run `/wr-itil:review-problems` to re-rate and refresh."* Then proceed to Step 1. |
352
+
353
+ **Why advisory not auto-dispatch at this surface** (the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 1 + the ": Enforce Governance Without Slowing Down" user outcome):
354
+ - The interactive user is at the keyboard. The advisory IS the surface; auto-dispatching a heavyweight skill mid-interactive-session would force a flow break that the ": Enforce Governance Without Slowing Down" user outcome explicitly proscribes ("Reviews complete in under 60 seconds so they don't break flow").
355
+ - The advisory preserves the user's authority to pick when to absorb the re-rate cost — at the next natural break, after a release, before the next session, etc.
356
+ - `request_user_input` would also be valid here (the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 1 interactive surface), but for a single optional pre-flight directive the advisory shape carries less round-trip friction than a structured question. The advisory is a **directive**, not a decision — the user already knows to run review-problems if they want to.
357
+
358
+ **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 composition note**: when the user follows the advisory and invokes `/wr-itil:review-problems`, that skill includes Step 4.6 relevance-close per 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 — relevance-close fires as a side-effect of any review pass.
359
+
360
+ **Fail-soft**: any error in this step (helper missing, malformed output) MUST NOT block manage-problem — log an advisory note and proceed to Step 1.
361
+
362
+ <!-- @jtbd the ": Enforce Governance Without Slowing Down" user outcome (Enforce Governance Without Slowing Down — interactive advisory keeps the signal surfaced without forcing a flow break) -->
363
+
364
+ After Step 0.5 completes (whether silent-pass or advisory emitted), proceed to Step 1.
365
+
366
+ ### 1. Parse the request
367
+
368
+ Determine the operation from `$ARGUMENTS`:
369
+ - If arguments start with a number (e.g., "011") **followed by a status word** (`known-error`, `verifying`, or `close`), **delegate to `/wr-itil:transition-problem`** via the installed skill invocation. See "Deprecated-argument forwarders" below.
370
+ - If arguments start with a bare number (e.g., "011" with no status word after it), this is an update flow — handled inline by the ticket-body edit steps (Step 6).
371
+ - If arguments contain "list", **delegate to `/wr-itil:list-problems`** via the installed skill invocation. See "Deprecated-argument forwarders" below.
372
+ - If arguments contain "work", **delegate to `/wr-itil:work-problem`** via the installed skill invocation. See "Deprecated-argument forwarders" below.
373
+ - If arguments contain "review", **delegate to `/wr-itil:review-problems`** via the installed skill invocation. See "Deprecated-argument forwarders" below.
374
+ - Otherwise, this is a new problem creation
375
+
376
+ #### Deprecated-argument forwarders (the "Rename `wr-problem` Plugin to `wr-itil`" architecture rule amended + the "Problem 071: Argument-based skill subcommands are not discoverable in Codex autocomplete" problem)
377
+
378
+ Per the "Rename `wr-problem` Plugin to `wr-itil`" architecture rule's amended Skill Granularity section, word-argument subcommands that name distinct user intents are being split into their own named skills. During the deprecation window, this skill's Step 1 parser retains the legacy argument routes as **thin-router forwarders** that re-invoke the new named skill via the installed skill invocation AND emit a one-line systemMessage with the canonical deprecation notice so the user learns the new invocation shape.
379
+
380
+ **Forwarder for `list`** (the "Problem 071: Argument-based skill subcommands are not discoverable in Codex autocomplete" problem split slice 1 — new skill `/wr-itil:list-problems`):
381
+
382
+ When `$ARGUMENTS` contains the word `list` as a top-level argument (not inside a ticket body edit), delegate to `/wr-itil:list-problems` via the installed skill invocation and emit this systemMessage verbatim:
383
+
384
+ > `/wr-itil:manage-problem list is deprecated; use /wr-itil:list-problems directly. This forwarder will be removed in @windyroad/itil's next major version.`
385
+
386
+ The forwarder does NOT re-implement the list logic locally — it invokes the installed skill invocation with `wr-itil:list-problems` and returns the new skill's output verbatim. Duplicating the logic would harden the deprecation window into a permanent fork.
387
+
388
+ **Forwarder for `review`** (the "Problem 071: Argument-based skill subcommands are not discoverable in Codex autocomplete" problem split slice 2 — new skill `/wr-itil:review-problems`):
389
+
390
+ When `$ARGUMENTS` contains the word `review` as a top-level argument (not inside a ticket body edit), delegate to `/wr-itil:review-problems` via the installed skill invocation and emit this systemMessage verbatim:
391
+
392
+ > `/wr-itil:manage-problem review is deprecated; use /wr-itil:review-problems directly. This forwarder will be removed in @windyroad/itil's next major version.`
393
+
394
+ The forwarder does NOT re-implement the review logic locally — it invokes the installed skill invocation with `wr-itil:review-problems` and returns the new skill's output verbatim. Duplicating the Step 9 re-scoring / auto-transition / verification-prompt / README-refresh stack would harden the deprecation window into a permanent fork.
395
+
396
+ **Forwarder for `work`** (the "Problem 071: Argument-based skill subcommands are not discoverable in Codex autocomplete" problem split slice 3 — new skill `/wr-itil:work-problem`, singular):
397
+
398
+ When `$ARGUMENTS` contains the word `work` as a top-level argument (not inside a ticket body edit), delegate to `/wr-itil:work-problem` via the installed skill invocation and emit this systemMessage verbatim:
399
+
400
+ > `/wr-itil:manage-problem work is deprecated; use /wr-itil:work-problem directly. This forwarder will be removed in @windyroad/itil's next major version.`
401
+
402
+ The forwarder does NOT re-implement the selection logic locally — it invokes the installed skill invocation with `wr-itil:work-problem` and returns the new skill's output verbatim. Duplicating the freshness-check / request_user_input selection / delegate-to-`manage-problem <NNN>` stack would harden the deprecation window into a permanent fork. Note the singular/plural distinction: the forwarder targets `/wr-itil:work-problem` (singular, one ticket per invocation), NOT `/wr-itil:work-problems` (plural AFK orchestrator). The two names coexist intentionally per the "Problem 071: Argument-based skill subcommands are not discoverable in Codex autocomplete" problem.
403
+
404
+ **Forwarder for `<NNN> <status>` transitions** (the "Problem 071: Argument-based skill subcommands are not discoverable in Codex autocomplete" problem split slice 4 — new skill `/wr-itil:transition-problem`):
405
+
406
+ When `$ARGUMENTS` starts with a three-digit ticket ID followed by a status word (`known-error`, `verifying`, or `close`), delegate to `/wr-itil:transition-problem` via the installed skill invocation and emit the canonical deprecation notice verbatim, naming the specific argument form the user supplied:
407
+
408
+ > `/wr-itil:manage-problem <NNN> <status> is deprecated; use /wr-itil:transition-problem <NNN> <status> directly. This forwarder will be removed in @windyroad/itil's next major version.`
409
+
410
+ The parser must distinguish a **bare `<NNN>`** (update flow — handled inline by Step 6) from a **`<NNN> <status>` pair** (transition — delegated). The status-word tokens that trigger the transition forwarder are fixed: `known-error`, `verifying`, `close`. Any other suffix after `<NNN>` routes to the inline update flow per Step 6. This preserves the two legitimate shapes the original subcommand carried while splitting the transition intent out cleanly.
411
+
412
+ The forwarder does NOT re-implement the Step 7 transition logic locally — it invokes the installed skill invocation with `wr-itil:transition-problem` and returns the new skill's output verbatim. Duplicating the pre-flight-checks / the "Problem 063: manage-problem does not trigger /wr-itil:report-upstream when root cause is external" problem-external-root-cause-detection / the "Problem 057: `git mv` + Edit + `git add` staging-ordering trap drops content edits from the commit" problem-staging-trap / 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 stack would harden the deprecation window into a permanent fork. Per the "Rename `wr-problem` Plugin to `wr-itil`" architecture rule amended "Split-skill execution ownership" (the "Problem 093: `/wr-itil:transition-problem` ↔ `/wr-itil:manage-problem` circular delegation for `<NNN> <status>` args" problem), the forwarder is **one-way** — `/wr-itil:transition-problem` hosts its own inline Step 7 block and does NOT re-invoke `/wr-itil:manage-problem`. The in-skill Step 7 block below stays in place for in-skill callers (Step 9b auto-transition, the Parked path, Step 9d closure inside review); the split skill carries a scoped inline copy for the user-initiated transition path only ("copy, not move"). Lifecycle completeness (known-error + verifying + close) is covered per the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule's three-status mandate.
413
+
414
+ ### 2. For new problems: Check for duplicates FIRST
415
+
416
+ Before creating, search existing problems for similar issues. The user may not know a problem already exists.
417
+
418
+ 1. Extract keywords from the description/title (e.g., "foul drawn", "checkpoint", "delete", "stuck saving")
419
+ 2. Search all files in `docs/problems/` for those keywords using Grep
420
+ 3. Read the title and status of each match
421
+ 4. If matches are found, present them to the user via `request_user_input`:
422
+ - "I found existing problems that may be related: the "Problem 011: Grep-based BATS tests produce false positives on legitimate refactors" problem (stuck saving, CLOSED), the "Problem 023: Governance skills should commit completed work, not defer to user" problem (foul drawn garbled, OPEN). Would you like to: (a) Update an existing problem, (b) Create a new problem anyway, (c) Cancel?"
423
+ 5. If the user chooses to update, switch to the update flow for that problem ID
424
+ 6. If no matches found, proceed to create
425
+ 7. **After the grep completes** (whether duplicates were found or not), write the per-session create-gate marker so the `PreToolUse:Write` hook (`<itil-plugin-root>/hooks/manage-problem-enforce-create.sh`, the "Agent bypasses `/wr-itil:manage-problem` Step 2 duplicate-check by writing tickets directly to `docs/problems/`" problem) allows the subsequent Write of the new `.open.md` file. The marker is `/tmp/manage-problem-grep-${SESSION_ID}`. Per **the "create-gate marker race between concurrent Codex sessions via shared runtime-sid file" problem / the "Capture the runtime stdin session_id via a PreToolUse hook so the create-gate marker binds to the same SID the runtime hook will see" architecture rule Option C**, the agent writes it under EVERY recent candidate session SID — not just one — by sourcing the discovery helpers (the "`/wr-itil:manage-problem` Step 2 substep 7 session-id discovery is brittle — agent has no env var, must scrape marker filenames" problem) and piping the candidate set into `mark_step2_complete_candidates`:
426
+
427
+ ```bash
428
+ <itil-plugin-root>/bin/wr-itil-mark-create-gate
429
+ ```
430
+
431
+ `<itil-plugin-root>/bin/wr-itil-mark-create-gate` is the "Plugin-bundled scripts invoked from SKILL.md resolve via `bin/` on `$PATH`" architecture rule `$PATH` shim (adopter-safe — resolves its `hooks/lib` siblings relative to the script, NOT cwd; the "capture-problem / capture-rfc / manage-problem Step 2 create-gate marker step sources repo-relative `<itil-plugin-root>/hooks/lib/*.sh` — fails in adopter installs (recurring published-path class: //)" problem/the ": Adopter-safe path resolution in shipped SKILLs ( — 24 repo-relative references)" release design) that internalises the former inline `source <itil-plugin-root>/hooks/lib/{session-id,create-gate}.sh` + `get_candidate_session_ids | mark_step2_complete_candidates`. NEVER `source packages/...` repo-relative from a SKILL — those paths only resolve in the source monorepo, not adopter installs.
432
+
433
+ **Why every candidate, not one (the "create-gate marker race between concurrent Codex sessions via shared runtime-sid file" problem / the "Capture the runtime stdin session_id via a PreToolUse hook so the create-gate marker binds to the same SID the runtime hook will see" architecture rule Option C)**: under `/wr-itil:work-problems` the orchestrator main turn fires PreToolUse hooks concurrently with its backgrounded iter subprocess (Step 5). Both sessions write the same per-machine runtime-sid marker (last-writer-wins), so the single-SID `get_current_session_id` can return the subprocess SID while the orchestrator's Write carries the orchestrator SID on its stdin — marker mismatch, create-gate deny. No agent-side algorithm can predict the right single SID from filesystem state alone (the "Capture the runtime stdin session_id via a PreToolUse hook so the create-gate marker binds to the same SID the runtime hook will see" architecture rule §Context). The command instead enumerates EVERY candidate SID the hook might read — the `get_current_session_id` pick (env-var > runtime-sid > announce-marker priority, the "`/wr-itil:manage-problem` Step 2 substep 7 session-id discovery is brittle — agent has no env var, must scrape marker filenames" problem) PLUS every recent `/tmp/<system>-announced-<UUID>` UUID within a 24h mtime window (the "Progressive disclosure + once-per-session budget for UserPromptSubmit governance prose" architecture rule announce markers, set on prompt 1 of every session by architect / jtbd / tdd / style-guide / voice-tone / itil-assistant-gate / itil-correction-detect hooks) — and writes the marker under each. Whichever SID the hook reads from the Write's stdin, a matching marker provably exists. The candidate set is **bounded** to recent same-machine announce markers + the runtime-sid value — NOT a global fail-open: the "Agent bypasses `/wr-itil:manage-problem` Step 2 duplicate-check by writing tickets directly to `docs/problems/`" problem audit invariant holds (every marker still records that THIS session ran the duplicate-check grep). The marker is per-session, so a single write covers all new tickets for the rest of this session, enabling Step 4b multi-concern splits and same-session unrelated-ticket creation without re-running the grep.
434
+
435
+ **Why helpers instead of inline `${CODEX_THREAD_ID:-default}`**: the agent's process does NOT export `CODEX_THREAD_ID` today; the hook side reads `session_id` from its stdin JSON payload (per the Codex PreToolUse contract). The prior fallback wrote the marker under `default` while the hook checked the real UUID — mismatch caused the Write deny on every first ticket of a session until the agent ad-hoc scraped a UUID-bearing marker. The helpers canonicalise that scrape so every agent context discovers candidate SIDs the same way. the "`/wr-itil:manage-problem` Step 2 substep 7 session-id discovery is brittle — agent has no env var, must scrape marker filenames" problem.
436
+
437
+ **Phase 4 (the "Phase 4 — `get_current_session_id` helper system-priority bug; subprocess SIDs win mtime selection over orchestrator SID" problem / the "Capture the runtime stdin session_id via a PreToolUse hook so the create-gate marker binds to the same SID the runtime hook will see" architecture rule)** — the helper reads the runtime stdin `session_id` from a per-machine marker written by the `itil-runtime-sid-marker.sh` PreToolUse hook on every tool call. Because every Bash call that sources the helper is itself a PreToolUse:Bash event, the marker the helper reads was written moments earlier with the same `session_id` the runtime Write hook will see — so SID-mismatch denial is structurally impossible **in non-concurrent flow**. The Phase 3 announce-marker priority logic is preserved as cold-path fallback (first tool call of a session, before any PreToolUse fires).
438
+
439
+ **Phase 5 (the "create-gate marker race between concurrent Codex sessions via shared runtime-sid file" problem / the "Capture the runtime stdin session_id via a PreToolUse hook so the create-gate marker binds to the same SID the runtime hook will see" architecture rule Option C)** — the "structurally impossible" guarantee above holds ONLY when no second session writes the runtime-sid marker concurrently. Under `/wr-itil:work-problems`, the orchestrator main turn and its backgrounded subprocess write the per-machine runtime-sid marker concurrently (last-writer-wins), re-introducing the mismatch (this was the "create-gate marker race between concurrent Codex sessions via shared runtime-sid file" problem, surfaced by the 2026-05-18 the "report-upstream skill has automation blocks that clamp the agent feedback signal — external-comms risk assessment is the actual protection layer" problem/the "Rule 6 AFK fail-safe clamps intake-scaffold auto-execution — sibling-class to at the intake-scaffold surface; external-comms risk assessment is the actual protection layer" problem foreground captures). The candidate-set marker-write above is the mitigation: it does not depend on the runtime marker carrying the right SID at Write-time, because it marks under every recent candidate SID.
440
+
441
+ **Search strategy**: Search problem filenames AND file content. A match on the filename (kebab-case title) or the Description/Symptoms sections counts. Cast a wide net — false positives are cheap (user chooses), but false negatives mean duplicate problems.
442
+
443
+ #### Sub-step 2.8 — Hang-off-check via fresh-context subagent (the "`/wr-itil:review-problems` has no path to close tickets that are no longer relevant (evidence-based, NOT age-based) — structural outflow gap drives monotonic backlog growth" problem Phase 3 amendment, 2026-05-31; the "Governance skill invocation patterns — foreground + background with deferred-question resumption" architecture rule 5th invocation pattern)
444
+
445
+ The wide-net grep + request_user_input at sub-steps 1-6 above handles the title/keyword-overlap class. Sub-step 2.8 closes a wider gap: parent tickets where the new problem's scope belongs absorbed as an Investigation Tasks expansion / Phase N section rather than as a sibling. The wrongly-captured the "Phase 2 — extend `evaluate-relevance.sh` with 4 more evidence shapes + fix Phase 1 file-no-longer-exists false-positive class" problem sibling of the "`/wr-itil:review-problems` has no path to close tickets that are no longer relevant (evidence-based, NOT age-based) — structural outflow gap drives monotonic backlog growth" problem on 2026-05-31 (now closed as duplicate-of-the "`/wr-itil:review-problems` has no path to close tickets that are no longer relevant (evidence-based, NOT age-based) — structural outflow gap drives monotonic backlog growth" problem) is the canonical regression — the main agent mid-iter pattern-matched the existing capture flow under session-context bias.
446
+
447
+ Sub-step 2.8 adds a **mechanical pre-filter + fresh-context subagent dispatch** that closes this gap without re-introducing the main agent's bias. Mirrors the `/wr-itil:capture-problem` Step 2 sub-step 2b dispatch verbatim.
448
+
449
+ **Mechanical pre-filter** — grep `docs/problems/open/*.md` + `docs/problems/verifying/*.md` BODIES for tokens shared with the new problem's description: any `ADR-NNN` / `RFC-NNN` / `JTBD-NNN` reference, SKILL path (`/wr-<plugin>:<skill>` or `packages/<plugin>/skills/<skill>/`), or file path (`packages/...`, `docs/...`, `.github/...`, `bin/...`, `scripts/...`). Collect candidates that share ≥1 signal; cap at 5; empty or >5 → skip dispatch.
450
+
451
+ **the "Report a Problem Without Pre-Classifying It" user outcome firewall** — sub-step 2.8 fires on **maintainer-internal new-problem** captures ONLY. The dispatch MUST be skipped when manage-problem is ingesting a plugin-user-reported issue from `.github/ISSUE_TEMPLATE/problem-report.yml` (plugin-user descriptions do not carry the same authorial intent as maintainer-internal captures; a plugin-user describing their friction in maintainer vocabulary could plausibly trigger a wrong-parent HANG_OFF). When ingesting plugin-user reports, triage stays user-judgement per the "Report a Problem Without Pre-Classifying It" user outcome. Mirrors the existing Step 1.5 / Step 4 firewall patterns in `/wr-itil:capture-problem` (see line 116 of `<itil-plugin-root>/skills/capture-problem/SKILL.md`).
452
+
453
+ **AFK safe-default**: when `--no-prompt` is propagated, the dispatch still fires (the subagent verdict is non-interactive by construction — no `request_user_input`), and ambiguous-multi-parent cases collapse to `PROCEED_NEW` per the subagent's Rule 6 contract. This satisfies the ": Progress the Backlog While I'm Away" user outcome's safe-default contract.
454
+
455
+ **Dispatch** — delegate to `wr-itil:hang-off-check` via the native Codex subagent tool with the same structured payload shape capture-problem uses (`SURFACE: manage-problem-step-2.8`; `<new-capture>` payload; `<candidates>` payload with `P<NNN> | <title> | <path> | shared-signals: ...` per row). The subagent reads candidate bodies in full and emits:
456
+
457
+ - `HANG_OFF: P<NNN>` with **Rationale**, **Signals matched**, **Where to absorb** → halt manage-problem's new-problem creation; route to the parent-ticket update flow (Step 6 ticket-body edit on the named parent). Record the hang-off decision + rationale in the parent ticket's Investigation Tasks bullet or `### Phase N — <name>` section per the subagent's `Where to absorb` directive. Single-commit grain preserved (the parent-ticket amendment commit IS this manage-problem invocation's commit per the "Governance Skills Commit Their Own Completed Work" architecture rule).
458
+
459
+ - `PROCEED_NEW` with **Rationale** + **Per-candidate explanation** → continue to Step 3 (ID assignment). Append the subagent's rationale + per-candidate explanation to the new ticket's `## Related` section as the audit trail per the "Agent output grounding — no fabricated quantitative estimates, cite + persist + uncertainty" architecture rule grounding + the "Restore Service Fast with an Audit Trail" user outcome.
460
+
461
+ **Why a subagent (not in-SKILL checks)**: the main agent is biased by session context — mid-iter, mid-work, pattern-matching existing flows ("I captured X then dispatched iter; do the same shape for Y"). A fresh subagent invocation starts clean, reads only the structured inputs, and reasons about candidate absorption without the bias. Same architectural pattern as `wr-architect:agent` / `wr-jtbd:agent` / `tdd:review-test` / `wr-risk-scorer:pipeline` — codified as the "Governance skill invocation patterns — foreground + background with deferred-question resumption" architecture rule's 5th invocation pattern under the "`/wr-itil:review-problems` has no path to close tickets that are no longer relevant (evidence-based, NOT age-based) — structural outflow gap drives monotonic backlog growth" problem amendment 2026-05-31.
462
+
463
+ **Cross-references**: `<itil-plugin-root>/agents/hang-off-check.md` (the subagent); `<itil-plugin-root>/agents/test/fixtures/regression-p347-vs-p346.md` (canonical behavioural fixture); `docs/decisions/032-governance-skill-invocation-patterns.proposed.md` § Foreground fresh-context-subagent-as-decision-arbiter variant; `docs/rfcs/the ": backlog flow control multi-phase" release design-p346-backlog-flow-control-multi-phase.proposed.md` (multi-phase trace per the "Every fix goes through an RFC" architecture rule); `docs/problems/.../346-...md` (driver master ticket).
464
+
465
+ **Hook contract (the "Agent bypasses `/wr-itil:manage-problem` Step 2 duplicate-check by writing tickets directly to `docs/problems/`" problem)**: writing a `.open.md` (or any `.<status>.md`) file under `docs/problems/` without first running this Step 2 grep + marker-touch is blocked by the `manage-problem-enforce-create.sh` PreToolUse hook with a `permissionDecision: deny` directing the agent back to this skill. Agents that try to bypass the skill (e.g. mid-retrospective inline capture, post-mortem wrap-up, or any "I'll just write it directly" shortcut) will hit the deny and be redirected here. Do not work around the deny by setting the marker manually — the marker exists to record that this Step 2 ran, and a marker without a grep is the audit-trail gap the "Agent bypasses `/wr-itil:manage-problem` Step 2 duplicate-check by writing tickets directly to `docs/problems/`" problem closes.
466
+
467
+ ### 3. For new problems: Assign the next ID
468
+
469
+ Compute the next ID as the **max of the local and origin highest IDs**, plus one, zero-padded to 3 digits. Comparing against `origin/<base>` is required by the "AFK orchestrator preflight: get the repo into a clean state before starting" architecture rule (confirmation criterion 2): without it, parallel sessions can mint the same ID for different problems and force a destructive surgical rebase on push (the "Problem 040: work-problems does not fetch origin before starting" problem incident).
470
+
471
+ ```bash
472
+ # Local-max ID — dual-tolerant enumeration covers BOTH the flat
473
+ # `docs/problems/<NNN>-<title>.<state>.md` layout AND the per-state
474
+ # subdir `docs/problems/<state>/<NNN>-<title>.md` layout per the ": docs/problems/ flat layout migration — per-state subdirs + adopter auto-migration" release design
475
+ # migration window. Both halves contribute to next-ID compute so a
476
+ # pre-migration ticket at flat-104 and a post-migration ticket at
477
+ # per-state-204 BOTH appear in `local_max` — never re-allocates an
478
+ # already-taken ID. `sed 's|.*/||'` strips ALL leading path components
479
+ # (works for both `100-foo.open.md` flat and `open/200-foo.md` per-state).
480
+ local_max=$(ls docs/problems/*.md docs/problems/*/*.md 2>/dev/null | sed 's|.*/||' | grep -oE '^[0-9]+' | sort -n | tail -1)
481
+
482
+ # Origin-max ID — `git ls-tree origin/<base>` reads remote-tracking ref
483
+ # without requiring a fetch in this step (Step 0 preflight is the place
484
+ # where the fetch happens). Default base is `main`; if the user is on
485
+ # another branch, swap accordingly.
486
+ #
487
+ # `--name-only` is required (the "Problem 056: Ticket-creator next-ID lookup greps blob SHAs, producing wrong `origin_max` values" problem): without it, each ls-tree line is
488
+ # `<mode> <type> <sha>\t<path>` and the 40-char blob SHA can contain
489
+ # three-digit runs that `grep -oE '[0-9]{3}'` false-matches (observed
490
+ # `origin_max=997` on 2026-04-20 opening the "Problem 055: No standard problem-reporting channel for plugin users, and no reusable pattern for downstream projects to report upstream" problem). `-r` recurses into
491
+ # the per-state subdirs introduced by the ": docs/problems/ flat layout migration — per-state subdirs + adopter auto-migration" release design. `sed 's|.*/||'` strips
492
+ # all leading path components so the anchored `grep -oE '^[0-9]+'`
493
+ # picks up filename IDs in both layouts.
494
+ origin_max=$(git ls-tree --name-only -r origin/main docs/problems/ 2>/dev/null | sed 's|.*/||' | grep -oE '^[0-9]+' | sort -n | tail -1)
495
+
496
+ # Take the max of the two and increment.
497
+ next=$(printf '%03d' $(( 10#$(echo -e "${local_max:-0}\n${origin_max:-0}" | sort -n | tail -1) + 1 )))
498
+ ```
499
+
500
+ If the local choice would have collided with an origin ticket created since the last fetch, the `git ls-tree origin/<base>` lookup catches it here and the renumber is automatic. Log the renumber decision in the operation report (e.g. "Bumped next ID from 042 → 043 to avoid collision with origin").
501
+
502
+ ### 4. For new problems: Gather information (the "Agents over-ask in interactive sessions — conflating mechanical-stages with user-interactive-stages of multi-stage skill contracts (inverse-)" problem derive-first; the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule category-4 silent-framework on derivable fields; category-1 direction-setting fallback only on Description)
503
+
504
+ **Shared dispatch helper**: this surface invokes `<itil-plugin-root>/lib/derive-first-dispatch.sh` for the canonical slug derivation (Title), RISK-POLICY matrix lookup (Priority), and I2-isomorphic stderr advisory format. The helper is sourced by `/wr-itil:capture-problem`, `/wr-itil:manage-incident`, and `/wr-itil:manage-problem`; drift in the advisory shape re-opens the "Agents over-ask in interactive sessions — conflating mechanical-stages with user-interactive-stages of multi-stage skill contracts (inverse-)" problem. Surface-specific signal definitions (priority impact / likelihood regex lists) stay inline below — the helper owns the mechanism, not the per-surface signals (architect verdict 2026-05-15 the "Agents over-ask in interactive sessions — conflating mechanical-stages with user-interactive-stages of multi-stage skill contracts (inverse-)" problem Phase 2a-iii-A: "Helper must preserve per-surface signal definitions; only the dispatch mechanism is shared").
505
+
506
+ **Derive-first dispatch.** Problem-declaration inputs carry observable evidence in the user's prose, the working tree, `RISK-POLICY.md`, and the wall-clock — the framework can resolve most fields without firing `request_user_input`. Only **Description** is genuinely user-knowledge (without prose there is literally nothing to capture); only **Description** retains the request_user_input gate.
507
+
508
+ The "Agents over-ask in interactive sessions — conflating mechanical-stages with user-interactive-stages of multi-stage skill contracts (inverse-)" problem inverse-the "Problem 078: Assistant does not offer to capture a problem ticket when the user delivers strong-signal correction" problem trap (`docs/problems/known-error/132-...md`) is the load-bearing motivation. The 2026-05-06 I001 declaration regression cited in the "Agents over-ask in interactive sessions — conflating mechanical-stages with user-interactive-stages of multi-stage skill contracts (inverse-)" problem fired a 4-question request_user_input with 3 of 4 sub-questions being lazy classifications (Title kebab-derivable, Severity matrix-derivable, Start time git-log-derivable). manage-problem Step 4 is the second declaration-skill surface under Phase 2a (after manage-incident Step 4 in commit b7cc645) to ship the derive-first dispatch. The pattern is isomorphic across `/wr-itil:capture-problem` Step 1.5 (the "`/wr-itil:capture-problem` asks a classification question (technical vs user-business) that it can answer itself from the description's observable evidence" problem worked example), `/wr-itil:manage-incident` Step 4, and this skill.
509
+
510
+ Resolve each field via the following dispatch. **The order is load-bearing** — every field except Description resolves silently with a stderr advisory citing the source; Description alone fires `request_user_input` as the genuine category-1 surface.
511
+
512
+ | Field | Dispatch | the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule category |
513
+ |-------|----------|------------------|
514
+ | **Title** | Derive silently. Kebab-case the first 8-10 non-stopword tokens of the user's prose description (same slug derivation as `/wr-itil:capture-problem` Step 1.4 and `/wr-itil:manage-incident` Step 4). Emit stderr advisory: `manage-problem: derived title='<slug>' from description; re-invoke with the desired title or rename the file if the slug is wrong`. Do NOT fire request_user_input. | category-4 silent-framework |
515
+ | **Description** | Pull verbatim from `$ARGUMENTS` prose into Step 5's `## Description` section. **Fallback**: when `$ARGUMENTS` carries NO prose at all (only flags / status / no body), fire request_user_input as the genuine category-1 direction-setting surface — *"only the user knows the goals that haven't been written down yet."* Question text: *"What is happening? What should happen instead?"* This is the ONLY user-knowledge field at Step 4. | category-1 direction-setting (fallback only; category-4 silent-framework on the typical path where prose is present) |
516
+ | **Priority** (Impact × Likelihood) | Derive silently when description signals map to a clear `RISK-POLICY.md` Impact × Likelihood cell. Cross-reference signals: (a) **impact** — service-disruption keywords (`down` / `degraded` / `unavailable` / `data loss` → high; latency / throughput / slow → moderate; cosmetic / typo / minor friction → low); (b) **likelihood** — reproducibility keywords (`every invocation` / `reproducible` / `100%` → high; `intermittent` / `flaky` / `sometimes` → medium; `one-off` / `single observation` → low); (c) **named anchors** — explicit `Impact: <label>` / `Likelihood: <label>` or `Priority: <score>` mentions in prose take precedence. When the cross-reference produces a single clear cell, set it silently and emit stderr advisory: `manage-problem: priority derived as <score> (<label>) from RISK-POLICY matrix + evidence: <evidence list>; re-invoke or update if mis-rated`. **Ambiguous-evidence fallback** (no mappable signal, or signals point to conflicting cells): fire request_user_input with the Impact (1-5) × Likelihood (1-5) options as the genuine the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule **category-5 (taste)** fallback surface. The fallback is genuine ambiguity, NOT defaults. | category-4 silent-framework (derivable); category-5 fallback (ambiguous) |
517
+
518
+ **Inferred fields (no ask, no advisory needed)**:
519
+
520
+ - **Reported date**: today's date (`date +%Y-%m-%d`)
521
+ - **Status**: always "Open" for new problems
522
+ - **Symptoms**: infer from description verbatim into Step 5's `## Symptoms` section
523
+ - **Workaround**: default to "None identified yet." unless explicit workaround prose appears in `$ARGUMENTS`
524
+
525
+ **Stderr advisory contract**: each derived field emits a SINGLE line to stderr (NOT stdout, NOT in the ticket body) per the capture-problem Step 1.5 + manage-incident Step 4 pattern. The advisory text shape is I2-isomorphic — identical sentence structure across the three declaration-skill surfaces (`<skill>: derived <field>=<value> from <source>; <reversibility-clause>`) beyond substituted values + source names. Embedding the advisory in stdout would risk machine-readers parsing it as a ticket-body line; embedding it in the ticket body would violate the required-section schema. Stderr is the correct channel — visible to interactive maintainers in the terminal; invisible to ticket consumers; loggable by orchestrators that capture subprocess stderr.
526
+
527
+ **the "Agent output grounding — no fabricated quantitative estimates, cite + persist + uncertainty" architecture rule cost-source grounding**: each derived field cites its source in the advisory (description token sequence for Title; RISK-POLICY matrix cell + named evidence for Priority). The `re-invoke or update if mis-rated` clause carries the reversibility marker the "Agent output grounding — no fabricated quantitative estimates, cite + persist + uncertainty" architecture rule mandates for ungrounded outputs.
528
+
529
+ **AFK fail-safe (the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6)**: under AFK orchestration, all derivable fields resolve without interactive input; only Description-when-absent can block. The orchestrator should halt-with-stderr citing the missing-prose case rather than guess (Description is genuinely user-judgment per the ": Progress the Backlog While I'm Away" user outcome's "Problems requiring my judgment ... are queued for my return, not guessed at"). The typical AFK manage-problem call carries prose in `$ARGUMENTS` (or the orchestrator's per-iter context supplies it), so the halt-on-Description path is the rare-corner-case behaviour, not the routine flow.
530
+
531
+ **Cross-skill consistency note**: this is the third declaration-skill surface to ship the derive-first dispatch (after `/wr-itil:capture-problem` Step 1.5 and `/wr-itil:manage-incident` Step 4 in commit b7cc645). The architect verdict 2026-05-15 the "Agents over-ask in interactive sessions — conflating mechanical-stages with user-interactive-stages of multi-stage skill contracts (inverse-)" problem Phase 2a-ii flagged this triplet as the pattern-lock point — the I2-isomorphic stderr advisory format is now established across three skills before Phase 2a-iii (`/wr-architect:create-adr` argument-collection) extends the same pattern to a fourth.
532
+
533
+ ### 4b. For new problems: Concern-boundary analysis (multi-concern check)
534
+
535
+ Before writing the problem file, perform a concern-boundary analysis on the gathered description to prevent conflated tickets that make WSJF scoring meaningless (the "Problem 016: `manage-problem` skill does not flag or split multi-concern tickets" problem).
536
+
537
+ **Self-check**: Read the description and root cause information gathered in step 4. Answer: "How many distinct root causes are present? If fixed independently, how many separate fix paths exist?"
538
+
539
+ - **Single concern** (one root cause, one fix path): proceed directly to step 5.
540
+ - **Multiple concerns** (two or more distinct root causes, different components, or if the architect review flagged this needs its own ADR): present a split prompt.
541
+
542
+ **Split prompt** — use `request_user_input`:
543
+ - `header: "Multi-concern problem"`
544
+ - `multiSelect: false`
545
+ - Options:
546
+ 1. `Split into separate problems (Recommended)` — description: "Create one problem ticket per distinct concern, with consecutive IDs. Each ticket gets its own priority, WSJF score, and fix path."
547
+ 2. `Keep as a single problem` — description: "Create one ticket covering all concerns. Use this only if the concerns are so tightly coupled that they cannot be fixed independently."
548
+
549
+ **Non-interactive fallback**: When `request_user_input` is unavailable (e.g., non-interactive/AFK mode), automatically split into separate problems and note the auto-split in output. Do not block creation.
550
+
551
+ **the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6 carve-out audit (the "AFK iter default when a skill needs to ask a question and request_user_input is unavailable — should queue the question and move to the next iteration (not halt, not silently skip)" problem, 2026-06-06 amendment)**: the universal AFK default is **queue-and-continue**; this site is a documented **AUTO-DEFAULT** carve-out. Authorising principle: policy-authorised safe default per the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule category 4 (silent framework). Splitting is fully reversible (manual combine via Related cross-references + WSJF re-rank), the framework's lifecycle model rewards explicit per-concern WSJF ranking, and "split when in doubt" is the persona-correct safe heuristic for the ": Progress the Backlog While I'm Away" user outcome — the loop progresses, over-splits are cheap to combine, and halt would cost more loop throughput than the over-split risk. Symmetric with the parallel `/wr-architect:create-adr` Step 1 multi-decision auto-split (same authority, same rationale).
552
+
553
+ **Split implementation**: When splitting, assign consecutive IDs (e.g., if next ID is 035, create the "Problem 035: manage-problem commit gate has no fallback when subagent delegation is unavailable" problem and the "Problem 036: work-problems orchestrator does not verify commit-landing between iterations" problem). Create each problem file independently. Cross-reference each ticket in the other's "Related" section.
554
+
555
+ **Scope**: This step applies only to **new problem creation** (steps 2–5). It does NOT apply to updates, status transitions, or reviews of existing tickets.
556
+
557
+ ### 5. For new problems: Write the problem file
558
+
559
+ **File path**: `docs/problems/open/<NNN>-<kebab-case-title>.md`
560
+
561
+ **Template**:
562
+
563
+ ```markdown
564
+ # Problem <NNN>: <Title>
565
+
566
+ **Status**: Open
567
+ **Reported**: <YYYY-MM-DD>
568
+ **Priority**: <score> (<label>) — Impact: <label> (<n>) x Likelihood: <label> (<n>)
569
+ **Origin**: internal
570
+
571
+ ## Description
572
+
573
+ <description>
574
+
575
+ ## Symptoms
576
+
577
+ <bullet list of observable symptoms>
578
+
579
+ ## Workaround
580
+
581
+ <workaround or "None identified yet.">
582
+
583
+ ## Impact Assessment
584
+
585
+ - **Who is affected**: <personas>
586
+ - **Frequency**: <when/how often>
587
+ - **Severity**: <High/Medium/Low — reason>
588
+ - **Analytics**: <data source or N/A>
589
+
590
+ ## Root Cause Analysis
591
+
592
+ ### Investigation Tasks
593
+
594
+ - [ ] Investigate root cause
595
+ - [ ] Create reproduction test
596
+ - [ ] Create INVEST story for permanent fix
597
+
598
+ ## Dependencies
599
+
600
+ - **Blocks**: <tickets that can't close until this one does — bare IDs, comma-separated; leave empty if none>
601
+ - **Blocked by**: <tickets that must close first — bare IDs, comma-separated; drives the transitive-effort rule; leave empty if none>
602
+ - **Composes with**: <tickets whose work overlaps but neither blocks the other — does NOT propagate effort; leave empty if none>
603
+
604
+ ## Related
605
+
606
+ <links to related files, problems, ADRs>
607
+ ```
608
+
609
+ **`**Origin**` field (the "Inbound-reported problems rank ahead of internally-discovered problems via a sort tier" architecture rule)** records where the problem came from and is an authoritative input to the "Inbound-reported problems rank ahead of internally-discovered problems via a sort tier" architecture rule reported-first ranking tier. Two values:
610
+
611
+ - `internal` — internally discovered (the default for tickets created by hand or by an internal observation).
612
+ - `inbound-reported (#NN)` — reported to us by an external user via an upstream channel, where `#NN` is the upstream issue/discussion number. Written by the "Inbound upstream-report discovery + assessment pipeline (peer of )" architecture rule'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 (the "Inbound-reported problems rank ahead of internally-discovered problems via a sort tier" architecture rule). When backfilling existing tickets during a review, stamp reported ones with `inbound-reported (#NN)`; leave the rest `internal`.
613
+
614
+ The `## Dependencies` section uses **bare ticket IDs** (`the "Problem 038: No voice-and-tone gate on external communications" problem`, not `[the "Problem 038: No voice-and-tone gate on external communications" problem](./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.
615
+
616
+ **Concrete example** (for the "Problem 073: No voice-and-tone check or risk assessment on changeset bodies (which populate CHANGELOG.md, Release PRs, GitHub Releases, and npm release notes)" problem referencing two upstreams):
617
+
618
+ ```markdown
619
+ ## Dependencies
620
+
621
+ - **Blocks**: (none)
622
+ - **Blocked by**: the "Problem 038: No voice-and-tone gate on external communications" problem, the "Problem 064: No risk-scoring gate on external communications" problem
623
+ - **Composes with**: (none)
624
+ ```
625
+
626
+ #### README.md refresh on new ticket (the "Problem 094: `/wr-itil:manage-problem` does not refresh `docs/problems/README.md` on ticket creation" problem)
627
+
628
+ After writing the new `.open.md` file, regenerate `docs/problems/README.md` to insert the new ticket's row into the WSJF Rankings, and stage the refreshed README in the same commit as the new ticket. Without this refresh, new tickets are absent from the ranked table until the next `/wr-itil:review-problems` invocation or the next Step 7 transition — staleness accumulates silently on every creation-only session.
629
+
630
+ **Mechanism**: use the same rendering rules as Step 7's the "Problem 062: `manage-problem` does not refresh `docs/problems/README.md` on single-ticket transitions; fast-path cache goes stale silently" problem 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 the "Problem 062: `manage-problem` does not refresh `docs/problems/README.md` on single-ticket transitions; fast-path cache goes stale silently" problem's established discipline. Only the new ticket's own WSJF is consumed from its freshly-written file.
631
+
632
+ **WSJF Rankings tier + tie-break sort (the "`docs/problems/README.md` WSJF Rankings table row order doesn't match `/wr-itil:work-problems`'s tie-break selection — users assume the orchestrator is broken" problem + the "Inbound-reported problems rank ahead of internally-discovered problems via a sort tier" architecture rule)**: 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 "Inbound-reported problems rank ahead of internally-discovered problems via a sort tier" architecture rule 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 (the "Inbound-reported problems rank ahead of internally-discovered problems via a sort tier" architecture rule) --> <!-- 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 the "Problem 062: `manage-problem` does not refresh `docs/problems/README.md` on single-ticket transitions; fast-path cache goes stale silently" problem block, the Step 9e template, AND `/wr-itil:review-problems` SKILL.md Step 3 / Step 5 — drift here re-opens the "`docs/problems/README.md` WSJF Rankings table row order doesn't match `/wr-itil:work-problems`'s tie-break selection — users assume the orchestrator is broken" problem / the "Inbound-reported problems rank ahead of internally-discovered problems via a sort tier" architecture rule.
633
+
634
+ **Verification Queue sort direction (the "docs/problems/README.md Verification Queue rendered newest-first contradicts section header "Ranked by release age, oldest first"" problem)**: rows in the Verification Queue table are sorted by `Released date ASC` (oldest at row 1; same-day releases tiebreak by ID ASC) per the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule + the "Problem 048: manage-problem does not surface Fix Released problems as verification candidates when the fix path has been exercised" problem 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 the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule --> Any future change to the VQ sort direction MUST update this render block, the Step 7 the "Problem 062: `manage-problem` does not refresh `docs/problems/README.md` on single-ticket transitions; fast-path cache goes stale silently" problem 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 the "docs/problems/README.md Verification Queue rendered newest-first contradicts section header "Ranked by release age, oldest first"" problem.
635
+
636
+ **Likely-verified cell shape (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)**: the `Likely verified?` column carries an **evidence-first** cell — `yes — observed: <evidence>` / `no — not observed` / `no — observed regression`. The 14-day age-based heuristic (originally introduced by the "Problem 048: manage-problem does not surface Fix Released problems as verification candidates when the fix path has been exercised" problem Candidate 4) is superseded — age is preserved separately via the `Released` column; the `Likely verified?` column is reserved for session-observed evidence (Step 4 user confirmation, in-session test invocation outcome per the "Agent output grounding — no fabricated quantitative estimates, cite + persist + uncertainty" architecture rule grounding, or `run-retro` Step 4a close-on-evidence citation). <!-- LIKELY-VERIFIED-CELL-SHAPE: evidence-based per 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 --> Any future change to the cell shape MUST update this render block, the Step 7 the "Problem 062: `manage-problem` does not refresh `docs/problems/README.md` on single-ticket transitions; fast-path cache goes stale silently" problem 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 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.
637
+
638
+ 1. After `Write`-ing the new `.open.md` file (and, for multi-concern splits per step 4b, after all split files are written), regenerate `docs/problems/README.md` in-place reflecting the new filename set.
639
+ 2. Update the "Last reviewed" line per the **inline the "`docs/problems/README.md` line 3 narrative-blob accumulator bloat — sibling to (briefing tier 3) on a different surface" problem rotation mechanism** below. The mechanism is inlined here at the execution site (not deferred via cross-reference to the § Last-reviewed line discipline subsection further down this SKILL) so a single-pass agent reading this Step 5 does not silently skip the archive step. **Skipping the BEFORE-rewrite archive step destroys the displaced fragment and re-opens the "transition-problem SKILL Step 7 Last-reviewed rotation silently skipped across iters" problem** (iter-7 + iter-8 of 2026-05-30's AFK work-problems session silently skipped the rotation in 2 of 9 transition-bearing iters under exactly that failure mode). The mechanism MUST execute IN ORDER:
640
+
641
+ 1. **Read** line 3 of `docs/problems/README.md`: `awk 'NR==3' docs/problems/README.md` (`head -3 | tail -1` or `sed -n '3p'` are acceptable equivalents).
642
+ 2. **Append-if-non-empty (BEFORE step 3, not after)** — if line 3 is non-empty AND not a same-session same-verb near-duplicate of the new fragment, append the existing line 3 verbatim to `docs/problems/README-history.md` under a `## YYYY-MM-DD` heading (creating the heading on first append for that date; subsequent same-day appends nest under the existing heading). Run this BEFORE the Edit-tool rewrite in step 3 — Edit's replace pattern destroys the displaced content otherwise.
643
+ 3. **Rewrite** line 3 of `docs/problems/README.md` with the new fragment of form `> Last reviewed: YYYY-MM-DD **<event>** — <one-line summary>` (e.g. `P<NNN> opened — <one-line title>`). Soft cap ≤ 1024 bytes per fragment; hard ceiling 5120 bytes per the "Session-start briefing surface — SessionStart hook over tiered directory + indexed README" architecture rule Tier 3 envelope.
644
+ 4. **Stage both** — `git add docs/problems/README.md docs/problems/README-history.md` so the same single commit per the "Governance Skills Commit Their Own Completed Work" architecture rule captures both files.
645
+
646
+ Canonical rationale anchor: § Last-reviewed line discipline (the "`docs/problems/README.md` line 3 narrative-blob accumulator bloat — sibling to (briefing tier 3) on a different surface" problem) subsection below. The cross-reference is preserved for the "why"; the "what" is inlined above for execution-time legibility per the "transition-problem SKILL Step 7 Last-reviewed rotation silently skipped across iters" problem.
647
+ 3. `git add docs/problems/README.md` — the stage list at Step 11 must include it alongside the new `.open.md` file (Step 11's `git add -u` catch-all handles tracked-file modifications; the new README render lands via this path when README.md already exists in git, and via an explicit `git add docs/problems/README.md` when it is newly created). When line-3 truncation displaces prior content, also `git add docs/problems/README-history.md`.
648
+
649
+ For the multi-concern split path (step 4b), the refresh fires **once** after all split tickets are written, not per-split — a single render captures the full new set in one pass.
650
+
651
+ #### Last-reviewed line discipline (the "`docs/problems/README.md` line 3 narrative-blob accumulator bloat — sibling to (briefing tier 3) on a different surface" problem)
652
+
653
+ The "Last reviewed" line (line 3 of `docs/problems/README.md`) was designed as a short audit marker — one ticket name + one transition reason — but historically accumulated multi-paragraph session-summary fragments unbounded ("Prior:" stacking on every refresh). At ~62 KB / 76 KB it crossed the Read-tool 25K-token whole-file limit and could no longer be window-read at any offset/limit. the "`docs/problems/README.md` line 3 narrative-blob accumulator bloat — sibling to (briefing tier 3) on a different surface" problem closes the accumulator on this surface; sibling to the "Problem 099: `docs/BRIEFING.md` grows unbounded via run-retro appends — violates progressive disclosure" problem on `docs/briefing/<topic>.md`.
654
+
655
+ **Contract** — applies to every refresh that touches line 3 (Step 5 the "Problem 094: `/wr-itil:manage-problem` does not refresh `docs/problems/README.md` on ticket creation" problem creation, Step 6 the "Problem 094: `/wr-itil:manage-problem` does not refresh `docs/problems/README.md` on ticket creation" problem conditional update, Step 7 the "Problem 062: `manage-problem` does not refresh `docs/problems/README.md` on single-ticket transitions; fast-path cache goes stale silently" problem transition; mirrored in `transition-problem`, `transition-problems`, `review-problems`, `reconcile-readme`):
656
+
657
+ 1. **Single most-recent fragment only on line 3.** The "Last reviewed" parenthetical names ONE event — the operation this refresh covers. Do NOT prepend a `Prior:` segment, do NOT stack multi-paragraph rationale, do NOT carry history forward inline.
658
+ 2. **Soft cap: ≤ 1024 bytes per fragment.** Authoring guidance — keep the fragment dense and audit-meaningful (ticket ID + verb + one-line summary + ADR/JTBD anchors when load-bearing). Multi-paragraph rationale belongs in retros, ticket bodies, and ADR amendments — never on line 3.
659
+ 3. **Archive sibling: `docs/problems/README-history.md`.** When this refresh would displace prior line-3 content, append the displaced content to `README-history.md` BEFORE writing the new line 3. Forward-chronology — newest fragment goes at the bottom under a date heading (`## YYYY-MM-DD`). The archive is a log; it's grep-and-tail territory, not display-tier (which is why its chronology diverges from the README's reverse-chrono surface convention).
660
+ 4. **Hard ceiling: 5120 bytes on line 3.** Matches the "Session-start briefing surface — SessionStart hook over tiered directory + indexed README" architecture rule Tier 3 envelope. Surfaced advisory-only by `<itil-plugin-root>/bin/wr-itil-check-problems-readme-budget` (`$PATH`-resolved shim per the "Plugin-bundled scripts invoked from SKILL.md resolve via `bin/` on `$PATH`" architecture rule; canonical body at `<itil-plugin-root>/scripts/check-problems-readme-budget.sh`) — the script emits `OVER docs/problems/README.md line=3 bytes=<N> threshold=<N>` when the ceiling is breached. Always exits 0 (advisory; overflow is signal, not failure).
661
+
662
+ **Mechanism** (when authoring a refresh):
663
+
664
+ 1. Read the current line 3 of the README (e.g. `awk 'NR==3' docs/problems/README.md`).
665
+ 2. If the current line 3 is non-empty AND the new fragment is not a near-duplicate (same ticket + same verb in the same session): append the current line 3 verbatim to `docs/problems/README-history.md` under a `## YYYY-MM-DD` heading (creating the heading on first append for that date; subsequent same-day appends nest under the existing heading).
666
+ 3. Compose the new line 3 as a single paragraph naming the operation only. Keep ≤ 1024 bytes.
667
+ 4. Replace line 3 of README.md with the new paragraph.
668
+ 5. Stage both files in the same commit as the ticket change per the "Governance Skills Commit Their Own Completed Work" architecture rule: `git add docs/problems/README.md docs/problems/README-history.md`.
669
+
670
+ **Fast-path interaction**: the Step 9 freshness check uses git-mtime on `docs/problems/README.md`, NOT the prose contents of line 3. Truncating line 3 does NOT degrade the fast-path contract.
671
+
672
+ **Cross-references**: the "Session-start briefing surface — SessionStart hook over tiered directory + indexed README" architecture rule line 92 (reusable accumulator-doc pattern — explicitly names "problems index"), the "Progressive disclosure + once-per-session budget for UserPromptSubmit governance prose" architecture rule (progressive disclosure), the "Governance Skills Commit Their Own Completed Work" architecture rule (single-commit governance), the "Plugin-bundled scripts invoked from SKILL.md resolve via `bin/` on `$PATH`" architecture rule (plugin-bundled scripts via `bin/` on `$PATH`), `<itil-plugin-root>/bin/wr-itil-check-problems-readme-budget` shim (canonical body at `<itil-plugin-root>/scripts/check-problems-readme-budget.sh`), `<itil-plugin-root>/scripts/test/check-problems-readme-budget.bats`.
673
+
674
+ ### 6. For updates: Edit the existing file
675
+
676
+ Find the file matching the problem ID. Dual-tolerant lookup spans the flat layout AND the per-state subdir layout per the ": docs/problems/ flat layout migration — per-state subdirs + adopter auto-migration" release design migration window:
677
+ ```bash
678
+ ls docs/problems/<NNN>-*.md docs/problems/*/<NNN>-*.md 2>/dev/null
679
+ ```
680
+
681
+ Apply the update — this could be:
682
+ - Adding root cause evidence to the "Root Cause Analysis" section
683
+ - Checking off investigation tasks
684
+ - Adding a "Fix Strategy" section
685
+ - Adding "Related" links
686
+ - Updating priority based on new information
687
+
688
+ #### README.md refresh on conditional update (the "Problem 094: `/wr-itil:manage-problem` does not refresh `docs/problems/README.md` on ticket creation" problem)
689
+
690
+ If the update changed the ticket's **Priority**, **Effort**, or **WSJF** line, regenerate `docs/problems/README.md` to reflect the new ranking and stage it in the same commit as the update. If the update was to other sections (Root Cause Analysis, Symptoms, Related, Dependencies, etc.) and did NOT change the ranking-bearing fields, skip the refresh — the rendered table would be identical and the cost is not load-bearing.
691
+
692
+ **Trigger rule**: refresh if any of these lines changed between pre-edit and post-edit:
693
+
694
+ - `**Priority**: ...` (Impact × Likelihood line)
695
+ - `**Effort**: ...`
696
+ - `**WSJF**: ...`
697
+
698
+ If the edit touched only `## Root Cause Analysis`, `## Symptoms`, `## Workaround`, `## Dependencies`, `## Related`, or other non-ranking sections, skip the refresh. A conservative check is: run a diff of the pre-edit vs post-edit file and grep for any of the three field labels above in the diff's `+` / `-` lines; if none match, skip.
699
+
700
+ **Mechanism** (when the trigger fires):
701
+
702
+ 1. Regenerate `docs/problems/README.md` using the same render rules as Step 7's the "Problem 062: `manage-problem` does not refresh `docs/problems/README.md` on single-ticket transitions; fast-path cache goes stale silently" problem block — render, not re-rank. Trust every other ticket's stored WSJF; consume only this ticket's updated WSJF from the post-edit file.
703
+ 2. Update the "Last reviewed" line per the **inline the "`docs/problems/README.md` line 3 narrative-blob accumulator bloat — sibling to (briefing tier 3) on a different surface" problem rotation mechanism** below. The mechanism is inlined here at the execution site (not deferred via cross-reference to the § Last-reviewed line discipline subsection further up this SKILL) so a single-pass agent reading this Step 6 does not silently skip the archive step. **Skipping the BEFORE-rewrite archive step destroys the displaced fragment and re-opens the "transition-problem SKILL Step 7 Last-reviewed rotation silently skipped across iters" problem**. The mechanism MUST execute IN ORDER:
704
+
705
+ 1. **Read** line 3 of `docs/problems/README.md`: `awk 'NR==3' docs/problems/README.md`.
706
+ 2. **Append-if-non-empty (BEFORE step 3, not after)** — if line 3 is non-empty AND not a same-session same-verb near-duplicate of the new fragment, append the existing line 3 verbatim to `docs/problems/README-history.md` under a `## YYYY-MM-DD` heading (creating the heading on first append for that date). Run this BEFORE the Edit-tool rewrite in step 3 — Edit's replace pattern destroys the displaced content otherwise.
707
+ 3. **Rewrite** line 3 of `docs/problems/README.md` with the new fragment of form `> Last reviewed: YYYY-MM-DD **<event>** — <one-line summary>` (e.g. `P<NNN> re-rated — <old-WSJF> → <new-WSJF>`). Soft cap ≤ 1024 bytes; hard ceiling 5120 bytes per the "Session-start briefing surface — SessionStart hook over tiered directory + indexed README" architecture rule Tier 3 envelope.
708
+ 4. **Stage both** — `git add docs/problems/README.md docs/problems/README-history.md` so the same single commit per the "Governance Skills Commit Their Own Completed Work" architecture rule captures both files.
709
+
710
+ Canonical rationale anchor: § Last-reviewed line discipline (the "`docs/problems/README.md` line 3 narrative-blob accumulator bloat — sibling to (briefing tier 3) on a different surface" problem) subsection in Step 5 above. The cross-reference is preserved for the "why"; the "what" is inlined above for execution-time legibility per the "transition-problem SKILL Step 7 Last-reviewed rotation silently skipped across iters" problem.
711
+ 3. `git add docs/problems/README.md` so the refresh rides the same commit as the ticket update per the "Governance Skills Commit Their Own Completed Work" architecture rule. When line-3 truncation displaces prior content, also `git add docs/problems/README-history.md`.
712
+
713
+ **Dependency ripple**: if this update changed the ticket's Effort, and the ticket is an upstream of other tickets (any ticket's `## Dependencies` → `**Blocked by**` list references this ID), the transitive-effort rule (the "Problem 076: WSJF scoring in manage-problem does not model transitive dependencies" problem) says dependents may need to re-rate too. The surgical render in this step does NOT re-walk the graph — that is Step 9b.1's job. If the dependency graph is known to be non-trivial, prefer `/wr-itil:review-problems` instead of a bare update; the review path handles the re-walk deterministically. The conditional refresh here is sufficient for the common case of a self-only re-rate.
714
+
715
+ ### 7. For status transitions
716
+
717
+ **Open → Known Error** (rename file, update content):
718
+
719
+ Known Error means "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, 2026-06-08 amendment). The fix is proposed AFTER Known Error, by drawing a release row on a story map. Releasing the fix is a separate Known Error → Verification Pending transition — do NOT stay on `.known-error.md` after the fix ships.
720
+
721
+ Pre-flight checks before allowing transition:
722
+ - [ ] Root cause is documented (not just "Preliminary Hypothesis")
723
+ - [ ] At least one investigation task is checked off
724
+ - [ ] A reproduction test exists or is referenced
725
+ - [ ] A workaround is documented (even if "feature disabled")
726
+ - [ ] Effort bucket re-rated against the now-documented fix strategy; if the bucket changed since creation, update the Effort / WSJF lines and note the reason (the "Problem 047: WSJF effort buckets are coarse and not re-rated at lifecycle transitions" problem — creation-time estimates drift as scope clarifies)
727
+ - [ ] Status multiplier re-rated from Open 1.0 to Known Error 2.0; recompute WSJF with the post-transition status and current Effort (the "WSJF uses the pre-transition status multiplier" problem)
728
+
729
+ If any check fails, report which checks failed and ask the user to address them before transitioning.
730
+
731
+ #### External-root-cause detection (the "Problem 063: manage-problem does not trigger /wr-itil:report-upstream when root cause is external" problem)
732
+
733
+ Before renaming the file, scan the ticket's Root Cause Analysis section for external-root-cause markers. The same detection fires when parking a ticket with the `upstream-blocked` reason (see the Parked lifecycle entry at the top of this skill — it routes back to this block).
734
+
735
+ **Strict detection tokens** (any of the following within the Root Cause Analysis section counts as a hit):
736
+
737
+ - Literal label words: `upstream`, `third-party`, `external`, `vendor`.
738
+ - Scoped npm package pattern: `@[\w-]+/[\w-]+` (e.g. `@anthropic/claude-code`, `@windyroad/itil`).
739
+
740
+ Bash heuristic:
741
+
742
+ ```bash
743
+ if grep -iE '\b(upstream|third-party|external|vendor)\b|@[[:alnum:]_-]+/[[:alnum:]_-]+' "$problem_file"; then
744
+ external_root_cause_detected=1
745
+ fi
746
+ ```
747
+
748
+ Detection is intentionally **strict** (explicit label or scoped-npm package only) to avoid prompt fatigue (the "Problem 063: manage-problem does not trigger /wr-itil:report-upstream when root cause is external" problem Direction decision). A passing reference to a bare package name (`gh`, `npm`) does NOT trigger the prompt.
749
+
750
+ **Already-noted check** — before firing the prompt, grep the ticket for the stable marker `- **Upstream report pending** --` (canonical ASCII form per the "work-problems SKILL.md AFK-fallback marker wording uses em-dash, forces consumer-side whitespace surgery" problem) or the legacy em-dash variant `- **Upstream report pending** —` (written by option 2 / the AFK fallback below; the grep MUST match BOTH variants for backward compatibility) or `- **Reported Upstream:**` / a `## Reported Upstream` section (written by `/wr-itil:report-upstream` Step 7 back-write per the "Cross-project problem-reporting contract — `report-upstream` skill in `@windyroad/itil`" architecture rule Confirmation criterion 3a). If any of those are already present, skip the prompt — the detection has already fired on a prior run.
751
+
752
+ **If the detection fires and nothing has been noted yet**, use `request_user_input`:
753
+
754
+ - `header: "External root cause detected"`
755
+ - `multiSelect: false`
756
+ - Options:
757
+ 1. `Invoke /wr-itil:report-upstream now` — halt the transition; the skill runs (it writes the `## Reported Upstream` appendage per the "Cross-project problem-reporting contract — `report-upstream` skill in `@windyroad/itil`" architecture rule Confirmation criterion 3a); the transition resumes afterwards.
758
+ 2. `Defer and note in ticket` — append a pending-upstream-report line to the ticket's `## Related` section using the stable marker `- **Upstream report pending** -- external dependency identified; invoke /wr-itil:report-upstream when ready`. The marker wording is fixed (ASCII `--` per the "work-problems SKILL.md AFK-fallback marker wording uses em-dash, forces consumer-side whitespace surgery" problem — ASCII-only in machine-parseable identifiers; em-dash permitted in pure narrative prose) so subsequent runs (and the work-problems `upstream-blocked` skip path) can detect "already noted" without re-firing.
759
+ 3. `Not actually upstream` — proceed without invocation; append the same marker with text `- **Upstream report pending** -- false positive; detection misfire` so the prompt does not re-fire on later reviews.
760
+
761
+ **Non-interactive (AFK) branch** (per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6 + the "Cross-project problem-reporting contract — `report-upstream` skill in `@windyroad/itil`" architecture rule 2026-06-04 (the "Agent waits for human to initiate upstream report instead of filing on detect — feedback delay class" problem) amendment): when `request_user_input` is unavailable, **auto-invoke `/wr-itil:report-upstream`** instead of deferring with the marker. The skill composes the report draft via its own Steps 1–5/4b/5c/6 then scores the drafted prose via the `wr-risk-scorer:external-comms` agent (the "External-comms gate — voice-tone + risk/leak evaluators on shared PreToolUse surface" architecture rule) per the "Cross-project problem-reporting contract — `report-upstream` skill in `@windyroad/itil`" architecture rule 2026-06-04 amendment's orchestrator-side pre-fire gate. Branches:
762
+
763
+ - **Below external-comms appetite** → the skill proceeds (public-issue path Step 5, comment path Step 5c, or security path Step 6 per the existing classification routing); commits the `## Reported Upstream` back-write per Step 7 / Step 8.
764
+ - **Above appetite** → the skill takes risk-reducing measures (per the "Auto-apply scorer remediations to reach within appetite — open action-class vocabulary" architecture rule within-axis precedent generalised to the external-comms risk class — the measures vocabulary is **open-ended LLM judgement** per the "Cross-project problem-reporting contract — `report-upstream` skill in `@windyroad/itil`" architecture rule 2026-06-04 second-amendment ratification leaf (a): the `wr-risk-scorer:external-comms` agent's own scoring picks the remedy case-by-case, matching the "Auto-apply scorer remediations to reach within appetite — open action-class vocabulary" architecture rule's open-vocabulary precedent — NOT a bounded enumeration); re-scores; if within appetite → sends; else → **queues** an `outstanding_questions` entry naming the local ticket ID + queued report path + risk-reduce attempts + residual band + remedy ("review the queued report at `/wr-itil:report-upstream <NNN> <upstream-repo-url>` on return"). The orchestrator continues (the "AFK iter default when a skill needs to ask a question and request_user_input is unavailable — should queue the question and move to the next iteration (not halt, not silently skip)" problem queue-and-continue). The `## Queued Upstream Report` section (renamed from `## Drafted Upstream Report` per the "Cross-project problem-reporting contract — `report-upstream` skill in `@windyroad/itil`" architecture rule 2026-06-04 second-amendment leaf (c) — same shape; new name reflects the queue-for-review-on-return semantics) carries the report content for the queued question's reference. Security-path routing follows leaf (b) ratification: upstream-with-`SECURITY.md` + below-appetite → file via the declared channel; upstream-without-`SECURITY.md` but with another disclosure channel → external-comms-gated assessment considering impact to (i) our repository, (ii) our reputation, (iii) the party we are reporting to.
765
+
766
+ The legacy `- **Upstream report pending** --` marker append (canonical ASCII per the "work-problems SKILL.md AFK-fallback marker wording uses em-dash, forces consumer-side whitespace surgery" problem; em-dash variant is the pre-the "work-problems SKILL.md AFK-fallback marker wording uses em-dash, forces consumer-side whitespace surgery" problem form, still matched for backward compatibility) — the pre-2026-06-04 AFK default — is **superseded** by this auto-invoke branch for all classifications including security. Tickets that already carry the marker from prior sessions (either form) are still handled correctly by the work-problems Step 4 classifier — the new path's "already-noted check" matches both variants and routes to the report-upstream invocation. The marker shape is retained for backward compatibility on the parking + interactive fallback paths (interactive option 2 still appends it; see options 1/2/3 above).
767
+
768
+ **Scope**: this detection block fires at two points —
769
+
770
+ - **Open → Known Error transition** (this step, primary insertion point).
771
+ - **Parking path with `upstream-blocked` reason** — the parking workflow runs the same detection before `git mv` to `.parked.md`. Parking an upstream-blocked ticket without having noted (or reported) the upstream dependency is the canonical audit-trail gap this block closes.
772
+
773
+ The work-problems orchestrator's `upstream-blocked` skip path (see `<itil-plugin-root>/skills/work-problems/SKILL.md` classifier table) runs the AFK fallback before skipping, so ticket bodies accumulate the marker even when the orchestrator never invokes `manage-problem` on them.
774
+
775
+ > **Staging trap (the "Problem 057: `git mv` + Edit + `git add` staging-ordering trap drops content edits from the commit" problem).** `git mv` stages only the rename — it does NOT pick up subsequent `Edit`-tool content changes. After the `Edit` tool modifies the renamed file (Status field, `## Fix Released` section, etc.), re-stage it explicitly: `git add <new>`. Without the explicit re-stage, the transition commit captures the rename-only change and the content edit leaks into the next commit, corrupting the audit trail. This rule applies to every `git mv` block below (Open → Known Error, Known Error → Verification Pending, Verification Pending → Closed) and to the supersession rename in `create-adr` Step 6.
776
+
777
+ ```bash
778
+ git mv docs/problems/open/<NNN>-<title>.md docs/problems/known-error/<NNN>-<title>.md
779
+ # ... use the Edit tool to update the Status field ...
780
+ git add docs/problems/known-error/<NNN>-<title>.md
781
+ ```
782
+
783
+ Update the "Status" field in the file to "Known Error".
784
+
785
+ **Known Error → Verification Pending** (fix released, per the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule):
786
+
787
+ When the fix for a Known Error ships, transition the ticket in a single commit.
788
+
789
+ #### Conditional-deferral check BEFORE the rename (the "Agent treats conditionally-deferred work (deferred-pending-X-graduation) as permanently out of scope — prematurely transitions parent ticket when X graduates" problem)
790
+
791
+ BEFORE the `git mv` to `.verifying.md`, scan the `.known-error.md` ticket body for **phase-tracking sections with unticked checkboxes whose deferral conditions have now lifted**. Conditional-deferral language ("Phase N SHIP deferred to post-Phase-M-graduation" / "deferred-pending-X-graduation" / "Phase N deferred until Y") names a CONDITION — it is NOT terminal. When the gating condition fires (Phase M graduates, dependency Y ships), the conditionally-deferred work is back IN SCOPE; transitioning K→V while it remains unticked silently loses the work. the "Agent treats conditionally-deferred work (deferred-pending-X-graduation) as permanently out of scope — prematurely transitions parent ticket when X graduates" problem's driver case (the "Problem tickets strain as fixes decompose into multiple coordinated changes — need an RFC framework that ties all changes back to problems (and unifies technical with user/business problems)" problem Phase 2 SHIP deferred to post-Phase-1-graduation) is the canonical regression — the agent's NLP parsed "deferred" as terminal without checking the conditional clause, transitioned the parent ticket, and would have lost the Phase 2 work if the user hadn't asked an orthogonal question that surfaced the misreading.
792
+
793
+ **Detection** (run in order):
794
+
795
+ 1. Grep the ticket body for phase-tracking section headers — regex `^### (Phase|Slice|Tier) [0-9]+` covers the canonical shapes.
796
+ 2. For each detected section, count the unticked `- [ ]` checkboxes inside it (up to the next `^### ` boundary or EOF).
797
+ 3. Grep the body (any section, not just the phase-tracking one) for conditional-deferral markers:
798
+ - `deferred (?:to|pending|until) (?:post-)?[A-Za-z0-9-]+(?:-graduation)?`
799
+ - `Phase [0-9]+ (?:SHIP )?deferred`
800
+ - `deferred-pending-[a-z-]+`
801
+ 4. For each conditional-deferral marker, resolve whether the **gating condition** has fired. The gating condition typically names another phase, ticket, or RFC — check whether that artefact has reached `.closed.md` / `.verifying.md` (for tickets), or `closed` lifecycle (for RFCs / stories per the "Problem-RFC-Story framework with mandatory problem-trace and unified problem ontology" architecture rule).
802
+
803
+ **Halt-and-route** (when ANY conditional deferral has lifted with unticked work remaining):
804
+
805
+ Emit a structured report naming each deferred section + the lifted condition + the unticked task count, then **halt the transition**:
806
+
807
+ - **Interactive**: fire `request_user_input` with `header: "Conditional deferral lifted"` + options:
808
+ 1. `Re-open Phase N — work the deferred tasks now (Recommended)` — halt the K→V transition; route to working the deferred Phase N tasks; revert to Known Error.
809
+ 2. `Confirm Phase N permanently out of scope — proceed with K→V` — user explicit acknowledgement that the deferral was misclassified as conditional and is in fact terminal; proceed with the K→V transition; append `<!-- the "Agent treats conditionally-deferred work (deferred-pending-X-graduation) as permanently out of scope — prematurely transitions parent ticket when X graduates" problem: user-confirmed Phase N permanently OOS -->` marker to the deferred section so re-detection skips it.
810
+ 3. `Split Phase N into a new ticket — proceed with K→V on this one` — halt the K→V transition; route to `/wr-itil:capture-problem` for a new ticket carrying the Phase N scope; once captured, resume the K→V transition on the original ticket.
811
+ - **AFK** (per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6 + the "AFK iter default when a skill needs to ask a question and request_user_input is unavailable — should queue the question and move to the next iteration (not halt, not silently skip)" problem queue-and-continue universal default): queue an `outstanding_questions` entry naming the local ticket ID + the lifted-condition citation + the unticked task count + the three options above. **Do NOT auto-transition.** The orchestrator main turn surfaces the queued question at loop end via the existing batched-`request_user_input` end-of-loop gate. Brief the substance BEFORE referencing IDs per `feedback_brief_before_id.md` — the user reads the prompt without project filesystem access.
812
+
813
+ **Proceed silently** (no halt) when:
814
+ - No phase-tracking sections exist in the ticket body (the common case).
815
+ - Phase-tracking sections exist but every task is ticked.
816
+ - Phase-tracking sections exist with unticked tasks BUT the deferral marker explicitly states "permanently out of scope" / "won't fix" / "rejected" without a conditional clause.
817
+ - The conditional-deferral marker carries the `<!-- the "Agent treats conditionally-deferred work (deferred-pending-X-graduation) as permanently out of scope — prematurely transitions parent ticket when X graduates" problem: user-confirmed Phase N permanently OOS -->` marker from a prior surfacing.
818
+
819
+ **Why halt-and-route not silent-default-with-marker**: the "Agent treats conditionally-deferred work (deferred-pending-X-graduation) as permanently out of scope — prematurely transitions parent ticket when X graduates" problem's failure mode is "work silently lost if user doesn't notice"; the "Problem 063: manage-problem does not trigger /wr-itil:report-upstream when root cause is external" problem silent-default-with-marker shape leaves the lost-work-detection burden on the user reading the marker in the Verification Queue. The halt-and-route shape catches the failure at the transition surface where the loss occurs. Authority: the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule category 2 (deviation-approval) — the agent surfaces a deviation candidate with citations + evidence + a proposed shape; user picks. Driver: user direction in the "Agent treats conditionally-deferred work (deferred-pending-X-graduation) as permanently out of scope — prematurely transitions parent ticket when X graduates" problem Workaround line 37 — *"explicitly ask the user 'is Phase N still deferred or is it now in-scope?' before transitioning when the ticket body shows phase-tracking sections."*
820
+
821
+ 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 below — halt-on-conditional-deferral is the outer gate, seed-and-rename is the inner mechanic.
822
+
823
+ **Seed `Release vehicle` reference BEFORE the rename (the "derive-release-vehicle helper requires pre-edit of ticket changeset reference — three-touch when one-touch would suffice" problem).** BEFORE the `git mv` to `.verifying.md`, edit the `.known-error.md` ticket body to append a `**Release vehicle**: .changeset/<name>.md` paragraph at the END of the `## Fix Strategy` section (create the section if absent). The `<name>.md` is the kebab-case slug of the changeset file the fix commit authored under `.changeset/` (e.g. `<itil-plugin-root>/bin/wr-itil-p330-option-b.md`). The seed eliminates the `<itil-plugin-root>/bin/wr-itil-derive-release-vehicle <NNN>` helper's exit-2 routing on standalone K→V iters — the helper greps the ticket body for `.changeset/<name>.md` and exits 2 when absent; seeding the reference at fix-ship time (when the changeset name is fresh in scope, since the fix commit just created it) makes the helper exit 0 deterministically on first call. The exit-2 recovery routing documented in `/wr-itil:transition-problem` Step 6 remains as the legacy-ticket fallback. Matches the user's documented workaround pattern across 3 of 4 standalone K→V dogfoods in the 2026-05-30 session (the "Rejected-pending-supersede ADRs re-surface in every review-decisions drain — no "rejected" state to suppress them" problem / the "capture-problem skill template references pre- flat-path shape" problem / the "ADR-confirmation summaries should lead with the Decision Outcome, not the meta-framing (caused 2 user re-asks this session)" problem — see the "derive-release-vehicle helper requires pre-edit of ticket changeset reference — three-touch when one-touch would suffice" problem § Symptoms).
824
+
825
+ > **Two the "Problem 057: `git mv` + Edit + `git add` staging-ordering trap drops content edits from the commit" problem staging-trap windows on K→V (seed + rename).** The seed Edit on `.known-error.md` is the FIRST the "Problem 057: `git mv` + Edit + `git add` staging-ordering trap drops content edits from the commit" problem window; the Edit that updates Status / writes `## Fix Released` AFTER the `git mv` is the SECOND. Consolidate staging into a SINGLE `git add docs/problems/verifying/<NNN>-<title>.md` AFTER both Edits + the `git mv`. `git mv` operates on the index entry — the body content the index references at rename time is the post-seed content, so the seed Edit's content is carried across the rename automatically; the single final `git add` re-stages the post-rename file with the post-`Edit` Status + `## Fix Released` content. The seed step does NOT introduce a separate `git add` of the `known-error/` path — staging discipline stays single-call by riding the rename's index entry.
826
+
827
+ ```bash
828
+ # Step 1 — seed `**Release vehicle**: .changeset/<name>.md` in the Fix Strategy section
829
+ # ... use the Edit tool to append the seed paragraph to docs/problems/known-error/<NNN>-<title>.md ...
830
+
831
+ # Step 2 — rename
832
+ git mv docs/problems/known-error/<NNN>-<title>.md docs/problems/verifying/<NNN>-<title>.md
833
+
834
+ # Step 3 — update Status + add `## Fix Released` section
835
+ # ... use the Edit tool on docs/problems/verifying/<NNN>-<title>.md ...
836
+
837
+ # Step 4 — single re-stage covers both Edit windows
838
+ git add docs/problems/verifying/<NNN>-<title>.md
839
+ ```
840
+
841
+ Then edit the file:
842
+ - Update the "Status" field to "Verification Pending"
843
+ - Add a `## Fix Released` section with: release marker (version, commit SHA, or date), one-sentence fix summary, "Awaiting user verification" line, and any exercise evidence from the releasing session.
844
+
845
+ Re-stage the `.verifying.md` file explicitly after the `Edit` tool runs (the "Problem 057: `git mv` + Edit + `git add` staging-ordering trap drops content edits from the commit" problem). The trailing `git add` above is NOT redundant — `git mv` alone stages only the rename, not the subsequent content edit; the same `git add` also re-stages the seed Edit content carried across the rename (single staging call, two Edit windows; the "derive-release-vehicle helper requires pre-edit of ticket changeset reference — three-touch when one-touch would suffice" problem + the "Problem 057: `git mv` + Edit + `git add` staging-ordering trap drops content edits from the commit" problem).
846
+
847
+ Both the `git mv` and the file edits belong in the same commit as the fix implementation per the "Governance Skills Commit Their Own Completed Work" architecture rule (governance skills commit their own work). 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.
848
+
849
+ **Verification Pending → Closed** (user confirms):
850
+
851
+ Only the user can make this call. When they explicitly confirm the fix works in production:
852
+
853
+ ```bash
854
+ git mv docs/problems/verifying/<NNN>-<title>.md docs/problems/closed/<NNN>-<title>.md
855
+ # ... use the Edit tool to update the Status field to "Closed" ...
856
+ git add docs/problems/closed/<NNN>-<title>.md
857
+ ```
858
+
859
+ Update the "Status" field to "Closed". Reference the problem ID in the closure commit message (e.g., "Closes the "Problem 008: request_user_input Unavailable When --channels Is Active" problem"). Step 9d's verification prompt is the structured path that fires this transition during `manage-problem review`. Re-stage the `.closed.md` file explicitly after the Edit (the "Problem 057: `git mv` + Edit + `git add` staging-ordering trap drops content edits from the commit" problem staging trap).
860
+
861
+ #### README.md refresh on every transition (the "Problem 062: `manage-problem` does not refresh `docs/problems/README.md` on single-ticket transitions; fast-path cache goes stale silently" problem)
862
+
863
+ Every Step 7 status transition (Open → Known Error, Known Error → Verification Pending, Verification Pending → Closed, Parked — regardless of source or destination suffix) regenerates `docs/problems/README.md` and stages it in the same commit so the dev-work table, Verification Queue, Parked section, and "Last reviewed" line never lag the on-disk ticket inventory. Without this step, README.md accumulates staleness between `review` invocations; the next `work` fast-path check correctly detects the lag and forces a full rescan (self-healing but wasteful), and any human browsing the file between transitions sees outdated rankings.
864
+
865
+ The refresh uses the same rendering rules as Step 9e (dual-tolerant glob per the ": docs/problems/ flat layout migration — per-state subdirs + adopter auto-migration" release design 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.
866
+
867
+ **WSJF Rankings tier + tie-break sort (the "`docs/problems/README.md` WSJF Rankings table row order doesn't match `/wr-itil:work-problems`'s tie-break selection — users assume the orchestrator is broken" problem + the "Inbound-reported problems rank ahead of internally-discovered problems via a sort tier" architecture rule)**: 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 (the "Inbound-reported problems rank ahead of internally-discovered problems via a sort tier" architecture rule) --> <!-- 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 the "Problem 094: `/wr-itil:manage-problem` does not refresh `docs/problems/README.md` on ticket creation" problem block, the Step 9e template, AND `/wr-itil:review-problems` SKILL.md Step 3 / Step 5 — drift here re-opens the "`docs/problems/README.md` WSJF Rankings table row order doesn't match `/wr-itil:work-problems`'s tie-break selection — users assume the orchestrator is broken" problem / the "Inbound-reported problems rank ahead of internally-discovered problems via a sort tier" architecture rule.
868
+
869
+ **Verification Queue sort direction (the "docs/problems/README.md Verification Queue rendered newest-first contradicts section header "Ranked by release age, oldest first"" problem)**: rows in the Verification Queue table are sorted by `Released date ASC` (oldest at row 1; same-day releases tiebreak by ID ASC) per the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule + the "Problem 048: manage-problem does not surface Fix Released problems as verification candidates when the fix path has been exercised" problem 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 the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule --> Any future change to the VQ sort direction MUST update this render block, the Step 5 the "Problem 094: `/wr-itil:manage-problem` does not refresh `docs/problems/README.md` on ticket creation" problem 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 the "docs/problems/README.md Verification Queue rendered newest-first contradicts section header "Ranked by release age, oldest first"" problem.
870
+
871
+ **Likely-verified cell shape (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)**: the `Likely verified?` column carries an **evidence-first** cell — `yes — observed: <evidence>` / `no — not observed` / `no — observed regression`. Age is preserved separately via the `Released` column; session-observed evidence drives the cell. On a Known Error → Verification Pending transition the refresh writes `no — not observed` as the default (no observed evidence yet at the moment of release). <!-- LIKELY-VERIFIED-CELL-SHAPE: evidence-based per 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 --> Any future change to the cell shape MUST update this render block, the Step 5 the "Problem 094: `/wr-itil:manage-problem` does not refresh `docs/problems/README.md` on ticket creation" problem 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 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.
872
+
873
+ **Mechanism:**
874
+
875
+ 1. After renaming + Editing + `git add`-ing the transitioned ticket file (per the staging-trap rule above), regenerate `docs/problems/README.md` in-place reflecting the new filename set and the transitioned ticket's new Status.
876
+ 2. `git add docs/problems/README.md` — stage the refreshed README with the same commit as the transition.
877
+ 3. Update the "Last reviewed" line per the **inline the "`docs/problems/README.md` line 3 narrative-blob accumulator bloat — sibling to (briefing tier 3) on a different surface" problem rotation mechanism** below. The mechanism is inlined here at the execution site (not deferred via cross-reference to the § Last-reviewed line discipline subsection in Step 5 above) so a single-pass agent reading this Step 7 does not silently skip the archive step. **Skipping the BEFORE-rewrite archive step destroys the displaced fragment and re-opens the "transition-problem SKILL Step 7 Last-reviewed rotation silently skipped across iters" problem** (iter-7 + iter-8 of 2026-05-30's AFK work-problems session silently skipped the rotation in 2 of 9 transition-bearing iters under exactly that failure mode). The mechanism MUST execute IN ORDER:
878
+
879
+ 1. **Read** line 3 of `docs/problems/README.md`: `awk 'NR==3' docs/problems/README.md` (`head -3 | tail -1` or `sed -n '3p'` are acceptable equivalents).
880
+ 2. **Append-if-non-empty (BEFORE step 3, not after)** — if line 3 is non-empty AND not a same-session same-verb near-duplicate of the new fragment, append the existing line 3 verbatim to `docs/problems/README-history.md` under a `## YYYY-MM-DD` heading (creating the heading on first append for that date; subsequent same-day appends nest under the existing heading). Run this BEFORE the Edit-tool rewrite in step 3 — Edit's replace pattern destroys the displaced content otherwise.
881
+ 3. **Rewrite** line 3 of `docs/problems/README.md` with the new fragment of form `> Last reviewed: YYYY-MM-DD **<event>** — <one-line summary>` (e.g. `P<NNN> <status> — <one-line fix summary>`). Soft cap ≤ 1024 bytes per fragment; hard ceiling 5120 bytes per the "Session-start briefing surface — SessionStart hook over tiered directory + indexed README" architecture rule Tier 3 envelope.
882
+ 4. **Stage both** — `git add docs/problems/README.md docs/problems/README-history.md` so the same single commit per the "Governance Skills Commit Their Own Completed Work" architecture rule single-commit grain captures both files.
883
+
884
+ Canonical rationale anchor: § Last-reviewed line discipline (the "`docs/problems/README.md` line 3 narrative-blob accumulator bloat — sibling to (briefing tier 3) on a different surface" problem) subsection in Step 5 above. The cross-reference is preserved for the "why"; the "what" is inlined above for execution-time legibility per the "transition-problem SKILL Step 7 Last-reviewed rotation silently skipped across iters" problem.
885
+
886
+ **Scope**: fires for every Step 7 rename. Applies equally to:
887
+ - Standalone transition commits (e.g. `docs(problems): P<NNN> known error — <summary>`).
888
+ - **Folded-fix commits** where the `.verifying.md` transition rides with the fix implementation commit (e.g. `fix(<scope>): <description> (closes P<NNN>)` — per Step 11's convention for Known Error → Verification Pending). In both cases the refreshed README.md joins the same commit as the rename + content edit; never split across commits.
889
+
890
+ **Fast-path interaction**: the Step 9 fast-path freshness check (`git log -1 --format=%H -- docs/problems/README.md` followed by `git log --oneline "${readme_commit}..HEAD" -- 'docs/problems/*.md'`) remains the authoritative staleness test. When this refresh fires on every transition, that check should return empty on any subsequent invocation — the cache stays fresh by construction. If the check still reports "stale", something skipped the refresh (bug) and the slow-path is the correct recovery.
891
+
892
+ #### Bidirectional upstream lifecycle update (the "Problem 080: No bidirectional update of upstream-reported problems — local lifecycle transitions never propagate back to the reporter" problem — advisory, copy-not-move from transition-problem Step 7b)
893
+
894
+ After the rename + README refresh land but BEFORE the Step 11 commit, fire the bidirectional lifecycle-update sibling skill so the upstream issue (if any) receives the lifecycle update comment in the SAME commit as the transition per the "Governance Skills Commit Their Own Completed Work" architecture rule single-commit grain. This is the **outbound-lifecycle-update leg** of the reporter loop (the inbound-discovery leg is owned by the "Inbound upstream-report discovery + assessment pipeline (peer of )" architecture rule's assessment pipeline; together they close the reporter relationship per the "Report a Problem Without Pre-Classifying It" user outcome + the "Restore Service Fast with an Audit Trail" user outcome).
895
+
896
+ This subsection is the **copy-not-move sibling** of `transition-problem` SKILL.md Step 7b per [the "Rename `wr-problem` Plugin to `wr-itil`" architecture rule](../../../docs/decisions/010-rename-wr-problem-to-wr-itil.proposed.md) amended "Split-skill execution ownership" rule (the "Problem 093: `/wr-itil:transition-problem` ↔ `/wr-itil:manage-problem` circular delegation for `<NNN> <status>` args" problem). The user-initiated transition path lives in `/wr-itil:transition-problem`; the in-skill callers (Step 9b auto-transition, Step 9d closure inside review, the Parked path) need the same lifecycle-update trigger and carry their own scoped copy. Drift between the two copies re-opens the "Problem 080: No bidirectional update of upstream-reported problems — local lifecycle transitions never propagate back to the reporter" problem's bidirectional gap on the in-skill paths.
897
+
898
+ The trigger fires **whenever the ticket carries a `## Reported Upstream` section (outbound) OR an `**Origin**: inbound-reported (#NN)` field (inbound, the "Inbound-reported tickets never receive fix-released verdict on originating issue" problem)** — gate the installed-skill-invocation dispatch behind a one-line mechanical pre-check rather than dispatching on every transition. Dispatching unconditionally pays the full `/wr-itil:update-upstream` SKILL.md context load (~14 KB into the calling agent's context) just to hit the sibling skill's no-op exit; the common case is a ticket with neither surface, so the load is wasted (the "Unconditional update-upstream Skill dispatch pays full SKILL.md context load for the common no-op case" problem). The grep IS the trigger: it preserves the fire-whenever-a-surface-exists semantics — an upstream/inbound comment posts iff one of the two surfaces is present — while eliminating the context load for the common no-op case. Authority: [the "SKILL.md runtime budget policy" architecture rule](../../../docs/decisions/054-skill-md-runtime-budget-policy.proposed.md) (SKILL.md runtime-budget policy; [the "Progressive disclosure + once-per-session budget for UserPromptSubmit governance prose" architecture rule](../../../docs/decisions/038-progressive-disclosure-for-governance-tooling-context.proposed.md) progressive-disclosure as the ancestor principle); [the "Cross-project problem-reporting contract — `report-upstream` skill in `@windyroad/itil`" architecture rule](../../../docs/decisions/024-cross-project-problem-reporting-contract.proposed.md) amendment (the "Inbound-reported tickets never receive fix-released verdict on originating issue" problem) for the inbound-origin alternation.
899
+
900
+ **Pre-check first** (mechanical — no user decision): run `grep -qE '^## Reported Upstream|^\*\*Origin\*\*: inbound-reported \(#' <ticket-file>`. If it does NOT match (NEITHER the outbound `## Reported Upstream` section NOR the inbound `**Origin**: inbound-reported (#NN)` field is present), skip the Skill dispatch entirely, log one line (`no ## Reported Upstream section and no inbound Origin; skipping upstream lifecycle update`), and proceed to Step 11. Only when it matches, invoke the sibling skill via the installed skill invocation:
901
+
902
+ ```
903
+ /wr-itil:update-upstream <NNN>
904
+ ```
905
+
906
+ Behaviour matrix:
907
+
908
+ - **Neither `## Reported Upstream` section nor inbound `**Origin**` field on the local ticket** → the grep pre-check skips the Skill dispatch (no context load); log `no ## Reported Upstream section and no inbound Origin; skipping upstream lifecycle update` and proceed to Step 11. (The sibling skill retains its own Step 1 no-op exit as defence-in-depth for any path that reaches it directly.)
909
+ - **`**Origin**: inbound-reported (#NN)` present** → the sibling skill runs its inbound-origin verdict dispatch leg (the "Inbound-reported tickets never receive fix-released verdict on originating issue" problem): posts the reporter-facing fix-released / closed verdict on the originating own-repo issue through the same external-comms + voice-tone gates, idempotency-guarded, and back-writes a direction-tagged `## Upstream Lifecycle Updates` entry. If BOTH surfaces are present, the outbound and inbound legs fire independently.
910
+ - **`## Reported Upstream` present AND both gates within appetite** → the sibling skill posts via `gh issue comment` (and on Verifying → Closed, also `gh issue close`), back-writes to `## Upstream Lifecycle Updates`, and stages the back-write into the index. The Step 11 commit captures the back-write alongside the transition.
911
+ - **`## Reported Upstream` present AND above-appetite (after silent risk-reduce + re-score)** → the sibling skill saves the drafted comment to `## Queued Upstream Update` and queues an `outstanding_questions` entry. The Step 11 commit captures the `## Queued Upstream Update` appendage alongside the transition. **The orchestrator continues per the "AFK iter default when a skill needs to ask a question and request_user_input is unavailable — should queue the question and move to the next iteration (not halt, not silently skip)" problem queue-and-continue** — do NOT halt the transition on an above-appetite upstream update.
912
+
913
+ If `/wr-itil:update-upstream` is not installed (the `@windyroad/itil` package version pre-dates the "Problem 080: No bidirectional update of upstream-reported problems — local lifecycle transitions never propagate back to the reporter" problem shipping), the installed skill invocation returns a not-found error. Log a one-line warning (`update-upstream skill not available; skipping upstream lifecycle update`) and proceed to Step 11 — do NOT halt the transition.
914
+
915
+ Per [the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6](../../../docs/decisions/013-structured-user-interaction-for-governance-decisions.proposed.md) (AFK fail-safe), AFK orchestrators MUST NOT halt this transition path on a queued upstream-update — the queued entry surfaces at the existing batched-`request_user_input` end-of-loop gate.
916
+
917
+ Authority: [the "Cross-project problem-reporting contract — `report-upstream` skill in `@windyroad/itil`" architecture rule](../../../docs/decisions/024-cross-project-problem-reporting-contract.proposed.md) amendment (the "Problem 080: No bidirectional update of upstream-reported problems — local lifecycle transitions never propagate back to the reporter" problem) — bidirectional lifecycle-update sibling skill. The advisory ALSO lives in `/wr-itil:transition-problem` Step 7b per the "Rename `wr-problem` Plugin to `wr-itil`" architecture rule amended "copy, not move" (the "Problem 093: `/wr-itil:transition-problem` ↔ `/wr-itil:manage-problem` circular delegation for `<NNN> <status>` args" problem) — both copies must move in lockstep.
918
+
919
+ ### 8. For list: Show summary
920
+
921
+ Read all open + known-error tickets via the dual-tolerant glob `ls docs/problems/*.open.md docs/problems/*.known-error.md docs/problems/open/*.md docs/problems/known-error/*.md 2>/dev/null` (the ": docs/problems/ flat layout migration — per-state subdirs + adopter auto-migration" release design migration window). Extract ID, title, priority, and status. Sort by priority (highest first). Display as a markdown table.
922
+
923
+ ### 9. For review: Re-assess all open problems
924
+
925
+ This is a batch operation that reviews every open/known-error problem and updates it.
926
+
927
+ **Fast-path for `work` (skip full re-scan when cache is fresh):**
928
+
929
+ Before running the full review, check whether `docs/problems/README.md` exists and is up to date using **git history** (not filesystem mtime, which is unreliable in worktrees and fresh checkouts — see the "Problem 031: `manage-problem work` incorrectly determines cache is fresh" problem):
930
+
931
+ ```bash
932
+ readme_commit=$(git log -1 --format=%H -- docs/problems/README.md 2>/dev/null)
933
+ # Cache is stale if: no README commit, OR problem files committed since README, OR uncommitted problem file changes.
934
+ # Pathspec pair `'docs/problems/*.md' 'docs/problems/*/*.md'` is the
935
+ # the ": docs/problems/ flat layout migration — per-state subdirs + adopter auto-migration" release design dual-tolerant transitional shape — covers BOTH the flat
936
+ # layout AND the per-state subdir layout. T6 drops the flat half post-T5.
937
+ if [ -z "$readme_commit" ] || \
938
+ git log --oneline "${readme_commit}..HEAD" -- 'docs/problems/*.md' 'docs/problems/*/*.md' ':!docs/problems/README.md' 2>/dev/null | grep -q .; then
939
+ echo "stale"
940
+ fi
941
+ ```
942
+
943
+ If the command produces **no output** (no problem files have been committed or modified since the last README.md update), the cache is fresh:
944
+ - Read `docs/problems/README.md` only — it contains the ranked table from the last review
945
+ - Skip steps 9a–9b entirely
946
+ - Proceed to step 9c (work selection) using the cached table
947
+ - **Step 9d always fires even on the fast-path cache hit** (the "Problem 048: manage-problem does not surface Fix Released problems as verification candidates when the fix path has been exercised" problem Candidate 1): the verification prompt surface must not depend on whether the cache is fresh — pending verifications accumulate across sessions and the user expects the prompts to appear on every `review`. Skipping 9d alongside 9a–9b would suppress verification prompts whenever the cache is fresh, which is exactly when the user is most likely to verify.
948
+ - Note in the output: "Using cached ranking from [timestamp in README.md]"
949
+
950
+ If the command prints "stale", or `README.md` does not exist in git, run the full review (steps 9a–9e) and refresh the cache.
951
+
952
+ **Step 9a: Read the risk framework**
953
+
954
+ Read `RISK-POLICY.md` to get the current impact levels (1-5), likelihood levels (1-5), risk matrix, and label bands. These are the authoritative definitions — do not use outdated scales.
955
+
956
+ **Step 9b: For each open/known-error problem (skip parked / verifying tickets entirely):**
957
+
958
+ Enumerate via dual-tolerant glob `docs/problems/*.open.md docs/problems/*.known-error.md docs/problems/open/*.md docs/problems/known-error/*.md` per the ": docs/problems/ flat layout migration — per-state subdirs + adopter auto-migration" release design migration window. Parked problems and Verification Pending problems are excluded from WSJF ranking — do not read, score, or update them in this step. Parked tickets are shown in a dedicated Parked section in step 9c; Verification Pending tickets are shown in a dedicated Verification Queue section in step 9c (ranked by release age, not WSJF — per the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule).
959
+
960
+ 1. Read the problem file
961
+ 2. Read the codebase context — check if the problem's root cause has been investigated, if there are related fixes in git history, or if the problem is stale
962
+ 3. **Re-assess Impact** (1-5) using the product-specific impact levels from RISK-POLICY.md. Ask: "If this problem occurs during a live game, what is the worst business consequence?"
963
+ 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?"
964
+ 5. **Calculate Severity** = Impact × Likelihood
965
+ 6. **Look up Label** from the risk matrix label bands
966
+ 7. **Re-estimate Effort** (S / M / L / XL) by reading the root cause analysis and fix strategy. 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 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"). the "Problem 047: WSJF effort buckets are coarse and not re-rated at lifecycle transitions" problem.
967
+ 8. **Auto-transition to Known Error**: If an open problem has confirmed root cause AND a workaround documented (even "feature disabled"), automatically transition it to known-error:
968
+ - `git mv docs/problems/open/<NNN>-<title>.md docs/problems/known-error/<NNN>-<title>.md`
969
+ - Update the Status field to "Known Error"
970
+ - This happens automatically — do not ask the user
971
+ 9. **Calculate WSJF** = (Severity × Status Multiplier) / Effort Divisor, using the ticket's status after step 8 (Open 1.0; Known Error 2.0). the "WSJF uses the pre-transition status multiplier" problem.
972
+ 10. **Update the Priority and WSJF lines** in the problem file if the scores changed
973
+
974
+ **Step 9b.1: Dependency-graph traversal — propagate transitive effort (the "Problem 076: WSJF scoring in manage-problem does not model transitive dependencies" problem)**
975
+
976
+ After every `.open.md` / `.known-error.md` ticket has a marginal effort, run a **second pass** that walks the dependency graph and propagates effort up per the transitive-dependency rule (see the WSJF Prioritisation section's "Transitive dependencies" subsection). This is a deterministic re-rate — no `request_user_input` required.
977
+
978
+ 1. **Build the graph**: for each `.open.md` / `.known-error.md` ticket, parse the `## Dependencies` section. Record `Blocked by` edges (bare IDs) into an adjacency map. Ignore `Composes with` (does not propagate) and `Blocks` (derivable from inverse).
979
+ 2. **Classify upstream status**: for each upstream ID referenced in any `Blocked by` edge, resolve the file suffix. Upstreams in `.closed.md`, `.verifying.md`, or `.parked.md` contribute **0** to the closure per the carve-out. Upstreams in `.open.md` or `.known-error.md` contribute their own transitive effort.
980
+ 3. **Topologically sort** the open/known-error subgraph so upstream tickets are scored before their dependents. If a cycle is detected (two or more tickets mutually `Blocked by` each other), treat the strongly-connected component as a **bundle** with effort = `max{ marginal | members }`.
981
+ 4. **Compute transitive effort** for each ticket in topological order using `Effort_transitive = max(marginal, max{ upstream transitive })`. Cycle-bundle members all receive the bundle's effort.
982
+ 5. **Update Effort and WSJF lines**: if a ticket's transitive effort differs from its marginal, edit the Effort line to the transitive bucket (S → M / L / XL as needed), recompute WSJF, and update the Priority and WSJF lines. Write a short audit trail in a `<!-- transitive: <bucket> via <UPSTREAM> -->` HTML comment on the Effort line so the next review can distinguish a manually-set marginal from a propagated transitive.
983
+ 6. **Report each re-rate** in the review summary using the concrete format:
984
+
985
+ ```
986
+ P<NNN>: Effort <OLD> → <NEW> (transitive via <UPSTREAM>)
987
+ ```
988
+
989
+ Example: `the "Problem 073: No voice-and-tone check or risk assessment on changeset bodies (which populate CHANGELOG.md, Release PRs, GitHub Releases, and npm release notes)" problem: Effort S → XL (transitive via the "Problem 038: No voice-and-tone gate on external communications" problem)`. The shape is fixed so downstream audit tools can grep it deterministically.
990
+
991
+ 7. **Cycle-bundle output**: for cycle bundles, surface a shared WSJF line covering all members, e.g. `Bundle [the "Problem 038: No voice-and-tone gate on external communications" problem, the "Problem 064: No risk-scoring gate on external communications" problem]: effort XL (cycle), WSJF 3.0 (shared)`. The shared WSJF is a computed artefact of the review rendering — do NOT write a shared-bundle field into the individual ticket files.
992
+
993
+ The re-rate pass is part of Step 9b's output — a re-rate row appears in the step 9c ranked table with the transitive effort (not the marginal). Hide the marginal from the main table but preserve it in the ticket's HTML-comment audit trail so a future review knows where the propagation came from.
994
+
995
+ **Step 9c: Present summary and select problem to work**
996
+
997
+ 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 (the "`docs/problems/README.md` WSJF Rankings table row order doesn't match `/wr-itil:work-problems`'s tie-break selection — users assume the orchestrator is broken" problem + the "Inbound-reported problems rank ahead of internally-discovered problems via a sort tier" architecture rule): <!-- REPORTED-FIRST-TIER-SOURCE: /wr-itil:work-problems SKILL.md Step 3 (the "Inbound-reported problems rank ahead of internally-discovered problems via a sort tier" architecture rule) -->
998
+
999
+ | WSJF | ID | Title | Severity | Status | Effort | Reported | Origin | Notes |
1000
+ |------|-----|-------|----------|--------|--------|----------|--------|-------|
1001
+
1002
+ Then present a separate **Verification Queue** section for `.verifying.md` files (per the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule — 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 the "docs/problems/README.md Verification Queue rendered newest-first contradicts section header "Ranked by release age, oldest first"" problem. <!-- VQ-SORT-DIRECTION: oldest-first per the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule --> The final `Likely verified?` column carries an **evidence-first** cell (per 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 — supersedes the original the "Problem 048: manage-problem does not surface Fix Released problems as verification candidates when the fix path has been exercised" problem Candidate 4 14-day heuristic). <!-- LIKELY-VERIFIED-CELL-SHAPE: evidence-based per 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 --> Three canonical values:
1003
+
1004
+ | ID | Title | Released | Fix summary | Likely verified? |
1005
+ |----|-------|----------|-------------|------------------|
1006
+
1007
+ The `Likely verified?` column takes values (per 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):
1008
+ - `yes — observed: <evidence>` — session-observed evidence the fix works. Cite the evidence inline (≤ 120 chars): a Step 9d user confirmation phrase quoted, an in-session test invocation + observable outcome per the "Agent output grounding — no fabricated quantitative estimates, cite + persist + uncertainty" architecture rule grounding, or a `run-retro` Step 4a close-on-evidence citation. Surface these FIRST in step 9d's verification prompt so the user can batch-close them.
1009
+ - `no — not observed` — fix released but no session-observable evidence yet. Default for newly-released tickets. Fire step 9d for these too, without batch-close highlight. Aging surfaces via the `Released` column — NOT in this cell.
1010
+ - `no — observed regression` — fix released and the bug recurred this session. Cite the recurrence inline (≤ 120 chars). Do NOT batch-close — these may warrant `.verifying.md` → `.known-error.md` flip-back via `/wr-itil:transition-problem`.
1011
+
1012
+ Then present a separate **Parked** section listing `.parked.md` files (no ranking):
1013
+
1014
+ | ID | Title | Reason | Parked since |
1015
+ |----|-------|--------|-------------|
1016
+
1017
+ Highlight:
1018
+ - Problems whose priority changed (↑ or ↓)
1019
+ - Problems that were auto-transitioned to known-error
1020
+ - Problems that may be stale (reported > 2 weeks ago with no investigation progress)
1021
+ - Problems that have been fixed but not closed (check git history for fix commits)
1022
+ - Verification Pending tickets whose fix has been exercised repeatedly without regression (the "Problem 048: manage-problem does not surface Fix Released problems as verification candidates when the fix path has been exercised" problem detection layer — candidate for closure verification)
1023
+
1024
+ **When the operation is `work` (not just `review`), select the problem to work using `request_user_input`:**
1025
+
1026
+ - If one problem has a strictly higher WSJF than all others, present it as the recommended option:
1027
+ - Option 1: `Work P<NNN>: <title> (Recommended)` — with description showing WSJF score and status
1028
+ - Option 2: `Pick a different problem` — let the user name a specific ID
1029
+ - If two or more problems tie for the highest WSJF, present the tied problems as options:
1030
+ - One option per tied problem: `Work P<NNN>: <title>` — with description showing WSJF and a one-line rationale for why this one
1031
+ - Final option: `Pick a different problem`
1032
+ - Use `header: "Next problem"` and `multiSelect: false`
1033
+
1034
+ **Never present the selection as prose "(a)/(b)/(c)" or "which would you like?"** — always use `request_user_input` so the decision is structured and auditable.
1035
+
1036
+ **Step 9d: Check for pending verifications**
1037
+
1038
+ Target `docs/problems/*.verifying.md` via glob — 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). For each `.verifying.md` file, the agent collects in-session evidence per Step 4a's "Exercised successfully in-session" pattern (test invocation + observable outcome per the "Agent output grounding — no fabricated quantitative estimates, cite + persist + uncertainty" architecture rule grounding). When evidence-citation is concrete and unambiguous, the agent **closes the ticket on evidence** by delegating to `/wr-itil:transition-problem <NNN> close` (per the "Governance Skills Commit Their Own Completed Work" architecture rule commit grain) WITHOUT firing `request_user_input` — per the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule framework-resolution boundary, evidence-grounded close is a framework-mediated decision (the agent applies the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule's evidence semantics; per-candidate ask is sub-contracting that resolution back to the user as lazy deferral per Step 2d Ask Hygiene Pass classification).
1039
+
1040
+ When evidence is **ambiguous, contested, or absent** (no specific in-session citation), leave the ticket as Verification Pending — same exclusion path as Step 4a. The user surfaces concerns via the "Problem 078: Assistant does not offer to capture a problem ticket when the user delivers strong-signal correction" problem capture-on-correction surface (authentic-correction per the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule category 6) if a close-on-evidence action was wrong; closes are reversible via `/wr-itil:transition-problem <NNN> known-error` (the verifying-flip-back path used in the 2026-04-27 the "`/wr-itil:manage-problem` Step 2 substep 7 session-id discovery is brittle — agent has no env var, must scrape marker filenames" problem regression flip-back). The Step 9d output table records each close action with its triggering citation + the documented recovery path.
1041
+
1042
+ **Step 9e: Update files and refresh README.md cache**
1043
+
1044
+ 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.
1045
+
1046
+ **WSJF Rankings tier + tie-break sort (the "`docs/problems/README.md` WSJF Rankings table row order doesn't match `/wr-itil:work-problems`'s tie-break selection — users assume the orchestrator is broken" problem + the "Inbound-reported problems rank ahead of internally-discovered problems via a sort tier" architecture rule)**: 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 (the "Inbound-reported problems rank ahead of internally-discovered problems via a sort tier" architecture rule) --> <!-- 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 the "Problem 094: `/wr-itil:manage-problem` does not refresh `docs/problems/README.md` on ticket creation" problem block, the Step 7 the "Problem 062: `manage-problem` does not refresh `docs/problems/README.md` on single-ticket transitions; fast-path cache goes stale silently" problem block, AND `/wr-itil:review-problems` SKILL.md Step 3 / Step 5 — drift here re-opens the "`docs/problems/README.md` WSJF Rankings table row order doesn't match `/wr-itil:work-problems`'s tie-break selection — users assume the orchestrator is broken" problem / the "Inbound-reported problems rank ahead of internally-discovered problems via a sort tier" architecture rule.
1047
+
1048
+ ```markdown
1049
+ # Problem Backlog
1050
+
1051
+ > Last reviewed: <ISO timestamp>
1052
+ > Run `/wr-itil:manage-problem review` to refresh.
1053
+
1054
+ ## WSJF Rankings
1055
+
1056
+ | WSJF | ID | Title | Severity | Status | Effort | Reported | Origin |
1057
+ |------|-----|-------|----------|--------|--------|----------|--------|
1058
+ | <score> | P<NNN> | <title> | <severity> | <status> | <effort> | <YYYY-MM-DD> | <internal / inbound-reported (#NN)> |
1059
+ ...
1060
+
1061
+ ## Verification Queue
1062
+
1063
+ Fix released, awaiting user verification (driven off `docs/problems/*.verifying.md` via glob — per the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule). Sorted by `Released date ASC` (oldest at row 1; same-day releases tiebreak by ID ASC). <!-- VQ-SORT-DIRECTION: oldest-first per the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule --> Drift here re-opens the "docs/problems/README.md Verification Queue rendered newest-first contradicts section header "Ranked by release age, oldest first"" problem — any change to VQ sort direction MUST update the Step 5 the "Problem 094: `/wr-itil:manage-problem` does not refresh `docs/problems/README.md` on ticket creation" problem block, the Step 7 the "Problem 062: `manage-problem` does not refresh `docs/problems/README.md` on single-ticket transitions; fast-path cache goes stale silently" problem block, the Step 9c presentation block, this template, AND `/wr-itil:review-problems` + `/wr-itil:transition-problem` + `/wr-itil:transition-problems` + `/wr-itil:reconcile-readme` + `/wr-itil:list-problems`. The `Likely verified?` column carries an **evidence-first** cell per 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 — three canonical values: `yes — observed: <evidence>`, `no — not observed` (default for newly-released tickets), `no — observed regression`. <!-- LIKELY-VERIFIED-CELL-SHAPE: evidence-based per 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 --> Age is preserved separately via the `Released` column — drift on the cell shape re-opens 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.
1064
+
1065
+ | ID | Title | Released | Fix summary | Likely verified? |
1066
+ |----|-------|----------|-------------|------------------|
1067
+ | P<NNN> | <title> | <release marker> | <one-sentence fix summary> | <yes — observed: … / no — not observed / no — observed regression> |
1068
+ ...
1069
+
1070
+ ## Parked
1071
+
1072
+ | ID | Title | Reason | Parked since |
1073
+ |----|-------|--------|-------------|
1074
+ | P<NNN> | <title> | <reason> | <date> |
1075
+ ...
1076
+ ```
1077
+
1078
+ Then commit all changed files per the "Governance Skills Commit Their Own Completed Work" architecture rule:
1079
+ 1. `git add` the changed problem files and `docs/problems/README.md`
1080
+ 2. Satisfy the commit gate — two paths are valid (either produces a bypass marker):
1081
+ - **Primary**: delegate to the `wr-risk-scorer:pipeline` subagent-type via the native Codex subagent tool
1082
+ - **Fallback**: if the `wr-risk-scorer:pipeline` subagent-type is not available in the current tool set (e.g., this skill is itself running inside a spawned subagent), invoke the `/wr-risk-scorer:assess-release` skill via the installed skill invocation. Per the "On-Demand Assessment Skills for Governance Plugins" architecture rule it wraps the same pipeline subagent and produces an equivalent bypass marker via the `PostToolUse:Agent` hook. Do not silently skip the gate because the primary path is unavailable — the fallback exists specifically to close this gap (see the "Problem 035: manage-problem commit gate has no fallback when subagent delegation is unavailable" problem).
1083
+ 3. `git commit -m "docs(problems): review — re-rank priorities"`
1084
+
1085
+ If `request_user_input` is unavailable and risk is above appetite, skip the commit and report the uncommitted state (the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6 fail-safe). This applies only to the risk-above-appetite branch, not to the delegation-unavailable case above.
1086
+
1087
+ ### 10. Quality checks
1088
+
1089
+ After creating or updating a problem file, verify:
1090
+
1091
+ - **ID uniqueness**: No duplicate IDs in `docs/problems/`
1092
+ - **Naming convention**: File matches `<NNN>-<kebab-case>.<status>.md`
1093
+ - **Required sections**: Description, Impact Assessment, and Investigation Tasks exist
1094
+ - **Priority calculation**: Score = Impact × Likelihood, label matches score
1095
+ - **No orphaned references**: If the problem references other problems by number, verify those files exist
1096
+ - **Status consistency**: The Status field in the frontmatter matches the filename suffix
1097
+
1098
+ **Priority label mapping**: Read the label bands from `RISK-POLICY.md` — do not hardcode them here.
1099
+
1100
+ ### 11. Report
1101
+
1102
+ After any operation, report:
1103
+ - The file path created/modified
1104
+ - The problem ID and title
1105
+ - The current status
1106
+ - Any quality check warnings
1107
+
1108
+ Commit the completed work per the "Governance Skills Commit Their Own Completed Work" architecture rule (governance skills commit their own work):
1109
+ 1. `git add` all created/modified files for this operation — **including any file renamed via `git mv` that was then modified by the `Edit` tool** (the "Problem 057: `git mv` + Edit + `git add` staging-ordering trap drops content edits from the commit" problem staging trap — `git mv` alone stages only the rename, not the subsequent content edit). `git add -u` is a safe catch-all for tracked modifications. **For any Step 7 status transition** (Open → Known Error, Known Error → Verification Pending, Verification Pending → Closed, or Parked) — including folded-fix commits where the `.verifying.md` transition rides with a `fix(<scope>): ...` commit — the stage list MUST include `docs/problems/README.md` refreshed per Step 7's "README.md refresh on every transition" block (the "Problem 062: `manage-problem` does not refresh `docs/problems/README.md` on single-ticket transitions; fast-path cache goes stale silently" problem). Skipping the refresh leaks staleness to the next session's fast-path. **For any Step 5 new-ticket creation** (single or multi-concern split) and for any Step 6 update that changed Priority / Effort / WSJF, the stage list MUST include `docs/problems/README.md` refreshed per the "Problem 094: `/wr-itil:manage-problem` does not refresh `docs/problems/README.md` on ticket creation" problem blocks in those steps. Creation-path and ranking-change-update-path refreshes are treated identically to Step 7 transitions — single-commit transaction, README alongside the ticket.
1110
+ 2. Satisfy the commit gate — two paths are valid (either produces a bypass marker):
1111
+ - **Primary**: delegate to the `wr-risk-scorer:pipeline` subagent-type via the native Codex subagent tool (subagent_type: `wr-risk-scorer:pipeline`)
1112
+ - **Fallback**: if the `wr-risk-scorer:pipeline` subagent-type is not available in the current tool set (e.g., this skill is itself running inside a spawned subagent), invoke the `/wr-risk-scorer:assess-release` skill via the installed skill invocation. Per the "On-Demand Assessment Skills for Governance Plugins" architecture rule it wraps the same pipeline subagent and the `PostToolUse:Agent` hook writes an equivalent bypass marker. Do not silently skip the gate because the primary path is unavailable — the fallback exists specifically to close this gap (see the "Problem 035: manage-problem commit gate has no fallback when subagent delegation is unavailable" problem).
1113
+ 3. Land the commit via the **`wr-risk-scorer-restage-commit`** helper — atomic re-stage + commit in a single bash call (the "Staged index is cleared after a `wr-risk-scorer:pipeline` Agent delegation — forces a re-`git add` before the commit lands" problem wrapper):
1114
+ ```bash
1115
+ wr-risk-scorer-restage-commit -m "<message>" -- <path1> [<path2>...]
1116
+ ```
1117
+ The native-Codex-subagent-tool delegation in step 2 can silently clear the parent index — a subsequent bare `git commit` then fails with `Changes not staged for commit`. The helper re-adds the supplied paths, asserts the cached diff is non-empty, then runs `git commit "${msg_args[@]}"` — eliminating the silent re-add round-trip the "Staged index is cleared after a `wr-risk-scorer:pipeline` Agent delegation — forces a re-`git add` before the commit lands" problem documents. Pass repeated `-m` flags for trailer paragraphs (e.g. `RISK_BYPASS:` allow-list tokens).
1118
+ 4. Message conventions per operation type:
1119
+ - New problem: `docs(problems): open P<NNN> <title>`
1120
+ - Known Error transition: `docs(problems): P<NNN> known error — <root cause summary>`
1121
+ - Verification Pending transition: usually folded into the `fix(<scope>): ... (closes P<NNN>)` commit that ships the fix — the `git mv` to `.verifying.md` and the `## Fix Released` section land together. If transitioning without a fix commit, use `docs(problems): P<NNN> verification pending — <release marker>`.
1122
+ - Problem closed: `docs(problems): close P<NNN> <title>`
1123
+ - Review/re-rank: `docs(problems): review — re-rank priorities`
1124
+ - Fix implemented: `fix(<scope>): <description> (closes P<NNN>)` — include problem file changes (rename to `.verifying.md` + `## Fix Released` section) in the same commit per the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule
1125
+ 5. If commit risk is above appetite: auto-apply scorer remediations per **the "Auto-apply scorer remediations to reach within appetite — open action-class vocabulary" architecture rule Rule 1** incrementally until residual commit risk is within appetite (≤ 4/25), OR halt per the "Auto-apply scorer remediations to reach within appetite — open action-class vocabulary" architecture rule Rule 5 if the scorer cannot converge. **The skill MUST NOT commit above appetite, and MUST NOT call `request_user_input` to ask whether to commit anyway** (the "Skills, agents, and hooks override RISK-POLICY appetite instead of applying it" problem/the ": Apply RISK-POLICY appetite faithfully across all surfaces" release design amendment 2026-06-24 — above-appetite is framework-mediated, never a category-3 one-time-override; same invariant the push/release branch at Step 12 already enforces). The "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6 fail-safe (no `request_user_input` available / non-interactive → skip the commit and report the uncommitted state) remains the terminal fallback. This applies only to the risk-above-appetite branch, not to the delegation-unavailable case above.
1126
+
1127
+ **Multi-commit slice changeset discipline (the "AFK iter `packages/<plugin>/` commits without changesets — orchestrator-main-turn back-fill is fragile recovery, hook-level enforcement preferable" problem Phase 2)**: when a single logical fix lands across multiple the "Governance Skills Commit Their Own Completed Work" architecture rule-grain commits targeting the same plugin (e.g. helper extraction in commit 1, callers wired in commit 2, SKILL note + transition in commit 3 — all `packages/<plugin>/`), author ONE changeset on the first commit in the slice. Subsequent same-plugin commits do NOT need their own changeset — the `itil-changeset-discipline.sh` hook's Check 2b recognises any `.changeset/*.md` already in the unpushed slice scope (`origin/<base>..HEAD` + untracked + modified-not-staged) that targets `"@windyroad/<plugin>": <any-bump>` and allows. This eliminates the per-commit changeset ceremony that previously produced N redundant `.changeset/*.md` files for one logical release entry (changesets-action collapses bump-class at version-package time, so per-commit changesets rendered N near-identical CHANGELOG bullets for one release). Once a changeset hits `origin/<base>` (drained at release time), it no longer counts — a fresh changeset is required for the next slice. Cross-plugin coverage is NOT permitted: an `@windyroad/itil` changeset does not satisfy a `packages/voice-tone/` commit.
1128
+
1129
+ ### 12. Auto-release when changesets are queued (the "Governance skills auto-release when changesets are queued" architecture rule)
1130
+
1131
+ **Skip this step if the skill is running inside an AFK orchestrator** (e.g. `/wr-itil:work-problems`). Orchestrators handle release cadence themselves per the "Inter-iteration release cadence for AFK loops" architecture rule (Step 6.5). Detect via the presence of an orchestrator marker in the invoking prompt — look for phrases like "AFK", "work-problems", "batch-work", or the sentinel `ALL_DONE` convention. When in doubt, defer to the orchestrator by skipping this step.
1132
+
1133
+ Otherwise, after the commit in step 11 lands, drain the release queue so the fix actually lands on npm without requiring manual user action.
1134
+
1135
+ **Mechanism — delegate, do not re-implement scoring (per the "On-Demand Assessment Skills for Governance Plugins" architecture rule):**
1136
+
1137
+ 1. Invoke the release scorer. Two paths are valid:
1138
+ - **Primary**: delegate to subagent type `wr-risk-scorer:pipeline` via the native Codex subagent tool.
1139
+ - **Fallback**: if that subagent type is not available, invoke skill `/wr-risk-scorer:assess-release` via the installed skill invocation. The skill wraps the same pipeline subagent.
1140
+ 2. Read the returned `RISK_SCORES: commit=X push=Y release=Z` line.
1141
+ 3. **Drain condition**: if `push` and `release` are both within appetite (≤ 4/25, "Low" band per `RISK-POLICY.md`), AND `.changeset/` is non-empty, proceed to the drain action. Otherwise, skip the drain and report the unreleased state.
1142
+
1143
+ **Drain action (non-interactive, policy-authorised per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6):**
1144
+
1145
+ 1. Run `npm run push:watch` (push + wait for CI to pass).
1146
+ 2. If `.changeset/` remains non-empty after push (i.e. a release PR is pending), run `npm run release:watch` (merge the release PR + wait for npm publish).
1147
+ 3. Report the release: "Released <package>@<version>. Fix is now live on npm."
1148
+
1149
+ **Failure handling**: If `release:watch` fails (CI failure, publish failure), stop and report the failure clearly. Do not retry non-interactively — the user must intervene.
1150
+
1151
+ **Above-appetite branch (per the "Auto-apply scorer remediations to reach within appetite — open action-class vocabulary" architecture rule)**: If push or release risk is above appetite (≥ 5/25), the skill MUST auto-apply scorer remediations incrementally until residual risk converges within appetite, OR halt the skill per the "Auto-apply scorer remediations to reach within appetite — open action-class vocabulary" architecture rule Rule 5 if the scorer cannot produce a convergent plan. **The skill MUST NOT release above appetite under any circumstance.** The skill MUST NOT call `request_user_input` as a shortcut out of the auto-apply loop.
1152
+
1153
+ **Auto-apply mechanism (the "Auto-apply scorer remediations to reach within appetite — open action-class vocabulary" architecture rule Rule 2):**
1154
+
1155
+ 1. Parse the scorer's `RISK_REMEDIATIONS:` block. Expected shape per the "On-Demand Assessment Skills for Governance Plugins" architecture rule / the "Auto-apply scorer remediations to reach within appetite — open action-class vocabulary" architecture rule Rule 2a (5 columns):
1156
+ ```
1157
+ RISK_REMEDIATIONS:
1158
+ - R1 | <description> | <effort S/M/L> | <risk_delta -N> | <files affected>
1159
+ - R2 | ...
1160
+ ```
1161
+ 2. Read the descriptions. Decide what to do. The agent MAY follow a scorer suggestion, adapt it, or do something else entirely. There is no requirement to rank all suggestions upfront or iterate through them in order.
1162
+ 3. **Verification Pending carve-out (the "Auto-apply scorer remediations to reach within appetite — open action-class vocabulary" architecture rule Rule 2b)**: skip remediations that target a commit attached to a `.verifying.md` ticket. Do NOT auto-revert VP commits.
1163
+ 4. Apply the chosen action using standard primitives (git, Edit, Bash). Example actions:
1164
+ - `revert-commit`: `git revert --no-edit <sha>`. The scorer SHOULD supply the target commit SHA in the `description` column. Before executing, verify the SHA is NOT attached to a `.verifying.md` ticket (Rule 2b carve-out). After revert, commit the revert as a standalone auto-apply commit (no amend folding in non-AFK mode). If `git revert` produces merge conflicts, route to Rule 5 halt with the conflict detail.
1165
+ - `split-change`: split the work into independently releasable, within-appetite commits and re-score each slice.
1166
+ - `disable-or-revert`: remove the risky behaviour from shipped code until its required evidence or control exists.
1167
+ 5. Re-score via the same delegation path as step 1 above.
1168
+ 6. **Loop**: re-score within appetite → drain per the Drain action above. Re-score still above → continue working to reduce risk. The agent reads the new remediations and decides what to do next. Loop. Exhausted or unsupported class → Rule 5 halt.
1169
+
1170
+ **Rule 5 halt (non-AFK mode)**: halt the skill. Emit the terminal report naming:
1171
+ - The final `RISK_SCORES:` line
1172
+ - An "Auto-apply trail" subsection listing each remediation attempted with outcome
1173
+ - Any Verification Pending ticket IDs implicated per Rule 2b
1174
+ - A one-line scorer-gap note (e.g., "available remediations did not reduce residual risk below 5/25 — extend scorer vocabulary per the "Scorer `RISK_REMEDIATIONS:` block is free-form prose — agent must parse descriptions to decide what to do" problem")
1175
+
1176
+ The user resolves interactively — typical resolutions include splitting the commit, feature-flagging the change, or opening a problem ticket documenting the scorer gap.
1177
+
1178
+ `push:watch` and `release:watch` are policy-authorised actions when residual risk is within appetite per RISK-POLICY.md, so no `request_user_input` is required for the drain itself (the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 5). Auto-apply actions under Rules 2–7 are also policy-authorised per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 5 — `RISK-POLICY.md` appetite + the "Auto-apply scorer remediations to reach within appetite — open action-class vocabulary" architecture rule eligibility constitute the policy.
1179
+
1180
+ $ARGUMENTS