@netlify/axis 0.2.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 (230) hide show
  1. package/README.md +977 -0
  2. package/dist/adapters/base/acp-adapter.d.ts +44 -0
  3. package/dist/adapters/base/acp-adapter.d.ts.map +1 -0
  4. package/dist/adapters/base/acp-adapter.js +559 -0
  5. package/dist/adapters/base/acp-adapter.js.map +1 -0
  6. package/dist/adapters/base/agent-adapter.d.ts +132 -0
  7. package/dist/adapters/base/agent-adapter.d.ts.map +1 -0
  8. package/dist/adapters/base/agent-adapter.js +212 -0
  9. package/dist/adapters/base/agent-adapter.js.map +1 -0
  10. package/dist/adapters/claude-code.d.ts +3 -0
  11. package/dist/adapters/claude-code.d.ts.map +1 -0
  12. package/dist/adapters/claude-code.js +138 -0
  13. package/dist/adapters/claude-code.js.map +1 -0
  14. package/dist/adapters/claude-sdk.d.ts +11 -0
  15. package/dist/adapters/claude-sdk.d.ts.map +1 -0
  16. package/dist/adapters/claude-sdk.js +46 -0
  17. package/dist/adapters/claude-sdk.js.map +1 -0
  18. package/dist/adapters/codex.d.ts +3 -0
  19. package/dist/adapters/codex.d.ts.map +1 -0
  20. package/dist/adapters/codex.js +183 -0
  21. package/dist/adapters/codex.js.map +1 -0
  22. package/dist/adapters/gemini-acp.d.ts +11 -0
  23. package/dist/adapters/gemini-acp.d.ts.map +1 -0
  24. package/dist/adapters/gemini-acp.js +60 -0
  25. package/dist/adapters/gemini-acp.js.map +1 -0
  26. package/dist/adapters/gemini.d.ts +3 -0
  27. package/dist/adapters/gemini.d.ts.map +1 -0
  28. package/dist/adapters/gemini.js +222 -0
  29. package/dist/adapters/gemini.js.map +1 -0
  30. package/dist/adapters/goose.d.ts +3 -0
  31. package/dist/adapters/goose.d.ts.map +1 -0
  32. package/dist/adapters/goose.js +9 -0
  33. package/dist/adapters/goose.js.map +1 -0
  34. package/dist/adapters/registry.d.ts +7 -0
  35. package/dist/adapters/registry.d.ts.map +1 -0
  36. package/dist/adapters/registry.js +37 -0
  37. package/dist/adapters/registry.js.map +1 -0
  38. package/dist/adapters/utils/mcp.d.ts +23 -0
  39. package/dist/adapters/utils/mcp.d.ts.map +1 -0
  40. package/dist/adapters/utils/mcp.js +114 -0
  41. package/dist/adapters/utils/mcp.js.map +1 -0
  42. package/dist/adapters/utils/resolve.d.ts +20 -0
  43. package/dist/adapters/utils/resolve.d.ts.map +1 -0
  44. package/dist/adapters/utils/resolve.js +48 -0
  45. package/dist/adapters/utils/resolve.js.map +1 -0
  46. package/dist/adapters/utils/skills.d.ts +17 -0
  47. package/dist/adapters/utils/skills.d.ts.map +1 -0
  48. package/dist/adapters/utils/skills.js +52 -0
  49. package/dist/adapters/utils/skills.js.map +1 -0
  50. package/dist/adapters/utils/token-estimator.d.ts +21 -0
  51. package/dist/adapters/utils/token-estimator.d.ts.map +1 -0
  52. package/dist/adapters/utils/token-estimator.js +37 -0
  53. package/dist/adapters/utils/token-estimator.js.map +1 -0
  54. package/dist/baselines/diff.d.ts +9 -0
  55. package/dist/baselines/diff.d.ts.map +1 -0
  56. package/dist/baselines/diff.js +83 -0
  57. package/dist/baselines/diff.js.map +1 -0
  58. package/dist/baselines/index.d.ts +3 -0
  59. package/dist/baselines/index.d.ts.map +1 -0
  60. package/dist/baselines/index.js +3 -0
  61. package/dist/baselines/index.js.map +1 -0
  62. package/dist/baselines/store.d.ts +19 -0
  63. package/dist/baselines/store.d.ts.map +1 -0
  64. package/dist/baselines/store.js +104 -0
  65. package/dist/baselines/store.js.map +1 -0
  66. package/dist/cli.d.ts +3 -0
  67. package/dist/cli.d.ts.map +1 -0
  68. package/dist/cli.js +487 -0
  69. package/dist/cli.js.map +1 -0
  70. package/dist/config/loader.d.ts +8 -0
  71. package/dist/config/loader.d.ts.map +1 -0
  72. package/dist/config/loader.js +99 -0
  73. package/dist/config/loader.js.map +1 -0
  74. package/dist/config/validator.d.ts +11 -0
  75. package/dist/config/validator.d.ts.map +1 -0
  76. package/dist/config/validator.js +203 -0
  77. package/dist/config/validator.js.map +1 -0
  78. package/dist/docs-site/_astro/cli.DDWZtG0-.css +1 -0
  79. package/dist/docs-site/cli/index.html +18 -0
  80. package/dist/docs-site/configuration/index.html +121 -0
  81. package/dist/docs-site/content-assets.mjs +1 -0
  82. package/dist/docs-site/content-modules.mjs +1 -0
  83. package/dist/docs-site/data-store.json +9 -0
  84. package/dist/docs-site/index.html +69 -0
  85. package/dist/docs-site/quickstart/index.html +59 -0
  86. package/dist/docs-site/running/index.html +87 -0
  87. package/dist/docs-site/scoring/index.html +135 -0
  88. package/dist/index.d.ts +19 -0
  89. package/dist/index.d.ts.map +1 -0
  90. package/dist/index.js +15 -0
  91. package/dist/index.js.map +1 -0
  92. package/dist/report-ui/index.html +291 -0
  93. package/dist/report-ui/mock-data.json +298 -0
  94. package/dist/reports/html.d.ts +7 -0
  95. package/dist/reports/html.d.ts.map +1 -0
  96. package/dist/reports/html.js +27 -0
  97. package/dist/reports/html.js.map +1 -0
  98. package/dist/reports/reader.d.ts +21 -0
  99. package/dist/reports/reader.d.ts.map +1 -0
  100. package/dist/reports/reader.js +110 -0
  101. package/dist/reports/reader.js.map +1 -0
  102. package/dist/reports/writer.d.ts +14 -0
  103. package/dist/reports/writer.d.ts.map +1 -0
  104. package/dist/reports/writer.js +106 -0
  105. package/dist/reports/writer.js.map +1 -0
  106. package/dist/runner/lifecycle.d.ts +10 -0
  107. package/dist/runner/lifecycle.d.ts.map +1 -0
  108. package/dist/runner/lifecycle.js +58 -0
  109. package/dist/runner/lifecycle.js.map +1 -0
  110. package/dist/runner/runner.d.ts +34 -0
  111. package/dist/runner/runner.d.ts.map +1 -0
  112. package/dist/runner/runner.js +330 -0
  113. package/dist/runner/runner.js.map +1 -0
  114. package/dist/scoring/category-score.d.ts +52 -0
  115. package/dist/scoring/category-score.d.ts.map +1 -0
  116. package/dist/scoring/category-score.js +157 -0
  117. package/dist/scoring/category-score.js.map +1 -0
  118. package/dist/scoring/composite.d.ts +5 -0
  119. package/dist/scoring/composite.d.ts.map +1 -0
  120. package/dist/scoring/composite.js +24 -0
  121. package/dist/scoring/composite.js.map +1 -0
  122. package/dist/scoring/deep-eval.d.ts +25 -0
  123. package/dist/scoring/deep-eval.d.ts.map +1 -0
  124. package/dist/scoring/deep-eval.js +382 -0
  125. package/dist/scoring/deep-eval.js.map +1 -0
  126. package/dist/scoring/goal-achievement.d.ts +5 -0
  127. package/dist/scoring/goal-achievement.d.ts.map +1 -0
  128. package/dist/scoring/goal-achievement.js +241 -0
  129. package/dist/scoring/goal-achievement.js.map +1 -0
  130. package/dist/scoring/index.d.ts +22 -0
  131. package/dist/scoring/index.d.ts.map +1 -0
  132. package/dist/scoring/index.js +115 -0
  133. package/dist/scoring/index.js.map +1 -0
  134. package/dist/scoring/parse-json.d.ts +6 -0
  135. package/dist/scoring/parse-json.d.ts.map +1 -0
  136. package/dist/scoring/parse-json.js +18 -0
  137. package/dist/scoring/parse-json.js.map +1 -0
  138. package/dist/scoring/sparse-index.d.ts +15 -0
  139. package/dist/scoring/sparse-index.d.ts.map +1 -0
  140. package/dist/scoring/sparse-index.js +338 -0
  141. package/dist/scoring/sparse-index.js.map +1 -0
  142. package/dist/scoring/triage.d.ts +15 -0
  143. package/dist/scoring/triage.d.ts.map +1 -0
  144. package/dist/scoring/triage.js +204 -0
  145. package/dist/scoring/triage.js.map +1 -0
  146. package/dist/skills/resolver.d.ts +19 -0
  147. package/dist/skills/resolver.d.ts.map +1 -0
  148. package/dist/skills/resolver.js +95 -0
  149. package/dist/skills/resolver.js.map +1 -0
  150. package/dist/transcript/categorize.d.ts +24 -0
  151. package/dist/transcript/categorize.d.ts.map +1 -0
  152. package/dist/transcript/categorize.js +233 -0
  153. package/dist/transcript/categorize.js.map +1 -0
  154. package/dist/transcript/classify.d.ts +7 -0
  155. package/dist/transcript/classify.d.ts.map +1 -0
  156. package/dist/transcript/classify.js +32 -0
  157. package/dist/transcript/classify.js.map +1 -0
  158. package/dist/transcript/extract.d.ts +24 -0
  159. package/dist/transcript/extract.d.ts.map +1 -0
  160. package/dist/transcript/extract.js +266 -0
  161. package/dist/transcript/extract.js.map +1 -0
  162. package/dist/transcript/index.d.ts +3 -0
  163. package/dist/transcript/index.d.ts.map +1 -0
  164. package/dist/transcript/index.js +2 -0
  165. package/dist/transcript/index.js.map +1 -0
  166. package/dist/transcript/normalize.d.ts +15 -0
  167. package/dist/transcript/normalize.d.ts.map +1 -0
  168. package/dist/transcript/normalize.js +160 -0
  169. package/dist/transcript/normalize.js.map +1 -0
  170. package/dist/transcript/types.d.ts +92 -0
  171. package/dist/transcript/types.d.ts.map +1 -0
  172. package/dist/transcript/types.js +2 -0
  173. package/dist/transcript/types.js.map +1 -0
  174. package/dist/transcript/urls.d.ts +10 -0
  175. package/dist/transcript/urls.d.ts.map +1 -0
  176. package/dist/transcript/urls.js +31 -0
  177. package/dist/transcript/urls.js.map +1 -0
  178. package/dist/types/agent.d.ts +80 -0
  179. package/dist/types/agent.d.ts.map +1 -0
  180. package/dist/types/agent.js +2 -0
  181. package/dist/types/agent.js.map +1 -0
  182. package/dist/types/baseline.d.ts +65 -0
  183. package/dist/types/baseline.d.ts.map +1 -0
  184. package/dist/types/baseline.js +2 -0
  185. package/dist/types/baseline.js.map +1 -0
  186. package/dist/types/config.d.ts +76 -0
  187. package/dist/types/config.d.ts.map +1 -0
  188. package/dist/types/config.js +2 -0
  189. package/dist/types/config.js.map +1 -0
  190. package/dist/types/index.d.ts +8 -0
  191. package/dist/types/index.d.ts.map +1 -0
  192. package/dist/types/index.js +8 -0
  193. package/dist/types/index.js.map +1 -0
  194. package/dist/types/output.d.ts +70 -0
  195. package/dist/types/output.d.ts.map +1 -0
  196. package/dist/types/output.js +15 -0
  197. package/dist/types/output.js.map +1 -0
  198. package/dist/types/report.d.ts +37 -0
  199. package/dist/types/report.d.ts.map +1 -0
  200. package/dist/types/report.js +2 -0
  201. package/dist/types/report.js.map +1 -0
  202. package/dist/types/scenario.d.ts +23 -0
  203. package/dist/types/scenario.d.ts.map +1 -0
  204. package/dist/types/scenario.js +2 -0
  205. package/dist/types/scenario.js.map +1 -0
  206. package/dist/types/scoring.d.ts +176 -0
  207. package/dist/types/scoring.d.ts.map +1 -0
  208. package/dist/types/scoring.js +2 -0
  209. package/dist/types/scoring.js.map +1 -0
  210. package/dist/ui/AnimatedTokens.d.ts +29 -0
  211. package/dist/ui/AnimatedTokens.d.ts.map +1 -0
  212. package/dist/ui/AnimatedTokens.js +53 -0
  213. package/dist/ui/AnimatedTokens.js.map +1 -0
  214. package/dist/ui/App.d.ts +6 -0
  215. package/dist/ui/App.d.ts.map +1 -0
  216. package/dist/ui/App.js +16 -0
  217. package/dist/ui/App.js.map +1 -0
  218. package/dist/ui/LiveDuration.d.ts +20 -0
  219. package/dist/ui/LiveDuration.d.ts.map +1 -0
  220. package/dist/ui/LiveDuration.js +31 -0
  221. package/dist/ui/LiveDuration.js.map +1 -0
  222. package/dist/ui/LiveStatus.d.ts +7 -0
  223. package/dist/ui/LiveStatus.d.ts.map +1 -0
  224. package/dist/ui/LiveStatus.js +52 -0
  225. package/dist/ui/LiveStatus.js.map +1 -0
  226. package/dist/ui/format.d.ts +29 -0
  227. package/dist/ui/format.d.ts.map +1 -0
  228. package/dist/ui/format.js +514 -0
  229. package/dist/ui/format.js.map +1 -0
  230. package/package.json +65 -0
package/dist/cli.js ADDED
@@ -0,0 +1,487 @@
1
+ #!/usr/bin/env node
2
+ import * as fs from "node:fs";
3
+ import * as path from "node:path";
4
+ import { Command } from "commander";
5
+ import { run } from "./runner/runner.js";
6
+ import { loadConfig } from "./config/loader.js";
7
+ import { scoreRunResult, buildScoredOutput, buildMcpCategoryOverrides } from "./scoring/index.js";
8
+ import { writeReportToStore } from "./reports/writer.js";
9
+ import { listReports, readReport, readScenarioResults } from "./reports/reader.js";
10
+ import { setBaseline, readBaseline, listBaselines, deleteBaseline, DEFAULT_BASELINE_NAME } from "./baselines/store.js";
11
+ import { diffBaseline } from "./baselines/diff.js";
12
+ import { renderReportList, renderReportDetail, renderScenarioDetail, renderBaselineList, renderBaselineShow, renderBaselineDiff, } from "./ui/format.js";
13
+ import { formatError } from "./types/output.js";
14
+ const program = new Command();
15
+ program.name("axis").description("AXIS — Agent eXperience Index Score").version("0.1.0");
16
+ // --- Signal handling: kill child processes and clean up on Ctrl-C ---
17
+ const cleanupHandlers = [];
18
+ function registerCleanup(fn) {
19
+ cleanupHandlers.push(fn);
20
+ }
21
+ function handleSignal(signal) {
22
+ for (const fn of cleanupHandlers) {
23
+ try {
24
+ fn();
25
+ }
26
+ catch {
27
+ /* best-effort cleanup */
28
+ }
29
+ }
30
+ process.exit(signal === "SIGINT" ? 130 : 143);
31
+ }
32
+ process.on("SIGINT", () => handleSignal("SIGINT"));
33
+ process.on("SIGTERM", () => handleSignal("SIGTERM"));
34
+ /**
35
+ * Core run pipeline shared between JSON mode and interactive mode.
36
+ * Returns the final output (scored or unscored) and the reportId.
37
+ */
38
+ async function executeRunPipeline(opts, logger,
39
+ /** Called when a job finishes and scoring begins (interactive mode only). */
40
+ onScoringStart,
41
+ /** Called when scoring completes for a job (interactive mode only). */
42
+ onScoringDone) {
43
+ const { config, configDir } = await loadConfig(opts.configPath);
44
+ const scoringPromises = [];
45
+ const mcpCategoryOverrides = buildMcpCategoryOverrides(config.mcp_servers);
46
+ const concurrency = opts.concurrency ?? config.defaults?.concurrency;
47
+ const runOutput = await run({
48
+ configPath: opts.configPath,
49
+ scenarioFilter: opts.scenario ? [opts.scenario] : undefined,
50
+ agentFilter: opts.agent ? [opts.agent] : undefined,
51
+ concurrency,
52
+ logger,
53
+ registerCleanup,
54
+ debug: opts.debug,
55
+ refreshSkills: opts.refreshSkills,
56
+ onResult: opts.score
57
+ ? (result) => {
58
+ const scoring = scoreRunResult(result, {
59
+ weights: config.defaults?.scoring_weights,
60
+ logger,
61
+ mcpCategoryOverrides,
62
+ onProgress: (scenarioKey, agentName, phase) => {
63
+ if (phase === "start")
64
+ onScoringStart?.(scenarioKey, agentName);
65
+ },
66
+ }).then((scored) => {
67
+ onScoringDone?.(scored);
68
+ return scored;
69
+ });
70
+ scoringPromises.push(scoring);
71
+ return scoring.then(() => { });
72
+ }
73
+ : undefined,
74
+ });
75
+ let output;
76
+ if (opts.score && runOutput.results.length > 0) {
77
+ const scoredResults = await Promise.all(scoringPromises);
78
+ output = buildScoredOutput(runOutput, scoredResults);
79
+ }
80
+ else {
81
+ output = runOutput;
82
+ }
83
+ const reportId = writeReportToStore(output, configDir);
84
+ if (opts.outputDir) {
85
+ const reportPath = writeReportFile(output, opts.outputDir);
86
+ logger.info(`Report written to ${reportPath}`);
87
+ }
88
+ return { output, reportId, configDir };
89
+ }
90
+ // --- axis run command ---
91
+ program
92
+ .command("run")
93
+ .description("Run scenarios against configured agents")
94
+ .option("-c, --config <path>", "path to axis.config.json", "axis.config.json")
95
+ .option("-s, --scenario <key>", "run a specific scenario by key (e.g. hello-world, cms/create-post)")
96
+ .option("-a, --agent <name>", "run with a specific agent only")
97
+ .option("--json", "output results as JSON to stdout", false)
98
+ .option("-v, --verbose", "show detailed per-step logging", false)
99
+ .option("-o, --output-dir <dir>", "also write axis-report-[timestamp].json to this directory")
100
+ .option("--concurrency <n>", "max parallel jobs (default: unlimited)", parseInt)
101
+ .option("--debug", "show debug output (workspace paths, env, lifecycle)", false)
102
+ .option("--no-score", "skip scoring (raw results only)")
103
+ .option("--refresh-skills", "force re-clone of cached remote skills", false)
104
+ .option("--compare-baseline [name]", `compare results against a baseline after scoring (default: "${DEFAULT_BASELINE_NAME}")`)
105
+ .action(async (opts) => {
106
+ // Commander gives `true` for bare flag, a string for --flag=value
107
+ const baselineName = opts.compareBaseline === true ? DEFAULT_BASELINE_NAME : opts.compareBaseline || undefined;
108
+ if (baselineName && !opts.score) {
109
+ process.stderr.write("\n Warning: --compare-baseline requires scoring. Ignoring because --no-score is set.\n\n");
110
+ }
111
+ const pipelineOpts = {
112
+ configPath: opts.config,
113
+ scenario: opts.scenario,
114
+ agent: opts.agent,
115
+ concurrency: opts.concurrency,
116
+ score: opts.score,
117
+ verbose: opts.verbose,
118
+ debug: opts.debug,
119
+ outputDir: opts.outputDir,
120
+ json: opts.json,
121
+ refreshSkills: opts.refreshSkills,
122
+ };
123
+ // JSON mode: no UI, just run and output
124
+ if (opts.json) {
125
+ const logger = {
126
+ info() { },
127
+ error: (msg) => process.stderr.write(` ERROR: ${msg}\n`),
128
+ };
129
+ try {
130
+ const { output, reportId, configDir } = await executeRunPipeline(pipelineOpts, logger);
131
+ process.stdout.write(JSON.stringify(output, null, 2) + "\n");
132
+ if (baselineName && opts.score) {
133
+ const exitCode = runBaselineComparison(configDir, baselineName, reportId, opts.json);
134
+ if (exitCode !== 0)
135
+ process.exit(exitCode);
136
+ }
137
+ if (output.summary.failed > 0)
138
+ process.exit(1);
139
+ }
140
+ catch (err) {
141
+ process.stderr.write(`\n Error: ${formatError(err)}\n\n`);
142
+ process.exit(1);
143
+ }
144
+ return;
145
+ }
146
+ // Interactive / non-JSON mode
147
+ const isTTY = process.stderr.isTTY ?? false;
148
+ let onUpdate;
149
+ let unmountInk;
150
+ let lastJobs = [];
151
+ const logger = {
152
+ info: (msg) => process.stderr.write(` ${msg}\n`),
153
+ error: (msg) => process.stderr.write(` ERROR: ${msg}\n`),
154
+ verbose: opts.verbose || opts.debug ? (msg) => process.stderr.write(` ${msg}\n`) : undefined,
155
+ onJobUpdate: isTTY
156
+ ? (jobs) => {
157
+ lastJobs = jobs;
158
+ onUpdate?.([...jobs]);
159
+ }
160
+ : undefined,
161
+ };
162
+ // Start ink for TTY live display
163
+ if (isTTY) {
164
+ try {
165
+ const { render } = await import("ink");
166
+ const React = await import("react");
167
+ const { App } = await import("./ui/App.js");
168
+ const instance = render(React.createElement(App, {
169
+ subscribe: (cb) => {
170
+ onUpdate = cb;
171
+ },
172
+ }), { stdout: process.stderr, stderr: process.stderr });
173
+ unmountInk = () => {
174
+ instance.unmount();
175
+ };
176
+ registerCleanup(() => unmountInk?.());
177
+ }
178
+ catch (e) {
179
+ logger.verbose?.(`Ink display unavailable: ${formatError(e)}`);
180
+ }
181
+ }
182
+ try {
183
+ const { output, reportId, configDir } = await executeRunPipeline(pipelineOpts, logger,
184
+ // onScoringStart
185
+ (scenarioKey, agentName) => {
186
+ const job = lastJobs.find((j) => j.scenarioKey === scenarioKey && j.agentName === agentName);
187
+ if (job && job.status !== "failed") {
188
+ job.status = "scoring";
189
+ onUpdate?.([...lastJobs]);
190
+ }
191
+ },
192
+ // onScoringDone
193
+ (scored) => {
194
+ const job = lastJobs.find((j) => j.scenarioKey === scored.scenarioKey && j.agentName === scored.agentName);
195
+ if (job) {
196
+ if (job.status !== "failed") {
197
+ job.status = "done";
198
+ }
199
+ job.axisScore = scored.score.axisScore;
200
+ onUpdate?.([...lastJobs]);
201
+ }
202
+ });
203
+ // Let ink render the final "done" state before unmounting
204
+ if (unmountInk)
205
+ await new Promise((r) => setTimeout(r, 100));
206
+ unmountInk?.();
207
+ process.stderr.write(` Report saved: .axis/reports/${reportId}\n`);
208
+ process.stderr.write(` View details: axis reports ${reportId}\n`);
209
+ process.stderr.write(` Open in browser: axis reports ${reportId} --html\n\n`);
210
+ if (baselineName && opts.score) {
211
+ const exitCode = runBaselineComparison(configDir, baselineName, reportId, false);
212
+ if (exitCode !== 0)
213
+ process.exit(exitCode);
214
+ }
215
+ if (output.summary.failed > 0)
216
+ process.exit(1);
217
+ }
218
+ catch (err) {
219
+ unmountInk?.();
220
+ process.stderr.write(`\n Error: ${formatError(err)}\n\n`);
221
+ process.exit(1);
222
+ }
223
+ });
224
+ // --- axis reports command ---
225
+ program
226
+ .command("reports")
227
+ .description("View past AXIS reports")
228
+ .argument("[reportId]", "report ID or 'latest' (omit to list all)")
229
+ .argument("[scenarioKey]", "scenario key to view detailed result")
230
+ .option("-c, --config <path>", "path to axis.config.json", "axis.config.json")
231
+ .option("-a, --agent <name...>", "filter scenario detail to specific agent(s), repeatable")
232
+ .option("--json", "output as JSON", false)
233
+ .option("--html", "open report as HTML in browser", false)
234
+ .option("-n, --limit <count>", "max reports to list", "10")
235
+ .action(async (reportId, scenarioKey, opts) => {
236
+ try {
237
+ const { configDir } = await loadConfig(opts.config);
238
+ // List all reports
239
+ if (!reportId) {
240
+ const reports = listReports(configDir);
241
+ if (reports.length === 0) {
242
+ process.stdout.write("\n No reports found. Run `axis run` to generate one.\n\n");
243
+ return;
244
+ }
245
+ const limit = parseInt(opts.limit, 10) || 10;
246
+ const displayed = reports.slice(0, limit);
247
+ if (opts.json) {
248
+ process.stdout.write(JSON.stringify(displayed, null, 2) + "\n");
249
+ }
250
+ else {
251
+ process.stdout.write(renderReportList(displayed));
252
+ if (reports.length > limit) {
253
+ process.stdout.write(` ... and ${reports.length - limit} more\n\n`);
254
+ }
255
+ }
256
+ return;
257
+ }
258
+ // View a specific scenario result
259
+ if (scenarioKey) {
260
+ const agentFilter = opts.agent;
261
+ // Read all agents, then filter if --agent was specified
262
+ let results = readScenarioResults(configDir, reportId, scenarioKey);
263
+ if (agentFilter?.length) {
264
+ results = results.filter((r) => agentFilter.includes(r.agentName));
265
+ }
266
+ if (results.length === 0) {
267
+ const filterMsg = agentFilter?.length ? ` (agent: ${agentFilter.join(", ")})` : "";
268
+ process.stderr.write(`\n Scenario "${scenarioKey}"${filterMsg} not found in report "${reportId}".\n\n`);
269
+ process.exit(1);
270
+ }
271
+ if (opts.json) {
272
+ const jsonOut = results.length === 1 ? results[0] : results;
273
+ process.stdout.write(JSON.stringify(jsonOut, null, 2) + "\n");
274
+ }
275
+ else {
276
+ for (const result of results) {
277
+ process.stdout.write(renderScenarioDetail(result));
278
+ }
279
+ }
280
+ return;
281
+ }
282
+ // View a single report summary
283
+ const report = readReport(configDir, reportId);
284
+ if (!report) {
285
+ process.stderr.write(`\n Report "${reportId}" not found.\n\n`);
286
+ process.exit(1);
287
+ }
288
+ if (opts.html) {
289
+ const { generateReportHtml } = await import("./reports/html.js");
290
+ const { getReportsDir } = await import("./reports/writer.js");
291
+ const reportsDir = getReportsDir(configDir);
292
+ const htmlPath = path.join(reportsDir, report.reportId, "report.html");
293
+ fs.writeFileSync(htmlPath, generateReportHtml(report));
294
+ const { exec } = await import("node:child_process");
295
+ const openCmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
296
+ exec(`${openCmd} "${htmlPath}"`);
297
+ process.stdout.write(`\n Report opened in browser: ${htmlPath}\n\n`);
298
+ return;
299
+ }
300
+ if (opts.json) {
301
+ process.stdout.write(JSON.stringify(report, null, 2) + "\n");
302
+ }
303
+ else {
304
+ process.stdout.write(renderReportDetail(report));
305
+ }
306
+ }
307
+ catch (err) {
308
+ process.stderr.write(`\n Error: ${formatError(err)}\n\n`);
309
+ process.exit(1);
310
+ }
311
+ });
312
+ // --- Baseline comparison helper ---
313
+ function runBaselineComparison(configDir, baselineName, reportId, json) {
314
+ try {
315
+ const baseline = readBaseline(configDir, baselineName);
316
+ if (!baseline) {
317
+ process.stderr.write(`\n Baseline "${baselineName}" not found.\n\n`);
318
+ return 1;
319
+ }
320
+ const report = readReport(configDir, reportId);
321
+ if (!report) {
322
+ process.stderr.write(`\n Report "${reportId}" not found.\n\n`);
323
+ return 1;
324
+ }
325
+ const diff = diffBaseline(baseline, report);
326
+ if (json) {
327
+ process.stdout.write(JSON.stringify(diff, null, 2) + "\n");
328
+ }
329
+ else {
330
+ process.stdout.write(renderBaselineDiff(diff));
331
+ }
332
+ return diff.summary.regressed > 0 ? 1 : 0;
333
+ }
334
+ catch (err) {
335
+ process.stderr.write(`\n Error: ${formatError(err)}\n\n`);
336
+ return 1;
337
+ }
338
+ }
339
+ // --- axis baseline command ---
340
+ const baselineCmd = program.command("baseline").description("Manage baselines for regression detection");
341
+ baselineCmd
342
+ .command("set [name]")
343
+ .description(`Create or update a baseline from the latest (or specific) report (default name: "${DEFAULT_BASELINE_NAME}")`)
344
+ .option("-c, --config <path>", "path to axis.config.json", "axis.config.json")
345
+ .option("--from <reportId>", "use a specific report instead of latest")
346
+ .action(async (name, opts) => {
347
+ try {
348
+ const baselineName = name ?? DEFAULT_BASELINE_NAME;
349
+ const { configDir } = await loadConfig(opts.config);
350
+ const report = readReport(configDir, opts.from ?? "latest");
351
+ if (!report) {
352
+ process.stderr.write(opts.from ? `\n Report "${opts.from}" not found.\n\n` : `\n No reports found. Run \`axis run\` first.\n\n`);
353
+ process.exit(1);
354
+ }
355
+ const baseline = setBaseline(configDir, report, baselineName);
356
+ const scenarioCount = Object.keys(baseline.results).length;
357
+ const agentSet = new Set();
358
+ for (const agents of Object.values(baseline.results)) {
359
+ for (const agent of Object.keys(agents))
360
+ agentSet.add(agent);
361
+ }
362
+ process.stdout.write(`\n Baseline "${baselineName}" updated — ${scenarioCount} scenario(s), ${agentSet.size} agent(s)\n` +
363
+ ` Source: report ${report.reportId}\n\n`);
364
+ }
365
+ catch (err) {
366
+ process.stderr.write(`\n Error: ${formatError(err)}\n\n`);
367
+ process.exit(1);
368
+ }
369
+ });
370
+ baselineCmd
371
+ .command("list")
372
+ .description("List all baselines")
373
+ .option("-c, --config <path>", "path to axis.config.json", "axis.config.json")
374
+ .action(async (opts) => {
375
+ try {
376
+ const { configDir } = await loadConfig(opts.config);
377
+ const baselines = listBaselines(configDir);
378
+ if (baselines.length === 0) {
379
+ process.stdout.write("\n No baselines found. Use `axis baseline set` to create one.\n\n");
380
+ return;
381
+ }
382
+ process.stdout.write(renderBaselineList(baselines));
383
+ }
384
+ catch (err) {
385
+ process.stderr.write(`\n Error: ${formatError(err)}\n\n`);
386
+ process.exit(1);
387
+ }
388
+ });
389
+ baselineCmd
390
+ .command("show [name]")
391
+ .description(`Show baseline contents (default name: "${DEFAULT_BASELINE_NAME}")`)
392
+ .option("-c, --config <path>", "path to axis.config.json", "axis.config.json")
393
+ .option("--json", "output as JSON", false)
394
+ .action(async (name, opts) => {
395
+ try {
396
+ const baselineName = name ?? DEFAULT_BASELINE_NAME;
397
+ const { configDir } = await loadConfig(opts.config);
398
+ const baseline = readBaseline(configDir, baselineName);
399
+ if (!baseline) {
400
+ process.stderr.write(`\n Baseline "${baselineName}" not found.\n\n`);
401
+ process.exit(1);
402
+ }
403
+ if (opts.json) {
404
+ process.stdout.write(JSON.stringify(baseline, null, 2) + "\n");
405
+ }
406
+ else {
407
+ process.stdout.write(renderBaselineShow(baseline));
408
+ }
409
+ }
410
+ catch (err) {
411
+ process.stderr.write(`\n Error: ${formatError(err)}\n\n`);
412
+ process.exit(1);
413
+ }
414
+ });
415
+ baselineCmd
416
+ .command("diff [name]")
417
+ .description(`Compare the latest (or specific) report against a baseline (default name: "${DEFAULT_BASELINE_NAME}")`)
418
+ .option("-c, --config <path>", "path to axis.config.json", "axis.config.json")
419
+ .option("--report <reportId>", "compare a specific report instead of latest")
420
+ .option("--json", "output as JSON", false)
421
+ .action(async (name, opts) => {
422
+ try {
423
+ const baselineName = name ?? DEFAULT_BASELINE_NAME;
424
+ const { configDir } = await loadConfig(opts.config);
425
+ const baseline = readBaseline(configDir, baselineName);
426
+ if (!baseline) {
427
+ process.stderr.write(`\n Baseline "${baselineName}" not found.\n\n`);
428
+ process.exit(1);
429
+ }
430
+ const report = readReport(configDir, opts.report ?? "latest");
431
+ if (!report) {
432
+ process.stderr.write(opts.report
433
+ ? `\n Report "${opts.report}" not found.\n\n`
434
+ : `\n No reports found. Run \`axis run\` first.\n\n`);
435
+ process.exit(1);
436
+ }
437
+ const diff = diffBaseline(baseline, report);
438
+ if (opts.json) {
439
+ process.stdout.write(JSON.stringify(diff, null, 2) + "\n");
440
+ }
441
+ else {
442
+ process.stdout.write(renderBaselineDiff(diff));
443
+ }
444
+ if (diff.summary.regressed > 0)
445
+ process.exit(1);
446
+ }
447
+ catch (err) {
448
+ process.stderr.write(`\n Error: ${formatError(err)}\n\n`);
449
+ process.exit(1);
450
+ }
451
+ });
452
+ baselineCmd
453
+ .command("delete [name]")
454
+ .description(`Delete a baseline (default name: "${DEFAULT_BASELINE_NAME}")`)
455
+ .option("-c, --config <path>", "path to axis.config.json", "axis.config.json")
456
+ .action(async (name, opts) => {
457
+ try {
458
+ const baselineName = name ?? DEFAULT_BASELINE_NAME;
459
+ const { configDir } = await loadConfig(opts.config);
460
+ const deleted = deleteBaseline(configDir, baselineName);
461
+ if (deleted) {
462
+ process.stdout.write(`\n Baseline "${baselineName}" deleted.\n\n`);
463
+ }
464
+ else {
465
+ process.stderr.write(`\n Baseline "${baselineName}" not found.\n\n`);
466
+ process.exit(1);
467
+ }
468
+ }
469
+ catch (err) {
470
+ process.stderr.write(`\n Error: ${formatError(err)}\n\n`);
471
+ process.exit(1);
472
+ }
473
+ });
474
+ program.parse();
475
+ // --- Legacy report file writing (for --output-dir) ---
476
+ function writeReportFile(output, outputDir) {
477
+ const resolvedDir = path.resolve(outputDir);
478
+ fs.mkdirSync(resolvedDir, { recursive: true });
479
+ const timestamp = output.timestamp.replace(/[:.]/g, "-");
480
+ const filename = `axis-report-${timestamp}.json`;
481
+ const filePath = path.join(resolvedDir, filename);
482
+ const fd = fs.openSync(filePath, "w");
483
+ fs.writeSync(fd, JSON.stringify(output, null, 2));
484
+ fs.closeSync(fd);
485
+ return filePath;
486
+ }
487
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { AxisConfig } from "../types/config.js";
2
+ import type { Scenario } from "../types/scenario.js";
3
+ export declare function loadConfig(configPath?: string): Promise<{
4
+ config: AxisConfig;
5
+ configDir: string;
6
+ }>;
7
+ export declare function discoverScenarios(configDir: string, scenariosPath: string, filter?: string[]): Promise<Scenario[]>;
8
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAIrD,wBAAsB,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAuBxG;AAED,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,EACrB,MAAM,CAAC,EAAE,MAAM,EAAE,GAChB,OAAO,CAAC,QAAQ,EAAE,CAAC,CA0BrB"}
@@ -0,0 +1,99 @@
1
+ import * as fs from "node:fs/promises";
2
+ import * as path from "node:path";
3
+ import { validateConfig, validateScenario } from "./validator.js";
4
+ import { formatError } from "../types/output.js";
5
+ export async function loadConfig(configPath) {
6
+ const resolvedPath = path.resolve(configPath ?? "axis.config.json");
7
+ let raw;
8
+ try {
9
+ raw = await fs.readFile(resolvedPath, "utf-8");
10
+ }
11
+ catch (err) {
12
+ throw new Error(`Could not read config file at ${resolvedPath}: ${formatError(err)}`);
13
+ }
14
+ let parsed;
15
+ try {
16
+ parsed = JSON.parse(raw);
17
+ }
18
+ catch {
19
+ throw new Error(`Failed to parse JSON in ${resolvedPath}`);
20
+ }
21
+ validateConfig(parsed, resolvedPath);
22
+ return {
23
+ config: parsed,
24
+ configDir: path.dirname(resolvedPath),
25
+ };
26
+ }
27
+ export async function discoverScenarios(configDir, scenariosPath, filter) {
28
+ const rootDir = path.resolve(configDir, scenariosPath);
29
+ let stat;
30
+ try {
31
+ stat = await fs.stat(rootDir);
32
+ }
33
+ catch (err) {
34
+ throw new Error(`Could not read scenarios directory at ${rootDir}: ${formatError(err)}`);
35
+ }
36
+ if (!stat.isDirectory()) {
37
+ throw new Error(`Scenarios path is not a directory: ${rootDir}`);
38
+ }
39
+ const scenarios = [];
40
+ await walkDir(rootDir, rootDir, scenarios);
41
+ // Sort by key for deterministic ordering
42
+ scenarios.sort((a, b) => a.key.localeCompare(b.key));
43
+ // Filter scenarios if agent specifies a subset
44
+ if (filter && !filter.includes("*")) {
45
+ return scenarios.filter((s) => matchesFilter(s.key, filter));
46
+ }
47
+ return scenarios;
48
+ }
49
+ async function walkDir(dir, rootDir, scenarios) {
50
+ const entries = await fs.readdir(dir, { withFileTypes: true });
51
+ for (const entry of entries) {
52
+ const fullPath = path.join(dir, entry.name);
53
+ if (entry.isDirectory()) {
54
+ await walkDir(fullPath, rootDir, scenarios);
55
+ }
56
+ else if (entry.isFile() && entry.name.endsWith(".json")) {
57
+ const scenario = await loadScenarioFile(fullPath, rootDir);
58
+ scenarios.push(scenario);
59
+ }
60
+ }
61
+ }
62
+ async function loadScenarioFile(filePath, rootDir) {
63
+ const raw = await fs.readFile(filePath, "utf-8");
64
+ let parsed;
65
+ try {
66
+ parsed = JSON.parse(raw);
67
+ }
68
+ catch {
69
+ throw new Error(`Failed to parse JSON in scenario file ${filePath}`);
70
+ }
71
+ validateScenario(parsed, filePath);
72
+ // Derive key from relative path: scenarios/cms/create-post.json → "cms/create-post"
73
+ const relativePath = path.relative(rootDir, filePath);
74
+ const key = relativePath
75
+ .replace(/\.json$/, "")
76
+ .split(path.sep)
77
+ .join("/");
78
+ parsed.key = key;
79
+ return parsed;
80
+ }
81
+ function matchesFilter(key, filter) {
82
+ return filter.some((pattern) => {
83
+ // Exact match
84
+ if (pattern === key)
85
+ return true;
86
+ // Simple glob: "cms/*" matches "cms/create-post" and "cms/delete-post"
87
+ if (pattern.endsWith("/*")) {
88
+ const prefix = pattern.slice(0, -2);
89
+ return key.startsWith(prefix + "/");
90
+ }
91
+ // Prefix glob: "cms/**" matches any depth under cms/
92
+ if (pattern.endsWith("/**")) {
93
+ const prefix = pattern.slice(0, -3);
94
+ return key.startsWith(prefix + "/");
95
+ }
96
+ return false;
97
+ });
98
+ }
99
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { AxisConfig } from "../types/config.js";
2
+ import type { RubricCriterion, Scenario } from "../types/scenario.js";
3
+ export declare function validateConfig(data: unknown, filePath: string): asserts data is AxisConfig;
4
+ export declare function validateScenario(data: unknown, filePath: string): asserts data is Scenario;
5
+ /**
6
+ * Resolve optional weights on rubric entries. Entries with explicit weights
7
+ * keep them; entries without a weight split the remaining budget equally.
8
+ * If no entries have weights, each gets `1 / n`.
9
+ */
10
+ export declare function resolveRubricWeights(rubric: RubricCriterion[]): RubricCriterion[];
11
+ //# sourceMappingURL=validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/config/validator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEtE,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,IAAI,UAAU,CAuD1F;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,IAAI,QAAQ,CAoD1F;AAqFD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,eAAe,EAAE,GAAG,eAAe,EAAE,CAajF"}