Repository navigation
Commit 2da35ae
test(cli): pin migrate meta's range rewrite on the --from 17 shape, now that the runtime is protocol 18 (#22539)
Fixes #22219
Clause-②: no
The diff adds one test row and publishes nothing.
## What this adds
- The `from: 17` row of `SHAPES` in
`packages/cli/test/migrate-meta-protocol-range.test.ts`, verbatim as the
previous holder's dev quoted it (report comment 6056787854, last
`out_of_scope_findings` entry). It is a `'^17'` manifest carrying
`dashboards: [{ name: 'ops', label: 'Ops', widgets: [], refreshInterval:
300 }]`, a key the protocol-18 step converts
(`dashboard-refresh-interval-to-refresh-interval-seconds`).
- With it, cases 1 and 2 of the file (`describe.each(SHAPES)`) run for
`--from 17`, the shape this card was filed on:
- the control: the load refuses the manifest, and the refusal names this
command;
- a dry run names the range edit and writes nothing;
- `--write` rewrites `'^17'` to `'^18'` beside the rename, and only
those bytes change;
- the reload is not refused;
- a `'^17'` manifest with nothing to convert gets the range edit alone,
and then loads.
- The two comments that said the 17 → 18 row was still to come now say
what the file pins.
- No source edit. `packages/cli/test` is outside `@objectstack/cli`'s
`files`, so this publishes nothing and carries no changeset
(`skip-changeset`).
Diff: 1 file, +7 / −4.
## The row's three premises, measured first
All readings are at `1cbd8f728`, which is `origin/main` `4e9fe9ff6` plus
this test edit.
1. **The conversion id exists.** It is at
`packages/spec/src/conversions/registry.ts:11495` with `toMajor: 18` and
`retiredFromLoadPath: true`. It is listed in `MAJOR_18_CONVERSIONS` at
`:15041` (order 24).
2. **Protocol 18 tombstones the key, so the authored-source load hands
it to the chain as written.**
- `packages/spec/src/ui/dashboard.zod.ts:1774` declares
`refreshInterval: retiredKey(...)`, and its prescription names `os
migrate meta --from 17`.
- `DashboardSchema` from this worktree's build (`PROTOCOL_VERSION`
18.0.0) refuses the member with `invalid_type` at `refreshInterval`,
carrying the tombstone text. The renamed shape parses.
- In the test, the control answers `STACK_SCHEMA_INVALID` naming
`migrate meta --from 17`. `--write --json` reports `applied` and
`written` as exactly that one conversion id.
3. **The member is a valid protocol-17 dashboard.**
`DashboardSchema.safeParse` was run against the published npm packages:
- `@objectstack/spec@17.0.0` and `@17.3.0` accept it. Both refuse the
renamed `refreshIntervalSeconds` as an unrecognized key.
- `@17.7.0`, still `PROTOCOL_VERSION` 17.0.0, refuses it at the
tombstone, because the rename shipped inside the 17 line (`retiredAfter:
'17.3.0'`).
- So it is the shape an app authored on 17.0 to 17.3 carries. The member
is unchanged from the quoted row. It is the conversion fixture's own
shape (`name`, `label`, `widgets`, the key), so nothing smaller is
valid.
## Red, then green
- **Green as committed** (`1cbd8f728`): the file reports `Test Files 1
passed (1)` and `Tests 19 passed (19)`, which is the 14 earlier cases
plus 5 for `--from 17`.
- **Red with `planProtocolRange` neutralised.** This was a one-off
ablation from the committed state; no file was left behind.
- Method: `scripts/ablation-replace.mjs`, wrapped in a bash `trap … EXIT
INT TERM` that restores from `HEAD` on an absolute path and proves the
restore.
- The mutation: the anchor `if (compat.status !== 'incompatible') return
undefined;` became `if (true as boolean) return undefined; //
ABLATION-22219 …` in `packages/cli/src/commands/migrate/meta.ts`.
- Proof it landed on disk: anchor count 1 → 0, marker count 0 → 1, and
the blob went `f026976c` → `4bb72fea`. A grep run inside the mutation
window read marker 1 and anchor 0.
- No rebuild was needed: the test imports `meta.ts` relatively, so it
loads from `src`.
- Result: `Tests 15 failed | 4 passed (19)`. Every `--from 17` case went
red except its control: the dry run, `--write`, the reload, and the
nothing-to-convert case.
- The `--from 17` reload answered this card's titled refusal:
`ProtocolIncompatibleError` `OS_PROTOCOL_INCOMPATIBLE` 422, "package
'com.example.range' targets protocol ^17 (engines.protocol) but this
runtime is protocol 18.0.0. This is a major-version break. Run:
objectstack migrate meta --from 17".
- Restore proven twice, by the tool and by the trap: the blob after
restore is `f026976c08cc`, equal to the blob at `HEAD`; `git diff HEAD`
was empty and the porcelain was empty.
## Verification, all at `1cbd8f728`
- **cli unit layer** (`pnpm --filter @objectstack/cli exec vitest run
--project unit --maxWorkers=2`): `Test Files 275 passed (275)`, `Tests
4062 passed (4062)`, `VERDICT command-exit 0`. `vitest list --project
unit --filesOnly` lists this file, and the integration list does not.
- **`pnpm --filter @objectstack/cli typecheck`**: `VERDICT command-exit
0`.
- `check:test-typecheck` reports OK at `3 file(s) / 28 error(s) / 6
pinned signature(s)`, unchanged.
- The file is in `tsconfig.test.json`'s program (`--listFilesOnly`: 1
hit) and has no debt-ledger row.
- **Lint, as a proven narrowing:**
- ① Population, read from eslint's own config: `isPathIgnored` is false,
and `calculateConfigForFile` applies 5 rules.
- ② Count, read from `eslint --no-inline-config --format json`: 1 file,
0 errors, 0 warnings, 0 fatal.
- ③ Invariance: the config enables no type-aware linting. Every
`parserOptions` is `{ ecmaVersion, sourceType }`, with no `project` and
no `projectService`, as `eslint.config.mjs` itself states. So an edit to
one test file cannot move any other file's verdict.
- The full `pnpm lint` is declared to CI.
- **Derived gates:**
- `dispatch-gates --commands`, run with no paths, derived 50 commands,
identical to the dispatched list.
- `--ran` reports `50 derived, 50 run, 0 NOT-MEASURED, 0 UNRUN`.
- `check:dual-build-cjs-loads` first exited 3 (PREREQUISITE NOT MET:
dists outside the CLI closure). I built those with turbo (68/68 cached)
and re-ran it: exit 0.
- **Integration layer and dogfood**: declared to CI. The diff touches no
spawn entry and no dogfood input.
## Acceptance notes
- `dispatch-gates` warns that the tree is behind `origin/main`, and that
`scripts/engine-double-contract.pinned.json` moved in that range. No
commit in `4e9fe9ff6..faf6348` touches this file,
`packages/cli/src/commands/migrate/**`, the dashboard schema, the
conversion registry, the codemod, the config loader or the handshake. So
`main` was not merged, per the claim's fence; CI runs on the merge ref.
- `check:type-check-debt` (`--re-measure`) rebuilds package dists in the
worktree while it runs. A unit run alongside it hit module-not-found
errors mid-rebuild, so I discarded that run and re-took it after the
gates finished.
- The member counts as valid protocol-17 metadata only as published at
17.0.0 to 17.3.0. From 17.7.0, still on protocol 17, the 17-line schema
refuses `refreshInterval` itself. This is an observation only.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01BmsuLyUeuG5CNpZFMH1jzS)_
Co-authored-by: Claude <noreply@anthropic.com>1 parent 3073b72 commit 2da35ae
1 file changed
Lines changed: 7 additions & 4 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
40 | 40 | | |
41 | 41 | | |
42 | 42 | | |
43 | | - | |
44 | | - | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
45 | 47 | | |
46 | 48 | | |
47 | 49 | | |
| |||
87 | 89 | | |
88 | 90 | | |
89 | 91 | | |
90 | | - | |
91 | | - | |
| 92 | + | |
| 93 | + | |
92 | 94 | | |
93 | 95 | | |
94 | 96 | | |
| |||
98 | 100 | | |
99 | 101 | | |
100 | 102 | | |
| 103 | + | |
101 | 104 | | |
102 | 105 | | |
103 | 106 | | |
| |||
0 commit comments