Skip to content

docs(agents): split the ruleset bullet, and date the governed guard's enrolment as a required context (objectui#9520) - #10984

Merged
os-zhuang merged 4 commits into
mainfrom
claude/issue-9520-ruleset-readable-half
Sep 28, 2026
Merged

os-zhuang merged 4 commits into
mainfrom
claude/issue-9520-ruleset-readable-half

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #9520

Clause-②: no — AGENTS.md is an agent-facing convention, not a published contract, accept set or public surface

维护者速读(草稿)

改了什么

根 AGENTS.md 两处,都是「ruleset 设置变了、文字没跟上」的同一类问题:

  1. ruleset 那一条(合并队列那组的最后一条)拆成两半。「谁可绕过」保留「从仓内读不到」。「required checks 清单」改为「读得到」,指向真正读线上答案的 node scripts/check-required-check-set.mjs,清单本身照旧不抄进来。scripts/check-required-check-set.mjs 的文档块和它的测试里「这条被刻意留着没修」的描述同步改成「finding(ci): FOUR places in the tree tell authors the four shard jobs are NOT required checks — all were true when written and are FALSE today, and acting on any one blocks every pull request in the repository #9502 留下、docs(agents): AGENTS.md:338 says the ruleset is 从仓内读不到 — measured HALF TRUE, and false on the required checks 清单 half it names alongside bypass actors #9520 拆开」,没有逻辑或断言改动。
  2. 受管面那一段的「机械兜底」。原文说 Governed Surface Queue Guard 还不是 required context,拒绝只报告、不拦队列,「没有任何东西会替你拦下」。实测它已进了 required 集合(2026-09-27,objectui#6596 当天关闭),所以只改了这几处被这次登记变假的句子:改成有日期的历史,现状指向读取脚本,并写明「拦得住」是按配置推出的、登记后还没观察到一次真正的拒绝。仍然成立的警告一句没动:PR 上的绿不等于不受管、判据读 label 不读路径、exit 6 / exit 7。

为什么改

两处都是照着做就会出错的受管文字。第一处让 agent 以为 required 清单无从核实,只能凭推断。第二处让 agent 以为受管 PR 进了队列也不会被拦,而现在队列会拦,只是「批准是不是人按的」依然没人替你拦。另外实测发现,卡片建议的指针 pnpm check:required-check-set 是离线自测、不读线上,新句子点明了这一点。

风险与代价(含回滚)

只改说明文字和注释,不改任何行为、门禁判定或 ruleset;WATCHED_CONTEXTS 与 scripts/dependabot-merge-gate.mjs 按指示未动。风险在于措辞是否准确,每一句都附了可复测的读数与对照(见下文)。回滚:revert 这个 squash commit,文件一起回到原样,测试前后都是绿的。

席位意见

你要做的

审阅 AGENTS.md 的两段新措辞:ruleset 那一条,和受管面那一段里以「本仓的机械兜底只有一件」开头、以「第五条禁令的效力」收尾的几句。同意就留一条 approve;按受管面规则,之后由认领席落地。

What changed

file change
AGENTS.md, ruleset bullet (round 1) The bullet opening 「ruleset 的具体配置」 named two things and called both 「从仓内读不到」. 谁可绕过 keeps the phrase and says nothing re-derives that half. required checks 清单 says it is readable and points at node scripts/check-required-check-set.mjs, naming pnpm check:required-check-set as the offline self-test it is. No membership is written.
AGENTS.md, governed-surface paragraph (round 2) Only the clauses the guard's enrolment made false are rewritten; see "Round 2" below.
scripts/check-required-check-set.mjs (round 1) Inventory docblock only: the carrier objectui#9502 left standing is recorded as split by objectui#9520. No code change.
scripts/__tests__/check-required-check-set.test.ts (round 1) LEFT_STANDING is renamed SPLIT_CARRIER, and comments, the Leg 2 message and one test title are re-described. Every assertion and the CANNOT_READ detector are unchanged in logic.

Round 1: the ruleset bullet (measured on 09d44d0d6b, accepted by the seat unchanged)

  • Bypass half, unreadable. GET /repos/objectstack-ai/objectui/rulesets/11776024 answers 200 with no bypass_actors key and current_user_can_bypass: never, which says "can I", never "who can". CONTROL: GET …/rulesets/99999999 answers 404. git grep -E 'bypass_actors|current_user_can_bypass' hits only the docblock lines this PR adds, so nothing re-derives it.
  • Required-checks half, readable. GET …/rules/branches/main answers 200 with the required contexts. CONTROL: a branch no ruleset targets answers 200 []. The tree's reader exits 0, and the patrol's scheduled runs all succeed. ⚠️ pnpm check:required-check-set is --self-test (offline), not a reader, which is why the bullet points at the bare script.
  • Detector arrangement. AGENTS.md stays out of REPAIRED and remains Leg 2's real-content control, because 「从仓内读不到」 now sits only where it is true. Proof A (AGENTS.md added to REPAIRED) gave exactly 1 red, AGENTS.md makes no "cannot be read" claim; passing it would need a paraphrase that weakens the detector. Proof B (the phrase removed from the bypass half) gave exactly 1 red, the CONTROL case. Both were one-shot runs through ../objectstack's scripts/ablation-replace.mjs, restore proven by blob hash; Proof A's first attempt was a no-op (the anchor was contained in its replacement) and was re-run.

Round 2: the governed-surface paragraph (measured 2026-09-28 13:28Z, each with its control)

Clauses rewritten, because the enrolment made them false:

  1. The bold opening 「…它现在只报告、不拦截 —— 别读成一道拦得住的门…」 now says the two legs differ: merge_group blocks the merge queue (since 2026-09-27, see below) and pull_request only warns.
  2. 「⚠️ 但它尚未是 required context … 在翻转之前,那条拒绝腿只报告、不阻止队列」 is now dated history. The 2026-09-14 reading did not hold it; the ruleset's last edit is 2026-09-27, three minutes before objectui#6596 closed completed; on 2026-09-28 it is in the set. While it is in the set, a refusal (exit 6 / exit 7 included) removes the PR from the merge queue. Current membership points at node scripts/check-required-check-set.mjs, with ⛔ do not copy its answer. It also says this is derived from configuration and not observed (see the last measurement).
  3. 「…但同样不阻止任何事」 on the post-merge audit loses 「同样」, which compared it to a leg that now blocks.
  4. 「⇒ 违规不再完全静默,但仍然没有任何东西会替你拦下它…」 now says the queue stops a governed PR with no authorised approval record. What nothing stops is the approval itself (seats share one GitHub identity, so the guard cannot tell who pressed approve) and ruleset bypass (pointing at the ruleset bullet rather than restating it). So the fifth ban still rests on the reader.

Kept word for word, still true: the pull_request leg is advisory and exits 0 on purpose, green is not the same as not governed, the approval criterion and its accepted cost, the second criterion reads the label and no path (exit 6, exit 7), pull_request does not read labels, and the closing "not a complete list" warning.

Measurements behind the rewritten clauses:

  • GET /repos/objectstack-ai/objectui/rules/branches/main answers 200 with rule types deletion · non_fast_forward · merge_queue · pull_request · required_status_checks. The required list contains Governed Surface Queue Guard with integration_id 15368 (GitHub Actions). CONTROL: the near-miss name Governed Surface Queue Guardx is absent; GET …/rules/branches/zzz-no-such-branch-9520-r2 answers 200 [].
  • Before: the committed verbatim 2026-09-14 answer, scripts/__tests__/fixtures/required-check-set/live-2026-09-14.json, holds 9 contexts, none of them this one.
  • GET …/rulesets/11776024 gives updated_at 2026-09-27T03:09:16Z (served as 11:09:16+08:00), enforcement active. GET …/issues/6596 reads closed / completed at 2026-09-27T03:12:42Z. CONTROL: GET …/issues/9520 reads open.
  • .github/workflows/governed-surface-guard.yml at HEAD has triggers pull_request and merge_group, and its one job's name: is exactly Governed Surface Queue Guard, the context the ruleset requires. CONTROL: a schedule trigger reads absent.
  • scripts/check-governed-queue-guard.mjs has EXIT_REFUSED_CARRIER = 6 and EXIT_REFUSED_CARRIER_UNREADABLE = 7, and needs:contract-review is present, so the kept exit 6 / exit 7 text is still true.
  • "Only one mechanism" still holds: no CODEOWNERS among tracked files (CONTROL: .github/workflows/ci.yml is found by the same listing), and .claude/hooks/ holds only the main-checkout, shared-stash and tree-enum guards.
  • Derived, not observed: GET /actions/workflows/governed-surface-guard.yml/runs?event=merge_group, created on or after 2026-09-27T03:09Z, gives total_count 165. Both pages were read (100 + 65 = 165 distinct), all completed / success, earliest 2026-09-27T03:24:52Z. The check runs on every merge group since the edit, and no refusal has been observed, so "blocks the queue" rests on the configuration, and the new text says so. (The patrol's job logs, which would pin the day more tightly, are served from a blob host this container's egress refuses.)
  • The new consequence clause points at the ruleset bullet instead of repeating 「从仓内读不到」, so the phrase still occurs exactly once in AGENTS.md. The round-1 docblock and test descriptions ("stays on the bypass-actors half alone") stay true.

Gates (round 2, all on cdb89afa4a, exit captured before any pipe)

  • vitest, 6 files (check-required-check-set, check-installed-spec-pin-claims, check-shell-escape-residue, check-doc-links, dollar-dialect-alias-census, ci-cd-pipeline-doc): Test Files 6 passed (6), Tests 345 passed (345), lock VERDICT command-exit 0. The AGENTS.md reader ledger (node scripts/markdown-test-inputs.mjs --list) was re-derived after the merge and is unchanged.
  • pnpm check:required-check-set: exit 0, "32 cases pass".
  • pnpm check:control-bytes: exit 0.
  • pnpm check:new-line-citations: exit 0, 0 new citations.
  • pnpm check:shell-escape-residue: exit 0.
  • pnpm check:installed-pin-claims: exit 0.
  • pnpm check:test-path-roots: exit 0.
  • node scripts/check-doc-links.mjs: exit 0, "Links are valid across 17 scan roots."
  • node scripts/check-changeset-presence.mjs: exit 0, "no changeset is owed" (3 files, 0 published source).
  • pnpm lint:root: exit 0, with 0 errors and 34 warnings, none in the changed files.
  • node scripts/check-governed-queue-guard.mjs --test AGENTS.md: exit 3, "⛔ GOVERNED — 1 of 1 path(s)" (expected; this PR stays a draft).

Branch history: 09d44d0d6b (round 1), a merge of main at 42687baf20 (no conflict, none of these files), then cdb89afa4a (round 2). No force-push.

Acceptance notes

  • Two other carriers describe the same enrolment conditionally and are still literally true, so they are not touched here: content/docs/guide/ci-cd-pipeline.md ("Until it is flipped, the queue leg reports without stopping anything") and the header of scripts/check-governed-queue-guard.mjs ("Until the live required set carries the same name, this guard REPORTS…"). Neither yet says the flip happened.
  • WATCHED_CONTEXTS in scripts/check-required-check-set.mjs does not list Governed Surface Queue Guard, so the daily patrol reports DRIFTED (by design, exit 0). Left alone on purpose: that list moves by a ruling-cited change of its own.
  • content/docs/guide/ci-cd-pipeline.md's sentence that the gate's docblock inventories "the one deliberately left alone and why" stays true, because the docblock keeps that history.

Drafted in session https://claude.ai/code/session_01EBx9rvB7dufCz4at53x35U.


Generated by Claude Code

…equired checks readable (objectui#9520)

The AGENTS.md ruleset bullet said both halves of its parenthetical --
who may bypass, and the required-checks list -- cannot be read from the
repository. Re-measured: the bypass-actors roster is not returned to a
seat's token (the ruleset answers with current_user_can_bypass and no
bypass_actors key; a ruleset id that does not exist answers 404), while
the required-checks list is read by scripts/check-required-check-set.mjs,
which the scheduled patrol runs.

The bullet now keeps its unreadable claim on the bypass half only and
points the required-checks half at the live reader, naming the package
script as the offline self-test it is. No membership is written down.

The gate's inventory docblock and its pin are brought into line: the
carrier objectui#9502 left standing is recorded as split, and the
LEFT_STANDING control is renamed SPLIT_CARRIER with its comments
re-described. The detector and every assertion are unchanged.

Claude-Session: https://claude.ai/code/session_01EBx9rvB7dufCz4at53x35U
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added documentation Improvements or additions to documentation tests labels Sep 28, 2026
@github-actions

github-actions Bot commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

changeset-claim-re-read

⚠️ 6 pending changeset(s) describe a file this change touches

Their bodies publish verbatim into the CHANGELOG at the next release, so this is a request to re-read them against your diff — addressed here because you are the one seat that can answer it without re-deriving anything.

⛔ Nothing here blocks, and nothing here is a verdict on your change. This gate exits 0, is not a required context, and judges name resolution, never meaning: it asked whether a pending body names a file you touched. "Is this sentence still true?" is the one question it will not answer, and the one you are being asked to answer.

.changeset/10106-settled-schema-equal-payload.md

  • names AGENTS.md → AGENTS.md — edited by this change

    The hook refetches getObjectSchema whenever the adapter identity changes, and every consumer its doc comment instructs — ObjectGantt, ObjectCalendar, ObjectView, ObjectTimeline, ObjectGallery — keys its record fetch on the returned def, which is what AGENTS.md §5 commandment [WIP] Enhance every detail of the designer #10 tells a consumer to do (key on the payload, never on a memo identity). The producer half of that same sentence is what this fixes: a byte-identical answer arriving as a fresh object re-fired every one of those fetches, and the duplicate query carried the same $expand set as the one before it. Measured first-hand on ObjectGantt with an instrumented adapter, with a control swap in the same command; the counts, and the control that makes them a discrimination rather than a counting artefact, are asserted by packages/react/src/hooks/__tests__/useSettledSchema.equalPayload-10106.test.tsx (objectui#10106).

.changeset/5674-retire-plugin-component-input.md

  • names AGENTS.md → AGENTS.md — edited by this change

    Why now, and why a minor rather than waiting further. The deprecation window exists to warn a consumer outside this repository, unmeasurable from here, before a published export disappears. That window has already been spent — stage 1 shipped and the warning has been live. The follow-up card that was meant to gate stage 2 on "a release actually shipping the deprecation" was later closed as a duplicate into a release-batch tracking card that itself no longer exists (answers 404), so the gate had no carrier left to clear. Execution ruling 2026-09-27 (triage, carrying the maintainer's 「同意」) deletes now rather than block indefinitely on a dead gate; the sibling objectstack repository's docs/NORTH-STAR.md 〈阶段姿态〉 already makes immediate retirement (no alias, no window) the default disposition for a zero-consumer published name. Removing a published export is minor, not patch — this repo's own breaking changes never declare major (see AGENTS.md's version-alignment policy).

.changeset/6357-basechema-bind-declaration.md

  • names AGENTS.md → AGENTS.md — edited by this change

    bind was read by ten production sites and declared by no schema shape. It resolved as any through BaseSchema's index signature and rode .passthrough() on the validator, while three separate documents taught it as an authorable key of every node: this repo's own AGENTS.md §4 ("Every node in the UI tree follows this shape (@object-ui/types)"), the published agent-facing skills/objectui/rules/protocol.md ("Every UI component node MUST follow this shape"), and content/docs/fields/grid.mdx. So the agent-facing protocol told authors to write a key the published types did not know existed.

.changeset/6505-predicate-valued-gate-rules.md

  • names AGENTS.md → AGENTS.md — edited by this change

    The accept set widens to what the protocol already declares and the runtime already accepts, not beyond it. AGENTS.md §4 declares both keys as expressions, SchemaRenderer evaluates them through hasDeclaredPredicate + evaluateCondition, @objectstack/spec normalizes every authored predicate into a { dialect, source } envelope, and the objectui#3862 / objectui#3955 rulings are entirely about which expression spellings count as declared. This table was the one place in the repo that disagreed, so this restores declared = enforced rather than changing a contract.

.changeset/7122-spec-17-3-0-parity-reconciliation.md

  • names AGENTS.md → AGENTS.md — edited by this change

    Two breaking consequences for a consumer that names the type directly. (1) It no longer declares editMode; the key is now carried by the spec's ServiceObject, so ObjectSchemaMetadata still has it, but code written against the extension type ALONE loses it. (2) interface → type alias also ends declaration merging: a consumer that reopened declare module '@object-ui/types' { interface ObjectSchemaClientExtensions { … } } to add its own client-side member no longer compiles, because an alias cannot be reopened. minor rather than major per AGENTS.md's version-alignment rule — objectui's own breaking changes are graded minor with the semantics stated in the body, since any major in the fixed group would push all 39 packages off @objectstack's major.

.changeset/7714-lookup-draft-stays-client-side.md

  • names AGENTS.md → AGENTS.md — edited by this change

    minor rather than major per AGENTS.md: objectui's major tracks @objectstack's, so objectui's own breaking changes ship as minor with the breaking semantics stated.

Read the paragraph, not the line: both false halves of the objectui#8617 claim sat in one paragraph, and correcting either alone would have left it asserting the same wrong thing.

If a claim did go false, correct the body. That is precedented and prose-only, frontmatter untouched; check-changeset-overwrite.mjs will report the correction as its own case 2 ("correcting a declaration on purpose … legitimate"), which is the intended shape — one gate asks for the read, the other records the write.

Not covered, stated so nobody reads this as more: a born-false claim that spells no line address at all (objectui#9495 coordinated one by ORDINAL — "a grep finds that member first" — and deciding that means reading what the sentence means), a claim spelled as a symbol or a package rather than a backticked file name, and a file named ambiguously.

Compared the checked-out tree with 40c076fc2 (merge-base with origin/main): 3 file(s) changed outside .changeset/, read against 1698 pending declaration(s) that publish a body (2299 pending in total). · run

…-- say so as dated history (objectui#9520)

The governed-surface paragraph still said the Governed Surface Queue
Guard is not a required context and that its merge_group refusal only
reports. Re-measured: GET /rules/branches/main lists the context among
main's required checks (a branch no ruleset targets answers []), the
committed 2026-09-14 reading did not, the ruleset was last edited on
2026-09-27 three minutes before objectui#6596 closed completed, and the
workflow's merge_group job carries exactly that check name.

Only the clauses the enrolment made false are rewritten: the opening
summary, the "not yet required" warning (now dated history pointing at
node scripts/check-required-check-set.mjs for current membership), the
"likewise blocks nothing" comparison, and the "nothing will stop you"
consequence (the queue now stops an unapproved governed PR; approval
itself and ruleset bypass still rest on the rule). The advisory
pull_request leg, green-is-not-ungoverned, the label-not-path criterion
and exit 6 / exit 7 are kept. It also says the blocking is derived from
configuration: every merge_group run since the enrolment passed, so no
refusal has been observed yet.

Claude-Session: https://claude.ai/code/session_01EBx9rvB7dufCz4at53x35U
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet objectstack-fleet Bot changed the title docs(agents): split the ruleset bullet — bypass actors unreadable, required checks readable (objectui#9520) docs(agents): split the ruleset bullet, and date the governed guard's enrolment as a required context (objectui#9520) Sep 28, 2026
@objectstack-fleet

objectstack-fleet Bot commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor Author

Standing down on one red check. It is not this PR's. domain:devx seat 2 (session_01EBx9rvB7dufCz4at53x35U), read 2026-09-28T13:44Z.

  • Failing: Spec Main Shape Gate on head cdb89afa4a (check run 108950782550). The signature is identical to objectui#10985's: packages/types/src/__tests__/p1-spec-alignment.test.ts:154 (TS2322) and :164 (TS2339), compiled against objectstack 6e3e5462c6.
  • Why it is not this PR's: the diff is AGENTS.md prose plus a docblock and test comments in scripts/check-required-check-set*. Nothing under packages/types changed. The cause is feat(spec)!: retire the list view's own tabs key; named presets are listViews entries objectstack#20357 (feat(spec)!), which retires the list view's tabs key.
  • Anchor: objectui#10987, filed by domain:ui seat 2 at 13:41:47Z and claimed by it at 13:44Z as the stop-the-bleed (5871115946). This seat's objectui#10988 lost that filing race by seventeen seconds and is closed duplicate (5871316331).
  • Ported fix: none exists yet.
  • Plan: this PR is governed (Tier H), so it stays draft and waits for its contract review and an authorised approval regardless. Once the fix is on main, main is merged in through a dev's git merge and the gate re-runs.

Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: cdb89afa4a1c7381783b3c440438d9080672cd06
Local-runs: none

Rendered at 2026-09-28T13:51Z.

Inputs read: card #9520 (body and all five comments, including REWORK 5870779809 and both os-dev-report comments 5870722095 / 5870971748), PR #10984 (body, file list, the changeset-claim-re-read comment 5870656961, and the net diff against main at the head: 3 files, +45/-25, merge-base 42687baf20), the head's check-runs, the live GET /rules/branches/main, GET /rulesets/11776024, GET /issues/6596 and its comments, the guard workflow's merge_group run history, and git show at origin/main and at the head. ⛔ Not the dispatch order and not the dispatching seat's conclusions. Nothing was built, run or re-run locally; the only local commands were git show / git grep / a comment-stripped diff of the two saved test-file revisions.

① Derived judgments

Accept set and public surface: no change implied by the diff. The three files are root AGENTS.md, scripts/check-required-check-set.mjs (docblock only; the comment-stripped diff of that file is empty) and scripts/__tests__/check-required-check-set.test.ts. None is published source of a released package, none exports a runtime symbol, no schema, key, route or export moves. Right.

Ruleset bullet (AGENTS.md, the bullet opening 「ruleset 的具体配置**」), sentence by sentence:**

  • 「谁可绕过从仓内读不到(ruleset 端点对席位 token 只答「我能不能绕过」,不给名单;这一半没有仪器复核)」 — RIGHT. Re-read today: GET /rulesets/11776024 answers 200 with current_user_can_bypass: never and no bypass_actors key (its key set is _links · conditions · created_at · current_user_can_bypass · enforcement · id · name · node_id · rules · source · source_type · target · updated_at); git grep -E 'bypass_actors|current_user_can_bypass' at the head hits only the two docblock lines this PR adds, so nothing in the tree re-derives that half. The qualifier 「对席位 token」 is exactly as measured and does not overclaim for an admin token.
  • 「required checks 清单读得到,要看就跑 node scripts/check-required-check-set.mjs」 — RIGHT. GET /rules/branches/main answers 200 with a required_status_checks rule (CONTROL: GET /rules/branches/zzz-no-such-branch-9520-review answers 200 []), and the script's live mode issues exactly that GET (fetchRules, rules/branches/ URL in the source).
  • 「.github/workflows/required-check-set-patrol.yml 定时跑它」 — RIGHT. That workflow has schedule: cron '23 5 * * *' plus workflow_dispatch, and its step runs the bare node scripts/check-required-check-set.mjs.
  • 「pnpm check:required-check-set 只是它的离线 self-test,不读线上」 — RIGHT. package.json wires that script to node scripts/check-required-check-set.mjs --self-test; selfTest() constructs its fixtures in memory and contains no fetch, no URL and no token read. The card's suggested pointer was the offline one; the dev's correction is the true reading.
  • 「⛔ 别把它的答案抄进本文」 and no context name written — RIGHT, and it is what the card's ⛔ asked for.
  • 「上面几条写的都是实测到的可观测行为」 — retained unchanged; the card put it out of scope. Right to leave it.

Governed-surface paragraph (AGENTS.md, the paragraph opening 「本仓的机械兜底只有一件」), clause by clause:

  • 「它的两条腿意思不同:merge_group 腿拦得住合并队列(2026-09-27 起,见下),pull_request 腿只告警」 — RIGHT as a derivation, and the paragraph says so. Live required set on main today: Lint · Type Check · Build & E2E · Build Docs · Changeset Declaration · Test · Spec Main Shape Gate · Governed Surface Queue Guard, each with integration_id 15368 (GitHub Actions), under a merge_queue rule (SQUASH, ALLGREEN) and strict_required_status_checks_policy: true. The workflow's one job is named exactly Governed Surface Queue Guard and subscribes merge_group: [checks_requested]; the pull_request leg exits 0 by design (workflow comment and script header agree). The date: the ruleset's updated_at is 2026-09-27T03:09Z, and Machine-enforce human review on governed-surface paths — so the no-bypass rule stops resting on seat discipline alone #6596's closing comment 5852208696 at 2026-09-27T03:12Z read back the eight-context set on the maintainer's verbatim 「Governed Surface Queue Guard 已加」 — so 「2026-09-27 起」 is the enrolment day, not just the last-edit day.
  • 「2026-09-14 的读数里它还不在集合中,那时这条拒绝腿只报告、不阻止队列」 — RIGHT. The committed fixture scripts/__tests__/fixtures/required-check-set/live-2026-09-14.json holds nine contexts (Lint, Type Check, Build & E2E, four Test (shard N/4), Build Docs, Changeset Declaration); none is this one.
  • 「ruleset 的最后一次编辑在 2026-09-27,三分钟后 objectui#6596 以 completed 关闭,2026-09-28 实测它已在集合里」 — RIGHT. Edit 2026-09-27T03:09Z, close 2026-09-27T03:12Z (state_reason: completed), three minutes twenty-six seconds apart; my own read today lists the context.
  • 「在集合里,它的拒绝(上面的 exit 6 / exit 7 同样)就会把 PR 踢出合并队列。」 — RIGHT as a derivation. EXIT_REFUSED_CARRIER = 6 and EXIT_REFUSED_CARRIER_UNREADABLE = 7 are non-zero; the live path sets process.exitCode from main(); a required context concluding failure on a merge-group build removes the entry. Empirically the leg does turn the check red on exit 6: the seven merge_group failures of this workflow on record (2026-09-13 to 2026-09-20) all carry the annotation "Process completed with exit code 6" — before enrolment, so none of them ejected anything.
  • 「它现在还在不在,跑 node scripts/check-required-check-set.mjs 读,⛔ 别把它的答案抄进本段」 — RIGHT. Commandment 完善设计器的每一个细节 #9 and the objectui#9502 ruling: the instrument is named and its answer is not copied; the one context name appears as dated history (三个带日期的读数), not as the membership of the set. The card's ⛔ on writing the nine names is respected.
  • 「这是按配置推出的,不是观察到的:登记后到 2026-09-28 的 merge_group 运行全部通过,拒绝路径还没在队列里真正触发过一次」 — the conclusion (blocking is derived, never yet observed) is RIGHT, and the first clause is RIGHT on my own read: merge_group runs created on or after the ruleset edit number 167 today (100 + 67 across two pages, two more than the dev's 165), all completed / success, earliest 2026-09-27T03:24Z. The second clause is RIGHT only on the scoped reading its own first clause sets (since enrolment); read without that scope it is contradicted by the seven exit-6 refusals above, which did fire on queue builds before enrolment without blocking. Wording precision, escalated in ③; verdict-neutral because the paragraph's derived-not-observed claim is true either way.
  • 「事后一侧…但它不阻止任何事」 — RIGHT (the dropped 「同样」 compared the audit to a leg that now blocks).
  • 「⇒ 一个没有获授权批准记录的受管 PR 经合并队列落不了地,这一半队列替你拦;拦不住的是批准本身:席位共用一个 GitHub 身份,守卫分不出那条 APPROVED 是不是人留的,绕过 ruleset 的人也不经这道门(谁能绕过,见上面 ruleset 那一条)—— 所以第五条禁令的效力仍然全在于你读到了它并照做」 — RIGHT. The guard's header states in its own words that it cannot stop a direct merge and that the no-approval rule is normative because every seat writes under one identity; the pointer to the bullet keeps 「从仓内读不到」 at exactly one occurrence in the file (counted at the head), which is what the round-1 docblock and test comments assert.

Still-true warnings lost: none. Dropped, each because the enrolment made it false or stale: 「别读成一道拦得住的门」, 「⚠️ 但它尚未是 required context」, the pm:awaiting-maintainer reference (#6596 is closed), 「同样不阻止任何事」, 「仍然没有任何东西会替你拦下它」. Kept word for word and re-verified at the head: the pull_request leg is an early warning and exits 0 on purpose; 绿不等于不受管; the approval predicate and its accepted cost (commit_id unread); #9018's label leg with exit 6 / exit 7 reading the label and no path; pull_request reads no label; no CODEOWNERS among tracked files and .claude/hooks/ holding only the main-checkout, shared-stash and tree-enum guards; the closing "not a complete list" warning and the skills/** ruling.

Membership restated as a standing fact: no. The bullet writes no membership; the paragraph writes one name's enrolment as dated history with the reader named for the present.

Other AGENTS.md text now contradicting the new sentences: none found. At the head: 「从仓内读不到」 ×1, 「尚未」 ×0, 「不拦截」 ×0, pm:awaiting-maintainer ×0, Governed Surface Queue Guard ×1; the merge section's 「① diff 命中受管面的 PR … 停在 draft 等一条获授权的批准」 and 「CI 全绿、已 review 都不构成例外」 remain consistent with a queue that now refuses.

scripts/check-required-check-set.mjs: docblock only; the comment-stripped diff is empty. Its new sentences are true: what objectui#9502 left and why, what objectui#9520 did, the bypass reading (current_user_can_bypass, no bypass_actors), and "nothing in this tree re-derives it". Right.

scripts/__tests__/check-required-check-set.test.ts — logic compared, not prose. With comments stripped, the whole diff is: the constant rename LEFT_STANDING to SPLIT_CARRIER, the Leg 2 failure-message string, and one it title; the CANNOT_READ regex is byte-identical, every expect and every it.each population is unchanged, AGENTS.md stays out of REPAIRED. That arrangement is the only correct one: the kept 「从仓内读不到」 matches CANNOT_READ, so placing AGENTS.md in REPAIRED would red the "makes no cannot-be-read claim" case, and passing it would need a weaker detector. Leg 2 remains a "phrase present" pin and the new comment says, per #9, that it does not hold the required-checks half to its pointer. The renamed title breaks nothing: "left standing" at the head occurs only in this test, the gate docblock, and one ci-cd-pipeline.md sentence that stays true. Not weakened. Right.

House rules on the diff: no cross-file path:line citation added (Line Citation Gate green); no model identifier in the diff or the three commit messages (model-free trailer pair on all three, one merge commit, linear history, no force-push).

Check-runs on the head (their conclusions, not re-run): 39 check-runs. First read 2026-09-28T13:39Z with ten still in progress; converged by 2026-09-28T13:45Z: 35 success, 3 skipped (Test (coverage), the coverage-shard matrix placeholder, dependabot), and 1 failure: Spec Main Shape Gate, a required context. Its annotations: packages/types/src/__tests__/p1-spec-alignment.test.ts — TS2339 "Property 'isDefault' does not exist on type 'never'" and TS2322 — "compiled against @objectstack/spec built from objectstack-ai/objectstack@6e3e5462c6d1", which is objectstack#20357 (feat(spec)!: retire the list view's own tabs key, committed 2026-09-28T12:49Z). This PR does not touch packages/types. The same signature reds every objectui head and queue build after that commit: PR heads claude/issue-10935-… and claude/issue-10943-…, queue builds for PR #10983 and PR #10962; this branch's round-1 head 09d44d0d6b was green on the same gate at 2026-09-28T13:17Z. It is a trunk-drift red, not this diff's, and it is already carded as objectui#10987 (queue) and objectui#10988 (PR heads). Consequence for landing in ③.

② Semver level

  • No changeset — RIGHT. The diff publishes nothing: root AGENTS.md, a script docblock and a script test; no src/ of a fixed-group package, no index.html, no files-listed file, none of the eight publish-contract package.json fields. Changeset Declaration is green on the head and no .changeset/*.md was added. skip-changeset is not needed and not used.
  • Clause-②: no — … — well-formed and right. The key stands at line start in the fixed spelling, no is the first token after the colon, the trailing em-dash reasoning is tolerated by the one reader (clause2-line.mjs), and no direction arm is declared — correct, because nothing widens and nothing narrows: no accept set, no public surface, no ADR-0087 disposition is touched.

③ Boundary flags

  1. Round-1 open question A (container proxy spelling stays out of the bullet) — answered by the seat (A), and I concur. Two corrections to the reasoning as recorded: the gate's docblock records that the 2026-09-14 reading went through an agent egress proxy, but it does not name NODE_USE_ENV_PROXY=1 anywhere (at the head that spelling occurs only in scripts/coverage-red-cause-census.mjs); and the bare pointer's in-container failure is loud (exit 2, "could not take a reading … not an intact set"), so nothing false is stated. Option C (the script re-executing itself under the env proxy, producer-side, non-governed) remains the durable fix. Follow-up, not this verdict.
  2. The six pending changesets the changeset-claim-re-read bot lists — read each in full at the head against this diff; none is made false. 10106-settled-schema-equal-payload cites §5 commandment [WIP] Enhance every detail of the designer #10; 6357-basechema-bind-declaration and 6505-predicate-valued-gate-rules cite §4 (BaseSchema, predicate keys); 5674-retire-plugin-component-input, 7122-spec-17-3-0-parity-reconciliation and 7714-lookup-draft-stays-client-side cite the version-alignment policy (no major). This diff edits only the ruleset bullet in §9 and the governed-surface paragraph; §4, §5 [WIP] Enhance every detail of the designer #10 and the version-alignment section are byte-unchanged.
  3. content/docs/guide/ci-cd-pipeline.md ("Until it is flipped, the queue leg reports without stopping anything") and the "What this file does NOT do" header of scripts/check-governed-queue-guard.mjs ("Until the live required set carries the same name, this guard REPORTS …") — literally true conditionals, now misleading: a reader who does not know the flip happened concludes the leg reports only. They bear on a follow-up, not on this verdict — neither file is governed, and this PR's sentences are true on their own. The same family has a third carrier the dev did not list: the header of .github/workflows/spec-main-shape-gate.yml still says that context "is not REQUIRED" and sits in NOT_A_GATE, while the live set carries it and REQUIRED_CONTEXTS already lists it. The model for the repair already exists in ci-cd-pipeline.md's "How it became a required check" paragraph (dated history plus a pointer at the patrol). One ordinary docs/scripts PR can take all three.
  4. WATCHED_CONTEXTS lacks Governed Surface Queue Guard, so the daily patrol reports DRIFTED (exit 0) — left alone as the seat instructed, correctly: the gate's own header forbids editing that list to agree with the endpoint. The ruling-cited change it requires is now available — Machine-enforce human review on governed-surface paths — so the no-bypass rule stops resting on seat discipline alone #6596's closing comment 5852208696 carries the maintainer's verbatim 「Governed Surface Queue Guard 已加」, the same shape objectui#9969 gave Spec Main Shape Gate — and REQUIRED_CONTEXTS in scripts/dependabot-merge-gate.mjs already carries the name, so the declaration-integrity pin would pass. Follow-up card, not this PR.
  5. Wording precision, escalated to the seat (verdict-neutral): 「拒绝路径还没在队列里真正触发过一次」 is true since enrolment and false as an all-time statement — the guard's merge_group leg refused with exit 6 on seven queue builds between 2026-09-13 and 2026-09-20 (PRs fix(skills): guard the DataSource read in the marked data-integration example #9352, fix(app-shell): keep the approval envelope + pending-action id in the chat cache #9450, feat(plugin-view): ObjectView honours a spec-shaped named list view (objectui#8254) #9605, docs(skills): gate the usePermissions example on can(), a boolean, and mark its fence (objectui#9671) #9994, docs(skills): page-builder.md names the channel that publishes expression roots (objectui#9672) #9997, docs(skills): move the three published guides off the retired dataSource expression root #9378 twice), none blocking because the context was not yet required. Tightening the clause to say 「登记后…还没触发过」 would make it true on every reading; whether that is worth a further round on a Tier H PR is the seat's call.
  6. Dev deviations, each checked: ROUTE (bare script, not the package script) — right, verified in package.json; LEG 2 kept rather than dropped — right, see ①; ATTRIBUTION — the three commits carry the model-free Claude-Session / Co-authored-by pair; WRITE OP (issue_patch in place of a pr_update the relay lacks) — the PR body ends in exactly one session-URL footer; MERGE COMMIT — 9847e6ca6e merges main at 42687baf20, then one content commit, no force-push; WORDING — 「从仓内读不到」 counted once at the head. The dev's one-shot proofs A/B are the dev's measurements and are not re-run here; the property they demonstrate is structurally evident from the unchanged regex and the kept phrase.
  7. Landing pre-check ② (all checks green) is not met on this head today because of the Spec Main Shape Gate trunk red described in ①. It is not attributable to this diff and is already carded (objectui#10987 / finding(types): the Spec Main Shape Gate is red on every PR head built after objectstack#20357 retired the list view tabs key — p1-spec-alignment.test.ts still authors ListViewSchema.tabs #10988); the merge-base's own check-run on that gate is green only because it ran before objectstack main moved, so the "same signature on base" exception cannot be read off base check-runs. Tier H landing waits on the maintainer's word regardless; the owning seat re-reads the head's check-runs at landing time and does not ready or queue this PR while that context is red.
  8. Procedural, for the seat: the card's fence 1 asks that review be requested from os-zhuang and hotlong; the PR carries no requested reviewers and no reviews. Under Prime Directive Add Airtable-like Filter Builder Component with Advanced Field Types #14 the director seat requests the word as one batch, so this is that batch's job, not a contract finding. Fixes #9520 will close the card on merge, as intended.

Implemented-by: claude/issue-9520-ruleset-readable-half
Reviewed-by: session_01EBx9rvB7dufCz4at53x35U

VERDICT: PASS


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

维护者速读(终稿)

席位 domain:devx @ objectui 第 2 席(session_01EBx9rvB7dufCz4at53x35U)对照本 PR 的实际 diff(head cdb89afa4a)校正 dev 草稿后定稿。契约复审档复核 PASS 在案(5871279884),席位复核记录在 objectui#9520(5871353835)。

改了什么:根 AGENTS.md 两处,都属于「写给 agent 的说明已经和 ruleset 现状对不上」这一类。

  1. ruleset 那条:原句说「谁可绕过、required checks 清单」都「从仓内读不到」。实测只对一半,现在拆开写:
    • 谁可绕过仍然读不到(接口只回答「我能不能绕过」,不给名单);
    • required checks 清单读得到,指向每天定时在跑的 node scripts/check-required-check-set.mjs,并注明 pnpm check:required-check-set 只是离线自测。
    • 清单本身不抄进来。
  2. 受管面兜底那段:原文说 Governed Surface Queue Guard「尚未是 required context,只报告、不阻止队列」。你在 9 月 27 日已把它加进 required(objectui#6596),这句已经不成立。现改为带日期的历史:9/14 还不在集合里,9/27 加入,9/28 实测在。并写明:
    • 现在没有获授权批准记录的受管 PR 过不了合并队列;
    • 拦不住的是批准本身(席位共用一个身份)和 ruleset 绕过。
    • 其余仍然成立的警示逐字保留。

另外同步了 scripts/check-required-check-set.mjs 的文档注释和它的测试措辞(只改描述,断言和检测器一字未动)。

为什么改:按原文行事的 agent 会以为 required 清单无从核实、只能靠推断,或者以为挂 needs:contract-review 的 PR 照样能过队列。两者都与实际相反。

风险与代价(含回滚):只改说明文字与注释,不改任何门禁判定或 ruleset。唯一的「推断」处已写明是按配置推出、尚未实际观察到拦截。回滚:revert 这个 squash commit。

席位意见:建议批准。有三点请知悉:

  • 当前 CI 有一项红:Spec Main Shape Gate 是 objectstack#20357 下线 list view tabs 引起的全队列问题,不是本 PR 的。domain:ui 席已在 objectui#10987 按止血认领。修好后本席把 main 合进本分支、复读 CI 后再落地。批准可以先给。
  • 同一家族还有尾巴,本 PR 未改:
  • 范围比卡片原题宽:第 2 处是本席复核时让 dev 顺带补的。同一文件、同一类问题,合在一张受管 PR 里只需你审一次。

你要做的:读一下 AGENTS.md 这两处新措辞,同意就在本 PR 上点 Approve(os-zhuang 或 hotlong 任一账号即可)。之后合 main、翻 ready、入队由席位完成。


Generated by Claude Code

…eset-readable-half

Claude-Session: https://claude.ai/code/session_01EBx9rvB7dufCz4at53x35U
Co-authored-by: Claude <noreply@anthropic.com>
@os-zhuang
os-zhuang added this pull request to the merge queue Sep 28, 2026
Merged via the queue into main with commit a097316 Sep 28, 2026
41 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-9520-ruleset-readable-half branch September 28, 2026 14:55
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 tests

Projects

None yet

3 participants