Maintainer direct dispatch — the maintainer (pm@objectstack.ai) in the skills seat's chat session at 2026-09-13T16:14Z, verbatim: 「机制层的五道锁 现在就派发处理」, after the seat's analysis of the 2026-09-13 account suspension (os-musk): the root cause is the WRITE IDENTITY — content written through the MCP GitHub tools is authored by the claude.ai account's linked GitHub user (measured: os-musk's 12 hidden cards; #18045 and objectui#9404 authored os-project-manager; PR #18051 authored os-project-manager; the services seat's PRs #18035/#18039/#18043 authored hotlong), while content written through the REST proxy is authored by the App (claude[bot], measured on every REST comment of the day). Concurrency amplified the shape; identity is what a suspension acts on. Filed and claimed by the skills seat (session session_01DAcomhvR9kKizeYgg89Vo8) under the direct-dispatch channel; this card carries locks 1–4 (governed rules layer, one approval); lock 5 is its own card.
Dedupe keywords: write identity, claude[bot], MCP write tools, permissions.deny, batch default 2, REST proxy.
Lock 1 — MCP GitHub content writes unreachable (.claude/settings.json)
Add a permissions.deny list naming every MCP GitHub tool that CREATES content or history: mcp__github__issue_write, mcp__github__create_pull_request, mcp__github__add_issue_comment, mcp__github__add_comment_to_pending_review, mcp__github__add_reply_to_pull_request_comment, mcp__github__pull_request_review_write, mcp__github__push_files, mcp__github__create_or_update_file, mcp__github__delete_file, mcp__github__create_branch, mcp__github__sub_issue_write, mcp__github__merge_pull_request, mcp__github__create_repository, mcp__github__fork_repository. KEEP allowed (state, not content; some have no REST equivalent through the proxy): mcp__github__update_pull_request (REST cannot un-draft), mcp__github__enable_pr_auto_merge / disable_pr_auto_merge, mcp__github__actions_run_trigger, mcp__github__resolve_review_thread, every read tool. The dev measures whether Claude Code honours a repo-level permissions.deny for MCP tool names in this environment (read the Claude Code settings docs; state the reading) and records it in references/platform-readings.md if a row is owed (references tier).
Lock 2 — devs make no board API writes beyond three (.claude/agents/os-dev.md)
Rule: every GitHub write a dev makes goes through the REST proxy (curl with the environment GITHUB_TOKEN, Content-Type: application/json); the whole budget is git push + one POST /pulls (draft) + POST /issues/{n}/labels (skip-changeset) + one os-dev-report comment; ⛔ no MCP GitHub write tool, ⛔ no board enumeration (card and thread via the payload channel or repo-scoped single-card reads). The report gains a field api_writes (count + endpoints) that the seat verifies. Replace the :51–:58 dedupe-channel lines (already stale after ruling ③: the filer attaches keywords) so the file stays at 403/403.
Lock 3 — batch default 2 (SKILL.md :60; core-rules.md mirror if its line states a default)
「默认 3」 → 「默认 2」; the maintainer ceiling 5 unchanged; the seat post protocol line 「accelerator armed while devs are in flight」 unchanged. Maintainer's own words on the services seat today: 「当前任务处理完,后续并发降到2」.
Lock 4 — account roles (SKILL.md 〈全体座位的不变量〉 or 〈座位贴协议〉, one line; core-rules.md mirror)
User accounts do three things only — assignee (a label-state, never content), authorized approval, the maintainer's own hand; ⛔ a seat or dev never writes content as a user account; ⛔ an approver account (os-zhuang, hotlong) never runs a seat and is never the linked user of a seat's claude.ai account. Content identity = the session ID in the body (the Claim: Session: line, Reviewed-by:, the filing header), never the author field.
Budgets and gates
Every file is at its ceiling (SKILL.md 812/812, widest row 342 B; core-rules.md 151/151; os-dev.md 403/403): net 0 lines per file, density payments in the same file named per commit, 120-byte cap, frame block :733–:754 md5 3327d02c56f8a0eca88569dad2270f32 unchanged; check:pm-skill-ratchet, check:skill-frame-sync, check:pm-governed-prose, check:pm-skill-id-lint green. One commit per lock, each quoting the ruling. .claude/settings.json is a governed path (rules layer) — the PR stays draft until an authorized approval; the skills seat lands it under ruling C.
Executable criterion
git show origin/main:.claude/settings.json | grep -c mcp__github__issue_write 0 → 1 (inside permissions.deny); git grep -c '默认 \2`' .claude/skills/pm-dispatch/SKILL.md0 → 1 and 「默认3」 1 → 0; git grep -c 'api_writes' .claude/agents/os-dev.md` 0 → 1; a line naming 「approver」 / 「批准账号」 with 「never runs a seat」 semantics 0 → 1 in SKILL.md; lit controls on neighbouring phrases unchanged.
Generated by Claude Code
Maintainer direct dispatch — the maintainer (pm@objectstack.ai) in the skills seat's chat session at 2026-09-13T16:14Z, verbatim: 「机制层的五道锁 现在就派发处理」, after the seat's analysis of the 2026-09-13 account suspension (
os-musk): the root cause is the WRITE IDENTITY — content written through the MCP GitHub tools is authored by the claude.ai account's linked GitHub user (measured: os-musk's 12 hidden cards; #18045 and objectui#9404 authoredos-project-manager; PR #18051 authoredos-project-manager; the services seat's PRs #18035/#18039/#18043 authoredhotlong), while content written through the REST proxy is authored by the App (claude[bot], measured on every REST comment of the day). Concurrency amplified the shape; identity is what a suspension acts on. Filed and claimed by the skills seat (sessionsession_01DAcomhvR9kKizeYgg89Vo8) under the direct-dispatch channel; this card carries locks 1–4 (governed rules layer, one approval); lock 5 is its own card.Dedupe keywords:
write identity,claude[bot],MCP write tools,permissions.deny,batch default 2,REST proxy.Lock 1 — MCP GitHub content writes unreachable (
.claude/settings.json)Add a
permissions.denylist naming every MCP GitHub tool that CREATES content or history:mcp__github__issue_write,mcp__github__create_pull_request,mcp__github__add_issue_comment,mcp__github__add_comment_to_pending_review,mcp__github__add_reply_to_pull_request_comment,mcp__github__pull_request_review_write,mcp__github__push_files,mcp__github__create_or_update_file,mcp__github__delete_file,mcp__github__create_branch,mcp__github__sub_issue_write,mcp__github__merge_pull_request,mcp__github__create_repository,mcp__github__fork_repository. KEEP allowed (state, not content; some have no REST equivalent through the proxy):mcp__github__update_pull_request(REST cannot un-draft),mcp__github__enable_pr_auto_merge/disable_pr_auto_merge,mcp__github__actions_run_trigger,mcp__github__resolve_review_thread, every read tool. The dev measures whether Claude Code honours a repo-levelpermissions.denyfor MCP tool names in this environment (read the Claude Code settings docs; state the reading) and records it inreferences/platform-readings.mdif a row is owed (references tier).Lock 2 — devs make no board API writes beyond three (
.claude/agents/os-dev.md)Rule: every GitHub write a dev makes goes through the REST proxy (
curlwith the environmentGITHUB_TOKEN,Content-Type: application/json); the whole budget isgit push+ onePOST /pulls(draft) +POST /issues/{n}/labels(skip-changeset) + oneos-dev-reportcomment; ⛔ no MCP GitHub write tool, ⛔ no board enumeration (card and thread via the payload channel or repo-scoped single-card reads). The report gains a fieldapi_writes(count + endpoints) that the seat verifies. Replace the :51–:58 dedupe-channel lines (already stale after ruling ③: the filer attaches keywords) so the file stays at 403/403.Lock 3 —
batchdefault 2 (SKILL.md:60;core-rules.mdmirror if its line states a default)「默认
3」 → 「默认2」; the maintainer ceiling5unchanged; the seat post protocol line 「accelerator armed while devs are in flight」 unchanged. Maintainer's own words on the services seat today: 「当前任务处理完,后续并发降到2」.Lock 4 — account roles (
SKILL.md〈全体座位的不变量〉 or 〈座位贴协议〉, one line;core-rules.mdmirror)User accounts do three things only — assignee (a label-state, never content), authorized approval, the maintainer's own hand; ⛔ a seat or dev never writes content as a user account; ⛔ an approver account (
os-zhuang,hotlong) never runs a seat and is never the linked user of a seat's claude.ai account. Content identity = the session ID in the body (theClaim:Session:line,Reviewed-by:, the filing header), never the author field.Budgets and gates
Every file is at its ceiling (SKILL.md 812/812, widest row 342 B; core-rules.md 151/151; os-dev.md 403/403): net 0 lines per file, density payments in the same file named per commit, 120-byte cap, frame block :733–:754 md5
3327d02c56f8a0eca88569dad2270f32unchanged;check:pm-skill-ratchet,check:skill-frame-sync,check:pm-governed-prose,check:pm-skill-id-lintgreen. One commit per lock, each quoting the ruling..claude/settings.jsonis a governed path (rules layer) — the PR stays draft until an authorized approval; the skills seat lands it under ruling C.Executable criterion
git show origin/main:.claude/settings.json | grep -c mcp__github__issue_write0 → 1 (insidepermissions.deny);git grep -c '默认 \2`' .claude/skills/pm-dispatch/SKILL.md0 → 1 and 「默认3」 1 → 0;git grep -c 'api_writes' .claude/agents/os-dev.md` 0 → 1; a line naming 「approver」 / 「批准账号」 with 「never runs a seat」 semantics 0 → 1 in SKILL.md; lit controls on neighbouring phrases unchanged.Generated by Claude Code