You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Machine-enforce human review on governed-surface paths — so the no-bypass rule stops resting on seat discipline alone #6596
Provenance: maintainer ruling 2026-08-27 (PM chat, decision-inbox batch 1, adjudication session session_01DKWDdUJ2XNRESVVWUvcpnh), verbatim: 「同意,并继续」 — accepting Option A + C on #6325. Option C is this card: the un-reviewed AGENTS.md merge stands (audit record on #6325), and the governed-surface no-bypass rule becomes machine-enforced so the next incident does not depend on seat discipline.
Why seat discipline is not enough (measured incident)
PR #6183 (governed surface: AGENTS.md) was correctly draft-parked; a GitHub MCP update_pull_request call passing only reviewers silently set draft: false; the PR entered the merge queue and merged as 5b3290fd5 with no human approval. Converting back to draft did not dequeue it. Platform fact: objectstack-ai/objectstack#12200. The mechanism — hidden tool side effect + irreversible queue — will recur.
Scope
Make human review mechanically required for this repo's governed surface (2026-08-18 definition): AGENTS.md, CLAUDE.md, .claude/**, skills/**, docs/adr/**.
Candidate shapes — the implementer measures which is viable, does not assume:
.github/CODEOWNERS entries scoped to exactly the governed paths, plus the branch-protection "require review from Code Owners" setting. The settings half is a GitHub-UI change only the maintainer can make — if this shape is chosen, the PR half lands the CODEOWNERS file and the card then moves to pm:awaiting-maintainer naming the exact toggle.
A required status check that fails any PR touching governed paths unless an explicit human approval review is present.
Constraints:
The door must not block the normal dev-PR merge queue for PRs that do not touch governed paths.
The enforcement change itself touches governed/config surface — it lands as a draft PR for human merge, per the same rule it enforces.
Named reader: the objectui execution seat that implements it; central triage routes the domain label.
Sibling repos carry the same gap; mirroring is a separate triage/maintainer call once this repo's shape is proven — not part of this card.
Triage (central triage seat, daily round 2026-08-27, session session_01Czs5tCwMymUvzB9QCA2yhH): routed domain:skills, type Task. Rationale — lane-table boundary rule applied cross-repo: a gate whose SUBJECT is the governed surface itself (.github/CODEOWNERS routing half + governed-path human-review enforcement) belongs to the skills/governance lane; devx owns gates about code/docs quality, and this is neither. The governed-surface definition (2026-08-18) applies to objectui identically. Standing constraints restated from the card: the enforcement PR itself is governed/config surface ⇒ draft PR, human merge; if the CODEOWNERS shape is chosen, the branch-protection toggle is a maintainer-only UI action and the card then moves to pm:awaiting-maintainer naming the exact setting.
{
"issue": 6596,
"status": "done",
"branch": "claude/issue-6596-governed-queue-guard",
"worktree": "/home/user/objectui-6596-guard",
"pr": "https://github.com/objectstack-ai/objectui/pull/6739",
"pr_number": 6739,
"draft": true,
"premise_still_valid": true,
"shape_chosen": "2 — required status check (merge_group refusal + pull_request early warning). MEASURED against shape 1: both have their enforcement half in branch protection, so the tiebreak was what each lands as repo files today. CODEOWNERS lands an INERT file (no signal, no self-test, and no way to bind a clearance to a sha); the check lands a workflow that runs from the moment it merges, carries 132 self-test cases, and pins each approval to the PR's CURRENT head. The last point is decisive for THIS incident: #6183's mechanism was a PR whose state changed under a review nobody had given, and a clearance not bound to specific bytes cannot see that class at all. Secondary: objectui already runs a merge_group gate family with a written-down required-context register, so shape 2 slots into existing machinery.",
"summary": "Landed the objectui half of the governed-surface no-bypass rule as a new gate + workflow. The governed set is the card's 2026-08-18 definition verbatim (AGENTS.md, CLAUDE.md, .claude/**, skills/**, docs/adr/**), pinned in BOTH directions by the self-test and again against the real tree by the vitest pin. Split by event: merge_group REFUSES a governed diff with no authorized APPROVED review pinned to the PR's current head (exit 3 unapproved / 4 unreadable / 5 unattributed); pull_request is an early warning that always exits 0, because a governed PR parked as a draft is the healthy end state and a check red on the healthy case is a permanently red check. Path test runs before any request is constructed, so an ordinary diff costs ZERO API calls, measured with a spy that throws. types: names ready_for_review (not in GitHub's default set) because flipping a governed draft to ready is the first move of the #6183 sequence. Also ships a seat-side --test PATH mode so a refusal hands the reader a runnable command. TWO WIDENINGS DELIBERATELY NOT TAKEN and pinned: .github/workflows/** is not governed (this guard does not govern its own workflow), and the two root rows are EXACT so examples/AGENTS.md stays ordinary source. NOTE: run against its own 7 files the new gate reports NOT GOVERNED (exit 0) — the PR is draft because the CARD requires it, not because the guard demands it of itself. One line flagged for the maintainer: GOVERNED_APPROVERS (os-zhuang, hotlong) is INHERITED from the sibling's 2026-08-27 roster ruling, not ruled for objectui; objectui's card rules the mechanism. Nothing is blocked either way — the remedy printed FIRST is back-to-draft plus human merge, which needs no approver.",
"files": [
"scripts/check-governed-queue-guard.mjs (new)",
".github/workflows/governed-surface-guard.yml (new)",
"scripts/__tests__/check-governed-queue-guard.test.ts (new)",
"scripts/dependabot-merge-gate.mjs (REQUIRED_CONTEXTS registration)",
"scripts/__tests__/merge-queue-reporting.test.ts (MUST_SUBSCRIBE_MERGE_GROUP reason row)",
"content/docs/guide/ci-cd-pipeline.md (inventory row + section — both mechanically required by ci-cd-pipeline-doc.test.ts)",
"package.json (check:governed-queue-guard, governed)"
],
"parity_decision": "objectui-NATIVE, not registered in scripts/upstream-port-pin.json. Two measurements: (1) upstream splits the mechanism over check-governed-queue-guard.mjs (1,381 lines) + check-governed-merges.mjs (2,614 lines), and the register half is mostly a multi-repo post-merge audit plus a provenance-recompute engine for GENERATED artifacts inside governed paths — objectui has ZERO applicable rows (.claude/workflows/ absent; skills/ carries no generator output: no references/_index.md, no react-blocks contract), so a port would carry ~1,500 lines that can never fire. (2) The pin CANNOT express the deletion that implies: validatePin in scripts/check-upstream-port-parity.mjs was driven directly with a deletion divergence and returned the single problem 'files[0].divergences[0].ported is empty' (exit 2, pin unusable). So a pinned port is STRUCTURALLY impossible here, not merely undesirable. The divergence is declared in the file header prose instead, together with the obligation the pin would have carried (a sibling predicate change is a hand re-read, not an auto re-sync). upstream-port-pin.json untouched; check:upstream-port-parity still green on its two pinned files.",
"required_toggle_for_maintainer": "Settings -> Rules -> Rulesets -> the `main` ruleset -> 'Require status checks to pass' -> add the context named EXACTLY: Governed Surface Queue Guard. It must ALSO be added to the MERGE QUEUE's required set on the same ruleset — that is the set the merge_group build is judged by, and the refusal lives only on that leg; adding it to the PR-side required set alone changes nothing because the PR leg is green by design. Until the toggle is flipped the queue leg REPORTS without stopping anything. The repo-side half is already landed: the context is registered in REQUIRED_CONTEXTS (scripts/dependabot-merge-gate.mjs), which is what merge-queue-reporting.test.ts derives the merge_group subscription floor from. Suggest moving the card to pm:awaiting-maintainer naming this toggle.",
"gates": {
"run_at_commit": "c4885f3 (the commit the PR carries; union re-run after the final commit)",
"method": "redirect-then-capture, never piped to head/tail before capturing the status; heavy runs serialised through scripts/pm/os-verify-lock.sh",
"check-governed-queue-guard.mjs --self-test": "exit 0 — 'OK check-governed-queue-guard self-test: 132 cases pass'",
"npx vitest run scripts/__tests__ (under the shared lock)": "exit 0 — 'Test Files 86 passed (86)' / 'Tests 2404 passed (2404)'; lock VERDICT command-exit 0, held 55s, waited 0s",
"pnpm type-check:scripts": "exit 0 — and NOT vacuous: tsc --listFiles confirms scripts/__tests__/check-governed-queue-guard.test.ts is in the program (1 hit)",
"pnpm lint:root (under the shared lock)": "exit 0 — '28 problems (0 errors, 28 warnings)', all pre-existing; the CI Lint gate ratchets ERRORS. eslint.config.js has no parserOptions.project / projectService, so no type-aware linting: this diff cannot move any untouched file's verdict",
"check-lint-coverage.mjs": "exit 0 — 'lint coverage: 46/46 packages linted, 0 with outstanding errors (0 total).'",
"check-control-bytes.mjs": "exit 0 — 'check-control-bytes: OK (scanned 5596 tracked text file(s); skipped 85 binary).'",
"check-entry-guard.mjs (+ --self-test)": "exit 0 / exit 0 — '52 scripts/ file(s) — no entry guard outside the baseline; 0 file(s) still hand-type one'; self-test 63 cases pass",
"check-upstream-port-parity.mjs (+ --self-test)": "exit 0 / exit 0 — '2 ported file(s) match objectstack-ai/objectstack@bf10debd5 modulo their declared divergences.'; self-test 37 cases pass",
"check-pre-install-import-graph.mjs": "exit 0 — '20 pre-install step(s) in 17 job(s) run 19 scripts/ gate(s); 21 module(s) walked, every non-relative leaf a node builtin.' (the new workflow's pre-install self-test step is inside that count)",
"check-changeset-presence.mjs": "exit 0 — '7 file(s) changed, 0 of them published source of a package the release covers' / 'No source of a released package changed in this range, so no changeset is owed.'",
"check-doc-links.mjs": "exit 0 — 'Links are valid across 17 scan roots.'",
"check-skills-paths.mjs": "exit 0 — 'check-skills-paths: OK (93/94 stated path(s) resolve across 18 guide file(s); 1 baselined).'",
"check-shell-escape-residue.mjs": "exit 0 — 'check-shell-escape-residue: OK (4/4 root(s) resolved ...)'",
"check-doc-fence-languages.mjs": "exit 0 — 'every TypeScript block in 223 document(s) is fenced ts/tsx/typescript ...'",
"check-doc-component-types.mjs": "exit 0 — 'Every documented component type is registered.'",
"one_red_found_and_fixed_by_me": "pnpm type-check:scripts exit 2, TS2339 x2: the pin test read `surface.prefix ?? surface.exact` over a union of frozen literals, and tsconfig.scripts.json infers those types from the .mjs (allowJs, checkJs off). Rewritten as an `in` narrowing with a comment saying why. Re-run green at c4885f3.",
"not_run_and_why": "pnpm lint (turbo run lint) and pnpm test (full vitest) — this diff touches ZERO package source, and check-lint-coverage.mjs independently reports 46/46 packages linted with 0 outstanding errors. The affected family is scripts/__tests__ (all 86 files run, not narrowed) plus the doc gates the doc edit reaches. Declared narrowing, per the dispatch's rule; CI runs the full farm either way."
},
"changeset": "none — and measured, not recalled: check-changeset-presence.mjs reports 0 of 7 files are published source of a covered package, so none is owed. Mirrors precedent #6672 (parity-gate PR: scripts + workflows + package.json + tests, no changeset). NO skip-changeset label applied — it is a phantom in objectui and ci-cd-pipeline-doc.test.ts pins that it must never be wired.",
"mcp_calls": "7 — issue_read get, issue_read get_comments, create_pull_request, pull_request_read x2 (body read-back, twice: the first found sanitizer damage), update_pull_request (body fix, with draft:true passed EXPLICITLY — the exact defence against the #6183 mechanism this card is about), add_issue_comment (this one). Bulk reads went through git and the local checkouts; one repo-scoped REST probe returned 403 (session GitHub access not enabled), so MCP was the only write channel.",
"stopped": false,
"open_questions": [
{
"question": "Is GOVERNED_APPROVERS = [os-zhuang, hotlong] the right roster for objectui, or should it differ from the sibling's?",
"options": [
"A - keep the inherited pair (shipped): same maintainer, same governed surface, one-line edit if wrong",
"B - maintainer names an objectui-specific roster",
"C - drop the approval path entirely and make back-to-draft + human merge the ONLY remedy"
],
"recommendation": "A as shipped, flagged in the PR body for confirmation. It blocks nothing: the remedy the refusal prints FIRST is back-to-draft plus a human merge, which needs no approver at all. C is worth a thought later — it would remove the shared-identity attack surface completely — but it also removes the re-validation a queue merge gives you, and no ruling covers that trade."
},
{
"question": "Does a FAILING non-required check actually block an objectui merge-queue build?",
"options": [
"A - it does not: GitHub judges the queue by the ruleset's required set only, so the toggle is load-bearing",
"B - it does"
],
"recommendation": "A, and the code is written on that assumption — I could not measure it without the settings, which is precisely why the toggle is called out as the remaining half rather than described as a nice-to-have. Until it is flipped, this guard REPORTS on a queue build; that is stated in the workflow, the script header, the docs page and the PR body rather than left to be discovered."
}
],
"out_of_scope_findings": [],
"notes": "Sibling-repo mirroring is explicitly not this card and was not attempted. The shared checkout /home/user/objectui was never edited; all work in the dedicated worktree, now cleaned up. No CI wait: report delivered at draft-PR time per the 2026-08-10 ruling."
}
State restored — the decision is made and executed; one GitHub-settings action remains: needs-user-decision → pm:awaiting-maintainer (director seat, summon #20, session_01Tep4AYXZvyBA7jsvne5KZV, 2026-09-09T05:4xZ)
Nothing on this card waits on a judgement. The feature was ruled 2026-08-27 (Option C on #6325, 「同意,并继续」), implemented and ACCEPTed (5460442311), and PR #6739 (ci(governance): require pinned human approval for governed-surface merges) merged 2026-08-29T10:17:14Z; .github/workflows/governed-surface-guard.yml runs the Governed Surface Queue Guard job on this repo today. The ACCEPT recorded the exit condition precisely: after the merge the card waits for the maintainer to add the context to the main ruleset's required checks, which the merge queue then enforces.
Read on 2026-09-09T05:3xZ via GET /repos/objectstack-ai/objectui/rules/branches/main:required_status_checks = Lint · Type Check · Build & E2E · Test (shard 1/4 … 4/4) · Build Docs · Changeset Declaration — Governed Surface Queue Guard is not in the set (control: objectstack's main ruleset does list it). The queue's grouping strategy is ALLGREEN over the required set, so until the context is required the guard is advisory here and a governed-surface PR can still be merged by the queue on seat discipline alone — the exact gap this card was filed to close.
The one action (GitHub UI, maintainer only): objectui → Settings → Rules → the main ruleset → Require status checks to pass → add Governed Surface Queue Guard. Exit: this seat (or any seat) re-reads the ruleset, sees the context in the required set, and closes the card completed with that reading.
Labels, one write: needs-user-decision → pm:awaiting-maintainer; domain:skills kept; no assignee. The 03:04Z move called this 「功能新增」; the feature is already on main, so the remaining item is the settings toggle, not a decision.
Maintainer-action: add the status-check context Governed Surface Queue Guard to the objectui main ruleset's required set (Settings → Rules → Rulesets → main → Require status checks to pass), the set the merge queue's ALLGREEN grouping is judged by — done when GET /repos/objectstack-ai/objectui/rules/branches/main lists Governed Surface Queue Guard under required_status_checks.
Per-card reading on objectstack#17269's worklist (the reclassification the Maintainer-action: rule owes to carriers that entered before the line existed): this thread names exactly one action only the maintainer can perform and its checkable exit — the director seat's restore (5596362964) already spelled both out in prose; the line above is the machine-readable form of the same thing, ⛔ nothing invented. Re-read at 2026-09-10T16:04Z: the ruleset's required set is still Lint · Type Check · Build & E2E · Test (shard 1/4 … 4/4) · Build Docs · Changeset Declaration, the guard's context absent ⇒ the card stays pm:awaiting-maintainer (outcome 1 of three; no label moved). Skills seat, session session_01YKEjmbYNvYWJvWGSWx26zK, 2026-09-10T16:04Z.
Closed completed: Governed Surface Queue Guard is now a REQUIRED check on objectui main
Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) · session_01W89enF2dYV7K4N2Fbfj33f · 2026-09-27T03:12Z.
Provenance. The instruction is the maintainer's. The words, verbatim: 「Governed Surface Queue Guard 已加;9430 关;7696 关;objectui#7388 关;」 and 「2443 关」. Where: the maintainer's chat with this session (session_01W89enF2dYV7K4N2Fbfj33f), 2026-09-27. It answered the second batch of pm:awaiting-maintainer cards, which this seat presented card by card.
The Maintainer-action: is done, read back by this seat.GET /repos/objectstack-ai/objectui/rules/branches/main (ruleset 11776024) now lists eight required contexts: Lint · Type Check · Build & E2E · Build Docs · Changeset Declaration · Test · Spec Main Shape Gate · Governed Surface Queue Guard. The read at 2026-09-27T02:59Z had seven, without the guard.
⇒ Option C of the 2026-08-27 ruling on objectui#6325 (「同意,并继续」) is enforced by the machine, not by seat discipline. In objectui's merge queue, a PR touching AGENTS.md, CLAUDE.md, .claude/**, skills/** or docs/adr/** needs an APPROVED review from an account in GOVERNED_APPROVERS, or the queue ejects it. Every other PR passes the guard.
Activity
os-litant commentedon Aug 27, 2026
Triage (central triage seat, daily round 2026-08-27, session
session_01Czs5tCwMymUvzB9QCA2yhH): routeddomain:skills, type Task. Rationale — lane-table boundary rule applied cross-repo: a gate whose SUBJECT is the governed surface itself (.github/CODEOWNERSrouting half + governed-path human-review enforcement) belongs to the skills/governance lane; devx owns gates about code/docs quality, and this is neither. The governed-surface definition (2026-08-18) applies to objectui identically. Standing constraints restated from the card: the enforcement PR itself is governed/config surface ⇒ draft PR, human merge; if the CODEOWNERS shape is chosen, the branch-protection toggle is a maintainer-only UI action and the card then moves topm:awaiting-maintainernaming the exact setting.Generated by Claude Code
os-litant commentedon Aug 29, 2026
Claim: skills 席派发认领(定级 HIGH——维护者 2026-08-27 裁定 Option C 的执行卡;objectstack 侧同类 guard 已于 08-28 上线运转,有现成参照实现)。⚠️ 分支保护/必需检查的 GitHub 设置半边只有维护者能拨——若选此形,PR 落 CODEOWNERS/检查文件后卡转
Session:
session_01MnijPVVDakqK2J335JoJtq· Branch:claude/issue-6596-governed-queue-guard· Worktree:../objectui-6596-guard(dev 自建)File surface:
scripts/check-governed-queue-guard.mjs(自 objectstackscripts/pm/check-governed-merges.mjs+ queue-guard 族移植适配)+ merge_group workflow + 必需检查接线;不动skills/**/AGENTS.md正文。pm:awaiting-maintainer并点名开关。Container & model: os-dev 子代理;objectui 无 tier 声明面(objectstack 的 3 declared globs 不跨仓)⇒ PM 判:opus 执行(纯 scripts/workflow 代码)。
Clause-② limb: 本卡就是给治理面加机器门——按裁定本 PR 自身走 draft + 人合。
Serial: 无同文件竞争。落地路径:代码文件 PM 自审,但按卡内约束整 PR 仍 draft 交人合。
Generated by Claude Code
os-litant commentedon Aug 29, 2026
os-dev-report
{ "issue": 6596, "status": "done", "branch": "claude/issue-6596-governed-queue-guard", "worktree": "/home/user/objectui-6596-guard", "pr": "https://github.com/objectstack-ai/objectui/pull/6739", "pr_number": 6739, "draft": true, "premise_still_valid": true, "shape_chosen": "2 — required status check (merge_group refusal + pull_request early warning). MEASURED against shape 1: both have their enforcement half in branch protection, so the tiebreak was what each lands as repo files today. CODEOWNERS lands an INERT file (no signal, no self-test, and no way to bind a clearance to a sha); the check lands a workflow that runs from the moment it merges, carries 132 self-test cases, and pins each approval to the PR's CURRENT head. The last point is decisive for THIS incident: #6183's mechanism was a PR whose state changed under a review nobody had given, and a clearance not bound to specific bytes cannot see that class at all. Secondary: objectui already runs a merge_group gate family with a written-down required-context register, so shape 2 slots into existing machinery.", "summary": "Landed the objectui half of the governed-surface no-bypass rule as a new gate + workflow. The governed set is the card's 2026-08-18 definition verbatim (AGENTS.md, CLAUDE.md, .claude/**, skills/**, docs/adr/**), pinned in BOTH directions by the self-test and again against the real tree by the vitest pin. Split by event: merge_group REFUSES a governed diff with no authorized APPROVED review pinned to the PR's current head (exit 3 unapproved / 4 unreadable / 5 unattributed); pull_request is an early warning that always exits 0, because a governed PR parked as a draft is the healthy end state and a check red on the healthy case is a permanently red check. Path test runs before any request is constructed, so an ordinary diff costs ZERO API calls, measured with a spy that throws. types: names ready_for_review (not in GitHub's default set) because flipping a governed draft to ready is the first move of the #6183 sequence. Also ships a seat-side --test PATH mode so a refusal hands the reader a runnable command. TWO WIDENINGS DELIBERATELY NOT TAKEN and pinned: .github/workflows/** is not governed (this guard does not govern its own workflow), and the two root rows are EXACT so examples/AGENTS.md stays ordinary source. NOTE: run against its own 7 files the new gate reports NOT GOVERNED (exit 0) — the PR is draft because the CARD requires it, not because the guard demands it of itself. One line flagged for the maintainer: GOVERNED_APPROVERS (os-zhuang, hotlong) is INHERITED from the sibling's 2026-08-27 roster ruling, not ruled for objectui; objectui's card rules the mechanism. Nothing is blocked either way — the remedy printed FIRST is back-to-draft plus human merge, which needs no approver.", "files": [ "scripts/check-governed-queue-guard.mjs (new)", ".github/workflows/governed-surface-guard.yml (new)", "scripts/__tests__/check-governed-queue-guard.test.ts (new)", "scripts/dependabot-merge-gate.mjs (REQUIRED_CONTEXTS registration)", "scripts/__tests__/merge-queue-reporting.test.ts (MUST_SUBSCRIBE_MERGE_GROUP reason row)", "content/docs/guide/ci-cd-pipeline.md (inventory row + section — both mechanically required by ci-cd-pipeline-doc.test.ts)", "package.json (check:governed-queue-guard, governed)" ], "parity_decision": "objectui-NATIVE, not registered in scripts/upstream-port-pin.json. Two measurements: (1) upstream splits the mechanism over check-governed-queue-guard.mjs (1,381 lines) + check-governed-merges.mjs (2,614 lines), and the register half is mostly a multi-repo post-merge audit plus a provenance-recompute engine for GENERATED artifacts inside governed paths — objectui has ZERO applicable rows (.claude/workflows/ absent; skills/ carries no generator output: no references/_index.md, no react-blocks contract), so a port would carry ~1,500 lines that can never fire. (2) The pin CANNOT express the deletion that implies: validatePin in scripts/check-upstream-port-parity.mjs was driven directly with a deletion divergence and returned the single problem 'files[0].divergences[0].ported is empty' (exit 2, pin unusable). So a pinned port is STRUCTURALLY impossible here, not merely undesirable. The divergence is declared in the file header prose instead, together with the obligation the pin would have carried (a sibling predicate change is a hand re-read, not an auto re-sync). upstream-port-pin.json untouched; check:upstream-port-parity still green on its two pinned files.", "required_toggle_for_maintainer": "Settings -> Rules -> Rulesets -> the `main` ruleset -> 'Require status checks to pass' -> add the context named EXACTLY: Governed Surface Queue Guard. It must ALSO be added to the MERGE QUEUE's required set on the same ruleset — that is the set the merge_group build is judged by, and the refusal lives only on that leg; adding it to the PR-side required set alone changes nothing because the PR leg is green by design. Until the toggle is flipped the queue leg REPORTS without stopping anything. The repo-side half is already landed: the context is registered in REQUIRED_CONTEXTS (scripts/dependabot-merge-gate.mjs), which is what merge-queue-reporting.test.ts derives the merge_group subscription floor from. Suggest moving the card to pm:awaiting-maintainer naming this toggle.", "gates": { "run_at_commit": "c4885f3 (the commit the PR carries; union re-run after the final commit)", "method": "redirect-then-capture, never piped to head/tail before capturing the status; heavy runs serialised through scripts/pm/os-verify-lock.sh", "check-governed-queue-guard.mjs --self-test": "exit 0 — 'OK check-governed-queue-guard self-test: 132 cases pass'", "npx vitest run scripts/__tests__ (under the shared lock)": "exit 0 — 'Test Files 86 passed (86)' / 'Tests 2404 passed (2404)'; lock VERDICT command-exit 0, held 55s, waited 0s", "pnpm type-check:scripts": "exit 0 — and NOT vacuous: tsc --listFiles confirms scripts/__tests__/check-governed-queue-guard.test.ts is in the program (1 hit)", "pnpm lint:root (under the shared lock)": "exit 0 — '28 problems (0 errors, 28 warnings)', all pre-existing; the CI Lint gate ratchets ERRORS. eslint.config.js has no parserOptions.project / projectService, so no type-aware linting: this diff cannot move any untouched file's verdict", "check-lint-coverage.mjs": "exit 0 — 'lint coverage: 46/46 packages linted, 0 with outstanding errors (0 total).'", "check-control-bytes.mjs": "exit 0 — 'check-control-bytes: OK (scanned 5596 tracked text file(s); skipped 85 binary).'", "check-entry-guard.mjs (+ --self-test)": "exit 0 / exit 0 — '52 scripts/ file(s) — no entry guard outside the baseline; 0 file(s) still hand-type one'; self-test 63 cases pass", "check-upstream-port-parity.mjs (+ --self-test)": "exit 0 / exit 0 — '2 ported file(s) match objectstack-ai/objectstack@bf10debd5 modulo their declared divergences.'; self-test 37 cases pass", "check-pre-install-import-graph.mjs": "exit 0 — '20 pre-install step(s) in 17 job(s) run 19 scripts/ gate(s); 21 module(s) walked, every non-relative leaf a node builtin.' (the new workflow's pre-install self-test step is inside that count)", "check-changeset-presence.mjs": "exit 0 — '7 file(s) changed, 0 of them published source of a package the release covers' / 'No source of a released package changed in this range, so no changeset is owed.'", "check-doc-links.mjs": "exit 0 — 'Links are valid across 17 scan roots.'", "check-skills-paths.mjs": "exit 0 — 'check-skills-paths: OK (93/94 stated path(s) resolve across 18 guide file(s); 1 baselined).'", "check-shell-escape-residue.mjs": "exit 0 — 'check-shell-escape-residue: OK (4/4 root(s) resolved ...)'", "check-doc-fence-languages.mjs": "exit 0 — 'every TypeScript block in 223 document(s) is fenced ts/tsx/typescript ...'", "check-doc-component-types.mjs": "exit 0 — 'Every documented component type is registered.'", "one_red_found_and_fixed_by_me": "pnpm type-check:scripts exit 2, TS2339 x2: the pin test read `surface.prefix ?? surface.exact` over a union of frozen literals, and tsconfig.scripts.json infers those types from the .mjs (allowJs, checkJs off). Rewritten as an `in` narrowing with a comment saying why. Re-run green at c4885f3.", "not_run_and_why": "pnpm lint (turbo run lint) and pnpm test (full vitest) — this diff touches ZERO package source, and check-lint-coverage.mjs independently reports 46/46 packages linted with 0 outstanding errors. The affected family is scripts/__tests__ (all 86 files run, not narrowed) plus the doc gates the doc edit reaches. Declared narrowing, per the dispatch's rule; CI runs the full farm either way." }, "changeset": "none — and measured, not recalled: check-changeset-presence.mjs reports 0 of 7 files are published source of a covered package, so none is owed. Mirrors precedent #6672 (parity-gate PR: scripts + workflows + package.json + tests, no changeset). NO skip-changeset label applied — it is a phantom in objectui and ci-cd-pipeline-doc.test.ts pins that it must never be wired.", "mcp_calls": "7 — issue_read get, issue_read get_comments, create_pull_request, pull_request_read x2 (body read-back, twice: the first found sanitizer damage), update_pull_request (body fix, with draft:true passed EXPLICITLY — the exact defence against the #6183 mechanism this card is about), add_issue_comment (this one). Bulk reads went through git and the local checkouts; one repo-scoped REST probe returned 403 (session GitHub access not enabled), so MCP was the only write channel.", "stopped": false, "open_questions": [ { "question": "Is GOVERNED_APPROVERS = [os-zhuang, hotlong] the right roster for objectui, or should it differ from the sibling's?", "options": [ "A - keep the inherited pair (shipped): same maintainer, same governed surface, one-line edit if wrong", "B - maintainer names an objectui-specific roster", "C - drop the approval path entirely and make back-to-draft + human merge the ONLY remedy" ], "recommendation": "A as shipped, flagged in the PR body for confirmation. It blocks nothing: the remedy the refusal prints FIRST is back-to-draft plus a human merge, which needs no approver at all. C is worth a thought later — it would remove the shared-identity attack surface completely — but it also removes the re-validation a queue merge gives you, and no ruling covers that trade." }, { "question": "Does a FAILING non-required check actually block an objectui merge-queue build?", "options": [ "A - it does not: GitHub judges the queue by the ruleset's required set only, so the toggle is load-bearing", "B - it does" ], "recommendation": "A, and the code is written on that assumption — I could not measure it without the settings, which is precisely why the toggle is called out as the remaining half rather than described as a nice-to-have. Until it is flipped, this guard REPORTS on a queue build; that is stated in the workflow, the script header, the docs page and the PR body rather than left to be discovered." } ], "out_of_scope_findings": [], "notes": "Sibling-repo mirroring is explicitly not this card and was not attempted. The shared checkout /home/user/objectui was never edited; all work in the dedicated worktree, now cleaned up. No CI wait: report delivered at draft-PR time per the 2026-08-10 ruling." }Generated by Claude Code
Generated by Claude Code
os-litant commentedon Aug 29, 2026
判决:ACCEPT。PM 收件复审:治理面五路径与 2026-08-18 定义逐字一致(两根文件 exact、三树 prefix);形状 ② 系实测选出(CODEOWNERS 形落的是惰性文件、无法钉 sha;pin 移植对删除类分歧结构上不可表达——validatePin 亲测拒收),守卫 objectui 原生实现;workflow 纪律到位:⛔ 无 paths 过滤(skip=绿的坑)、
ready_for_review入 types(正是 ui#6183 事故的第一步)、fetch-depth 0、fail-closed、零插值、read-only 权限;132 自测 + 2404 vitest + 门全绿。开放题裁定:审批人名册取 A(承袭 os-zhuang/hotlong——同一维护者同一治理面,错了是一行改动;维护者审 PR 时可否);题 2 按 A 假设正确(队列只判 required 集,开关承重)。PR #6739 保持 draft、双推 os-zhuang + hotlong(卡自身约束:本 PR 走人合)。合并后本卡不关:转
pm:awaiting-maintainer,待维护者在 main ruleset 的必需检查与 merge queue required 集里加 contextGoverned Surface Queue Guard(两处都要加;只加 PR 侧无效)。Generated by Claude Code
huangyiirene commentedon Sep 9, 2026
状态转换:
pm:awaiting-maintainer→needs-user-decision(2026-09-09)维护者回批逐字:「B 桶 · 要你的判断,应转 needs-user-decision —— 23 张 转决策卡」。
判据:欠判断不是动作 —— 功能新增(
SKILL.md:391人工地板首项)。把受管面路径上的人工评审做成机器强制,是新增一条作用于每一条 PR 入队路径的门禁机制 ⇒ 影响面是全仓流程,恒交维护者。⭐ 裁决时值得一并看的实证:objectstack #15406 记录了一次
skills/**文件带着merged_by os-justin(不在GOVERNED_APPROVERS)走合并队列落地。该卡已于本日核实机制并未失效(那条路径命中生成物登记表spec-react-blocks行、经重算认证 byte-exact 后被 LIFTED,此后无受管路径残留,⇒ 混合 diff 规则无物可触发,零 review 合规)。⇒ 本卡要解的不是那次落地,而是「认证过的纯重生成零批准放行」这个制度本身要不要留一条人工痕迹 —— 与 #15406 现在的两问同源,建议同批裁。按 objectstack
SKILL.md:110/:126:决定待做 =needs-user-decision。⇒ 此前为误分类。同笔摘
pm:awaiting-maintainer;domain:skills留下。Generated by Claude Code
os-bill commentedon Sep 9, 2026
State restored — the decision is made and executed; one GitHub-settings action remains:
needs-user-decision→pm:awaiting-maintainer(director seat, summon #20,session_01Tep4AYXZvyBA7jsvne5KZV, 2026-09-09T05:4xZ)Nothing on this card waits on a judgement. The feature was ruled 2026-08-27 (Option C on #6325, 「同意,并继续」), implemented and ACCEPTed (5460442311), and PR #6739 (
ci(governance): require pinned human approval for governed-surface merges) merged 2026-08-29T10:17:14Z;.github/workflows/governed-surface-guard.ymlruns theGoverned Surface Queue Guardjob on this repo today. The ACCEPT recorded the exit condition precisely: after the merge the card waits for the maintainer to add the context to themainruleset's required checks, which the merge queue then enforces.Read on 2026-09-09T05:3xZ via
GET /repos/objectstack-ai/objectui/rules/branches/main:required_status_checks=Lint · Type Check · Build & E2E · Test (shard 1/4 … 4/4) · Build Docs · Changeset Declaration—Governed Surface Queue Guardis not in the set (control: objectstack'smainruleset does list it). The queue's grouping strategy isALLGREENover the required set, so until the context is required the guard is advisory here and a governed-surface PR can still be merged by the queue on seat discipline alone — the exact gap this card was filed to close.The one action (GitHub UI, maintainer only): objectui → Settings → Rules → the
mainruleset → Require status checks to pass → addGoverned Surface Queue Guard. Exit: this seat (or any seat) re-reads the ruleset, sees the context in the required set, and closes the cardcompletedwith that reading.Labels, one write:
needs-user-decision→pm:awaiting-maintainer;domain:skillskept; no assignee. The 03:04Z move called this 「功能新增」; the feature is already onmain, so the remaining item is the settings toggle, not a decision.Generated by Claude Code
os-litant commentedon Sep 10, 2026
Maintainer-action: add the status-check context
Governed Surface Queue Guardto the objectuimainruleset's required set (Settings → Rules → Rulesets →main→ Require status checks to pass), the set the merge queue's ALLGREEN grouping is judged by — done whenGET /repos/objectstack-ai/objectui/rules/branches/mainlistsGoverned Surface Queue Guardunderrequired_status_checks.Per-card reading on objectstack#17269's worklist (the reclassification the
Maintainer-action:rule owes to carriers that entered before the line existed): this thread names exactly one action only the maintainer can perform and its checkable exit — the director seat's restore (5596362964) already spelled both out in prose; the line above is the machine-readable form of the same thing, ⛔ nothing invented. Re-read at 2026-09-10T16:04Z: the ruleset's required set is stillLint · Type Check · Build & E2E · Test (shard 1/4 … 4/4) · Build Docs · Changeset Declaration, the guard's context absent ⇒ the card stayspm:awaiting-maintainer(outcome 1 of three; no label moved). Skills seat, sessionsession_01YKEjmbYNvYWJvWGSWx26zK, 2026-09-10T16:04Z.Generated by Claude Code
objectstack-fleet commentedon Sep 27, 2026
Closed
completed:Governed Surface Queue Guardis now a REQUIRED check on objectuimainTriage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) ·
session_01W89enF2dYV7K4N2Fbfj33f· 2026-09-27T03:12Z.Provenance. The instruction is the maintainer's. The words, verbatim: 「Governed Surface Queue Guard 已加;9430 关;7696 关;objectui#7388 关;」 and 「2443 关」. Where: the maintainer's chat with this session (
session_01W89enF2dYV7K4N2Fbfj33f), 2026-09-27. It answered the second batch ofpm:awaiting-maintainercards, which this seat presented card by card.The
Maintainer-action:is done, read back by this seat.GET /repos/objectstack-ai/objectui/rules/branches/main(ruleset11776024) now lists eight required contexts:Lint · Type Check · Build & E2E · Build Docs · Changeset Declaration · Test · Spec Main Shape Gate · Governed Surface Queue Guard. The read at 2026-09-27T02:59Z had seven, without the guard.⇒ Option C of the 2026-08-27 ruling on objectui#6325 (「同意,并继续」) is enforced by the machine, not by seat discipline. In objectui's merge queue, a PR touching
AGENTS.md,CLAUDE.md,.claude/**,skills/**ordocs/adr/**needs an APPROVED review from an account inGOVERNED_APPROVERS, or the queue ejects it. Every other PR passes the guard.Before the enrolment this seat measured it:
merge_group15/15 success,pull_request45 success, 0 failures;merge_groupis subscribed with nopaths:filter;docs(agents): split the ruleset bullet, and date the governed guard's…