Skip to content

The clause-② gate has three limbs and all three were silent on PR #13910 at once — the dual-carrier label rule has no enforcement, and 4 of 6 measured pairs are out of sync #13922

Description

@os-warren

Filed by the triage seat while running the contract-review round of 2026-08-31. Measured across every open needs:contract-review pair in the repo, not sampled. Sibling of #13914, and strictly worse: #13914 records one limb failing; this records all three failing on the same PR simultaneously, which is a complete gate bypass rather than a redundancy loss.

The gate has three limbs

Per scripts/pm/ensure-pm-labels.sh, in its own words:

a PR whose ACTUAL diff touches the contract surface — or whose card's claim comment declares Clause-②: yes (the content limb, judged from the card, path-independent) — but was dispatched below the contract-review tier waits outside the queue under this label until the review sub-round clears it. Named consumers: the enqueue gate and the triage sub-round's label query.

So: ① path limb (diff under packages/spec/src/**) · ② declaration limb (Clause-②: yes in the card's claim comment) · ③ the label itself, on both carriers.

PR #13910 — all three silent, on a PR whose own author declared Clause-②: yes

limb reading on #13910 / card #13476
① path silent — 4 changed files, all packages/rest; nothing under packages/spec/src/**
② declaration silent — the claim comment (5480774192) contains no Clause-②: line at all
③ label silent on the PR — labels were documentation, size/m, tests, tooling; the card had it, the PR did not

And the PR body declares, verbatim:

Clause ②: yes

… the declared ADR-0112 code on a public door changes for a real deployment condition, so it is declared yes rather than talked down.

⇒ An author correctly identified their own change as clause-②, wrote it down, and not one of the three mechanisms that exist to catch that was in a state to fire. The PR is draft and unarmed and a human is in the loop, which is why nothing has gone wrong yet — but nothing in the gate was holding it.

⚠️ Sharper still: the card's PM review comment (5481513968) states, verbatim, "needs:contract-review on both carriers." The label was on one. The record asserts a sync that did not happen — so a reader auditing this by reading the thread would conclude the mechanism ran.

The dual-carrier rule has no enforcement at all

references/contract-review.md states it:

PR 与卡双载体同笔挂(维护者 2026-08-22:「简化一点是否可以直接挂 PR 侧」「两边都挂好」; PR 一存在即挂,报告先于 PR 到达则先挂卡侧、ACCEPT 时补齐 PR 侧

ensure-pm-labels.sh creates the label object (colour, description) and does nothing else. There is no check anywhere that a needs:contract-review on one carrier implies it on the other. The rule is prose, executed by hand.

Measured compliance: 2 of 6

Every open pair, 2026-08-31:

PR card PR side card side
#13870 #13576 in sync
#13834 #13651 in sync
#13829 #13578 card missing
#13857 #13608 card missing
#13864 #13657 card missing
#13910 #13476 PR missing, record claims both

All four gaps were repaired by hand in the same round. That repair is the point: a rule whose compliance is 33% and whose only remedy is someone noticing is not a mechanism.

Why this is p1 and #13914 is p2

The two failure directions are not symmetric.

  • Card side missing (3 cases) is a visibility failure. The named consumer "the triage sub-round's label query" reads the card; a card without the label is invisible to the review round and simply never gets reviewed. The PR still carries the label, so nothing enqueues.
  • PR side missing (1 case) is a fail-open. It is the carrier the enqueue gate reads, and on fix(rest): a data engine that cannot be RESOLVED no longer answers 403 FORBIDDEN (#13476) #13910 it was the only limb left — the other two were independently silent. Nothing was holding the door.

⇒ The direction that actually admits an unreviewed contract change was measured live, in the one case it occurred.

Another rule already depends on this label being truthful

references/contract-review.md:

重挂前先查裁决:闸门标签缺失 ⇒ 先 grep 卡评论找复审结论 —— PASS + 无标 + head 未动 = 已清标非被剥;head 后移或无结论才重挂

This recovery procedure reads "label absent" as probably cleared. At a 33% sync rate that inference is wrong more often than right: absent means "never synced" four times as often as it means "cleared". The recovery rule is sound; its premise has been falsified by measurement.

Remedies — not chosen here, ⛔ this card does not rule

  1. Make the sync mechanical. The pairing is already machine-derivable: a PR body's Fixes #NNNN / Closes #NNNN, or GitHub's own closed_by_pull_requests, which answered correctly for every one of the six pairs above. A gate that reads one carrier's label and asserts the other's is a small script and has no judgement in it.
  2. Collapse to one carrier. The maintainer's 2026-08-22 exchange shows this was already asked — 「简化一点是否可以直接挂 PR 侧」 — and answered 「两边都挂好」. ⚠️ Re-opening that is a maintainer call, not this card's; recorded only because it is the alternative that removes the sync problem instead of policing it.
  3. Close the ② limb too. The Clause-②: yes | no machine spelling is missing from the claim comment on 2 of 3 measured cards — the enqueue gate's predicate reads it there, and it is not there #13914 is that half. ⚠️ Fixing ② alone would not have caught fix(rest): a data engine that cannot be RESOLVED no longer answers 403 FORBIDDEN (#13476) #13910 — its claim comment has no clause-② line in any spelling — and fixing ③ alone would. They are independent; neither subsumes the other.

⛔ What this card should not become: a one-off repair of the four gaps. Those are already repaired. The defect is that they happened and that nothing would have reported them.

Refs

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions