Description
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)returnsconversions.ts(conversionsis not a tracked prefix, so its up-front guard does not fire);hintCoversrefuses 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
huangyiirene commentedon Aug 27, 2026
Finding round: graded,
findingshed.domain:devxstands, type Task.State
pm:on-holdwith an opportunistic trigger — taking the card's own advice, which is right: "it sits onscripts/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. ⇒ Thetargetbranch 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
targetso the printed reason matches the refusal that actually fired. ⛔ Do not "teach thetargetsentence which refusal fired" — that adds machinery to a branch that then has no live caller. Once reordered, whether to retire thetargetbranch 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⚠️ 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.
ead731756: no dead bare hint (conversions,migrations, the rest) has a root-level module sibling.⭐ 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
claude commentedon Sep 6, 2026
Claim: PM loop round 1 — RIDER, folded into #16030
Session:
session_01Vbw3RPgdtqesx4azk9SbW8Branch:
claude/issue-16030-roster-self-test-rows(shared with the anchor card #16030; this card's edit rides on it per its own hold5445380987:Restart-when: any dispatch whose declared file surface includes scripts/pm/dispatch-gates.mjs)Worktree:
objectstack-issue-16030Domain:
domain:devxFile surface:
scripts/pm/dispatch-gates.mjs(the extensionless-target reason: order the bare-word branch ahead oftarget, per the ruling in the hold comment)Container & model: rider on an
Mdispatch,mode:subagent,model: opusClause-②: no
Serial constraints cleared: see the anchor claim on #16030 (05:4xZ).
pm:on-hold→pm:dispatchedin the same stroke as the assignee.Generated by Claude Code
claude commentedon Sep 6, 2026
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 thetargetbranch and has one owner,refusedAsTooGeneric, whichhintCoversitself calls; thetargetsentence was NOT taught which refusal fired. Reachability re-measured with the hold's own method: 236 dead hints on this tree, 0 reaching thetargetbranch, 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 reachesunreachableClassand theextensionlessModuleTargetpins. Full report on the anchor card.Generated by Claude Code
claude commentedon Sep 6, 2026
ACCEPT (rider) — delivered on PR #16221 with anchor #16030; full review on #16030 (PM seat
domain:devx @ objectstack, sessionsession_01Vbw3RPgdtqesx4azk9SbW8, 07:0xZ). The bare-word refusal now precedes the extensionless-targetsentence (refusedAsTooGeneric, single owner, pinned both ways); thetargetsentence is untouched per the ruling; reachability re-measured — 236 dead hints, 0 reachtarget— still latent. Retiring thetargetbranch stays an optional follow-on (open question answered A: keep, pinned); no card filed. PR closes this card via its ownFixesline;pm:dispatchedis stripped in the landing stroke.Generated by Claude Code
claude commentedon Sep 6, 2026
LANDED — PR #16221 MERGED via the merge queue as
a3bbb8b1aat 2026-09-06T07:25:38Z (added_to_merge_queue07:01:32Z →removed_from_merge_queue+mergedone second apart = a landing). PM seatdomain:devx @ objectstack, sessionsession_01Vbw3RPgdtqesx4azk9SbW8, 2026-09-06T07:39Z.Content probe on re-fetched
origin/main@618f70d74viagit show:export function refusedAsTooGeneric= 1 inscripts/pm/dispatch-gates.mjs(the bare-word refusal's single owner, consulted ahead of the extensionless-targetsentence); firing controlArtifact rosters —= 3; nonsense token = 0. Thetargetbranch stays, pinned, with zero live callers on record (open question answered A).Same stroke:
pm:dispatchedstripped and the assignee cleared (GitHub closes the card throughFixesand leaves labels — #16005). Ownership labels stay.Generated by Claude Code
fix(pm): dispatch-gates --ran never reads a killed run as RUN — a cla…