zelari-code 2.1.0 → 2.1.1
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
package/README.md
CHANGED
|
@@ -54,7 +54,7 @@ zelari-code
|
|
|
54
54
|
| Requirement | Version | Notes |
|
|
55
55
|
|---|---|---|
|
|
56
56
|
| **Node.js** | **≥ 24 LTS** | CI tests Node 24 only; Node 20 was dropped from the matrix (the dependency tree requires it). |
|
|
57
|
-
| **npm** | **≥
|
|
57
|
+
| **npm** | **≥ 11.7** | Required to reproduce the workspace lockfile; use the version pinned by `packageManager`. |
|
|
58
58
|
| **OS** | Linux, macOS, Windows 10/11 | Tested on Pop!_OS 24.04, macOS 15, Windows 11. Windows requires Git Bash (auto-detected). |
|
|
59
59
|
| **Disk** | ~50 MB for the CLI + `@zelari/core` | Models are not bundled — provider APIs are remote. |
|
|
60
60
|
| **Account + API key** | 1 of: xAI Grok, ChatGPT, Anthropic, OpenAI-compatible, GLM/Z.AI, MiniMax, DeepSeek | OAuth via `/login grok`, `/login chatgpt`, `/login anthropic`. |
|
|
@@ -97,10 +97,10 @@ npm run desktop:dev # Tauri dev window
|
|
|
97
97
|
# npm run desktop:build # MSI / NSIS / DMG / AppImage
|
|
98
98
|
```
|
|
99
99
|
|
|
100
|
-
See [apps/desktop/README.md](./apps/desktop/README.md) and **[docs/GUIDA.md](./docs/GUIDA.md)** (Desktop, MCP, SSH). Requires Rust + Node ≥
|
|
100
|
+
See [apps/desktop/README.md](./apps/desktop/README.md) and **[docs/GUIDA.md](./docs/GUIDA.md)** (Desktop, MCP, SSH). Requires Rust + Node ≥ 24.
|
|
101
101
|
|
|
102
102
|
**Prerequisites:**
|
|
103
|
-
- **Node.js ≥
|
|
103
|
+
- **Node.js ≥ 24** — required. Without it the agent cannot run `npm`/`tsc`/builds, so zelari-code refuses to boot.
|
|
104
104
|
- **Git** — recommended. Without it, `/diff`, `/undo` and the git sidebar are disabled. Install from <https://git-scm.com>.
|
|
105
105
|
- **Git Bash** (Windows only) — recommended. The agent's `bash` tool needs real POSIX semantics (`ls`, `which`, `$VAR`, `&&`). Ships with Git for Windows.
|
|
106
106
|
|
|
@@ -468,4 +468,4 @@ npm run typecheck
|
|
|
468
468
|
|
|
469
469
|
## License
|
|
470
470
|
|
|
471
|
-
[Apache-2.0](./LICENSE) © 2026 [Anathema Studio](https://anathema-studio.com/).
|
|
471
|
+
[Apache-2.0](./LICENSE) © 2026 [Anathema Studio](https://anathema-studio.com/).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zelari-code",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.1",
|
|
4
4
|
"description": "Zelari Code — AI Council coding agent CLI. Multi-agent orchestration (Caronte, Nettuno, Gerione, Plutone, Minosse, Lucifero) with slash commands, provider-agnostic LLM streaming, and self-update.",
|
|
5
5
|
"author": "Anathema Studio <https://anathema-studio.com/>",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -24,11 +24,14 @@
|
|
|
24
24
|
],
|
|
25
25
|
"preferGlobal": true,
|
|
26
26
|
"engines": {
|
|
27
|
-
"node": ">=24.0.0"
|
|
27
|
+
"node": ">=24.0.0",
|
|
28
|
+
"npm": ">=11.7.0"
|
|
28
29
|
},
|
|
30
|
+
"packageManager": "npm@11.7.0",
|
|
29
31
|
"scripts": {
|
|
30
|
-
"
|
|
31
|
-
"build
|
|
32
|
+
"clean": "node scripts/clean-dist.mjs",
|
|
33
|
+
"build": "npm run clean && npm run build --workspace=@zelari/core && tsc -p tsconfig.json && node scripts/bundle-cli.mjs",
|
|
34
|
+
"build:cli": "npm run clean && npm run build --workspace=@zelari/core && tsc -p tsconfig.json && node scripts/bundle-cli.mjs",
|
|
32
35
|
"typecheck": "npm run build --workspace=@zelari/core && tsc --noEmit -p tsconfig.json",
|
|
33
36
|
"pretest": "npm run build --workspace=@zelari/core",
|
|
34
37
|
"test": "vitest run",
|
|
@@ -54,7 +57,7 @@
|
|
|
54
57
|
},
|
|
55
58
|
"devDependencies": {
|
|
56
59
|
"@testing-library/react": "^16.3.2",
|
|
57
|
-
"@zelari/core": "2.1.
|
|
60
|
+
"@zelari/core": "2.1.1",
|
|
58
61
|
"@types/node": "^25.3.0",
|
|
59
62
|
"@types/react": "^19.0.10",
|
|
60
63
|
"esbuild": "^0.25.0",
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* S2.1/S2.3 — unit tests for the loud, discriminated parse result of
|
|
3
|
-
* ast/engine (plan: .zelari/docs/piano-loud-tool-errors-ast-diag-readonly-shell.md §2).
|
|
4
|
-
*/
|
|
5
|
-
import { mkdtemp, writeFile } from 'node:fs/promises';
|
|
6
|
-
import { tmpdir } from 'node:os';
|
|
7
|
-
import path from 'node:path';
|
|
8
|
-
import { vi, describe, it, expect } from 'vitest';
|
|
9
|
-
import { parseFileSymbolsDiag, parseFileSymbols, astOutline, findSymbol, } from './engine.js';
|
|
10
|
-
const SAMPLE = [
|
|
11
|
-
'export interface Shape { kind: string }',
|
|
12
|
-
'export class Circle implements Shape {',
|
|
13
|
-
' kind = "circle";',
|
|
14
|
-
' area(): number { return 1; }',
|
|
15
|
-
'}',
|
|
16
|
-
'export const area = (r: number): number => r * r;',
|
|
17
|
-
'const hidden = 1;',
|
|
18
|
-
'',
|
|
19
|
-
].join('\n');
|
|
20
|
-
describe('parseFileSymbolsDiag', () => {
|
|
21
|
-
it('resolves relative paths against the injected cwd and parses symbols', async () => {
|
|
22
|
-
const dir = await mkdtemp(path.join(tmpdir(), 'zelari-ast-'));
|
|
23
|
-
await writeFile(path.join(dir, 'sample.ts'), SAMPLE, 'utf8');
|
|
24
|
-
const r = await parseFileSymbolsDiag('sample.ts', dir);
|
|
25
|
-
expect(r.status).toBe('ok');
|
|
26
|
-
if (r.status !== 'ok')
|
|
27
|
-
return;
|
|
28
|
-
const names = r.symbols.map((s) => s.name);
|
|
29
|
-
expect(names).toContain('Shape');
|
|
30
|
-
expect(names).toContain('Circle');
|
|
31
|
-
expect(names).toContain('area'); // arrow function → kind 'function'
|
|
32
|
-
expect(names).toContain('hidden');
|
|
33
|
-
const circle = r.symbols.find((s) => s.name === 'Circle');
|
|
34
|
-
expect(circle.exported).toBe(true);
|
|
35
|
-
expect(circle.text).toContain('area(): number');
|
|
36
|
-
});
|
|
37
|
-
it('reports file-not-found with the ABSOLUTE resolved path', async () => {
|
|
38
|
-
const dir = await mkdtemp(path.join(tmpdir(), 'zelari-ast-'));
|
|
39
|
-
const r = await parseFileSymbolsDiag('missing.ts', dir);
|
|
40
|
-
expect(r.status).toBe('file-not-found');
|
|
41
|
-
if (r.status !== 'file-not-found')
|
|
42
|
-
return;
|
|
43
|
-
expect(r.resolvedPath).toBe(path.join(dir, 'missing.ts'));
|
|
44
|
-
expect(path.isAbsolute(r.resolvedPath)).toBe(true);
|
|
45
|
-
expect(r.recoverable).toBe(false);
|
|
46
|
-
expect(r.recommendedFallback).toBe('grep_content');
|
|
47
|
-
});
|
|
48
|
-
it('reports unsupported-extension with the extension it saw', async () => {
|
|
49
|
-
const dir = await mkdtemp(path.join(tmpdir(), 'zelari-ast-'));
|
|
50
|
-
await writeFile(path.join(dir, 'script.py'), 'def f(): pass\n', 'utf8');
|
|
51
|
-
const r = await parseFileSymbolsDiag('script.py', dir);
|
|
52
|
-
expect(r.status).toBe('unsupported-extension');
|
|
53
|
-
if (r.status !== 'unsupported-extension')
|
|
54
|
-
return;
|
|
55
|
-
expect(r.extension).toBe('.py');
|
|
56
|
-
expect(r.resolvedPath).toBe(path.join(dir, 'script.py'));
|
|
57
|
-
});
|
|
58
|
-
it('reports typescript-unavailable when the compiler API cannot load', async () => {
|
|
59
|
-
const dir = await mkdtemp(path.join(tmpdir(), 'zelari-ast-'));
|
|
60
|
-
await writeFile(path.join(dir, 'sample.ts'), SAMPLE, 'utf8');
|
|
61
|
-
// Fresh module graph where the dynamic `import('typescript')` rejects.
|
|
62
|
-
vi.resetModules();
|
|
63
|
-
vi.doMock('typescript', () => {
|
|
64
|
-
throw new Error('simulated: typescript not installed');
|
|
65
|
-
});
|
|
66
|
-
try {
|
|
67
|
-
const fresh = await import('./engine.js');
|
|
68
|
-
const r = await fresh.parseFileSymbolsDiag('sample.ts', dir);
|
|
69
|
-
expect(r.status).toBe('typescript-unavailable');
|
|
70
|
-
if (r.status !== 'typescript-unavailable')
|
|
71
|
-
return;
|
|
72
|
-
expect(r.recoverable).toBe(true);
|
|
73
|
-
expect(r.recommendedFallback).toBe('read_file');
|
|
74
|
-
}
|
|
75
|
-
finally {
|
|
76
|
-
vi.doUnmock('typescript');
|
|
77
|
-
}
|
|
78
|
-
});
|
|
79
|
-
});
|
|
80
|
-
describe('quiet compatibility wrappers', () => {
|
|
81
|
-
it('parseFileSymbols: [] on non-ok, symbols on ok', async () => {
|
|
82
|
-
const dir = await mkdtemp(path.join(tmpdir(), 'zelari-ast-'));
|
|
83
|
-
const file = path.join(dir, 'sample.ts');
|
|
84
|
-
await writeFile(file, SAMPLE, 'utf8');
|
|
85
|
-
// No cwd → resolves against process.cwd(); absolute path keeps it exact.
|
|
86
|
-
expect(await parseFileSymbols(path.join(dir, 'missing.ts'))).toEqual([]);
|
|
87
|
-
expect((await parseFileSymbols(file)).length).toBeGreaterThan(0);
|
|
88
|
-
});
|
|
89
|
-
it('astOutline drops text; findSymbol round-trips exact text', async () => {
|
|
90
|
-
const dir = await mkdtemp(path.join(tmpdir(), 'zelari-ast-'));
|
|
91
|
-
const file = path.join(dir, 'sample.ts');
|
|
92
|
-
await writeFile(file, SAMPLE, 'utf8');
|
|
93
|
-
const outline = await astOutline(file);
|
|
94
|
-
expect(outline.every((s) => !('text' in s))).toBe(true);
|
|
95
|
-
const sym = await findSymbol(file, 'Circle');
|
|
96
|
-
expect(sym?.text.startsWith('export class Circle')).toBe(true);
|
|
97
|
-
expect(await findSymbol(file, 'DoesNotExist')).toBeNull();
|
|
98
|
-
expect(await findSymbol(path.join(dir, 'missing.ts'), 'X')).toBeNull();
|
|
99
|
-
});
|
|
100
|
-
});
|
|
101
|
-
//# sourceMappingURL=engine.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"engine.test.js","sourceRoot":"","sources":["../../../src/cli/ast/engine.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* S2.0/S2.2/S2.3 — tool-level tests: root propagation, ctx.cwd resolution,
|
|
3
|
-
* loud degraded notes with machine fields, and "found: false only when the
|
|
4
|
-
* file was actually read and parsed".
|
|
5
|
-
*/
|
|
6
|
-
import { mkdtemp, writeFile } from 'node:fs/promises';
|
|
7
|
-
import { tmpdir } from 'node:os';
|
|
8
|
-
import path from 'node:path';
|
|
9
|
-
import { describe, it, expect } from 'vitest';
|
|
10
|
-
import { createAstTools } from './tools.js';
|
|
11
|
-
const SAMPLE = [
|
|
12
|
-
'export interface Shape { kind: string }',
|
|
13
|
-
'export class Circle implements Shape {',
|
|
14
|
-
' kind = "circle";',
|
|
15
|
-
' area(): number { return 1; }',
|
|
16
|
-
'}',
|
|
17
|
-
'export const area = (r: number): number => r * r;',
|
|
18
|
-
'',
|
|
19
|
-
].join('\n');
|
|
20
|
-
function fakeCtx(cwd) {
|
|
21
|
-
return {
|
|
22
|
-
signal: new AbortController().signal,
|
|
23
|
-
cwd,
|
|
24
|
-
audit: () => { },
|
|
25
|
-
sessionId: 'ast-tools-test',
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
async function run(tool, args, ctx) {
|
|
29
|
-
const r = await tool.execute(args, ctx);
|
|
30
|
-
if (!r.ok)
|
|
31
|
-
throw new Error(r.error);
|
|
32
|
-
return r.value;
|
|
33
|
-
}
|
|
34
|
-
function getTools(root) {
|
|
35
|
-
const tools = createAstTools(root);
|
|
36
|
-
const outline = tools.find((t) => t.name === 'ast_outline');
|
|
37
|
-
const findSym = tools.find((t) => t.name === 'find_symbol');
|
|
38
|
-
return { outline, findSym };
|
|
39
|
-
}
|
|
40
|
-
describe('ast_outline (loud degradation)', () => {
|
|
41
|
-
it('resolves a RELATIVE path against ctx.cwd', async () => {
|
|
42
|
-
const dir = await mkdtemp(path.join(tmpdir(), 'zelari-ast-'));
|
|
43
|
-
await writeFile(path.join(dir, 'sample.ts'), SAMPLE, 'utf8');
|
|
44
|
-
const { outline } = getTools('/nonexistent-root');
|
|
45
|
-
const v = await run(outline, { path: 'sample.ts' }, fakeCtx(dir));
|
|
46
|
-
expect(v.status).toBe('ok');
|
|
47
|
-
expect(v.count).toBeGreaterThan(0);
|
|
48
|
-
const symbols = v.symbols;
|
|
49
|
-
expect(symbols.some((s) => s.includes('export class Circle'))).toBe(true);
|
|
50
|
-
});
|
|
51
|
-
it('falls back to the factory root when ctx has no cwd (S2.0)', async () => {
|
|
52
|
-
const dir = await mkdtemp(path.join(tmpdir(), 'zelari-ast-'));
|
|
53
|
-
await writeFile(path.join(dir, 'sample.ts'), SAMPLE, 'utf8');
|
|
54
|
-
const { outline } = getTools(dir);
|
|
55
|
-
const ctxNoCwd = {
|
|
56
|
-
signal: new AbortController().signal,
|
|
57
|
-
audit: () => { },
|
|
58
|
-
sessionId: 'ast-tools-test',
|
|
59
|
-
};
|
|
60
|
-
const v = await run(outline, { path: 'sample.ts' }, ctxNoCwd);
|
|
61
|
-
expect(v.status).toBe('ok');
|
|
62
|
-
expect(v.count).toBeGreaterThan(0);
|
|
63
|
-
});
|
|
64
|
-
it('file-not-found names the absolute path it looked at', async () => {
|
|
65
|
-
const dir = await mkdtemp(path.join(tmpdir(), 'zelari-ast-'));
|
|
66
|
-
const { outline } = getTools('/nonexistent-root');
|
|
67
|
-
const v = await run(outline, { path: 'missing.ts' }, fakeCtx(dir));
|
|
68
|
-
expect(v.status).toBe('file-not-found');
|
|
69
|
-
expect(v.symbols).toEqual([]);
|
|
70
|
-
expect(v.note).toContain(path.join(dir, 'missing.ts'));
|
|
71
|
-
expect(v.recoverable).toBe(false);
|
|
72
|
-
expect(v.recommendedFallback).toBe('grep_content');
|
|
73
|
-
});
|
|
74
|
-
it('unsupported-extension reports the extension in the note', async () => {
|
|
75
|
-
const dir = await mkdtemp(path.join(tmpdir(), 'zelari-ast-'));
|
|
76
|
-
await writeFile(path.join(dir, 'script.py'), 'def f(): pass\n', 'utf8');
|
|
77
|
-
const { outline } = getTools('/nonexistent-root');
|
|
78
|
-
const v = await run(outline, { path: 'script.py' }, fakeCtx(dir));
|
|
79
|
-
expect(v.status).toBe('unsupported-extension');
|
|
80
|
-
expect(v.note).toContain('.py');
|
|
81
|
-
});
|
|
82
|
-
it('an empty-but-parsed file is a TRUE empty, not a degraded note', async () => {
|
|
83
|
-
const dir = await mkdtemp(path.join(tmpdir(), 'zelari-ast-'));
|
|
84
|
-
await writeFile(path.join(dir, 'empty.ts'), '\n', 'utf8');
|
|
85
|
-
const { outline } = getTools('/nonexistent-root');
|
|
86
|
-
const v = await run(outline, { path: 'empty.ts' }, fakeCtx(dir));
|
|
87
|
-
expect(v.status).toBe('ok');
|
|
88
|
-
expect(v.symbols).toEqual([]);
|
|
89
|
-
expect(v.note).toContain('no declarations');
|
|
90
|
-
// The old conflated three-causes note must be gone.
|
|
91
|
-
expect(String(v.note)).not.toContain('TypeScript unavailable');
|
|
92
|
-
});
|
|
93
|
-
});
|
|
94
|
-
describe('find_symbol (found:false only after a successful parse)', () => {
|
|
95
|
-
it('degraded file surfaces status, not a fake "no declaration named"', async () => {
|
|
96
|
-
const dir = await mkdtemp(path.join(tmpdir(), 'zelari-ast-'));
|
|
97
|
-
const { findSym } = getTools('/nonexistent-root');
|
|
98
|
-
const v = await run(findSym, { path: 'missing.ts', name: 'Circle' }, fakeCtx(dir));
|
|
99
|
-
expect(v.found).toBe(false);
|
|
100
|
-
expect(v.status).toBe('file-not-found');
|
|
101
|
-
expect(v.note).toContain(path.join(dir, 'missing.ts'));
|
|
102
|
-
});
|
|
103
|
-
it('symbol truly absent from a PARSED file → found:false, status ok, hint of present names', async () => {
|
|
104
|
-
const dir = await mkdtemp(path.join(tmpdir(), 'zelari-ast-'));
|
|
105
|
-
await writeFile(path.join(dir, 'sample.ts'), SAMPLE, 'utf8');
|
|
106
|
-
const { findSym } = getTools('/nonexistent-root');
|
|
107
|
-
const v = await run(findSym, { path: 'sample.ts', name: 'Sphere' }, fakeCtx(dir));
|
|
108
|
-
expect(v.found).toBe(false);
|
|
109
|
-
expect(v.status).toBe('ok');
|
|
110
|
-
expect(v.note).toContain('Sphere');
|
|
111
|
-
expect(v.note).toContain('Circle');
|
|
112
|
-
});
|
|
113
|
-
it('returns the exact declaration text for editing', async () => {
|
|
114
|
-
const dir = await mkdtemp(path.join(tmpdir(), 'zelari-ast-'));
|
|
115
|
-
await writeFile(path.join(dir, 'sample.ts'), SAMPLE, 'utf8');
|
|
116
|
-
const { findSym } = getTools('/nonexistent-root');
|
|
117
|
-
const v = await run(findSym, { path: 'sample.ts', name: 'Circle' }, fakeCtx(dir));
|
|
118
|
-
expect(v.found).toBe(true);
|
|
119
|
-
expect(v.kind).toBe('class');
|
|
120
|
-
expect(v.exported).toBe(true);
|
|
121
|
-
expect(String(v.text).startsWith('export class Circle')).toBe(true);
|
|
122
|
-
});
|
|
123
|
-
});
|
|
124
|
-
//# sourceMappingURL=tools.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tools.test.js","sourceRoot":"","sources":["../../../src/cli/ast/tools.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* parseHeadlessFlags tests — --task-file / --kraken-graph-file slices.
|
|
3
|
-
*
|
|
4
|
-
* Covers the Windows argv-cap workaround (os error 206): the desktop
|
|
5
|
-
* spills long prompts to a temp file and the CLI must read the task
|
|
6
|
-
* from it exactly like the inline --task flag.
|
|
7
|
-
*
|
|
8
|
-
* @since v1.44.0
|
|
9
|
-
*/
|
|
10
|
-
import { describe, it, expect, afterEach } from 'vitest';
|
|
11
|
-
import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
12
|
-
import { tmpdir } from 'node:os';
|
|
13
|
-
import { join } from 'node:path';
|
|
14
|
-
import { parseHeadlessFlags } from './headless.js';
|
|
15
|
-
const dirs = [];
|
|
16
|
-
function tmpFile(content) {
|
|
17
|
-
const dir = mkdtempSync(join(tmpdir(), 'zelari-headless-test-'));
|
|
18
|
-
dirs.push(dir);
|
|
19
|
-
const p = join(dir, 'task.txt');
|
|
20
|
-
writeFileSync(p, content, 'utf-8');
|
|
21
|
-
return p;
|
|
22
|
-
}
|
|
23
|
-
afterEach(() => {
|
|
24
|
-
while (dirs.length) {
|
|
25
|
-
rmSync(dirs.pop(), { recursive: true, force: true });
|
|
26
|
-
}
|
|
27
|
-
});
|
|
28
|
-
describe('parseHeadlessFlags --task-file', () => {
|
|
29
|
-
it('reads the task prompt from a file (argv-cap workaround)', () => {
|
|
30
|
-
const p = tmpFile('Refactor the workspace plan store and verify tests');
|
|
31
|
-
const res = parseHeadlessFlags(['--headless', '--task-file', p]);
|
|
32
|
-
expect(res.options).not.toBeNull();
|
|
33
|
-
expect(res.options?.task).toBe('Refactor the workspace plan store and verify tests');
|
|
34
|
-
expect(res.error).toBeUndefined();
|
|
35
|
-
});
|
|
36
|
-
it('inline --task wins over a previous --task-file (last flag wins)', () => {
|
|
37
|
-
const p = tmpFile('from file');
|
|
38
|
-
const res = parseHeadlessFlags([
|
|
39
|
-
'--headless',
|
|
40
|
-
'--task-file',
|
|
41
|
-
p,
|
|
42
|
-
'--task',
|
|
43
|
-
'inline wins',
|
|
44
|
-
]);
|
|
45
|
-
expect(res.options?.task).toBe('inline wins');
|
|
46
|
-
});
|
|
47
|
-
it('missing file leaves task undefined → clear validation error', () => {
|
|
48
|
-
const res = parseHeadlessFlags([
|
|
49
|
-
'--headless',
|
|
50
|
-
'--task-file',
|
|
51
|
-
'Z:/definitely/not/here/task.txt',
|
|
52
|
-
]);
|
|
53
|
-
expect(res.options).toBeNull();
|
|
54
|
-
expect(res.error).toMatch(/requires --task/);
|
|
55
|
-
});
|
|
56
|
-
it('empty file also degrades to the validation error', () => {
|
|
57
|
-
const p = tmpFile(' ');
|
|
58
|
-
const res = parseHeadlessFlags(['--headless', '--task-file', p]);
|
|
59
|
-
expect(res.options).toBeNull();
|
|
60
|
-
expect(res.error).toMatch(/requires --task/);
|
|
61
|
-
});
|
|
62
|
-
it('still mutually exclusive with --kraken-graph', () => {
|
|
63
|
-
const p = tmpFile('do the graph thing');
|
|
64
|
-
const res = parseHeadlessFlags([
|
|
65
|
-
'--headless',
|
|
66
|
-
'--task-file',
|
|
67
|
-
p,
|
|
68
|
-
'--kraken-graph',
|
|
69
|
-
'goal',
|
|
70
|
-
]);
|
|
71
|
-
expect(res.options).toBeNull();
|
|
72
|
-
expect(res.error).toMatch(/mutually exclusive/);
|
|
73
|
-
});
|
|
74
|
-
});
|
|
75
|
-
describe('parseHeadlessFlags --kraken-graph-file', () => {
|
|
76
|
-
it('reads the graph goal from a file', () => {
|
|
77
|
-
const p = tmpFile('Plan + execute the release DAG');
|
|
78
|
-
const res = parseHeadlessFlags(['--headless', '--kraken-graph-file', p]);
|
|
79
|
-
expect(res.options).not.toBeNull();
|
|
80
|
-
expect(res.options?.krakenGraph).toBe('Plan + execute the release DAG');
|
|
81
|
-
});
|
|
82
|
-
it('inline --kraken-graph wins over a previous --kraken-graph-file', () => {
|
|
83
|
-
const p = tmpFile('from file');
|
|
84
|
-
const res = parseHeadlessFlags([
|
|
85
|
-
'--headless',
|
|
86
|
-
'--kraken-graph-file',
|
|
87
|
-
p,
|
|
88
|
-
'--kraken-graph',
|
|
89
|
-
'inline goal',
|
|
90
|
-
]);
|
|
91
|
-
expect(res.options?.krakenGraph).toBe('inline goal');
|
|
92
|
-
});
|
|
93
|
-
it('mutually exclusive with --task-file as well', () => {
|
|
94
|
-
const a = tmpFile('task a');
|
|
95
|
-
const b = tmpFile('graph b');
|
|
96
|
-
const res = parseHeadlessFlags([
|
|
97
|
-
'--headless',
|
|
98
|
-
'--task-file',
|
|
99
|
-
a,
|
|
100
|
-
'--kraken-graph-file',
|
|
101
|
-
b,
|
|
102
|
-
]);
|
|
103
|
-
expect(res.options).toBeNull();
|
|
104
|
-
expect(res.error).toMatch(/mutually exclusive/);
|
|
105
|
-
});
|
|
106
|
-
});
|
|
107
|
-
//# sourceMappingURL=headless.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"headless.test.js","sourceRoot":"","sources":["../../src/cli/headless.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,189 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* F11 / Exit-3.6 — headless session smoke, end-to-end (doc §14).
|
|
3
|
-
*
|
|
4
|
-
* Product-level chain, executed against the REAL `runHeadless` pipeline for
|
|
5
|
-
* both Kraken and Council:
|
|
6
|
-
*
|
|
7
|
-
* headless run → session_started (NDJSON) → session id → --resume second
|
|
8
|
-
* turn → --export-session → fresh reader/replay → same semantic trajectory
|
|
9
|
-
*
|
|
10
|
-
* The ONLY mocked seam is `provider/resolveStream.js` (deterministic echo
|
|
11
|
-
* stream — "provider fake/deterministici dove possibile"): key resolution,
|
|
12
|
-
* spine open/resume, dual-write, export and replay are all the real product
|
|
13
|
-
* code paths a Desktop host exercises.
|
|
14
|
-
*
|
|
15
|
-
* Trajectory equality: deriveMessages() over (a) the log after turn 2,
|
|
16
|
-
* (b) a second fresh readSessionLog (new reader), (c) the exported
|
|
17
|
-
* zelari-session-export/1 events — all three must be deep-equal.
|
|
18
|
-
*/
|
|
19
|
-
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
20
|
-
import { promises as fs } from 'node:fs';
|
|
21
|
-
import path from 'node:path';
|
|
22
|
-
import os from 'node:os';
|
|
23
|
-
import { deriveMessages, readSessionLog } from '@zelari/core/session';
|
|
24
|
-
vi.mock('./provider/resolveStream.js', () => ({
|
|
25
|
-
// Deterministic provider: reply echoes the tail of the last user message,
|
|
26
|
-
// so turn 1 and turn 2 replies differ deterministically. Pure text — no
|
|
27
|
-
// tool calls — which is exactly the Desktop Q&A turn shape.
|
|
28
|
-
buildProviderStream: () => async function* fakeDeterministicStream(params) {
|
|
29
|
-
const lastUser = [...params.messages].reverse().find((m) => m.role === 'user');
|
|
30
|
-
const raw = lastUser?.content;
|
|
31
|
-
const text = typeof raw === 'string' ? raw : JSON.stringify(raw ?? 'no-user');
|
|
32
|
-
yield { kind: 'text', delta: `e2e-reply:${text.slice(-48)}` };
|
|
33
|
-
yield { kind: 'finish', reason: 'stop' };
|
|
34
|
-
},
|
|
35
|
-
}));
|
|
36
|
-
import { runHeadless } from './runHeadless.js';
|
|
37
|
-
let tmp;
|
|
38
|
-
let sessionsDir;
|
|
39
|
-
let savedEnv;
|
|
40
|
-
const ENV_KEYS = [
|
|
41
|
-
'OPENAI_API_KEY',
|
|
42
|
-
'ZELARI_SESSIONS_DIR',
|
|
43
|
-
'ZELARI_LOCAL_CLI',
|
|
44
|
-
'ZELARI_STRICT_DONE',
|
|
45
|
-
'ZELARI_VERIFY_PACK',
|
|
46
|
-
'ZELARI_PERM_SOCKET',
|
|
47
|
-
];
|
|
48
|
-
beforeEach(() => {
|
|
49
|
-
tmp = path.join(os.tmpdir(), `zelari-e2e-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
50
|
-
sessionsDir = path.join(tmp, 'sessions');
|
|
51
|
-
savedEnv = {};
|
|
52
|
-
for (const k of ENV_KEYS)
|
|
53
|
-
savedEnv[k] = process.env[k];
|
|
54
|
-
process.env.OPENAI_API_KEY = 'e2e-deterministic-key';
|
|
55
|
-
process.env.ZELARI_SESSIONS_DIR = sessionsDir;
|
|
56
|
-
// Never let a developer-machine environment leak into the product path.
|
|
57
|
-
delete process.env.ZELARI_LOCAL_CLI;
|
|
58
|
-
delete process.env.ZELARI_STRICT_DONE;
|
|
59
|
-
delete process.env.ZELARI_VERIFY_PACK;
|
|
60
|
-
delete process.env.ZELARI_PERM_SOCKET;
|
|
61
|
-
});
|
|
62
|
-
afterEach(() => {
|
|
63
|
-
for (const k of ENV_KEYS) {
|
|
64
|
-
const v = savedEnv[k];
|
|
65
|
-
if (v === undefined)
|
|
66
|
-
delete process.env[k];
|
|
67
|
-
else
|
|
68
|
-
process.env[k] = v;
|
|
69
|
-
}
|
|
70
|
-
return fs.rm(tmp, { recursive: true, force: true });
|
|
71
|
-
});
|
|
72
|
-
/** Capture (and swallow) stdout+stderr while the headless run emits NDJSON. */
|
|
73
|
-
async function captureOutput(fn) {
|
|
74
|
-
const out = process.stdout.write.bind(process.stdout);
|
|
75
|
-
const err = process.stderr.write.bind(process.stderr);
|
|
76
|
-
const lines = [];
|
|
77
|
-
const collect = (chunk) => {
|
|
78
|
-
lines.push(String(chunk));
|
|
79
|
-
return true;
|
|
80
|
-
};
|
|
81
|
-
process.stdout.write = collect;
|
|
82
|
-
process.stderr.write = collect;
|
|
83
|
-
const restore = () => {
|
|
84
|
-
process.stdout.write = out;
|
|
85
|
-
process.stderr.write = err;
|
|
86
|
-
};
|
|
87
|
-
try {
|
|
88
|
-
const result = await fn();
|
|
89
|
-
return { result, lines };
|
|
90
|
-
}
|
|
91
|
-
finally {
|
|
92
|
-
restore();
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
function parseNdjson(lines) {
|
|
96
|
-
const events = [];
|
|
97
|
-
for (const line of lines) {
|
|
98
|
-
for (const part of line.split('\n')) {
|
|
99
|
-
const t = part.trim();
|
|
100
|
-
if (!t.startsWith('{'))
|
|
101
|
-
continue;
|
|
102
|
-
try {
|
|
103
|
-
events.push(JSON.parse(t));
|
|
104
|
-
}
|
|
105
|
-
catch {
|
|
106
|
-
/* not JSON — ignore */
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
return events;
|
|
111
|
-
}
|
|
112
|
-
function trajectory(events) {
|
|
113
|
-
return deriveMessages(events).map((m) => `${m.role}:${m.content}`);
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* The full §14 chain for one mode. Everything asserted here is the contract
|
|
117
|
-
* a Desktop host depends on: stable session id across turns, seq continuity,
|
|
118
|
-
* export round-trip, replay determinism.
|
|
119
|
-
*/
|
|
120
|
-
async function runModeChain(mode) {
|
|
121
|
-
const base = {
|
|
122
|
-
mode,
|
|
123
|
-
phase: 'build',
|
|
124
|
-
useCouncil: false,
|
|
125
|
-
output: 'json',
|
|
126
|
-
provider: 'openai-compatible',
|
|
127
|
-
model: 'e2e-fake-model',
|
|
128
|
-
};
|
|
129
|
-
// --- Turn 1: fresh run → session_started → session id -------------------
|
|
130
|
-
const t1 = await captureOutput(() => runHeadless({ ...base, task: `e2e smoke ${mode} turn one question` }));
|
|
131
|
-
expect(t1.result, `${mode} turn 1 must exit 0`).toBe(0);
|
|
132
|
-
const started = parseNdjson(t1.lines).find((e) => e.type === 'session_started');
|
|
133
|
-
expect(started, `${mode} turn 1 must emit session_started NDJSON`).toBeDefined();
|
|
134
|
-
const sessionId = String(started.sessionId);
|
|
135
|
-
expect(sessionId.length).toBeGreaterThan(0);
|
|
136
|
-
const logPath = path.join(sessionsDir, sessionId, 'events.jsonl');
|
|
137
|
-
const after1 = await readSessionLog(logPath);
|
|
138
|
-
expect(after1.ok).toBe(true);
|
|
139
|
-
expect(after1.issues).toEqual([]);
|
|
140
|
-
expect(after1.events.some((e) => e.kind === 'session.started')).toBe(true);
|
|
141
|
-
expect(after1.events.some((e) => e.kind === 'user.message')).toBe(true);
|
|
142
|
-
expect(after1.events.some((e) => e.kind === 'assistant.message')).toBe(true);
|
|
143
|
-
// --- Turn 2: resume SAME id + export ------------------------------------
|
|
144
|
-
const exportPath = path.join(tmp, `export-${mode}.json`);
|
|
145
|
-
const t2 = await captureOutput(() => runHeadless({
|
|
146
|
-
...base,
|
|
147
|
-
task: `e2e smoke ${mode} turn two question`,
|
|
148
|
-
resumeSessionId: sessionId,
|
|
149
|
-
exportSessionPath: exportPath,
|
|
150
|
-
}));
|
|
151
|
-
expect(t2.result, `${mode} turn 2 (resume) must exit 0`).toBe(0);
|
|
152
|
-
const after2 = await readSessionLog(logPath);
|
|
153
|
-
expect(after2.ok).toBe(true);
|
|
154
|
-
expect(after2.issues).toEqual([]);
|
|
155
|
-
expect(after2.events.some((e) => e.kind === 'session.resumed')).toBe(true);
|
|
156
|
-
// Same log, seq still monotonic from 1 — resume adopts, never rewrites.
|
|
157
|
-
after2.events.forEach((e, i) => expect(e.seq).toBe(i + 1));
|
|
158
|
-
expect(after2.events.length).toBeGreaterThan(after1.events.length);
|
|
159
|
-
// Both turns are in the canonical trajectory, in order.
|
|
160
|
-
const users = trajectory(after2.events).filter((t) => t.startsWith('user:'));
|
|
161
|
-
const i1 = users.findIndex((u) => u.includes('turn one question'));
|
|
162
|
-
const i2 = users.findIndex((u) => u.includes('turn two question'));
|
|
163
|
-
expect(i1, 'turn one prompt must be in the derived trajectory').toBeGreaterThanOrEqual(0);
|
|
164
|
-
expect(i2, 'turn two prompt must be in the derived trajectory').toBeGreaterThan(i1);
|
|
165
|
-
// --- Export round-trip (zelari-session-export/1) ------------------------
|
|
166
|
-
const exported = JSON.parse(await fs.readFile(exportPath, 'utf8'));
|
|
167
|
-
expect(exported.events.length).toBe(after2.events.length);
|
|
168
|
-
// --- Fresh reader/replay → same semantic trajectory ---------------------
|
|
169
|
-
const freshRead = await readSessionLog(logPath);
|
|
170
|
-
expect(freshRead.ok).toBe(true);
|
|
171
|
-
const fromLog = trajectory(after2.events);
|
|
172
|
-
const fromFresh = trajectory(freshRead.events);
|
|
173
|
-
const fromExport = trajectory(exported.events);
|
|
174
|
-
expect(fromFresh, 'two fresh replays must be deep-equal').toEqual(fromLog);
|
|
175
|
-
expect(fromExport, 'export must carry the same semantic trajectory').toEqual(fromLog);
|
|
176
|
-
expect(fromLog.some((t) => t.startsWith('assistant:e2e-reply:'))).toBe(true);
|
|
177
|
-
}
|
|
178
|
-
describe('Exit-3.6 — headless session e2e smoke (run → resume → export → replay)', () => {
|
|
179
|
-
it('kraken: full chain preserves the semantic trajectory', async () => {
|
|
180
|
-
await runModeChain('kraken');
|
|
181
|
-
// 90s: the kraken chain cold-imports the whole headless pipeline in-process;
|
|
182
|
-
// under full-suite parallel load (341 files on vitest 4) 30s proved too
|
|
183
|
-
// tight — in isolation the whole file runs in ~11s.
|
|
184
|
-
}, 90_000);
|
|
185
|
-
it('council: full chain preserves the semantic trajectory', async () => {
|
|
186
|
-
await runModeChain('council');
|
|
187
|
-
}, 30_000);
|
|
188
|
-
});
|
|
189
|
-
//# sourceMappingURL=headlessE2eSession.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"headlessE2eSession.test.js","sourceRoot":"","sources":["../../src/cli/headlessE2eSession.test.ts"],"names":[],"mappings":"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"}
|