Skip to content

Commit 1c29ef7

Browse files
committed
fix(pm): the queue guard's remedy names the Merge button's bypass-rules option, and a pin reads the ruleset
The size limb (and the governed limb beside it) prescribed 人工直合 — "the maintainer's own click" — without naming which click. Ruleset `main` mandates the merge queue and lists this guard as a required context, so the only Merge that is not an enqueue is the Merge button's bypass-rules option, offered only while the ruleset configures a bypass actor. With none configured the remedy named a terminal nobody could reach: PR #19024 was enqueued three times and refused three times. The four remedy sentences (the header's and the three rendered ones) now name that option and keep 人工直合 as the NAME of the act. A new self-test battery judges the remedy text against a RECORDED reading of `GET /repos/objectstack-ai/objectstack/rulesets/12119582`: red when `bypass_actors` is present and empty, red when the remedy drifts back to a bare click, and a pass that PRINTS its reading when the field is unreadable — which is what every seat and Actions token gets, `administration` being outside the 17 permissions a workflow may grant. The reading is recorded rather than fetched because this self-test is the required guard job's first step and is declared offline; a live read would answer "unreadable" on every CI run, asserting nothing while adding a network dependency to a merge precondition. Claude-Session: https://claude.ai/code/session_017ETYWqMQD4qMtZzAGovWNi Co-authored-by: Claude <noreply@anthropic.com>
1 parent 23f1de0 commit 1c29ef7

1 file changed

Lines changed: 67 additions & 7 deletions

File tree

‎scripts/pm/check-governed-queue-guard.mjs‎

Lines changed: 67 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,13 @@
407407
* landed predicate says a human MERGE — 「人工审核」 landed as the same terminal
408408
* a governed diff has (ACCEPT on the card, `needs-user-decision` on the PR, a
409409
* final 维护者速读, review requested from `GOVERNED_APPROVERS`) and the
410-
* maintainer's own click (人工直合). An authorized APPROVED review lifts a
410+
* maintainer's own click (人工直合). ⭐ #19344 — THAT CLICK IS ONE BUTTON
411+
* OPTION and this text now names it: `main` mandates the queue and requires
412+
* this check, so the only Merge that is not an enqueue is the Merge button's
413+
* BYPASS-RULES option, offered only while the ruleset configures a bypass
414+
* actor. While none was, the remedy named a terminal nobody could reach and
415+
* PR #19024 was enqueued and refused three times. That it IS offered is a
416+
* ruleset fact the pin reads. An authorized APPROVED review lifts a
411417
* Tier H path because the 2026-08-27 ruling said so of PATHS; nothing has
412418
* said it of the NUMBER, and widening a governance gate past its own ruling is
413419
* how gates acquire policy nobody agreed to. Widening it is a one-line
@@ -547,11 +553,12 @@ const SELF_TEST_BATTERIES = Object.freeze({
547553
'⭐ #18020 → #19133 Tier S: a review of record, not an approval': 43,
548554
'⭐ #18701: the record lives on the PR or its card, and BOTH are read': 14,
549555
'⛔ #19036: the SIZE line at the queue — imported, per queued PR, fail-closed': 30,
556+
'⭐ #19344: the remedy names a path the ruleset actually offers': 5,
550557
});
551558

552559
// DELETING an entry silences that battery's floor exactly as effectively as
553560
// zeroing it, so the roster's own size is pinned too.
554-
const SELF_TEST_BATTERY_FLOOR = 22;
561+
const SELF_TEST_BATTERY_FLOOR = 23;
555562

556563
// The key an assertion is filed under when no battery is open. It is not a
557564
// declared battery, so it reds by the same set difference rather than silently
@@ -1376,8 +1383,9 @@ export function renderGuardVerdict(verdict) {
13761383
` ✅ What a seat DOES do once an account in GOVERNED_APPROVERS (${GOVERNED_APPROVERS.join(', ')}) has APPROVED it,`,
13771384
' on ANY commit: the CLAIMING SEAT lands it — ruling C (#17971, maintainer 2026-09-13, verbatim',
13781385
' 「C. approve 后不管后续改动都由席位落地:」), 「席位落地 = 过落地前检、清标、ready、',
1379-
' auto-merge,踢出/变基同法。」 Unapproved, the maintainer\'s own direct merge (人工直合) is',
1380-
' the only landing this pull request has.',
1386+
' auto-merge,踢出/变基同法。」 Unapproved, the maintainer\'s own direct merge (人工直合) is the',
1387+
' only landing this pull request has, and it IS the Merge button\'s bypass-rules option —',
1388+
' offered only while ruleset `main` configures a bypass actor (#19344).',
13811389
);
13821390
}
13831391
if (tierS.length > 0) {
@@ -1469,7 +1477,8 @@ export function renderGuardVerdict(verdict) {
14691477
' 要卡最新的提交。」); the authorized set is still the 2026-08-27 one (「os-zhuang hotlong 批准',
14701478
' 算数」). ⛔ An agent seat never submits that approval, under any account — the post-merge audit',
14711479
' reads the approver too. ⛔ Unapproved, the maintainer\'s own direct merge (人工直合) is the only',
1472-
' landing this pull request has.',
1480+
' landing this pull request has, and it IS the Merge button\'s bypass-rules option — offered only',
1481+
' while ruleset `main` configures a bypass actor (#19344); the audit log records it.',
14731482
);
14741483
if (verdict.entries.some((e) => e.record !== undefined)) {
14751484
lines.push(
@@ -1925,6 +1934,32 @@ export async function runSizeGuard({ event, rows, namedPull = null, fetchPull })
19251934
return sizeGuardVerdict({ event, pulls, readings, apiCalls });
19261935
}
19271936

1937+
// ── #19344: the remedy's terminal is a RULESET fact, so it is READ ─────────
1938+
//
1939+
// GitHub offers it only to an account ruleset `main` lists as a bypass actor,
1940+
// and `bypass_actors` is withheld below `administration`, so a read answers
1941+
// three ways and only ONE is a refusal. ⛔ Never assert a path from a field that
1942+
// was not read (a permission difference must not red CI), ⛔ never pass mute.
1943+
export const BYPASS_OPTION_PHRASE = "Merge button's bypass-rules option";
1944+
1945+
/** `offered` | `not-offered` | `unreadable`, with the words a log should carry. */
1946+
export function bypassActorReading(ruleset) {
1947+
const read = ruleset && typeof ruleset === 'object' ? ruleset : {};
1948+
if (!Object.prototype.hasOwnProperty.call(read, 'bypass_actors')) {
1949+
return { reading: 'unreadable', detail: `bypass_actors: unreadable with this token (the key is absent); current_user_can_bypass: ${JSON.stringify(read.current_user_can_bypass ?? null)}` };
1950+
}
1951+
const actors = read.bypass_actors;
1952+
if (Array.isArray(actors) && actors.length > 0) return { reading: 'offered', detail: `bypass_actors: ${actors.length} configured` };
1953+
return { reading: 'not-offered', detail: `bypass_actors: ${JSON.stringify(actors)} — nobody is offered the bypass-rules option` };
1954+
}
1955+
1956+
/** Two ways to red: the remedy stops naming a path (#19344's defect), or the ruleset is READ to offer none. */
1957+
export function remedyPathVerdict({ remedy, ruleset }) {
1958+
const names = remedy.includes(BYPASS_OPTION_PHRASE);
1959+
const { reading, detail } = bypassActorReading(ruleset);
1960+
return { ok: names && reading !== 'not-offered', names, reading, detail };
1961+
}
1962+
19281963
/**
19291964
* The words a reader acts on for this leg. Returns '' on the `pull_request`
19301965
* leg. Every entry prints WHAT WAS READ — the two numbers, their sum and the
@@ -2003,7 +2038,11 @@ export function renderSizeVerdict(verdict) {
20032038
' alone does NOT dequeue it) and park it there — parked outside the queue is the SAFE state.',
20042039
' 2. Then a HUMAN MERGE — the same terminal a governed diff has: ACCEPT on the card,',
20052040
' `needs-user-decision` on the PR, a final 维护者速读, review requested from GOVERNED_APPROVERS',
2006-
` (${GOVERNED_APPROVERS.join(', ')}); the maintainer's own click lands it (人工直合).`,
2041+
` (${GOVERNED_APPROVERS.join(', ')}); the maintainer's own click lands it (人工直合) — and that`,
2042+
' click is the Merge button\'s bypass-rules option, offered only while ruleset `main` configures a',
2043+
' bypass actor — ⛔ NOT a second Merge button: `main` mandates the queue and requires this check, so',
2044+
' with none configured every re-enqueue comes back here (#19344). The audit log records the bypass',
2045+
' and `check-governed-merges` lists such a landing on size.',
20072046
' ⛔ An authorized APPROVED review does NOT lift this limb the way it lifts a Tier H path, and no',
20082047
' review of record does either: the landed predicate says a human MERGE, and widening it is the',
20092048
' maintainer\'s one-line decision in the sibling, not this file\'s.',
@@ -3851,6 +3890,25 @@ export async function selfTest() {
38513890
assert('the-workflow-is-readable-for-the-size-scope-pin', false, String(error?.message ?? error).split('\n')[0]);
38523891
}
38533892

3893+
// ── ⭐ #19344: the remedy names a path the RULESET actually offers ────────
3894+
//
3895+
// RECORDED, not live: this self-test is the required guard job's FIRST step,
3896+
// declared offline, and a live read answers `unreadable` from every token CI
3897+
// can hold — a network dependency asserting nothing. ⛔ And a pinned phrase
3898+
// split across two wrapped array entries can never match: keep it on ONE.
3899+
battery('⭐ #19344: the remedy names a path the ruleset actually offers');
3900+
// GET /repos/objectstack-ai/objectstack/rulesets/12119582, read 2026-09-20 by
3901+
// an ordinary seat token: HTTP 200, and NO `bypass_actors` key at all.
3902+
const RULESET_19344 = Object.freeze({ id: 12119582, name: 'main', enforcement: 'active', current_user_can_bypass: 'never' });
3903+
const judgeRemedy = (remedy, over = {}) => remedyPathVerdict({ remedy, ruleset: { ...RULESET_19344, ...over } });
3904+
const sizeRemedy = renderSizeVerdict(overOne);
3905+
const recorded = judgeRemedy(sizeRemedy);
3906+
console.log(` ℹ #19344 ruleset reading — ${recorded.detail}`);
3907+
assert('⭐ all-four-remedies-NAME-the-bypass-rules-option-and-keep-人工直合-as-the-name-of-the-act', recorded.names && judgeRemedy(refusalText).names && judgeRemedy(warnText).names && sizeRemedy.includes('人工直合') && /BYPASS-RULES option/.test(sizeOwnSource), sizeRemedy);
3908+
assert('⛔ a-field-this-token-cannot-see-is-UNREADABLE-and-PASSES-asserting-no-path-it-did-not-read', recorded.reading === 'unreadable' && recorded.ok === true && /unreadable with this token/.test(recorded.detail), recorded.detail);
3909+
assert('⛔ bypass_actors-PRESENT-and-EMPTY-REDS-the-remedy-names-a-path-the-ruleset-does-not-offer', judgeRemedy(sizeRemedy, { bypass_actors: [] }).ok === false && judgeRemedy(sizeRemedy, { bypass_actors: null }).reading === 'not-offered');
3910+
assert('⭐ one-configured-bypass-actor-makes-the-named-path-REACHABLE-and-the-pin-clears', judgeRemedy(sizeRemedy, { bypass_actors: [{ actor_type: 'RepositoryRole', bypass_mode: 'pull_request' }] }).ok === true);
3911+
assert('⛔ and-a-remedy-drifting-back-to-a-bare-maintainer-click-REDS-even-where-the-path-IS-offered', judgeRemedy("the maintainer's own click lands it (人工直合).", { bypass_actors: [{ actor_id: 5 }] }).ok === false);
38543912

38553913
// ── the WIRING pin: the workflow still spells this context name ──────────
38563914
//
@@ -4443,7 +4501,9 @@ export async function selfTest() {
44434501
'on the governed code; an authorized approval lifting nothing from the size; a certified regeneration lifting ' +
44444502
'nothing from it either; an unreadable size or a pull object without the pair FAIL-CLOSED on exit 9; the ' +
44454503
'pull_request leg silent and read-free; and the three-leg exit precedence (governed, size, carrier) pinned on ' +
4446-
'every combination.',
4504+
'every combination — and the #19344 remedy pin: every limb names the Merge button\'s bypass-rules option, ' +
4505+
'judged against the recorded ruleset reading, red on a present-and-empty `bypass_actors` and on a remedy ' +
4506+
'drifting back to a bare click, and passing with the reading PRINTED when the field is unreadable.',
44474507
);
44484508

44494509
selfTestReachedVerdict = true;

0 commit comments

Comments
 (0)