Skip to content

[finding] dispatch-gates residue: after #12514 the extensionless-target reason is only reachable for a BARE hint, where it names the wrong cause — latent wrong-reason row, zero instances today #12797

Description

@claude

Observed 2026-08-27 while implementing #12514 (PR #12794), on origin/main @ ead731756 plus that PR's change. Filed unassigned, recording only. ⛔ Not fixed in #12794 — out of that card's scope, which is the matcher.

What changed under this branch

unreachableReason checks target FIRST, and it is the strongest sentence the residue can print:

if (target) {
  return `'${hint}' — the tree HAS ${target}; the literal is that file's
           extensionless module spelling, which no whole-segment comparison reaches`;
}

That was true when it was written: hintCovers could not reach a dropped extension, so "no whole-segment comparison reaches" was a statement about the rule. #12514 taught hintCovers to follow a dropped extension, so a hint that carries a path separator and names a real file is now MATCHED and never enters dead at all.

The residue path that survives, and prints the wrong cause

One population still reaches the target branch: a hint the matcher refuses for a different reason — the bare-single-segment rule (if (!hint.includes('/') && !plain.startsWith('.')) return false). For a hint spelled conversions with a tracked root file conversions.ts:

  • extensionlessModuleTarget('conversions', files, prefixes) returns conversions.ts (conversions is not a tracked prefix, so its up-front guard does not fire);
  • hintCovers refuses it for being a bare word, not for the extension;
  • the reader is told the whole-segment comparison cannot reach it, which is now false — a separator is what it lacks, and the "too generic" branch below is the sentence that names the real escape (declare the subtree spelling).

Same species as #12299 and #12568: a residue row whose classification and whose evidence are both wrong, about a file that is sitting right there. Those two were the reason the branch exists; this is the branch drifting back into the same failure through a different door.

Reachability today: LATENT, measured not assumed

Zero on this tree. It needs a bare separator-less hint whose plain + ext is a tracked repo-root file. Measured over the live fleet at ead731756: no dead bare hint (conversions, migrations, and the rest) has a root-level module sibling. So this is a latent wrong sentence, not a live one — which is exactly the state the two closed cards above were in before a layout change made them live.

Why the #12794 pin does not cover it

That PR adds a coherence case asserting no hint that carries a separator is both dead to the matcher and extensionless-resolvable. The filter is deliberate and stated: for a separator-carrying hint the disjointness is structural, and for a bare one it is not. So the class is named there and left open here rather than pinned green by a case that quietly excludes it.

⛔ Not proposing a shape

Whether the right repair is to order the bare-word branch ahead of target, to teach the target sentence which refusal actually fired, or to decide the branch is now residue that should be retired, is triage — and it sits on scripts/pm/dispatch-gates.mjs, which has a serial queue on it (#12470, #12411, #12410, #12500, #12749). Whoever holds that file next is the cheapest place for it.

Dedup: one targeted search of the board for dispatch-gates residue/reason cards found #12299 and #12568 (both closed, both the other direction) and no open card naming this branch.


Generated by Claude Code

Activity

  1. huangyiirene commented on Aug 27, 2026

    @huangyiirene
    Collaborator

    Finding round: graded, finding shed. domain:devx stands, type Task.

    State pm:on-hold with an opportunistic trigger — taking the card's own advice, which is right: "it sits on scripts/pm/dispatch-gates.mjs, which has a serial queue on it (#12470, #12411, #12410, #12500, #12749). Whoever holds that file next is the cheapest place for it." ⇒ A latent one-sentence diagnostic fix should not contend for the busiest file in the lane on its own dispatch, and it should not be discarded either. The rider path is exactly this shape — same disposition as #12789 last round.

    Restart-when: any dispatch whose declared file surface includes scripts/pm/dispatch-gates.mjs — this card is then a pre-declared rider on it, to be folded in and closed with it.

    Restart-touch: scripts/pm/dispatch-gates.mjs

    ⭐ The trigger here is not merely reachable but near-certain to fire soon — five open cards already queue on that file. ⛔ Unlike the two holds this seat refused today for unreachable exits, this one will be woken by ordinary traffic.

    Direction ruled, so the rider is a small edit rather than a fresh analysis — the card leaves the shape to triage, and the shape follows from its own measurement:

    After #12514, a separator-carrying hint that names a real file is MATCHED and never enters dead, and #12794's coherence case pins that disjointness. ⇒ The target branch is now reachable only via a bare separator-less hint — the one population where its sentence ("no whole-segment comparison reaches") is false: what that hint lacks is a separator, and the "too generic" branch below is the one that names the real escape.

    ⇒ A branch reachable only where its statement is wrong has no correct remaining use. So: order the bare-word branch ahead of target so the printed reason matches the refusal that actually fired. ⛔ Do not "teach the target sentence which refusal fired" — that adds machinery to a branch that then has no live caller. Once reordered, whether to retire the target branch outright is a natural follow-on the rider may take if the reading still holds at that time; ⛔ report rather than assume, since #12514 and #12794 were still landing when this was measured.

    Reachability is LATENT and measured, not assumed — zero on this tree at ead731756: no dead bare hint (conversions, migrations, the rest) has a root-level module sibling. ⚠️ And the card is right that this is precisely the state #12299 and #12568 were in before a layout change made them live. That is the argument for the rider rather than for closing it.

    ⭐ Worth crediting: #12794 named the class and left it open here rather than pinning it green with a case that quietly excludes it — its coherence filter covers separator-carrying hints only, deliberately and stated. A pin that silently excluded the uncovered population would have been the more comfortable choice and the wrong one.

    Dedup as filed: #12299 and #12568 both closed and both the other direction; no open card names this branch.


    Generated by Claude Code

  2. claude commented on Sep 6, 2026

    @claude
    ContributorAuthor

    Claim: PM loop round 1 — RIDER, folded into #16030
    Session: session_01Vbw3RPgdtqesx4azk9SbW8
    Branch: claude/issue-16030-roster-self-test-rows (shared with the anchor card #16030; this card's edit rides on it per its own hold 5445380987: Restart-when: any dispatch whose declared file surface includes scripts/pm/dispatch-gates.mjs)
    Worktree: objectstack-issue-16030
    Domain: domain:devx
    File surface: scripts/pm/dispatch-gates.mjs (the extensionless-target reason: order the bare-word branch ahead of target, per the ruling in the hold comment)
    Container & model: rider on an M dispatch, mode:subagent, model: opus
    Clause-②: no
    Serial constraints cleared: see the anchor claim on #16030 (05:4xZ). pm:on-hold → pm:dispatched in the same stroke as the assignee.


    Generated by Claude Code

  3. claude commented on Sep 6, 2026

    @claude
    ContributorAuthor

    Ridden and delivered in draft PR #16221 (branch claude/issue-16030-roster-self-test-rows), folded into anchor #16030 per this card's hold. The bare-word refusal is now ordered ahead of the target branch and has one owner, refusedAsTooGeneric, which hintCovers itself calls; the target sentence was NOT taught which refusal fired. Reachability re-measured with the hold's own method: 236 dead hints on this tree, 0 reaching the target branch, 0 of those bare — still LATENT, same reading as 2026-08-27 at ead7317. Reported rather than assumed, as ruled: after the reorder that branch has no live caller in either population, so retiring it is a real follow-on, left for triage because it also reaches unreachableClass and the extensionlessModuleTarget pins. Full report on the anchor card.


    Generated by Claude Code

  4. claude commented on Sep 6, 2026

    @claude
    ContributorAuthor

    ACCEPT (rider) — delivered on PR #16221 with anchor #16030; full review on #16030 (PM seat domain:devx @ objectstack, session session_01Vbw3RPgdtqesx4azk9SbW8, 07:0xZ). The bare-word refusal now precedes the extensionless-target sentence (refusedAsTooGeneric, single owner, pinned both ways); the target sentence is untouched per the ruling; reachability re-measured — 236 dead hints, 0 reach target — still latent. Retiring the target branch stays an optional follow-on (open question answered A: keep, pinned); no card filed. PR closes this card via its own Fixes line; pm:dispatched is stripped in the landing stroke.


    Generated by Claude Code

  5. claude commented on Sep 6, 2026

    @claude
    ContributorAuthor

    LANDED — PR #16221 MERGED via the merge queue as a3bbb8b1a at 2026-09-06T07:25:38Z (added_to_merge_queue 07:01:32Z → removed_from_merge_queue + merged one second apart = a landing). PM seat domain:devx @ objectstack, session session_01Vbw3RPgdtqesx4azk9SbW8, 2026-09-06T07:39Z.

    Content probe on re-fetched origin/main @ 618f70d74 via git show: export function refusedAsTooGeneric = 1 in scripts/pm/dispatch-gates.mjs (the bare-word refusal's single owner, consulted ahead of the extensionless-target sentence); firing control Artifact rosters — = 3; nonsense token = 0. The target branch stays, pinned, with zero live callers on record (open question answered A).

    Same stroke: pm:dispatched stripped and the assignee cleared (GitHub closes the card through Fixes and leaves labels — #16005). Ownership labels stay.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions