Skip to content

finding(pm-gate): H26's "can never CLOSE" premise is asserted, not counted — and check-half-states.mjs refutes it twice in its own text #9317

Description

@claude

domain:devx @ objectui seat (#5748), session session_01FhBNJcLRZLe8M87VcUgpKr. Reading anchored at origin/main = d7f0601ee72ba646c296dcd8c1f65343f6877ac3, taken 2026-09-12T21:57Z. ⛔ Nothing is repaired here, no card is re-labelled, and the two cards named in "Downstream" are another seat's — untouched.

The defect

scripts/pm/check-half-states.mjs H26 fires on an open pm:blocked card whose Blocked-by: target is open and carries a member of

:4564  export const INDEFINITE_TARGET_LABELS = ['pm:on-hold', 'needs-user-decision'];

and emits, verbatim:

:4613        `\`pm:blocked\` on ${indefinite.length} target(s) that can never CLOSE: ${named}${more}. ` +
:4615          '`needs-user-decision` are by definition states a card sits in WHILE OPEN — so this ' +
:4616          'block has NO MECHANISM THAT WILL EVER RELEASE IT. Every existing check passes on this ' +

with the same claim in the doc block:

:501   *       and parked in a state that can never close  `pm:on-hold` or
:502   *       `needs-user-decision`, both by definition states a card sits in WHILE

"by definition" is an assertion. It was never counted, and it is false.

Measured — objectui, 2026-09-12, REST labels=<L>&state=<S>&per_page=100, issues only

label open closed closed state_reason
pm:on-hold 63 7 6 × completed, 1 × not_planned
needs-user-decision 4 3 3 × completed
pm:blocked (control) 100 6

The closed pm:on-hold cards: #5961 (not_planned), #5479, #4986, #4280, #4163, #3670, #3374 — the last six all completed. The closed needs-user-decision cards: #5637, #4051, #2929 — all three completed.

Control with a known direction: the same enumerator returns non-zero on both axes (63/7, 4/3, 100/6), so neither the zero-free closed column nor the open column is a query artifact; a broken state=closed would have returned 0 across all three rows and it returned 7, 3 and 6.

⇒ Cards do close out of both states, and in 9 of the 10 measured cases they close as completed — i.e. the hold was lifted and the work finished, which is exactly the release H26 says cannot exist.

The same file says so too — twice, and one of them is a count

(a) H22 exists because pm:on-hold lands on closed cards.

:3734  // H22 — a CLOSED card still carrying a `pm:*` STATE label (#10688).
:3788  export const PM_RESIDUE_LABELS = [
:3792    'pm:on-hold',

A label can only be residue on a closed card if cards close carrying it. H22's own doc then states the converse of H26 outright:

:3772   * and `needs-user-decision` are perfectly good states for a closed card to have

So needs-user-decision is simultaneously, in one file, "a state a card sits in WHILE OPEN" (:502, H26) and "a perfectly good state for a closed card to have ended in" (:3772, H22).

(b) This file's own census already counted the refuting row. The objectui port measurement at :7906:7923:

:7918   *   of those 400, carrying a `PM_RESIDUE_LABELS` member:
:7919   *     `pm:dispatched`                                         259
:7920   *     `pm:queue`                                               86
:7921   *     `pm:blocked`                                              1
:7922   *     `pm:on-hold`                                              1

One closed card carrying pm:on-hold, in a 6.2-day window, written into the file 15 days before H26's "by definition" sentence was relied on.

Downstream — the sentence has already been published as fact

H26's wording is not confined to a report body; it is quoted verbatim into card threads. Two live instances, both on cards belonging to the domain:spec seat (⛔ raised here only, not touched):

  • objectui#2231 comment 5591833377"This card's unlock predicate can never fire", quoting row H26 verbatim including "can never CLOSE".
  • objectui#2890 comment 5591828952 — the mirror reading.

The target in that pair is #2890 (pm:on-hold + pm:blocking). On the measurement above, #2890 closing is an ordinary event, not a structural impossibility — 6 other pm:on-hold cards in this repo have done exactly that.

⚠️ Scope of the correction — the row is miscalibrated, not wrong

H26's final sentence is already accurate and is the useful half:

"It says the wait is indefinite BY CONSTRUCTION, so the release has to come from the target's own state changing (a ruling answered, a hold restarted) and someone has to want that." (:4622:4624)

That is true and worth surfacing: a parked target releases only if a human decides to unpark it, and nothing schedules that. The defect is the categorical half — "can never CLOSE" / "NO MECHANISM THAT WILL EVER RELEASE IT" / "by definition" — which overstates a no one is scheduled to act into a no mechanism exists, and it is the overstatement that propagates into other seats' threads as a structural verdict.

So the plausible repair is wording + provenance, not deleting the row: say what was measured (the wait has no scheduled releaser) rather than what was assumed (the state cannot be exited). Whether the doc block, the emitted string, the #11219 rationale and the H26: self-tests at :12174:12216 (several of which assert the "NO MECHANISM THAT WILL EVER RELEASE IT" substring) all move together is the implementer's call, not decided here.

⛔ Disclosure — this correction is against my own intent first

I was carrying a standing note to file the #2231/#2890 pair as a deadlock — "pm:on-hold is a state a card does not close from, so #2231's unlock predicate can never fire". I had inherited that premise from this row and had not counted it. Counting it is what produced this card. The deadlock finding I intended to file would have been false, and is withdrawn rather than filed.

Not graded

No domain:* and no pm:* applied — this seat does not grade. Triage's call.


Generated by Claude Code

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingdomain:devxobjectui devx stream: fix lands on .github/, scripts/ or release pipeline — devx lane cross-repopm:blockedpriority:p2

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions