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.
Files changed (114) hide show
  1. package/README.md +4 -4
  2. package/package.json +8 -5
  3. package/dist/cli/ast/engine.test.js +0 -101
  4. package/dist/cli/ast/engine.test.js.map +0 -1
  5. package/dist/cli/ast/tools.test.js +0 -124
  6. package/dist/cli/ast/tools.test.js.map +0 -1
  7. package/dist/cli/headless.test.js +0 -107
  8. package/dist/cli/headless.test.js.map +0 -1
  9. package/dist/cli/headlessE2eSession.test.js +0 -189
  10. package/dist/cli/headlessE2eSession.test.js.map +0 -1
  11. package/dist/cli/headlessHistorySeed.test.js +0 -158
  12. package/dist/cli/headlessHistorySeed.test.js.map +0 -1
  13. package/dist/cli/headlessSessionEvent.test.js +0 -83
  14. package/dist/cli/headlessSessionEvent.test.js.map +0 -1
  15. package/dist/cli/headlessSpine.test.js +0 -153
  16. package/dist/cli/headlessSpine.test.js.map +0 -1
  17. package/dist/cli/hooks/observationStore.test.js +0 -135
  18. package/dist/cli/hooks/observationStore.test.js.map +0 -1
  19. package/dist/cli/hooks/sessionSurface.test.js +0 -112
  20. package/dist/cli/hooks/sessionSurface.test.js.map +0 -1
  21. package/dist/cli/kraken/candidateRegistry.test.js +0 -211
  22. package/dist/cli/kraken/candidateRegistry.test.js.map +0 -1
  23. package/dist/cli/kraken/completionGate.test.js +0 -172
  24. package/dist/cli/kraken/completionGate.test.js.map +0 -1
  25. package/dist/cli/kraken/evidenceAnchoring.test.js +0 -92
  26. package/dist/cli/kraken/evidenceAnchoring.test.js.map +0 -1
  27. package/dist/cli/kraken/evidenceProvenance.test.js +0 -113
  28. package/dist/cli/kraken/evidenceProvenance.test.js.map +0 -1
  29. package/dist/cli/kraken/executor.workbench.test.js +0 -134
  30. package/dist/cli/kraken/executor.workbench.test.js.map +0 -1
  31. package/dist/cli/kraken/metrics.test.js +0 -145
  32. package/dist/cli/kraken/metrics.test.js.map +0 -1
  33. package/dist/cli/kraken/nativeVerification.test.js +0 -207
  34. package/dist/cli/kraken/nativeVerification.test.js.map +0 -1
  35. package/dist/cli/kraken/planner.test.js +0 -43
  36. package/dist/cli/kraken/planner.test.js.map +0 -1
  37. package/dist/cli/kraken/scriptPlanner.test.js +0 -152
  38. package/dist/cli/kraken/scriptPlanner.test.js.map +0 -1
  39. package/dist/cli/kraken/selectionPlaybook.test.js +0 -55
  40. package/dist/cli/kraken/selectionPlaybook.test.js.map +0 -1
  41. package/dist/cli/kraken/skillSuggest.test.js +0 -157
  42. package/dist/cli/kraken/skillSuggest.test.js.map +0 -1
  43. package/dist/cli/kraken/strictDefaults.test.js +0 -149
  44. package/dist/cli/kraken/strictDefaults.test.js.map +0 -1
  45. package/dist/cli/kraken/strictGatePackIndependence.test.js +0 -112
  46. package/dist/cli/kraken/strictGatePackIndependence.test.js.map +0 -1
  47. package/dist/cli/kraken/turnRuntime.test.js +0 -377
  48. package/dist/cli/kraken/turnRuntime.test.js.map +0 -1
  49. package/dist/cli/kraken/verificationBridge.session.test.js +0 -104
  50. package/dist/cli/kraken/verificationBridge.session.test.js.map +0 -1
  51. package/dist/cli/kraken/verificationBridge.test.js +0 -177
  52. package/dist/cli/kraken/verificationBridge.test.js.map +0 -1
  53. package/dist/cli/kraken/verifier.test.js +0 -232
  54. package/dist/cli/kraken/verifier.test.js.map +0 -1
  55. package/dist/cli/kraken/verifierAdvisoryLock.test.js +0 -154
  56. package/dist/cli/kraken/verifierAdvisoryLock.test.js.map +0 -1
  57. package/dist/cli/kraken/verifierLifecycle.test.js +0 -181
  58. package/dist/cli/kraken/verifierLifecycle.test.js.map +0 -1
  59. package/dist/cli/kraken/verifierRoundTrip.test.js +0 -166
  60. package/dist/cli/kraken/verifierRoundTrip.test.js.map +0 -1
  61. package/dist/cli/kraken/verifierSettings.test.js +0 -237
  62. package/dist/cli/kraken/verifierSettings.test.js.map +0 -1
  63. package/dist/cli/kraken/verifyReport.test.js +0 -111
  64. package/dist/cli/kraken/verifyReport.test.js.map +0 -1
  65. package/dist/cli/kraken/weaknessMeter.test.js +0 -212
  66. package/dist/cli/kraken/weaknessMeter.test.js.map +0 -1
  67. package/dist/cli/kraken/workbench.test.js +0 -253
  68. package/dist/cli/kraken/workbench.test.js.map +0 -1
  69. package/dist/cli/kraken/workbenchView.test.js +0 -130
  70. package/dist/cli/kraken/workbenchView.test.js.map +0 -1
  71. package/dist/cli/legacyContextIsolation.test.js +0 -65
  72. package/dist/cli/legacyContextIsolation.test.js.map +0 -1
  73. package/dist/cli/lsp/tools.test.js +0 -90
  74. package/dist/cli/lsp/tools.test.js.map +0 -1
  75. package/dist/cli/missionContinuation.test.js +0 -117
  76. package/dist/cli/missionContinuation.test.js.map +0 -1
  77. package/dist/cli/profileMatrix.test.js +0 -130
  78. package/dist/cli/profileMatrix.test.js.map +0 -1
  79. package/dist/cli/provider/capabilities.test.js +0 -46
  80. package/dist/cli/provider/capabilities.test.js.map +0 -1
  81. package/dist/cli/provider/openai-compatible.timeout.test.js +0 -72
  82. package/dist/cli/provider/openai-compatible.timeout.test.js.map +0 -1
  83. package/dist/cli/providerConfig.test.js +0 -85
  84. package/dist/cli/providerConfig.test.js.map +0 -1
  85. package/dist/cli/sessionReplayInvariant.test.js +0 -187
  86. package/dist/cli/sessionReplayInvariant.test.js.map +0 -1
  87. package/dist/cli/sessionSpine.test.js +0 -171
  88. package/dist/cli/sessionSpine.test.js.map +0 -1
  89. package/dist/cli/thinking.test.js +0 -214
  90. package/dist/cli/thinking.test.js.map +0 -1
  91. package/dist/cli/tools/inspectCommand.schema.test.js +0 -82
  92. package/dist/cli/tools/inspectCommand.schema.test.js.map +0 -1
  93. package/dist/cli/tools/inspectCommand.test.js +0 -311
  94. package/dist/cli/tools/inspectCommand.test.js.map +0 -1
  95. package/dist/cli/tools/krakenCsvFanout.test.js +0 -200
  96. package/dist/cli/tools/krakenCsvFanout.test.js.map +0 -1
  97. package/dist/cli/tools/krakenSelectTool.test.js +0 -246
  98. package/dist/cli/tools/krakenSelectTool.test.js.map +0 -1
  99. package/dist/cli/tools/observeBatch.test.js +0 -329
  100. package/dist/cli/tools/observeBatch.test.js.map +0 -1
  101. package/dist/cli/tools/taskTool.dynamicChecks.test.js +0 -156
  102. package/dist/cli/tools/taskTool.dynamicChecks.test.js.map +0 -1
  103. package/dist/cli/tools/taskTool.planSafety.test.js +0 -280
  104. package/dist/cli/tools/taskTool.planSafety.test.js.map +0 -1
  105. package/dist/cli/tools/taskTool.verifyReport.test.js +0 -140
  106. package/dist/cli/tools/taskTool.verifyReport.test.js.map +0 -1
  107. package/dist/cli/utils/contextGrowthSummary.test.js +0 -74
  108. package/dist/cli/utils/contextGrowthSummary.test.js.map +0 -1
  109. package/dist/cli/workspace/planDriftCheck.test.js +0 -146
  110. package/dist/cli/workspace/planDriftCheck.test.js.map +0 -1
  111. package/dist/cli/workspace/planStore.test.js +0 -295
  112. package/dist/cli/workspace/planStore.test.js.map +0 -1
  113. package/dist/cli/zelariMission.test.js +0 -44
  114. 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":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EACL,iBAAiB,EACjB,wBAAwB,EACxB,gBAAgB,GAEjB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,cAAc,EACd,cAAc,EACd,mBAAmB,EACnB,kBAAkB,GAEnB,MAAM,sBAAsB,CAAC;AAG9B,IAAI,GAAW,CAAC;AAEhB,UAAU,CAAC,KAAK,IAAI,EAAE;IACpB,GAAG,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,oBAAoB,CAAC,CAAC,CAAC;AACvE,CAAC,CAAC,CAAC;AAEH,SAAS,CAAC,KAAK,IAAI,EAAE;IACnB,MAAM,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AACrD,CAAC,CAAC,CAAC;AAEH,SAAS,UAAU,CAAC,SAAiB;IACnC,OAAO,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE,SAAS,EAAE,cAAc,CAAC,CAAC;AACpF,CAAC;AAED,SAAS,UAAU,CAAC,IAAY,EAAE,OAAgC,EAAE;IAClE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,EAAE,iBAAiB,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,IAAI,EAAW,CAAC;AAC9F,CAAC;AAED,6EAA6E;AAC7E,KAAK,UAAU,MAAM,CAAC,SAAiB;IACrC,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;IAC3D,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAClC,OAAO,MAAM,CAAC,MAAM,CAAC;AACvB,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,kBAAkB,CAAC,SAAiB;IACjD,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAEjF,MAAM,MAAM,GAAmB;QAC7B,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE;QACtC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE;KAC5C,CAAC;IACF,MAAM,IAAI,GAAG,MAAM,wBAAwB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5D,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAEzC,0DAA0D;IAC1D,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC;IAClC,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,UAAU,CAAC,eAAe,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC,CAAC,CAAC;IAC3G,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,UAAU,CAAC,eAAe,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC;IACvG,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,UAAU,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;IACpG,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAC3B,UAAU,CAAC,sBAAsB,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,CACpG,CAAC;IACF,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAC3B,UAAU,CAAC,oBAAoB,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,eAAe,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAChG,CAAC;IACF,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,UAAU,CAAC,mBAAmB,EAAE,EAAE,OAAO,EAAE,mBAAmB,EAAE,CAAC,CAAC,CAAC;IACjG,MAAM,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IAC3B,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,QAAQ,CAAC,iEAAiE,EAAE,GAAG,EAAE;IAC/E,EAAE,CAAC,2EAA2E,EAAE,KAAK,IAAI,EAAE;QACzF,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,WAAW,CAAC,CAAC;QACrD,MAAM,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QAE/B,sEAAsE;QACtE,MAAM,QAAQ,GAAG,MAAM,kBAAkB,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5F,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACvC,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,iBAAiB,EAAE,CAAC;QACnD,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;QAE/B,oEAAoE;QACpE,MAAM,QAAQ,GAAG,cAAc,CAAC,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC;QAC3D,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAElC,MAAM,WAAW,GAAG,OAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QAClE,MAAM,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC;YAC1B,gBAAgB;YAChB,qBAAqB;YACrB,kBAAkB;YAClB,wCAAwC;YACxC,oBAAoB,EAAE,8CAA8C;YACpE,0BAA0B,EAAE,oDAAoD;SACjF,CAAC,CAAC;QACH,MAAM,QAAQ,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uEAAuE,EAAE,KAAK,IAAI,EAAE;QACrF,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,WAAW,CAAC,CAAC;QACrD,MAAM,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QAC/B,MAAM,KAAK,GAAG,cAAc,CAAC,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC;QACxD,MAAM,MAAM,GAAG,cAAc,CAAC,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC;QACzD,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sDAAsD,EAAE,KAAK,IAAI,EAAE;QACpE,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,WAAW,CAAC,CAAC;QACrD,MAAM,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QAE/B,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC;QAC1D,MAAM,IAAI,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;QACvC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;YACxD,gBAAgB;YAChB,qBAAqB;YACrB,kBAAkB;YAClB,wCAAwC,EAAE,oCAAoC;YAC9E,wBAAwB,EAAE,kDAAkD;YAC5E,4EAA4E;SAC7E,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,sDAAsD,EAAE,GAAG,EAAE;IACpE,EAAE,CAAC,uEAAuE,EAAE,KAAK,IAAI,EAAE;QACrF,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,WAAW,CAAC,CAAC;QACrD,MAAM,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QAE/B,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;QACzC,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;QACvC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QAC1C,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC;YACnD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,wBAAwB,CAAC,CAAC,WAAW,EAAE,CAAC;YACnE,MAAM,CAAC,mBAAmB,CAAC,MAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChD,MAAM,YAAY,GAChB,MAAO,CAAC,IAAI,KAAK,cAAc;gBAC7B,CAAC,CAAC,MAAM;gBACR,CAAC,CAAC,MAAO,CAAC,IAAI,KAAK,mBAAmB;oBACpC,CAAC,CAAC,WAAW;oBACb,CAAC,CAAC,MAAO,CAAC,IAAI,KAAK,mBAAmB;wBACpC,CAAC,CAAC,QAAQ;wBACV,CAAC,CAAC,MAAM,CAAC;YACjB,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACpC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mGAAmG,EAAE,KAAK,IAAI,EAAE;QACjH,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,WAAW,CAAC,CAAC;QACrD,MAAM,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QAE/B,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;QACzC,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;QACvC,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACvD,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;QACnD,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QAC1C,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,iEAAiE;YACjE,+DAA+D;YAC/D,IAAI,CAAC,CAAC,IAAI,KAAK,WAAW;gBAAE,SAAS;YACrC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9E,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uEAAuE,EAAE,KAAK,IAAI,EAAE;QACrF,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,WAAW,CAAC,CAAC;QAErD,0EAA0E;QAC1E,MAAM,IAAI,GAAG,MAAM,wBAAwB,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QACxD,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAClC,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC;QAClC,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,UAAU,CAAC,eAAe,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC;QACvG,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,UAAU,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;QACpG,MAAM,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QAE3B,sEAAsE;QACtE,+DAA+D;QAC/D,4DAA4D;QAC5D,yDAAyD;QACzD,MAAM,OAAO,GAAG,CAAC,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;QACxE,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACpC,MAAM,CACH,CAAC,CAAC,IAA4C,CAAC,IAAI;YACjD,CAAC,CAAC,IAA6B,CAAC,OAAO;YACxC,EAAE,CACL,CACF,CAAC;QACF,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CACrC,CAAC,WAAW,EAAE,aAAa,EAAE,aAAa,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CACxD,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,aAAa,EAAE,aAAa,CAAC,CAAC,CAAC;QACnE,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAC7B,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QAC3C,CAAC;QACD,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC;QAEhF,MAAM,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QAC/B,MAAM,KAAK,GAAG,MAAM,kBAAkB,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACzF,MAAM,KAAK,GAAG,gBAAgB,CAAC,CAAC,MAAM,KAAK,CAAC,iBAAiB,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;QACxE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;YAC1C,WAAW;YACX,WAAW;YACX,aAAa;YACb,8BAA8B;YAC9B,mBAAmB;YACnB,aAAa;YACb,cAAc;SACf,CAAC,CAAC;QACH,MAAM,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -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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"}