Skip to content

[problem] wr-itil stale-ticket surfaces all miss the incidental-fix shape, where a ticket's fix ships inside another work item's commit #394

Description

@tompahoward

Description

Three wr-itil surfaces exist to catch a problem ticket whose fix has already shipped: the fix-title lifecycle advisory hook (itil-fix-title-lifecycle-advisory.sh, P345), the post-release Known Error to Verifying drain (enumerate-postrelease-kv-candidates.sh, P228), and the evaluate-relevance Shape 2 ADR-shipped-confirmed evaluator. Each keys on a signal that one common shape lacks: a ticket whose fix ships incidentally, inside a commit authored for a different work item. In that shape the commit is not fix:-typed, it does not name the fixed ticket in its subject, the ticket cites no changeset of its own, and the ticket does not cite the ADR that carried the fix (the ADR cites the ticket, not the reverse). All three surfaces stay silent, and the ticket ages in open/ or known-error/ holding its dev-work WSJF rank until a human or an AFK iteration stumbles on it.

A second, much cheaper defect compounds the first. Shape 2 scans ticket bodies for ADR references with the regex \bADR-[0-9]{3}\b, which matches only the hyphenated form. The ADR 027 space form is widely used in adopter tickets and in wr-itil's own prose, and it is invisible to the scan.

Symptoms

  • A fix-typed advisory never fires for a fix that shipped inside a feat: release commit.
  • The post-release Known Error to Verifying drain skips silently for a ticket fixed by another ticket's release: derive-release-vehicle returns exit 2 (no changeset reference in the ticket body) and the candidate is dropped without a log line.
  • evaluate-relevance returns no close verdict for a ticket whose fix is live and whose governing ADR is ratified, because the ticket spells the citation ADR 027 rather than ADR-027.
  • Downstream effect: the ticket keeps its dev-work WSJF rank at or near the top of the queue, and an AFK /wr-itil:work-problems iteration spends a full investigate-and-propose cycle on a stale premise before discovering the fix is already live.

Workaround

Periodic manual sweep that cross-references still-open ticket IDs against commit bodies rather than subjects:

git log --since="3 months ago" --format='%H %s%n%b' \
  | grep -oE 'P[0-9]{3}' | sort -u > /tmp/cited.txt
ls docs/problems/open docs/problems/known-error \
  | grep -oE '^[0-9]{3}' | sed 's/^/P/' | sort -u > /tmp/still-open.txt
comm -12 /tmp/cited.txt /tmp/still-open.txt

Each hit is a candidate for a skipped ADR-022 transition fold. Nothing schedules this sweep, so it runs only when someone remembers.

Affected plugin or component

@windyroad/itil, three files:

  • hooks/itil-fix-title-lifecycle-advisory.sh: fix: type filter, subject-only token scan, docs/problems/open/ glob.
  • lib/enumerate-postrelease-kv-candidates.sh: own-changeset-citation filter via derive-release-vehicle.
  • scripts/evaluate-relevance.sh Shape 2: \bADR-[0-9]{3}\b regex, ticket-cites-ADR direction only.

Frequency

Two confirmed multi-week occurrences across roughly 50 tickets in one adopter repo. Both were found by accident rather than by a surface firing.

Versions

  • Local plugin: @windyroad/itil@0.59.2
  • Upstream package: @windyroad/itil@0.59.2
  • Claude Code CLI: 2.1.219 (Claude Code)
  • Node: v24.16.0
  • OS: Darwin 25.3.0 x86_64

Evidence

Occurrence 1: downstream P026, which sat in open/ for roughly 3 months before anyone noticed. It has since been closed.

  • The fix shipped in downstream commit 920fce6, subject feat(search): v2.4.0 ... (ADR 027 + ADR 028). The type is feat, so the P345 hook's fix: / fix( filter excludes it before any token scan runs.
  • The token P026 appears only in the commit body ("Combined release resolving both halves of issue [problem] wr-itil: work-problems/SKILL.md is 245KB (5x the P097 50KB anchor) — largest skills breach the ADR-054 runtime-budget policy #367 / P015 / P026"). The hook reads git log -1 --format='%s', so a body-only citation is out of reach even for a correctly typed commit.
  • P026's ticket body cites the governing ADR nine times, every one as ADR 027. Shape 2's regex matches none of them, so ADR-shipped-confirmed was never recorded, even after the ADR was ratified.
  • The ADR cites P026. P026 does not cite the ADR in the matched form. There is no reverse-citation shape, so neither direction connects.

Occurrence 2: downstream P040, which sat in known-error/ for roughly 54 days. It has since moved to verifying/.

  • The fix shipped in downstream commit 3969b9e, subject feat(deploy): version-control Cloudflare Worker via Terraform (P042, ADR 032). The subject names P042, the ticket the commit was authored for. P040 appears only in the body ("the P040 regression guard").
  • The P345 hook globs docs/problems/open/ only, so a known-error/ ticket is out of scope regardless of subject content.
  • The P228 drain requires the ticket to cite its own .changeset/<name>.md. P040 was fixed by another ticket's release and cites no changeset, so derive-release-vehicle returns exit 2 and the ticket is skipped silently.
  • The ticket sat at WSJF 20.0, top of the dev-work queue, for the full 54 days.

Suggested direction

Two independent pieces, listed cheapest first. Not prescriptive about where they land.

  1. Widen Shape 2's ADR reference regex to accept ADR[ -]?[0-9]{3}. This is a one-line change, and on its own it would have closed occurrence 1 within days rather than months. Low over-fire risk, since the existing human-oversight: confirmed check remains the gate.
  2. Add a reverse-citation shape: scan commit bodies, and @problem P<NNN> markers in ADRs and code comments, for ticket IDs, then cross-reference against tickets still in open/ or known-error/, independent of commit type and independent of which ticket the commit was authored for. Whether that belongs as a widened P345 hook, a new evaluate-relevance shape, or a review-problems Step 4.6 extension is a design call for the maintainer. A hook-side version stays advisory per ADR-092, since a shipped fix does not by itself establish the knowledge claim that Open to Known Error asserts.

Piece 2 needs a false-positive guard. A commit body naming a ticket does not always mean it fixed it, so the emitted verdict should be a candidate with the citing SHA quoted, not an auto-transition.

Related upstream issues, distinct root causes:

Cross-reference

Reported from the downstream addressr project; tracked locally as P050 in its docs/problems/ directory.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions