Skip to content

fix(runtime): the organization-ownership boot refusals say what 18.0 supports and name no step of the withdrawn ceremony command - #24682

Merged
objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-24651-boot-refusal-18-0-text
Oct 20, 2026
Merged

objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-24651-boot-refusal-18-0-text

Conversation

@objectstack-fleet

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

Copy link
Copy Markdown
Contributor

Fixes #24651
Clause-②: no (refusal text only: the refusal code ORGANIZATION_OWNERSHIP_MIGRATION_REQUIRED, the refused tables and the boot outcome do not move)

In 18.0, os migrate organization-ownership refuses plan and apply on every database (ORGANIZATION_OWNERSHIP_UPGRADE_UNAVAILABLE, NOT_IMPLEMENTED). Three branches of the v18 boot refusal in packages/runtime/src/organization-ownership-boot-guard.ts still sent the operator to that command's --out PLAN and --apply --plan-file PLAN --backup-taken. Each branch now closes on the sentence the landed member of this family (PR #24635, f89d29e38) put into os migrate apply's drop gate and os dev's way on:

18.0 supports fresh installs only and does not upgrade a v17 database: keep a v17 database on a 17.x release until the 18.x release that carries the upgrade path, and upgrade it there.

A development boot ({ dev: true }, as os serve --dev composes the guard) says "a v17 development database", the exact wording of the landed os dev text. No branch names the command or any step of it. ceremonyCommand() (which only built the --dev command name) is gone. The dev option stays, and still changes the text. The refusal code, the refused tables, isOrganizationOwnershipBootRefusal, the plugin's ordering and every boot outcome are unchanged. This is the domain:cli row of the family close-out #24637.

Branch map

branch selected when source refused tables
A, v17 shape findV17ShapeTables finds a table whose object declares no organization column (systemFields.tenant: false, no declared organization_id) but still has a physical organization_id, and the marker is absent, unverified or unreadable organizationOwnershipRefusalMessage, tables not empty (was about :252–:258) the tables found
B1, marker not verified no table in the v17 shape, and the sys_migration row adr-0131-organization-ownership exists but is not verified: a ceremony ran every step and its post-check found discrepancies organizationOwnershipRefusalMessage, tables empty, marker unverified (was about :239–:243) none
B2, marker unreadable no table in the v17 shape, and a store serves the ledger but its read of the marker threw the same return as B1, marker unreadable (was about :239–:243) none
C, column read failed findV17ShapeTables itself threw while reading a table's columns assertOrganizationOwnershipMigrated's catch (was about :339–:344) none

The card's ":242" is B1 and B2 (one return statement), ":256–257" is A, and ":342–343" is C. A marker that is absent with no v17 table, and a verified marker, still boot.

Before and after, per branch

Rendered by importing the guard at bfc1539fe (before) and at this PR's head (after) and calling it. TABLES stands for the table list. The --dev before-texts are the same with os migrate organization-ownership --dev.

A, v17 shape (marker absent; unverified and unreadable differ only in the state clause)

  • Before: "This database is still in the v17 organization-ownership shape: TABLES still carry a physical organization_id column, and the ceremony has not run on it. The server refuses to start rather than serve v17 data with v18 semantics. 18.0 does not upgrade a v17 database: keep this one on a 17.x release until the 18.x release that carries the upgrade path, and run these steps there. Run 'os migrate organization-ownership --out PLAN' to write and review its plan, take a backup, then run 'os migrate organization-ownership --apply --plan-file PLAN --backup-taken', and start again. To keep 17.x semantics, run a 17.x runtime."
  • After: "This database is still in the v17 organization-ownership shape: TABLES still carry a physical organization_id column, and the ceremony has not run on it. The server refuses to start rather than serve v17 data with v18 semantics. 18.0 supports fresh installs only and does not upgrade a v17 database: keep a v17 database on a 17.x release until the 18.x release that carries the upgrade path, and upgrade it there."
  • What was kept: everything up to "v18 semantics", and the 17.x answer. What was dropped: the two steps, "run these steps there", and "To keep 17.x semantics, run a 17.x runtime.", which now repeats "keep a v17 database on a 17.x release".

B1, marker not verified

  • Before: "The organization-ownership ceremony has not finished on this database: its marker (sys_migration 'adr-0131-organization-ownership') is not verified: the post-check still found rows the ceremony has not carried. The server refuses to start rather than serve rows of an organization-owned object with no organization. Resolve what the apply report names, then run 'os migrate organization-ownership --out PLAN' again, review it, run 'os migrate organization-ownership --apply --plan-file PLAN --backup-taken', and start again."
  • After: "The organization-ownership ceremony has not finished on this database: its marker (sys_migration 'adr-0131-organization-ownership') is not verified: the post-check still found rows the ceremony has not carried. The server refuses to start rather than serve rows of an organization-owned object with no organization. 18.0 supports fresh installs only and does not upgrade a v17 database: keep a v17 database on a 17.x release until the 18.x release that carries the upgrade path, and upgrade it there."
  • Dropped: "Resolve what the apply report names", the re-plan and the re-apply. In 18.0 nothing can verify the marker, so resolving the report's rows does not let this database boot. The 18.x release finishes the ceremony.

B2, marker unreadable

  • Before: the B1 text with "its marker (sys_migration 'adr-0131-organization-ownership') could not be read" as the state. It prescribed the same re-plan and re-apply.
  • After: "The organization-ownership ceremony has not finished on this database: its marker (sys_migration 'adr-0131-organization-ownership') could not be read. The server refuses to start rather than serve rows of an organization-owned object with no organization. Fix the read, then start again. 18.0 supports fresh installs only and does not upgrade a v17 database: keep a v17 database on a 17.x release until the 18.x release that carries the upgrade path, and upgrade it there."
  • Added: "Fix the read, then start again." This branch also reaches a fresh 18.0 database whose ledger read failed: no v17 table, and a marker the guard could not read. On that database the true way on is the read. Once the read answers, a database with no marker boots. The old text sent it to an apply report it never had.

C, column read failed

  • Before: "The server refuses to start: it could not read whether this database is still in the v17 organization-ownership shape (ERROR), and an unread answer is never taken for a migrated database. Fix the read, or run the ceremony ('os migrate organization-ownership --out PLAN', then 'os migrate organization-ownership --apply --plan-file PLAN --backup-taken'), then start again."
  • After: "The server refuses to start: it could not read whether this database is still in the v17 organization-ownership shape (ERROR), and an unread answer is never taken for a migrated database. Fix the read, then start again. 18.0 supports fresh installs only and does not upgrade a v17 database: keep a v17 database on a 17.x release until the 18.x release that carries the upgrade path, and upgrade it there."
  • Kept: "Fix the read". Dropped: the command as the alternative.

Census: packages/runtime

git grep -n -E "migrate organization-ownership|--plan-file|--out PLAN|backup-taken|ceremony" -- packages/runtime at the base, every hit read:

location what it is disposition
organization-ownership-boot-guard.ts about :242, :256–:257, :342–:343 the three branches changed (above)
organization-ownership-boot-guard.ts:110 ceremonyCommand() built the command name the refusals interpolated removed. The dev option now selects "development database".
organization-ownership-boot-guard.ts:19, standalone-stack.ts:336 code comments that describe the ceremony excluded (comments). The module docblock sentence beside :19 ("says which command to run") was corrected anyway, because it described this behaviour.
packages/runtime/CHANGELOG.md :473, :481, :912 (and :296, :444, :900, :913) released entries naming the ceremony's steps not changed. Release-owned, never edited in a code PR (AGENTS.md, Documentation Guardrails). Each entry records what its release shipped.
seed-loader-null-organization-holder-real-driver.integration.test.ts:215 a runtime test pinning 'os migrate organization-ownership' in @objectstack/metadata-protocol's seed-loader refusal not changed. The string lives in packages/metadata-protocol/src/seed-loader.ts, outside this lane (see Acceptance notes)
everything else (action-execution.ts, domain-handler-registry.ts, flow-clone.ts, sandbox/quickjs-runner.ts, security/security-catalog.testkit.ts) the word "ceremony" in unrelated comments not this family
docs/qa/platform-checklist/areas/platform-core.json, item platform-core.v18-boot-refusals (outside packages/runtime) a QA checklist item whose title and acceptance[1] expected the refusal to name the command changed in patch round 1 (revision 4, 21f7e90f4)

Met and not pre-empted: branch A also reaches a database that 18.0 itself created, when one of its objects newly declares systemFields: { tenant: false }. This PR still calls such a database "still in the v17 organization-ownership shape". The 17.x sentence is false for that database, and this PR adds no sentence for it. That wording is the open maintainer decision in #24638, and #24638 remains open.

Pins and the ablation

  • organization-ownership-boot-guard.test.ts: the old pins on the command text are rewritten. A new block holds one pin per branch: A (absent, unverified and unreadable markers), B1, B2, C, and a development boot across all four. Each asserts the refusal code, the closing text (B2 and C with "Fix the read, then start again." before it), and that the message matches none of os migrate organization-ownership, --plan-file, --out PLAN, --backup-taken.
  • organization-ownership-boot-guard.kernel.test.ts: case 4 (B1 on a real kernel) asserted --apply --plan-file PLAN --backup-taken. It now asserts the 18.0 sentence and the absence.
  • packages/qa/dogfood/test/organization-ownership-boot-refusal-order.dogfood.test.ts step 1 asserted the refusal contains 'os migrate organization-ownership'. It now asserts the 18.0 sentence and the absence. Dogfood runs only on main's full battery, not on this PR's CI, so it was run locally (below).
  • docs/qa/platform-checklist/areas/platform-core.json, item platform-core.v18-boot-refusals, revision 3 to 4 (patch round 1, commit 21f7e90f4): the title and acceptance[1] (clause, verify) asserted that the refusal names os migrate organization-ownership. They now assert the named tables, the closing 18.0 sentence, and 0 hits for --out PLAN, --plan-file and the command. The ⛔ on the code literal is kept, and a history row cites fix(runtime): the organization-ownership boot refusals say what 18.0 supports and name no step of the withdrawn ceremony command #24682.
  • Ablation, on the committed head 7ac4f50e9: node scripts/ablation-replace.mjs put branch C's old "Fix the read, or run the ceremony ('os migrate organization-ownership --out PLAN', then '… --apply --plan-file PLAN --backup-taken'), then start again." back. On disk: anchor x1 to x0, replacement x0 to x1, blob 65f1c9e2 to dad453f6. The unit file then ran 2 failed and 20 passed. The red pins were "a column read that failed: fix the read first" and "a development boot says the same … in every branch". The restore leg: blob back to 65f1c9e2 (HEAD), git diff HEAD empty. The unit test imports the guard by relative path (source), so no build or dist leg applies.

Tests and gates (code at 7ac4f50e9; the union, wide families, lint and dogfood re-run at 21f7e90f4, the final commit)

  • @objectstack/runtime, every project: pnpm --filter @objectstack/runtime test (project local) passed 425 files, 6676 tests, 19 skipped. test:repo (project repo) passed 3 files, 808 tests. typecheck passed: tsc --noEmit, plus check:test-typecheck OK with the debt ledger held. tsc -p tsconfig.test.json --listFilesOnly lists both edited test files.
  • @objectstack/cli, the tests that read the boot refusal (apply.organization-ownership-refusal.test.ts, organization-ownership.no-organization.integration.test.ts, organization-ownership.declared-rule-mirrors.integration.test.ts), against runtime's rebuilt dist: 3 files and 8 tests passed. The runtime dist carries the new sentence and has 0 hits of --apply --plan-file PLAN.
  • @objectstack/dogfood, test/organization-ownership-boot-refusal-order.dogfood.test.ts, run once at this head after its closure built (66 tasks, exit 0): 1 file and 5 tests passed.
  • Derived gates: node scripts/pm/dispatch-gates.mjs --commands named 68 commands, and each exit was captured before any pipe. 67 exited 0 on the first pass. pnpm check:dual-build-cjs-loads first answered PREREQUISITE NOT MET (exit 3), because not every package had a dist. After the whole-repo build it was re-run and exited 0 (111 require entry points across 69 packages load). --ran reconciliation: "68 derived, 68 run, 0 NOT-MEASURED, 0 UNRUN". At 21f7e90f4 the new path adds pnpm check:platform-checklist and pnpm --filter @objectstack/lint run check:doc-formula-expressions. The derivation named 70 commands, and all 70 exited 0 after the whole-repo build was restored from cache. --ran: "70 derived, 70 run, 0 NOT-MEASURED, 0 UNRUN".
  • Declared-wide families, all 11 exited 0: check:init-service-contract, check:live-db-isolation, check:meta-type-normalized, check:optional-error-sink, check:resume-authority-declared, check:route-envelope, check:runner-env-posture, check:settings-bind-window, check:startup-registry-verdict, check:verify-stand-in, check:wildcard-fallthrough. pnpm lint (eslint . --no-inline-config) exited 0. At 21f7e90f4 all 11 and pnpm lint were re-run and exited 0.
  • node scripts/check-platform-checklist.mjs --changed-from origin/main exited 0 at both heads: 3 anchors judged, 0 lost. At 21f7e90f4, pnpm check:platform-checklist exited 0 ("16 areas, 327 items"). @objectstack/plugin-auth's checklist-refusal-envelope-consistency.test.ts, which reads every area file, passed 1 file and 5 tests. The dogfood file re-run at 21f7e90f4 passed 1 file and 5 tests.
  • origin/main has moved since this branch was cut, but nothing new touches these files, so main was not merged in.

Acceptance notes


Generated by Claude Code

…supports and name no step of the withdrawn ceremony command

In 18.0, os migrate organization-ownership refuses plan and apply on every
database. Three branches of the v18 boot refusal (the v17 shape, the
no-column marker branch, and the failed column read) still prescribed its
--out PLAN / --apply --plan-file PLAN --backup-taken steps. Each now closes
on the sentence os migrate apply's drop gate and os dev already use: 18.0
supports fresh installs only and does not upgrade a v17 database; keep a v17
database on a 17.x release until the 18.x release that carries the upgrade
path. An unreadable marker or column read says to fix the read first.

Refusal text only: the refusal code, the refused tables and the boot
outcome do not move. The unit and kernel pins and the dogfood step-1 pin
that named the command are updated, with one pin per branch asserting the
sentence and the absence of the command's steps.

Claude-Session: https://claude.ai/code/session_01SYEJqDL3NXxrJRBVqaMu9T
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/m documentation Improvements or additions to documentation tests tooling labels Oct 19, 2026
@github-actions

github-actions Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

5 anchor(s) derived from 1 changed package(s); no hand-written page names any of them, so this run has nothing to list — not a clean bill of health. This check sees only pages that NAME a derived anchor: one that documents this change in prose, or enumerates it in an authoring dialect, names none and stays invisible to it on every run.

What this run could not see
  • the SDK route bridge reached 54 of 206 client-bound route-ledger rows — the other 152 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 152: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 97 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 26 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 92ce3af404a9b6ca16881a89f2e841d29da52175 → packageMentionDocs.

Which tree this was computed on

This run read content/docs from 799e034dffe255a19aafcff1fda369064ad8cbc5 — the merge of head 21f7e90f46d24a52bca2678ffb8aba46c5f30c5b into base 92ce3af404a9b6ca16881a89f2e841d29da52175, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 799e034dffe255a19aafcff1fda369064ad8cbc5 && git checkout 799e034dffe255a19aafcff1fda369064ad8cbc5
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 92ce3af404a9b6ca16881a89f2e841d29da52175 21f7e90f46d24a52bca2678ffb8aba46c5f30c5b && git checkout -B drift-repro 92ce3af404a9b6ca16881a89f2e841d29da52175 && git merge --no-ff 21f7e90f46d24a52bca2678ffb8aba46c5f30c5b

node scripts/docs-audit/affected-docs.mjs --json 92ce3af404a9b6ca16881a89f2e841d29da52175

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

…xt (revision 4)

platform-core.v18-boot-refusals asserted that the organization-ownership
boot refusal names `os migrate organization-ownership`. In 18.0 that
command refuses on every database and the refusal no longer names it or
its steps, so a run against the current text would record FAIL on a
correct product. The title and acceptance[1] (clause, verify) now assert
the named tables, the closing 18.0 sentence ("18.0 supports fresh
installs only and does not upgrade a v17 database: ...") and the absence
of the command and its --out PLAN / --apply --plan-file steps. The code
literal note is kept. Revision 3 -> 4 with a history row.

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

Copy link
Copy Markdown
Contributor Author

席位核对 — ACCEPT

domain:cli seat 1 (seat post #6024) · zhuangjianguo · session session_01SYEJqDL3NXxrJRBVqaMu9T · 2026-10-19T23:56Z · on head 21f7e90f4 · #24651 (p1, target:v18; claim 6278703183, reports 6279485022 and 6279958070). This is the seat's own review at the default tier (Clause-②: no), read against the diff on GitHub, not the reports.

  1. What moved: 6 files, +174 / −59.
    • organization-ownership-boot-guard.ts: every refusal branch ends on the sentence PR fix(cli): the organization-ownership drop refusal says what 18.0 supports for a v17 database #24635 landed: "18.0 supports fresh installs only and does not upgrade a v17 database: keep a v17 database on a 17.x release until the 18.x release that carries the upgrade path, and upgrade it there." The branches are A (v17 shape), B1 (unverified marker), B2 (unreadable marker) and C (the column read failed).
    • No branch names --out PLAN or --apply --plan-file PLAN --backup-taken any more, both of which 18.0 refuses on every database. ceremonyCommand() is gone.
    • B2 and C keep (or gain) "Fix the read, then start again." A development boot says "a v17 development database".
    • The refusal code, the refused tables and every boot outcome are unchanged. The changeset is a patch on @objectstack/runtime.
  2. Pins:
    • The unit, kernel and dogfood pins assert the code, the 18.0 sentence and the absence of the command's steps, one pin per branch.
    • The ablation that restores branch C's old alternative turns exactly 2 pins red. The restore was proven by blob.
  3. Patch round 1 (owed by this PR, in place): platform-core.v18-boot-refusals moves to revision 4.
  4. Accepted deviations:
    • The dogfood pin organization-ownership-boot-refusal-order.dogfood.test.ts is one of the "tests that pin these strings". It was run locally (5/5), since dogfood does not run on PR CI.
    • Pinning the closing sentence rather than the first follows the card's ask; the code is asserted alongside.
  5. Gates:
    • dispatch-gates 70 derived and 70 run, 0 NOT-MEASURED.
    • The 11 wide families and pnpm lint exited 0. check:platform-checklist exited 0.
    • runtime local tier: 425 files, 6,676 passed. The three cli readers of the refusal pass against the rebuilt dist.
  6. Serial note: the epic lane's PR 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 (feat(cli): 18.x step 5: the upgrade ceremony steps behind the refusal (webhook re-source, sibling moves, 9c, 8e NOT NULL) #24581) rewrites the same file. This seat's dispatch missed that claim's description, and owns that miss. The order is recorded on feat(cli): 18.x step 5: the upgrade ceremony steps behind the refusal (webhook re-source, sibling moves, 9c, 8e NOT NULL) #24581 (this seat's declaration): this PR lands first, and 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 merges main afterwards and takes its own text. It is an ordering, not a merge of the two.
  7. Findings:
  8. Landing: ready plus auto-merge through the queue once every check of 21f7e90f4 is green or a rostered skip. Fixes #24651 closes the card on the merge.

Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 19, 2026 23:58
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 19, 2026 23:58
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 20, 2026
Merged via the queue into main with commit 9e2722a Oct 20, 2026
49 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-24651-boot-refusal-18-0-text branch October 20, 2026 00:23
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 tests tooling

Projects

None yet

2 participants