From c8ec00b159201cd4bbd24ad2c46a837682aaa1f9 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 12 Sep 2026 05:55:00 +0000 Subject: [PATCH] fix(devx): pin `Governed Surface Queue Guard` as the seventh REQUIRED_CONTEXTS row The guard has been a live required context on `main` since 2026-08-27 and no registry row named it, so nothing made its check-run name load-bearing in a machine-checked way -- `--verify-required-set` read it as `direction B` every day since. Direction B is not #12427's direction A: that card fixed the guard running ADVISORY; this pins the NAME it is required under. Adding the row also makes the registry judge the workflow that publishes it, and that surfaced a live defect the row exists to surface: the guard's `pull_request:` trigger carries `branches: [main]`, the base-filter shape #16482 retired from `ci.yml` and `lint.yml`. A base-filtered trigger publishes no check run on a PR based on a feature branch -- an absence, not a skip -- so the one gate that governs the governed surface reports nothing there. That half is NOT fixed here; see the PR body. Carried with the row, because the registry derives both from it: - the readings ledger's `mustName` gains the seventh name (`--self-test` asserts it names every required context, so the count line alone is not what makes the seat's copy non-optional); - the self-test's workflow corpus is derived from the registry instead of a hand-listed pair, so a registered file can no longer go unread and report "never read" (#4690) through every fixture. Claude-Session: https://claude.ai/code/session_012GKcPZbMoGq7WPzKLfRBTU Co-authored-by: Claude --- .../references/platform-readings.md | 7 ++-- scripts/check-required-contexts.mjs | 36 ++++++++++++++++--- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/.claude/skills/pm-dispatch/references/platform-readings.md b/.claude/skills/pm-dispatch/references/platform-readings.md index 276786c4d0..1910db045c 100644 --- a/.claude/skills/pm-dispatch/references/platform-readings.md +++ b/.claude/skills/pm-dispatch/references/platform-readings.md @@ -376,9 +376,12 @@ - 强制档不得因不可用而降档 —— 那正是降档保险丝要拒的替换。 - 本车道强制多是过宽的回忆:`dispatch-gates.mjs --tier PATH` 逐路径现推,路径线是下限非放行。 - 该脚本只答自己那棵树:姊妹仓路径回 absent from this tree,姊妹仓的档位与条款②只能手推。 -- required checks 的名单是每仓事实,objectstack 六个: +- required checks 的名单是每仓事实,objectstack 七个: `TypeScript Type Check` · `Lint & Repo Gates` · `Test Core` · `Dogfood Regression Gate` · - `Build Core` · `Temporal Conformance (live PG + MySQL)`。 + `Build Core` · `Temporal Conformance (live PG + MySQL)` · `Governed Surface Queue Guard`。 +- 第七个 2026-08-27 入集(#12427),而注册表到 #15233 才钉住它。 +- ⭐ 本表的 `mustName` 不要求排他 ⇒ 第七个加注册行不会让本表变红。 +- ⇒ ⛔ 门绿不是本行已对的读数:计数行只能手跟改。 - `in_progress` 不是过;advisory 门禁红进 main 是共享损伤,照样止血立单。 - ⛔ 聚合命令同样不作判定:`check:type-check-debt` 可在包级 typecheck 绿时红。 - `check:i18n` 以 PREREQUISITE NOT MET(workspace CLI 未 build)退 3,不是漂移。 diff --git a/scripts/check-required-contexts.mjs b/scripts/check-required-contexts.mjs index 005a2d58bc..33a88e427d 100644 --- a/scripts/check-required-contexts.mjs +++ b/scripts/check-required-contexts.mjs @@ -423,6 +423,22 @@ export const REQUIRED_CONTEXTS = [ '2026-08-18 read, so it was applied somewhere between the two — no attestation names the day', carries: 'the live-server datetime conformance axis (#3912/#3942)', }, + { + workflow: 'governed-surface-guard.yml', + job: 'governed-surface-guard', + // The one gate that governs the governed surface, and until this row the + // one live required context nothing pinned — `--verify-required-set` read + // it as `direction B` (required, pinned by NO registry row) from the day + // the enrolment landed until this row (#15233). Direction B is not + // direction A: #12427 fixed the guard running ADVISORY (not required at + // all); this pins the NAME it is required under. Neither implies the + // other, and the sweep counts them separately. + context: 'Governed Surface Queue Guard', + authorized: + '#12427 maintainer confirmation, closed `completed` 2026-08-27T07:51Z on the verbatim 「Governed Surface Queue Guard 已添加」 (comment 5436049459); ' + + 'read back live in the ruleset sweep of 2026-09-10 that carries the director ruling enrolling this row (#15233)', + carries: 'the governed-surface refusal — the `merge_group` leg that refuses a governed diff carrying no ruled approval', + }, ]; /** @@ -548,6 +564,11 @@ export const INSTRUCTION_SURFACES = [ 'Dogfood Regression Gate', 'Build Core', 'Temporal Conformance (live PG + MySQL)', + // The seventh, enrolled 2026-08-27 (#12427) and pinned here by #15233. + // The ledger's own count line is hand-followed prose, so it is this + // array — asserted against REQUIRED_CONTEXTS.length in `--self-test` — + // that makes the seat's copy of the required set non-optional. + 'Governed Surface Queue Guard', ], }, { @@ -1703,10 +1724,17 @@ async function selfTest() { const root = scriptRepoRoot(); const { parse } = await requireDependency('yaml', () => import('yaml'), import.meta.url); - const sources = { - 'lint.yml': readFileSync(join(root, '.github', 'workflows', 'lint.yml'), 'utf8'), - 'ci.yml': readFileSync(join(root, '.github', 'workflows', 'ci.yml'), 'utf8'), - }; + // Every workflow the registry names, read from disk. A registered file left + // out here is not simply unexercised: `judge` reports it as never read + // (#4690), so EVERY fixture below inherits that finding and asserts against + // the wrong problem list. Derived from the registry so enrolling an eighth + // context cannot silently skip this step. + const sources = Object.fromEntries( + [...new Set(REQUIRED_CONTEXTS.map((e) => e.workflow))].map((file) => [ + file, + readFileSync(join(root, '.github', 'workflows', file), 'utf8'), + ]), + ); /** Judge the real workflows with one file's text replaced by `source`. */ const withSource = (file, source) =>