Repository navigation
docs(releases): write the 18.0.0 upgrade checklist — the v18 page still says curated notes "are not written yet", and Upgrading's per-release table has no v18.0.0 row (nor 17.5–17.7) #24905
Copy link
Copy link
Closed
Labels
area:devpathThe road — create, dev, verify, publish/install, connect an agent, iterateThe road — create, dev, verify, publish/install, connect an agent, iteratedocumentationImprovements or additions to documentationImprovements or additions to documentationdomain:devxpriority:p1High: required for production / M2High: required for production / M2
Description
Filing gate ③: a task the maintainer set. The maintainer said 「立一张 p1 文档卡交给 domain:devx,写 18.0.0 的升级清单」 in the triage seat's chat, after 18.0.0 published. Filed by the triage seat (#6015, session_01AavokzJ5DndAwitDXvKy4U). ⛔ Not a claim.
Reader (who acts): the domain:devx seat, in one docs PR on content/docs/releases/v18/** and content/docs/upgrading.mdx. The first real reader is objectstack-ai/hotcrm#2202, HotCRM's upgrade to 18.0.0, which is dispatched now.
Readings (origin/main, after the 18.0.0 publish)
- The v18 page is not finished.
content/docs/releases/v18/index.mdx(last touched by PR docs(releases): state 18.0.0 as the v18 GA release, so the GA Version Packages PR renders #24584, before the cut) ends with: "Curated notes for the line's releases are compiled at release time and are not written yet; until then, the changesets are the record." No 18.0.0 page and no upgrade checklist exist. The v17 line has one page per minor, each with## Upgrade checklist. - Upgrading's per-release table (
content/docs/upgrading.mdx, "Per-release specifics", about:336–360):- it has no v18.0.0 row;
- it stops at
v17.4.0 — ⛔ checklist not written, although17-4.mdxnow carries## Upgrade checklist; - it has no rows for 17.5, 17.6 or 17.7, though each of those pages has a checklist.
The page's own rule is to read the checklist for every release you cross, so a 17.4 → 18 reader is sent nowhere.
- The record a checklist is curated from:
packages/spec/CHANGELOG.mdat the version commit06cab4849a. Its## 18.0.0section alone is about 6,300 lines and 344 entries, the raw changesets of the whole line.
The checklist covers (each item measured on the 18.0.0 artifact, not restated from a card)
- Moving the pins: every
@objectstack/*to 18 together,engines.protocol: '^18', and the skills move (the v18 page's existing step). - The database: a v17 database takes the ownership ceremony,
os migrate organization-ownership(plan, then--apply --plan-file; ADR-0131 D10; 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) #2468112d14765c7, "a server serves only a database it created or one the ceremony certified"). Say what an operator sees when it has not been run. - The breaking narrowings that reach an app author, grouped by what the author must edit, each with its error code or refusal text. Curated from the 18.0.0 CHANGELOG, not copied from it.
- What 18.0.0 does not yet carry: the 18.x steps that landed after the cut (for example 7a-2, PR feat(core,plugin-security)!: 18.x step 7 part 7a-2 — a grant applies only in its own organization; the organization-less grant readers retire #24872) ship in 18.1.0.
mainholds 12 pending changesets, 5 of themminor, and the fixed group renders 18.1.0 from them. Read this offmainwhen writing, and state the posture of the walled modes (group/isolated) asos serve18.0.0 actually behaves. - The npm tags:
latest=18.0.0, whilenextstill names18.0.0-next.5, which is older thanlatest. The docs never point a reader at@nextfor 18. Moving that dist-tag is the maintainer's act, not this PR's.
Done when
content/docs/releases/v18/carries the 18.0.0 notes with a## Upgrade checklist(an18-0.mdxbesideindex.mdx, as the v17 line does it, or the checklist in the index), and the "not written yet" sentence is gone.- Upgrading's table has a v18.0.0 row linking that checklist, and its 17.4–17.7 rows match their pages.
- The checklist is walked once against a real upgrade, ideally HotCRM's in chore(deps): upgrade the ObjectStack platform to 18.0.0 hotcrm#2202, and any step that reads differently is fixed before merge.
- The docs gates the repo runs on
content/docsstay green. ⛔ No new gate.
Dedupe
objectstack issues and PRs updated since 2026-10-12 were grepped for curated, release notes, releases/v18, "GA prose", "upgrade guide" and Upgrading. The hits:
- docs(releases): the v18 GA prose — the release index and the v18 page state 18.0.0 released, so the GA Version Packages PR renders #24569 (closed
completedon 10-19 through PR docs(releases): state 18.0.0 as the v18 GA release, so the GA Version Packages PR renders #24584): it wrote only the GA status prose and deferred the curated notes in so many words; - spec(migrations): two step-18 upgrade rationale fragments print a tracker id to the author, "(#11509, ruling A-narrow)", in
os migrate metaand the upgrade guide #24179 (closed, unrelated).
New.
Generated by Claude Code
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
area:devpathThe road — create, dev, verify, publish/install, connect an agent, iterateThe road — create, dev, verify, publish/install, connect an agent, iteratedocumentationImprovements or additions to documentationImprovements or additions to documentationdomain:devxpriority:p1High: required for production / M2High: required for production / M2
Activity
objectstack-fleet commentedon Oct 20, 2026
Claim: PM loop round 26 · a p1
domain:devxdocs card the maintainer set after 18.0.0 published; serial dispatch under the maintainer's 「串行派发」Session:
session_01FM29ZqLTrnPNXxijioZwMpAccount:
os-warren(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-24905-v18-upgrade-checklistWorktree:
objectstack-issue-24905Domain:
domain:devxSeat:
domain:devx#1File surface:
content/docs/releases/v18/**: the 18.0.0 notes with a## Upgrade checklist, in an18-0.mdxbesideindex.mdxas the v17 line does it, plusmeta.json. The "not written yet" sentence goes.content/docs/upgrading.mdx: the "Per-release specifics" table gains a v18.0.0 row, and its 17.4–17.7 rows match their pages.Every checklist step is measured on the published 18.0.0 artifact, not restated from a card or from
main. Stop on breach and explain.nexttag is the maintainer's.Container & model:
M (one new release page and one table, each step measured on the 18.0.0 tarballs),mode:subagent,model: TIER_DEFAULTClause-②: no
Responsibility:
the v18 release page says its curated notes "are not written yet", and Upgrading's per-release table has no v18.0.0 row, so a 17.x → 18 reader has no checklist (#24905)|none: the raw 18.0.0 CHANGELOG, about 6,300 lines and 344 entries|every app upgrading to 18.0.0, first HotCRM (objectstack-ai/hotcrm#2202)Thread-read: none
Serial constraints cleared: no open PR touches
content/docs/releases/v18/orcontent/docs/upgrading.mdx(read at 2026-10-20T13:42Z). No dev of this session is in flight: round 15 of qa(checklist): 18.0 release sweep anchor at 5b14b7f3 — re-point 5 red-row clauses + the wave's checklist-accuracy findings, fixture gaps and not-run handover (18 records) #24579 has reported, and its PR docs(qa): 18.0 sweep anchor round 15 — QA round 4's ref-accuracy findings, scored per RUNNER rule 6 (a pin scores only the layer it drives) #24891 is queued.Generated by Claude Code
objectstack-fleet commentedon Oct 20, 2026
os-dev-report
{
"issue": 24905,
"status": "done",
"branch": "claude/issue-24905-v18-upgrade-checklist",
"pr": "#24922",
"session": "session_01FM29ZqLTrnPNXxijioZwMp — subagent run, the parent's id (dispatch.mjs --route derived the same from CLAUDE_CODE_REMOTE_SESSION_ID)",
"premise_still_valid": true,
"summary": "Wrote content/docs/releases/v18/18-0.mdx (highlights, measured release facts, how to read the cumulative 18.0.0 CHANGELOG, and a 5-step ## Upgrade checklist), listed it in meta.json, removed the 'not written yet' sentence from v18/index.mdx and linked the page, and gave Upgrading's table a v18.0.0 row plus 17.7/17.6/17.5 rows and a fixed 17.4 row. Every checklist line carries its measurement class (walk / probe on the installed 18.0.0 spec and CLI / tarball read); the checklist was walked twice from a create-objectstack@17.7.0 scaffold with a 17.7.0-created SQLite database, through the refused boot, the ownership ceremony and a clean served boot. The card's core premise holds; one sub-premise does not: 7a-2 (#24872) is an open PR, not on main, and 7a-3 (#24828) / 7b-3 (#24845) landed BEFORE the version commit, so their code shipped in 18.0.0 while their changesets are still pending (8 such changesets) — step 4 states this split.",
"tests": "Docs-only diff: no package test or typecheck owed (no package touched, no ① closure). Evidence is the walk and the probes, all on npm 18.0.0: walk 1 and walk 2 (fresh scaffold following the written steps) both printed ceremony plan '81 table(s) planned … 34 will receive NOT NULL', unattributableRows 0, apply '✓ The ceremony is complete; recorded as adr-0131-organization-ownership.'; refused boot exit 1 with the quoted ORGANIZATION_OWNERSHIP refusal; served boot ✓ Server is ready, 3 notes read, 17.7.0 API key HTTP 200; final boot 0 schema-drift lines. Probes: 4 os validate probe stacks (exit 1, rule expression-invalid / component-props-*), defineStack probes (STACK_SCHEMA_INVALID / STACK_CROSS_REFERENCE_INVALID 422), defineSeed, ListViewSchema editInline=true. No ablation: no tested behaviour changed.",
"gates": "Local, at head 5019f51: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 62 commands; all 62 ran, each exit 0 captured before any pipe (runner redirects to a log then reads $?). check:docs-transcript-drift and spec check:skill-examples first answered exit 3 PREREQUISITE NOT MET, then exit 0 after pnpm --filter '@objectstack/lint...' build (os-verify-lock VERDICT command-exit 0, 129s) and pnpm --filter '@objectstack/client-react...' build (VERDICT command-exit 0, 326s). --ran with ':: exit N' records: 'Run reconciliation — 62 derived, 62 run, 0 NOT-MEASURED, 0 UNRUN' (a DERIVED zero). Earlier at 36cbe22 check:docs-audit-scope exit 1 (roster missing the new page; fixed with check-audit-scope.mjs --write, +1) and check:role-word exit 1 (2 uses of the reserved word; reworded) — both exit 0 on the final head. CI check-runs on 5019f51 at report time: No other open PR may claim the same issue success, Check Changeset success, Check Documentation Links success, filter success; Lint (8 lanes), Type Check (4 lanes), Governed Surface Queue Guard, Spec property liveness in_progress; Build Docs and Test Core 1-6 queued; Build Core skipped. Not waited on (CI convergence is the PM's).",
"mcp_calls": "0",
"api_writes": "2 — (1) one fleet-relay stroke: POST /repos/objectstack-ai/objectstack/dispatches (HTTP 204), relay run 39445276524 executing POST /repos/objectstack-ai/objectstack/pulls (draft #24922), POST /repos//issues/24922/assignees [os-warren], POST /repos//issues/24922/labels [skip-changeset]; read back: body 15156 bytes identical, assignees os-warren, labels skip-changeset, draft true. (2) this os-dev-report via scripts/pm/post-stamped.mjs: POST /repos//issues/24905/comments. Plus git push (not REST). Reads only otherwise (gh api GET, npm view/pack).",
"checklist_measurements": [
"1 pins: walk — pnpm install moved 7 ^17.7.0 ranges to 18.0.0, no peer warning",
"1 protocol: walk — on '^17' validate warns, boot exit 1 '✗ package 'com.example.v17app' targets protocol ^17 … Run: objectstack migrate meta --from 17'; migrate meta --from 17 --write printed 'manifest.engines.protocol: '^17' → '^18''; specVersion is read by neither validate nor boot (validate passed with it on ^17.0.0)",
"1 migrate meta: walk — '406 manual change(s) require your judgment' on a one-object app",
"1 skills: walk — sync before removal: 'Skipped … installed with skills add' x10 + 'Nothing to sync.' exit 0; after: 'Synced 10 skills'; npm install --save-dev exit 1 'Cannot read properties of null (reading 'edgesOut')' in the pnpm project; pnpm add -D wrote '"@objectstack/skills": "18.0.0"'",
"2 overlays: walk 2 — os migrate security-catalog-overlays exit 0 '✓ No environment-wide permission-set or position row is stored over a package-held name'",
"2 refused boot: walk — exit 1 before listening, plugin com.objectstack.organization-ownership-boot-guard; code ORGANIZATION_OWNERSHIP_MIGRATION_REQUIRED read off @objectstack/runtime 18.0.0 dist/index.js; plan before that boot 77 tables, after 81",
"2 apply-first trap: walk on a DB copy — os migrate plan '28 change(s): 0 safe, 0 needs-confirm, 28 destructive' naming apply --allow-destructive; that apply exit 1 '✗ Refusing to drop sys_comment.reactions …'",
"2 ceremony: walks 1+2 — plan 81 tables / 34 NOT NULL / unattributableRows 0; apply rowsAttributed 32, grants named 2, mirrors deleted 49, columns dropped 14, NOT NULL applied 32; served boot keeps platform_admin/org_owner/admin_full_access",
"2 drift: walk 2 — comment-reactions --apply --yes 'Converted 1 reaction(s)'; migrate apply --allow-destructive --yes 'Applied 3 change(s)'; next boot 0 drift lines; reaction reads back from sys_comment_reaction",
"3 flows/pages/objects/security/datasources: probes on the installed 18.0.0 (defineStack 422 codes, os validate exit 1) at the positions each line's tag names; save door PUT /api/v1/meta/page/NAME → 422 INVALID_METADATA for an undeclared prop and kind 'jsx'; OS_DATABASE_DRIVER=mongo os serve exit 1 'Unsupported driver "mongo"'",
"3 hooks/code: tarball — cli dist/utils/extract-hook-body.js (ctx.dispatch.scope, ctx.submitted), plugin-security ('carries no principal', AUTHZ_STORE_IDENTITY_OBJECTS), service-i18n d.ts ('registerRoutes and basePath are gone'), verify (bootStack, runDashboardWindowProofs); exports normalizeVisibleWhen/VISIBILITY_ALIAS_KEYS/VISIBILITY_STRICT_OPTIONS/CONVERSION_CONFLICT_CODE/checkPageComponentViewData probed absent; walk: os meta resync exit 2 'command meta:resync not found'",
"3 REST/SDK/keys: walk 2 against served 18.0.0 — new key expires_at +90d; 2-year key 400 API_KEY_EXPIRY_TOO_LONG; 17.x key stamped expires_at +1y and HTTP 200; foreign Origin GET and preflight: no access-control-allow-origin; 401 UNAUTHENTICATED on /api/v1/openapi.json and /api/v1/i18n/locales; text/plain → 400 INVALID_REQUEST; null / [1,2] / expectedVersion 3 → 400 VALIDATION_FAILED; sys_permission_set, sys_position, sys_position_permission_set, sys_capability → 404; grants carry permission_set, no permission_set_id; upload scope public → 400 INVALID_REQUEST; API_KEY_INACTIVE/EXPIRED/REVOKED (core), PAYLOAD_TOO_LARGE (service-storage), forms submit and treatAsHistorical (rest), 'no searchable field' (objectql) read off tarballs",
"4 pending: main at a7199ef — 20 changesets, 6 minor ⇒ 18.1.0; merge-base --is-ancestor vs 06cab48 in a full clone: 8 exit 0 (shipped in 18.0.0, unlisted), 12 exit 1 (not in it); tarball: deploymentWide (plugin-sharing), codeInviteRoleNotFound (plugin-auth) present, adopt-orphans guard absent (runtime); walk: os serve with no auth secret exit 1 '✗ This stack enables auth, but no auth secret is set …'; #24872 open, not merged",
"4 walled: walk on fresh DBs — refusals in order: organizations runtime absent ('✖ FATAL: tenancy posture 'group' was requested but @objectstack/organizations could not be loaded'), OS_PLATFORM_OWNER_EMAIL, membership policy; with all set both group and isolated '✓ Server is ready'",
"5 tags: npm view dist-tags — latest 18.0.0, next 18.0.0-next.5, rc 17.0.0-rc.6 (spec, cli, runtime, core, objectql; skills and organizations have no rc); versions list has no 18.0.0-next.4"
],
"walk": "Fixture: create-objectstack@17.7.0 blank scaffold 'v17app' (pnpm 10.28, Node 22.22, 10 skills via skills add), booted once on 17.7.0 with objectstack start → .objectstack/data/objectstack.db; walk 1 seeded an admin + 3 notes, walk 2 (fresh scaffold, following the written steps 1-2) also an API key and a comment with a stored emoji reaction. All under the session scratchpad. Each step's outcome is in checklist_measurements. What the walk changed in the page: (1) skills step uses the project's package manager (npm exit 1 in a pnpm project) — also fixed in v18/index.mdx; (2) specVersion is a hand edit; (3) step 2 order: overlays → a deliberately refused boot (77 → 81 tables) → backup → plan → apply, and not apply --allow-destructive first; (4) the post-ceremony drift tail (comment-reactions, then apply --allow-destructive); (5) step 4 split into 'shipped unlisted' vs 'not in 18.0.0'. HotCRM (objectstack-ai/hotcrm#2202) named in the PR as first downstream reader, not walked.",
"hypotheses": [
"H1 FALSIFIED — walledPostureRefusal is in @objectstack/cli@18.0.0-next.5 dist/commands/serve.js and absent from 18.0.0 (added ae6bd1a #24480, removed fc34d00 #24667); os serve 18.0.0 boots group/isolated given @objectstack/organizations + OS_PLATFORM_OWNER_EMAIL + a declared membership policy",
"H2 CONFIRMED — refused before the port binds, exit 1, code ORGANIZATION_OWNERSHIP_MIGRATION_REQUIRED (on the error object; the printed line carries the remedy naming os migrate organization-ownership --out PLAN, then --apply --plan-file PLAN --backup-taken)",
"H3 CONFIRMED — 17-4.mdx has ## Upgrade checklist at line 606; 17-5/17-6/17-7 at 1671/1524/1259 had no rows"
],
"deviations": [
"File-surface breach, named: scripts/docs-audit/handwritten-docs.json +1 line (generated by check-audit-scope.mjs --write) — the ruled page shape makes check:docs-audit-scope red without it, and the dispatch also rules the docs gates green; kept green, named here and in the PR body (open_questions[0])",
"Upgrading.mdx: besides the rows, the sentence 'Only the v17 line is broken out per release. Each of its three minors…' (made false by the v18 row; 'three' already wrong) now reads 'The v17 and v18 lines are broken out per release. Each v17 minor…'; the page's rules and its step-4 skills command are untouched",
"Corpus widened from packages/spec/CHANGELOG.md (341 entries, 132 of 340 flagged) to all 53 package CHANGELOG 18.0.0 sections (1,115 entries) — business-need axis",
"Two app-relevant behaviours left out of the checklist as unmeasurable here (1b40780; f05649f/3f0b6f2) instead of tagged 'not measured'",
"Merged origin/main once before opening the PR (a7199ef, no conflict); main has since moved to 81e6edd (+1 pending changeset), not merged (no conflict, no red)",
"Two walks instead of one: the first drafted steps 1-2, the second followed the written text"
],
"files_changed": [
"content/docs/releases/v18/18-0.mdx (new)",
"content/docs/releases/v18/index.mdx",
"content/docs/releases/v18/meta.json",
"content/docs/upgrading.mdx",
"scripts/docs-audit/handwritten-docs.json"
],
"open_questions": [
{
"question": "Accept the one-line scripts/docs-audit/handwritten-docs.json entry outside the dispatched file surface?",
"options": [
"A keep it in PR #24922 — check:docs-audit-scope stays green, the line is generator-written",
"B split it into its own PR — #24922's Lint & Repo Gates stays red until that lands"
],
"recommendation": "A, because the ruled 18-0.mdx shape requires it and the dispatch also rules the docs gates green; it is a generated roster row, not gate code"
}
],
"out_of_scope_findings": [
"class: b · reach: exception: release-text (published 18.0.0 tarballs) — the 18.0.0 CHANGELOGs omit 8 changesets whose commits precede the version commit 06cab48 and whose code ships in 18.0.0: .changeset/24583-7a3, 24583-7b3, 24750, 24751, 24767, 24772, 24773, 24785; measured: os serve 18.0.0 with no auth secret exits 1 '✗ This stack enables auth, but no auth secret is set …' (7b-3, #24845) while no 18.0.0 CHANGELOG entry mentions it; deploymentWide in plugin-sharing, codeInviteRoleNotFound in plugin-auth. Contract: AGENTS.md documentation-guardrails row (the CHANGELOG ships in the tarball as the text an upgrading agent greps). Seam: release.yml version-pr job (six-hourly regeneration) → publish on merge. Dedupe words: version packages stale, changeset not consumed, CHANGELOG missing shipped entry, version-pr regeneration race",
"class: a · reach: public door
os migrate plan/ the boot's [schema-drift] lines on a 17.7.0-created database, measured: '28 change(s) … 28 destructive', 'Apply with: os migrate apply (add --allow-destructive …)', no word of the ownership ceremony; the prescribed apply then exits 1 on sys_comment.reactions. Misleading operator copy (user-visible). Dedupe words: migrate plan ownership ceremony, schema-drift organization_id orphaned, allow-destructive before ceremony","class: a · reach: walk —
npm install --save-dev \"@objectstack/skills@…\"exits 1 ('npm error Cannot read properties of null (reading 'edgesOut')') in a pnpm-installed create-objectstack project; still the command in content/docs/upgrading.mdx step 4, content/docs/ai/skills.mdx:32, content/docs/ai/skills-reference.mdx:21, skills/README.md:11, skills/objectstack-upgrade/SKILL.md:129 (fixed here only in releases/v18). Dedupe words: skills npm install pnpm, @objectstack/skills save-dev, experimental_sync pnpm","carrier: 承接者:无 · noted, not filed — 18.0.0-next.4 was never published (npm versions list) while every CHANGELOG carries a ## 18.0.0-next.4 section",
"carrier: 承接者:无 · noted, not filed — os migrate security-catalog-overlays' read-only preview printed 'Raw execute() called … FORWARDED, not refused — if it wrote, this boot wrote' on the walk's DB; the file's mtime did not move",
"carrier: 承接者:无 · noted, not filed — os migrate meta --from 17 lists 406 manual to-dos on a one-object app (none proved absent)"
]
}
objectstack-fleet commentedon Oct 20, 2026
os-dev-report
{
"issue": 24905,
"status": "done",
"branch": "claude/issue-24905-v18-upgrade-checklist",
"pr": "#24922",
"session": "session_01FM29ZqLTrnPNXxijioZwMp — subagent run, the parent's id (fleet-write --route derived the same from CLAUDE_CODE_REMOTE_SESSION_ID)",
"premise_still_valid": true,
"summary": "Fix round: merged origin/main (#24912, 7169612) into the branch with git merge (merge commit b6917f0, no rebase/amend/force). The one conflict — both sides adding a v18.0.0 row to Upgrading's Per-release specifics, #24912's side also carrying the stale v17.4.0 row — resolved to ONE v18.0.0 row linking /docs/releases/v18/18-0#upgrade-checklist, #upgrading-to-180 and /docs/releases/v18, with this PR's 17.4–17.7 rows. Upgrading to 18.0's sequence now runs in the walk's order (security-catalog-overlays first, the drift tail last, one link to 18-0#2-upgrade-the-database); the membership-policy prerequisite and an os-build-first caveat for os dev were added to #24912's bullets in upgrading.mdx and v18/index.mdx; 18-0.mdx names which CHANGELOG copy its ae6bd1a caution reads, links the Upgrading overview, and replaces three 'not walked' statements with new measurements (a walled group 17.7.0 database upgraded and served; an os dev database upgraded in place; os start generating its auth secret). packages/cli/CHANGELOG.md untouched; the diff vs main is still exactly the five files.",
"tests": "Docs-only diff: no package test or typecheck owed. New measurements on npm 18.0.0 (walk 3, scratchpad): walled — create-objectstack@17.7.0 app + @objectstack/organizations@17.7.0 booted under OS_TENANCY_POSTURE=group, owner + 2 records; after moving to 18.0.0: security-catalog-overlays exit 0, refused boot exit 1, plan 'posture group' 81 tables unattributableRows 0, apply '✓ The ceremony is complete', served 'Tenancy: group' with both records in their organization. Dev DB — a 17.7.0 os dev database: OS_DATABASE_URL=file:… os serve --dev exit 1 "Run 'os migrate organization-ownership --dev --out PLAN' …"; os dev with the 17.7.0-compiled dist/objectstack.json: '✗ The upgrade plan was refused, and nothing was changed.'; after os build: '✓ Upgraded the development database to the v18 organization ownership' and '✓ server started on the upgraded database'. os start, fresh --home, no AUTH_SECRET/OS_AUTH_SECRET: wrote HOME/auth-secret mode 0600, served, sign-up 200. CHANGELOG copies: tarball @objectstack/cli@18.0.0 CHANGELOG.md line 162 old ae6bd1a text; repo packages/cli/CHANGELOG.md at 7169612 line 162 amended text, fc34d00 headline amended. No ablation.",
"gates": "Re-derived on the final diff at head b6917f0 vs merge base 7169612: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack → 62 commands (identical to the pre-merge 62); all 62 ran, each exit 0 captured before any pipe, after pnpm --filter '@objectstack/lint...' --filter '@objectstack/client-react...' build under os-verify-lock (VERDICT command-exit 0, 302s). --ran with ':: exit N': 'Run reconciliation — 62 derived, 62 run, 0 NOT-MEASURED, 0 UNRUN' (a DERIVED zero). git merge-tree --write-tree origin/main HEAD exit 0 before the push and again after (origin/main 7169612). CI check-runs on b6917f0 at report time: Lint & Repo Gates success, TypeScript Type Check success, Test Core success (1/6–6/6 success), Governed Surface Queue Guard success, Build Docs success, Check Documentation Links success, all 8 Lint lanes and 4 Type Check lanes success; Build Core skipped, Check Changeset skipped; 'No other open PR may claim the same single-writer path', 'Part-of PR must not also close its card', 'The card this PR closes must claim this branch' in_progress. Totals: 35 success, 11 skipped, 3 in_progress.",
"mcp_calls": "0",
"api_writes": "2 this round — (1) one fleet-relay stroke: POST /repos/objectstack-ai/objectstack/dispatches (HTTP 204), relay run 39461739940 executing PATCH /repos//issues/24922 (PR body: + '## Merge with #24912', Gates re-measured, superseded statements marked); read back 21954 bytes identical; draft still true, assignees os-warren, labels documentation, size/l, skip-changeset. (2) this os-dev-report via scripts/pm/post-stamped.mjs: POST /repos//issues/24905/comments. Plus git push (b6917f0; not REST). Reads otherwise (gh api GET, npm view/pack/install). Previous round: 2 (pr_create stroke, first report comment).",
"reconciled_points": [
"1 · content/docs/upgrading.mdx table · two v18.0.0 rows + #24912's stale 'v17.4.0 — ⛔ checklist not written' row → one v18.0.0 row 'Upgrade checklist — 18.0.0 · Upgrading to 18.0 (the ownership ceremony) · v18' + this PR's 17.4–17.7 rows · measured: hypothesis 3 (17-4.mdx carries ## Upgrade checklist)",
"2 · content/docs/upgrading.mdx 'Upgrading to 18.0' sequence · 6 steps → 8 in the walk's order: 1 os migrate security-catalog-overlays (exit 1 on a listed row, --apply deletes) before the first boot … 8 os migrate comment-reactions --apply --yes, then os migrate apply --allow-destructive --yes; + one link to /docs/releases/v18/18-0#2-upgrade-the-database for each step's measured output; the rest of #24912's prose unchanged · measured: walks 2 and 3 overlays exit 0 '✓ No environment-wide permission-set or position row is stored over a package-held name'; walk 2 'Converted 1 reaction(s)', 'Applied 3 change(s)', next boot 0 drift lines",
"3 · content/docs/upgrading.mdx --dev paragraph · '… os dev runs the whole sequence itself for a local SQLite development database.' → + 'Run os build before it: while dist/objectstack.json was still the artifact 17.x compiled, os dev's in-place upgrade refused its plan and changed nothing.' · measured: walk 3 dev DB ('✗ The upgrade plan was refused, and nothing was changed.' then, after os build, '✓ Upgraded the development database …')",
"4 · content/docs/upgrading.mdx walled bullet · + 'A walled boot also needs a declared membership policy, OS_AUTH_MEMBERSHIP_POLICY=invite-only (or auto, chosen knowingly); without one it is refused: ✖ FATAL: tenancy posture 'group' is walled, but this deployment never declared a membership policy.' · measured: fresh-DB walled walk (refusal), walk 3 (upgraded group DB served with it set)",
"5 · content/docs/releases/v18/index.mdx --dev bullet · '… os dev runs the ceremony itself for a local SQLite development database.' → + ', once os build has replaced the artifact 17.x compiled: with that artifact in dist/, its in-place upgrade refused its plan and changed nothing.' · measured: as 3",
"6 · content/docs/releases/v18/index.mdx walled bullet · + '18.0.0 also refuses a walled boot until a membership policy is declared (OS_AUTH_MEMBERSHIP_POLICY=invite-only, or auto chosen knowingly): ✖ FATAL: …' ; #24912's 'same prerequisites as 17.x' sentence kept · measured: as 4",
"7 · content/docs/releases/v18/index.mdx 'Upgrading a database to 18.0.0' · closing sentence + 'each step's measured output is in the walked 18.0.0 upgrade checklist'; ## Per-release notes kept; nothing of #24912's removed · measured: —",
"8 · content/docs/releases/v18/18-0.mdx 'How to read the 18.0.0 CHANGELOG' · ae6bd1a caution unqualified → reads the copy the published @objectstack/cli@18.0.0 tarball carries (what node_modules holds), names #24912's in-place amendment of packages/cli/CHANGELOG.md (ae6bd1a and the fc34d00 headline) and quotes the amended text · measured: tarball CHANGELOG.md line 162 vs repo line 162 at 7169612",
"9 · content/docs/releases/v18/18-0.mdx step 2 intro · + 'The overview is Upgrading to 18.0' · measured: —",
"10 · content/docs/releases/v18/18-0.mdx step 2 os dev · 'according to the CLI reference … the walk … did not exercise that path' → measured os serve --dev refusal ('Run 'os migrate organization-ownership --dev --out PLAN' …'), os dev's in-place upgrade with a backup copy, and the os-build-first caveat · measured: walk 3 dev DB",
"11 · content/docs/releases/v18/18-0.mdx step 4 auth secret · 'A production server boot with no auth secret is refused' → 'A production os serve boot …' + 'os start is not refused: with no secret set it wrote HOME_DIR/auth-secret (mode 0600) on its first run and served sign-up' — agrees with #24912 · measured: os start fresh --home, no secret",
"12 · content/docs/releases/v18/18-0.mdx Callout + step 4 walled · 'A walled database … not walked' / 'Upgrading a walled 17.x database … was not walked' → the group upgrade walked (isolated not walked) — agrees with #24912's 'on a database the ceremony upgraded' for group · measured: walk 3 walled",
"13 · content/docs/releases/v18/18-0.mdx step 4 pending set (not a #24912 point; named because the merge brought .changeset/24583-7a2-… into the tree) · 'Read on main at a7199ef: 20 … six minor … 7a-2 is an open pull request' → 'Read on main at 7169612: 26 … ten minor'; 8 shipped in 18.0.0 unlisted; 18 not in it, six minor: 7a-2 (#24872, merged 15:26 UTC, after the cut), #24875, #24861, #24920, #24878, #24881 · measured: merge-base --is-ancestor per changeset vs 06cab48 (8 exit 0, 18 exit 1); gh api pulls/24872 merged true",
"agreement, re-measured: #24912 'Start 18.0 against the database once (os serve / os start)' (walks used os start); 'The refusal os serve --dev prints names the command with --dev' (walk 3)"
],
"deviations": [
"File surface held: the diff vs main is the same five files (18-0.mdx, v18/index.mdx, v18/meta.json, upgrading.mdx, scripts/docs-audit/handwritten-docs.json); packages/cli/CHANGELOG.md untouched",
"Point 13 edits this PR's own step-4 reading (not #24912 text) because the merge made 'not on main' false",
"Points 3 and 5 add one sentence each to #24912's --dev text under ruling 4 (the measurement adds a precondition #24912's sentence does not state); no other #24912 prose rewritten",
"The worktree had been removed after round 1; it was re-created from the pushed branch (5019f51, identical to origin) before the merge"
],
"files_changed": [
"content/docs/releases/v18/18-0.mdx",
"content/docs/releases/v18/index.mdx",
"content/docs/upgrading.mdx",
"(unchanged this round: content/docs/releases/v18/meta.json, scripts/docs-audit/handwritten-docs.json)"
],
"open_questions": [],
"out_of_scope_findings": [
"carrier: 承接者:无 · noted, not filed — WITHDRAWN as a defect: the round-1 finding '18.0.0 CHANGELOGs omit 8 changesets whose code shipped in 18.0.0' is the #23818 ruling's annotate-shipped path working as ruled (epic seat note 6294471945); the 18.0.0 CHANGELOG already carries entries headed 'Shipped in 18.0.0-next.2, whose CHANGELOG missed this entry'",
"class: a · reach: walk 3 — os dev 18.0.0's in-place ceremony on a 17.x dev database reads the stale dist/objectstack.json (17.7.0's os start compiled it) and refuses the plan with the protocol-^17 refusal although objectstack.config.ts reads '^18'; nothing changes and a backup is kept, but the refusal prescribes 'objectstack migrate meta --from 17', which was already done — the remedy that works is os build. Documented here; the misleading prescription is the CLI's. Dedupe words: os dev ownership upgrade stale artifact, dist objectstack.json protocol 17, upgrade plan was refused",
"class: a · reach: public door os migrate plan on a 17.7.0-created database (round 1, unchanged) — the [schema-drift] lines and os migrate plan prescribe os migrate apply --allow-destructive for the organization_id columns with no word of the ceremony; the apply then exits 1 on sys_comment.reactions. Dedupe words: migrate plan ownership ceremony, schema-drift organization_id orphaned, allow-destructive before ceremony",
"class: a · reach: walk (round 1, unchanged) — npm install --save-dev "@objectstack/skills@…" exits 1 (edgesOut) in a pnpm-installed project; still the command in content/docs/upgrading.mdx step 4, content/docs/ai/skills.mdx:32, content/docs/ai/skills-reference.mdx:21, skills/README.md:11, skills/objectstack-upgrade/SKILL.md:129. Dedupe words: skills npm install pnpm, @objectstack/skills save-dev",
"carrier: 承接者:无 · noted, not filed — os serve --dev with no OS_DATABASE_URL booted ':memory:', not the project's .objectstack/data database, so the --dev refusal only appears when the URL names the dev database file (walk 3)"
]
}
objectstack-fleet commentedon Oct 20, 2026
os-dev-report
{
"issue": 24905,
"status": "done",
"branch": "claude/issue-24905-v18-upgrade-checklist",
"pr": "#24922",
"session": "session_01FM29ZqLTrnPNXxijioZwMp — subagent run; parent's harness-stamped id (Claude-Session: line)",
"premise_still_valid": true,
"summary": "Fix round 2: the two sites that told a reader to run
os migrate apply --allow-destructive --yeswithout reading its plan now say: previewos migrate comment-reactions, then--apply --yes; runos migrate planand go on only if its destructive entries are the ceremony's leftovers (the walk's three columns); any other entry is the app's own and decided separately; then runos migrate apply --allow-destructivewithout--yesin a terminal and answer its[y/N]prompt.--yeswas measured on 18.0.0 first (TTY and non-TTY), and the non-TTY exit-0-with-nothing-applied behaviour is stated on both pages. The rule-4 sweep foundnpx skills remove --all(removes every installed skill, no prompt) on Upgrading and v18/index with no preview: both now say runnpx skills listfirst, and 18-0 step 1 names it before the named remove. Commit 9da4c8d pushed; PR body gained## Round 3; the ceremony's--apply --plan-file … --backup-takenuntouched.","sites": [
{
"file": "content/docs/upgrading.mdx",
"where": "Upgrading to 18.0, step 8",
"old": "Clear the orphaned columns the first served boot still reports:
os migrate comment-reactions --apply --yes, thenos migrate apply --allow-destructive --yes.","new": "Clear the orphaned columns the first served boot still reports, and only those. Preview with
os migrate comment-reactions, thenos migrate comment-reactions --apply --yes. Thenos migrate planand check its destructive entries are only the ceremony's leftovers (in the walk:sys_comment.reactions,sys_sso_provider.created_by,sys_sso_provider.updated_by); any other is the app's own and decided separately (--allow-destructiveapplies every destructive change). Thenos migrate apply --allow-destructivein a terminal, answering its[y/N]prompt after reading the list; non-interactive it applies nothing, prints⚠ Confirmation required. Re-run with --yes to apply …and still exits0."},
{
"file": "content/docs/releases/v18/18-0.mdx",
"where": "Upgrade checklist step 2, bullet 'Then clear the drift …'",
"old": "Then clear the drift that remains. … then
os migrate apply --allow-destructive --yes, which dropped the three columns.","new": "Then clear the drift the ceremony leaves, and only that. … (on the
groupwalk's database also the indexidx_sys_sso_provider_organization_id); comment-reactions without--yesapplies nothing and asks for it; thenos migrate plan, ⛔ go on only if the destructive entries are the ceremony's leftovers, others are the app's own and decided separately; thenos migrate apply --allow-destructivein a terminal: prints the changes, asksApply 4 change(s) to DATABASE? [y/N], answeryonly for the list you checked (nprintedℹ Aborted — no changes made.); non-interactive applies nothing, prints⚠ Confirmation required. Re-run with --yes to apply, or use \"os migrate plan\" to preview., exits0: read the output, not the exit code. The walk's own--yesrun stays recorded as what the walk did, after that check."}
],
"yes_measurement": "npm 18.0.0, on a copy of the
groupwalk's post-ceremony database:os migrate plan→ 4 destructive (sys_comment.reactions,sys_sso_provider.created_by,sys_sso_provider.updated_by, indexidx_sys_sso_provider_organization_id).os migrate comment-reactions --applywithout--yes, non-TTY: exit 1,⚠ Apply mode writes sys_comment_reaction rows. Re-run with --yes to confirm, or run without --apply to preview.os migrate apply --allow-destructivewithout--yes, non-TTY (stdin /dev/null): exit 0,⚠ Confirmation required. Re-run with --yes to apply, or use \"os migrate plan\" to preview., nothing applied (plan still 4). TTY (pty driver): lists the changes, asksApply 4 change(s) to DATABASE? [y/N];n→ℹ Aborted — no changes made.exit 0, plan still 4;y→✓ Applied 4 change(s).exit 0, then plan✓ Physical schema is in sync with metadata.","sweep": {
"found_and_fixed": [
"content/docs/upgrading.mdx step 4 and content/docs/releases/v18/index.mdx:
npx skills remove --all(-y implied, removes every installed skill) with no preview → runnpx skills listfirst, use--allonly when the list shows nothing but these","content/docs/releases/v18/18-0.mdx step 1: named
npx skills remove … -y→npx skills listshows what is installed first (measured: the ten objectstack-* skills), the removal deletes only the names given"],
"reviewed_not_changed": [
"the ceremony's
os migrate organization-ownership --apply --plan-file … --backup-taken(ruled out of scope)","
os migrate security-catalog-overlays(bare run is the preview;--applyfollows it)","
os migrate comment-reactions --apply --yesin 18-0.mdx (already after its preview)","
os migrate meta --from 17 --write(source edits only, re-runs the chain and restores on mismatch; not destructive)","
npx skills experimental_sync --copy -y(copies the package's skills, skipsskills addones)","Upgrading's
os migrate apply --allow-destructive # … once you have read the plan(already afteros migrate plan)"]
},
"tests": "Docs-only diff: no package test or typecheck owed; no ablation (no tested behaviour changed). Measurements as in yes_measurement (env from the walk's env file, values not printed);
npx skills listin the walk app listed the tenobjectstack-*skills;skills remove --allreads as -y implied (CLI help). All cited at head 9da4c8d.","gates": "Re-derived at head 9da4c8d vs merge base 7169612: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack → 62 commands (identical to round 1's 62; 5 paths, +780/-22). Prerequisite build pnpm --workspace-concurrency=2 --filter '@objectstack/lint...' --filter '@objectstack/client-react...' build under os-verify-lock: 'VERDICT command-exit 0 · held the lock 281s'. All 62 ran, each exit 0 captured before any pipe. --ran: 'Run reconciliation — 62 derived, 62 run, 0 NOT-MEASURED, 0 UNRUN' (a DERIVED zero). git merge-tree --write-tree origin/main HEAD exit 0 before the push and again at report time (origin/main still 7169612). CI check-runs on 9da4c8d at report time: 46 runs — success 29, skipped 11, in_progress 6 (Test Core 1/6, 2/6; Build Docs; Type Check · consumer gates; Lint · repo & tooling gates, · docs & code guards). Success includes Test Core 3/6, 4/6, 5/6, 6/6, Type Check · source gates, Lint · CI, release & engine gates, Lint · ESLint, Lint · PM dispatch-gates, Type Check · workspace, Type Check · debt ledger, Check Documentation Links, Governed Surface Queue Guard, Dogfood Regression Gate and the claim/closing-keyword guards. in_progress is the honest value; not waited on.",
"mcp_calls": "0",
"api_writes": "2 this round — (1) one fleet-relay stroke: POST /repos/objectstack-ai/objectstack/dispatches (HTTP 204), relay run 39465235340 executing PATCH /repos//issues/24922 (PR body: + '## Round 3', Gates at 9da4c8d); read back 25091 bytes sent, 25091 stored, identical; draft still true, assignees os-warren, labels documentation, size/l, skip-changeset, no requested reviewers. (2) this os-dev-report via scripts/pm/post-stamped.mjs: POST /repos//issues/24905/comments. Plus git push of 9da4c8d (not REST). Reads otherwise (gh api GET). No ready flip, no review request.",
"deviations": [
"File surface held: the diff vs main is the same five files; this round touched three (18-0.mdx, v18/index.mdx, upgrading.mdx); packages/cli/CHANGELOG.md untouched",
"Upgrading step 8 names the three columns, as ruling 1 words the walk; the
groupwalk's fourth entry, indexidx_sys_sso_provider_organization_id, is named only in 18-0.mdx. A group-posture reader of Upgrading alone would set that index aside as 'decided separately' (the safe direction). Left as ruled so the PR body's Round 3 stays accurate; the seat can rule a one-clause addition","Sweep fixes beyond the two named sites (skills
--allon Upgrading and v18/index,skills listin 18-0 step 1) are ruling 4's 'name and fix'"],
"files_changed": [
"content/docs/releases/v18/18-0.mdx",
"content/docs/releases/v18/index.mdx",
"content/docs/upgrading.mdx",
"(unchanged this round: content/docs/releases/v18/meta.json, scripts/docs-audit/handwritten-docs.json)"
],
"open_questions": [],
"out_of_scope_findings": [
"carrier: 承接者:无 · noted, not filed — WITHDRAWN as a defect: the round-1 finding '18.0.0 CHANGELOGs omit 8 changesets whose code shipped in 18.0.0' is the #23818 ruling's annotate-shipped path working as ruled (epic seat note 6294471945); the 18.0.0 CHANGELOG already carries entries headed 'Shipped in 18.0.0-next.2, whose CHANGELOG missed this entry'",
"class: a · reach: walk 3 — os dev 18.0.0's in-place ceremony on a 17.x dev database reads the stale dist/objectstack.json (17.7.0's os start compiled it) and refuses the plan with the protocol-^17 refusal although objectstack.config.ts reads '^18'; nothing changes and a backup is kept, but the refusal prescribes 'objectstack migrate meta --from 17', which was already done — the remedy that works is os build. Documented here; the misleading prescription is the CLI's. Dedupe words: os dev ownership upgrade stale artifact, dist objectstack.json protocol 17, upgrade plan was refused",
"class: a · reach: public door os migrate plan on a 17.7.0-created database (round 1, unchanged) — the [schema-drift] lines and os migrate plan prescribe os migrate apply --allow-destructive for the organization_id columns with no word of the ceremony; the apply then exits 1 on sys_comment.reactions. Dedupe words: migrate plan ownership ceremony, schema-drift organization_id orphaned, allow-destructive before ceremony",
"class: a · reach: walk (round 1, unchanged) — npm install --save-dev "@objectstack/skills@…" exits 1 (edgesOut) in a pnpm-installed project; still the command in content/docs/upgrading.mdx step 4, content/docs/ai/skills.mdx:32, content/docs/ai/skills-reference.mdx:21, skills/README.md:11, skills/objectstack-upgrade/SKILL.md:129. Dedupe words: skills npm install pnpm, @objectstack/skills save-dev",
"carrier: 承接者:无 · noted, not filed — os serve --dev with no OS_DATABASE_URL booted ':memory:', not the project's .objectstack/data database, so the --dev refusal only appears when the URL names the dev database file (walk 3)",
"class: a · reach: public door
os migrate apply --allow-destructive(npm 18.0.0) in a non-interactive shell without--yes, on a database whose plan lists 4 destructive changes: prints⚠ Confirmation required. Re-run with --yes to apply, or use \"os migrate plan\" to preview., applies nothing (plan still 4) and exits 0 — a script reading the exit code reads success;os migrate comment-reactions --applywithout--yesin the same shell exits 1. Documented on both pages; the exit code is the CLI's. Dedupe words: migrate apply confirmation exit code, allow-destructive non-interactive exit 0, Confirmation required --yes"]
}
objectstack-fleet commentedon Oct 20, 2026
Landed ·
domain:devxseat 1 ·session_01FM29ZqLTrnPNXxijioZwMp· 2026-10-20T18:20Z223ae939bb(ACCEPT6297081922; not governed;Fixes #24905)origin/main, by contentcontent/docs/releases/v18/18-0.mdx,index.mdx,meta.json,content/docs/upgrading.mdxandscripts/docs-audit/handwritten-docs.jsonare byte-identical to the head9da4c8d328mainchecks at223ae939bbState change: PR #24922 closed this card through
Fixes #24905(completed).pm:dispatchedcomes off in this act.What is on
mainnow:/docs/releases/v18/18-0carries the 18.0.0 notes and a five-step upgrade checklist. Every line is tagged with how it was measured on npm 18.0.0, and the checklist was walked from 17.7.0 onsingle,groupandos devdatabases./docs/upgradingcarries onev18.0.0row. Its "Upgrading to 18.0" section (from docs: the 18.0.0 release text sends a v17 operator to the ownership ceremony, not to 17.x #24912) runs in the walk's order, and no destructive command in it runs without its preview.The done-when's real-upgrade walk was done on scratch fixtures. HotCRM (objectstack-ai/hotcrm#2202), the first downstream reader, was not walked from this session.
Filed from this card:
os migrate apply --allow-destructive, with no word of the ceremony #24925:os migrate planprescribes--allow-destructivebefore the ceremony;@objectstack/skillsinstall linenpm install --save-dev …exits 1 in a pnpm-installed project (edgesOut), and five sites still print it as the only command #24926: the skillsnpm install --save-devline fails in a pnpm project;packages/clihook-timeout-override-refusal.test.ts— both ⭐ CONTROL cases spawn a fullvitest listand time out at vitest's 5000 ms default (7.3 s, 7.9 s), which took PR #24912 out of the merge queue #24927: the flakyhook-timeout-override-refusalcontrols;os migrate apply --allow-destructivein a non-interactive shell without--yesapplies nothing, prints "Confirmation required", and exits 0 — a script reads success, whileos migrate comment-reactions --applywithout--yesexits 1 #24949: non-interactiveos migrate apply --allow-destructiveexits 0 having applied nothing.There is also a measured note
6296464418on #24833. The claim miss against #24904's earlier claim is recorded in the ACCEPT.Generated by Claude Code