@kodax-ai/kodax 0.7.95 → 0.7.96-alpha.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 (163) hide show
  1. package/CHANGELOG.md +178 -1
  2. package/LICENSE +158 -158
  3. package/README.md +149 -24
  4. package/README_CN.md +117 -24
  5. package/config-templates/config.example.jsonc +2 -1
  6. package/config-templates/integrations/a2a.example.jsonc +91 -91
  7. package/config-templates/integrations/extensions.example.jsonc +7 -7
  8. package/config-templates/integrations/mcp.example.jsonc +16 -16
  9. package/dist/builtin/code-review/SKILL.md +82 -82
  10. package/dist/builtin/git-workflow/SKILL.md +84 -84
  11. package/dist/builtin/skill-creator/SKILL.md +127 -127
  12. package/dist/builtin/skill-creator/agents/analyzer.md +12 -12
  13. package/dist/builtin/skill-creator/agents/comparator.md +13 -13
  14. package/dist/builtin/skill-creator/agents/grader.md +13 -13
  15. package/dist/builtin/skill-creator/references/schemas.md +227 -227
  16. package/dist/builtin/skill-creator/scripts/aggregate-benchmark.d.ts +46 -46
  17. package/dist/builtin/skill-creator/scripts/aggregate-benchmark.js +208 -208
  18. package/dist/builtin/skill-creator/scripts/analyze-benchmark.d.ts +46 -46
  19. package/dist/builtin/skill-creator/scripts/analyze-benchmark.js +286 -286
  20. package/dist/builtin/skill-creator/scripts/compare-runs.d.ts +62 -62
  21. package/dist/builtin/skill-creator/scripts/compare-runs.js +330 -330
  22. package/dist/builtin/skill-creator/scripts/generate-review.d.ts +33 -33
  23. package/dist/builtin/skill-creator/scripts/generate-review.js +414 -414
  24. package/dist/builtin/skill-creator/scripts/grade-evals.d.ts +73 -73
  25. package/dist/builtin/skill-creator/scripts/grade-evals.js +402 -402
  26. package/dist/builtin/skill-creator/scripts/improve-description.d.ts +23 -23
  27. package/dist/builtin/skill-creator/scripts/improve-description.js +160 -160
  28. package/dist/builtin/skill-creator/scripts/init-skill.d.ts +14 -14
  29. package/dist/builtin/skill-creator/scripts/init-skill.js +155 -155
  30. package/dist/builtin/skill-creator/scripts/install-skill.d.ts +29 -29
  31. package/dist/builtin/skill-creator/scripts/install-skill.js +173 -173
  32. package/dist/builtin/skill-creator/scripts/package-skill.d.ts +38 -38
  33. package/dist/builtin/skill-creator/scripts/package-skill.js +121 -121
  34. package/dist/builtin/skill-creator/scripts/quick-validate.d.ts +8 -8
  35. package/dist/builtin/skill-creator/scripts/quick-validate.js +163 -163
  36. package/dist/builtin/skill-creator/scripts/run-eval.d.ts +66 -66
  37. package/dist/builtin/skill-creator/scripts/run-eval.js +353 -353
  38. package/dist/builtin/skill-creator/scripts/run-loop.d.ts +49 -49
  39. package/dist/builtin/skill-creator/scripts/run-loop.js +242 -242
  40. package/dist/builtin/skill-creator/scripts/run-trigger-eval.d.ts +58 -58
  41. package/dist/builtin/skill-creator/scripts/run-trigger-eval.js +224 -224
  42. package/dist/builtin/tdd/SKILL.md +56 -56
  43. package/dist/chunks/agent-4FABF6WK.js +2 -0
  44. package/dist/chunks/argument-completer-72VHB2VL.js +2 -0
  45. package/dist/chunks/{chunk-7JXA3533.js → chunk-4OIQZWA5.js} +223 -226
  46. package/dist/chunks/{chunk-BNVSKIAB.js → chunk-6BVF3HZ7.js} +136 -136
  47. package/dist/chunks/chunk-7JZZIFZH.js +501 -0
  48. package/dist/chunks/chunk-AC7Z2OIY.js +2 -0
  49. package/dist/chunks/{chunk-JS452J2F.js → chunk-C4KYZAFU.js} +2 -2
  50. package/dist/chunks/chunk-CHUPIWIF.js +251 -0
  51. package/dist/chunks/{chunk-C4DTUKTR.js → chunk-GYUU7XLH.js} +5 -4
  52. package/dist/chunks/{chunk-OK4AXDC5.js → chunk-HAX55GOQ.js} +1 -1
  53. package/dist/chunks/chunk-JKTJCGO2.js +418 -0
  54. package/dist/chunks/{chunk-O743AJ5V.js → chunk-LQYETRFK.js} +171 -175
  55. package/dist/chunks/{chunk-2PEDBGKN.js → chunk-LTUZTQ6W.js} +1 -1
  56. package/dist/chunks/chunk-LYWDUSKO.js +2 -0
  57. package/dist/chunks/chunk-NGH6T4FD.js +92 -0
  58. package/dist/chunks/{chunk-SRIJX5ZP.js → chunk-NVRWCSA5.js} +1 -1
  59. package/dist/chunks/chunk-O4DS7RIQ.js +384 -0
  60. package/dist/chunks/chunk-ORXU6OWZ.js +2 -0
  61. package/dist/chunks/chunk-POTW3O65.js +124 -0
  62. package/dist/chunks/{chunk-2TM3W3GK.js → chunk-RIQSS56Y.js} +1 -1
  63. package/dist/chunks/chunk-U27XKEN5.js +407 -0
  64. package/dist/chunks/{chunk-6ABQJUK6.js → chunk-XUX6OUCA.js} +2 -2
  65. package/dist/chunks/{client-JDOS3YJR.js → client-4C456K4O.js} +1 -1
  66. package/dist/chunks/compaction-config-3VQRDFF4.js +2 -0
  67. package/dist/chunks/{construction-bootstrap-YCWHHUYO.js → construction-bootstrap-AHN7EDGG.js} +1 -1
  68. package/dist/chunks/dist-BCBQXAGI.js +2 -0
  69. package/dist/chunks/dist-QK2YDWU6.js +2 -0
  70. package/dist/chunks/host-VIHV7ADG.js +2 -0
  71. package/dist/chunks/run-manager-NBVMU3KV.js +2 -0
  72. package/dist/chunks/utils-MEJZ2IGI.js +2 -0
  73. package/dist/index.d.ts +22 -21
  74. package/dist/index.js +7 -7
  75. package/dist/kodax_bootstrap.js +26 -26
  76. package/dist/kodax_cli.js +1905 -1882
  77. package/dist/native/darwin-arm64/LICENSE-APACHE.txt +13 -0
  78. package/dist/native/darwin-arm64/kodax-text-transaction.node +0 -0
  79. package/dist/native/darwin-arm64/manifest.json +16 -0
  80. package/dist/native/darwin-x64/LICENSE-APACHE.txt +13 -0
  81. package/dist/native/darwin-x64/kodax-text-transaction.node +0 -0
  82. package/dist/native/darwin-x64/manifest.json +16 -0
  83. package/dist/native/linux-arm64/LICENSE-APACHE.txt +13 -0
  84. package/dist/native/linux-arm64/kodax-text-transaction.node +0 -0
  85. package/dist/native/linux-arm64/manifest.json +16 -0
  86. package/dist/native/linux-x64/LICENSE-APACHE.txt +13 -0
  87. package/dist/native/linux-x64/kodax-text-transaction.node +0 -0
  88. package/dist/native/linux-x64/manifest.json +16 -0
  89. package/dist/native/win32-x64/LICENSE-APACHE.txt +13 -0
  90. package/dist/native/win32-x64/NOTICE-windows-sandbox.txt +8 -0
  91. package/dist/native/win32-x64/kodax-windows-sandbox.exe +0 -0
  92. package/dist/native/win32-x64/kodax-windows-text-transaction.node +0 -0
  93. package/dist/native/win32-x64/manifest.json +30 -0
  94. package/dist/provider-capabilities.json +108 -2
  95. package/dist/runtime-worker.js +1745 -1727
  96. package/dist/sandbox-network-broker.js +1715 -0
  97. package/dist/sdk-a2a.d.ts +13 -12
  98. package/dist/sdk-a2a.js +1 -1
  99. package/dist/sdk-agent.d.ts +27 -18
  100. package/dist/sdk-agent.js +1 -1
  101. package/dist/sdk-coding.d.ts +107 -58
  102. package/dist/sdk-coding.js +1 -1
  103. package/dist/sdk-experimental-memory.d.ts +4 -4
  104. package/dist/sdk-experimental-memory.js +1 -1
  105. package/dist/sdk-llm.d.ts +9 -10
  106. package/dist/sdk-llm.js +1 -1
  107. package/dist/sdk-mcp.js +1 -1
  108. package/dist/sdk-media.d.ts +1 -1
  109. package/dist/sdk-media.js +1 -1
  110. package/dist/sdk-repl.d.ts +25 -17
  111. package/dist/sdk-repl.js +1 -1
  112. package/dist/sdk-runtime.d.ts +41 -17
  113. package/dist/sdk-runtime.js +1 -1
  114. package/dist/sdk-sandbox.d.ts +17 -3
  115. package/dist/sdk-sandbox.js +1 -1
  116. package/dist/sdk-session.d.ts +8 -7
  117. package/dist/sdk-session.js +1 -1
  118. package/dist/sdk-skills.js +1 -1
  119. package/dist/semantic-worker.js +61 -61
  120. package/dist/types-chunks/{base.d-vopO1rml.d.ts → base.d-COo8E2dk.d.ts} +18 -27
  121. package/dist/types-chunks/{bash-prefix-extractor.d-B2rxNI4L.d.ts → bash-prefix-extractor.d-DQOlA8cy.d.ts} +72 -52
  122. package/dist/types-chunks/{capability-learning.d-CE1tm29C.d.ts → capability-learning.d-lRPgA3Or.d.ts} +1 -1
  123. package/dist/types-chunks/{capsule.d-Y7QRS4J2.d.ts → capsule.d-0zxsgXg_.d.ts} +3 -3
  124. package/dist/types-chunks/{controller.d-BR-UVeUR.d.ts → controller.d-BTtyIIC1.d.ts} +1 -1
  125. package/dist/types-chunks/{controller.d-C5noq5-w.d.ts → controller.d-C7tXUcXo.d.ts} +2 -2
  126. package/dist/types-chunks/{guardrail.d-DqHD-61O.d.ts → guardrail.d-DKTyEHJa.d.ts} +5 -5
  127. package/dist/types-chunks/{history-retrieval.d-CKU8zmt_.d.ts → history-retrieval.d-CHnL99S7.d.ts} +2 -2
  128. package/dist/types-chunks/{public-api.d-D7fXaWW8.d.ts → public-api.d-Dx3L3W4Z.d.ts} +7 -4
  129. package/dist/types-chunks/{repl.d-BYDb14s6.d.ts → repl.d-mO01olIa.d.ts} +5 -5
  130. package/dist/types-chunks/{resolver.d-CwHUwbdE.d.ts → resolver.d-DlXPjeyx.d.ts} +38 -6
  131. package/dist/types-chunks/{review-inbox.d-BSgFewyj.d.ts → review-inbox.d-WDSe1nze.d.ts} +1 -1
  132. package/dist/types-chunks/{run-manager.d-BVJSntpS.d.ts → run-manager.d-DENbbzgR.d.ts} +1 -1
  133. package/dist/types-chunks/{sdk-session-CqEG84oP.d.ts → sdk-session-DYHGXXH4.d.ts} +3 -3
  134. package/dist/types-chunks/{shell-command-sets.d-DqaaBwhU.d.ts → shell-command-sets.d-CjFqS4dp.d.ts} +1 -1
  135. package/dist/types-chunks/{side-query.d-iH0P9ASy.d.ts → side-query.d-j8A3sFv_.d.ts} +2 -2
  136. package/dist/types-chunks/{types.d-rUOjXych.d.ts → types.d-BbZjR0Wr.d.ts} +1 -1
  137. package/dist/types-chunks/{types.d-CaTXAW_Q.d.ts → types.d-BkTIKdH6.d.ts} +2 -2
  138. package/dist/types-chunks/{types.d-C5xQEFcj.d.ts → types.d-DncLrpu_.d.ts} +4 -4
  139. package/dist/types-chunks/{types.d-CK9A9rpP.d.ts → types.d-Xy0f3x4i.d.ts} +9 -0
  140. package/dist/types-chunks/{utils.d-CWUyLiXo.d.ts → utils.d-CnxefMos.d.ts} +6 -6
  141. package/package.json +10 -3
  142. package/public_docs/README.md +130 -0
  143. package/public_docs/configuration/sandbox.md +289 -0
  144. package/public_docs/sdk/embedder-guide.md +6674 -0
  145. package/scripts/kodax-bin.cjs +28 -28
  146. package/scripts/production-env.cjs +25 -25
  147. package/dist/chunks/agent-XXZMXKKA.js +0 -2
  148. package/dist/chunks/argument-completer-KCYDGTQW.js +0 -2
  149. package/dist/chunks/chunk-77PNP27P.js +0 -92
  150. package/dist/chunks/chunk-7QBWHCIZ.js +0 -2
  151. package/dist/chunks/chunk-BHE66SP3.js +0 -123
  152. package/dist/chunks/chunk-BR2OSB2I.js +0 -722
  153. package/dist/chunks/chunk-DSMONSVB.js +0 -407
  154. package/dist/chunks/chunk-Q5VRWSKG.js +0 -418
  155. package/dist/chunks/chunk-XWRPOGJN.js +0 -4
  156. package/dist/chunks/chunk-Y5VIQBT6.js +0 -383
  157. package/dist/chunks/compaction-config-EGS4577X.js +0 -2
  158. package/dist/chunks/dist-ITTXQHRJ.js +0 -2
  159. package/dist/chunks/dist-KFYN3OKD.js +0 -2
  160. package/dist/chunks/host-VAYADIPW.js +0 -2
  161. package/dist/chunks/run-manager-52IJZMZJ.js +0 -2
  162. package/dist/chunks/utils-P7PBSL3R.js +0 -2
  163. package/dist/sandbox-workspace-session.js +0 -1705
@@ -1,210 +1,210 @@
1
- #!/usr/bin/env node
2
-
3
- import { readFile, readdir, stat, writeFile } from 'node:fs/promises';
4
- import path from 'node:path';
5
- import { fileURLToPath } from 'node:url';
6
- import { calculateStats, formatDelta } from './utils.js';
7
-
8
- async function readJson(filePath) {
9
- return JSON.parse(await readFile(filePath, 'utf8'));
10
- }
11
-
12
- async function pathExists(filePath) {
13
- try {
14
- await stat(filePath);
15
- return true;
16
- } catch {
17
- return false;
18
- }
19
- }
20
-
21
- async function listDirectories(dirPath) {
22
- const entries = await readdir(dirPath, { withFileTypes: true }).catch(() => []);
23
- return entries
24
- .filter((entry) => entry.isDirectory())
25
- .map((entry) => path.join(dirPath, entry.name))
26
- .sort((left, right) => left.localeCompare(right));
27
- }
28
-
29
- export async function loadRunResults(iterationDir) {
30
- const runsRoot = await pathExists(path.join(iterationDir, 'runs'))
31
- ? path.join(iterationDir, 'runs')
32
- : iterationDir;
33
-
34
- const evalDirs = (await listDirectories(runsRoot))
35
- .filter((dirPath) => path.basename(dirPath).startsWith('eval-'));
36
-
37
- const configs = {};
38
-
39
- for (const evalDir of evalDirs) {
40
- const metadataPath = path.join(evalDir, 'eval_metadata.json');
41
- const metadata = await readJson(metadataPath).catch(() => ({}));
42
- const evalId = metadata.eval_id ?? path.basename(evalDir);
43
-
44
- for (const configDir of await listDirectories(evalDir)) {
45
- const configName = path.basename(configDir);
46
- const runDirs = (await listDirectories(configDir))
47
- .filter((dirPath) => path.basename(dirPath).startsWith('run-'));
48
-
49
- if (runDirs.length === 0) {
50
- continue;
51
- }
52
-
53
- configs[configName] ??= [];
54
-
55
- for (const runDir of runDirs) {
56
- const grading = await readJson(path.join(runDir, 'grading.json')).catch(() => null);
57
- if (!grading) {
58
- continue;
59
- }
60
-
61
- const timing = await readJson(path.join(runDir, 'timing.json')).catch(() => ({}));
62
-
63
- configs[configName].push({
64
- eval_id: evalId,
65
- run_id: path.basename(runDir),
66
- pass_rate: grading.summary?.pass_rate ?? 0,
67
- passed: grading.summary?.passed ?? 0,
68
- failed: grading.summary?.failed ?? 0,
69
- total: grading.summary?.total ?? 0,
70
- time_seconds: timing.total_duration_seconds ?? grading.timing?.total_duration_seconds ?? 0,
71
- tokens: timing.total_tokens ?? grading.execution_metrics?.output_chars ?? 0,
72
- tool_calls: grading.execution_metrics?.total_tool_calls ?? 0,
73
- errors: grading.execution_metrics?.errors_encountered ?? 0,
74
- expectations: Array.isArray(grading.expectations) ? grading.expectations : [],
75
- notes: [
76
- ...(grading.user_notes_summary?.uncertainties ?? []),
77
- ...(grading.user_notes_summary?.needs_review ?? []),
78
- ...(grading.user_notes_summary?.workarounds ?? []),
79
- ],
80
- });
81
- }
82
- }
83
- }
84
-
85
- return configs;
86
- }
87
-
88
- export function summarizeConfigs(configRuns) {
89
- const summary = {};
90
-
91
- for (const [configName, runs] of Object.entries(configRuns)) {
92
- summary[configName] = {
93
- pass_rate: calculateStats(runs.map((run) => Number(run.pass_rate ?? 0))),
94
- time_seconds: calculateStats(runs.map((run) => Number(run.time_seconds ?? 0))),
95
- tokens: calculateStats(runs.map((run) => Number(run.tokens ?? 0))),
96
- };
97
- }
98
-
99
- const orderedConfigs = Object.keys(summary);
100
- const primary = summary[orderedConfigs[0]] ?? {
101
- pass_rate: { mean: 0 },
102
- time_seconds: { mean: 0 },
103
- tokens: { mean: 0 },
104
- };
105
- const baseline = summary[orderedConfigs[1]] ?? {
106
- pass_rate: { mean: 0 },
107
- time_seconds: { mean: 0 },
108
- tokens: { mean: 0 },
109
- };
110
-
111
- return {
112
- configs: summary,
113
- delta: {
114
- pass_rate: formatDelta(primary.pass_rate.mean - baseline.pass_rate.mean),
115
- time_seconds: formatDelta(primary.time_seconds.mean - baseline.time_seconds.mean),
116
- tokens: formatDelta(primary.tokens.mean - baseline.tokens.mean),
117
- },
118
- };
119
- }
120
-
121
- export function buildBenchmarkDocument(iterationDir, skillName, configRuns) {
122
- const summary = summarizeConfigs(configRuns);
123
-
124
- return {
125
- skill_name: skillName,
126
- generated_at: new Date().toISOString(),
127
- workspace: path.resolve(iterationDir),
128
- configs: summary.configs,
129
- delta: summary.delta,
130
- runs: configRuns,
131
- };
132
- }
133
-
134
- export function renderBenchmarkMarkdown(benchmark) {
135
- const lines = [
136
- `# Benchmark: ${benchmark.skill_name}`,
137
- '',
138
- `Generated: ${benchmark.generated_at}`,
139
- '',
140
- '| Config | Pass Rate | Time (s) | Tokens |',
141
- '| --- | --- | --- | --- |',
142
- ];
143
-
144
- for (const [configName, metrics] of Object.entries(benchmark.configs)) {
145
- lines.push(
146
- `| ${configName} | ${metrics.pass_rate.mean} ± ${metrics.pass_rate.stddev} | ${metrics.time_seconds.mean} ± ${metrics.time_seconds.stddev} | ${metrics.tokens.mean} ± ${metrics.tokens.stddev} |`
147
- );
148
- }
149
-
150
- lines.push('');
151
- lines.push('## Delta');
152
- lines.push('');
153
- lines.push(`- Pass rate: ${benchmark.delta.pass_rate}`);
154
- lines.push(`- Time (s): ${benchmark.delta.time_seconds}`);
155
- lines.push(`- Tokens: ${benchmark.delta.tokens}`);
156
-
157
- return lines.join('\n');
158
- }
159
-
160
- function parseArgs(argv) {
161
- const args = {
162
- iterationDir: argv[2],
163
- skillName: 'unknown-skill',
164
- };
165
-
166
- for (let index = 3; index < argv.length; index += 1) {
167
- const token = argv[index];
168
- if (token === '--skill-name' && argv[index + 1]) {
169
- args.skillName = argv[index + 1];
170
- index += 1;
171
- }
172
- }
173
-
174
- return args;
175
- }
176
-
177
- async function main() {
178
- const { iterationDir, skillName } = parseArgs(process.argv);
179
- if (!iterationDir) {
180
- console.error('Usage: node scripts/aggregate-benchmark.js <iteration-dir> --skill-name <name>');
181
- process.exit(1);
182
- }
183
-
184
- const configRuns = await loadRunResults(iterationDir);
185
- if (Object.keys(configRuns).length === 0) {
186
- console.error(`No benchmark runs found in ${iterationDir}`);
187
- process.exit(1);
188
- }
189
-
190
- const benchmark = buildBenchmarkDocument(iterationDir, skillName, configRuns);
191
- const benchmarkJsonPath = path.join(iterationDir, 'benchmark.json');
192
- const benchmarkMdPath = path.join(iterationDir, 'benchmark.md');
193
-
194
- await writeFile(benchmarkJsonPath, JSON.stringify(benchmark, null, 2));
195
- await writeFile(benchmarkMdPath, `${renderBenchmarkMarkdown(benchmark)}\n`);
196
-
197
- console.log(`Wrote ${benchmarkJsonPath}`);
198
- console.log(`Wrote ${benchmarkMdPath}`);
199
- }
200
-
1
+ #!/usr/bin/env node
2
+
3
+ import { readFile, readdir, stat, writeFile } from 'node:fs/promises';
4
+ import path from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+ import { calculateStats, formatDelta } from './utils.js';
7
+
8
+ async function readJson(filePath) {
9
+ return JSON.parse(await readFile(filePath, 'utf8'));
10
+ }
11
+
12
+ async function pathExists(filePath) {
13
+ try {
14
+ await stat(filePath);
15
+ return true;
16
+ } catch {
17
+ return false;
18
+ }
19
+ }
20
+
21
+ async function listDirectories(dirPath) {
22
+ const entries = await readdir(dirPath, { withFileTypes: true }).catch(() => []);
23
+ return entries
24
+ .filter((entry) => entry.isDirectory())
25
+ .map((entry) => path.join(dirPath, entry.name))
26
+ .sort((left, right) => left.localeCompare(right));
27
+ }
28
+
29
+ export async function loadRunResults(iterationDir) {
30
+ const runsRoot = await pathExists(path.join(iterationDir, 'runs'))
31
+ ? path.join(iterationDir, 'runs')
32
+ : iterationDir;
33
+
34
+ const evalDirs = (await listDirectories(runsRoot))
35
+ .filter((dirPath) => path.basename(dirPath).startsWith('eval-'));
36
+
37
+ const configs = {};
38
+
39
+ for (const evalDir of evalDirs) {
40
+ const metadataPath = path.join(evalDir, 'eval_metadata.json');
41
+ const metadata = await readJson(metadataPath).catch(() => ({}));
42
+ const evalId = metadata.eval_id ?? path.basename(evalDir);
43
+
44
+ for (const configDir of await listDirectories(evalDir)) {
45
+ const configName = path.basename(configDir);
46
+ const runDirs = (await listDirectories(configDir))
47
+ .filter((dirPath) => path.basename(dirPath).startsWith('run-'));
48
+
49
+ if (runDirs.length === 0) {
50
+ continue;
51
+ }
52
+
53
+ configs[configName] ??= [];
54
+
55
+ for (const runDir of runDirs) {
56
+ const grading = await readJson(path.join(runDir, 'grading.json')).catch(() => null);
57
+ if (!grading) {
58
+ continue;
59
+ }
60
+
61
+ const timing = await readJson(path.join(runDir, 'timing.json')).catch(() => ({}));
62
+
63
+ configs[configName].push({
64
+ eval_id: evalId,
65
+ run_id: path.basename(runDir),
66
+ pass_rate: grading.summary?.pass_rate ?? 0,
67
+ passed: grading.summary?.passed ?? 0,
68
+ failed: grading.summary?.failed ?? 0,
69
+ total: grading.summary?.total ?? 0,
70
+ time_seconds: timing.total_duration_seconds ?? grading.timing?.total_duration_seconds ?? 0,
71
+ tokens: timing.total_tokens ?? grading.execution_metrics?.output_chars ?? 0,
72
+ tool_calls: grading.execution_metrics?.total_tool_calls ?? 0,
73
+ errors: grading.execution_metrics?.errors_encountered ?? 0,
74
+ expectations: Array.isArray(grading.expectations) ? grading.expectations : [],
75
+ notes: [
76
+ ...(grading.user_notes_summary?.uncertainties ?? []),
77
+ ...(grading.user_notes_summary?.needs_review ?? []),
78
+ ...(grading.user_notes_summary?.workarounds ?? []),
79
+ ],
80
+ });
81
+ }
82
+ }
83
+ }
84
+
85
+ return configs;
86
+ }
87
+
88
+ export function summarizeConfigs(configRuns) {
89
+ const summary = {};
90
+
91
+ for (const [configName, runs] of Object.entries(configRuns)) {
92
+ summary[configName] = {
93
+ pass_rate: calculateStats(runs.map((run) => Number(run.pass_rate ?? 0))),
94
+ time_seconds: calculateStats(runs.map((run) => Number(run.time_seconds ?? 0))),
95
+ tokens: calculateStats(runs.map((run) => Number(run.tokens ?? 0))),
96
+ };
97
+ }
98
+
99
+ const orderedConfigs = Object.keys(summary);
100
+ const primary = summary[orderedConfigs[0]] ?? {
101
+ pass_rate: { mean: 0 },
102
+ time_seconds: { mean: 0 },
103
+ tokens: { mean: 0 },
104
+ };
105
+ const baseline = summary[orderedConfigs[1]] ?? {
106
+ pass_rate: { mean: 0 },
107
+ time_seconds: { mean: 0 },
108
+ tokens: { mean: 0 },
109
+ };
110
+
111
+ return {
112
+ configs: summary,
113
+ delta: {
114
+ pass_rate: formatDelta(primary.pass_rate.mean - baseline.pass_rate.mean),
115
+ time_seconds: formatDelta(primary.time_seconds.mean - baseline.time_seconds.mean),
116
+ tokens: formatDelta(primary.tokens.mean - baseline.tokens.mean),
117
+ },
118
+ };
119
+ }
120
+
121
+ export function buildBenchmarkDocument(iterationDir, skillName, configRuns) {
122
+ const summary = summarizeConfigs(configRuns);
123
+
124
+ return {
125
+ skill_name: skillName,
126
+ generated_at: new Date().toISOString(),
127
+ workspace: path.resolve(iterationDir),
128
+ configs: summary.configs,
129
+ delta: summary.delta,
130
+ runs: configRuns,
131
+ };
132
+ }
133
+
134
+ export function renderBenchmarkMarkdown(benchmark) {
135
+ const lines = [
136
+ `# Benchmark: ${benchmark.skill_name}`,
137
+ '',
138
+ `Generated: ${benchmark.generated_at}`,
139
+ '',
140
+ '| Config | Pass Rate | Time (s) | Tokens |',
141
+ '| --- | --- | --- | --- |',
142
+ ];
143
+
144
+ for (const [configName, metrics] of Object.entries(benchmark.configs)) {
145
+ lines.push(
146
+ `| ${configName} | ${metrics.pass_rate.mean} ± ${metrics.pass_rate.stddev} | ${metrics.time_seconds.mean} ± ${metrics.time_seconds.stddev} | ${metrics.tokens.mean} ± ${metrics.tokens.stddev} |`
147
+ );
148
+ }
149
+
150
+ lines.push('');
151
+ lines.push('## Delta');
152
+ lines.push('');
153
+ lines.push(`- Pass rate: ${benchmark.delta.pass_rate}`);
154
+ lines.push(`- Time (s): ${benchmark.delta.time_seconds}`);
155
+ lines.push(`- Tokens: ${benchmark.delta.tokens}`);
156
+
157
+ return lines.join('\n');
158
+ }
159
+
160
+ function parseArgs(argv) {
161
+ const args = {
162
+ iterationDir: argv[2],
163
+ skillName: 'unknown-skill',
164
+ };
165
+
166
+ for (let index = 3; index < argv.length; index += 1) {
167
+ const token = argv[index];
168
+ if (token === '--skill-name' && argv[index + 1]) {
169
+ args.skillName = argv[index + 1];
170
+ index += 1;
171
+ }
172
+ }
173
+
174
+ return args;
175
+ }
176
+
177
+ async function main() {
178
+ const { iterationDir, skillName } = parseArgs(process.argv);
179
+ if (!iterationDir) {
180
+ console.error('Usage: node scripts/aggregate-benchmark.js <iteration-dir> --skill-name <name>');
181
+ process.exit(1);
182
+ }
183
+
184
+ const configRuns = await loadRunResults(iterationDir);
185
+ if (Object.keys(configRuns).length === 0) {
186
+ console.error(`No benchmark runs found in ${iterationDir}`);
187
+ process.exit(1);
188
+ }
189
+
190
+ const benchmark = buildBenchmarkDocument(iterationDir, skillName, configRuns);
191
+ const benchmarkJsonPath = path.join(iterationDir, 'benchmark.json');
192
+ const benchmarkMdPath = path.join(iterationDir, 'benchmark.md');
193
+
194
+ await writeFile(benchmarkJsonPath, JSON.stringify(benchmark, null, 2));
195
+ await writeFile(benchmarkMdPath, `${renderBenchmarkMarkdown(benchmark)}\n`);
196
+
197
+ console.log(`Wrote ${benchmarkJsonPath}`);
198
+ console.log(`Wrote ${benchmarkMdPath}`);
199
+ }
200
+
201
201
  const isDirectRun = process.env.KODAX_MODULE_BUNDLE !== 'true'
202
202
  && process.argv[1]
203
- && fileURLToPath(import.meta.url) === path.resolve(process.argv[1]);
204
-
205
- if (isDirectRun) {
206
- main().catch((error) => {
207
- console.error(error instanceof Error ? error.message : String(error));
208
- process.exit(1);
209
- });
210
- }
203
+ && fileURLToPath(import.meta.url) === path.resolve(process.argv[1]);
204
+
205
+ if (isDirectRun) {
206
+ main().catch((error) => {
207
+ console.error(error instanceof Error ? error.message : String(error));
208
+ process.exit(1);
209
+ });
210
+ }
@@ -1,47 +1,47 @@
1
- export interface AnalyzeBenchmarkOptions {
2
- workspaceDir: string;
3
- benchmarkPath?: string;
4
- outputPath?: string;
5
- markdownPath?: string;
6
- skillName?: string;
7
- provider?: string;
8
- model?: string;
9
- reasoningMode?: string;
10
- maxIter?: number;
11
- cwd?: string;
12
- }
13
-
14
- export interface BenchmarkAnalysis {
15
- skill_name: string;
16
- generated_at: string;
17
- workspace: string;
18
- verdict: 'improves' | 'regresses' | 'mixed' | 'inconclusive';
19
- release_readiness: 'ready' | 'needs_iteration' | 'needs_manual_review';
20
- recommendation: string;
21
- key_findings: string[];
22
- variance_hotspots: string[];
23
- suggested_actions: string[];
24
- watchouts: string[];
25
- supporting_metrics: {
26
- pass_rate_delta: string;
27
- time_seconds_delta: string;
28
- tokens_delta: string;
29
- };
30
- failure_clusters: Record<string, unknown>;
31
- }
32
-
33
- export function buildAnalysisPrompt(input: Record<string, unknown>): string;
34
-
35
- export function renderAnalysisMarkdown(analysis: Record<string, any>): string;
36
-
37
- export function analyzeBenchmark(
38
- options: AnalyzeBenchmarkOptions,
39
- runner?: (prompt: string, options: Record<string, unknown>) => Promise<string>
40
- ): Promise<{
41
- analysis: BenchmarkAnalysis;
42
- prompt: string;
43
- rawResponse: string;
44
- analysisJsonPath: string;
45
- analysisMdPath: string;
46
- }>;
1
+ export interface AnalyzeBenchmarkOptions {
2
+ workspaceDir: string;
3
+ benchmarkPath?: string;
4
+ outputPath?: string;
5
+ markdownPath?: string;
6
+ skillName?: string;
7
+ provider?: string;
8
+ model?: string;
9
+ reasoningMode?: string;
10
+ maxIter?: number;
11
+ cwd?: string;
12
+ }
13
+
14
+ export interface BenchmarkAnalysis {
15
+ skill_name: string;
16
+ generated_at: string;
17
+ workspace: string;
18
+ verdict: 'improves' | 'regresses' | 'mixed' | 'inconclusive';
19
+ release_readiness: 'ready' | 'needs_iteration' | 'needs_manual_review';
20
+ recommendation: string;
21
+ key_findings: string[];
22
+ variance_hotspots: string[];
23
+ suggested_actions: string[];
24
+ watchouts: string[];
25
+ supporting_metrics: {
26
+ pass_rate_delta: string;
27
+ time_seconds_delta: string;
28
+ tokens_delta: string;
29
+ };
30
+ failure_clusters: Record<string, unknown>;
31
+ }
32
+
33
+ export function buildAnalysisPrompt(input: Record<string, unknown>): string;
34
+
35
+ export function renderAnalysisMarkdown(analysis: Record<string, any>): string;
36
+
37
+ export function analyzeBenchmark(
38
+ options: AnalyzeBenchmarkOptions,
39
+ runner?: (prompt: string, options: Record<string, unknown>) => Promise<string>
40
+ ): Promise<{
41
+ analysis: BenchmarkAnalysis;
42
+ prompt: string;
43
+ rawResponse: string;
44
+ analysisJsonPath: string;
45
+ analysisMdPath: string;
46
+ }>;
47
47
  export declare function main(argv?: string[]): Promise<void>;