Filed by the domain:devx @ objectui execution seat (objectstack-ai/objectui#5748), PM session session_012CZgmFFzqA9cX8tBMhvpFe, 2026-08-25 R30. Filed here rather than in objectui because the fix is a line in the pm-dispatch skill's platform fact table (.claude/skills/pm-dispatch/references/platform-readings.md), which lives in this repo — the incident was in objectui, the repair is not.
Unassigned. Grading and domain:* are the triage seat's; on the routing judgement above it looks like domain:skills (the fact table is under .claude/skills/**).
The reading
Calling the GitHub MCP tool update_pull_request with onlyreviewersalso sets draft: false. The tool sends the draft field whether or not the caller supplies it, so a call whose visible intent is "request a review" silently publishes a draft pull request.
Measured, not inferred — the same PR, twenty minutes apart, with one call between:
| time | reading | source |
|---|
| ~12:05Z | "draft": true, requested_reviewers: [] | pull_request_read on objectui#6183 |
| ~12:11Z | — | update_pull_request(pullNumber: 6183, reviewers: ["os-zhuang"]) — no draft argument passed |
| 12:45Z | "draft": false, requested_reviewers: ["os-zhuang"] | list_pull_requests on the same head ref |
Nothing else touched that PR in the window (it had no commits since 2026-08-24T23:07Z).
Why it is worth a card and not a note
⚠️It defeats the governed-surface rule by making the safe action the dangerous one. The pm-dispatch ACCEPT path requires, for a governed-surface PR: leave it draft, ⛔ never ready / enqueue / auto-merge, and request review from os-zhuang so it is visible in a human's queue. Those two instructions are given together — and performing the second, through this tool, breaks the first.
In this instance the PR (objectui#6183, an AGENTS.md change) went ready and entered objectui's merge queue, where it was found third in a five-PR chain. It was converted back to draft and did not land — origin/main was verified not to contain its commit. Caught by re-reading the queue refs for an unrelated reason, ⛔ not by any check: no gate fires on "a governed file is about to merge without a human", because the entire defence is seat discipline.
The window between "ready" and "merged" on a repo with an active merge queue is minutes.
Dispositions
- Fact-table line (cheapest, and the reason this is filed here): record in
references/platform-readings.md that update_pull_request un-drafts, and that any call against a draft PR must pass draft: true explicitly. Same register as the existing "list_issueslabels is a UNION, not an intersection" entry. - Skill text: the ACCEPT-path fork instructs seats to request review on a draft. That instruction is unsafe as written with this tool, so it should carry the
draft: true requirement inline where it is given — a fact-table line alone is not read at the moment of the call. - Consider whether requesting a reviewer needs this tool at all. A dedicated review-request path would not carry the
draft field; worth checking what else is available before hardening around the general-purpose updater.
⚠️ The same hazard applies to title, body, labels and any other single-field update_pull_request call on a draft — the reviewers case is just the one that has now happened. Whoever takes this should state the rule over the whole tool, not over one argument.
Related
- objectui#6183 — the affected PR; the incident is recorded on it in full.
- objectui#6069 — its card.
- The 2026-08-18 maintainer ruling establishing the governed surface (
docs/adr/**, .claude/**, skills/**, AGENTS.md, CLAUDE.md) as draft-only with human merge, cross-repo.
Filed by the
domain:devx@ objectui execution seat (objectstack-ai/objectui#5748), PM sessionsession_012CZgmFFzqA9cX8tBMhvpFe, 2026-08-25 R30. Filed here rather than in objectui because the fix is a line in the pm-dispatch skill's platform fact table (.claude/skills/pm-dispatch/references/platform-readings.md), which lives in this repo — the incident was in objectui, the repair is not.Unassigned. Grading and
domain:*are the triage seat's; on the routing judgement above it looks likedomain:skills(the fact table is under.claude/skills/**).The reading
Calling the GitHub MCP tool
update_pull_requestwith onlyreviewersalso setsdraft: false. The tool sends thedraftfield whether or not the caller supplies it, so a call whose visible intent is "request a review" silently publishes a draft pull request.Measured, not inferred — the same PR, twenty minutes apart, with one call between:
"draft": true,requested_reviewers: []pull_request_readon objectui#6183update_pull_request(pullNumber: 6183, reviewers: ["os-zhuang"])— nodraftargument passed"draft": false,requested_reviewers: ["os-zhuang"]list_pull_requestson the same head refNothing else touched that PR in the window (it had no commits since 2026-08-24T23:07Z).
Why it is worth a card and not a note
os-zhuangso it is visible in a human's queue. Those two instructions are given together — and performing the second, through this tool, breaks the first.In this instance the PR (objectui#6183, an
AGENTS.mdchange) went ready and entered objectui's merge queue, where it was found third in a five-PR chain. It was converted back to draft and did not land —origin/mainwas verified not to contain its commit. Caught by re-reading the queue refs for an unrelated reason, ⛔ not by any check: no gate fires on "a governed file is about to merge without a human", because the entire defence is seat discipline.The window between "ready" and "merged" on a repo with an active merge queue is minutes.
Dispositions
references/platform-readings.mdthatupdate_pull_requestun-drafts, and that any call against a draft PR must passdraft: trueexplicitly. Same register as the existing "list_issueslabelsis a UNION, not an intersection" entry.draft: truerequirement inline where it is given — a fact-table line alone is not read at the moment of the call.draftfield; worth checking what else is available before hardening around the general-purpose updater.title,body,labelsand any other single-fieldupdate_pull_requestcall on a draft — the reviewers case is just the one that has now happened. Whoever takes this should state the rule over the whole tool, not over one argument.Related
docs/adr/**,.claude/**,skills/**,AGENTS.md,CLAUDE.md) as draft-only with human merge, cross-repo.