zelari-code 1.28.0 → 1.30.0

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 (60) hide show
  1. package/dist/cli/headless.js +14 -0
  2. package/dist/cli/headless.js.map +1 -1
  3. package/dist/cli/hooks/useSlashDispatch.js +11 -0
  4. package/dist/cli/hooks/useSlashDispatch.js.map +1 -1
  5. package/dist/cli/kraken/executor.js +725 -42
  6. package/dist/cli/kraken/executor.js.map +1 -1
  7. package/dist/cli/kraken/graphMemory.js +27 -5
  8. package/dist/cli/kraken/graphMemory.js.map +1 -1
  9. package/dist/cli/kraken/graphStatus.js +59 -0
  10. package/dist/cli/kraken/graphStatus.js.map +1 -1
  11. package/dist/cli/kraken/planner.js +189 -12
  12. package/dist/cli/kraken/planner.js.map +1 -1
  13. package/dist/cli/kraken/planner.test.js +43 -0
  14. package/dist/cli/kraken/planner.test.js.map +1 -0
  15. package/dist/cli/kraken/runtime/compile.js +73 -0
  16. package/dist/cli/kraken/runtime/compile.js.map +1 -0
  17. package/dist/cli/kraken/runtime/runScriptPlan.js +195 -0
  18. package/dist/cli/kraken/runtime/runScriptPlan.js.map +1 -0
  19. package/dist/cli/kraken/scriptPlanner.js +286 -0
  20. package/dist/cli/kraken/scriptPlanner.js.map +1 -0
  21. package/dist/cli/kraken/scriptPlanner.test.js +152 -0
  22. package/dist/cli/kraken/scriptPlanner.test.js.map +1 -0
  23. package/dist/cli/kraken/skillSuggest.js +97 -0
  24. package/dist/cli/kraken/skillSuggest.js.map +1 -0
  25. package/dist/cli/kraken/skillSuggest.test.js +157 -0
  26. package/dist/cli/kraken/skillSuggest.test.js.map +1 -0
  27. package/dist/cli/kraken/weaknessMeter.js +183 -0
  28. package/dist/cli/kraken/weaknessMeter.js.map +1 -0
  29. package/dist/cli/kraken/weaknessMeter.test.js +212 -0
  30. package/dist/cli/kraken/weaknessMeter.test.js.map +1 -0
  31. package/dist/cli/kraken/workbench.js +296 -0
  32. package/dist/cli/kraken/workbench.js.map +1 -0
  33. package/dist/cli/kraken/workbench.test.js +253 -0
  34. package/dist/cli/kraken/workbench.test.js.map +1 -0
  35. package/dist/cli/kraken/workbenchView.js +155 -0
  36. package/dist/cli/kraken/workbenchView.js.map +1 -0
  37. package/dist/cli/kraken/workbenchView.test.js +130 -0
  38. package/dist/cli/kraken/workbenchView.test.js.map +1 -0
  39. package/dist/cli/main.bundled.js +2930 -353
  40. package/dist/cli/main.bundled.js.map +4 -4
  41. package/dist/cli/runHeadless.js +83 -8
  42. package/dist/cli/runHeadless.js.map +1 -1
  43. package/dist/cli/slashCommands.js +16 -0
  44. package/dist/cli/slashCommands.js.map +1 -1
  45. package/dist/cli/slashHandlers/krakenFanout.js +200 -0
  46. package/dist/cli/slashHandlers/krakenFanout.js.map +1 -0
  47. package/dist/cli/slashHandlers/krakenGraph.js +10 -3
  48. package/dist/cli/slashHandlers/krakenGraph.js.map +1 -1
  49. package/dist/cli/slashHandlers/krakenWorkbench.js +49 -0
  50. package/dist/cli/slashHandlers/krakenWorkbench.js.map +1 -0
  51. package/dist/cli/tools/krakenCsvFanout.js +260 -0
  52. package/dist/cli/tools/krakenCsvFanout.js.map +1 -0
  53. package/dist/cli/tools/krakenCsvFanout.test.js +200 -0
  54. package/dist/cli/tools/krakenCsvFanout.test.js.map +1 -0
  55. package/dist/cli/tools/krakenModel.js +32 -0
  56. package/dist/cli/tools/krakenModel.js.map +1 -1
  57. package/dist/cli/tools/krakenRadio.js.map +1 -1
  58. package/dist/cli/tools/taskTool.js +2 -2
  59. package/dist/cli/tools/taskTool.js.map +1 -1
  60. package/package.json +2 -2
@@ -0,0 +1,155 @@
1
+ /**
2
+ * Kraken workbench — pure parser + renderer (F3.2 TUI viewer).
3
+ *
4
+ * The workbench writer (`workbench.ts`) produces a Markdown file. This
5
+ * module parses that file back into a structured form and renders it as
6
+ * a text block suitable for the TUI (Ink) transcript or a tail-able
7
+ * text view.
8
+ *
9
+ * The parser is **deliberately tolerant**: a partial or truncated file
10
+ * (mid-write, mid-rename) must not throw. Missing sections render as
11
+ * empty rather than as a stack trace.
12
+ *
13
+ * @since Kraken v1.30.x — workflow script runtime (Pillar 3 F3.2)
14
+ */
15
+ const EMPTY = {
16
+ goal: '',
17
+ graphId: '',
18
+ started: '',
19
+ elapsed: '',
20
+ progress: '',
21
+ nodes: [],
22
+ events: [],
23
+ };
24
+ /** Parse a workbench Markdown file into a structured form. Tolerant. */
25
+ export function parseWorkbench(content) {
26
+ if (!content)
27
+ return { ...EMPTY, nodes: [], events: [] };
28
+ const lines = content.split(/\r?\n/);
29
+ const out = { ...EMPTY, nodes: [], events: [] };
30
+ let i = 0;
31
+ while (i < lines.length) {
32
+ const line = lines[i];
33
+ // Header: `**Goal:**`, `**Graph id:**`, `**Started:** ... · **Elapsed:** ...`
34
+ const goalM = /^\*\*Goal:\*\*\s*(.*)$/.exec(line);
35
+ if (goalM) {
36
+ out.goal = goalM[1];
37
+ i += 1;
38
+ continue;
39
+ }
40
+ const gidM = /^\*\*Graph id:\*\*\s*`?([^`\s]*)`?/.exec(line);
41
+ if (gidM) {
42
+ out.graphId = gidM[1];
43
+ i += 1;
44
+ continue;
45
+ }
46
+ const startedM = /^\*\*Started:\*\*\s*(.+?)\s*·\s*\*\*Elapsed:\*\*\s*(\S+)/.exec(line);
47
+ if (startedM) {
48
+ out.started = startedM[1];
49
+ out.elapsed = startedM[2];
50
+ i += 1;
51
+ continue;
52
+ }
53
+ const justStarted = /^\*\*Started:\*\*\s*(.*)$/.exec(line);
54
+ if (justStarted) {
55
+ out.started = justStarted[1];
56
+ i += 1;
57
+ continue;
58
+ }
59
+ // Section header: `## Section` or `## Section: data`. The section name
60
+ // is anything up to the first whitespace or colon, so `## Progress: 2/5`
61
+ // gives section='Progress', inline='2/5'; `## Events (latest 30)` gives
62
+ // section='Events' and the `(latest 30)` is dropped. No `$` anchor:
63
+ // when the inline group doesn't match (no `:` after the section name),
64
+ // an anchored `$` would require the regex to be at end-of-line, which
65
+ // it isn't because the section name is followed by a space.
66
+ const sectionM = /^##\s+([^:\s]+)(?::\s*(.*))?/.exec(line);
67
+ if (!sectionM) {
68
+ i += 1;
69
+ continue;
70
+ }
71
+ const section = sectionM[1];
72
+ const inline = sectionM[2] ?? '';
73
+ if (section === 'Progress') {
74
+ if (inline)
75
+ out.progress = inline;
76
+ i += 1;
77
+ continue;
78
+ }
79
+ if (section === 'Wave') {
80
+ // Skip until the first DATA row (starts with `| t`), not just any
81
+ // `|`. The header row `| id | label | ...` does not match `| t` so we
82
+ // walk past it cleanly. Tolerates blank lines between the section
83
+ // header and the table.
84
+ while (i < lines.length && !lines[i].startsWith('| t'))
85
+ i += 1;
86
+ // Read data rows.
87
+ while (i < lines.length && lines[i].startsWith('| t')) {
88
+ const cells = splitRow(lines[i]);
89
+ if (cells.length >= 7) {
90
+ out.nodes.push({
91
+ id: cells[0],
92
+ label: cells[1],
93
+ kind: cells[2],
94
+ scope: cells[3],
95
+ status: cells[4],
96
+ model: cells[5],
97
+ duration: cells[6],
98
+ });
99
+ }
100
+ i += 1;
101
+ }
102
+ continue;
103
+ }
104
+ if (section === 'Events' || section.startsWith('Events')) {
105
+ // Skip blank lines between the section header and the first event.
106
+ while (i < lines.length && !lines[i].startsWith('- '))
107
+ i += 1;
108
+ while (i < lines.length && lines[i].startsWith('- ')) {
109
+ const m = /^-\s+(\d{2}:\d{2}:\d{2})\s+(.*)$/.exec(lines[i]);
110
+ if (m)
111
+ out.events.push({ ts: m[1], text: m[2] });
112
+ i += 1;
113
+ }
114
+ continue;
115
+ }
116
+ // Unknown section: skip.
117
+ i += 1;
118
+ }
119
+ return out;
120
+ }
121
+ function splitRow(line) {
122
+ return line
123
+ .replace(/^\|/, '')
124
+ .replace(/\|$/, '')
125
+ .split('|')
126
+ .map((c) => c.trim());
127
+ }
128
+ /** Render a parsed workbench as a fixed-width text block. */
129
+ export function formatWorkbenchForTerminal(p) {
130
+ const lines = [];
131
+ if (p.goal)
132
+ lines.push(`[kraken] ${p.goal}`);
133
+ if (p.progress)
134
+ lines.push(`[kraken] progress: ${p.progress}`);
135
+ if (p.elapsed)
136
+ lines.push(`[kraken] elapsed: ${p.elapsed}`);
137
+ lines.push('');
138
+ if (p.nodes.length > 0) {
139
+ lines.push('[kraken] wave:');
140
+ for (const n of p.nodes) {
141
+ const scope = n.scope ? ` (${n.scope})` : '';
142
+ const dur = n.duration ? ` ${n.duration}` : '';
143
+ lines.push(` ${n.status} ${n.id} ${n.label}${scope}${dur ? ' ' + dur : ''}`);
144
+ }
145
+ lines.push('');
146
+ }
147
+ if (p.events.length > 0) {
148
+ lines.push('[kraken] events (latest):');
149
+ for (const e of p.events.slice(-10)) {
150
+ lines.push(` ${e.ts} ${e.text}`);
151
+ }
152
+ }
153
+ return lines.join('\n');
154
+ }
155
+ //# sourceMappingURL=workbenchView.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workbenchView.js","sourceRoot":"","sources":["../../../src/cli/kraken/workbenchView.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Kraken workbench view — tests.
3
+ *
4
+ * Covers:
5
+ * - `parseWorkbench` round-trips a workbench file produced by the writer
6
+ * - Tolerant: partial / truncated input does not throw
7
+ * - `formatWorkbenchForTerminal` produces a readable text block
8
+ */
9
+ import { describe, it, expect } from 'vitest';
10
+ import { parseWorkbench, formatWorkbenchForTerminal } from './workbenchView.js';
11
+ import { WorkbenchWriter } from './workbench.js';
12
+ import { promises as fs } from 'node:fs';
13
+ import os from 'node:os';
14
+ import path from 'node:path';
15
+ const SAMPLE = `# Kraken workbench
16
+
17
+ **Goal:** refactor auth
18
+ **Graph id:** \`g-abc\`
19
+ **Started:** 2026-08-08T11:00:00.000Z · **Elapsed:** 00:01:23
20
+
21
+ ## Progress: 2/5 · 1↑ · 0✗
22
+
23
+ ## Wave
24
+
25
+ | id | label | kind | scope | status | model | duration |
26
+ |----|-------|------|-------|--------|-------|----------|
27
+ | t0001 | map auth | explore | src/auth | ✓ | grok-3-mini | 4.0s |
28
+ | t0002 | refactor | general | src/auth | ✓ | grok-4.5 | 12.3s |
29
+ | t0003 | test | general | tests/auth | ↑ | grok-4.5 | |
30
+ | t0004 | judge | verify | | pending | | |
31
+ | t0005 | merge | merge | | pending | | |
32
+
33
+ ## Events (latest 30)
34
+
35
+ - 11:00:01 node_start t0001 map auth
36
+ - 11:00:05 node_end t0001 done (4000ms)
37
+ - 11:00:06 node_start t0002 refactor
38
+ - 11:00:18 node_end t0002 done (12300ms)
39
+ - 11:00:18 node_start t0003 test
40
+ `;
41
+ describe('parseWorkbench', () => {
42
+ it('parses a full workbench file', () => {
43
+ const p = parseWorkbench(SAMPLE);
44
+ expect(p.goal).toBe('refactor auth');
45
+ expect(p.graphId).toBe('g-abc');
46
+ expect(p.started).toContain('2026-08-08');
47
+ expect(p.progress).toContain('2/5');
48
+ expect(p.nodes).toHaveLength(5);
49
+ expect(p.nodes[0]).toMatchObject({
50
+ id: 't0001',
51
+ label: 'map auth',
52
+ kind: 'explore',
53
+ scope: 'src/auth',
54
+ status: '✓',
55
+ model: 'grok-3-mini',
56
+ duration: '4.0s',
57
+ });
58
+ expect(p.events).toHaveLength(5);
59
+ expect(p.events[0]).toEqual({ ts: '11:00:01', text: 'node_start t0001 map auth' });
60
+ });
61
+ it('returns empty for empty / null input', () => {
62
+ expect(parseWorkbench('')).toEqual({
63
+ goal: '', graphId: '', started: '', elapsed: '', progress: '',
64
+ nodes: [], events: [],
65
+ });
66
+ expect(parseWorkbench(undefined)).toEqual({
67
+ goal: '', graphId: '', started: '', elapsed: '', progress: '',
68
+ nodes: [], events: [],
69
+ });
70
+ expect(parseWorkbench(null)).toEqual({
71
+ goal: '', graphId: '', started: '', elapsed: '', progress: '',
72
+ nodes: [], events: [],
73
+ });
74
+ });
75
+ it('tolerates a truncated file (only header, no sections)', () => {
76
+ const p = parseWorkbench('# Kraken workbench\n\n**Goal:** x\n');
77
+ expect(p.goal).toBe('x');
78
+ expect(p.nodes).toEqual([]);
79
+ expect(p.events).toEqual([]);
80
+ });
81
+ it('tolerates a partial events section', () => {
82
+ const p = parseWorkbench('# Kraken workbench\n\n## Events (latest 30)\n\n- 11:00:01 hello\n');
83
+ expect(p.events).toHaveLength(1);
84
+ expect(p.events[0].text).toBe('hello');
85
+ });
86
+ it('ignores rows that do not have enough cells', () => {
87
+ const content = `
88
+ ## Wave
89
+
90
+ | id | label | kind | scope | status | model | duration |
91
+ |----|-------|------|-------|--------|-------|----------|
92
+ | t0001 ok
93
+ `;
94
+ const p = parseWorkbench(content);
95
+ expect(p.nodes).toEqual([]); // row has only 1 cell, dropped
96
+ });
97
+ it('round-trips with the writer', async () => {
98
+ const tmp = await fs.mkdtemp(path.join(os.tmpdir(), 'kraken-wb-view-'));
99
+ const w = new WorkbenchWriter({ cwd: tmp, graphId: 'g-rt', goal: 'rt test', debounceMs: 0 });
100
+ w.setNodes([
101
+ { id: 't0001', kind: 'explore', label: 'a', status: 'done', model: 'm1', durationMs: 100 },
102
+ { id: 't0002', kind: 'general', label: 'b', status: 'running', scope: ['src/x'] },
103
+ ]);
104
+ w.logEvent('event 1');
105
+ w.logEvent('event 2');
106
+ const out = await w.flush();
107
+ const content = await fs.readFile(out, 'utf8');
108
+ const parsed = parseWorkbench(content);
109
+ expect(parsed.goal).toBe('rt test');
110
+ expect(parsed.graphId).toBe('g-rt');
111
+ expect(parsed.nodes).toHaveLength(2);
112
+ expect(parsed.events.length).toBeGreaterThanOrEqual(2);
113
+ });
114
+ });
115
+ describe('formatWorkbenchForTerminal', () => {
116
+ it('includes the goal, progress, and recent events', () => {
117
+ const out = formatWorkbenchForTerminal(parseWorkbench(SAMPLE));
118
+ expect(out).toContain('[kraken] refactor auth');
119
+ expect(out).toContain('[kraken] progress: 2/5');
120
+ expect(out).toContain('[kraken] wave:');
121
+ expect(out).toContain('t0001 map auth');
122
+ expect(out).toContain('11:00:01 node_start t0001');
123
+ });
124
+ it('produces a readable block for an empty workbench', () => {
125
+ const out = formatWorkbenchForTerminal(parseWorkbench(''));
126
+ // Empty workbench → empty render (nothing to show).
127
+ expect(out.trim()).toBe('');
128
+ });
129
+ });
130
+ //# sourceMappingURL=workbenchView.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workbenchView.test.js","sourceRoot":"","sources":["../../../src/cli/kraken/workbenchView.test.ts"],"names":[],"mappings":"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"}