From 3bf0627876043d1a60a6ae31d9af0a35dfa66faa Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 2 Nov 2026 03:59:03 +0000 Subject: [PATCH 1/3] docs(skills): objectstack-upgrade teaches the stored pass before 18.3 drops the <=16.x conversions The stored-rows section said a protocol-16 row rehydrates in its protocol-17 shape forever. On 18.3 the conversions retired at or below 16.x leave the tree, so such a row is no longer rewritten at read. The section, the 3.6 assertion, the report template and eval 4 now say to canonicalize with `os migrate meta --stored --apply --yes` on the release being left (18.2 or earlier) before moving; new eval 5 asks the 18.1 -> 18.3 question. Claude-Session: https://claude.ai/code/session_01J8VVAkD2h5o5cmhTRa3bsF Co-authored-by: Claude --- ...3-upgrade-skill-stored-rows-before-18-3.md | 12 +++++++++++ skills/objectstack-upgrade/SKILL.md | 20 +++++++++---------- .../evals/protocol-major-upgrade.json | 12 ++++++++++- .../references/examples-upgrade.md | 2 +- 4 files changed, 33 insertions(+), 13 deletions(-) create mode 100644 .changeset/26303-upgrade-skill-stored-rows-before-18-3.md diff --git a/.changeset/26303-upgrade-skill-stored-rows-before-18-3.md b/.changeset/26303-upgrade-skill-stored-rows-before-18-3.md new file mode 100644 index 00000000000..4ace5935725 --- /dev/null +++ b/.changeset/26303-upgrade-skill-stored-rows-before-18-3.md @@ -0,0 +1,12 @@ +--- +'@objectstack/skills': patch +--- + +docs(skills): objectstack-upgrade says a stored row in a ≤16.x shape stops being rewritten at read on 18.3, and teaches the stored pass on 18.2 or earlier first + +Clause-②: no +Metadata-protocol: none + +- **Before.** § "Stored rows" said every stored-row rehydration replays the conversion chain including entries retired from the load path, so "a row written under protocol 16 therefore rehydrates in its protocol-17 shape without anybody editing it", and offered `os migrate meta --stored --apply` only as a way to make that durable. § 3.6 called the read-time rehydration "still the guarantee", the report template marked the stored pass optional ("rows rehydrate correctly today"), and eval 4 expected the same answer. On 18.3, which drops every conversion retired at or below 16.x, that advice leaves such a row unconverted for good. +- **Now.** The section says rehydration replays only the conversions the installed release still carries, that 18.3 drops those retired at or below 16.x, and to run the stored pass on the release being left (18.2 or earlier for such a row) before moving; § 3.6 says to get exit `0` from `os migrate meta --stored --json` before the move; the report template's stored-pass line says it is owed before any release that drops the rows' conversions. Eval 4's expected answer says the same, and new eval 5 asks the 18.1 → 18.3 question directly. +- `SKILL.md` and `references/examples-upgrade.md` stay under their token ceilings (no ceiling moves). No schema, key, command or behaviour changes. diff --git a/skills/objectstack-upgrade/SKILL.md b/skills/objectstack-upgrade/SKILL.md index aef545defb0..c2d8c395ed3 100644 --- a/skills/objectstack-upgrade/SKILL.md +++ b/skills/objectstack-upgrade/SKILL.md @@ -171,18 +171,17 @@ other with the reason it was not written, never writes a semantic change, and if re-running the chain over the written files disagrees, restores every file and exits 1. -### Stored rows: rehydration replays the same conversions +### Stored rows: rehydration replays what the release carries -A deployment's `sys_metadata` rows are the other subject. They are handled for -you at read time — the metadata loader and the ObjectQL plugin both pass each -stored row through `applyConversionsToStoredItem`, which replays the conversion -chain over a single item **including entries retired from the load path**. A row -written under protocol 16 therefore rehydrates in its protocol-17 shape without -anybody editing it. +A deployment's `sys_metadata` rows are the other subject. At read time the +metadata loader and the ObjectQL plugin pass each stored row through +`applyConversionsToStoredItem`, which replays every conversion the release still +carries, **including entries retired from the load path**. 18.3 drops those +retired at or below 16.x, so a row still in such a shape is no longer rewritten. Rehydration is a read-time projection: the rows on disk keep their old shape, -and you never hand-edit `sys_metadata`. To make it durable, run the stored pass -— read-only by default: +and you never hand-edit `sys_metadata`. ⛔ Run the stored pass before you move +(on 18.2 or earlier for such a row) — read-only by default: ```bash os migrate meta --stored # preview, writes nothing @@ -448,8 +447,7 @@ os migrate meta --stored --json # 0 = every row canonical, 1 = work left ``` That is what makes "this deployment is on protocol N" a CI check rather than a -belief. Nothing gates on it having run; the read-time rehydration is still the -guarantee. +belief. Nothing gates on it having run, so get `0` before you move. --- diff --git a/skills/objectstack-upgrade/evals/protocol-major-upgrade.json b/skills/objectstack-upgrade/evals/protocol-major-upgrade.json index ebd472a15a7..fa27293c8a1 100644 --- a/skills/objectstack-upgrade/evals/protocol-major-upgrade.json +++ b/skills/objectstack-upgrade/evals/protocol-major-upgrade.json @@ -34,12 +34,22 @@ { "id": 4, "prompt": "We bumped @objectstack/spec 16 → 17 and `os validate` is green, so there was nothing to upgrade, right? Production also has `sys_metadata` rows written under 16.", - "expected_output": "No: `validate` green is necessary, not sufficient — migration-chain-only conversions (16 → 17 has `field-required-notnull-explicit`) reject nothing at parse. Replays `os migrate meta --from 17 --json` and reads `applied` (must be `[]`). Stored rows rehydrate through `applyConversionsToStoredItem` at read time; to make it durable runs `os migrate meta --stored` (read-only) then `os migrate meta --stored --apply --yes` (`--yes` is mandatory in a non-TTY), and never hand-edits `sys_metadata`. Any per-deployment data-migration gates the run prints go into the report as pending, by name.", + "expected_output": "No: `validate` green is necessary, not sufficient — migration-chain-only conversions (16 → 17 has `field-required-notnull-explicit`) reject nothing at parse. Replays `os migrate meta --from 17 --json` and reads `applied` (must be `[]`). Stored rows rehydrate through `applyConversionsToStoredItem` only while the installed release carries their conversions (18.3 drops those retired at or below 16.x), so before moving past 18.2 it runs `os migrate meta --stored` (read-only) then `os migrate meta --stored --apply --yes` (`--yes` is mandatory in a non-TTY), and never hand-edits `sys_metadata`. Any per-deployment data-migration gates the run prints go into the report as pending, by name.", "files": [], "assertions": { "must_contain": ["applied", "--stored", "--yes", "field-required-notnull-explicit", "applyConversionsToStoredItem"], "must_not_contain": ["UPDATE sys_metadata"] } + }, + { + "id": 5, + "prompt": "我们在 @objectstack/spec 18.1,想直接升到 18.3。生产库 sys_metadata 里还有 16 时代存下的行,现在读出来都正常,直接升可以吗?", + "expected_output": "Not yet: those rows read fine today only because `applyConversionsToStoredItem` replays the conversions 18.1 still carries, and 18.3 drops those retired at or below 16.x, so after the bump such a row is no longer rewritten at read. On 18.1, before the bump: `os migrate meta --stored` (read-only preview), then `os migrate meta --stored --apply --yes`, then `os migrate meta --stored --json` must exit 0; only then move to 18.3. Never hand-edits `sys_metadata`, and never bumps first expecting the 18.3 stored pass to repair the rows — the conversions are gone there too.", + "files": [], + "assertions": { + "must_contain": ["--stored --apply --yes", "--stored --json", "18.3", "applyConversionsToStoredItem"], + "must_not_contain": ["UPDATE sys_metadata"] + } } ] } diff --git a/skills/objectstack-upgrade/references/examples-upgrade.md b/skills/objectstack-upgrade/references/examples-upgrade.md index 840e17708e1..573b003511b 100644 --- a/skills/objectstack-upgrade/references/examples-upgrade.md +++ b/skills/objectstack-upgrade/references/examples-upgrade.md @@ -76,7 +76,7 @@ _N sites, M conversions. Ported into sources from `os migrate meta --out`._ - [ ] `os migrate files-to-references` — media values only warn until it passes. - [ ] `os migrate value-shapes` — stored reference/JSON values unchecked until it passes. -- [ ] `os migrate meta --stored --apply` — rows rehydrate correctly today; this makes it durable. +- [ ] `os migrate meta --stored --apply` — before any release that drops their conversions. ## 5 · Not changed, and why From 43d397d498d05ffaa719726fd263bb8f14bf4206 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 2 Nov 2026 04:31:45 +0000 Subject: [PATCH 2/3] docs(skills): objectstack-upgrade says a stored-pass exit 0 counts only on the release being left On a release that no longer carries a row's conversions, the stored pass finds no notice and no todo on that row, records it canonical, and exits 0, so the check in 3.6 proves nothing there. Say so in 3.6, and extend eval 5's expected answer with the same point. Claude-Session: https://claude.ai/code/session_01J8VVAkD2h5o5cmhTRa3bsF Co-authored-by: Claude --- skills/objectstack-upgrade/SKILL.md | 5 +++-- skills/objectstack-upgrade/evals/protocol-major-upgrade.json | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/skills/objectstack-upgrade/SKILL.md b/skills/objectstack-upgrade/SKILL.md index c2d8c395ed3..62fdb16754f 100644 --- a/skills/objectstack-upgrade/SKILL.md +++ b/skills/objectstack-upgrade/SKILL.md @@ -446,8 +446,9 @@ code: os migrate meta --stored --json # 0 = every row canonical, 1 = work left ``` -That is what makes "this deployment is on protocol N" a CI check rather than a -belief. Nothing gates on it having run, so get `0` before you move. +That is what makes "this deployment is on protocol N" a CI check — valid only +on the release you are leaving: one that dropped a row's conversions no longer +recognises it and answers `0`. Nothing gates on it having run. --- diff --git a/skills/objectstack-upgrade/evals/protocol-major-upgrade.json b/skills/objectstack-upgrade/evals/protocol-major-upgrade.json index fa27293c8a1..2d81e63ed56 100644 --- a/skills/objectstack-upgrade/evals/protocol-major-upgrade.json +++ b/skills/objectstack-upgrade/evals/protocol-major-upgrade.json @@ -44,7 +44,7 @@ { "id": 5, "prompt": "我们在 @objectstack/spec 18.1,想直接升到 18.3。生产库 sys_metadata 里还有 16 时代存下的行,现在读出来都正常,直接升可以吗?", - "expected_output": "Not yet: those rows read fine today only because `applyConversionsToStoredItem` replays the conversions 18.1 still carries, and 18.3 drops those retired at or below 16.x, so after the bump such a row is no longer rewritten at read. On 18.1, before the bump: `os migrate meta --stored` (read-only preview), then `os migrate meta --stored --apply --yes`, then `os migrate meta --stored --json` must exit 0; only then move to 18.3. Never hand-edits `sys_metadata`, and never bumps first expecting the 18.3 stored pass to repair the rows — the conversions are gone there too.", + "expected_output": "Not yet: those rows read fine today only because `applyConversionsToStoredItem` replays the conversions 18.1 still carries, and 18.3 drops those retired at or below 16.x, so after the bump such a row is no longer rewritten at read. On 18.1, before the bump: `os migrate meta --stored` (read-only preview), then `os migrate meta --stored --apply --yes`, then `os migrate meta --stored --json` must exit 0; only then move to 18.3. Never hand-edits `sys_metadata`, and never bumps first expecting the 18.3 stored pass to repair the rows — the conversions are gone there too, so an 18.3 `--stored --json` exit 0 proves nothing about such a row: nothing recognises it any more.", "files": [], "assertions": { "must_contain": ["--stored --apply --yes", "--stored --json", "18.3", "applyConversionsToStoredItem"], From 4e175a6ac4990b8bc2bc598c3c70e72905273e3f Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 2 Nov 2026 04:52:32 +0000 Subject: [PATCH 3/3] docs(changeset): the 26303 changeset describes the 3.6 exit-0 caveat as it now reads The patch round changed 3.6 to say the stored-pass exit 0 counts only on the release being left; the changeset's Now bullet still described the earlier wording. Claude-Session: https://claude.ai/code/session_01J8VVAkD2h5o5cmhTRa3bsF Co-authored-by: Claude --- .changeset/26303-upgrade-skill-stored-rows-before-18-3.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/26303-upgrade-skill-stored-rows-before-18-3.md b/.changeset/26303-upgrade-skill-stored-rows-before-18-3.md index 4ace5935725..223bc3926ff 100644 --- a/.changeset/26303-upgrade-skill-stored-rows-before-18-3.md +++ b/.changeset/26303-upgrade-skill-stored-rows-before-18-3.md @@ -8,5 +8,5 @@ Clause-②: no Metadata-protocol: none - **Before.** § "Stored rows" said every stored-row rehydration replays the conversion chain including entries retired from the load path, so "a row written under protocol 16 therefore rehydrates in its protocol-17 shape without anybody editing it", and offered `os migrate meta --stored --apply` only as a way to make that durable. § 3.6 called the read-time rehydration "still the guarantee", the report template marked the stored pass optional ("rows rehydrate correctly today"), and eval 4 expected the same answer. On 18.3, which drops every conversion retired at or below 16.x, that advice leaves such a row unconverted for good. -- **Now.** The section says rehydration replays only the conversions the installed release still carries, that 18.3 drops those retired at or below 16.x, and to run the stored pass on the release being left (18.2 or earlier for such a row) before moving; § 3.6 says to get exit `0` from `os migrate meta --stored --json` before the move; the report template's stored-pass line says it is owed before any release that drops the rows' conversions. Eval 4's expected answer says the same, and new eval 5 asks the 18.1 → 18.3 question directly. +- **Now.** The section says rehydration replays only the conversions the installed release still carries, that 18.3 drops those retired at or below 16.x, and to run the stored pass on the release being left (18.2 or earlier for such a row) before moving; § 3.6 says the `os migrate meta --stored --json` exit `0` counts only on the release being left, because one that dropped a row's conversions answers `0` without recognising the row; the report template's stored-pass line says it is owed before any release that drops the rows' conversions. Eval 4's expected answer says the same, and new eval 5 asks the 18.1 → 18.3 question directly. - `SKILL.md` and `references/examples-upgrade.md` stay under their token ceilings (no ceiling moves). No schema, key, command or behaviour changes.