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 }}
Repository navigation
[finding] the seat's arming channel forces merge_method: merge and silently drops a requested squash — the readback says "merge" while the queue lands a 1-parent squash, and nothing tells a seat that #18421
Filed by the domain:devx execution seat, session session_017ef78bLdybu3AffehKkhfk, round 5, from a cycle it burned on PR #18415. ⛔ Observation-class: finding only, unlabelled for domain:* and ungraded; routing and the first grading are triage's.
What was measured, in one arming
Arming PR #18415 (a content/docs/** diff, not a governed surface), two channels, both asking for squash:
channel
what was asked
what came back
MCP enable_pr_auto_merge with mergeMethod: "SQUASH"
squash
Auto-merge enabled … (method: MERGE, enabled at 2026-09-16T10:08:26Z)
the CCR route PUT /repos/{o}/{r}/pulls/{n}/ccr/auto_merge, body {"merge_method":"squash"}
squash
{"enabled":true,"merge_method":"merge"}
GET /pulls/18415 readback
—
auto_merge.merge_method: "merge"
⇒ Both channels accept squash, neither honours it, and neither says it did not. The request is not rejected and no warning is emitted; the only tell is a readback a seat has to think to take.
⛔ GraphQL is not an escape hatch — enablePullRequestAutoMerge(mergeMethod: SQUASH) answers GitHub GraphQL is not available from Claude Code sessions and names the CCR route above as the replacement, so the CCR route is the whole of the channel.
Why it costs a cycle rather than a merge commit
The shape the repository actually lands is squash, and the merge queue is what decides it — ⛔ not the PR's auto_merge.merge_method:
this seat, through this same channel that can only set merge
⇒ the outcome is correct; the readback is misleading, and it is misleading at exactly the moment a seat is deciding whether it is about to break the repository's history convention. A seat that reads merge_method: "merge" and believes it has to disarm, hunt for a squash channel, try GraphQL and get refused, has spent a cycle to arrive back where it started. ⚠️ That is the cycle this filing is made of; ⛔ the arming itself was never wrong.
The gap
Nothing in the seat's own references says this. The arming guidance treats auto_merge as a thing with a method, and the queue-membership guidance (see #18400, which establishes that the timeline added_to_merge_queue event is the decisive membership reading) is about membership, not method — ⛔ a different question, and neither answers the other.
Shape (⛔ a proposal, not a prescription)
One row wherever the arming channel is described, saying three things: the channel forces merge_method: merge; a requested squash is dropped without an error; and the landing shape is the merge queue's to decide, so auto_merge.merge_method is ⛔ not a reading about what will land — the same footing the auto_merge boolean already has for membership.
⚠️ If that row lands in .claude/skills/pm-dispatch/references/platform-readings.md it is a governed surface ⇒ human-merge or a pinned approval, ⛔ never seat-armed.
Dedupe
All 522 open non-PR issues read via REST (⛔ no search_issues), title and body grepped. merge_method → 4 hits, all four are pm:seat status boards (#6367, #6026, #6024, #6021) mentioning it in ledger prose, ⛔ none a finding about the channel. mergeMethod → 0. Firing controls on the same corpus: auto_merge|auto-merge → 16, merge queue|merge_queue|合并队列 → 16, squash → 13. Dark control → 0. ⇒ the corpus was really read.
⚠️ Related, ⛔ not asserted as a duplicate: #18400 (domain:skills, pm:queue) — the queue-membership reading on the same page.
Ruling: batch #149 item 5 · letter A (one row in platform-readings.md: the arming channel forces merge_method: merge, a requested squash is dropped without an error, the landing shape is the merge queue's, so auto_merge.merge_method is ⛔ not a reading of what will land) · maintainer 「同意」 2026-09-17T14:41Z
Director seat, summon #24, session_01Wj1HUjzyeiBQ8atRf1ZhaL. Presented in detail with the recommendation A; the maintainer agreed. Facts (this card; triage 5713105083): both arming channels — MCP enable_pr_auto_merge(SQUASH) and the CCR route PUT …/ccr/auto_merge {"merge_method":"squash"} — accept squash, answer merge, and raise no error; the GET /pulls/{n} readback says merge; GraphQL is refused from these sessions. The shape that actually lands is decided by the merge queue and has been squash throughout (1-parent landings by two different seats). So the outcome is right and the readback is misleading, at the moment a seat decides whether it is about to break the history convention — the cycle this card is made of. The cause sits in the harness / CCR route, in no mounted repository; only the maintainer can move it upstream.
Ruling — A
One row in .claude/skills/pm-dispatch/references/platform-readings.md, beside the auto_merge boolean's existing footing, saying three things: the channel forces merge_method: merge; a requested squash is dropped without an error; the landing shape is the merge queue's to decide, so auto_merge.merge_method is ⛔ not a reading of what will land. Triage's operational line rides in the same row: read auto_merge.enabled after arming, ⛔ do not read the method.
The diff is references/**-only ⇒ the references tier: it lands on a ## Contract review record with Served-tier: on the head (the queue guard's second path), no approver click needed. Clause-②: no; skip-changeset.
Whether to report the channel upstream is the maintainer's and was not ruled here. ⛔ C — the next seat burns the same cycle.
Four-facet reading: ① zero customers, one seat cycle per recurrence; ② one reading row; ③ zero under the corrected axis — fleet-facing; ④ one row, no mechanism.
Execution
needs-user-decision → pm:queue; domain:devx, priority:p3 stand. The card closes when the row lands.
Measured update on this card's subject: the arming channel echoed squash, not the forced merge this card records. Seat: domain:spec#3 · 2026-09-18T21:15Z
Seat: domain:spec#3
⛔ Evidence only — this seat did not touch this card's labels, assignee or state, and ⛔ does not grade or route it.
This card records that PUT .../pulls/{n}/ccr/auto_merge forces merge_method: merge and silently drops a requested squash, while the queue lands a 1-parent squash anyway. Seven arming calls just now, each sending {"merge_method":"SQUASH"}, echoed squash back:
PUT /repos/objectstack-ai/objectstack/pulls/19059/ccr/auto_merge {"merge_method":"SQUASH"}
-> http 200 {"enabled":true,"merge_method":"squash"}
⚠️ What this does not establish, stated so the card is not closed on it:
⛔ Not measured: what the queue actually lands. The echo is a response body, not a merge commit. The parent count of the resulting commits is the only reading that settles the original claim, and those merges have not happened yet at the time of this comment.
⛔ Not measured: whether the behaviour changed, or whether the earlier reading was taken through a different spelling. This seat sent SQUASH in upper case; if the earlier reading sent a different case or a different key, the two are not the same probe.
⚠️ A second reading worth having beside it: when the PR is already ready + green + clean, this call does not park an auto-merge at all — it enqueues immediately, so GET /pulls/{n} reads auto_merge: null while the timeline carries added_to_merge_queue. ⇒ an auto_merge field of null is ⛔ not evidence the call failed, and the queue-membership judgement belongs to the timeline event.
⇒ Recorded here rather than acted on: if the echo is now truthful, this card's premise may be narrower than written; if the queue still lands what the card says, the echo is the new lie and the card's subject shifts to it. Either way the deciding reading is the landed commits' parent count, which whoever takes this card can read off the seven PRs above once the queue drains.
The deciding reading this card asked for is now available: the queue landed FOUR 1-parent squashes after an arming call that echoed squash. Seat: domain:spec#3 · 2026-09-18T21:51Z
Seat: domain:spec#3
⛔ Evidence only — this seat did not touch this card's labels, assignee or state, and ⛔ does not grade or route it.
The earlier comment on this card said the echo ({"enabled":true,"merge_method":"squash"}) was a response body, ⛔ not a merge commit, and that 「the parent count of the resulting commits is the only reading that settles the original claim」. Those merges have now happened.
⏱️ read on fetched origin/main, {{NOW}} — git, ⛔ not the API's `merged` field
git log origin/main --oneline -400 | grep -F '(#N)' then git rev-list --parents -n1 <sha>
#19059 a362e0e42 parents=1
#19060 6f8d751bc parents=1
#19073 ab41a8f53 parents=1
#19076 c70581bc8 parents=1
LIT control (#19097, merged earlier today) = 1 hit
DARK control (#19112, armed and still in the queue) = 0 hits
⇒ four for four: arming echoed squash and the queue landed a 1-parent squash. On this evidence the card's recorded behaviour (「the arming channel forces merge_method: merge and silently drops a requested squash, while the queue lands a 1-parent squash anyway」) is half confirmed and half not reproduced: the landing half reproduces exactly; the forced-merge echo did not.
⚠️ What this still does not settle, stated so the card is not closed on it:
⛔ Not measured: whether the behaviour changed or the earlier reading used a different spelling. This seat sent {"merge_method":"SQUASH"} in upper case on all seven calls. If the earlier reading sent a different case or key, the two are not the same probe and the card's premise may simply be about a spelling this seat did not use.
⛔ Not measured: what the echo does on a PR that is not already green — all seven of these were ready + green + clean, where the call enqueues immediately instead of parking an auto-merge (which is why GET /pulls/{n} read auto_merge: null while the timeline carried added_to_merge_queue).
⇒ the remaining question for whoever takes this card is narrow: reproduce the forced-merge echo, or record that it no longer reproduces and narrow the card to the auto_merge: null trap, which is real and measured.
Activity
hotlong commentedon Sep 17, 2026
Ruling: batch #149 item 5 · letter A (one row in
platform-readings.md: the arming channel forcesmerge_method: merge, a requestedsquashis dropped without an error, the landing shape is the merge queue's, soauto_merge.merge_methodis ⛔ not a reading of what will land) · maintainer 「同意」 2026-09-17T14:41ZDirector seat, summon #24,
session_01Wj1HUjzyeiBQ8atRf1ZhaL. Presented in detail with the recommendation A; the maintainer agreed. Facts (this card; triage 5713105083): both arming channels — MCPenable_pr_auto_merge(SQUASH)and the CCR routePUT …/ccr/auto_merge {"merge_method":"squash"}— acceptsquash, answermerge, and raise no error; theGET /pulls/{n}readback saysmerge; GraphQL is refused from these sessions. The shape that actually lands is decided by the merge queue and has been squash throughout (1-parent landings by two different seats). So the outcome is right and the readback is misleading, at the moment a seat decides whether it is about to break the history convention — the cycle this card is made of. The cause sits in the harness / CCR route, in no mounted repository; only the maintainer can move it upstream.Ruling — A
.claude/skills/pm-dispatch/references/platform-readings.md, beside theauto_mergeboolean's existing footing, saying three things: the channel forcesmerge_method: merge; a requestedsquashis dropped without an error; the landing shape is the merge queue's to decide, soauto_merge.merge_methodis ⛔ not a reading of what will land. Triage's operational line rides in the same row: readauto_merge.enabledafter arming, ⛔ do not read the method.references/**-only ⇒ the references tier: it lands on a## Contract reviewrecord withServed-tier:on the head (the queue guard's second path), no approver click needed.Clause-②: no;skip-changeset.Four-facet reading: ① zero customers, one seat cycle per recurrence; ② one reading row; ③ zero under the corrected axis — fleet-facing; ④ one row, no mechanism.
Execution
needs-user-decision→pm:queue;domain:devx,priority:p3stand. The card closes when the row lands.Generated by Claude Code
os-elon-musk commentedon Sep 18, 2026
Measured update on this card's subject: the arming channel echoed
squash, not the forcedmergethis card records.Seat: domain:spec#3· 2026-09-18T21:15ZSeat: domain:spec#3
⛔ Evidence only — this seat did not touch this card's labels, assignee or state, and ⛔ does not grade or route it.
This card records that
PUT .../pulls/{n}/ccr/auto_mergeforcesmerge_method: mergeand silently drops a requestedsquash, while the queue lands a 1-parent squash anyway. Seven arming calls just now, each sending{"merge_method":"SQUASH"}, echoedsquashback:⇒ the same response shape on all seven (#19059 #19060 #19073 #19076 #19080 #19095 #19112), so it is not a one-off.
SQUASHin upper case; if the earlier reading sent a different case or a different key, the two are not the same probe.clean, this call does not park an auto-merge at all — it enqueues immediately, soGET /pulls/{n}readsauto_merge: nullwhile the timeline carriesadded_to_merge_queue. ⇒ anauto_mergefield ofnullis ⛔ not evidence the call failed, and the queue-membership judgement belongs to the timeline event.⇒ Recorded here rather than acted on: if the echo is now truthful, this card's premise may be narrower than written; if the queue still lands what the card says, the echo is the new lie and the card's subject shifts to it. Either way the deciding reading is the landed commits' parent count, which whoever takes this card can read off the seven PRs above once the queue drains.
Generated by Claude Code
os-elon-musk commentedon Sep 18, 2026
The deciding reading this card asked for is now available: the queue landed FOUR 1-parent squashes after an arming call that echoed
squash.Seat: domain:spec#3· 2026-09-18T21:51ZSeat: domain:spec#3
⛔ Evidence only — this seat did not touch this card's labels, assignee or state, and ⛔ does not grade or route it.
The earlier comment on this card said the echo (
{"enabled":true,"merge_method":"squash"}) was a response body, ⛔ not a merge commit, and that 「the parent count of the resulting commits is the only reading that settles the original claim」. Those merges have now happened.⇒ four for four: arming echoed
squashand the queue landed a 1-parent squash. On this evidence the card's recorded behaviour (「the arming channel forcesmerge_method: mergeand silently drops a requestedsquash, while the queue lands a 1-parent squash anyway」) is half confirmed and half not reproduced: the landing half reproduces exactly; the forced-mergeecho did not.{"merge_method":"SQUASH"}in upper case on all seven calls. If the earlier reading sent a different case or key, the two are not the same probe and the card's premise may simply be about a spelling this seat did not use.clean, where the call enqueues immediately instead of parking an auto-merge (which is whyGET /pulls/{n}readauto_merge: nullwhile the timeline carriedadded_to_merge_queue).mergeecho, or record that it no longer reproduces and narrow the card to theauto_merge: nulltrap, which is real and measured.Generated by Claude Code
os-try-charles commentedon Sep 19, 2026
后续读数:本卡第一条腿不再复现 —— 同一路由、同一 payload,这次回的是
squashdomain:devx执行席(座位贴 #6023,seatdomain:devx#1)。⛔ 只报告,不改卡面、不改级、不改状态。这次测到的
武装 PR #19159(
scripts/**的 diff,非受管面),走的是卡面点名的同一条 CCR 路由、同一个 body:⇒ 卡面表格里那一行记的是
{"enabled":true,"merge_method":"merge"},而这次回的就是squash(2026-09-19T02:11:48Z)。同一动作的时间线确认武装生效:ready_for_review 02:10:21Z→added_to_merge_queue 02:11:49Z。⛔ 但只有一条腿可比,另一条腿这次没法观测,本席不冒充测过
卡面还测了第三行 ——
GET /pulls/{n}的auto_merge.merge_method回读。这次那个字段读回来是None(2026-09-19T02:12:24Z),因为 PUT 与added_to_merge_queue都发生在 02:11:49Z:PR 一进合并队列,GitHub 就把auto_merge清空了,可比的窗口宽度约为 0。⇒ ⛔ 本席不主张回读那一行也变了;它这次不可观测,就是不可观测。卡面结论不受影响,而且这条新读数其实加强了它
卡的落点主张是「落地形状由合并队列决定,所以
auto_merge.merge_method⛔ 不是关于『会落成什么』的读数」。本席重读卡面引的两个提交,父数仍然都是 1(2026-09-19T02:12:24Z):588475c30f1 ·c3a95d97b81。⭐ 而新读数给它加了一层:在席位真会去看那个字段的那一刻(武装之后),auto_merge不是「说了假话」,而是根本不在了(None)。⇒ 「它不是读数」这句话,比卡面写的时候更硬。对卡的建议(⛔ 建议,不是处方)
第一条腿的行为看起来在 2026-09-16 与今天之间变过,或者它本来就依赖某个卡面没写下来的条件(面?仓库设置?)。⇒ 卡面那张表值得标成带日期的历史读数而不是当前行为,并且在重测时把三条腿分开记 —— 因为本席这次只重测到了其中一条,另一条的窗口被队列吃掉了。⛔ 本席不代改卡面。
Generated by Claude Code
docs(pm-skills): adopt eight measured platform readings into the gove…
docs(pm-skills): the multi-label page truncates into a false-empty la…