@windyroad/itil 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -497,5 +497,5 @@
497
497
  }
498
498
  },
499
499
  "name": "wr-itil",
500
- "version": "2.0.0"
500
+ "version": "2.1.0"
501
501
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wr-itil",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "ITIL problem-management workflows for AI coding agents",
5
5
  "author": {
6
6
  "name": "Windy Road Technology",
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env bash
2
+ # Generated by scripts/sync-shim-wrappers.sh from
3
+ # packages/shared/lib/shim-wrapper-template.sh. DO NOT EDIT individual
4
+ # shim files in packages/*/bin/wr-* directly; edit the template + run
5
+ # `npm run sync:shim-wrappers` to regenerate.
6
+ #
7
+ # Resolution (highest-version-wins-shim-wrapper-for-plugin-scaffold-template-shims-architecture-rule):
8
+ # 1. If the wrapper's parent dir is semver-shaped, treat as installed-
9
+ # cache execution and resolve to the highest-version sibling's
10
+ # scripts/ entry below.
11
+ # 2. Otherwise (parent dir is e.g. `architect`), treat as source-
12
+ # monorepo execution and dispatch to own scripts/. The source-repo-
13
+ # guard `exec` is the anchor parsed by
14
+ # packages/retrospective/scripts/check-tarball-shipped-shims.sh.
15
+ # 3. If the cache parent contains zero semver-shaped siblings, exit
16
+ # 127 with a stderr message naming the cache parent (per SQ-080-2).
17
+ #
18
+ # @adr highest-version-wins-shim-wrapper-for-plugin-scaffold-template-shims-architecture-rule (highest-version-wins shim wrapper plugin scaffold)
19
+ # @adr plugin-bundled-scripts-invoked-from-skill-md-resolve-via-bin-on-path-architecture-rule (plugin-bundled scripts resolve via bin/ on $PATH — amended)
20
+ # @problem install-updates-refreshes-the-global-plugin-cache-but-does-not-fix-path-ordering-stale-plugin-version-shims-stay-first-on-path-so-subsequent-shim-invocations-run-old-code-problem (mid-session staleness window)
21
+
22
+ set -euo pipefail
23
+
24
+ SHIM_DIR="$(cd "$(dirname "$0")" && pwd)"
25
+ OWN_VERSION_DIR="$(dirname "$SHIM_DIR")"
26
+ OWN_VERSION_NAME="$(basename "$OWN_VERSION_DIR")"
27
+ CACHE_PARENT="$(dirname "$OWN_VERSION_DIR")"
28
+
29
+ SEMVER_RE='^[0-9]+\.[0-9]+\.[0-9]+([-+][0-9A-Za-z.-]+)?$'
30
+
31
+ # Source-repo guard: own parent dir is NOT semver → dispatch to own scripts/.
32
+ if ! [[ "$OWN_VERSION_NAME" =~ $SEMVER_RE ]]; then
33
+ exec "$SHIM_DIR/../scripts/is-close-blocked.sh" "$@"
34
+ fi
35
+
36
+ # Cache execution: pick the highest-semver sibling under CACHE_PARENT.
37
+ HIGHEST=""
38
+ while IFS= read -r dir; do
39
+ name="$(basename "$dir")"
40
+ [[ "$name" =~ $SEMVER_RE ]] || continue
41
+ if [[ -z "$HIGHEST" ]] || [[ "$(printf '%s\n%s\n' "$HIGHEST" "$name" | sort -V | tail -1)" == "$name" ]]; then
42
+ HIGHEST="$name"
43
+ fi
44
+ done < <(find "$CACHE_PARENT" -mindepth 1 -maxdepth 1 -type d 2>/dev/null)
45
+
46
+ if [[ -z "$HIGHEST" ]]; then
47
+ printf 'wr-shim: no cached versions in %s\n' "$CACHE_PARENT" >&2
48
+ exit 127
49
+ fi
50
+
51
+ exec "$CACHE_PARENT/$HIGHEST/scripts/is-close-blocked.sh" "$@"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@windyroad/itil",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "ITIL-aligned IT service management for Claude Code and Codex",
5
5
  "bin": {
6
6
  "windyroad-itil": "./bin/install.mjs"
@@ -0,0 +1,93 @@
1
+ #!/usr/bin/env bash
2
+ # wr-itil — predicate: is a ticket's closure explicitly blocked? (the-verification-pending-closed-transition-is-reserved-for-the-maintainer-so-evidence-based-closure-never-fires-and-the-verification-queue-grows-without-bound-problem)
3
+ #
4
+ # Sibling of packages/architect/scripts/is-decision-unconfirmed.sh: answers ONE
5
+ # question for ONE ticket via its EXIT CODE, for the Verification Pending ->
6
+ # Closed guard in /wr-itil:transition-problem, /wr-itil:transition-problems,
7
+ # /wr-itil:manage-problem and /wr-itil:work-problems.
8
+ #
9
+ # Evidence-backed closure is agent-authorised (the-verification-pending-closed-transition-is-reserved-for-the-maintainer-so-evidence-based-closure-never-fires-and-the-verification-queue-grows-without-bound-problem). This predicate is the
10
+ # machine-checkable half of the carve-out that keeps genuine ambiguity on the
11
+ # maintainer's surface: a ticket carrying an explicit DO-NOT-CLOSE marker keeps
12
+ # blocking closure even when the evidence would otherwise satisfy the ticket's
13
+ # own close criterion. Making the marker a field read rather than prose the
14
+ # next agent must happen to notice is what stops the carve-out eroding.
15
+ #
16
+ # Marker shape (LINE-ANCHORED, 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 advisory-A2 lesson): the literal
17
+ # uppercase `DO NOT CLOSE` in a markdown heading line, or in a bold/bullet
18
+ # marker line. A mention inside a fenced code block or mid-prose is NOT a
19
+ # marker — that is how tickets *discuss* the mechanism, and treating discussion
20
+ # as a block would re-strand the queue this predicate exists to let drain.
21
+ #
22
+ # Usage:
23
+ # is-close-blocked.sh <ticket-ref> [PROBLEMS_DIR]
24
+ # <ticket-ref> = P<NNN> | <NNN> | path/to/<NNN>-title.md
25
+ # PROBLEMS_DIR defaults to docs/problems
26
+ #
27
+ # Exit codes:
28
+ # 0 = BLOCKED — marker present. Prints the matching line on stdout.
29
+ # 1 = not blocked. No stdout.
30
+ # 2 = ticket not found / unreadable ref. No stdout; reason on stderr.
31
+ #
32
+ # @adr plugin-bundled-scripts-invoked-from-skill-md-resolve-via-bin-on-path-architecture-rule (bin/ on PATH shim — adopter-safe script resolution)
33
+ # @adr problem-lifecycle-add-a-verification-pending-status-between-known-error-and-closed-architecture-rule (Verifying lifecycle — the V->C transition this guards)
34
+ # @adr decision-delegation-contract-when-agents-act-on-the-framework-vs-ask-the-user-architecture-rule (framework-resolution boundary — the marker is the recorded
35
+ # signal that routes a close back to the user's surface)
36
+ # @adr agent-output-grounding-no-fabricated-quantitative-estimates-cite-persist-uncertainty-architecture-rule (agent output grounding)
37
+ # @problem the-verification-pending-closed-transition-is-reserved-for-the-maintainer-so-evidence-based-closure-never-fires-and-the-verification-queue-grows-without-bound-problem (evidence-backed closure is agent-authorised; ambiguity is not)
38
+
39
+ set -uo pipefail
40
+
41
+ REF="${1:-}"
42
+ PROBLEMS_DIR="${2:-docs/problems}"
43
+
44
+ if [ -z "$REF" ]; then
45
+ echo "is-close-blocked: missing <ticket-ref>" >&2
46
+ echo "usage: is-close-blocked.sh <ticket-ref> [PROBLEMS_DIR]" >&2
47
+ exit 2
48
+ fi
49
+
50
+ # --- Resolve the ticket file -----------------------------------------------
51
+ file=""
52
+ if [ -f "$REF" ]; then
53
+ file="$REF"
54
+ else
55
+ id="${REF#[Pp]}"
56
+ # Zero-pad a bare number to the three-digit ticket convention.
57
+ case "$id" in
58
+ ''|*[!0-9]*) : ;;
59
+ *) id="$(printf '%03d' "$((10#$id))")" ;;
60
+ esac
61
+ # Dual-tolerant per docs-problems-flat-layout-migration-per-state-subdirs-adopter-auto-migration-release-design: per-state subdirs AND the flat legacy layout.
62
+ for cand in \
63
+ "$PROBLEMS_DIR"/*/"$id"-*.md \
64
+ "$PROBLEMS_DIR"/"$id"-*.md
65
+ do
66
+ [ -f "$cand" ] || continue
67
+ file="$cand"
68
+ break
69
+ done
70
+ fi
71
+
72
+ if [ -z "$file" ] || [ ! -r "$file" ]; then
73
+ echo "is-close-blocked: no readable ticket for ref '$REF' under '$PROBLEMS_DIR'" >&2
74
+ exit 2
75
+ fi
76
+
77
+ # --- Scan for the marker, skipping fenced code blocks ----------------------
78
+ match="$(awk '
79
+ # Toggle fence state on ``` or ~~~ openers/closers.
80
+ /^[[:space:]]*(```|~~~)/ { fenced = !fenced; next }
81
+ fenced { next }
82
+ # Line-anchored: a heading, or a bold/bullet marker line.
83
+ /^[[:space:]]*(#{1,6}[[:space:]]|[-*+][[:space:]]|\*\*)/ {
84
+ if (index($0, "DO NOT CLOSE") > 0) { print; exit }
85
+ }
86
+ ' "$file")"
87
+
88
+ if [ -n "$match" ]; then
89
+ printf '%s\n' "$match"
90
+ exit 0
91
+ fi
92
+
93
+ exit 1
@@ -43,10 +43,11 @@ The preamble check is a one-shot; the `.intake-scaffold-done` and `.intake-scaff
43
43
  - **Work**: `problem work` — runs a review first, then begins working the highest-WSJF problem
44
44
  - **Review**: `problem review` — re-assess all open problems: update priorities per RISK-POLICY.md, estimate effort, calculate WSJF, and update files
45
45
 
46
- **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):
47
- 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.
48
- 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: AskUserQuestion Unavailable When --channels Is Active" problem").
49
- 3. Never assume the fix worksalways wait for explicit user confirmation before closing.
46
+ **Closing problems:** Problems are closed when the fix is **verified** — not when it is committed or released. Verification comes from cited evidence or from the user; it never comes from assuming. The workflow (per the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule, amended by the "The Verification Pending → Closed transition is reserved for the maintainer, so evidence-based closure never fires and the verification queue grows without bound" problem):
47
+ 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 verification.`). All three edits land in the same commit per the "Governance Skills Commit Their Own Completed Work" architecture rule.
48
+ 2. When the fix is **verified** — either by cited evidence the agent can point at (a test invocation and its outcome, a commit SHA whose diff covers the fix path, a skill or hook invocation that exercised the fix and behaved as the fix contracts, a post-release invocation of the shipped artefact that behaved as the fix contracts, or an existing `yes — observed: <citation>` Verification Queue cell) **or** by the user explicitly confirming ("it's fixed", "verified", "working"): `git mv` from `.verifying.md` to `.closed.md`, update the Status field to "Closed", record the citation in the closure, and reference the problem in the commit message (e.g., "Closes the "Problem 008: AskUserQuestion Unavailable When --channels Is Active" problem"). **Evidence-backed closure is agent-authorised** and is a mechanical stage — do NOT fire `AskUserQuestion` for it (the "Agents over-ask in interactive sessions — conflating mechanical-stages with user-interactive-stages of multi-stage skill contracts (inverse-)" problem / the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule category 4). It is cheap and reversible: report `Recovery: rerun /wr-itil:transition-problem <NNN> known-error to reopen` alongside every close.
49
+ 3. **Never close on inference — absence of evidence is not evidence.** A ticket nobody exercised stays Verification Pending, however old and however plausible the fix looks. "The fix is on disk", "it has been months" and "the ADR that prescribed it shipped" are inference, not observation (the "Relevance-close evaluator over-fires a bare ADR/skill citation is read as "fix shipped", so live tickets return CLOSE-CANDIDATE" problem). Closing tickets nobody exercised is the opposite failure and is exactly as wrong as never closing any.
50
+ 4. **Genuine ambiguity is the user's surface** — contested evidence, a fix covering only part of the ticket, or a recorded do-not-close marker. Run `wr-itil-is-close-blocked <NNN> docs/problems` before closing; exit 0 means BLOCKED (do not close, whatever the evidence says — flip back or queue for the user), exit 1 means not blocked, exit 2 means the ref did not resolve and is a pre-flight failure rather than permission.
50
51
 
51
52
  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.
52
53
 
@@ -56,9 +57,9 @@ The `.verifying.md` suffix distinguishes "fix released, awaiting user verificati
56
57
  |--------|-----------|---------|----------------|
57
58
  | **Open** | `.open.md` | Reported, under investigation | New problem identified |
58
59
  | **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 |
59
- | **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 |
60
+ | **Verification Pending** | `.verifying.md` | Fix released, awaiting verification (the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule) | Fix shipped; `## Fix Released` section written; verification outstanding by cited evidence or by the user |
60
61
  | **Parked** | `.parked.md` | Blocked on upstream or suspended by user decision | Upstream blocker identified, or user explicitly suspends; reason and un-park trigger documented |
61
- | **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 `AskUserQuestion` surface-batch-confirm path. |
62
+ | **Closed** | `.closed.md` | Fix verified in production OR ticket determined no longer relevant via evidence | (a) The released fix is verified — either by cited evidence meeting the ticket's own close criterion (agent-authorised, mechanical, no `AskUserQuestion`; blocked when `wr-itil-is-close-blocked` exits 0) or by the user explicitly confirming (canonical Verifying → Closed path; the "The Verification Pending → Closed transition is reserved for the maintainer, so evidence-based closure never fires and the verification queue grows without bound" problem), 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 `AskUserQuestion` surface-batch-confirm path. |
62
63
 
63
64
  **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:
64
65
  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.
@@ -68,7 +69,7 @@ The `.verifying.md` suffix distinguishes "fix released, awaiting user verificati
68
69
 
69
70
  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.
70
71
 
71
- **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.
72
+ **Verification Pending problems** are also excluded from WSJF ranking — their remaining work is verification — by evidence or by the user, 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.
72
73
 
73
74
  **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.
74
75
 
@@ -833,11 +834,26 @@ Then edit the file:
833
834
 
834
835
  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).
835
836
 
836
- 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.
837
+ 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 verification — by evidence or by the user — no file-body scan needed.
837
838
 
838
- **Verification Pending → Closed** (user confirms):
839
+ **Verification Pending → Closed** (verified — by evidence or by the user):
839
840
 
840
- Only the user can make this call. When they explicitly confirm the fix works in production:
841
+ **Sibling-with `/wr-itil:transition-problem` Step 4** per the "Rename `wr-problem` Plugin to `wr-itil`" architecture rule amended the "Problem 093: `/wr-itil:transition-problem` ↔ `/wr-itil:manage-problem` circular delegation for `<NNN> <status>` args" problem (copy-not-move — edit both or neither; drift here is the class the "The Verification Pending → Closed transition is reserved for the maintainer, so evidence-based closure never fires and the verification queue grows without bound" problem fixed). Two admissible triggers:
842
+
843
+ - **Cited evidence** meeting the ticket's own stated close criterion — a test invocation and its outcome, a commit SHA whose diff covers the fix path, a skill or hook invocation that exercised the fix and behaved as the fix contracts, a post-release invocation of the shipped artefact that behaved as the fix contracts, or an existing `yes — observed: <citation>` Verification Queue cell. The agent closes on its own authority and records the citation in the closure. **Mechanical stage — do NOT fire `AskUserQuestion`** (the "Agents over-ask in interactive sessions — conflating mechanical-stages with user-interactive-stages of multi-stage skill contracts (inverse-)" problem / the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule category 4). Report `Recovery: rerun /wr-itil:transition-problem <NNN> known-error to reopen`.
844
+
845
+ **Evidence-authorised tracker updates.** Write the basis into the ticket's `**Status**:` line alongside the citation (`**Status**: Closed (closed-on-evidence <YYYY-MM-DD> — <citation>. Recovery: rerun /wr-itil:transition-problem <NNN> known-error to reopen)`). A provenance-proven GitHub issue on this project's tracker receives the gated comment and closes; an unresolved or non-issue inbound origin performs no issue mutation. An issue on another maintainer's tracker receives the comment but stays open on our evidence alone; that upstream party's confirmation may authorize closure. Pull requests remain comment-only.
846
+ - **Explicit user confirmation** that the fix works in production.
847
+
848
+ **Never close on inference** — absence of evidence is not evidence; a ticket nobody exercised stays Verification Pending. **Do-not-close guard**, before either trigger:
849
+
850
+ ```bash
851
+ wr-itil-is-close-blocked <NNN> docs/problems && close_blocked=1
852
+ ```
853
+
854
+ Exit 0 → BLOCKED; do not close whatever the evidence says (flip back to `known-error` or queue for the user). Exit 1 → not blocked. Exit 2 → the ref did not resolve; a pre-flight failure, not permission.
855
+
856
+ When one of the two triggers holds and the guard is clear:
841
857
 
842
858
  ```bash
843
859
  git mv docs/problems/verifying/<NNN>-<title>.md docs/problems/closed/<NNN>-<title>.md
@@ -845,7 +861,14 @@ git mv docs/problems/verifying/<NNN>-<title>.md docs/problems/closed/<NNN>-<titl
845
861
  git add docs/problems/closed/<NNN>-<title>.md
846
862
  ```
847
863
 
848
- Update the "Status" field to "Closed". Reference the problem ID in the closure commit message (e.g., "Closes the "Problem 008: AskUserQuestion 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).
864
+ **Write the close's authority basis into the Status field.** The Status line is the only place the basis survives the `Likely verified?` cell lives in the README's Verification Queue table, and that row is deleted by this very transition, so a downstream reader (Step 7b's upstream leg) would find nothing there. Shape, matching what the 2026-07-15 closes already wrote (`docs/problems/closed/186-*.md:3`):
865
+
866
+ - Evidence-authorised: `**Status**: Closed (closed-on-evidence <YYYY-MM-DD> — <citation>. Recovery: rerun /wr-itil:transition-problem <NNN> known-error to reopen)`
867
+ - User-confirmed: `**Status**: Closed (user-confirmed <YYYY-MM-DD>)`
868
+
869
+ `closed-on-evidence` is what the outbound leg reads to keep a foreign issue open on our evidence alone. The inbound leg uses committed issue-channel provenance instead: ambiguity fails closed before any issue operation.
870
+
871
+ Reference the problem ID in the closure commit message (e.g., "Closes the "Problem 008: AskUserQuestion 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).
849
872
 
850
873
  #### 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)
851
874
 
@@ -21,7 +21,7 @@ When referencing problem IDs, ADR IDs, JTBD IDs, or RFC IDs in prose output (the
21
21
  **In scope** (the ": docs/problems/ flat layout migration — per-state subdirs + adopter auto-migration" release design migration window — each glob is dual-tolerant, covering BOTH the flat `docs/problems/<NNN>-<title>.<state>.md` filename-suffix layout AND the per-state subdir `docs/problems/<state>/<NNN>-<title>.md` layout):
22
22
 
23
23
  - `docs/problems/*.open.md` + `docs/problems/open/*.md` and `docs/problems/*.known-error.md` + `docs/problems/known-error/*.md` — re-scored (Impact × Likelihood × Effort → WSJF); Priority + Effort + WSJF lines updated when they change.
24
- - `docs/problems/*.verifying.md` + `docs/problems/verifying/*.md` — surfaced in the Verification Queue and fed to Step 4's verification prompt (Known Error → Closed path when the user confirms).
24
+ - `docs/problems/*.verifying.md` + `docs/problems/verifying/*.md` — surfaced in the Verification Queue and fed to Step 4's verification routing (the Verification Pending → Closed path Bucket 1 closes on evidence, Bucket 2 asks, Bucket 3 flips back).
25
25
  - `docs/problems/*.parked.md` + `docs/problems/parked/*.md` — listed in the Parked section; NOT re-scored (WSJF multiplier is 0).
26
26
  - `docs/problems/README.md` — rewritten with the refreshed WSJF Rankings + Verification Queue + Parked tables; staged and committed with the review.
27
27
 
@@ -113,7 +113,7 @@ Omit an empty section rather than rendering an empty header.
113
113
 
114
114
  Target the dual-tolerant glob `docs/problems/*.verifying.md docs/problems/verifying/*.md` (the ": docs/problems/ flat layout migration — per-state subdirs + adopter auto-migration" release design migration window) — do NOT scan `.known-error.md` bodies for a `## Fix Released` section (per the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule, Verification Pending is a first-class status, not a substring marker). Bucket each verifying ticket by its Step-3 `Likely verified?` cell (the "VQ `Likely verified?` column uses age-based heuristic (≥14 days = yes) instead of session-observed evidence — sibling proxy-for-evidence anti-pattern to" problem evidence-first cell shape: `yes — observed: <evidence>` / `no — not observed` / `no — observed regression`) and route each bucket differently. **Do NOT fire one `AskUserQuestion` per ticket** — the evidence-backed subset closes on evidence; only the unobserved subset asks.
115
115
 
116
- **Bucket 1 — `yes — observed: <evidence>` → close-on-evidence (framework-mediated, silent agent action per the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule + the "Decision-delegation contract — agents over-apply Rule 1's interactive default to framework-resolved decisions; codify the framework-resolution boundary + AFK loop's batched-questions-as-deliverable + lazy-AskUserQuestion measurement" problem).** These rows carry the "Agent output grounding — no fabricated quantitative estimates, cite + persist + uncertainty" architecture rule-grounded cited evidence (a prior Step 4 user confirmation, an in-session test invocation + observable outcome, or a `run-retro` Step 4a close-on-evidence citation see the Step 3 cell definition). The framework has resolved this decision: a `.verifying.md` ticket with specific cited evidence IS verified per the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule's evidence semantics, so close it mechanically WITHOUT `AskUserQuestion` — mirroring the shipped `run-retro` Step 4a step 5 close-on-evidence. A per-candidate ask here is lazy deferral (sub-contracting a framework-resolved decision back to the user) per the Step 2d Ask Hygiene Pass. For each such ticket: close the problem (`git mv` from `.verifying.md` to `.closed.md`, update Status to "Closed", re-stage per the "Problem 057: `git mv` + Edit + `git add` staging-ordering trap drops content edits from the commit" problem staging trap) and update the `Likely verified?` cell to `yes — observed: closed-on-evidence <YYYY-MM-DD> — <citation>`. Report each closure in the review output with a documented reversible recovery path: `Recovery: rerun /wr-itil:transition-problem <NNN> known-error to reopen` closes are cheap and reversible; user disagreement surfaces via authentic-correction (the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule category 6), not a pre-close consent gate.
116
+ **Bucket 1 — `yes — observed: <evidence>` → close-on-evidence.** Specific observed evidence authorizes a mechanical close without asking again. First run `wr-itil-is-close-blocked <NNN> docs/problems`: exit 0 keeps the ticket open and reports the matched marker; exit 2 is a pre-flight failure; exit 1 proceeds. Move the ticket to `.closed.md`, re-stage it, and persist the authority in `**Status**: Closed (closed-on-evidence <YYYY-MM-DD> — <citation>. Recovery: rerun /wr-itil:transition-problem <NNN> known-error to reopen)`. A provenance-proven GitHub issue on this project's tracker receives the gated comment and closes; unresolved or non-issue inbound provenance performs no issue mutation. A foreign issue receives the comment but stays open on local evidence alone, while that upstream party's confirmation may authorize closure. Pull requests remain comment-only. Update the review cell with the same evidence citation and report the reversible recovery path.
117
117
 
118
118
  **Bucket 2 — `no — not observed` → ask (genuine user-authority).** No session-observable evidence yet, so the user may hold out-of-band production knowledge the agent cannot observe — this is the genuine user-input surface. Use `AskUserQuestion` to ask whether the fix has been verified in production. The question MUST include a fix summary extracted from the `## Fix Released` section — inline the first sentence (or first bullet list) of that section in the question body or option description per the brief-before-ID discipline, so the user can answer without reading the full problem file. Do NOT ask with only the problem ID + title + version.
119
119
  - If the user confirms: close the problem (`git mv` from `.verifying.md` to `.closed.md`, update Status to "Closed", re-stage per the "Problem 057: `git mv` + Edit + `git add` staging-ordering trap drops content edits from the commit" problem staging trap). Update the `Likely verified?` cell to `yes — observed: user confirmed <YYYY-MM-DD>`.
@@ -18,7 +18,7 @@ The deprecated `/wr-itil:manage-problem <NNN> known-error` subcommand route rema
18
18
  - `<status>` — the destination status. One of:
19
19
  - `known-error` — Open → Known Error (root cause identified AND workaround documented; fix not yet proposed — per the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule corrected semantics; the fix proposal draws a release row on a story map).
20
20
  - `verifying` — Known Error → Verification Pending (fix released, awaiting user verification per the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule).
21
- - `close` — Verification Pending → Closed (user has confirmed the fix works in production).
21
+ - `close` — Verification Pending → Closed (cited evidence meets the ticket's own close criterion, OR the user has confirmed the fix works in production — see Step 4).
22
22
 
23
23
  The `<NNN>` and `<status>` tokens are **data parameters**, not word-subcommands. Per the "Problem 071: Argument-based skill subcommands are not discoverable in Claude Code autocomplete" problem split rule (the "Rename `wr-problem` Plugin to `wr-itil`" architecture rule amended), data parameters (IDs, paths, URLs, enum destinations) are permitted; word-subcommands that name distinct user intents are not. This skill's argument shape is `data + data`, which is the same shape as `/wr-itil:report-upstream <NNN>`.
24
24
 
@@ -68,8 +68,12 @@ Check the current filename suffix and verify the destination status is reachable
68
68
  | `.open.md` | `known-error` | yes |
69
69
  | `.known-error.md` | `verifying` | yes |
70
70
  | `.verifying.md` | `close` | yes |
71
+ | `.verifying.md` | `known-error` | yes — **flip-back**: the fix recurred or proved incomplete. Required by `review-problems` Bucket 3, `manage-problem`, and `run-retro` Step 4a, all of which already instruct it. |
72
+ | `.closed.md` | `known-error` | yes — **reopen**: a close was wrong. This is the recovery path every evidence-authorised close reports (the "The Verification Pending → Closed transition is reserved for the maintainer, so evidence-based closure never fires and the verification queue grows without bound" problem), so it has to be reachable or the reversibility that justifies closing without a consent gate is fiction. |
71
73
  | any other pairing | — | no — emit an error and stop |
72
74
 
75
+ The two backward pairings are what make an agent-authorised close safe to make. The argument for closing on evidence without asking is that the close is cheap and reversible; a reopen route the skill refuses would make that argument false. Both are ordinary renames — `git mv` back to `known-error/`, Status field back to `Known Error`, append the recurrence or mis-close citation to the ticket body, refresh the README, one commit per the "Governance Skills Commit Their Own Completed Work" architecture rule — and neither re-runs the Open → Known Error pre-flight, because root cause and workaround were established the first time round. (the "The transition lifecycle table rejects both the fix-on-capture fast path and its own documented recovery path" problem tracks the wider set of missing pairings, including the fix-on-capture fast path.)
76
+
73
77
  If the pairing is invalid, emit a clear message naming the current status, the requested destination, and the valid next step. Do not silently skip or auto-correct — invalid transitions are almost always user typos and a clear error is the cheapest recovery.
74
78
 
75
79
  ### 4. Run pre-flight checks
@@ -117,9 +121,34 @@ Emit a structured report naming each deferred section + the lifted condition + t
117
121
 
118
122
  This check fires BEFORE the "derive-release-vehicle helper requires pre-edit of ticket changeset reference — three-touch when one-touch would suffice" problem Release-vehicle seed step in Step 6 — halt-on-conditional-deferral is the outer gate, seed-and-rename is the inner mechanic.
119
123
 
120
- **Verification Pending → Closed** (`<status>` = `close`) requires:
124
+ **Verification Pending → Closed** (`<status>` = `close`) requires **either** of:
125
+
126
+ - [ ] **Cited evidence** that meets the ticket's own stated close criterion — a test invocation and its outcome, a commit SHA whose diff covers the fix path, a skill or hook invocation that exercised the fix and behaved as the fix contracts, a post-release invocation of the shipped artefact that behaved as the fix contracts, or a `yes — observed: <citation>` cell already carried in the Verification Queue. The agent closes on its own authority and records the citation in the closure. **Mechanical stage — do NOT fire `AskUserQuestion`** (the "Agents over-ask in interactive sessions — conflating mechanical-stages with user-interactive-stages of multi-stage skill contracts (inverse-)" problem / the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule category 4, mirroring the shipped `review-problems` Step 4 Bucket 1 and `run-retro` Step 4a sub-step 5). Surface the recovery path alongside the close: `Recovery: rerun /wr-itil:transition-problem <NNN> known-error to reopen`.
127
+ - [ ] **The user has explicitly confirmed** the fix works in production, or an orchestrator supplied the `close` argument under prior user authorisation.
128
+
129
+ **Never close on inference — absence of evidence is not evidence.** A ticket nobody exercised stays Verification Pending, however old it is and however plausible the fix looks. "The fix is on disk", "it has been months", "that area has been touched a lot" and "the ADR that prescribed it shipped" are inference, not observation — see the "Relevance-close evaluator over-fires — a bare ADR/skill citation is read as "fix shipped", so live tickets return CLOSE-CANDIDATE" problem for what happens when a bare citation is read as proof of shipping. Closing tickets nobody exercised is the opposite failure and is exactly as wrong as never closing any.
130
+
131
+ **Genuine ambiguity stays the user's surface** — contested evidence, a fix that covers only part of the ticket, or a recorded do-not-close marker. Run the mechanical check first; it is a field read, not a judgement:
132
+
133
+ ```bash
134
+ wr-itil-is-close-blocked <NNN> docs/problems && close_blocked=1
135
+ ```
136
+
137
+ Exit 0 means **BLOCKED**: the ticket carries a line-anchored `DO NOT CLOSE` marker (`docs/problems/verifying/151-*.md` § "Regression / incomplete observed … DO NOT CLOSE" is the canonical shape). Do NOT close it whatever the evidence says — route it to the `verifying → known-error` flip-back, or queue it for the user. Exit 1 means not blocked. Exit 2 means the ticket ref did not resolve — treat as a pre-flight failure, not as permission.
138
+
139
+ **Evidence-authorised tracker updates.** Write the basis into the ticket's `**Status**:` line alongside the citation (`**Status**: Closed (closed-on-evidence <YYYY-MM-DD> — <citation>. Recovery: rerun /wr-itil:transition-problem <NNN> known-error to reopen)`). A provenance-proven GitHub issue on this project's tracker receives the gated comment and closes; unresolved or non-issue inbound provenance performs no issue mutation. A foreign issue receives the comment but stays open on our evidence alone; that upstream party's confirmation may authorize closure. Pull requests remain comment-only.
121
140
 
122
- - [ ] The user has explicitly confirmed the fix works in production (this skill never auto-closes on inference only on explicit user confirmation or orchestrator-supplied `close` argument)
141
+ Authority: the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule (framework-resolution boundary — evidence-backed close is category 4, silent framework action; contested or absent evidence is category 1, queued not guessed), the "Agent output grounding no fabricated quantitative estimates, cite + persist + uncertainty" architecture rule (cite the evidence, persist it, state the uncertainty), the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 5 (policy-authorised silent proceed), the "Evidence-based relevance-close pass for the problem backlog (Phase 1: file-no-longer-exists; Phase 2: ADR-shipped-confirmed + named-skill-exists + self-marker-in-body + driver-child-closed + Phase 1 false-positive fixes)" architecture rule (evidence-based closure precedent on the open/known-error side of the same lifecycle), the "The Verification Pending → Closed transition is reserved for the maintainer, so evidence-based closure never fires and the verification queue grows without bound" problem (this contract).
142
+
143
+ **Verification Pending → Known Error** (`<status>` = `known-error` — flip-back) requires:
144
+
145
+ - [ ] A recurrence or incompleteness citation: what was observed, and when. Append it to the ticket body; the `Likely verified?` cell becomes `no — observed regression — <one-line citation>`.
146
+
147
+ **Closed → Known Error** (`<status>` = `known-error` — reopen) requires:
148
+
149
+ - [ ] A stated reason the close was wrong. Nothing more — this is the recovery path for an evidence-authorised close and it must stay one command deep, or the reversibility that justifies closing without a consent gate is not real.
150
+
151
+ Neither backward pairing re-runs the Open → Known Error pre-flight above: root cause and workaround were established when the ticket first reached Known Error and are still on the ticket. Neither fires the "Problem 063: manage-problem does not trigger /wr-itil:report-upstream when root cause is external" problem external-root-cause detection (Step 5 is Open → Known Error only).
123
152
 
124
153
  ### 5. External-root-cause detection (the "Problem 063: manage-problem does not trigger /wr-itil:report-upstream when root cause is external" problem — Open → Known Error only)
125
154
 
@@ -195,7 +224,7 @@ git mv docs/problems/known-error/<NNN>-<title>.md docs/problems/verifying/<NNN>-
195
224
  git add docs/problems/verifying/<NNN>-<title>.md
196
225
  ```
197
226
 
198
- The `## Fix Released` section contains: release marker (version, commit SHA, or date), one-sentence fix summary, "Awaiting user verification" line, and any exercise evidence from the releasing session. The `.verifying.md` suffix signals to every downstream consumer (work-problems classifier, review step 9d, README rendering) that the remaining work is user-side verification — no file-body scan needed.
227
+ The `## Fix Released` section contains: release marker (version, commit SHA, or date), one-sentence fix summary, "Awaiting user verification" line, and any exercise evidence from the releasing session. The `.verifying.md` suffix signals to every downstream consumer (work-problems classifier, review step 9d, README rendering) that the remaining work is verification — by evidence or by the user — no file-body scan needed.
199
228
 
200
229
  When this transition is folded into a `fix(<scope>): ... (closes P<NNN>)` commit (the common case), the `git mv` + `Edit` + re-stage + README refresh all join that single commit — never split across commits.
201
230
 
@@ -230,10 +259,17 @@ Use the structured values verbatim when authoring the `## Fix Released` section'
230
259
 
231
260
  ```bash
232
261
  git mv docs/problems/verifying/<NNN>-<title>.md docs/problems/closed/<NNN>-<title>.md
233
- # ... use the Edit tool to update the Status field to "Closed" ...
262
+ # ... use the Edit tool to update the Status field per the shape below ...
234
263
  git add docs/problems/closed/<NNN>-<title>.md
235
264
  ```
236
265
 
266
+ **Write the close's authority basis into the Status field.** The Status line is the only place the basis survives — the `Likely verified?` cell lives in the README's Verification Queue table, and that row is deleted by this very transition, so a downstream reader (Step 7b's upstream leg) would find nothing there. Shape, matching what the 2026-07-15 closes already wrote (`docs/problems/closed/186-*.md:3`):
267
+
268
+ - Evidence-authorised: `**Status**: Closed (closed-on-evidence <YYYY-MM-DD> — <citation>. Recovery: rerun /wr-itil:transition-problem <NNN> known-error to reopen)`
269
+ - User-confirmed: `**Status**: Closed (user-confirmed <YYYY-MM-DD>)`
270
+
271
+ `closed-on-evidence` is what the outbound leg reads to keep a foreign issue open on our evidence alone. The inbound leg uses committed issue-channel provenance instead: ambiguity fails closed before any issue operation.
272
+
237
273
  ### 7. Refresh docs/problems/README.md (the "Problem 062: `manage-problem` does not refresh `docs/problems/README.md` on single-ticket transitions; fast-path cache goes stale silently" problem)
238
274
 
239
275
  Every Step 7 status transition regenerates `docs/problems/README.md` and stages it in the same commit so the dev-work table, Verification Queue, Parked section, and "Last reviewed" line never lag the on-disk ticket inventory. Without this step, README.md accumulates staleness between review invocations.
@@ -35,7 +35,7 @@ A space-separated list of `<NNN> <status>` pairs. Repeating the singular skill's
35
35
  - `<status>` — destination status. One of:
36
36
  - `known-error` — Open → Known Error (root cause + workaround documented).
37
37
  - `verifying` — Known Error → Verification Pending (fix released; awaiting user verification per the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule).
38
- - `close` — Verification Pending → Closed (user has confirmed the fix works in production).
38
+ - `close` — Verification Pending → Closed (cited evidence meets the ticket's own close criterion, OR the user has confirmed the fix works in production — see Step 2c).
39
39
 
40
40
  **Examples:**
41
41
 
@@ -100,13 +100,19 @@ If no file is found OR multiple files are found (suffix-exclusive lifecycle viol
100
100
  | `.open.md` | `known-error` | yes |
101
101
  | `.known-error.md` | `verifying` | yes |
102
102
  | `.verifying.md` | `close` | yes |
103
+ | `.verifying.md` | `known-error` | yes — **flip-back**: the fix recurred or proved incomplete. `review-problems` Bucket 3 already instructs this and had no batch path. |
104
+ | `.closed.md` | `known-error` | yes — **reopen**: a close was wrong. The recovery path every evidence-authorised close reports (the "The Verification Pending → Closed transition is reserved for the maintainer, so evidence-based closure never fires and the verification queue grows without bound" problem). |
103
105
  | any other pairing | — | no — record as `invalid-transition` and continue |
104
106
 
107
+ Lockstep with `/wr-itil:transition-problem` Step 3 per the drift clause below — the singular and plural tables move together or neither moves. The two backward pairings are what make an agent-authorised close safe: the argument for closing on evidence without asking is that the close is cheap and reversible, and a reopen route either skill refuses would make that argument false. Both are ordinary renames; neither re-runs the Open → Known Error pre-flight (root cause and workaround were established the first time round) and neither fires the "Problem 063: manage-problem does not trigger /wr-itil:report-upstream when root cause is external" problem detection at 2d.
108
+
105
109
  **2c. Run pre-flight checks** for the destination (same gating as the singular):
106
110
 
107
111
  - Open → Known Error (`known-error`): root cause documented; ≥ 1 investigation task ticked; reproduction test or reference; workaround documented; effort bucket re-rated if scope shifted (the "Problem 047: WSJF effort buckets are coarse and not re-rated at lifecycle transitions" problem); status multiplier re-rated from Open 1.0 to Known Error 2.0 and WSJF recomputed with the post-transition status and current Effort (the "WSJF uses the pre-transition status multiplier" problem).
108
112
  - Known Error → Verification Pending (`verifying`): fix implemented; release marker available (version, commit SHA, or date) for the `## Fix Released` section.
109
- - Verification Pending → Closed (`close`): user has explicitly confirmed the fix works in production. AFK callers (work-problems orchestrator) MUST supply the close pair via prior user authorisation (e.g. an `AskUserQuestion`-batched closure prompt at the orchestrator layer); this skill never auto-closes on inference.
113
+ - Verification Pending → Closed (`close`): cited observed evidence or explicit user confirmation authorizes closure. Evidence-backed closure is mechanical and does not require another question. Record the citation and recovery path (`/wr-itil:transition-problem <NNN> known-error`) in each ticket's Status line. A provenance-proven GitHub issue on this project's tracker receives the gated comment and closes; unresolved or non-issue inbound provenance performs no issue mutation. A foreign issue receives the comment but stays open on local evidence alone; that upstream party's confirmation may authorize closure. Pull requests remain comment-only.
114
+
115
+ **Never close on inference** — absence of evidence is not evidence. A pair whose ticket carries no citation records as `pre-flight-failed` with reason `no-evidence` and stays Verification Pending; age, plausibility, and "the fix is on disk" are not observations. **Do-not-close marker check** — run `wr-itil-is-close-blocked <NNN> docs/problems` per pair before closing. Exit 0 → record the pair as `pre-flight-failed` with reason `close-blocked` plus the matched marker line, and continue to the next pair; do NOT close it whatever the evidence says. Exit 2 (unresolvable ref) is a pre-flight failure, not permission.
110
116
 
111
117
  If any pre-flight fails, record the pair as `pre-flight-failed` with the failed-check list and continue to the next pair.
112
118
 
@@ -151,10 +157,18 @@ git add docs/problems/verifying/<NNN>-<title>.md
151
157
  ```bash
152
158
  # Verification Pending → Closed
153
159
  git mv docs/problems/verifying/<NNN>-<title>.md docs/problems/closed/<NNN>-<title>.md
154
- # Edit Status field to "Closed"
160
+ # Edit Status field per the shape below
155
161
  git add docs/problems/closed/<NNN>-<title>.md
156
162
  ```
157
163
 
164
+ **Write the close's authority basis into the Status field.** The Status line is the only place the basis survives — the `Likely verified?` cell lives in the README's Verification Queue table, and that row is deleted by this very transition, so a downstream reader (Step 7b's upstream leg) would find nothing there. Shape, matching what the 2026-07-15 closes already wrote (`docs/problems/closed/186-*.md:3`):
165
+
166
+ - Evidence-authorised: `**Status**: Closed (closed-on-evidence <YYYY-MM-DD> — <citation>. Recovery: rerun /wr-itil:transition-problem <NNN> known-error to reopen)`
167
+ - User-confirmed: `**Status**: Closed (user-confirmed <YYYY-MM-DD>)`
168
+
169
+ `closed-on-evidence` is what the outbound leg reads to keep a foreign issue open on our evidence alone. The inbound leg uses committed issue-channel provenance instead: ambiguity fails closed before any issue operation.
170
+
171
+
158
172
  If `git mv` or `git add` fails for a pair (e.g. the file has been moved by a parallel process), record the pair as `git-failed` with the error and continue to the next pair. Do NOT attempt to roll back prior pairs' staged renames — those are now part of the in-progress batch.
159
173
 
160
174
  Record each pair's outcome (succeeded / failed-with-reason) for the summary in Step 5.