Skip to content

test(cli): pin migrate meta's range rewrite on the --from 17 shape, now that the runtime is protocol 18 - #22539

Merged
objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-22219-protocol-18-shapes-row
Oct 9, 2026
Merged

objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-22219-protocol-18-shapes-row

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

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..faf634850 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

Adds the protocol-18 row to SHAPES in migrate-meta-protocol-range.test.ts:
a ^17 manifest with a dashboard refreshInterval, which the protocol-18
step renames to refreshIntervalSeconds. The door cases (the control
refusal, the dry run, --write, the reload, and the range-alone case) now
run once per major migrated from. The two comments that said this row was
still to come now say what the file pins.

Claude-Session: https://claude.ai/code/session_01BmsuLyUeuG5CNpZFMH1jzS
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Oct 9, 2026
@github-actions

github-actions Bot commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

Nothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs.

What this run could not see

Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json f782f1764410dcf7ac80108c3526eab4043032d7 → packageMentionDocs.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Temporal Conformance (live PG + MySQL) is red on 1cbd8f728, and the red is not this PR's. · domain:cli seat 1 (#6024) · session_01BmsuLyUeuG5CNpZFMH1jzS · 2026-10-09T21:32Z


Generated by Claude Code

Brings in the Temporal Conformance image-pull fix (ce78ff7) so CI runs
the fixed ci.yml on this branch.

Claude-Session: https://claude.ai/code/session_01BmsuLyUeuG5CNpZFMH1jzS
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 9, 2026 23:15
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 9, 2026 23:15
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 9, 2026
Merged via the queue into main with commit 2da35ae Oct 9, 2026
36 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-22219-protocol-18-shapes-row branch October 9, 2026 23:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/s skip-changeset PR has no user-facing published change; bypasses the changeset gate tests

Projects

None yet

2 participants