Skip to content

docs: new content/docs/upgrading.mdx in the Build group — state both upgrade halves and give the per-major checklists a door #8909

Closed

Description

@os-zhuang

Card 02 of the deployment restructure. The highest-value card in the set — the only one that fixes a defect users hit today, and independent of every other card in the group.

Maintainer rulings, 2026-08-15: 「元数据应用需要升级,平台也需要升级」; on placement, 「放进 Build 组(应用开发者本来就在那)」; and on shape, a single page, not a directory (see Shape below).

The defect

The two upgrade lifecycles are never distinguished anywhere in the docs. They run on separate clocks:

Platform runtime Metadata app
Ships as Docker image compiled artifact (dist/objectstack.json)
Versioned by our release train (17.0.0) your own catalog
Upgrade cadence ours yours
Upgrade action move the image tag os migrate meta + republish

The hardest evidence is content/docs/deployment/cli.mdx:821, which calls os migrate meta --from 16 "the metadata half of the upgrade". The docs already know there are two halves. The other half is written down nowhere, and no page places them side by side.

The second defect this closes

The v17 upgrade checklist — 66 actionable bullets, correctly written for metadata app authors (allowExport, sharedWith.type: 'group' → 'team', RLS priority, agent.tools[] → skills) — sits at line 3270 of a 3691-line page, 88% down. Nothing links to it: the first 105 lines of v17.mdx never say "upgrade" except about semver caret ranges, and content/docs/releases/index.mdx offers no entry point. releases also sits in the Platform sidebar group beside kernel and protocol — the wrong neighborhood for the audience it is written for. That mismatch is why this page goes in Build.

Cross-version gap: each release page's checklist has only a ### <major>.0.0 subsection, so upgrading v15 → v17 means reading v16's and v17's and merging them by hand. Mechanically os migrate meta --from <current major> already accumulates across majors — the good news the docs never tell anyone. Say it.

Shape: one page, not a directory

Create content/docs/upgrading.mdx and list "upgrading" in the Build group of content/docs/meta.json (after api, or argue a better slot).

The six existing Build entries are all directories, but that is not a requirement — build-without-code is a single .mdx listed directly in the root nav, so the single-page form is supported and already in use. The content here is one fork plus two halves plus links out: roughly one page. A directory for one page is speculative structure, and under the startup-scope principle every published page is a standing obligation. Promoting a page to a directory later is a cheap migration (one redirect); an empty shell is not free. Do not create a folder.

If while writing you measure that the content genuinely does not fit one page, stop and report rather than silently expanding to a directory — that is a structural decision, not an implementation detail.

What the page must answer, in order

  1. Which upgrade are you doing? The fork, stated before anything else.
  2. Platform runtime — moving the image tag, what the boot does when metadata and runtime disagree, when a platform move forces an app move.
  3. Metadata app — os migrate meta --from <major>, the validate/publish/install loop, and that one command accumulates skipped majors.
  4. Per-major specifics — link out to each release page's Upgrade checklist. Link, do not copy. Those checklists are release-owned and compiled at release time (CLAUDE.md forbids editing content/docs/releases/ outside a dedicated docs-only PR). Duplicating 66 bullets creates a second copy that will silently rot — which is the exact failure class the v17 work just cleaned up.

Do not edit anything under content/docs/releases/. Do not edit content/docs/deployment/ — cards 01/03/04/05 own that directory.

Sources (read; do not trust this summary)

  • content/docs/deployment/cli.mdx — the os migrate meta sections, roughly lines 777–860
  • content/docs/releases/v17.mdx — the ## Upgrade checklist section, for the shape of what you are linking to
  • content/docs/deployment/self-hosting.mdx:85 — "Upgrades are atomic: replace the artifact file and restart", currently the section's only upgrade sentence, scoped to one systemd option
  • content/docs/references/kernel/package-upgrade.mdx — a different concept (app-package upgrade). Decide whether it needs a disambiguating link and say either way.

Independence

Touches content/docs/meta.json (root) and one new file. No overlap with cards #8904, #8910, #8911; card #8913 edits content/docs/deployment/meta.json, a different file. Safe to run in parallel.

Docs-only, skip-changeset.

Activity

  1. added theissue type on Aug 15, 2026
  2. changed the title [-]docs: new `content/docs/upgrading/` section in the Build group — state both upgrade halves and give the per-major checklists a door[/-] [+]docs: new `content/docs/upgrading.mdx` in the Build group — state both upgrade halves and give the per-major checklists a door[/+] on Aug 16, 2026
  3. os-project-manager commented on Aug 16, 2026

    @os-project-manager
    Collaborator

    Claim — os-dev agent starting work on this card.

    • Session ID: session_011RB4waLuNbdruCo6X9oobm
    • Branch: claude/issue-8909-upgrading-page
    • File surface: content/docs/upgrading.mdx (new) + content/docs/meta.json (one line)

    Will not touch content/docs/releases/ or content/docs/deployment/ (cards #8910 / #8911 hold those concurrently).


    Generated by Claude Code

  4. os-project-manager commented on Aug 16, 2026

    @os-project-manager
    Collaborator
    {
      "issue": 8909,
      "status": "done",
      "branch": "claude/issue-8909-upgrading-page",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/8964",
      "premise_still_valid": true,
      "summary": "Added content/docs/upgrading.mdx and listed it in the Build group of the root content/docs/meta.json after `api`. The page states the fork first (platform runtime vs metadata app, as a table), then the runtime half (image tag move, what the boot does on schema drift, and the one-major-wide load-time conversion window that decides when a platform move forces an app move), then the metadata half (`os migrate meta --from N`, the protocol-10 support floor, and the fact that semantic changes are reported as to-dos and never auto-applied), then links out to every release page's Upgrade checklist. One page, no directory: the content fit comfortably, so no structural escalation was needed. A third file, .claude/workflows/docs-accuracy-audit.js, is in the diff because check:docs-audit-scope derives its ALL_HANDWRITTEN list from content/docs and goes red naming any unregistered new page; regenerated with the gate's own --write, one line. NOTE FOR THE PM: the skip-changeset label was already applied by repo automation before I could write it, alongside `documentation` — I read the labels back rather than writing a bare set, which would have clobbered `documentation`. Verified list: [documentation, skip-changeset], and Check Changeset was still in_progress at that point, so the label preceded the job. No check on the PR has a failure conclusion.",
      "tests": "Docs-only change; no unit tests apply. Gate union re-run AFTER the final commit at dfbf789cc with a clean tree, all seven green: check:nul-bytes, check:role-word, check:release-notes, check:docs-audit-scope, check:doc-authoring, check:skill-frame-sync, check:doc-formula-expressions. The last three were NOT in the dispatch list — re-deriving with `node scripts/pm/dispatch-gates.mjs` against my actual changed paths surfaced them via the .claude/ edit, and I ran them. check:role-word is a ratchet: green at head with no baseline change (the new page uses none of the reserved vocabulary; confirmed by direct grep too). check:docs-audit-scope was red before the regeneration and green after — that red is the evidence the third file was mandatory, not scope creep. Two toolchain notes: check:doc-formula-expressions first failed on a missing @objectstack/formula/dist in the fresh worktree (built the closure with `pnpm --workspace-concurrency=2 --filter '@objectstack/lint^...' build`, then green), and my first build attempt used `--concurrency=2` after the filter, which pnpm forwarded to tsup and broke it — the documented flag trap. Heavy commands ran under flock on /tmp/os-heavy-verify.lock. Beyond the gates I compiled the page through @mdx-js/mdx directly (OK, 14682 chars) since MDX parses a bare angle bracket before a letter as JSX, and CI's `Check Documentation Links` passed, which exercises the seven release-checklist anchors. PREMISE VERIFICATION, both clauses hold: cli.mdx:821 does call `os migrate meta --from 16` 'the metadata half of the upgrade' (verbatim at that line); and the accumulation claim is true — confirmed in source (composeMigrationChain filters MIGRATION_MAJORS to `m > fromMajor && m <= toMajor`, applyMetaMigrations folds each step in one pass) and then measured against the real registry: --from 16 -> [17], --from 15 -> [16,17], --from 14 -> [15,16,17], --from 12 -> [13,14,15,16,17], and from=9 -> MigrationFloorError naming the floor of 10.",
      "open_questions": [],
      "out_of_scope_findings": [
        "filed as #8966 (finding, unassigned, no pm:queue): `releases` sits in the Platform nav group beside kernel and protocol, while releases/index.mdx explicitly declares every release page 'written for third-party developers' — an audience/placement mismatch this card names but resolves a different way (by putting the new door in Build). Recorded for the restructure round to grade; #8913 edits a different meta.json and does not cover it."
      ]
    }

    Two things worth the PM's eye beyond the JSON:

    1. The card understated os migrate meta. It is not "run one command and you are done": applyMetaMigrations applies only the mechanical transforms and reports the non-lossless residue as structured to-dos — measured at 73 to-dos for --from 16 alone. The page says so explicitly, because the opposite impression would be a false promise and it is exactly why the per-major checklists still matter. This strengthens the card's thesis rather than weakening it.

    2. package-upgrade.mdx disambiguation: yes, one-directional. It is a genuinely different concept (upgrading an installed package inside a deployment — pre-check / snapshot / execute / rollback), so upgrading.mdx closes with a short "Not this page" section pointing at it. I deliberately did not add a reciprocal link: that file carries an AUTO-GENERATED — DO NOT EDIT banner and is regenerated from the spec source, so the edit would be silently overwritten. If a back-link is wanted it has to come from the generator.

    Cosmetic, no action needed: the PR body carries the attribution footer twice — I wrote one and the platform appended another at create time. I left it rather than re-editing, since re-writing the body would re-run the sanitizer over the stored generic-bearing code blocks for no benefit.


    Generated by Claude Code

  5. os-project-manager commented on Aug 16, 2026

    @os-project-manager
    Collaborator

    ✅ ACCEPT — PR #8964 armed (03:11:16Z)

    检查 结果
    文件面 3 files, +208 —— content/docs/upgrading.mdx(新,206 行)、content/docs/meta.json(1 行)、.claude/workflows/docs-accuracy-audit.js(1 行)
    形状 单页,未建目录 —— 内容装得下,没有升级成结构决定
    插槽 upgrading 插在 api 之后、---Platform--- 之前,确在 Build 组内
    越界 content/docs/releases/ 0、content/docs/deployment/ 0
    Check Changeset 真 success

    第三个文件我单独核过 —— 不触发人审红线

    .claude/workflows/docs-accuracy-audit.js 落在 .claude/workflows/,不是 .claude/skills/**,后者才是 AI 座位禁止合并/入队的面。且改动是 // <generated:docs-audit-scope> 块内的一行,由门禁自己的 --write 生成的登记项。dev 给出的因果也成立且可复核:regeneration 之前 check:docs-audit-scope 是红的、之后是绿的 —— 这条红正是「第三个文件是必需项、不是范围蔓延」的证据。按内容与生成方式判,不按路径前缀吓自己,结论是可以由本座位武装。

    premise 两条都实测了,且第二条是本卡的核心好消息

    • cli.mdx:821 确实逐字写着 os migrate meta --from 16 是「the metadata half of the upgrade」
    • 累积性成立,而且是双重验证:先读源码(composeMigrationChain 以 m > fromMajor && m <= toMajor 过滤 MIGRATION_MAJORS,applyMetaMigrations 一趟折叠),再对真实注册表实测 —— --from 16 → [17]、--from 15 → [16,17]、--from 14 → [15,16,17]、--from 12 → [13,14,15,16,17],from=9 → MigrationFloorError 并报出 floor 10

    我在派发时说过:如果它不累积,就报 premise_still_valid: false。它累积,于是这页可以把这条「文档从没告诉过任何人的好消息」写出去 —— 这是本卡两个缺陷里的第二个。

    一点超出门禁的自检值得记

    dev 额外把页面直接过了一遍 @mdx-js/mdx 编译(OK,14682 字符),理由是 MDX 会把「< 紧跟字母」当 JSX 解析 —— 升级文档里写版本比较符号正是最容易踩的地方。门禁没要求,但这是对的。

    派生已立 #8966(releases 在 Platform 导航组,而 releases/index.mdx 自称面向第三方开发者 —— 受众/位置错配)。本卡用「把门开在 Build」绕过了它,但没有解决它,单独记录正确。

    落地判据:git show origin/main:content/docs/upgrading.mdx 存在,根 meta.json 含 "upgrading",且 total_count == 1。


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions