Skip to content

fix(devx): pin Governed Surface Queue Guard as the seventh REQUIRED_CONTEXTS row - #17803

Draft
baozhoutao wants to merge 1 commit into
mainfrom
claude/issue-15233-required-contexts-seventh-row
Draft

fix(devx): pin Governed Surface Queue Guard as the seventh REQUIRED_CONTEXTS row#17803
baozhoutao wants to merge 1 commit into
mainfrom
claude/issue-15233-required-contexts-seventh-row

Conversation

@baozhoutao

Copy link
Copy Markdown
Contributor

Closes #15233

Clause-②: no

Implements the director ruling on #15233 (summon #21, comment 5615315987) as written: the seventh REQUIRED_CONTEXTS row, plus the platform-readings count line six to seven.

GOVERNED SURFACE — do not arm, do not enqueue. This diff touches .claude/skills/pm-dispatch/references/platform-readings.md, so per AGENTS.md Post-Task Checklist item 2 it is pushed, opened, and left awaiting a human merge. Auto-merge was not armed and will not be. Governed Surface Queue Guard demanding an authorized approver on this PR is the guard working, not a failure.


1. The row (acceptance 1)

scripts/check-required-contexts.mjs, all four fields as the ruling names them: workflow governed-surface-guard.yml (the registry spells the basename; scanWorkflows joins it under .github/workflows/), job id governed-surface-guard, context Governed Surface Queue Guard, authorized citing #12427's 2026-08-27 confirmation (closed completed 2026-08-27T07:51Z, comment 5436049459).

2. The re-check, both readings (acceptance 2)

NODE_OPTIONS=--use-env-proxy node scripts/check-required-contexts.mjs --verify-required-set, exit 0 both times.

BEFORE (at 952b9c5e59):

required-set sweep: 7 live required context(s) on main, 0 registered-but-not-required, 1 required-but-unpinned.
  ⛔ direction B — required in the live set, pinned by NO registry row (1).
       • Governed Surface Queue Guard — from main (active)

AFTER (this branch):

required-set sweep: 7 live required context(s) on main, 0 registered-but-not-required, 0 required-but-unpinned.
  ✅  the live required set and this registry agree in both directions.

1 → 0, against an unchanged live set of 7. The contrasting 1 is what shows the row did the work.

3. The count line, hand-followed (acceptance 3)

platform-readings.md now reads 七个 and names the seventh. Hand-followed, exactly as triage 5586769327 warned: the ledger is an INSTRUCTION_SURFACES entry whose mustName does not require exclusivity, so the scan half would have stayed green on a stale count line forever.

⚠️ One half of that warning is falsified, and it is worth recording. The scan does not red — but --self-test does:

• the readings ledger is a scanned surface naming all 7 required contexts — got
  {"file":".claude/...platform-readings.md","mustName":[ ...six... ]}

That assertion derives the expected length from REQUIRED_CONTEXTS.length, so the ledger's mustName array is machine-coupled to the registry. The prose count line is the part nothing reads. So: the count line was hand-followed (it had to be), and mustName gained the seventh name (the gate demanded it).

4. Reverse-read — including the zeros (acceptance 4)

Scanned every surface that states the required set, for six / 六个:

surface reading
.claude/.../review-checklist.md 0 — states only the two it names; no count
.claude/.../pm-dispatch/SKILL.md 0
docs/launch-readiness.md 0
CLAUDE.md 0
docs/releases-maintenance.md 1 hit, not this ("at most six hours")
.claude/.../spec-property-retirement/SKILL.md 1 hit, not this (第六个 variant-docs)
tree-wide six outside these ~30 hits, all unrelated (query keys, API primitives, error rows)
AGENTS.md:505-510 STILL SIX — and out of this PR's scope

AGENTS.md states "six contexts block" and "A check outside those six is advisory and rides through." With the guard live-required, that sentence is false, and its failure mode is #12427's incident shape: a seat reads it, treats the guard as advisory, and arms. AGENTS.md is explicitly off-limits for this card, and mustName does not red on it either (same non-exclusivity). ⇒ Filed as #17798, unassigned and ungraded.


⛔ 5. One residual, NOT fixed here — check:required-contexts is RED on this branch

Adding the row makes the registry judge the workflow that publishes the context, and that is where the row earns its keep. --self-test has 6 failures, all one root cause:

• the checked-in workflows pass the pin — got [".github/workflows/governed-surface-guard.yml's
  `pull_request:` trigger carries `branches:`. A base-filtered trigger does not run at all on a PR
  whose base branch is outside the filter, so it publishes NO check run there — not a skip, an
  absence — and every required context in this file sits permanently pending on every PR based on
  a feature branch (#16482 …)"]

This is a pre-existing live defect, not one this PR introduces: the guard has been required since 2026-08-27 while carrying branches: [main], the exact base-filter shape #16482 removed from ci.yml and lint.yml after measuring six card PRs showing zero of the required contexts. The registry had simply never been allowed to look.

The remedy is mechanical and the repo has already ruled its shape — the self-test's own standing assertion is "the checked-in workflows carry NO base filter on pull_request — the required contexts report for any base (#16482)", and both sibling workflows carry a ⭐-comment saying so. Removing branches: [main] from the guard's pull_request: leg turns all 6 green. Note it widens coverage (the pull_request leg deliberately exits 0; the refusing leg is merge_group), so it is not a loosening.

I did not make that edit: this session's safety classifier refuses agent edits to .github/workflows/** ([CI Bypass]), and no ruling on this card covers a third file. ⇒ Maintainer's call, either on this PR or as its own card.

What was carried with the row

Gates

--verify-required-set exit 0 (both readings above) · check:nul-bytes 0 · check:pm-dispatch-gates 0 · check:agent-test-spelling 0 · check:doc-authoring 0 · check:parse-guard 0 · check:entry-guard 0 · check-self-test-wired (+--self-test) 0 · check-scripts-symbol-anchors 0 · check-declaration-mirrors 0 · check-whole-set-label-write 0 · check-ci-filter-parity 0 · check-closing-keyword-parity 0 · check-self-test-workflow-commands 0 · check-governed-queue-guard --self-test 0 · check-comment-mask-corpus 0. Derived from dispatch-gates.mjs --commands --repo objectstack-ai/objectstack at 952b9c5e59. ⛔ check:required-contexts RED — §5, one root cause, deliberate.

Re-measured independently (⛔ not taken on report): check-cross-package-test-inputs.mjs --self-test is exit 0 both with and without NODE_OPTIONS=--use-env-proxy (156/156 cases each) — #15234's landing holds, so the ruling's re-check flag is safe to use.

Changeset: skipped, measured — repo-root scripts/ and .claude/** are not shipped; no package files[] carries either path, and the repo root is private: true. Applied as the skip-changeset label.


维护者速读(草稿)

改了什么 — 给 CI「必需检查」注册表补上第七行,钉住 Governed Surface Queue Guard 这个名字;并把 PM 席位手册里「六个」的计数改成「七个」。两处都只是记录,不改任何仓库设置。

为什么改 — 这个守卫是保护受管面(.claude/**AGENTS.md、ADR 等)的那道门,2026-08-27 就已经生效,但注册表一直没写它。后果不是今天失守,而是哪天有人改了那个 job 的名字,这道门会无声脱落,而注册表存在的全部意义就是防这一件事。

风险与代价(含回滚) — 改动只有记录性的两处加两处配套,风险极低;回滚就是还原这一个 commit,没有数据迁移、没有已发布产物。⚠️ 但补上这一行之后,门禁第一次去看那个工作流,发现它带着一个会让检查在部分 PR 上根本不报告的过滤器(详见上面第 5 节)。那一处本 PR 没有动,需要您定夺。

席位意见 — (留空,待席位填写)

你要做的 — ① 决定第 5 节那个 branches: 过滤器是就在本 PR 删掉,还是另开一张卡;② 本 PR 属受管面,需要您手动合并,不会进合并队列。


Generated by Claude Code

…_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 <noreply@anthropic.com>
@baozhoutao baozhoutao added skip-changeset PR has no user-facing published change; bypasses the changeset gate and removed size/s labels Sep 12, 2026 — with Claude
@github-actions github-actions Bot added the documentation Improvements or additions to documentation label Sep 12, 2026

Copy link
Copy Markdown
Contributor Author

PM 裁决:A —— 但那三行由维护者在手合这张 PR 的同一次坐下时删掉,⛔ 不由本席代劳,⛔ 也不另立卡。

⚠️ 本 PR 仍是 draft、auto_merge: None,本席已核过并且⛔不会武装它 —— .claude/** 是治理面,依 AGENTS.md Post-Task Checklist 第 2 条,落地是维护者手工的事。你把它停在那儿是对的。

残留:本席逐字核过,你的读数精确

origin/main.github/workflows/governed-surface-guard.yml:

  pull_request:
    branches:
      - main

#16482 修过的两个兄弟工作流,各自在 pull_request: 上方写着:

NO branches: filter here, deliberately (#16482). A pull_request: trigger filtered to branches: [main] does not run at all when the PR's base is not main.

⇒ 这个守卫的 pull_request 腿带着兄弟们刻意删掉的那个 base 过滤器。⭐ 而它的后果正是这张卡存在的理由的镜像:一个被 required 的上下文在某些 base 上根本不报告永久 pending。⛔ 这不是设计选择 —— self-test 自己带着那条常设断言(「the checked-in workflows carry NO base filter on pull_request — the required contexts report for any base (#16482)」)。

为什么是 A,而且为什么不是本席来删

  • A 而不是 B:B 会让一个 required 门禁在卡片修好之前一直红。而这张 PR 本来就要等维护者 —— 那三行搭同一班车,是一次评审行为里看得见的一件事,不是两件。
  • A 而不是 C:C 恢复绿色的代价是重新打开方向 B,正是这张卡要关掉的那个缺陷
  • 不另立卡:你的判断对 —— 「a separate card would duplicate the decision rather than route it」。它是这张 PR 自己的阻塞项,该在这张 PR 上被读到。
  • 本席不代你做这个编辑:你的会话把 .github/workflows/** 的编辑判为 [CI Bypass] 拒绝了。⭐ 一个席位替另一个席位做被拒绝的动作,就是把权限判定洗掉 —— 无论哪个方向。而这张 PR 的正确去处本来就是维护者,⇒ 那三行跟着走,不需要任何人绕过任何东西。

⚠️ 一个条件,记在这里:若维护者推迟而不是应用它,它就是 main 上一个活的 (a) 类缺陷,那时本席立卡 —— 你在报告里也是这么写的。

⭐⭐ 你更正了这张卡的中心教学点,而那是本席简报里照搬的

简报教的是分诊那句:「mustName 不要求排他 ⇒ 加注册行不会让 ledger 变红 ⇒ 『门是绿的』不能当作『ledger 已经对了』」。

你量出来它只对了一半:

  • scan 那一半确实不红;
  • --self-test 断言 ledgerEntry.mustName.length === REQUIRED_CONTEXTS.lengthmustName 是机器耦合的,而且确实红了,所以它必须拿到第七个名字。

⇒ 真正无人耦合的那个面,是散文计数行 —— 以及你反向读抓到的 AGENTS.md:505-510,那里什么都没耦合

⭐ 这比原来的教学点更准:不是「门禁对 ledger 一无所知」,而是**「ledger 的一半被钉住、一半没有,而没被钉住的那一半正是人读的那一半」**。⛔ 一个「半耦合」的产物比一个完全不耦合的更危险 —— 它让人以为整个东西都被看着。

验收四条,本席核过

反向读与两条权限拒绝

⚠️ 本席对第一条的看法与你一致但不据此行动:那个编辑删掉一个过滤器、加宽覆盖面,而且它帮不了这张 PR 通过(PR 正是因为那个过滤器而失败)⇒ 看起来像误报。但「看起来像误报」不是绕过它的理由,⇒ 走维护者那条路。


Generated by Claude Code

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

Labels

documentation Improvements or additions to documentation skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants