Repository navigation
docs(releases): 17.2.0 and 17.3.0 detail sections, and repair the upgrade entry page that reads a breaking upgrade as a tag swap - #15333
Conversation
…rade entry page (#15322) Two releases shipped with no upgrade guidance, and the customer's entry page reads a breaking upgrade as a tag swap. content/docs/upgrading.mdx - The per-major checklist table listed v17 once, pointing at 17.0.0. A deployment on 17.1.0 got no pointer to either release it has to cross. The section becomes "Per-release specifics" and carries a row per v17 release. - The page's framing ("move the tag, restart") plus the metadata-compatibility Callout read together as "a minor is a no-op". A second Callout scopes the first: the major boundary promises metadata compatibility and nothing else. The two-upgrades-two-clocks argument is untouched. content/docs/releases/v17.mdx - New "What's new in 17.2.0" and "What's new in 17.3.0" detail sections, in the shape 17.0.0/17.1.0 establish. Content is reused from the packages' own CHANGELOG entries rather than paraphrased; every entry is cited by changeset hash. - Release-status blockquote now says 17.3.0 is current, and names what makes 17.3.0 a minor by number only. - "Upgrade checklist" and "References" are promoted from h3 to h2 so they stay page-level sections after two more release sections are appended. No published prose in the 17.0.0 / 17.1.0 sections is changed; the #upgrade-checklist, #1700 and #1710 anchors are preserved. The consolidated 17.1.0 -> 17.3.0 upgrade checklist is deliberately NOT in this commit: it is blocked on hotcrm#1576's documentation-first upgrade log, and a checklist step nobody has run is worse than a missing one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UHvF5hyiZjnCyExFnfQB8m
第一趟复核:PASS,两个 open question 已裁 —— 其中一个不按你的推荐
已核
Q1 —— 裁 B(修正版),不按你推荐的 A你的 A 是「压住 #15322 等 hotcrm#1576」。我裁 B:第一趟 CI 绿了就落地,理由是你自己在 B 那条里写出来的:
维护者提出这件事时的原话是:「我们最终客户不可能到仓库里来查源码,然后再决定他们的项目怎么升级。」 现在站上那一页正在把一次带破坏性变更的升级读成换 tag —— 这是活着的、面向客户的缺陷,而 hotcrm#1576 连日志都还没开始产出(分支停在基线提交)。把一个活缺陷的修复压在另一个仓库的在飞测量后面,这笔交易不划算。
修正的地方:⛔ 不另开卡。#15322 保持开着,收窄成第二趟(合并清单)那张卡, Q2 —— 裁 A,确认
|
…ured upgrade Pass 2 of #15322. Pass 1 (#15333) wrote the 17.2.0 / 17.3.0 detail sections and repaired the upgrade entry page's per-release table; this pass writes the two Upgrade checklists that were left open, and answers the structural defects the upgrade drill found in `upgrading.mdx`. The spine is a real upgrade of an application repository across one minor, 17.2.0 -> 17.3.0, driven as a customer using only published artifacts: the docs site, the CHANGELOG.md inside each npm tarball, and the CLI's own output. Its headline reading was that the documentation covered zero of the eleven breakages that run hit. content/docs/releases/v17.mdx - `## Upgrade checklist` gains `### 17.2.0` and `### 17.3.0`; pass 1's interim paragraph is removed. - Provenance is marked per line. The drill covered ONE hop. Nobody has walked 17.1.0 -> 17.3.0, so every 17.2.0 line is marked "not exercised" and kept in its own list rather than blended with measured steps. - Two operational hard requirements are written in: deduplicating autonumber columns before the new unique indexes can build on an existing database, and `OS_PLATFORM_OWNER_EMAIL` on walled deployments. - #15337 (the dev-admin lockout) is written as a known issue with no workaround, not as a step. content/docs/upgrading.mdx - New "Moving the dependency pins": the npm-consumer upgrade path the page did not have at all, which is the shape create-objectstack scaffolds. - New "A runtime move can still force metadata edits": the page's "move the tag, restart" framing, narrowed by measurement rather than by assertion. - "Nothing to migrate" is qualified next to the command it comes from. - The per-package CHANGELOG.md files are authorised for every upgrader, not only for v10/v11, with the reason the release pages cannot replace them. - The v17.3.0 / v17.2.0 rows repoint at the new checklists. Transcript drift: four pages printed `author-time rules (41)`; the registry resolves 42 for both `validate` and `build`. Number only. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UHvF5hyiZjnCyExFnfQB8m
…m a measured upgrade (objectstack-ai#15369) * docs(releases): the 17.2.0 and 17.3.0 upgrade checklists, from a measured upgrade Pass 2 of objectstack-ai#15322. Pass 1 (objectstack-ai#15333) wrote the 17.2.0 / 17.3.0 detail sections and repaired the upgrade entry page's per-release table; this pass writes the two Upgrade checklists that were left open, and answers the structural defects the upgrade drill found in `upgrading.mdx`. The spine is a real upgrade of an application repository across one minor, 17.2.0 -> 17.3.0, driven as a customer using only published artifacts: the docs site, the CHANGELOG.md inside each npm tarball, and the CLI's own output. Its headline reading was that the documentation covered zero of the eleven breakages that run hit. content/docs/releases/v17.mdx - `## Upgrade checklist` gains `### 17.2.0` and `### 17.3.0`; pass 1's interim paragraph is removed. - Provenance is marked per line. The drill covered ONE hop. Nobody has walked 17.1.0 -> 17.3.0, so every 17.2.0 line is marked "not exercised" and kept in its own list rather than blended with measured steps. - Two operational hard requirements are written in: deduplicating autonumber columns before the new unique indexes can build on an existing database, and `OS_PLATFORM_OWNER_EMAIL` on walled deployments. - objectstack-ai#15337 (the dev-admin lockout) is written as a known issue with no workaround, not as a step. content/docs/upgrading.mdx - New "Moving the dependency pins": the npm-consumer upgrade path the page did not have at all, which is the shape create-objectstack scaffolds. - New "A runtime move can still force metadata edits": the page's "move the tag, restart" framing, narrowed by measurement rather than by assertion. - "Nothing to migrate" is qualified next to the command it comes from. - The per-package CHANGELOG.md files are authorised for every upgrader, not only for v10/v11, with the reason the release pages cannot replace them. - The v17.3.0 / v17.2.0 rows repoint at the new checklists. Transcript drift: four pages printed `author-time rules (41)`; the registry resolves 42 for both `validate` and `build`. Number only. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UHvF5hyiZjnCyExFnfQB8m * docs(releases): retract the 17.3.0 dev-admin known issue — it was misattributed The Callout claimed 17.3.0 shipped an unrecoverable sign-in lockout. That is false, and it was a false alarm on a customer-facing page. Root cause of the misattribution: the server that produced the reading was started as `objectstack serve --ui` under NODE_ENV=production, not `objectstack dev`. The dev-admin seed is by design not armed in that shape -- `isDevAdminSeedArmed()` returns false whenever NODE_ENV is not 'development' -- so the account was never created and the 401 was correct behaviour. An ablation holding tree, published install and database path fixed and varying only the start mode reproduced the 401 on the serve/production leg and answered 200 on the dev leg; three further independent shapes all answered 200. The two readings that made it look like a platform defect (a transplanted hash having no effect, an authenticating user missing from the database) were measurement artefacts of `rm -rf .objectstack/data` run against a live server, which left the process holding deleted file descriptors. Two sites removed, both introduced by this branch: - the "Known issue" Callout at the head of the 17.3.0 checklist, in full; - the trailing half of the audience-posture bullet, which existed only to explain why the lockout was total and carried a now-dangling back-reference. The bullet keeps its changelog-sourced first half and is marked "not exercised"; the "measured only as a non-change" claim came from the same retracted run and goes with it. Nothing is added in their place. Whether the `os dev` / `os serve` difference in dev-admin seeding deserves a sentence anywhere is referred to the maintainer; it is not a 17.3.0 change and would not belong in an upgrade checklist. check:doc-anchors still reports 305 internal fragment links across 410 files, unchanged -- the deleted block's only link was an absolute URL, not an anchor. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UHvF5hyiZjnCyExFnfQB8m --------- Co-authored-by: Claude <noreply@anthropic.com>
Part of #15322
Part of, not a closing keyword — and the PM has ruled it necessary rather than merely cautious. This PR is pass 1 of the card's two passes, so merging it must NOT close the card: #15322 stays open and narrows to pass 2 (the consolidated 17.1.0 → 17.3.0 Upgrade checklist), keeping itsBlocked-by: hotcrm#1576. ⛔ No new card is opened for pass 2, and no closing keyword appears anywhere in this body — including in prose about one, because GitHub's parser matches the keyword and the number and ignores the surrounding sentence, which is precisely the lossscripts/check-partof-closing-keyword.mjsexists to block.Two releases shipped with no upgrade guidance, and the page a customer starts from currently reads a breaking upgrade as a tag swap. This is pass 1 of two: everything that does not depend on hotcrm#1576. The consolidated 17.1.0 → 17.3.0 Upgrade checklist is deliberately not here — see "What is NOT in this PR" below.
PM ruling on why pass 1 lands ahead of that checklist: the misleading page is a live, customer-facing defect, and holding its repair behind an in-flight measurement in another repository is the worse trade. The maintainer's own framing of the problem is 「我们最终客户不可能到仓库里来查源码」. Landing pass 1 removes a misleading sentence rather than leaving a hole, because
## Upgrade checkliststates plainly that 17.2.0 and 17.3.0 have no consolidated checklist yet and points at the per-change Migration notes.Docs-only, two files, no code, no
content/docs/drive-bys.skip-changesetis needed: the diff publishes nothing from any package.1.
content/docs/upgrading.mdx— the entry page was misleading, not just incompleteThe measured defect. The per-major checklist table at
:197listed v17 exactly once, pointing at/docs/releases/v17#upgrade-checklist(17.0.0). 17.1 / 17.2 / 17.3 did not exist in it. A deployment pinned at 17.1.0 —objectstack-ai/hotcrmis exactly that — starts here and gets no pointer to either release it has to cross.Worse than the omission: the page's framing. The runtime half's upgrade action is "move the image tag, restart", and the Callout under it says a major move keeps working with metadata authored against the previous major. Read together, 17.1 → 17.3 reads as a tag swap (and
:41's example already readsobjectstack:17.3.0). It is not: those two releases carry an alias-freeclient.projects.*rename, drivers that start enforcing declaredunique/indexes[], a self-registration default flipping toinvite_only, a permission-store outage that starts failing loudly, andsys_record_sharebecoming tenant-scoped.What changed:
Callout type="warn"immediately after the existing one, scoping it: the major boundary promises metadata compatibility and nothing else, so read the checklist for every release you cross, not every major. ⛔ The page's main argument — two upgrades on two clocks — is untouched; so is theos migrate metasection and every other claim on the page.## Per-major specifics→## Per-release specifics, with the lead rewritten to say why a minor still needs reading (os migrate metahas nothing to replay for a minor, so the release page is the only channel its tightenings have), and one row per v17 release. The v16-and-earlier rows are unchanged.#per-major-specifics(greppedcontent/**), andcheck:doc-anchorsis green on the rename.2.
content/docs/releases/v17.mdx— 17.2.0 and 17.3.0 detail sectionsNew
## Highlights — 17.3.0,## What's new in 17.2.0and## What's new in 17.3.0, in the shape 17.0.0 / 17.1.0 already establish. The release-status blockquote now says 17.3.0 is current and names what makes these minors minors by number only.Content provenance. Every entry is reused from the packages' own
CHANGELOG.md— the release process already compiled it, and it was written by the change's author. Entries carrying a Migration table (87042b5's method/response-key tables,914c413's metric FROM → TO,266436a's status matrix,db16b94's per-method rewrite table,9a1ed7a's route/capability table) are reused, not paraphrased. Every entry is cited by changeset short hash so a reader can find the original.⛔ The published 17.0.0 and 17.1.0 sections are not rewritten or tidied. Their prose is byte-identical.
The one structural edit to published headings, declared
### Upgrade checklist→## Upgrade checklist, its#### 17.0.0/#### 17.1.0→### 17.0.0/### 17.1.0, and### References→## References. Four lines, no prose touched.Why: both sections span all releases but sat inside
## What's new in 17.1.0. Appending two more release sections without this would have filed the published 17.0.0 and 17.1.0 checklists under "What's new in 17.3.0" — a worse corruption of the record than the promotion. Anchors are preserved —github-sluggerkeys on heading text, not level — so#upgrade-checklist,#1700and#1710all still resolve;check:doc-anchorsverifies it across 302 fragment links. The promoted shape is also the onecheck-release-section-coverage.mjsnames as correct: "the shape both current pages use is# What's new in 17.3.0plus### 17.3.0in the upgrade checklist".How the BREAKING entries were triaged
The rule, stated on the page itself: an entry is written up when the change can be reached from something an application ships or operates — its metadata, its data, its own code calling the SDK / REST / CLI, its deployment config, or a plugin it authors. Everything else is left to the per-package changelogs.
Measured against the changelogs (distinct entries across all 69 package
CHANGELOG.mdfiles; an entry landing in several packages counted once). Two units are counted below and they are not interchangeable — the reconciliation is stated under the table, because 94 + 6 = 100 while the coverage check reads 98:Why 98 and not 100, and why 98 and not 94. The triage split (94 in / 6 out) counts entries — one changelog bullet. The coverage check counts short hashes, and differs from it for two independent reasons:
93940d4is "IDataDriver.update()declares its not-found arm" inspecand "update()andupsert()publish their honest types" indriver-memory;be21955is the nine deadcontributesmembers in one text andcontributes.kinds[].globsin another. Both texts of both are written up.So: 94 of 100 BREAKING entries are written up with migration prose; 6 are named only as exclusions; and 98 of 98 distinct hashes appear somewhere in the new sections, which is the check that nothing went unmentioned. The four Console pin refreshes are inside the 94 — written up once under their own heading rather than enumerated as four breaking entries.
Those four Console pin refreshes are summarized rather than enumerated because their per-commit content is objectui's changelog, and four pin bodies inline would be transcription. The host-facing half of that range (retired
@object-ui/typesexports, theoptions.actor/X-Actorremoval) is called out explicitly.The six left out of 17.3.0 are named on the page rather than silently dropped, and none is reachable from an application: the six branded identifier schemas and
EventNameSchema(45b9051),MetadataChangedEventPayloadSchema— a payload nothing ever emitted or consumed (50d6c92),RestApiEndpoint.handlerStatuswith the Route Coverage Report shapes (53d3689), the orphanCLICommandContributionSchemaexport (7a25e7d),SendTemplateInput.org(8619f95), andFilesystemLoader.list()reporting only the names its siblings can resolve (4b4d5a3).Ordering inside the section is by blast radius, not by package: the three entries that change behaviour on a running deployment with nothing to parse-fail on lead — the audience-posture default,
sys_record_sharetenant-scoping, and the newly-enforceddriver-memoryuniqueness — followed by the alias-free SDK rename, then author-time refusals, then smaller changes.What is NOT in this PR, and why
The consolidated 17.1.0 → 17.3.0 Upgrade checklist, which #15322 narrows to after this merges. hotcrm#1576 is running a real 17.1.0 app through the upgrade as a customer, using only published documentation, and its deliverable is the log of where the docs stop carrying you. That log is the checklist's spine. At the time this PR opened, hotcrm#1576 is open with a claim comment and a method-correction comment and no log delivered — its branch
claude/issue-1576-objectstack-17.3.0is still at its base commit.⛔ Writing the checklist now would mean inventing steps, and a step nobody has run is worse than a missing step: it sends upgraders to do work whose effect nobody has verified. So
## Upgrade checklistgains a lead paragraph saying plainly that 17.2.0 and 17.3.0 have no consolidated checklist yet and pointing at their per-change Migration notes, which is also whereupgrading.mdxpoints for those two releases. Pass 2 adds### 17.2.0and### 17.3.0once that log lands.content/docs/releases/index.mdx. Its v17 entry still reads "current series: 17.2.0, released 2026-08-23". Real, gated, and out of this PR's declared scope — filed as #15332 with the measurement, including that the arm which catches it (--strict) runs only in the standing patrol, not inlint.yml.Verification
All 42 runnable gate commands derived at the final commit
c13400b5fbynode scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands(36 families; the 3 value-bearing CI-only invocations are excluded by the script itself). Exit codes captured before any pipe, one log per gate.41 of 42 green. The single non-zero is
node scripts/check-release-section-coverage.mjs --strict, and it is a pre-existing finding in a file this PR does not touch — measured on both trees:eb40a7210(dedicated compare worktree)v17.mdxhas no 17.3 section;index.mdxnames a superseded current seriesc13400b5findex.mdxonlySo this PR clears one of the two strict findings and inherits the other, which is #15332. The PR-blocking
lint.ymlform runs the gate without--strictand is green here.Citation coverage was measured, not asserted: every 7-hex hash in the three new sections was extracted and diffed against the changelog-derived BREAKING set — 19/19 distinct 17.2.0 hashes and 98/98 distinct 17.3.0 hashes appear in the new prose. That 98 is the hash unit; see the reconciliation under the triage table.
Also green and worth naming:
check:doc-anchors(302 fragment links, including the six new ones),check:release-notes,check:release-page-status,check-release-section-coverage.mjs(non-strict),check:docs-image-tag,check:docs-single-h1,check:doc-authoring,check:nul-bytes,pnpm --filter @objectstack/spec run check:docsandcheck:skill-examples(257 prose examples type-check).PREREQUISITE NOT MET/ exit 3 rather than a finding, because@objectstack/spec,@objectstack/lint,@objectstack/formulaand@objectstack/client-reactwere unbuilt in a fresh worktree. Those runs measured nothing and are not reported as passes: the packages were built and all four re-run green.⛔ No auto-merge armed, and it will not be armed from here — the PM arms it after CI converges.
🤖 Generated with Claude Code
https://claude.ai/code/session_01UHvF5hyiZjnCyExFnfQB8m