zelari-code 2.1.0 → 2.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/package.json +8 -5
- package/dist/cli/ast/engine.test.js +0 -101
- package/dist/cli/ast/engine.test.js.map +0 -1
- package/dist/cli/ast/tools.test.js +0 -124
- package/dist/cli/ast/tools.test.js.map +0 -1
- package/dist/cli/headless.test.js +0 -107
- package/dist/cli/headless.test.js.map +0 -1
- package/dist/cli/headlessE2eSession.test.js +0 -189
- package/dist/cli/headlessE2eSession.test.js.map +0 -1
- package/dist/cli/headlessHistorySeed.test.js +0 -158
- package/dist/cli/headlessHistorySeed.test.js.map +0 -1
- package/dist/cli/headlessSessionEvent.test.js +0 -83
- package/dist/cli/headlessSessionEvent.test.js.map +0 -1
- package/dist/cli/headlessSpine.test.js +0 -153
- package/dist/cli/headlessSpine.test.js.map +0 -1
- package/dist/cli/hooks/observationStore.test.js +0 -135
- package/dist/cli/hooks/observationStore.test.js.map +0 -1
- package/dist/cli/hooks/sessionSurface.test.js +0 -112
- package/dist/cli/hooks/sessionSurface.test.js.map +0 -1
- package/dist/cli/kraken/candidateRegistry.test.js +0 -211
- package/dist/cli/kraken/candidateRegistry.test.js.map +0 -1
- package/dist/cli/kraken/completionGate.test.js +0 -172
- package/dist/cli/kraken/completionGate.test.js.map +0 -1
- package/dist/cli/kraken/evidenceAnchoring.test.js +0 -92
- package/dist/cli/kraken/evidenceAnchoring.test.js.map +0 -1
- package/dist/cli/kraken/evidenceProvenance.test.js +0 -113
- package/dist/cli/kraken/evidenceProvenance.test.js.map +0 -1
- package/dist/cli/kraken/executor.workbench.test.js +0 -134
- package/dist/cli/kraken/executor.workbench.test.js.map +0 -1
- package/dist/cli/kraken/metrics.test.js +0 -145
- package/dist/cli/kraken/metrics.test.js.map +0 -1
- package/dist/cli/kraken/nativeVerification.test.js +0 -207
- package/dist/cli/kraken/nativeVerification.test.js.map +0 -1
- package/dist/cli/kraken/planner.test.js +0 -43
- package/dist/cli/kraken/planner.test.js.map +0 -1
- package/dist/cli/kraken/scriptPlanner.test.js +0 -152
- package/dist/cli/kraken/scriptPlanner.test.js.map +0 -1
- package/dist/cli/kraken/selectionPlaybook.test.js +0 -55
- package/dist/cli/kraken/selectionPlaybook.test.js.map +0 -1
- package/dist/cli/kraken/skillSuggest.test.js +0 -157
- package/dist/cli/kraken/skillSuggest.test.js.map +0 -1
- package/dist/cli/kraken/strictDefaults.test.js +0 -149
- package/dist/cli/kraken/strictDefaults.test.js.map +0 -1
- package/dist/cli/kraken/strictGatePackIndependence.test.js +0 -112
- package/dist/cli/kraken/strictGatePackIndependence.test.js.map +0 -1
- package/dist/cli/kraken/turnRuntime.test.js +0 -377
- package/dist/cli/kraken/turnRuntime.test.js.map +0 -1
- package/dist/cli/kraken/verificationBridge.session.test.js +0 -104
- package/dist/cli/kraken/verificationBridge.session.test.js.map +0 -1
- package/dist/cli/kraken/verificationBridge.test.js +0 -177
- package/dist/cli/kraken/verificationBridge.test.js.map +0 -1
- package/dist/cli/kraken/verifier.test.js +0 -232
- package/dist/cli/kraken/verifier.test.js.map +0 -1
- package/dist/cli/kraken/verifierAdvisoryLock.test.js +0 -154
- package/dist/cli/kraken/verifierAdvisoryLock.test.js.map +0 -1
- package/dist/cli/kraken/verifierLifecycle.test.js +0 -181
- package/dist/cli/kraken/verifierLifecycle.test.js.map +0 -1
- package/dist/cli/kraken/verifierRoundTrip.test.js +0 -166
- package/dist/cli/kraken/verifierRoundTrip.test.js.map +0 -1
- package/dist/cli/kraken/verifierSettings.test.js +0 -237
- package/dist/cli/kraken/verifierSettings.test.js.map +0 -1
- package/dist/cli/kraken/verifyReport.test.js +0 -111
- package/dist/cli/kraken/verifyReport.test.js.map +0 -1
- package/dist/cli/kraken/weaknessMeter.test.js +0 -212
- package/dist/cli/kraken/weaknessMeter.test.js.map +0 -1
- package/dist/cli/kraken/workbench.test.js +0 -253
- package/dist/cli/kraken/workbench.test.js.map +0 -1
- package/dist/cli/kraken/workbenchView.test.js +0 -130
- package/dist/cli/kraken/workbenchView.test.js.map +0 -1
- package/dist/cli/legacyContextIsolation.test.js +0 -65
- package/dist/cli/legacyContextIsolation.test.js.map +0 -1
- package/dist/cli/lsp/tools.test.js +0 -90
- package/dist/cli/lsp/tools.test.js.map +0 -1
- package/dist/cli/missionContinuation.test.js +0 -117
- package/dist/cli/missionContinuation.test.js.map +0 -1
- package/dist/cli/profileMatrix.test.js +0 -130
- package/dist/cli/profileMatrix.test.js.map +0 -1
- package/dist/cli/provider/capabilities.test.js +0 -46
- package/dist/cli/provider/capabilities.test.js.map +0 -1
- package/dist/cli/provider/openai-compatible.timeout.test.js +0 -72
- package/dist/cli/provider/openai-compatible.timeout.test.js.map +0 -1
- package/dist/cli/providerConfig.test.js +0 -85
- package/dist/cli/providerConfig.test.js.map +0 -1
- package/dist/cli/sessionReplayInvariant.test.js +0 -187
- package/dist/cli/sessionReplayInvariant.test.js.map +0 -1
- package/dist/cli/sessionSpine.test.js +0 -171
- package/dist/cli/sessionSpine.test.js.map +0 -1
- package/dist/cli/thinking.test.js +0 -214
- package/dist/cli/thinking.test.js.map +0 -1
- package/dist/cli/tools/inspectCommand.schema.test.js +0 -82
- package/dist/cli/tools/inspectCommand.schema.test.js.map +0 -1
- package/dist/cli/tools/inspectCommand.test.js +0 -311
- package/dist/cli/tools/inspectCommand.test.js.map +0 -1
- package/dist/cli/tools/krakenCsvFanout.test.js +0 -200
- package/dist/cli/tools/krakenCsvFanout.test.js.map +0 -1
- package/dist/cli/tools/krakenSelectTool.test.js +0 -246
- package/dist/cli/tools/krakenSelectTool.test.js.map +0 -1
- package/dist/cli/tools/observeBatch.test.js +0 -329
- package/dist/cli/tools/observeBatch.test.js.map +0 -1
- package/dist/cli/tools/taskTool.dynamicChecks.test.js +0 -156
- package/dist/cli/tools/taskTool.dynamicChecks.test.js.map +0 -1
- package/dist/cli/tools/taskTool.planSafety.test.js +0 -280
- package/dist/cli/tools/taskTool.planSafety.test.js.map +0 -1
- package/dist/cli/tools/taskTool.verifyReport.test.js +0 -140
- package/dist/cli/tools/taskTool.verifyReport.test.js.map +0 -1
- package/dist/cli/utils/contextGrowthSummary.test.js +0 -74
- package/dist/cli/utils/contextGrowthSummary.test.js.map +0 -1
- package/dist/cli/workspace/planDriftCheck.test.js +0 -146
- package/dist/cli/workspace/planDriftCheck.test.js.map +0 -1
- package/dist/cli/workspace/planStore.test.js +0 -295
- package/dist/cli/workspace/planStore.test.js.map +0 -1
- package/dist/cli/zelariMission.test.js +0 -44
- package/dist/cli/zelariMission.test.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"capabilities.test.js","sourceRoot":"","sources":["../../../src/cli/provider/capabilities.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { readChunkWithTimeout } from './openai-compatible.js';
|
|
3
|
-
/**
|
|
4
|
-
* Regression: the stream idle timeout used to reset on EVERY network chunk,
|
|
5
|
-
* including SSE keep-alive frames that carry no content (blank lines, `: ping`,
|
|
6
|
-
* `data:` with no choices). A stalled model behind a keep-alive gateway looked
|
|
7
|
-
* "alive" forever: process hung 20+ min with an ESTABLISHED socket and zero
|
|
8
|
-
* tokens, and the 5-min idle timeout never fired because keep-alives kept
|
|
9
|
-
* resetting it. The idle budget now measures silence since the last *useful*
|
|
10
|
-
* delta (text/thinking/tool_call/usage), so keep-alives cannot mask a stall.
|
|
11
|
-
*/
|
|
12
|
-
function makeStream(chunk) {
|
|
13
|
-
const encoder = new TextEncoder();
|
|
14
|
-
let timer;
|
|
15
|
-
const stream = new ReadableStream({
|
|
16
|
-
start(controller) {
|
|
17
|
-
timer = setInterval(() => {
|
|
18
|
-
try {
|
|
19
|
-
controller.enqueue(encoder.encode(chunk));
|
|
20
|
-
}
|
|
21
|
-
catch {
|
|
22
|
-
// Controller already closed (reader cancelled) — stop the timer.
|
|
23
|
-
if (timer)
|
|
24
|
-
clearInterval(timer);
|
|
25
|
-
}
|
|
26
|
-
}, 10);
|
|
27
|
-
},
|
|
28
|
-
});
|
|
29
|
-
return {
|
|
30
|
-
reader: stream.getReader(),
|
|
31
|
-
stop: () => {
|
|
32
|
-
if (timer)
|
|
33
|
-
clearInterval(timer);
|
|
34
|
-
},
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
describe('readChunkWithTimeout idle budget', () => {
|
|
38
|
-
it('fires idle timeout even when keep-alive frames keep arriving (no content)', async () => {
|
|
39
|
-
const { reader, stop } = makeStream(':\n\n'); // SSE comment = keep-alive
|
|
40
|
-
const lastUsefulAt = Date.now() - 5_000; // last useful delta 5s ago
|
|
41
|
-
const deadline = Date.now() + 30_000;
|
|
42
|
-
const started = Date.now();
|
|
43
|
-
await expect(readChunkWithTimeout(reader, {
|
|
44
|
-
idleMs: 2_000,
|
|
45
|
-
deadlineMs: deadline,
|
|
46
|
-
lastUsefulAt: () => lastUsefulAt,
|
|
47
|
-
})).rejects.toThrow(/idle/);
|
|
48
|
-
// The timeout must fire promptly (not wait for the absolute deadline),
|
|
49
|
-
// because the idle budget is already exhausted.
|
|
50
|
-
expect(Date.now() - started).toBeLessThan(1_000);
|
|
51
|
-
await reader.cancel('test done');
|
|
52
|
-
stop();
|
|
53
|
-
});
|
|
54
|
-
it('does NOT fire idle when useful content keeps the budget fresh', async () => {
|
|
55
|
-
const { reader, stop } = makeStream('data: {"choices":[{"delta":{"content":"x"}}]}\n\n');
|
|
56
|
-
let lastUsefulAt = Date.now();
|
|
57
|
-
// Read 3 chunks; with each chunk the caller would markUseful(), so the
|
|
58
|
-
// idle budget never runs out. A single read returns the chunk.
|
|
59
|
-
for (let i = 0; i < 3; i += 1) {
|
|
60
|
-
const res = await readChunkWithTimeout(reader, {
|
|
61
|
-
idleMs: 2_000,
|
|
62
|
-
deadlineMs: Date.now() + 30_000,
|
|
63
|
-
lastUsefulAt: () => lastUsefulAt,
|
|
64
|
-
});
|
|
65
|
-
expect(res.done).toBe(false);
|
|
66
|
-
lastUsefulAt = Date.now(); // simulate markUseful()
|
|
67
|
-
}
|
|
68
|
-
await reader.cancel('test done');
|
|
69
|
-
stop();
|
|
70
|
-
});
|
|
71
|
-
});
|
|
72
|
-
//# sourceMappingURL=openai-compatible.timeout.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"openai-compatible.timeout.test.js","sourceRoot":"","sources":["../../../src/cli/provider/openai-compatible.timeout.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
2
|
-
import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
3
|
-
import os from 'node:os';
|
|
4
|
-
import path from 'node:path';
|
|
5
|
-
import { getProviderConfig, loadProviderConfig, setKrakenVerifier, clearKrakenVerifier, setCustomEndpoint, setActiveProviderId, } from './providerConfig.js';
|
|
6
|
-
const ENV_KEYS = ['ANATHEMA_PROVIDER_CONFIG_FILE', 'ANATHEMA_ACTIVE_PROVIDER', 'OPENAI_MODEL'];
|
|
7
|
-
/**
|
|
8
|
-
* Exit-0 E0.2 — sync/async round-trip parity for provider config.
|
|
9
|
-
* Regression guard for E0.1: `loadProviderConfig()` (async) used to silently
|
|
10
|
-
* drop `krakenVerifier` and skip env overrides on the fallback path.
|
|
11
|
-
*/
|
|
12
|
-
describe('providerConfig sync/async round-trip (E0.1/E0.2)', () => {
|
|
13
|
-
let tmpDir;
|
|
14
|
-
let savedEnv;
|
|
15
|
-
beforeEach(() => {
|
|
16
|
-
tmpDir = mkdtempSync(path.join(os.tmpdir(), 'zelari-providerconfig-'));
|
|
17
|
-
savedEnv = {};
|
|
18
|
-
for (const key of ENV_KEYS)
|
|
19
|
-
savedEnv[key] = process.env[key];
|
|
20
|
-
process.env.ANATHEMA_PROVIDER_CONFIG_FILE = path.join(tmpDir, 'provider.json');
|
|
21
|
-
delete process.env.ANATHEMA_ACTIVE_PROVIDER;
|
|
22
|
-
delete process.env.OPENAI_MODEL;
|
|
23
|
-
});
|
|
24
|
-
afterEach(() => {
|
|
25
|
-
for (const key of ENV_KEYS) {
|
|
26
|
-
if (savedEnv[key] === undefined)
|
|
27
|
-
delete process.env[key];
|
|
28
|
-
else
|
|
29
|
-
process.env[key] = savedEnv[key];
|
|
30
|
-
}
|
|
31
|
-
rmSync(tmpDir, { recursive: true, force: true });
|
|
32
|
-
});
|
|
33
|
-
it('a dedicated krakenVerifier survives an async load (E0.1 regression)', async () => {
|
|
34
|
-
setKrakenVerifier('anthropic', 'claude-sonnet-4-6');
|
|
35
|
-
const asyncCfg = await loadProviderConfig();
|
|
36
|
-
expect(asyncCfg.krakenVerifier).toEqual({ provider: 'anthropic', model: 'claude-sonnet-4-6' });
|
|
37
|
-
});
|
|
38
|
-
it('clearKrakenVerifier → back to inherit on both sync and async paths', async () => {
|
|
39
|
-
setKrakenVerifier('grok', 'grok-4.6');
|
|
40
|
-
clearKrakenVerifier();
|
|
41
|
-
expect(getProviderConfig().krakenVerifier).toBeUndefined();
|
|
42
|
-
expect((await loadProviderConfig()).krakenVerifier).toBeUndefined();
|
|
43
|
-
});
|
|
44
|
-
it('sync and async loads are deep-equal for a populated config', async () => {
|
|
45
|
-
setActiveProviderId('grok');
|
|
46
|
-
setCustomEndpoint('openai-compatible', 'http://localhost:11434/v1');
|
|
47
|
-
setKrakenVerifier('anthropic', 'claude-sonnet-4-6');
|
|
48
|
-
expect(await loadProviderConfig()).toEqual(getProviderConfig());
|
|
49
|
-
});
|
|
50
|
-
it('env overrides win on both paths (async fallback included)', async () => {
|
|
51
|
-
setActiveProviderId('grok');
|
|
52
|
-
process.env.ANATHEMA_ACTIVE_PROVIDER = 'anthropic';
|
|
53
|
-
process.env.OPENAI_MODEL = 'claude-opus-4-6';
|
|
54
|
-
const syncCfg = getProviderConfig();
|
|
55
|
-
const asyncCfg = await loadProviderConfig();
|
|
56
|
-
for (const cfg of [syncCfg, asyncCfg]) {
|
|
57
|
-
expect(cfg.activeProviderId).toBe('anthropic');
|
|
58
|
-
expect(cfg.modelByProvider['anthropic']).toBe('claude-opus-4-6');
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
it('missing file → cloned defaults, no shared mutable state across loads', async () => {
|
|
62
|
-
const first = await loadProviderConfig();
|
|
63
|
-
first.modelByProvider['grok'] = 'MUTATED';
|
|
64
|
-
const second = getProviderConfig();
|
|
65
|
-
expect(second.modelByProvider['grok']).not.toBe('MUTATED');
|
|
66
|
-
});
|
|
67
|
-
it('corrupt file → defaults on both paths', async () => {
|
|
68
|
-
writeFileSync(path.join(tmpDir, 'provider.json'), '{ not json', 'utf-8');
|
|
69
|
-
const asyncCfg = await loadProviderConfig();
|
|
70
|
-
const syncCfg = getProviderConfig();
|
|
71
|
-
expect(asyncCfg.activeProviderId).toBe(syncCfg.activeProviderId);
|
|
72
|
-
expect(asyncCfg.modelByProvider).toEqual(syncCfg.modelByProvider);
|
|
73
|
-
expect(asyncCfg.krakenVerifier).toBeUndefined();
|
|
74
|
-
});
|
|
75
|
-
it('hand-edited partial krakenVerifier blob is dropped by both paths', async () => {
|
|
76
|
-
writeFileSync(path.join(tmpDir, 'provider.json'), JSON.stringify({
|
|
77
|
-
activeProviderId: 'grok',
|
|
78
|
-
modelByProvider: { grok: 'grok-4.6' },
|
|
79
|
-
krakenVerifier: { provider: 'anthropic' }, // model missing → invalid, must fall back to inherit
|
|
80
|
-
}), 'utf-8');
|
|
81
|
-
expect(getProviderConfig().krakenVerifier).toBeUndefined();
|
|
82
|
-
expect((await loadProviderConfig()).krakenVerifier).toBeUndefined();
|
|
83
|
-
});
|
|
84
|
-
});
|
|
85
|
-
//# sourceMappingURL=providerConfig.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"providerConfig.test.js","sourceRoot":"","sources":["../../src/cli/providerConfig.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* sessionReplayInvariant — Exit-1 gate E1.6 + E1.7 (CI-required).
|
|
3
|
-
*
|
|
4
|
-
* E1.6 (replay determinismo): a scripted multi-turn run must reconstruct
|
|
5
|
-
* entirely from `events.jsonl` alone — replay → deriveMessages →
|
|
6
|
-
* derivedModelSeed is deterministic and semantic-equal to the documented
|
|
7
|
-
* mapping (compacted → user, orphan tool results dropped, assistant
|
|
8
|
-
* scrubbed with the binding policy).
|
|
9
|
-
*
|
|
10
|
-
* E1.7 (invariante P1, ADR-0016): model-visible ⟺ logged.
|
|
11
|
-
* forward: every message that feeds the harness traces back to a
|
|
12
|
-
* MODEL_SURFACE event by seq;
|
|
13
|
-
* backward: every model-surface event either lands in the derived
|
|
14
|
-
* history or is excluded by a declared, tested policy.
|
|
15
|
-
*/
|
|
16
|
-
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
17
|
-
import { promises as fs } from 'node:fs';
|
|
18
|
-
import path from 'node:path';
|
|
19
|
-
import os from 'node:os';
|
|
20
|
-
import { SessionSpineMirror } from './sessionSpine.js';
|
|
21
|
-
import { openHeadlessSpine, seedHeadlessModelHistory, derivedModelSeed, } from './headlessSpine.js';
|
|
22
|
-
import { readSessionLog, deriveMessages, isModelSurfaceEvent, resolveSessionsDir, } from '@zelari/core/session';
|
|
23
|
-
let tmp;
|
|
24
|
-
beforeEach(async () => {
|
|
25
|
-
tmp = await fs.mkdtemp(path.join(os.tmpdir(), 'zelari-replay-inv-'));
|
|
26
|
-
});
|
|
27
|
-
afterEach(async () => {
|
|
28
|
-
await fs.rm(tmp, { recursive: true, force: true });
|
|
29
|
-
});
|
|
30
|
-
function eventsPath(sessionId) {
|
|
31
|
-
return path.join(resolveSessionsDir({ baseDir: tmp }), sessionId, 'events.jsonl');
|
|
32
|
-
}
|
|
33
|
-
function brainEvent(type, rest = {}) {
|
|
34
|
-
return { type, id: `id-${type}`, ts: 1_755_000_000_000, sessionId: 's1', ...rest };
|
|
35
|
-
}
|
|
36
|
-
/** Replay the raw JSONL without touching any writer (cross-process view). */
|
|
37
|
-
async function replay(sessionId) {
|
|
38
|
-
const report = await readSessionLog(eventsPath(sessionId));
|
|
39
|
-
expect(report.ok).toBe(true);
|
|
40
|
-
expect(report.issues).toEqual([]);
|
|
41
|
-
return report.events;
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Script a full headless-shaped run: legacy import, one live turn with a
|
|
45
|
-
* streamed assistant reply (message_end coalescer) plus a tool call/result,
|
|
46
|
-
* then a compaction — the whole model-surface zoo.
|
|
47
|
-
*/
|
|
48
|
-
async function runScriptedSession(sessionId) {
|
|
49
|
-
const handle = await openHeadlessSpine({ sessionId, baseDir: tmp, quiet: true });
|
|
50
|
-
const legacy = [
|
|
51
|
-
{ role: 'user', content: 'legacy-u1' },
|
|
52
|
-
{ role: 'assistant', content: 'legacy-a1' },
|
|
53
|
-
];
|
|
54
|
-
const seed = await seedHeadlessModelHistory(handle, legacy);
|
|
55
|
-
expect(seed.source).toBe('spine-import');
|
|
56
|
-
// Live turn 1 — exactly the order runHeadless wires them.
|
|
57
|
-
handle.userMessage('turn-1 task');
|
|
58
|
-
handle.spine.mirrorBrainEvent(brainEvent('message_delta', { messageId: 'm1', delta: '<think>x</think>' }));
|
|
59
|
-
handle.spine.mirrorBrainEvent(brainEvent('message_delta', { messageId: 'm1', delta: 'turn-1 reply' }));
|
|
60
|
-
handle.spine.mirrorBrainEvent(brainEvent('message_end', { messageId: 'm1', finishReason: 'stop' }));
|
|
61
|
-
handle.spine.mirrorBrainEvent(brainEvent('tool_execution_start', { toolCallId: 'c1', toolName: 'bash', args: { command: 'ls' } }));
|
|
62
|
-
handle.spine.mirrorBrainEvent(brainEvent('tool_execution_end', { toolCallId: 'c1', result: 'file-a file-b', isError: false }));
|
|
63
|
-
handle.spine.mirrorBrainEvent(brainEvent('session_compacted', { summary: 'compacted-context' }));
|
|
64
|
-
await handle.spine.flush();
|
|
65
|
-
return handle;
|
|
66
|
-
}
|
|
67
|
-
describe('Exit-1/E1.6 — replay determinismo (log → deriveMessages → seed)', () => {
|
|
68
|
-
it('reconstructs the whole run from events.jsonl alone (cross-process resume)', async () => {
|
|
69
|
-
const handle = await runScriptedSession('inv-e16-a');
|
|
70
|
-
await handle.close('test-end');
|
|
71
|
-
// New adopt on the same log — no shared memory with the scripted run.
|
|
72
|
-
const reopened = await SessionSpineMirror.adopt('inv-e16-a', { baseDir: tmp, quiet: true });
|
|
73
|
-
expect(reopened.status).toBe('active');
|
|
74
|
-
const derived = await reopened.derivedPriorTurns();
|
|
75
|
-
expect(derived).not.toBeNull();
|
|
76
|
-
// Independent derive straight from the raw file must agree exactly.
|
|
77
|
-
const fromFile = deriveMessages(await replay('inv-e16-a'));
|
|
78
|
-
expect(derived).toEqual(fromFile);
|
|
79
|
-
const roleContent = derived.map((m) => `${m.role}:${m.content}`);
|
|
80
|
-
expect(roleContent).toEqual([
|
|
81
|
-
'user:legacy-u1',
|
|
82
|
-
'assistant:legacy-a1',
|
|
83
|
-
'user:turn-1 task',
|
|
84
|
-
'assistant:<think>x</think>turn-1 reply',
|
|
85
|
-
'tool:file-a file-b', // derived neutral history keeps tool results…
|
|
86
|
-
'system:compacted-context', // …and compaction, before the seed policy maps them
|
|
87
|
-
]);
|
|
88
|
-
await reopened.close('test-end');
|
|
89
|
-
});
|
|
90
|
-
it('derives deterministically: two replays of the same log are deep-equal', async () => {
|
|
91
|
-
const handle = await runScriptedSession('inv-e16-b');
|
|
92
|
-
await handle.close('test-end');
|
|
93
|
-
const first = deriveMessages(await replay('inv-e16-b'));
|
|
94
|
-
const second = deriveMessages(await replay('inv-e16-b'));
|
|
95
|
-
expect(first).toEqual(second);
|
|
96
|
-
});
|
|
97
|
-
it('seed policy is the documented semantic-equal mapping', async () => {
|
|
98
|
-
const handle = await runScriptedSession('inv-e16-c');
|
|
99
|
-
await handle.close('test-end');
|
|
100
|
-
const derived = deriveMessages(await replay('inv-e16-c'));
|
|
101
|
-
const seed = derivedModelSeed(derived);
|
|
102
|
-
expect(seed.map((m) => `${m.role}:${m.content}`)).toEqual([
|
|
103
|
-
'user:legacy-u1',
|
|
104
|
-
'assistant:legacy-a1',
|
|
105
|
-
'user:turn-1 task',
|
|
106
|
-
'assistant:<think>x</think>turn-1 reply', // binding policy: <think> preserved
|
|
107
|
-
'user:compacted-context', // compacted summary → user (1.x store convention)
|
|
108
|
-
// tool result dropped: orphan role 'tool' without a paired tool_calls block
|
|
109
|
-
]);
|
|
110
|
-
});
|
|
111
|
-
});
|
|
112
|
-
describe('Exit-1/E1.7 — invariante model-visible ⟺ logged (P1)', () => {
|
|
113
|
-
it('forward: every derived message traces to a model-surface event by seq', async () => {
|
|
114
|
-
const handle = await runScriptedSession('inv-e17-a');
|
|
115
|
-
await handle.close('test-end');
|
|
116
|
-
const events = await replay('inv-e17-a');
|
|
117
|
-
const derived = deriveMessages(events);
|
|
118
|
-
expect(derived.length).toBeGreaterThan(0);
|
|
119
|
-
for (const m of derived) {
|
|
120
|
-
const source = events.find((e) => e.seq === m.seq);
|
|
121
|
-
expect(source, `seq ${m.seq} must exist in the log`).toBeDefined();
|
|
122
|
-
expect(isModelSurfaceEvent(source)).toBe(true);
|
|
123
|
-
const expectedRole = source.kind === 'user.message'
|
|
124
|
-
? 'user'
|
|
125
|
-
: source.kind === 'assistant.message'
|
|
126
|
-
? 'assistant'
|
|
127
|
-
: source.kind === 'session.compacted'
|
|
128
|
-
? 'system'
|
|
129
|
-
: 'tool';
|
|
130
|
-
expect(m.role).toBe(expectedRole);
|
|
131
|
-
}
|
|
132
|
-
});
|
|
133
|
-
it('backward: every model-surface event reaches the derived history or is excluded by declared policy', async () => {
|
|
134
|
-
const handle = await runScriptedSession('inv-e17-b');
|
|
135
|
-
await handle.close('test-end');
|
|
136
|
-
const events = await replay('inv-e17-b');
|
|
137
|
-
const derived = deriveMessages(events);
|
|
138
|
-
const derivedSeqs = new Set(derived.map((m) => m.seq));
|
|
139
|
-
const surface = events.filter(isModelSurfaceEvent);
|
|
140
|
-
expect(surface.length).toBeGreaterThan(0);
|
|
141
|
-
for (const e of surface) {
|
|
142
|
-
// tool.call is the only surface kind the neutral derive drops by
|
|
143
|
-
// default (includeToolCalls=false) — everything else must map.
|
|
144
|
-
if (e.kind === 'tool.call')
|
|
145
|
-
continue;
|
|
146
|
-
expect(derivedSeqs.has(e.seq), `${e.kind}@${e.seq} must derive`).toBe(true);
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
|
-
it('next-turn harness history rebuilds from the spine alone after the run', async () => {
|
|
150
|
-
const handle = await runScriptedSession('inv-e17-c');
|
|
151
|
-
// Turn 2 wiring, exactly as runHeadless does: seed BEFORE the prompt log.
|
|
152
|
-
const seed = await seedHeadlessModelHistory(handle, []);
|
|
153
|
-
expect(seed.source).toBe('spine');
|
|
154
|
-
handle.userMessage('turn-2 task');
|
|
155
|
-
handle.spine.mirrorBrainEvent(brainEvent('message_delta', { messageId: 'm2', delta: 'turn-2 reply' }));
|
|
156
|
-
handle.spine.mirrorBrainEvent(brainEvent('message_end', { messageId: 'm2', finishReason: 'stop' }));
|
|
157
|
-
await handle.spine.flush();
|
|
158
|
-
// What the harness of turn 2 saw is the seed plus the current prompt.
|
|
159
|
-
// Forward invariant on live wiring: every seed message — user,
|
|
160
|
-
// assistant, compacted-summary-as-user — traces to a logged
|
|
161
|
-
// model-surface event, and log order matches turn order.
|
|
162
|
-
const surface = (await replay('inv-e17-c')).filter(isModelSurfaceEvent);
|
|
163
|
-
const loggedTexts = surface.map((e) => String(e.data.text ??
|
|
164
|
-
e.data.summary ??
|
|
165
|
-
''));
|
|
166
|
-
const texts = loggedTexts.filter((t) => ['legacy-u1', 'turn-1 task', 'turn-2 task'].includes(t));
|
|
167
|
-
expect(texts).toEqual(['legacy-u1', 'turn-1 task', 'turn-2 task']);
|
|
168
|
-
for (const m of seed.history) {
|
|
169
|
-
expect(loggedTexts).toContain(m.content);
|
|
170
|
-
}
|
|
171
|
-
expect(texts.indexOf('turn-1 task')).toBeLessThan(texts.indexOf('turn-2 task'));
|
|
172
|
-
await handle.close('test-end');
|
|
173
|
-
const turn3 = await SessionSpineMirror.adopt('inv-e17-c', { baseDir: tmp, quiet: true });
|
|
174
|
-
const seed3 = derivedModelSeed((await turn3.derivedPriorTurns()) ?? []);
|
|
175
|
-
expect(seed3.map((m) => m.content)).toEqual([
|
|
176
|
-
'legacy-u1',
|
|
177
|
-
'legacy-a1',
|
|
178
|
-
'turn-1 task',
|
|
179
|
-
'<think>x</think>turn-1 reply',
|
|
180
|
-
'compacted-context',
|
|
181
|
-
'turn-2 task',
|
|
182
|
-
'turn-2 reply',
|
|
183
|
-
]);
|
|
184
|
-
await turn3.close('test-end');
|
|
185
|
-
});
|
|
186
|
-
});
|
|
187
|
-
//# sourceMappingURL=sessionReplayInvariant.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sessionReplayInvariant.test.js","sourceRoot":"","sources":["../../src/cli/sessionReplayInvariant.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* sessionSpine tests — dual-write bridge onto the 2.0 session spine.
|
|
3
|
-
*
|
|
4
|
-
* Covers: BrainEvent→spine mapping, adopt/resume seq continuation, ownership
|
|
5
|
-
* lock, message-delta coalescing, user.message logging (the P1 gap), the
|
|
6
|
-
* declared-discrete-fallback degradation, and the kill switch.
|
|
7
|
-
*/
|
|
8
|
-
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
9
|
-
import { promises as fs } from 'node:fs';
|
|
10
|
-
import path from 'node:path';
|
|
11
|
-
import os from 'node:os';
|
|
12
|
-
import { SessionSpineMirror, mapBrainEventToSpine, resumeSpineContext, spineEnabled, } from './sessionSpine.js';
|
|
13
|
-
import { readSessionLog } from '@zelari/core/session';
|
|
14
|
-
let tmp;
|
|
15
|
-
beforeEach(async () => {
|
|
16
|
-
tmp = await fs.mkdtemp(path.join(os.tmpdir(), 'zelari-spine-'));
|
|
17
|
-
});
|
|
18
|
-
afterEach(async () => {
|
|
19
|
-
await fs.rm(tmp, { recursive: true, force: true });
|
|
20
|
-
});
|
|
21
|
-
function ev(type, rest = {}) {
|
|
22
|
-
return { type, id: `id-${type}`, ts: 1_755_000_000_000, sessionId: 's1', ...rest };
|
|
23
|
-
}
|
|
24
|
-
describe('mapBrainEventToSpine', () => {
|
|
25
|
-
it('maps tool_execution_start → tool.call with tool/args/callId', () => {
|
|
26
|
-
const mapped = mapBrainEventToSpine(ev('tool_execution_start', { toolCallId: 'c1', toolName: 'bash', args: { command: 'ls' } }));
|
|
27
|
-
expect(mapped).not.toBeNull();
|
|
28
|
-
expect(mapped.kind).toBe('tool.call');
|
|
29
|
-
expect(mapped.data).toMatchObject({ tool: 'bash', callId: 'c1' });
|
|
30
|
-
});
|
|
31
|
-
it('maps tool_execution_end → tool.result with ok inverted from isError', () => {
|
|
32
|
-
const mapped = mapBrainEventToSpine(ev('tool_execution_end', { toolCallId: 'c1', result: 'err', isError: true, durationMs: 5 }));
|
|
33
|
-
expect(mapped.kind).toBe('tool.result');
|
|
34
|
-
expect(mapped.data).toMatchObject({ callId: 'c1', ok: false });
|
|
35
|
-
});
|
|
36
|
-
it('drops ui/progress events (queue_update, message_start, thinking_delta)', () => {
|
|
37
|
-
expect(mapBrainEventToSpine(ev('queue_update', { queuedCount: 1 }))).toBeNull();
|
|
38
|
-
expect(mapBrainEventToSpine(ev('message_start', { messageId: 'm', role: 'assistant' }))).toBeNull();
|
|
39
|
-
expect(mapBrainEventToSpine(ev('thinking_delta', { messageId: 'm', delta: 'x' }))).toBeNull();
|
|
40
|
-
});
|
|
41
|
-
});
|
|
42
|
-
describe('SessionSpineMirror.adopt', () => {
|
|
43
|
-
it('bootstraps a fresh session with session.started at seq 1', async () => {
|
|
44
|
-
const mirror = await SessionSpineMirror.adopt('sess-a', { baseDir: tmp, quiet: true });
|
|
45
|
-
expect(mirror.status).toBe('active');
|
|
46
|
-
await mirror.close();
|
|
47
|
-
const report = await readSessionLog(path.join(tmp, 'sess-a', 'events.jsonl'));
|
|
48
|
-
expect(report.events.map((e) => e.kind)).toEqual(['session.started', 'session.ended']);
|
|
49
|
-
expect(report.events[0].seq).toBe(1);
|
|
50
|
-
});
|
|
51
|
-
it('resumes an existing session: session.resumed + seq continues after lastSeq', async () => {
|
|
52
|
-
const first = await SessionSpineMirror.adopt('sess-b', { baseDir: tmp, quiet: true });
|
|
53
|
-
first.userMessage('hello');
|
|
54
|
-
await first.close();
|
|
55
|
-
const second = await SessionSpineMirror.adopt('sess-b', { baseDir: tmp, quiet: true });
|
|
56
|
-
second.userMessage('again');
|
|
57
|
-
await second.close('done');
|
|
58
|
-
const report = await readSessionLog(path.join(tmp, 'sess-b', 'events.jsonl'));
|
|
59
|
-
const kinds = report.events.map((e) => e.kind);
|
|
60
|
-
expect(kinds).toEqual([
|
|
61
|
-
'session.started',
|
|
62
|
-
'user.message',
|
|
63
|
-
'session.ended',
|
|
64
|
-
'session.resumed',
|
|
65
|
-
'user.message',
|
|
66
|
-
'session.ended',
|
|
67
|
-
]);
|
|
68
|
-
// seq must be monotonic and gap-free across the reopen
|
|
69
|
-
report.events.forEach((e, i) => expect(e.seq).toBe(i + 1));
|
|
70
|
-
});
|
|
71
|
-
it('a second live writer is rejected as locked (ownership)', async () => {
|
|
72
|
-
const first = await SessionSpineMirror.adopt('sess-c', { baseDir: tmp, quiet: true });
|
|
73
|
-
const second = await SessionSpineMirror.adopt('sess-c', { baseDir: tmp, quiet: true });
|
|
74
|
-
expect(second.status).toBe('locked');
|
|
75
|
-
// the locked mirror is inert, the first keeps writing
|
|
76
|
-
first.userMessage('still mine');
|
|
77
|
-
await first.close();
|
|
78
|
-
const report = await readSessionLog(path.join(tmp, 'sess-c', 'events.jsonl'));
|
|
79
|
-
expect(report.events.some((e) => e.kind === 'user.message')).toBe(true);
|
|
80
|
-
});
|
|
81
|
-
it('degrades silently when the sessions dir cannot be created', async () => {
|
|
82
|
-
// a FILE at the path where the directory should go → mkdir fails
|
|
83
|
-
const blocker = path.join(tmp, 'blocker');
|
|
84
|
-
await fs.writeFile(blocker, 'x', 'utf-8');
|
|
85
|
-
const mirror = await SessionSpineMirror.adopt('sess-d', { baseDir: blocker, quiet: true });
|
|
86
|
-
expect(mirror.status).toBe('degraded');
|
|
87
|
-
// never throws, stays inert
|
|
88
|
-
expect(() => mirror.userMessage('nope')).not.toThrow();
|
|
89
|
-
await mirror.close();
|
|
90
|
-
});
|
|
91
|
-
it('ZELARI_SESSION_SPINE=0 disables the mirror entirely', async () => {
|
|
92
|
-
const prev = process.env.ZELARI_SESSION_SPINE;
|
|
93
|
-
process.env.ZELARI_SESSION_SPINE = '0';
|
|
94
|
-
try {
|
|
95
|
-
expect(spineEnabled()).toBe(false);
|
|
96
|
-
const mirror = await SessionSpineMirror.adopt('sess-e', { baseDir: tmp, quiet: true });
|
|
97
|
-
expect(mirror.status).toBe('disabled');
|
|
98
|
-
await mirror.close();
|
|
99
|
-
await expect(fs.access(path.join(tmp, 'sess-e'))).rejects.toThrow();
|
|
100
|
-
}
|
|
101
|
-
finally {
|
|
102
|
-
if (prev === undefined)
|
|
103
|
-
delete process.env.ZELARI_SESSION_SPINE;
|
|
104
|
-
else
|
|
105
|
-
process.env.ZELARI_SESSION_SPINE = prev;
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
});
|
|
109
|
-
describe('SessionSpineMirror.mirrorBrainEvent', () => {
|
|
110
|
-
it('coalesces message_delta into ONE assistant.message at message_end', async () => {
|
|
111
|
-
const mirror = await SessionSpineMirror.adopt('sess-f', { baseDir: tmp, quiet: true });
|
|
112
|
-
mirror.mirrorBrainEvent(ev('message_start', { messageId: 'm1', role: 'assistant' }));
|
|
113
|
-
mirror.mirrorBrainEvent(ev('message_delta', { messageId: 'm1', delta: 'Hello ' }));
|
|
114
|
-
mirror.mirrorBrainEvent(ev('message_delta', { messageId: 'm1', delta: 'world' }));
|
|
115
|
-
mirror.mirrorBrainEvent(ev('message_end', { messageId: 'm1', totalLength: 11, finishReason: 'stop' }));
|
|
116
|
-
await mirror.close();
|
|
117
|
-
const report = await readSessionLog(path.join(tmp, 'sess-f', 'events.jsonl'));
|
|
118
|
-
const assistant = report.events.filter((e) => e.kind === 'assistant.message');
|
|
119
|
-
expect(assistant).toHaveLength(1);
|
|
120
|
-
expect(assistant[0].data.text).toBe('Hello world');
|
|
121
|
-
});
|
|
122
|
-
it('message_end without buffered deltas logs nothing (no truncated claim)', async () => {
|
|
123
|
-
const mirror = await SessionSpineMirror.adopt('sess-g', { baseDir: tmp, quiet: true });
|
|
124
|
-
mirror.mirrorBrainEvent(ev('message_end', { messageId: 'orphan', totalLength: 0, finishReason: 'stop' }));
|
|
125
|
-
await mirror.close();
|
|
126
|
-
const report = await readSessionLog(path.join(tmp, 'sess-g', 'events.jsonl'));
|
|
127
|
-
expect(report.events.filter((e) => e.kind === 'assistant.message')).toHaveLength(0);
|
|
128
|
-
});
|
|
129
|
-
it('mirrors tool call+result pair', async () => {
|
|
130
|
-
const mirror = await SessionSpineMirror.adopt('sess-h', { baseDir: tmp, quiet: true });
|
|
131
|
-
mirror.mirrorBrainEvent(ev('tool_execution_start', { toolCallId: 'c9', toolName: 'bash', args: {} }));
|
|
132
|
-
mirror.mirrorBrainEvent(ev('tool_execution_end', { toolCallId: 'c9', result: 'ok', isError: false, durationMs: 12 }));
|
|
133
|
-
await mirror.close();
|
|
134
|
-
const report = await readSessionLog(path.join(tmp, 'sess-h', 'events.jsonl'));
|
|
135
|
-
const kinds = report.events.map((e) => e.kind);
|
|
136
|
-
expect(kinds).toContain('tool.call');
|
|
137
|
-
expect(kinds).toContain('tool.result');
|
|
138
|
-
});
|
|
139
|
-
});
|
|
140
|
-
describe('resumeSpineContext', () => {
|
|
141
|
-
it('returns null for an unknown session and a projection for a logged one', async () => {
|
|
142
|
-
expect(await resumeSpineContext('nope', tmp)).toBeNull();
|
|
143
|
-
const mirror = await SessionSpineMirror.adopt('sess-i', { baseDir: tmp, quiet: true });
|
|
144
|
-
mirror.userMessage('write a test');
|
|
145
|
-
mirror.mirrorBrainEvent(ev('message_end', { messageId: 'm', totalLength: 2, finishReason: 'stop' }));
|
|
146
|
-
// note: no deltas buffered → no assistant message; add one properly
|
|
147
|
-
mirror.mirrorBrainEvent(ev('message_delta', { messageId: 'm2', delta: 'done' }));
|
|
148
|
-
mirror.mirrorBrainEvent(ev('message_end', { messageId: 'm2', totalLength: 4, finishReason: 'stop' }));
|
|
149
|
-
await mirror.close();
|
|
150
|
-
const ctx = await resumeSpineContext('sess-i', tmp);
|
|
151
|
-
expect(ctx).not.toBeNull();
|
|
152
|
-
expect(ctx.derived.map((m) => m.role)).toEqual(['user', 'assistant']);
|
|
153
|
-
expect(ctx.derived[0].content).toBe('write a test');
|
|
154
|
-
expect(ctx.projection.lastSeq).toBeGreaterThan(2);
|
|
155
|
-
});
|
|
156
|
-
});
|
|
157
|
-
describe('SessionSpineMirror.release', () => {
|
|
158
|
-
it('leaves the log without session.ended so resume can continue the seq', async () => {
|
|
159
|
-
const mirror = await SessionSpineMirror.adopt('sess-int', { baseDir: tmp, quiet: true });
|
|
160
|
-
mirror.userMessage('partial');
|
|
161
|
-
await mirror.release();
|
|
162
|
-
const { readSessionLog } = await import('@zelari/core/session');
|
|
163
|
-
const report = await readSessionLog(path.join(tmp, 'sess-int', 'events.jsonl'));
|
|
164
|
-
expect(report.events.some((e) => e.kind === 'session.ended')).toBe(false);
|
|
165
|
-
const again = await SessionSpineMirror.adopt('sess-int', { baseDir: tmp, quiet: true });
|
|
166
|
-
expect(again.status).toBe('active');
|
|
167
|
-
expect(again.resumedFromSeq).toBeGreaterThan(0);
|
|
168
|
-
await again.close('done');
|
|
169
|
-
});
|
|
170
|
-
});
|
|
171
|
-
//# sourceMappingURL=sessionSpine.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sessionSpine.test.js","sourceRoot":"","sources":["../../src/cli/sessionSpine.test.ts"],"names":[],"mappings":"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"}
|