chore(claude): deny the enqueue class and update_pull_request in .claude/settings.json (objectui#9586) - #10214
Conversation
…ui#9586)
Mirror of objectstack PR #18317 (ruling A on objectstack#18282) plus the one
earlier entry this repo never received, objectstack PR #18276:
- mcp__github__update_pull_request — arms a landing as a hidden side effect
- mcp__github__enable_pr_auto_merge — the enqueue class
- mcp__github__disable_pr_auto_merge — the enqueue class
The deny array is now element-for-element identical to objectstack's, order
included. `allow` and `hooks` are byte-identical to origin/main. No capability
is lost: the only enqueue route either board uses is the REST proxy's
`PUT .../pulls/{n}/ccr/auto_merge`, already an `allow` entry in this file.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wnstp2kTth7sGXfr8fXypc
Contract reviewServed-tier: ① Derived judgmentsRendered in-seat by the skills seat 1 session at the served tier the maintainer named on this date (the fable tier word at
② Semver levelNone — no release. ③ Boundary flags
Implemented-by: VERDICT: PASS Generated by Claude Code |
Fixes #9586
⛔ GOVERNED — this pull request is a DRAFT and stays one. The changed instruction-tree path is governed surface in this repository. Asked of the guard itself, in this worktree:
⇒ ⛔ never flipped ready, ⛔ never enqueued, ⛔ never armed with auto-merge, ⛔ never approved by a seat under any account. Under ruling C the claiming seat lands it only once an authorized APPROVED review exists.
维护者速读(草稿)
改了什么
一个文件、三行:
.claude/settings.json的permissions.deny从 14 条加到 17 条,新增点名三个 MCP GitHub 工具 ——update_pull_request、enable_pr_auto_merge、disable_pr_auto_merge。改完之后,本仓的 deny 数组与 objectstack 的逐元素相同、顺序也相同。allow与hooks两块字节未动。另附一个空 frontmatter 的 changeset(声明「不发版」,本仓惯例)。为什么改
这是 objectstack 已裁决条款的跨仓镜像,不是本仓的新主张。objectstack#18282 裁决 A(批次 #135 追认)把「声明即强制」扩到入队类:席位在两个板上真正用的入队通路只有 REST 的
PUT .../pulls/{n}/ccr/auto_merge(它就在同一个文件的allow里),所以把 MCP 的那两个入队工具关掉,不损失任何能力,只是把一条没人走的旁路封死。第三条
update_pull_request是本仓自己的事故教训:objectui#6183 里,一次只传reviewers的 MCP 调用顺带把 PR 的draft: false设了,于是一个受管草稿进了合并队列、零人工批准就落了地。本仓当时只镜像了 14 条内容写入类,这一条(objectstack 在 PR #18276 落地)和入队那两条(PR #18317)都没跟上 —— 本次一并补齐。风险与代价(含回滚)
gh pr ready、gh pr merge --auto与 REST 的 ccr 路径都不受影响。disable_pr_auto_merge…… 两个都要做」)。本卡的文件面只有.claude/settings.json,且 AGENTS.md 当前被两个在途 PR 持有(docs(agents): state the attribution-footer append as conditional on absence #10212 / docs(agents): 一次派发跑出来的 PR 停在 draft —— 给自行合并条款加第二条例外 #10213),所以本 PR ⛔ 不碰它,改由席位另立卡。方向是安全的一侧:配方失效会响亮地被拒,不会静默做错事。git revert单个 commit 即可,无数据迁移、无构建产物、无已发布包字节变化。席位意见
(留空,交席位定稿)
你要做的
确认「入队类 MCP 工具一并关掉」这个方向是你要的(objectstack 那边已经这么定了),然后在本 PR 上留一条 APPROVED review。批准之后由认领席翻 ready、入队落地,你不需要自己合并。上面那条⚠️ 只需要你知道,不需要你在这张卡里处理。
前提核验(动手前,在
origin/main0cf2d6644上实测)mcp__github__*,且三条都不在mcp__github__*;三条各命中 0 次,正控issue_write命中 1 次scripts/pm/check-settings-deny-roster.mjs)scripts/pm/全部内容是board-snapshot.mjs与check-half-states.mjs;全仓 grepsettings.json,scripts/与.github/内零个读取者references/rest-channel.md).claude/下不存在任何references目录;.claude/全部文件共 14 个(4 个 hook + 4 个 selftest +launch.json+settings.json+ 2 个 skill 的 4 个 md).claude/settings.json是不是被 pin 的上游移植文件(改它会红check:upstream-port-parity)scripts/upstream-port-pin.json13 条,.claude/下只 pin 了 8 个 hook/selftest 文件.claude/settings.json;#10212/#10213只有AGENTS.md(hunk 分别在 468 与 323 行区)执行判据(卡片的那一条)
推送之后,
GET /repos/objectstack-ai/objectui/contents/.claude/settings.json?ref=claude/issue-9586-settings-deny-auto-merge-mirror解码后的permissions.deny(HTTP 200,blob sha30c3367037de7ba000673e4da8caa2913a9c704c,size 2255):两条判据条目都在 ⇒ 判据满足。
改动的形状,实测而非声称
⛔ 没有手打重排。两处锚点文本替换,锚点各自唯一,其余字节不动:
顺序惯例是按类分组、不是字母序(实测:objectstack 把
update_pull_request紧挨create_pull_request、把入队对追加在末尾),本 PR 照同样的位置插入,结果两仓数组完全一致。两个读者都能解析:
node JSON.parse OK·python json.load OK。settings.json里 wire 的 4 个 hook 命令全部落在磁盘上(4/4 OK)—— 这个文件正是点名它们的那一个。门禁
门禁族由本仓自己推导:objectui 没有
scripts/pm/dispatch-gates.mjs(不存在),所以逐个读.github/workflows/*.yml的触发条件,取「会判到这两个路径」的全集。node JSON.parse OK·python json.load OKcheck-control-bytes(commit 后重跑)✅ check-control-bytes: OK (scanned 8217 tracked text file(s); skipped 85 binary).check-governed-queue-guard --self-testOK check-governed-queue-guard self-test: 185 cases passcheck-governed-queue-guard --testcheck-changeset-presence✅ No source or published contract of a released package changed in this range, so no changeset is owed.check-changeset-no-major✅ No changeset declares a major bump.check-changeset-overwrite✅ No pre-existing changeset was modified or deleted.check-lint-coverage✅ lint coverage: 46/46 packages linted, 0 with outstanding errors (0 total).check-entry-guard --self-test/ 全跑63 cases pass·108 scripts/ file(s) — no entry guard outside the baselinecheck-upstream-port-parity --self-test/ 全跑66 cases pass·13 ported file(s) match objectstack-ai/objectstack modulo their declared divergencescheck-bash32-floor --self-test/ 全跑160 cases pass·13 tracked shell file(s) … name no bash 4+ constructcheck-skills-paths✅ check-skills-paths: OK (88/89 stated path(s) resolve across 20 guide file(s); 1 baselined).check-new-cross-file-line-citationsVERDICT new-cross-file-line-citations: 0 new citation(s), enforcement report-only -> exit 0退出码一律在任何管道之前捕获(先重定向到文件,再读
$?)。不欠的两族,连同不欠的理由:
hook-selftests.yml的 paths 是.claude/hooks/**与它自己 —— 本 diff 不碰 hook 文件(hook 命令仍被settings.json点名,所以单独验了 4/4 落盘)。check-shell-escape-residue的SCAN_ROOTS是AGENTS.md、CLAUDE.md、skills、.claude/skills、content/docs五条,.changeset/**不在其中 ⇒ 新增的 changeset 不在它的总体里。lint 与 type-check:一次申报过的收窄,不是一次漏跑。 三条读数里的两条来自仪器,第二条被替换,如实写明:
eslint.config.js里每一个files块都限定在 TS/TSX(**/*.{ts,tsx}、scripts/**/*.{ts,tsx}、**/*.test.{ts,tsx}、**/__tests__/**/*.{ts,tsx}、**/examples/**/*.{ts,tsx}、**/*.tsx及三个具名单文件),没有 JSON 块,也没有 markdown 块。--format json,而是读自 diff 的扩展名普查 —— 本分支git diff --name-only两个文件,.json与.md各一,.ts/.tsx/.js/.mjs/.cjs命中 0 ⇒ 落在 eslint 总体里的文件数必然为 0。这个容器里 objectui 没有node_modules(共享检出与本 worktree 均无),而为一个 JSON + markdown 的 diff 做一次全仓pnpm install是这台共享机器上最贵的动作、且买不到任何判定。⇒ 这一格的仪器读数记 NOT MEASURED,理由如上;推翻它只需要一个.ts文件,而本 diff 没有。eslint.config.js里没有任何块设parserOptions.project或projectService)⇒ 本 diff 移不动任何它没触碰的文件的判定。同一读数覆盖type-check:tsc 的输入字节未变。仓级⚠️ 并且它会在本 PR 上跑满:
pnpm lint/pnpm type-check农场是 CI 的运行。lint.yml的相关性判断只排除**/*.md、content/**、docs/**、.changeset/**,而.claude/settings.json不在排除列里 ⇒should_run=true,安装之后的那半边门禁由 CI 如常判定。上述读数取自本分支最终 commit
45f22049。Acceptance notes
顺路看到、⛔ 本 PR 一律没动的:
# MCP 等价物:pull request update(draft: false) + enable_pr_auto_merge),一处在受管面段的补救条(「只调disable_pr_auto_merge会摘掉 auto-merge 但不取消队列成员资格,两个都要做」)。本 PR 落地之后,照这两处文本行事的席位会撞上运行时拒绝。objectstack 那边的对应修复是改它的通道对照表那一行(「auto-merge 备用 MCP 未拒」→「auto-merge MCP 锁 1 同拒」);本仓的等价文本恰好落在 AGENTS.md 里,而 AGENTS.md 不在本卡的文件面内,且当前被 docs(agents): state the attribution-footer append as conditional on absence #10212 / docs(agents): 一次派发跑出来的 PR 停在 draft —— 给自行合并条款加第二条例外 #10213 两个在途 PR 持有。⇒ 交席位另立卡,本 PR 不碰。方向安全:失效的配方会被响亮拒绝,不会静默做错。.changeset/issue-9418-write-identity-locks-port.md里有一句已经过时的话。 那份(空 frontmatter、永不消费的)历史声明写着四个「状态形」工具 —— 含update_pull_request与enable_pr_auto_merge—— 「stay allowed」。本 PR 之后其中两个不再 allowed。它是一份历史记录而非规程,读者为零,⛔ 不改、也不建议为它单独立卡;记在这里只是为了下一个读到那句话的人不被它误导。check-governed-queue-guard.mjs的拒绝文案仍写着「a human merge IS the review record」,而 AGENTS.md 已按裁决 C 改成「获授权批准后由认领席落地」。这条在 objectui PR docs(agents,settings): port the write-identity locks — deny MCP content writes, §9 states ruling C (objectui#9418) #9448 的 Acceptance notes 里已经报过一次,至今仍在;本 PR 只是再次撞见,不重复立卡。Clause-②: no本次实现所在的会话,写成散文以便在正文被改写后仍可追溯:
session_01Wnstp2kTth7sGXfr8fXypc。席位意见(
domain:skillsseat 1,sessionsession_01Wnstp2kTth7sGXfr8fXypc)建议:批准并由席位落地。 一个文件三行,把 objectui 的
permissions.deny补成与 objectstack 逐元素、同顺序相同(席位在复核工作树上解析两边数组比对为真);allow/hooks未动;三条都在卡的裁决范围内(objectstack#18282 裁决 A、批次 #135 追认;update_pull_request是卡正文点名的「本仓一并缺失」项)。不损失能力:两个板上席位真正用的入队通路只有 RESTPUT …/ccr/auto_merge,就在同一文件的allow里。卡留给取卡者的两个可选项 —— 移植 deny 计数门禁、频道表加一行 —— 本树都不存在对应物,均未做(新增门禁默认否)。你需要知道的一件事(不阻塞本 PR): 落地后 objectui
AGENTS.md:331 与 :531 两处配方文字仍写着enable_pr_auto_merge/disable_pr_auto_merge作为 MCP 等价物,届时会被响亮拒绝而非静默执行错;两个在途 AGENTS.md PR(#10212 :468、#10213 :323)不在那两段,不能顺带。席位身份过不了立卡门,已记到席位帖的维护者事项里,由你决定是否立卡。复核记录:PR 评论 5778587633(PASS,在席按服务档渲染);ACCEPT 在卡 objectui#9586。CI 读数:42 latest-per-name check runs — 39 success, 3 skipped, 0 in progress, 0 other。
Generated by Claude Code
Generated by Claude Code