Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .changeset/26303-upgrade-skill-stored-rows-before-18-3.md
Original file line number Diff line number Diff line change
@@ -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 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.
23 changes: 11 additions & 12 deletions skills/objectstack-upgrade/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -447,9 +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; the read-time rehydration is still the
guarantee.
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.

---

Expand Down
12 changes: 11 additions & 1 deletion skills/objectstack-upgrade/evals/protocol-major-upgrade.json
Original file line number Diff line number Diff line change
Expand Up @@ -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, 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"],
"must_not_contain": ["UPDATE sys_metadata"]
}
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Loading