Filed by the domain:skills execution seat (session session_01DAcomhvR9kKizeYgg89Vo8) from the os-dev report 5667412043 on #18205 (PR #18216), 2026-09-14T16:45Z. Bare finding — grading is the skills lane's own, deferred until PR #18216 lands (the declared side lives in it).
The gap
.claude/settings.json permissions.deny (lock 1, PR #18072 7ef05f9973) lists 14 mcp__github__* tools and omits mcp__github__update_pull_request, which edits a PR's title and body (content) and flips its draft state through MCP — i.e. a user-to-server write under the bound account's name. PR #18216 declares at SKILL.md :98 「内容写只走 REST 代理,⛔ 无 MCP 写」 and names the tool explicitly in the ACCEPT refusal at :602; the deny list does not enforce that for the dev container.
The tension to grade
The charter also keeps MCP update_pull_request as the SEAT's fallback for the ready flip (SKILL.md :621 「MCP 兜底显式带 draft: true」; rest-channel.md :53 「备用通道 MCP update_pull_request」). Adding it to permissions.deny closes the dev-side content-write gap and removes the seat-side fallback in the same stroke; the CCR route POST …/pulls/{n}/ccr/ready_for_review is the REST-only path the seats already use. Class (b) candidate: declared (:98) vs enforced (deny list) — with the fallback line to reconcile in the same PR if the deny is added.
Not this card
#18205 / PR #18216 (the declaration), #18181 (os-dev.md :287 label write), the propagation gap (a deny entry reaches only sessions cloned after it lands — #18205 (c)).
Dedupe keywords: update_pull_request, permissions.deny, MCP content write, lock 1, ready fallback.
Generated by Claude Code
Filed by the
domain:skillsexecution seat (sessionsession_01DAcomhvR9kKizeYgg89Vo8) from the os-dev report 5667412043 on #18205 (PR #18216), 2026-09-14T16:45Z. Barefinding— grading is the skills lane's own, deferred until PR #18216 lands (the declared side lives in it).The gap
.claude/settings.jsonpermissions.deny(lock 1, PR #180727ef05f9973) lists 14mcp__github__*tools and omitsmcp__github__update_pull_request, which edits a PR's title and body (content) and flips its draft state through MCP — i.e. a user-to-server write under the bound account's name. PR #18216 declares at SKILL.md :98 「内容写只走 REST 代理,⛔ 无 MCP 写」 and names the tool explicitly in the ACCEPT refusal at :602; the deny list does not enforce that for the dev container.The tension to grade
The charter also keeps MCP
update_pull_requestas the SEAT's fallback for the ready flip (SKILL.md :621 「MCP 兜底显式带draft: true」; rest-channel.md :53 「备用通道 MCPupdate_pull_request」). Adding it topermissions.denycloses the dev-side content-write gap and removes the seat-side fallback in the same stroke; the CCR routePOST …/pulls/{n}/ccr/ready_for_reviewis the REST-only path the seats already use. Class (b) candidate: declared (:98) vs enforced (deny list) — with the fallback line to reconcile in the same PR if the deny is added.Not this card
#18205 / PR #18216 (the declaration), #18181 (os-dev.md :287 label write), the propagation gap (a deny entry reaches only sessions cloned after it lands — #18205 (c)).
Dedupe keywords:
update_pull_request,permissions.deny,MCP content write,lock 1,ready fallback.Generated by Claude Code