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
15 changes: 13 additions & 2 deletions docs/design/0036-warp-drift-ledger-crosslinks.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,10 +165,12 @@ The witness for this cycle is small and explicit:
- `docs/design/release-horizon-v20-v21.md`
- the audit now says directly that it is the drift ledger rather than the
canonical wall-chart
- the ratchet test exists at
- at cycle close, the ratchet coverage existed at
`test/unit/scripts/warp-drift-crosslinks-shape.test.ts`
- current successor coverage lives at
`test/unit/scripts/warp-drift-doc-graph.test.ts`

Verification command:
Historical verification command at cycle close:

```sh
npm exec vitest run \
Expand All @@ -177,6 +179,15 @@ npm exec vitest run \
test/unit/scripts/observer-geometry-ladder-shape.test.ts
```

Current successor command:

```sh
npm exec vitest run \
test/unit/scripts/warp-drift-doc-graph.test.ts \
test/unit/scripts/glossary-shape.test.ts \
test/unit/scripts/observer-geometry-ladder-shape.test.ts
```

### Agent playback

Question:
Expand Down
16 changes: 14 additions & 2 deletions docs/design/0037-remaining-warp-drift-release-slotting.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,9 +269,12 @@ The witness for this cycle is the alignment across four surfaces:

Ratchet test:

- `test/unit/scripts/warp-drift-release-slotting-shape.test.ts`
- at cycle close, `test/unit/scripts/warp-drift-release-slotting-shape.test.ts`
and `test/unit/scripts/warp-drift-crosslinks-shape.test.ts`
- current successor coverage lives at
`test/unit/scripts/warp-drift-doc-graph.test.ts`

Verification command:
Historical verification command at cycle close:

```sh
npm exec vitest run \
Expand All @@ -281,6 +284,15 @@ npm exec vitest run \
test/unit/scripts/observer-geometry-ladder-shape.test.ts
```

Current successor command:

```sh
npm exec vitest run \
test/unit/scripts/warp-drift-doc-graph.test.ts \
test/unit/scripts/glossary-shape.test.ts \
test/unit/scripts/observer-geometry-ladder-shape.test.ts
```

### Agent playback

Question:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,19 +48,27 @@ The cycle succeeded because it kept those responsibilities distinct.
### The crosslink contract is now ratcheted

The cycle added
[warp-drift-crosslinks-shape.test.ts](../../../../test/unit/scripts/warp-drift-crosslinks-shape.test.ts)
so the repo will fail loudly if those crosslinks disappear later.
`test/unit/scripts/warp-drift-crosslinks-shape.test.ts` so the repo would fail
loudly if those crosslinks disappeared later.

That historical ratchet has since been retired. Current successor coverage lives
at
[warp-drift-doc-graph.test.ts](../../../../test/unit/scripts/warp-drift-doc-graph.test.ts).

For a small docs hygiene slice, that is the right outcome: the fix is now
structural instead of purely editorial.

## Verification

Passed:
Passed at cycle close:

- `git diff --check`
- `npm exec vitest run test/unit/scripts/warp-drift-crosslinks-shape.test.ts test/unit/scripts/glossary-shape.test.ts test/unit/scripts/observer-geometry-ladder-shape.test.ts`

Current successor coverage:

- `npm exec vitest run test/unit/scripts/warp-drift-doc-graph.test.ts test/unit/scripts/glossary-shape.test.ts test/unit/scripts/observer-geometry-ladder-shape.test.ts`

Key witness commits:

- `bf316356` — `docs(design): pull warp drift crosslink cycle`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,15 @@ That keeps `v19` from silently inflating into “everything after `v18`.”

## Verification

Passed:
Passed at cycle close:

- `git diff --check`
- `npm exec vitest run test/unit/scripts/warp-drift-release-slotting-shape.test.ts test/unit/scripts/warp-drift-crosslinks-shape.test.ts test/unit/scripts/glossary-shape.test.ts test/unit/scripts/observer-geometry-ladder-shape.test.ts`

Current successor coverage:

- `npm exec vitest run test/unit/scripts/warp-drift-doc-graph.test.ts test/unit/scripts/glossary-shape.test.ts test/unit/scripts/observer-geometry-ladder-shape.test.ts`

Key witness commits:

- `10387c11` — `docs(design): pull remaining warp drift slotting cycle`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@
so `WarpCore.open()` now adopts the explicit runtime product surface instead
of linking onto the runtime bridge
- updated the closeout and composition-root ratchets:
- [warpcore-runtime-bridge.test.ts](../../../../test/unit/scripts/warpcore-runtime-bridge.test.ts)
- `test/unit/scripts/warpcore-runtime-bridge.test.ts`
- [openwarpgraph-composition-root.test.ts](../../../../test/unit/scripts/openwarpgraph-composition-root.test.ts)
- advanced the runtime-kill chain so the remaining order is now:
`API_delete-warpruntime-class` → `API_kill-warpruntime`

Current successor coverage for the retired closeout ratchet lives in
[publicReadingSurface.behavior.test.ts](../../../../test/unit/domain/publicReadingSurface.behavior.test.ts).

## Why it mattered

This removes the last `WarpCore` dependency on the bridge-era runtime aliasing
Expand All @@ -25,6 +28,12 @@ the runtime class to masquerade as its substrate.

## Witness

Historical witness at cycle close:

- `npm exec vitest run test/unit/scripts/warpcore-runtime-bridge.test.ts test/unit/scripts/openwarpgraph-composition-root.test.ts test/unit/domain/WarpCore.content.test.ts test/unit/domain/WarpCore.effectPipeline.test.ts test/unit/domain/WarpCore.emit.test.ts test/unit/domain/WarpGraph.strands.test.ts test/unit/domain/WarpGraph.conflicts.test.ts test/unit/domain/WarpGraph.worldline.test.ts test/unit/domain/WarpGraph.observerBoundary.test.ts test/unit/scripts/kill-warpruntime-split.test.ts`
- `npm run typecheck`
- `git diff --check`

Current successor witness:

- `npm exec vitest run test/unit/domain/publicReadingSurface.behavior.test.ts test/unit/scripts/openwarpgraph-composition-root.test.ts`
106 changes: 106 additions & 0 deletions test/unit/domain/publicReadingSurface.behavior.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { TextDecoder } from 'node:util';
import { describe, expect, it } from 'vitest';
import WarpAppDefault, {
InMemoryGraphAdapter,
openWarpGraph,
openWarpWorldline,
WarpApp,
WarpCore,
} from '../../../index.ts';

function openOptions(graphName: string, writerId: string): Parameters<typeof WarpCore.open>[0] {
return {
persistence: new InMemoryGraphAdapter(),
graphName,
writerId,
};
}

describe('public reading surfaces', () => {
it('opens WarpGraph as a capability bag without public materialization or runtime escapes', async () => {
const graph = await openWarpGraph(openOptions('public-reading-graph', 'writer-graph'));

expect(Object.isFrozen(graph)).toBe(true);
expect(graph.revelation.query).toBe(graph.query);
expect(graph.commitment.patches).toBe(graph.patches);
expect(typeof graph.query.worldline).toBe('function');
expect(typeof graph.query.observer).toBe('function');
expect(typeof graph.sync.syncWith).toBe('function');
expect('materialize' in graph).toBe(false);
expect('_materializeGraph' in graph).toBe(false);
expect('_runtime' in graph).toBe(false);

await (await graph.patches.createPatch()).addNode('node:capability').commit();

await expect(graph.query.hasNode('node:capability')).rejects.toMatchObject({
code: 'E_NO_STATE',
});
});

it('opens a worldline-first handle that commits and reads through live worldline objects', async () => {
const worldline = await openWarpWorldline({
persistence: new InMemoryGraphAdapter(),
worldlineName: 'public-worldline',
writerId: 'writer-worldline',
});

await worldline.commit((patch) => {
patch.addNode('user:alice');
patch.setProperty('user:alice', 'role', 'admin');
});

expect('materialize' in worldline).toBe(false);
expect('materializeCoordinate' in worldline).toBe(false);
expect('_materializeGraph' in worldline).toBe(false);
await expect(worldline.live().hasNode('user:alice')).resolves.toBe(true);

const result = await worldline.live().query().match('user:*').select(['id', 'props']).run();
expect('nodes' in result).toBe(true);
if (!('nodes' in result)) {
return;
}
expect(result.nodes).toEqual([
{ id: 'user:alice', props: { role: 'admin' } },
]);
});

it('keeps WarpApp curated while WarpCore remains the explicit materialization escape hatch', async () => {
const app = await WarpApp.open(openOptions('public-reading-app', 'writer-app'));

await app.patch(async (patch) => {
patch.addNode('doc:readme');
await patch.attachContent('doc:readme', 'hello from the app facade', {
mime: 'text/plain',
});
});

expect(WarpAppDefault).toBe(WarpApp);
expect(app).toBeInstanceOf(WarpApp);
expect(app.core()).toBeInstanceOf(WarpCore);
expect('materialize' in app).toBe(false);
expect('query' in app).toBe(false);
expect('traverse' in app).toBe(false);

await app.core().materialize();
const content = await app.getContent('doc:readme');
expect(content).toBeInstanceOf(Uint8Array);
expect(new TextDecoder().decode(content ?? new Uint8Array())).toBe('hello from the app facade');
});

it('keeps WarpCore as the explicit substrate escape hatch with representative writes and reads', async () => {
const core = await WarpCore.open(openOptions('public-reading-core', 'writer-core'));

await core.patch((patch) => {
patch.addNode('core:node');
patch.setProperty('core:node', 'status', 'open');
});
await core.materialize();

expect(core).toBeInstanceOf(WarpCore);
expect(typeof core.materialize).toBe('function');
expect(typeof core.createPatch).toBe('function');
expect(typeof core.syncWith).toBe('function');
await expect(core.hasNode('core:node')).resolves.toBe(true);
await expect(core.getNodeProps('core:node')).resolves.toEqual({ status: 'open' });
});
});
131 changes: 131 additions & 0 deletions test/unit/scripts/v17-migration-script-behavior.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import { execFile, type ExecFileException } from 'node:child_process';
import { mkdtemp, mkdir, readFile, rm, writeFile } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { join, relative } from 'node:path';
import { fileURLToPath } from 'node:url';
import { describe, expect, it } from 'vitest';
import { walkMigrationFiles } from '../../../scripts/migrations/v17.0.0/MigrationFileWalker.ts';

const REPO_ROOT = fileURLToPath(new URL('../../../', import.meta.url));

type ScriptResult = {
readonly exitCode: number;
readonly stdout: string;
readonly stderr: string;
};

class MigrationFixture {
readonly samplePath: string;

constructor(readonly root: string) {
this.samplePath = join(root, 'src', 'sample.ts');
}

async sampleSource(): Promise<string> {
return await readFile(this.samplePath, 'utf8');
}
}

async function withMigrationFixture(
test: (fixture: MigrationFixture) => Promise<void>,
): Promise<void> {
const root = await mkdtemp(join(tmpdir(), 'warp-v17-migration-'));
try {
await mkdir(join(root, 'src', 'nested'), { recursive: true });
await mkdir(join(root, 'node_modules', 'ignored'), { recursive: true });
await mkdir(join(root, '.git', 'ignored'), { recursive: true });
await writeFile(
join(root, 'src', 'sample.ts'),
[
"import { PatchBuilderV2, PatchV2, Lens } from '@git-stunts/git-warp/services/PatchBuilderV2.js';",
'const patch: PatchV2 = new PatchBuilderV2();',
'function useAperture(aperture: Lens): Lens { return aperture; }',
'void patch;',
'void useAperture;',
'',
].join('\n'),
'utf8',
);
await writeFile(join(root, 'src', 'nested', 'extra.js'), 'const ok = true;\n', 'utf8');
await writeFile(join(root, 'README.md'), 'PatchV2 should not be scanned here.\n', 'utf8');
await writeFile(join(root, 'node_modules', 'ignored', 'package.ts'), 'const stale: PatchV2 = null;\n', 'utf8');
await writeFile(join(root, '.git', 'ignored', 'hook.ts'), 'const stale: PatchV2 = null;\n', 'utf8');

await test(new MigrationFixture(root));
} finally {
await rm(root, { recursive: true, force: true });
}
}

function runMigrationScript(scriptPath: string, args: readonly string[]): Promise<ScriptResult> {
return new Promise((resolve) => {
execFile(
process.execPath,
[join(REPO_ROOT, scriptPath), ...args],
{ cwd: REPO_ROOT, encoding: 'utf8' },
(error: ExecFileException | null, stdout: string, stderr: string) => {
const exitCode = typeof error?.code === 'number' ? error.code : 0;
resolve({ exitCode, stdout, stderr });
},
);
});
}

describe('v17 migration script behavior', () => {
it('walks migration source files while skipping markdown, node_modules, and git internals', async () => {
await withMigrationFixture(async (fixture) => {
const visited: string[] = [];

for await (const filePath of walkMigrationFiles(fixture.root)) {
visited.push(relative(fixture.root, filePath));
}

expect(visited.sort()).toEqual([
'src/nested/extra.js',
'src/sample.ts',
]);
});
});

it('reports stale v16 APIs, rewrites them, and verifies the migrated fixture', async () => {
await withMigrationFixture(async (fixture) => {
const stale = await runMigrationScript('scripts/migrations/v17.0.0/verify.ts', [
'--dir',
fixture.root,
]);
expect(stale.exitCode).toBe(1);
expect(stale.stdout).toContain('PatchBuilderV2.js renamed to PatchBuilder.ts');
expect(stale.stdout).toContain('PatchV2 renamed to Patch');

const imports = await runMigrationScript('scripts/migrations/v17.0.0/fix-imports.ts', [
'--dir',
fixture.root,
]);
expect(imports).toMatchObject({ exitCode: 0, stderr: '' });
expect(imports.stdout).toContain('1 imports updated across 1 files');

const renames = await runMigrationScript('scripts/migrations/v17.0.0/fix-renames.ts', [
'--dir',
fixture.root,
]);
expect(renames).toMatchObject({ exitCode: 0, stderr: '' });
expect(renames.stdout).toContain('3 renames across 1 files');

const migrated = await fixture.sampleSource();
expect(migrated).toContain("from '@git-stunts/git-warp/services/PatchBuilder.ts'");
expect(migrated).toContain('PatchBuilder');
expect(migrated).toContain('Patch');
expect(migrated).toContain('Aperture');
expect(migrated).not.toContain('PatchBuilderV2');
expect(migrated).not.toContain('PatchV2');
expect(migrated).not.toContain('Lens');

const clean = await runMigrationScript('scripts/migrations/v17.0.0/verify.ts', [
'--dir',
fixture.root,
]);
expect(clean).toMatchObject({ exitCode: 0, stderr: '' });
expect(clean.stdout).toContain('No v16 migration issues found');
});
});
});
Loading
Loading