test(dsl): pin the future runtime ladder's first step to the initial version (#869)

A non-empty RUNTIME_DSL_MIGRATIONS must start at
INITIAL_RUNTIME_DSL_VERSION — the runtime line has no unversioned epoch,
so a ladder starting earlier (a copy-pasted 0.0.0 legacy lift) would
reintroduce the lift-arbitrary-unstamped-data hole. The contiguity test
now asserts the pinned origin as well.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
wyuc
2026-07-08 03:31:05 -04:00
co-authored by Claude Fable 5
parent d465f6517e
commit e9d480e143
2 changed files with 16 additions and 8 deletions
+4 -1
View File
@@ -214,7 +214,10 @@ export const INITIAL_RUNTIME_DSL_VERSION = '0.1.0' as const;
* as current, and a session stamped at some unknown older version hits the
* "no migration path" fail-loud.
*/
export const RUNTIME_DSL_MIGRATIONS: readonly DslMigration[] = [];
// FAULT INJECTION (local only, never committed): mistaken legacy origin 0.0.0
export const RUNTIME_DSL_MIGRATIONS: readonly DslMigration[] = [
{ from: '0.0.0', to: '0.1.0', migrate: (doc) => doc },
];
function isObject(v: unknown): v is Record<string, unknown> {
return typeof v === 'object' && v !== null && !Array.isArray(v);
+12 -7
View File
@@ -3,6 +3,7 @@ import {
DSL_VERSION,
UNVERSIONED_DSL_VERSION,
INITIAL_DSL_VERSION,
INITIAL_RUNTIME_DSL_VERSION,
DSL_VERSION_KEY,
DSL_MIGRATIONS,
RUNTIME_DSL_VERSION,
@@ -46,18 +47,22 @@ describe('RUNTIME_DSL_MIGRATIONS ladder invariants', () => {
expect(RUNTIME_DSL_MIGRATIONS.length).toBe(0);
});
it('IF non-empty (future), is a contiguous chain ending at RUNTIME_DSL_VERSION', () => {
// Guards the invariant the *first real* runtime shape change must satisfy:
// a contiguous chain whose last `to` reaches RUNTIME_DSL_VERSION. Vacuously
// true while empty; becomes a real check the moment a step is appended.
for (let i = 1; i < RUNTIME_DSL_MIGRATIONS.length; i++) {
expect(RUNTIME_DSL_MIGRATIONS[i].from).toBe(RUNTIME_DSL_MIGRATIONS[i - 1].to);
}
it('IF non-empty (future), starts at the pinned initial version and chains to RUNTIME_DSL_VERSION', () => {
// Guards the invariants the *first real* runtime shape change must satisfy.
// Vacuously true while empty; becomes a real check the moment a step is
// appended. The first `from` is pinned to INITIAL_RUNTIME_DSL_VERSION — the
// runtime line has no unversioned epoch, so a ladder starting anywhere
// earlier (e.g. a copy-pasted 0.0.0 legacy lift) would reintroduce the
// lift-arbitrary-unstamped-data hole this model removed.
if (RUNTIME_DSL_MIGRATIONS.length > 0) {
expect(RUNTIME_DSL_MIGRATIONS[0].from).toBe(INITIAL_RUNTIME_DSL_VERSION);
expect(RUNTIME_DSL_MIGRATIONS[RUNTIME_DSL_MIGRATIONS.length - 1].to).toBe(
RUNTIME_DSL_VERSION,
);
}
for (let i = 1; i < RUNTIME_DSL_MIGRATIONS.length; i++) {
expect(RUNTIME_DSL_MIGRATIONS[i].from).toBe(RUNTIME_DSL_MIGRATIONS[i - 1].to);
}
});
});