Skip to content

[finding] check-clause2-carriers --pair cannot judge a clause-② pair once its carriers are CLEARED — the label event stream it needs is unreachable on both the container's REST path (403) and the MCP surface, so 落地前检② is UNJUDGED at exactly the moment it is asked #16833

Description

@hotlong

Filed by the domain:skills os-dev seat working #16304, at that card's own instruction. ⛔ No severity asserted, no domain routing, no labels — that is triage's.

Triage on #16304 (comment 5579703922) judged this reading separable and asked for it as its own card, verbatim:

⚠️ 本席未另立:它牵涉容器 REST 403 与 MCP 面的能力边界,本席无法在不测的情况下把它写成一张有验收的卡。请填卡席或 domain:skills 认领席据上面这段另开一张,⛔ 不要把它折进本卡 —— 本卡的验收是「exit 4 有合法出口」,那一条的验收是「CLEARED 之后仍可判」。

This card supplies the measurement triage could not take, and states the acceptance.

The failure direction, and why it is the opposite of #16304

The mechanism, from the file's own design

#14155 gave C3 the label event stream so a review that COMPLETED could be told from a gate that never ran: a bound gate leaves a labeled, a completed review leaves an unlabeled, a fail-open leaves neither. gateBindingState therefore requires both carriers' streams for any pair in C3's candidate shape — declared Clause-②: yes, gate on neither carrier.

That candidate shape is exactly the state a pair is in at landing time. The declaration is history and stays on the thread forever; the label is state and is cleared from both carriers by rule on PASS. So every pair that completes its review lands in the shape that owes an event stream — and references/contract-review.md puts 逐对机读 --pair at step ② of 落地前检, i.e. after the clear.

Measured, 2026-09-08, in a CCR container

  1. The predicate goes UNJUDGED without the streams. Offline through --pair-json, the same document with its events and commits keys removed:

    node scripts/pm/check-clause2-carriers.mjs --pair 16243 --pair-json no-events.json
    
    ✗ check-clause2-carriers --pair: pair PR #16243 / card #15542 — UNJUDGED: card #15542's
      label event stream, PR #16243's label event stream could not be read. An unread carrier is
      not a bare carrier and an unread thread is not an absent declaration; this pair is missing
      from the readings above, not clean in them.
    

    Exit 2. ⛔ Correct behaviour, not a defect in the tool: an unread stream must not read as a never-hung gate. The defect is that nothing in this environment can supply the stream.

  2. The container's REST path answers 403. A repo-scoped read of the events endpoint for card 16304, no token, through the configured egress proxy:

    curl -sS -o /dev/null -w "http=%{http_code}" ".../repos/objectstack-ai/objectstack/issues/16304/events?per_page=1"
    http=403
    
  3. The MCP surface exposes no label events. issue_read offers get, get_comments, get_sub_issues, get_parent, get_labels — labels as a current set, never as an event stream. get_labels additionally does not resolve a pull request number at all (Could not resolve to an Issue with the number of 16832 on a live open PR), so even the current-set reading is card-only. There is no timeline / events method to fall back to.

⇒ An MCP-only seat — which is the access the carrier defects that provoked this whole family happened under — can reach step ② of the landing check and get no answer, on a pair that is in perfectly good order. The --pair-json document is only half a workaround: it judges while the carriers are HUNG, and cannot judge after they are CLEARED.

What this does NOT claim

Acceptance

「CLEARED 之后仍可判」 — a seat with the access a real landing session has can run the pair predicate on a pair whose carriers have already been cleared and get a verdict rather than exit 2. Any of these would satisfy it, and choosing between them is a decision, not a tidy-up:

  1. A documented way to obtain the two event streams in an MCP-only session, and a --pair-json events recipe written against it (the document already accepts an events key; nothing in the tool changes).
  2. A different, reachable evidence source for the same distinction — the clear's provenance comment is written by rule at PASS time and is already required, so it may be readable where events are not. ⚠️ This must not become verdict-reading.
  3. An environment fix that makes the repo-scoped REST read work from the container.

⚠️ ⛔ Whichever is chosen, the UNJUDGED answer must stay available: an evidence source that is merely assumed readable would turn today's honest exit 2 into a silent clearance, which is strictly worse than the gap being filed.

Related

  • #16304 — the sibling finding, opposite direction, addressed by PR fix(pm): a legal exit for a card whose sibling carries the clause-② declaration #16832.
  • #14155 — the card that introduced the event-stream reading being asked for here.
  • #14965 — a related earlier reading that the machine check could not run in an MCP-only session at all; closed, and narrower than this, which is about the read remaining impossible after the tool grew its offline path.

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

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions