Skip to content

feat(cli,runtime)!: the upgrade ceremony opens — v17 and 18.0 databases take it, and a server serves only a database it created or one the ceremony certified (18.x steps 5 and 6) - #24681

Merged
os-zhuang merged 42 commits into
mainfrom
claude/issue-24581-ceremony-open
Oct 20, 2026
Merged

os-zhuang merged 42 commits into
mainfrom
claude/issue-24581-ceremony-open

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Closes #24581
Closes #24582
Part of #24421
Part of #24489
Clause-②: yes (narrowing)

18.x line, steps 5 and 6 as ONE landing (ruling 6270035914 on #15194), under rulings 6266750393, 6267391172 and 6269955919 (and its amendment). Step 0's plan: os-dev-report 6268559156 on #24522. Seat note 6271949316 on #24581 holds what steps 1–3 left the ceremony to do.

Base and merge gate. The branch started from origin/main merged with #24588's head (step 1), because 5a reads its declared-webhook source. #24588 landed (191e0430), and step 4 (#24667) landed (fc34d000). main is merged in again at 1699ec5b (main 580fd4ed); the head is b5010d9c. The diff against main is 4,578 changed lines (+3,399 / −1,179) over 93 files, which is over the 3,000-line human-merge line.

Restated from #24635 (on main). That PR taught four surfaces to say "18.0 does not upgrade; keep a v17 database on 17.x": the drop-gate refusal of os migrate apply --allow-destructive, os dev's way-on line, the refusing class's help examples, and that class's pin. That is false once the ceremony is open. The drop refusal and os dev now name the ceremony's steps again, and their pins say so (apply.organization-ownership-refusal.test.ts, dev-organization-ownership-upgrade.test.ts). The --json detail keeps #24635's wording ("No run of the organization-ownership ceremony is recorded…"). The refusing class and its pin stay deleted.

What changed

os migrate organization-ownership runs again (#24489 items 1, 4, 6)

  • The refusing subclass MigrateOrganizationOwnership and ORGANIZATION_OWNERSHIP_UPGRADE_UNAVAILABLE are deleted. The default export is OrganizationOwnershipCeremony again.
  • The release-refusal test is deleted. The 16 test files import the default again.
  • The boot-refusal-order dogfood runs its step 2 through the real binary, and step 2a is dropped.
  • os dev's automatic upgrade works again: it runs the binary, which now runs the ceremony.

Four new ceremony steps (shape generation 1)

CEREMONY_STEPS order: attribution, authored-conversion, metadata-promotion, template-promotion, settings-move, sibling-moves, declared-webhooks, declared-rule-copies, rewrite, mirror-deletion, history-renumber, column-drops, not-null.

Every new step selects by shape, never by organization_id IS NULL (F3).

  • 5b sibling-moves. Rows move id for id. Each is copied over the columns both tables carry (never organization_id), read back, then deleted with its selector re-asserted. A row already in the sibling is not copied twice.
    • sys_setting_audit WHERE scope = 'global' moves to sys_platform_setting_audit.
    • Identity mail moves from sys_email to sys_identity_email. It is selected as related_object = 'sys_user' (reset, verification, account invitation, change-email notice), plus the magic link. Selector gap, defined here: an 18.0 magic-link row has no related record and no template column, so it is selected by related_object IS NULL AND related_id IS NULL and a body carrying better-auth's sign-in path /magic-link/verify?token=. The organization invitation (sys_invitation) is tenant mail and stays.
    • First: pending and running mail jobs (email.send.async, email.attachment.reclaim) that name a moving row get object: 'sys_identity_email' in their payload and metadata, and the sibling's idempotency-key spelling. Without this, a send finds no row and a reclaim takes the row-gone branch and deletes attachment content.
    • After each chunk: sys_activity rows about a moved row (every rotation shard) name the new object. sys_audit_log is a ledger and is not rewritten.
    • Exposure (measure(plugin-email): who can list sys_email rows that carry identity mail (reset and verification links) — sys_email declares no requiredPermissions #24625): nothing on sys_email changes. The moved rows land in a table with requiredPermissions, and the re-pointed activity rows follow them there, so the exposure is not widened. It is not fixed either.
  • 5a declared-webhooks. For each sys_webhook row with managed_by package or platform under a name a package still declares:
    • A pristine copy: its deliveries are re-sourced to declared:NAME, then the row is deleted, then the sys_secret cipher it referenced is deleted once no webhook row references it.
    • Customized only in its switch (every mapped column still equals the definition_json snapshot the 18.0 seeder last wrote, and no credential is stored): the switch becomes the declaration's sys_metadata_activation row, the deliveries are re-sourced, and the row is deleted. The harness fixture's row is this case.
    • Any other edit: the row is renamed in place to NAME_custom with managed_by 'admin', and the declaration is switched off. Its id, credentials and deliveries stay its own, so the deliveries' tail already names the clone's row id. A row holding a credential is always settled this way, because a stored secret cannot be compared without decrypting it.
    • A seeded row whose name no package declares is an ordinary webhook, as in 18.0. It stays and is reported.
    • Mirror predicate aligned: classifyDeclaredNameHolder treats platform like package (a new shared isSeededProvenance, also used by the provenance hook).
    • DECLARED_WEBHOOK_REF_PREFIX / declaredWebhookRefId are now exported by plugin-webhooks. The ceremony's copy of the spelling is pinned equal to them.
  • 5c declared-rule-copies (9c, plugin-sharing: refuse a new or renamed sys_sharing_rule row that takes a declared rule's name, and reconcile the shadowed declaration's grants on a same-name write (ruling B′ on #24378) #24421). The runtime half already landed in plugin-sharing, runtime: sharing_rule under regime C, so every same-name row is refused and declared rules are switched through the activation ledger (ruling A on #24378) #24428, measured: the same-name guard, the ledger switch and the load report. This step is the copy migration, ruling A item 3. Each sys_sharing_rule row under a declared rule's name that is not a pristine mirror (a customized copy, or an admin rule a later declaration collided with) is renamed in place to NAME_custom, managed_by 'admin'. Its id-keyed grants stay its own. The declaration is switched off (sharing_rule activation row, active: false), and grants still naming the declaration itself are removed. Pristine mirrors stay the mirror-deletion step's.
  • 5d not-null (8e, ruling ② A). After column-drops, every table the post-step plan clears (notNull.willReceive, zero NULL rows) takes organization_id NOT NULL. It goes through the drift apply door of the driver that holds the table: the SQLite rebuild, or SET NOT NULL. Results:
    • A table the composition does not declare is not-declared.
    • A transport with a declared apply limit (the Turso remote face) is unsupported.
    • A rotation shard is unsupported: the door rebuilds only declared tables, and new shards are created nullable.
    • The differ (diffManagedTable) takes the table's tenant column (ceremonyOwnedNullability, passed by SqlDriver.detectTableDrift from resolveTenantField) and proposes no relax_not_null for it. No metadata changes.
  • The CeremonyCheckpoint carries shapeGeneration. DeclaredSharingRulesPort.rules() returns packageId. Two new ports: DeclaredWebhooksPort (the command reads the registry, parsed with WebhookSchema) and NotNullPort.

The guard's verdict on an 18.0 database (F4, F5; ruling ① A)

  • ORGANIZATION_OWNERSHIP_SHAPE_GENERATION = 1, plus OrganizationOwnershipBirthMarkerSchema and organizationOwnershipShapeGenerationOf in @objectstack/spec/system. The migration.zod.ts prohibition is amended for this marker only.
  • Birth marker. On a datastore this boot created from empty (judged on the driver of the store that holds sys_migration, so a telemetry sibling neither ages a fresh primary nor freshens an old one), with no marker and no v17-shape table, the guard writes the ceremony's row once: verified, details.birth = { shapeGeneration, platformVersion, createdAt }. commit is absent, because no build records it. A failed write refuses the boot.
  • The rule. The guard decides on shapeGeneration alone. A verified marker at the current generation boots. A database with no marker (every 18.0 one) is refused, and so is one verified below the current generation (F5). Unverified or unreadable markers are refused as before.
  • Every CLI boot writes the birth half too. This is OrganizationOwnershipBirthMarkerPlugin in createStandaloneStack. It never refuses. Without it, an install whose first command is os migrate apply or os seed would be refused by its first os serve. The ceremony's own boots defer DDL, so they never trip it.
  • The refusal text no longer says to keep a database on 17.x. One sentence covers v17 and 18.0 databases, plus an outdated arm.
  • tenancy: { enabled: false } gap closed: the v17-shape probe reads that spelling and systemFields: false too.

sys_secret / sys_flow_credential flips (step 2's PR 2b, F2)

  • Both are systemFields: { tenant: false }, and their inventory rows are column-drop.
  • The settings writer no longer passes organization_id for sys_secret. SettingsSecretStore.insert no longer takes it.

Inventory

  • sys_setting_audit gains the global-audit-move departure, and sys_email gains identity-mail-move.
  • sys_webhook's declared category now covers package and platform, and its label names the settlement.

Proof

R1 — a fresh boot writes the birth marker and boots, again and again. Pins: organization-ownership-boot-guard.kernel.test.ts (a real kernel) and organization-ownership-boot-guard.test.ts (the CLI birth half).

R2 and R3, restated by name in upgrade-18x-harness.dogfood.test.ts: 8/8 pass.

  • 1. R2, restated: HEAD refuses the 18.0 database at boot, naming the ceremony, and writes no marker.
  • 1b. R2, restated: the ceremony, through the real binary in the showcase's directory, plans and applies the database and certifies it at this release's shape generation.
  • 1c. R2, restated: HEAD then boots over it.
  • 2: it serves the 18.0 data.
  • 2b: the declared webhook dispatches exactly once, from its declaration (declared:showcase_task_changed).
  • 3: every 18.0 row of every reshaped table is where the ceremony put it, with its key columns:
    • moved: identity mail and the global audit rows;
    • re-sourced: the deliveries;
    • deleted: the webhook copy, whose switch is kept;
    • organization_id gone on sys_secret / sys_flow_credential;
    • NOT NULL on the tenant tables.
  • 4. R3, restated: a v17-trait copy is refused, takes the ceremony, and boots.

A shorter ceremony's marker is refused (F5): organization-ownership-boot-guard.test.ts.

The ceremony's own pins: organization-ownership-apply.generation-1.test.ts, 16 cases over an 18.0-shaped database (every row stamped), one or more per step, plus idempotence and the walled block. Also organization-ownership-not-null.test.ts, on a real SQLite driver: NOT NULL is applied and the next drift scan reports nothing for it.

Ablations (scripts/ablation-replace.mjs). Every leg is committed first and restored to blob == HEAD, with git diff HEAD empty after the last leg:

ablated red
guard: the generation rule (>= current → >= 0) 1 (F5)
guard: birth only on a store created from empty 2
guard: the tenancy.enabled: false spelling 2
5b: the global-audit selector 3
5b: the magic-link selector 3
5b: the mail-job rewrite 2
5a: the delivery re-source 2
5a: the switch-only reading 2
5c: the declaration switched off 2
5d: NULL rows hold NOT NULL back 1
differ: the ceremony-owned nullability exemption 1

Tests. Run on this branch before the main merge, then the touched sets again after it at d6195b90. Exit codes were captured to files before any pipe.

  • @objectstack/runtime: full suite, 428 files, 7,492 passed, 19 skipped.
  • @objectstack/cli: full suite. The first run went red in 72 cases, mostly whole-file import errors while the spec dist was being rebuilt underneath it. A re-run of every failed file left 6, all fixed:
  • @objectstack/driver-sql: 234 files, 3,678 passed. Two drift fixtures were re-keyed off organization_id, and the tenant-column exemption pin was added.
  • The other suites touched:
    • service-settings: 892 passed (one pin restated: the cipher names no organization).
    • platform-objects: 1,192 passed (one control moved to sys_setting_audit, plus a sys_secret pin).
    • service-automation: 2,580 passed.
    • plugin-webhooks: 212 passed.
  • Dogfood, after the merge: upgrade-18x-harness, organization-ownership-boot-refusal-order, settings-audit-global-rung-sibling and webhook-materialization: 4 files, 17 passed, 50 s.
  • typecheck: exit 0 for cli, runtime, driver-sql, plugin-webhooks and service-settings. eslint --no-inline-config over the changed .ts files: exit 0.

Gates. node scripts/pm/dispatch-gates.mjs --commands derived 137 commands before the merge, and 132 after it, all among the 137.

  • 131 of the 137 exited 0 on the first sweep.
  • The 6 that did not:
    • check-platform-object-tenancy-census and its self-test: the census was regenerated with --write (sys_secret and sys_flow_credential leave reach, 44 → 42).
    • check:engine-double-contract: the guard double's findOne now asserts the predicate, and the pinned ledger was rewritten with --write.
    • check:spec-parsed-alias: the birth marker's z.input alias, with a Parsed alias beside it.
    • check:test-source-alias: a CLI vitest alias for @objectstack/plugin-webhooks.
    • check-plugin-teardown-shape --self-test: exit 3, NOT MEASURED. Its positive control needs history this shallow clone lacks; this is checker health, not this diff.
  • Each fixed one re-ran exit 0 after the merge. So did check:adr-0087-registration, check:tenant-audit-census, check:platform-checklist, and the spec check:generated (14 artifacts up to date).
  • check-governed-merges --branch: 0 of 95 paths on the register before the merge. The size decides: human merge or an authorized approval.

The merge after step 4 (1699ec5b)

One merge commit, no rebase. What it restates, with the ceremony open on this branch:

Re-run after the merge, after a fresh pnpm install and build:

  • The 18.0→HEAD harness and organization-ownership-boot-refusal-order: green.
  • Step 4's 7 walled e2e cases (serve-organizations-host-resolution, serve-organizations-mount-failure; R4 "walled boots"): 7 passed. wall-declared-webhook-deployment-wide dogfood: 8 passed.
  • Step 4's walled pins, isolated and group: service-settings 894 passed, service-datasource 852 passed, service-automation 2,604 passed (full suites).
  • plugin-sharing 1,172 passed; plugin-auth 3,168 passed, 10 skipped; objectql 8,449 passed; the runtime guard pins 34 passed; the CLI ownership, apply and one-shot-family sets 399 passed, 1 skipped.
  • json-stdout-purity.e2e (nightly tier): 65 passed, including the three os migrate organization-ownership --json cases (the stderr-diagnostics one was red on main).
  • The spec check:generated: 14 artifacts up to date.
  • dispatch-gates --commands: 149 commands; 147 exit 0. check-engine-split-ratio --days 90 and check-plugin-teardown-shape --self-test cannot measure in this shallow clone (checker health, not this diff).
  • check-governed-merges --branch: no path on the register; the size decides — human merge or an authorized approval.

Decisions taken, for the seat

  • Walled databases. A customized copy of a declared webhook or sharing rule BLOCKS its step under group / isolated, naming the rows and the remedy: rename it to a name no package declares, or delete it, then re-run. The declaration's switch is deployment-wide (ruling A item 1: no per-organization switch-off), so switching it off on the operator's behalf would remove it from every organization. Pristine copies are still deleted under a wall.
  • Clones are renamed in place, not inserted under a new id. The end state is the regime's (a row under a new name plus the declaration off), and every grant and delivery keyed by the row's id stays valid with no rewrite.
  • sys_webhook stays a category, not a departure. A departure withholds its NULL rows from attribution, and a seeded row no package declares is a live webhook that must be attributed like any other. The settlement selects by shape in its own step.
  • The magic-link selector is the sign-in path in the body (see 5b).

Acceptance notes

  • Files outside the claimed surface:
    • the spec's generated artifacts;
    • docs/qa/platform-checklist/areas/cli.json (item cli.organization-ownership-ceremony, revision 3: its pin organization-ownership.release-refusal.test.ts is deleted here);
    • content/docs/deployment/cli.mdx (the 18.0 refusal sentences);
    • two driver-sql drift tests whose relax_not_null fixture used organization_id, re-keyed to another column, plus a new pin that the tenant column is exempt;
    • standalone-stack.ts (the birth half).
  • Not touched: docs/adr/**, content/docs/releases/, serve.ts, step 4's walled sentences in tenancy-modes.mdx / self-hosting.mdx / environment-variables.mdx.
  • A pending delivery re-sourced by 5a keeps its partition_key. It is still claimed and sent, by that partition's worker.
  • The harness fixture holds no 9c copy (its one sharing rule is an admin rule under an undeclared name), so 5c is pinned by the unit fixture alone. A fixture regeneration with a customized declared-rule copy would cover it on the harness.

Generated by Claude Code

claude added 30 commits October 19, 2026 13:06
…r retired; webhook activation door

Claude-Session: https://claude.ai/code/session_01PDSxBZE561TFe1N2iEjKXZ
Co-authored-by: Claude <noreply@anthropic.com>
…he 18.0 dual read; door pins for webhook

Claude-Session: https://claude.ai/code/session_01PDSxBZE561TFe1N2iEjKXZ
Co-authored-by: Claude <noreply@anthropic.com>
…asserts no row and a dispatch

Claude-Session: https://claude.ai/code/session_01PDSxBZE561TFe1N2iEjKXZ
Co-authored-by: Claude <noreply@anthropic.com>
…the checklist, the webhooks guide and the showcase; changeset

Claude-Session: https://claude.ai/code/session_01PDSxBZE561TFe1N2iEjKXZ
Co-authored-by: Claude <noreply@anthropic.com>
…tcher's switch read

Claude-Session: https://claude.ai/code/session_01PDSxBZE561TFe1N2iEjKXZ
Co-authored-by: Claude <noreply@anthropic.com>
…posture builds no wall, as its 18.0 seeded copy stamped with the Default Organization was

Claude-Session: https://claude.ai/code/session_01PDSxBZE561TFe1N2iEjKXZ
Co-authored-by: Claude <noreply@anthropic.com>
…red writes; the declared-webhook double is drivable by the limit gate

Claude-Session: https://claude.ai/code/session_01PDSxBZE561TFe1N2iEjKXZ
Co-authored-by: Claude <noreply@anthropic.com>
…does not implement

Claude-Session: https://claude.ai/code/session_01PDSxBZE561TFe1N2iEjKXZ
Co-authored-by: Claude <noreply@anthropic.com>
…authors; checklist and admitsOrganization docblock say a declared webhook is deployment-wide under single

Claude-Session: https://claude.ai/code/session_01PDSxBZE561TFe1N2iEjKXZ
Co-authored-by: Claude <noreply@anthropic.com>
…the fixture's customized declared-webhook mirror

Claude-Session: https://claude.ai/code/session_01PDSxBZE561TFe1N2iEjKXZ
Co-authored-by: Claude <noreply@anthropic.com>
…n fail on a double delivery

Claude-Session: https://claude.ai/code/session_01PDSxBZE561TFe1N2iEjKXZ
Co-authored-by: Claude <noreply@anthropic.com>
…0g-webhooks-registry

# Conflicts:
#	content/docs/permissions/tenant-audit-census.mdx
#	docs/audits/2026-08-tenant-audit-write-call-sites.counts.md
…0g-webhooks-registry

# Conflicts:
#	content/docs/permissions/tenant-audit-census.mdx
#	docs/audits/2026-08-tenant-audit-write-call-sites.counts.md
…-registry' into claude/issue-24581-ceremony-open
…he ceremony, then boot; boot-refusal-order step 2 back on the binary
…el — the cipher names no organization

Claude-Session: https://claude.ai/code/session_014UATXWqAXqkaZkbG92ox6V
Co-authored-by: Claude <noreply@anthropic.com>
…sys_flow_credential leave reach)

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

Copy link
Copy Markdown
Contributor Author

维护者速读(总监席记录 · 第 45 场续场 1 · session_01Lg6GQ4xjqmvEzYv78d6H7i)· PR #24681 · 2026-10-20T07:07Z

本 PR 正文无「维护者速读」段,维护者只读评论,故由总监席按自己读到的 diff、达档复核记录 6284464125 与 epic 席增量核对 6285186426 补齐五段;放行与落地仍归 epic 席(os-steve),本席不翻 ready、不入队。

  • 改了什么: 18.x 升级仪式打开。os migrate organization-ownership 重新可用,v17 建的库与 18.0 建的库都走它;18.0 的「拒绝类」与其错误码删除,os dev 的自动升级恢复;仪式新增四步(sibling-moves 把全局设置审计与身份邮件迁到各自的兄弟表、declared-webhooks 把包声明的 webhook 行收回注册表或改名为自定义、declared-rule-copies 把声明规则的定制副本改名、not-null 收紧列);fix(cli): the organization-ownership drop refusal says what 18.0 supports for a v17 database #24635 教四处文本说「18.0 不升级」的句子改回仪式的真实步骤。十条待发 release note 按 finding: random changeset filenames collide silently across parallel agents — a round overwrote a sibling PR's minor changeset and every gate stayed green #17712 刻意改正(删 7、改写 3,都是本 PR 或步骤 4 在同一个未发布的 18.0.0 里改掉的状态)。lint.yml 新增一个 continue-on-error 的 check:closed-ceremony-text 步,守「不再有文本说仪式关闭」。5,078 行改动、约 120 个文件。
  • 为什么改: [epic] ADR-0131 — total organization ownership: no NULL organization_id (v18 line) #15194 裁决 6270035914(步骤 5、6 合为一次落地)与 6266750393 / 6267391172 / 6269955919;仪式一开,「18.0 只支持全新安装」就成了假话,本 PR 把文本与仪式一起改到位。
  • 风险与代价(含回滚): 破坏性(Clause-②: yes (narrowing));升级路径正式打开,数据迁移在真实库上跑,仪式有 marker 与报告但已迁移的库不能自动回退;代码层回滚 = revert 本 PR 一个 squash 提交。Check Changeset 红两条:按设计(十条 release note 刻意删改),非必查项,epic 席已在 6285186426 记门与因。达档复核 PASS 落在 b5010d9c;其后两笔提交(字符串文本、新门禁脚本 +207、lint.yml +12、十二个 changeset、三页文档)只有席内增量核对,⛔ 欠一条 head c6f775cb 的同形 PASS 记录,落地前由 epic 席补。
  • 席位意见(总监席): 同意呈批。放行三件:您的 APPROVED(任一提交上即算,之后推送不过期);您对十条 release note 改正的确认;epic 席在 c6f775cb 补同形 PASS。
  • 你要做的: 一个动作:在 PR 上 Approve,并回一句「十条认」(或点名不认的行)。

席位核对(总监席,只作记录,⛔ 非放行)

  1. 形态: draft、base main、首行 Closes #24581、Clause-②: yes (narrowing);assignee os-steve;GitHub 读 120 文件 +3,636/−1,270(本地 --branch 读 5,078 行);受管路径 .github/workflows/lint.yml ⇒ Tier H;超线 ⇒ 人合线;两者同一结论:您批、epic 席落地。
  2. 前提实测: PASS 记录 6284464125 的 Head-sha = b5010d9c0388;compare b5010d9c...c6f775cb = 2 提交、37 文件(12 changeset、lint.yml +12/−0、scripts/check-closed-ceremony-text.mjs +207、源码字符串与对应测试、3 页 docs、1 份 qa json、package.json +1);无 docs/adr/**。
  3. 门禁 check-runs(c6f775cb): 46 条 = 36 success、8 skipped、2 failure(Check Changeset ×2,按设计,非必查)。
  4. 接受的偏差: Check Changeset 红(十条刻意改正,finding: random changeset filenames collide silently across parallel agents — a round overwrote a sibling PR's minor changeset and every gate stayed green #17712);PASS 记录落后两笔(非纯散文面,须补记录)。
  5. 范围外去向: ADR-0131 的发布范围注记归单独的 ADR 注记 PR(epic 席)。
  6. 落地条款: Tier H。您 Approve 在案 + epic 席补 c6f775cb 同形 PASS + 其余 check 绿 ⇒ epic 席经中继 pr_ready + automerge_enable;本席已向 os-zhuang 与 hotlong 请审(本笔同轮)。

Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Correction to the director record 6285430460 · director seat, summon #45 continuation 1, session_01Lg6GQ4xjqmvEzYv78d6H7i · 2026-10-20T07:10Z

Read on the timeline after posting: before that record was written, os-zhuang had already APPROVED this PR (review 5581764518), flipped it ready, armed auto-merge, and the queue took it (added_to_merge_queue); the epic seat removed needs-user-decision in the same minutes. So the record's 「你要做的」 was already spent when it posted, and the two review requests this seat sent afterwards are moot — a freshness gap on this seat's side (the reviews were read at the continuation's opening, not again at the moment of writing), recorded on the seat post. The record's reading of the diff, the Check Changeset reason and the missing same-head PASS record for c6f775cb stand as written; landing is the queue's and the epic seat's.


Generated by Claude Code

Merged via the queue into main with commit 12d1476 Oct 20, 2026
47 of 50 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-24581-ceremony-open branch October 20, 2026 07:41
os-steve pushed a commit that referenced this pull request Oct 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/cd dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation protocol:system size/xl tests tooling

Projects

None yet

3 participants