Skip to content

feat(fleet-write): pr_create carries labels; os-dev declares skip-changeset in the create's stroke - #24175

Merged
objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-24157-skip-changeset-in-pr-create
Oct 17, 2026
Merged

objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-24157-skip-changeset-in-pr-create

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #24157
Clause-②: no

What this PR does

Two parts, one PR, the card's route 1 + 3 (fold skip-changeset into the pr_create stroke; rewrite the 「席位代做」 line). Option 4 (relaxing Check Changeset) is a gate change and is not here.

1. The relay op — pr_create carries labels

  • scripts/pm/fleet-write/ops.mjs: pr_create gains an optional labels list. It becomes a later request of the SAME action, POST /repos/REPO/issues/NUMBER/labels with fromAnswer: 'number' and labelled: [...a.labels] — the exact shape the assignees leg has (assigned). The row still spends pull-requests with alsoSpends: ['issues'], so the token minted for the stroke already covers the labels POST; PERMISSIONS is unchanged and the workflow's mint step needed no edit.
  • scripts/pm/fleet-write/validate.mjs: the typed check is the one labels_add already uses — FIELDS.labels (array of 1..20 strings, each ≤ 50 bytes, no duplicates) is applied to any op whose key list admits labels, so adding labels to the row's optional is the whole validator change; the self-test gains the pr_create labels cases beside the assignees ones, the minimal-shape ledger names labels, and the 「exactly ONE descriptor reads an earlier answer」 pin becomes 「exactly TWO — assignees then labels」, with a new pin that every such leg is an additive POST to /assignees or /labels, never the whole-set replace.
  • scripts/pm/fleet-write/execute.mjs — the one place that had to learn the leg (the dispatch order assumed none): ① requestLanded judges a labelled descriptor's 2xx against the names sent — the labels endpoint answers the pull's whole label set, so a name it lacks is a FAILED action naming it, never a quiet partial; more than sent (the Auto Label workflow's documentation / size/*) is a landing. ② resultOf prints the labels as the platform lists them on that row. ③ fromAnswer legs are now filled from the action's FIRST answer (the create's), not the PREVIOUS request's: with both legs present the previous answer of the labels leg would have been the assignee POST's issue object, which happens to carry a number but is not the create. The self-test pins the label leg landing on the number the create answered while the assignee answer carries a different one.
  • scripts/pm/fleet-write/dispatch.mjs and .github/workflows/fleet-write.yml need nothing: dispatch's self-test is green unchanged (222 cases), and the workflow only runs validate.mjs --from-env --github-output then execute.mjs.

2. The dev contract — .claude/agents/os-dev.md, 404 → 404 lines (ceiling 404, headroom 0)

Four lines rewritten in place, no line added or removed. Each line's old text and where every dropped clause survives:

line before after dropped clause → survival
61 写预算四笔:git push、pr_create(draft,含 assignee)、label-write(仅标签)、os-dev-report 评论 写预算三笔:git push、pr_create(draft,含 assignee 与 labels)、os-dev-report 评论 label-write(仅标签) as a budgeted stroke → it is no longer a default stroke; the late-label case is named on line 303
303 objectstack:标签是真实机制,打标签是你的默认步骤,PR 一开出就打;派发词可收窄或禁写 objectstack:skip-changeset 以 pr_create 的 labels 同笔申报;后发现的标签才走 label-write.mjs 「打标签是你的默认步骤,PR 一开出就打」→ strengthened: declared in the create's stroke, not after; 「标签是真实机制」→ the premise lines 306–307 rest on (a gate reads the label); 「派发词可收窄或禁写」→ line 304 verbatim: 范围 = 派发词点名的标签 + …;禁写或交集为空 ⇒ 零写并报告
305 写恒经 scripts/pm/label-write.mjs:取现集、加法 POST、回读比 union、缺者重挂一次并报告 该腿的回读是中继回报的行:答案须列出每个送出的标签,缺者该笔 FAILED、不发后续动作 the four steps are what label-write.mjs itself performs and prints on every invocation (its header: 「the four-step label write, as ONE spelling … Every invocation performs all four … re-added ONCE and REPORTED」), so the contract line was a mirror of the tool header, which AGENTS.md makes the authority; 「写恒经 scripts/pm/」→ line 55 (GitHub 写一律经 scripts/pm/ 写工具) and line 303 names the tool for the late-label case
309 分类器拒外部写 ⇒ 停手,deviations 记命令与拒因,席位代做;⛔ 不换路重发(curl/MCP/手工) 分类器拒外部写 ⇒ 停手,deviations 记命令与拒因,席位只转维护者定夺;⛔ 不换路重发 「席位代做」→ replaced by design (the card's finding: the seat's harness forbids substituting for a refused action); 「(curl/MCP/手工)」→ line 308 「不走 MCP」, AGENTS.md 「⛔ Never a bare curl / fetch / gh api -X POST… write」, and 「不换路重发」 covers any manual route

Lines 61 / 303 / 305 / 309 measure 104 / 118 / 119 / 117 bytes against the 120-byte line budget. No re-wrap, no merge, no ceiling raise.

Mechanism assumptions, measured

  • (a) confirmed at the base bd4276a91 (origin/main had advanced from the order's 697301491 when the worktree was cut): pr_create had optional: ['body', 'assignees'] only; the filer's 「the relay's pr_create op takes labels」 was false, so option 1 needed the op leg.
  • (b) stands, and nothing here can prove more: the classifier refusal was measured once (PR fix(example-todo): drop objectName from the two schedule start nodes #24153 refused, PR fix(showcase): the invoice print page heads its line-items table with labels, not field names #24139 allowed, identical label-write.mjs command). This PR cannot show the classifier will accept a pr_create carrying labels; the measured fact is that the pr_create stroke has not been refused since the assignee precedent pm tooling: the os-dev's PR-assignee write (label-write.mjs --assign) is refused by the auto-mode permission classifier on 4 of 12 objectui PRs in one seat's session — same command, same brief, nondeterministic #22467. This PR's own skip-changeset had to go the OLD way (label-write.mjs) because a PR cannot use the leg it introduces.
  • (c) confirmed: pr-automation.yml writes size/* and the path labels by additive POST (the Auto Label and Check PR Size jobs), so the two never overwrite each other. Check Changeset reads the label live (a re-read plus a settling read, because the frozen opened payload cannot see a label applied after creation; its own comment measures label latency at 10–45 s after creation). The leg lands inside the relay's own stroke, seconds after the create, so it falls inside that settling window — and the labeled event re-triggers the job in any case.
  • (d) run — see Verification. (e) read the current lines (the card's quotation of line 61 and the labels block matched the tree at the base).
  • Falsified: 「read execute.mjs … to confirm nothing else must learn the new leg」 — it did: without labelled the executor would have passed a 200 whose answer lacks the label (ablation B, below, shows exactly that quiet partial), and the fill source had to move from the previous answer to the create's (ablation A).

Verification (final commit f9e63d6c3)

Relay self-tests (rule ⑤ — the edited scripts' own suites; no *.test.* file names them):

  • node scripts/pm/fleet-write/validate.mjs --self-test → exit 0, 158 cases / 11 batteries (was 152).
  • node scripts/pm/fleet-write/execute.mjs --self-test → exit 0, 128 cases / 16 batteries (was 120; the assignees-leg battery is re-declared in SELF_TEST_BATTERIES as the assignees-and-labels battery, pin 11 → 19).
  • node scripts/pm/fleet-write/dispatch.mjs --self-test → exit 0, 222 cases / 20 batteries (unchanged).
  • ops.mjs has no --self-test of its own (its pins live in the validate and execute suites).

Ablations — each via node scripts/ablation-replace.mjs (anchor hit ×1, blob changed, command run, restore proven by blob == HEAD blob and git diff HEAD empty; no dist/ is involved, these are plain node scripts):

  • A execute.mjs: if (opener === null) opener = r; → opener = r; (back to previous-answer fill). Expected red; observed 2 of 128 red — 「at the number the CREATE answered, not the assignee answer's」 and the row-text case. Blob f246498… → af59de9… → restored f246498….
  • B execute.mjs: const missing = req.labelled.filter( → const missing = [].filter(. Expected red; observed 1 of 128 red — 「a 200 whose answer lacks a name sent is a FAILED action … never a quiet partial」 (the run passed with exit 0 and 3 writes under the mutation: the quiet partial). Blob f246498… → 69e1572… → restored f246498….
  • C ops.mjs: optional: ['body', 'assignees', 'labels'] → ['body', 'assignees']. Expected red; observed 6 of 158 validator cases red (the labels acceptance cases, the minimal-shape ledger, the two-descriptor pin). Blob 6ad2cb6… → 83deec1… → restored 6ad2cb6….

Gates — derived at f9e63d6c3 with node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (no paths; 48 families, the path-named derivation at the base plus check:pm-write-pace, which names execute.mjs). Every command run in the foreground with its exit code captured before any pipe: all 48 exit 0. One of them, pnpm --filter @objectstack/lint run check:doc-formula-expressions, first answered exit 3 (PREREQUISITE NOT MET: no @objectstack/formula / @objectstack/lint build in the fresh worktree — a non-measurement, not counted); after pnpm exec turbo run build --filter=@objectstack/formula --filter=@objectstack/lint behind scripts/pm/os-verify-lock.sh (VERDICT command-exit 0) it re-ran to exit 0. Reconciled with --ran: node scripts/pm/dispatch-gates.mjs --ran ran.list --repo objectstack-ai/objectstack → exit 0, 「48 derived, 48 run, 0 NOT-MEASURED, 0 UNRUN」, every family carrying a recorded exit code. The five families the order named (check:pm-skill-ratchet, check:pm-skill-id-lint, check:pm-governed-prose, check:agent-model-declared, check:pm-settings-deny-roster) are each exit 0. Repo-wide scans (pnpm lint, test:repo) are CI's; the PR's check-runs are the authority for every family CI runs.

Acceptance notes

  • .claude/skills/pm-dispatch/references/review-checklist.md line 22 still tells the seat 「dev 挂 skip-changeset 遭分类器拒 ⇒ 席位自核 tests/docs-only 即自挂」 — the seat-side twin of the line this PR rewrites, outside this card's file surface. Reported in the dev report for the seat; not changed here.
  • dispatch.mjs's seat-side read-back (assigneesReading) has no labels twin; the relay row (execute.mjs) is the read-back line 305 now names. Observation only, nothing filed.
  • Governed surface, Tier S (.claude/**): this PR stays draft and awaits a ## Contract review record; scripts/pm/** and .claude/** publish nothing → skip-changeset, applied the old way (reported in the dev report with endpoint and status if refused).

维护者速读(草稿)

改了什么:中继的 pr_create 操作新增可选 labels,开 PR 的同一笔里顺手贴标签(和已有的 assignee 腿同一形状);执行器只认「答案里列出了每个送出的标签」才算落地,缺一个就报 FAILED 停下。os-dev.md 四行原地改写:写预算四笔变三笔;skip-changeset 在开 PR 那一笔申报,事后才发现的标签才用 label-write.mjs;分类器拒写时席位只转维护者定夺、不代做。行数 404 → 404,未抬上限。

为什么改:同一条 label-write 命令,一次放行一次被拒(PR #24139 / PR #24153),被拒后原文让「席位代做」,而席位的 harness 把替子代理补做被拒动作视为洗权限,于是每次被拒都变成一次向您提问。把标签并入从未被拒的 pr_create 一笔,是 #22467 处理 assignee 时走过的同一条路。

风险与代价(含回滚):不能证明分类器一定放行带 labels 的 pr_create,只能说该笔自 #22467 以来未被拒过。本 PR 自身的 skip-changeset 仍按旧路贴(新腿要合并后才可用)。回滚 = revert 本 PR 一个 commit;中继无状态,不影响已开 PR。

席位意见:(留空,席位定稿)

你要做的:本 PR 触及 .claude/**(Tier S),由席位做达档复核后入队落地,无需您点击;如希望顺手也改 review-checklist.md 第 22 行的席位侧措辞,请一句话说明,席位另立卡。


Generated by Claude Code

…s-dev declares skip-changeset there

The relay's `pr_create` op gains an optional `labels` list, the shape its
`assignees` leg already has: a later POST to the created pull's issue-labels
endpoint at the number the create answered, judged against `labelled` so a
name the answer lacks is a FAILED action, never a quiet partial. Both legs
now fill from the action's FIRST answer (the create's), never a later leg's.
The validator reuses the typed `labels` list `labels_add` takes.

`.claude/agents/os-dev.md`: three writes instead of four; `skip-changeset`
is declared in the `pr_create` stroke and `label-write.mjs` serves only a
label found after the PR exists; a classifier refusal routes through the
seat to the maintainer's word instead of the seat substituting.

Claude-Session: https://claude.ai/code/session_012PxNHU3dfov2hbpg9ycZ8q
Co-authored-by: Claude <noreply@anthropic.com>
…write goes to the maintainer's word, the seat never applies it on its own

The seat-side twin of the os-dev.md routing line: on a classifier refusal
of the dev's `skip-changeset` write the seat routes to the maintainer and
applies the label only after that word AND its own tests/docs-only check,
naming both in the comment; substituting for a refused action is
permission laundering. The dev's `deviations` still carries the refused
command verbatim. 77 -> 77 lines, two lines rewritten in place.

Claude-Session: https://claude.ai/code/session_012PxNHU3dfov2hbpg9ycZ8q
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: c2d5928ee2f3da4ccfec3b75d425b87bf544f353
Local-runs: none
Scope: .claude/agents/os-dev.md, .claude/skills/pm-dispatch/references/review-checklist.md + scripts/pm/fleet-write/ops.mjs, scripts/pm/fleet-write/validate.mjs, scripts/pm/fleet-write/execute.mjs (the relay leg the rewritten rules name — read whole, the rule and the mechanism that enforces it are one change), scripts/pm/label-write.mjs (its header, the four steps the dropped L305 mirrored), .github/workflows/fleet-write.yml (read at bd4276a91: unchanged, runs validate.mjs --from-env then execute.mjs)

Read 2026-10-17T14:04Z in seat by session_012PxNHU3dfov2hbpg9ycZ8q (marchtian, domain:skills#1), whose served model is the CONTRACT_REVIEW_TIER value. Inputs: card #24157 (body + 5 comments: 6231428413, 6234206652, 6234261977, 6234597716, 6234628596, 6234816652), PR #24175 (body, 5-file list, diff +130/−74 against base bd4276a91, two rounds: f9e63d6c3 then the patch c2d5928ee), the head's check-runs at this write, origin/main b0fe9fad4. Read-only: nothing built, run or re-run; the dev's self-test runs and ablations are its evidence.

① Derived judgments

Governed rules text (the face that sets the tier).

  • os-dev.md L61 「写预算三笔:git push、pr_create(draft,含 assignee 与 labels)、os-dev-report 评论。」 — right: the label now rides the create; label-write leaves the default budget and is named at L303 for the late-label case.
  • L303 「objectstack:skip-changeset 以 pr_create 的 labels 同笔申报;后发现的标签才走 label-write.mjs。」 — right; the dropped 「打标签是你的默认步骤,PR 一开出就打」 is strengthened (declared in the create's stroke), 「派发词可收窄或禁写」 survives verbatim at L304, 「标签是真实机制」 is the premise L306–307 state.
  • L305 「该腿的回读是中继回报的行:答案须列出每个送出的标签,缺者该笔 FAILED、不发后续动作。」 — right of the code: execute.mjs requestLanded judges a labelled leg's 2xx against the names sent (case-insensitive), a missing name is FAILED, and the stroke stops (stoppedAt). The dropped four-step sentence mirrored label-write.mjs's own header, which AGENTS.md makes the authority; 「写恒经 scripts/pm/」 survives at L55.
  • L309 「分类器拒外部写 ⇒ 停手,deviations 记命令与拒因,席位只转维护者定夺;⛔ 不换路重发。」 — right: the card's measured fact (PR fix(example-todo): drop objectName from the two schedule start nodes #24153) is that the seat's harness treats substituting for a classifier-refused action as permission laundering; routing to the maintainer's word is the only path that was measured to work. 「(curl/MCP/手工)」 survives at L308 (不走 MCP) and AGENTS.md's bare-write prohibition.
  • L308 (untouched) 「被拒 ⇒ 报端点与状态码、席位代挂」 is the PLATFORM-refused case (GitHub answers 4xx): no permission verdict is overridden when the seat applies the label there, so it is rightly left — the two refusal classes now read apart (L308 platform, L309 classifier). Noted, not a defect.
  • review-checklist.md L22–23 (round 2, claim amendment 6234628596) 「dev 挂 skip-changeset 遭分类器拒 ⇒ 席位转维护者定夺,⛔ 不径自代挂:代做即洗权限。」 / 「其言与席位自核 tests/docs-only 俱备方挂,评论载两者;dev 报告 deviations 须逐字载被拒命令。」 — right and now consistent with L309: the maintainer's word AND the seat's own tests/docs-only check are both required before the seat applies the label, the comment names both, the verbatim-command clause is kept; 113 B and 120 B against the 120-byte cap; 77 → 77 lines. git grep "自挂\|代挂\|席位代做" on the head leaves only the L308 platform case.
  • Ratchet: os-dev.md 404 → 404 (ceiling 404), review-checklist.md 77 → 77 (ceiling 77); no CEILINGS row moved; each dropped clause's survival is tabled in the PR body and verified above.

The relay code (read at the head; the lane seat's own ACCEPT at TIER_DEFAULT would cover it, the served tier here is higher).

  • ops.mjs pr_create.optional gains labels; the leg is 「POST …/issues/{number}/labels, fromAnswer: 'number', labelled: [...a.labels]」 — one-for-one with the assignees leg; the header documents both legs, the first-answer fill and the additive-only verbs. Right.
  • validate.mjs labels on pr_create reuses FIELDS.labels (array 1..20, each ≤ 50 bytes, no duplicates — the labels_add rules); self-test cases added beside the assignees cases; the 「exactly TWO descriptors read an earlier answer」 pin and the new 「every such leg is an additive POST to /assignees or /labels, never PATCH/PUT」 pin. Right, and the second pin protects the whole-set hazard label-write.mjs's header documents.
  • execute.mjs — the file the order assumed untouched, which the dev falsified with two ablations: (A) fromAnswer legs now fill from the action's FIRST answer (opener), never the previous leg's — with both legs present the assignee POST's answer carries a number that is not the create's; (B) requestLanded refuses a 2xx whose label set lacks a name sent (the quiet partial). More-than-sent is a landing (the Auto Label workflow's additive documentation / size/*). resultOf prints the labels the platform lists. The battery is re-declared with its pin 11 → 19 and the three ablations each turned red then restored by blob equality. Right, and necessary: without (B) the relay would report a label that never landed as landed, the exact defect class the assignees leg was built to refuse.
  • The workflow needs nothing: the mint already carries issues: write for pr_create (alsoSpends), and the runner only calls the two scripts. The PR's own skip-changeset rightly went the old way (a PR cannot use the leg it introduces).
  • What this PR cannot prove, stated in its body: that the classifier accepts a pr_create carrying labels. The measured fact is the stroke's history since pm tooling: the os-dev's PR-assignee write (label-write.mjs --assign) is refused by the auto-mode permission classifier on 4 of 12 objectui PRs in one seat's session — same command, same brief, nondeterministic #22467; the first dev to use the leg measures it (a reading for the seat post).
  • Main drift. Base bd4276a91; origin/main is b0fe9fad4 (this seat's PR docs(checklist-test): a verification re-run files no qa-run record; sweeps still file one per run #24172, checklist-test/SKILL.md only); git merge-tree --write-tree origin/main FETCH_HEAD exits 0.

Check-runs on c2d5928ee at this write: 22 success, 8 skipped, 6 in_progress (lint and type-check lanes still running), none failed. Convergence is read at landing.

② Semver level

.claude/** and scripts/pm/** publish nothing (both on the fast lane of os-dev.md L300); skip-changeset is present (the dev's label-write, not refused this time; read back). The PR body's line 2 is Clause-②: no at line start, copied from the claim (6234206652): governed rule text and PM tooling, no published accept set or public surface. Matched and well-formed. No model identifier in the title, body (session-URL footer), the two commits or any comment read.

③ Boundary flags

Dev reports 6234597716 (round 1) and 6234816652 (round 2): open_questions: [] both rounds; deviations each answered:

  • R1-D1 execute.mjs edited beyond the claim's surface — declared with the two ablations that show why; the seat's claim amendment 6234628596 admits it. Accepted.
  • R1-D2 base 697301491 → bd4276a91. Answered.
  • R1-D3 ops.mjs has no --self-test entrypoint (its pins live in validate/execute); the order's 2(d) named one. The order's error; answered.
  • R1-D4 / R2 model-free trailers kept. Right.
  • R1-D5 the worktree's modified validate.mjs validated the PR's own strokes; both validators accept an assignees-only pr_create. Answered.
  • R1-D6 / R2 worktree and node_modules removed; PIDs exited. Right.
  • R1 OOS-1 review-checklist.md L22 — absorbed by the patch round; no sub-issue.
  • R2 check:pm-governed-prose run on its own (not in the derivation); the round-2 comment carries one tag-shaped placeholder in its summary (read back byte-identical by the API; the rendered page may hide it) — a record blemish, the JSON intact; accepted, no comment edit owed.
  • R2 OOS os-dev.md L308 (platform refusal) left as is — right, see ①.

Reviewer's own flags: none. mcp_calls 0 both rounds; api_writes four relay strokes in all (pr_create with assignee, labels_add, two report comments) plus three pushes; no PATCH, no MCP write.

Implemented-by: claude/issue-24157-skip-changeset-in-pr-create
Reviewed-by: session_012PxNHU3dfov2hbpg9ycZ8q

VERDICT: PASS

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

维护者速读

改了什么:① 中继 pr_create 新增可选 labels:开 PR 的同一笔里贴标签(与 assignee 腿同形);执行器只认「答案列出了每个送出的标签」才算落地,缺一个 FAILED 停下,多出的(Auto Label 加的)不算错;fromAnswer 腿改为从本动作第一个答案(create)取号。② os-dev.md 四行原地改写:写预算四笔→三笔;skip-changeset 在 pr_create 里申报,事后发现的标签才走 label-write;分类器拒写时席位只转你定夺、不代做。③ review-checklist.md 两行同步:席位不径自代挂,须有你的话加席位自核才挂。行数 404/404、77/77,上限未动。

为什么改:同一条 label-write 命令一次放行一次被拒(PR #24139 / #24153),被拒后原文让「席位代做」,而席位 harness 把替子代理补做被拒动作当洗权限,每次都变成一次向你提问。并入从未被拒的 pr_create 一笔,是 #22467 处理 assignee 的同一条路。

风险与代价(含回滚):不能证明分类器一定放行带 labels 的 pr_create,只有「该笔自 #22467 未被拒」的实测;第一个用新腿的 dev 会给出读数。本 PR 自身的标签仍走旧路。回滚 = revert 两个 commit;中继无状态。

席位意见:ACCEPT。三个脚本逐处读过,三次消融各自转红再复原;两处规则文本与代码一致(见上方 ## Contract review PASS)。Tier S,席位落地。

你要做的:无。

席位核对

Seat domain:skills#1 · session_012PxNHU3dfov2hbpg9ycZ8q (marchtian) · read 2026-10-17T14:07Z · head c2d5928ee2f3da4ccfec3b75d425b87bf544f353 · verdict: ACCEPT (Tier S — the seat lands it after the two pre-landing checks)

Implemented-by: claude/issue-24157-skip-changeset-in-pr-create
Reviewed-by: session_012PxNHU3dfov2hbpg9ycZ8q

  1. Shape. Draft PR against main; body line 1 Fixes #24157, line 2 Clause-②: no (from claim 6234206652). The only closing keyword is the Fixes line. Files: .claude/agents/os-dev.md (+4/−4), .claude/skills/pm-dispatch/references/review-checklist.md (+2/−2, round 2 under claim amendment 6234628596), scripts/pm/fleet-write/ops.mjs, validate.mjs, execute.mjs (the leg, its validator, its executor and their self-tests). Base bd4276a91; merge-tree against origin/main b0fe9fad4 exits 0.
  2. Route and acceptance, read by the seat. The card's 1 + 3 (and the filer's 「pr_create takes labels」 premise falsified and repaired by the op leg); each dropped rule clause's survivor verified (contract review 6234848528 ①); the seat-side twin rule now agrees with os-dev.md L309; the platform-refusal line L308 is a different class and rightly untouched.
  3. Gates — check-runs pinned to head c2d5928ee at this read: 29 success · 8 skipped · 1 in_progress · 0 failed. Local: validate 158 / execute 128 / dispatch 222 self-test cases exit 0; 49 derived families run and reconciled (--ran 49/49); three ablations red-then-restored. Landing waits for the lint and type-check lanes to complete; check-expected-skips.mjs --pr 24175 is read then. check-governed-merges.mjs --pr 24175: GOVERNED, Tier S, +130/−74 under the threshold.
  4. Changeset. None owed (.claude/**, scripts/pm/** unpublished); skip-changeset present (the dev's label-write, not refused this time). The seat concurs.
  5. Report hygiene. mcp_calls 0 both rounds; api_writes four relay strokes + three pushes; no PATCH; deviations answered in the contract review (the order's own two errors: ops.mjs has no self-test entrypoint; execute.mjs had to learn the leg).
  6. Out of scope. Round 1's review-checklist finding absorbed in round 2; dispatch.mjs's seat-side read-back has no labels twin (observation, the relay row is the read-back the contract names); nothing filed.
  7. Landing (Tier S). Pre-landing ①: PASS record 6234848528 on this head. ②: every check green or an expected skip — read at the flip. Then relay pr_ready + automerge_enable; the probe-table landing comment follows at MERGED. subscribe_pr_activity live on this PR.

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 17, 2026 14:10
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 17, 2026 14:10
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 17, 2026
Merged via the queue into main with commit cb8756b Oct 17, 2026
40 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-24157-skip-changeset-in-pr-create branch October 17, 2026 14:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants