Repository navigation
docs(releases): the 18.0.0 notes and upgrade checklist, walked from 17.7.0; Upgrading's table gains 18.0.0 and 17.5–17.7 - #24922
Conversation
…teps 1-2 (WIP) Claude-Session: https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp Co-authored-by: Claude <noreply@anthropic.com>
…7.7.0; Upgrading's table gains 18.0.0 and 17.5-17.7 Claude-Session: https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp Co-authored-by: Claude <noreply@anthropic.com>
…8-upgrade-checklist
Claude-Session: https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp Co-authored-by: Claude <noreply@anthropic.com>
… docs-audit roster lists the new page Claude-Session: https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs. What this run could not see
Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
|
Cross-lane note · epic PM #24912 (#24904, the 18.0.0 release-text fix) is in the merge queue. It edits two files this PR edits:
Once #24912 lands:
Already consistent, no change needed:
|
|
Cross-lane note · epic PM |
…ist; one v18.0.0 row, Upgrading to 18.0 in the walk's order, measured reconciliations Claude-Session: https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp Co-authored-by: Claude <noreply@anthropic.com>
… and drop --yes from it; preview skills before removing them Claude-Session: https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp Co-authored-by: Claude <noreply@anthropic.com>
Seat reviewACCEPT ·
This seat readies the PR and queues it with auto-merge. Generated by Claude Code |
Fixes #24905
Clause-②: no
The v18 line gets its curated 18.0.0 page,
content/docs/releases/v18/18-0.mdx, besideindex.mdxas the v17 line does it, with a## Upgrade checklistwalked from 17.7.0 on the published 18.0.0 packages.index.mdxdrops the "curated notes … are not written yet" sentence and links the page;meta.jsonlists it. Upgrading's per-release table gains a v18.0.0 row and the 17.5.0, 17.6.0 and 17.7.0 rows, and its stale v17.4.0 row now links the checklist17-4.mdxcarries. The first downstream reader is objectstack-ai/hotcrm#2202 (HotCRM's upgrade to 18.0.0); this PR does not claim to have walked it.The CHANGELOG filter
## 18.0.0sections of every package CHANGELOG at the version commit06cab4849a: 53 packages, 1,115 distinct entries (@objectstack/specalone: 341), 340 of them marked BREAKING or carrying a(narrowing)Clause-② arm. The 340 were read in body (their FROM → TO tables and one-line fixes); the other 775 were screened by title, and the 253 whose title says refuse / retire / remove / default / rename were read further.@objectstack/verify, or its deployment configuration) and the change could be measured on the 18.0.0 artifact. Left out: platform internals and tooling, the Console refresh entries, rules that bind only a walled operator, entries a later entry undoes, surfaces that shipped only in a prerelease (record:json), and two app-relevant behaviours that could not be measured here (1b40780approvals resume as the decider;f05649f/3f0b6f2hookreadonlyandonError: 'abort'rollback).packages/spec/CHANGELOG.md; it holds 132 of the 340 flagged entries, so the other packages' sections were read too (decided on the business-need axis: the CLI, runtime and plugin breaks an upgrader meets live there).Checklist steps, as measured on 18.0.0
@objectstack/*to 18.0.0 together, lockfilepnpm installmoved the seven ranges to 18.0.0, no peer warningengines.protocol: '^18',specVersion: '^18.0.0';migrate meta --from 17 --writerewrites the first'^17'validate warns and the boot exits 1✗ package … targets protocol ^17 … Run: objectstack migrate meta --from 17;--writeprintedmanifest.engines.protocol: '^17' → '^18'406 manual change(s)on a one-object appskills addskills, add@objectstack/skillswith the project's manager, syncSkipped … installed with skills add×10 +Nothing to sync.exit 0 before;Synced 10 skillsafter;npm install --save-devexit 1edgesOutin the pnpm projectos migrate security-catalog-overlaysbefore the first boot✓ No environment-wide permission-set or position row is stored over a package-held nameORGANIZATION_OWNERSHIP_MIGRATION_REQUIREDobjectstack startexit 1, port never bound; code read off@objectstack/runtimedist/index.jsos migrate apply --allow-destructiveis not the remedyos migrate plan28 destructive, apply exit 1✗ Refusing to drop sys_comment.reactions …--out plan.json, then--apply --plan-file plan.json --backup-takenunattributableRows: 0; apply attributed 32 rows, rewrote 2 grants, deleted 49 mirrors, dropped 14 columns, NOT NULL on 32,✓ The ceremony is completeplatform_admin/admin_full_access, 3 notes read, a 4th written, the 17.7.0 API key answers 200comment-reactionspreview +--apply --yes, thenmigrate apply --allow-destructive --yesConverted 1 reaction(s), 3 columns dropped, next boot 0 drift lines, reaction reads back{{ }}, bound roots,$names, node contracts, aliases, edges, retryos validate(ruleexpression-invalid, exit 1) anddefineStack(STACK_SCHEMA_INVALID422) on the installed 18.0.0 spec, each position the tag namesdataSourcebinding, retired keys, layout, list views,editInline, url schemesPUT /api/v1/meta/page/NAME→422 INVALID_METADATAfor an undeclared prop andkind: 'jsx'externalSharingModel,unique: true,controlled_by_parent, stagekind, one-hop formulas, optionvisibleWhen, metadata-table lookups, duplicates,defineSeeddefineStack,os validate,defineSeed)permissionSets, retired permission-set keys,packageId,'.FIELD', one name per holder, sharing rules, manifestpermissionsNAMESPACE_CONFLICTread off@objectstack/objectqldist/core.js; declared-rule text read off@objectstack/plugin-sharingmongo, template keys and registry, declared webhooks, timestamped signatureos servewithOS_DATABASE_DRIVER=mongoexit 1); tarball:plugin-email,DeclaredWebhookNameConflictError(plugin-webhooks),signature-body-only(trigger-api)allowEnvironmentOverlay, hand-built kernels,os meta resync, verifycli/dist/utils/extract-hook-body.js,plugin-security(carries no principal,AUTHZ_STORE_IDENTITY_OBJECTS),service-i18nd.ts,verify; exports probed absent; walk:os meta resyncexit 2command meta:resync not foundexpires_at+90 d, 2-year key400 API_KEY_EXPIRY_TOO_LONG, 17.x key stamped +1 y; noaccess-control-allow-originfor a foreign origin (GET and preflight);401 UNAUTHENTICATEDon/api/v1/openapi.jsonand/api/v1/i18n/locales;400 INVALID_REQUESTfortext/plain;400 VALIDATION_FAILEDfornull,[1,2]andexpectedVersion: 3; 404 on the four catalog objects; grants carrypermission_set, nopermission_set_id;scope: 'public'→400 INVALID_REQUEST;403codes,PAYLOAD_TOO_LARGE, the submit and import doors read off the tarballsa7199ef974: 20 pending changesets, sixminor⇒ 18.1.0; 8 shipped in 18.0.0 unlisted; 12 not in it; 7a-2 an open PR — re-read at71696121a6in Merge with #24912: 26 / 10 minor / 8 / 18, 7a-2 merged after the cutgit merge-base --is-ancestorof each changeset's adding commit against06cab4849ain a full clone (--is-shallow-repositoryfalse): 8 exit 0, 12 exit 1, the exit-0 rows of the same run being the control leg; tarball:deploymentWideinplugin-sharing,codeInviteRoleNotFoundinplugin-auth, adopt-orphans guard absent fromruntime; walk:os servewith no auth secret exit 1 with the quoted refusalgroup/isolatedboot on a fresh DB with their prerequisitesOS_PLATFORM_OWNER_EMAIL, membership policy), then✓ Server is readywithTenancy: groupandTenancy: isolatedlatest18.0.0,next18.0.0-next.5 (older),rc17.0.0-rc.6; never@nextnpm view … dist-tagson spec, cli, runtime, core, objectql, skills, organizations, create-objectstack;npm view … time/versions(nonext.4)The walk
create-objectstack@17.7.0blank scaffold (v17app, pnpm 10.28, Node 22.22), its ten skills installed byskills add, booted once on 17.7.0 withobjectstack startinto.objectstack/data/objectstack.db. Walk 1 seeded an admin and three notes; walk 2, on a fresh scaffold that followed the written steps 1 and 2 verbatim, also seeded an API key and a comment carrying a stored emoji reaction. Everything ran under the session scratchpad, never in the repo.OS_DATABASE_DRIVER=mongo, a production boot with no auth secret, and the save door.npm install --save-devexits 1 (npm error Cannot read properties of null (reading 'edgesOut')) in the pnpm projectcreate-objectstackmakes, so the page (andindex.mdx) adds the package with the project's manager.specVersionis a hand edit:--writerewritesengines.protocolonly, and nothing on the boot path readsspecVersion.os migrate apply --allow-destructive, which the drift lines recommend and which refuses.comment-reactionsthenapply --allow-destructiveclears them.The PM's hypotheses, measured
walledPostureRefusalis in@objectstack/cli@18.0.0-next.5(dist/commands/serve.js) and absent from@objectstack/cli@18.0.0; history: added byae6bd1a696(feat(cli)!: 18.0 guards — os migrate organization-ownership refuses, and os serve refuses a walled posture at boot #24480), removed byfc34d000fc(feat(objectql,cli,plugin-webhooks)!: 18.x step 4: the walled lift (8b walled half, the os serve lift, the declared-webhook name guard, declared webhooks deployment-wide) #24667).os serve18.0.0 bootsgroupandisolatedonce the organizations runtime, the owner email and a membership policy are present; point 4 states that posture with the measured refusals.com.objectstack.organization-ownership-boot-guardplugin; the error code isORGANIZATION_OWNERSHIP_MIGRATION_REQUIRED(on the error object, not in the printed line), and the remedy namesos migrate organization-ownership --out PLANthen--apply --plan-file PLAN --backup-taken.17-4.mdxcarries## Upgrade checklist(line 606) and### 17.4.0; 17.5–17.7 each carry one (lines 1671, 1524, 1259) and had no row.The card's own premise, measured (at
a7199ef974; 7a-2 has since merged after the cut — see the merge section). "The 18.x steps that landed after the cut (for example 7a-2, PR #24872) ship in 18.1.0" does not hold as written: #24872 is an open PR, not onmain; and 7a-3 (#24828) and 7b-3 (#24845) landed before the version commit, so their code is in the 18.0.0 packages while their changesets are still pending. Step 4 says so.Choices settled here
Deviations, named
scripts/docs-audit/handwritten-docs.json, one line.pnpm check:docs-audit-scopereds when a hand-written page exists that the roster does not list; the line was written bynode scripts/docs-audit/check-audit-scope.mjs --write(+1 added, -0 removed). The dispatch both bounds the surface tocontent/docs/releases/v18/**andcontent/docs/upgrading.mdxand requires the docs gates to stay green; the ruled page shape needs the roster line, so this PR keeps the gate green and names the breach here rather than choosing silently.Acceptance notes
6294471945: the release(next): 18.0.0-next.2 shipped 11 changesets with no CHANGELOG entry (the version PR merged behind main; #21361's class, in pre mode) #23818 ruling'sannotate-shippedstep carries such entries into the next CHANGELOG with a "Shipped in …" lead line — the 18.0.0 CHANGELOG already holds entries headed**Shipped in 18.0.0-next.2**, whose CHANGELOG missed this entry— so this is the release lane working as ruled, not a defect.) Ata7199ef974,.changeset/24583-7a3-…,24583-7b3-…,24750-…,24751-…,24767-…,24772-…,24773-…and24785-…belong to commits that are ancestors of the version commit06cab4849a, and the 18.0.0 tarballs carry their code (deploymentWide, the no-auth-secret refusal measured withos serve,codeInviteRoleNotFound); their entries will first appear in 18.1.0's CHANGELOG. Reported to the PM for filing.[schema-drift]lines andos migrate planprescribeos migrate apply --allow-destructivefor theorganization_idcolumns without naming the ceremony (28 destructive changes on the walk's database), and that apply then refuses onsys_comment.reactions. Reported to the PM for filing.npm install --save-dev "@objectstack/skills@…"fails in a pnpm-installed project and is still the command incontent/docs/upgrading.mdxstep 4,content/docs/ai/skills.mdx,content/docs/ai/skills-reference.mdx,skills/README.mdandskills/objectstack-upgrade/SKILL.md. Reported to the PM for filing.18.0.0-next.4was never published, while every CHANGELOG carries a## 18.0.0-next.4section. Observation only.os migrate security-catalog-overlays's preview printed "Raw execute() called … FORWARDED, not refused — if it wrote, this boot wrote"; the database file's mtime did not move. Observation only.Merge with #24912
#24912 (card #24904,
71696121a6) editedcontent/docs/upgrading.mdxandcontent/docs/releases/v18/index.mdxand amendedpackages/cli/CHANGELOG.mdin place.git merge origin/main(no rebase, no force) stopped on one conflict: both sides added av18.0.0row to Upgrading's "Per-release specifics" table, and #24912's side still carried the stalev17.4.0 — ⛔ checklist not writtenrow. Resolution: onev18.0.0row linking/docs/releases/v18/18-0#upgrade-checklist,#upgrading-to-180and/docs/releases/v18, and this PR's 17.4–17.7 rows.index.mdxmerged clean;packages/cli/CHANGELOG.mdis #24912's and untouched here. Merge commitb6917f0b72;git merge-tree --write-tree origin/main HEADexit 0 before the push and again after it (main71696121a6).New measurements for the reconciliation (all on npm 18.0.0, under the session scratchpad):
create-objectstack@17.7.0app with@objectstack/organizations@17.7.0, booted underOS_TENANCY_POSTURE=group, an owner and two records, moved to 18.0.0 (the exact"17.7.0"organizations pin moved by hand):os migrate security-catalog-overlaysexit 0; refused boot exit 1; planposture group, 81 tables,unattributableRows: 0; apply✓ The ceremony is complete; servedTenancy: group, both records in their organization.os devdatabase moved to 18.0.0.OS_DATABASE_URL=file:… os serve --devexit 1 namingRun 'os migrate organization-ownership --dev --out PLAN' ….os devwith the artifact 17.7.0'sos starthad compiled still indist/:✗ The upgrade plan was refused, and nothing was changed.(the plan refused protocol^17althoughobjectstack.config.tsread'^18'). Afteros build:✓ Upgraded the development database to the v18 organization ownershipand✓ server started on the upgraded database.os startwith no secret: a fresh--home, noAUTH_SECRET/OS_AUTH_SECRET: it wroteHOME/auth-secret(mode0600), served, sign-up200.@objectstack/cli@18.0.0tarball'sCHANGELOG.mdline 162 still readsae6bd1a: feat(cli)!: 18.0 supports fresh 'single' installs only — …; the repository'spackages/cli/CHANGELOG.mdat71696121a6line 162 readsae6bd1a: feat(cli)!: the 18.0 pre-release refusals of … both lifted in 18.0.0, and itsfc34d00headline adds "and on databases the ownership ceremony upgraded".upgrading.mdxtablev18.0.0rows + #24912's stalev17.4.0row → onev18.0.0row (checklist · Upgrading to 18.0 · v18) + this PR's 17.4–17.7 rowsupgrading.mdx"Upgrading to 18.0"os migrate security-catalog-overlaysfirst, the drift tail (comment-reactions --apply --yes, thenapply --allow-destructive --yes) last, and one link to/docs/releases/v18/18-0#2-upgrade-the-databasefor each step's output; the rest of #24912's prose unchangedConverted 1 reaction(s),Applied 3 change(s), next boot 0 drift lines)upgrading.mdx--devparagraphos devruns the whole sequence itself" → + "Runos buildbefore it: whiledist/objectstack.jsonwas still the artifact 17.x compiled,os dev's in-place upgrade refused its plan and changed nothing."upgrading.mdxwalled bulletOS_AUTH_MEMBERSHIP_POLICY=invite-only(orauto), with its refusal✖ FATAL: tenancy posture 'group' is walled, but this deployment never declared a membership policy.v18/index.mdx--devbulletos buildcaveatv18/index.mdxwalled bulletv18/index.mdx"Upgrading a database to 18.0.0"## Per-release noteskept; nothing of #24912's removed18-0.mdx"How to read the 18.0.0 CHANGELOG"ae6bd1acaution → says it reads the tarball's copy (whatnode_modulesholds), names #24912 and quotes the amended repository text18-0.mdxstep 2 intro/docs/upgrading#upgrading-to-18018-0.mdxstep 2,os devos serve --devrefusal,os dev's in-place upgrade, and theos build-first caveat18-0.mdxstep 4, auth secretos serveboot …" + "os startis not refused: it wroteHOME_DIR/auth-secret(mode0600) … and served sign-up" — now agrees with #24912os startwith no secret18-0.mdxCallout and step 4, walledgroup(anisolateddatabase not walked) — now agrees with #24912's "on a database the ceremony upgraded" forgroup18-0.mdxstep 4, pending changesetsa7199ef974(20, sixminor; "7a-2 is an open PR") → read at71696121a6: 26, tenminor; 8 shipped in 18.0.0 unlisted; 18 not in it, sixminor, 7a-2 (#24872, merged 2026-10-20 15:26 UTC, after the cut) first among themgit merge-base --is-ancestorper changeset against06cab4849a;gh api pulls/24872(merged: true)Point 13 is not one of #24912's: it is named because the merge brought
.changeset/24583-7a2-…into this branch's tree, which made "7a-2 is not onmain" false.Already in agreement, re-measured: #24912's "start 18.0 against the database once (
os serve/os start)" (the walks usedos start); "the refusalos serve --devprints names the command with--dev" (walk 3).Round 3
Two sites told a reader to run a destructive apply without reading its plan first;
os migrate apply --allow-destructiveapplies every destructive change in the plan, and--yesskipped its confirmation.groupwalk's post-ceremony database):os migrate planlisted 4 destructive changes (sys_comment.reactions,sys_sso_provider.created_by/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 ….os migrate apply --allow-destructivewithout--yes, non-TTY (stdin/dev/null): applied nothing, printed⚠ Confirmation required. Re-run with --yes to apply, or use "os migrate plan" to preview., exit 0 (the plan still listed 4). On a TTY (a pty): it listed the changes and askedApply 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✓ Physical schema is in sync with metadata.content/docs/upgrading.mdx, "Upgrading to 18.0" step 8: "os migrate comment-reactions --apply --yes, thenos migrate apply --allow-destructive --yes" → previewos migrate comment-reactions, then--apply --yes; runos migrate planand check its destructive entries are only the ceremony's leftovers (in the walk: the three columns); any other entry is the app's own and decided separately; thenos migrate apply --allow-destructivein a terminal, answering its[y/N]prompt after reading the list; in a non-interactive shell it applies nothing and still exits0.content/docs/releases/v18/18-0.mdx, step 2 "Then clear the drift …": "thenos migrate apply --allow-destructive --yes, which dropped the three columns" → the same plan check, the[y/N]prompt and the non-TTY behaviour, each quoted from the measurement; the walk's own--yesrun stays recorded as a fact of the walk; thegroupwalk's extra index entry is named.npx skills remove --all(-yimplied, removes every installed skill) inupgrading.mdxstep 4 andv18/index.mdx→ "runnpx skills listfirst", and18-0.mdxstep 1 namesnpx skills listbefore the namedskills remove … -y(measured: it listed the tenobjectstack-*skills with their source). Reviewed, not changed: the ceremony's--apply --plan-file … --backup-taken(ruled out of scope);os migrate security-catalog-overlays(its bare run is the preview,--applyfollows it);os migrate comment-reactions --apply --yesin18-0.mdx(already after its preview);os migrate meta --from 17 --write(writes only the source edits it can prove, re-runs the chain and restores on a mismatch; not destructive);skills experimental_sync --copy -y(copies the package's skills into the agent directory, skippingskills addones); Upgrading'sos migrate apply --allow-destructive # … once you have read the plan(already afteros migrate plan).Gates
At head
9da4c8d328(merge base71696121a6), the re-derived list (62 commands, the same 62 as rounds 1 and 2) ran locally, every one exit 0, afterpnpm --filter '@objectstack/lint...' --filter '@objectstack/client-react...' buildunder the verify lock (VERDICT command-exit 0);--ranwith recorded exit codes:62 derived, 62 run, 0 NOT-MEASURED, 0 UNRUN.git merge-tree --write-tree origin/main HEADexit 0 just before the push. Earlier heads5019f5152fandb6917f0b72were green on the same 62. CI's own check-runs are the record for everything outside that list.Changeset: none. Measured: all 73 published
package.jsonmanifests declarefiles[](control: all 73 namedist), none namescontent/, a docs path orscripts/, and the root package is private, soskip-changeset.Generated by Claude Code