stepproof 0.2.22 → 0.4.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 (85) hide show
  1. package/dist/adapters/anthropic.d.ts +3 -2
  2. package/dist/adapters/anthropic.d.ts.map +1 -1
  3. package/dist/adapters/anthropic.js +27 -5
  4. package/dist/adapters/anthropic.js.map +1 -1
  5. package/dist/adapters/base.d.ts +14 -1
  6. package/dist/adapters/base.d.ts.map +1 -1
  7. package/dist/adapters/gemini.d.ts +9 -0
  8. package/dist/adapters/gemini.d.ts.map +1 -0
  9. package/dist/adapters/gemini.js +80 -0
  10. package/dist/adapters/gemini.js.map +1 -0
  11. package/dist/adapters/index.d.ts.map +1 -1
  12. package/dist/adapters/index.js +7 -1
  13. package/dist/adapters/index.js.map +1 -1
  14. package/dist/adapters/ollama.d.ts +9 -0
  15. package/dist/adapters/ollama.d.ts.map +1 -0
  16. package/dist/adapters/ollama.js +61 -0
  17. package/dist/adapters/ollama.js.map +1 -0
  18. package/dist/adapters/openai.d.ts +3 -2
  19. package/dist/adapters/openai.d.ts.map +1 -1
  20. package/dist/adapters/openai.js +16 -5
  21. package/dist/adapters/openai.js.map +1 -1
  22. package/dist/assertions/engine.d.ts +6 -1
  23. package/dist/assertions/engine.d.ts.map +1 -1
  24. package/dist/assertions/engine.js +176 -11
  25. package/dist/assertions/engine.js.map +1 -1
  26. package/dist/baseline.d.ts +23 -0
  27. package/dist/baseline.d.ts.map +1 -0
  28. package/dist/baseline.js +98 -0
  29. package/dist/baseline.js.map +1 -0
  30. package/dist/cache.d.ts +5 -0
  31. package/dist/cache.d.ts.map +1 -0
  32. package/dist/cache.js +71 -0
  33. package/dist/cache.js.map +1 -0
  34. package/dist/cli.js +283 -18
  35. package/dist/cli.js.map +1 -1
  36. package/dist/commands/compare.d.ts +43 -0
  37. package/dist/commands/compare.d.ts.map +1 -0
  38. package/dist/commands/compare.js +75 -0
  39. package/dist/commands/compare.js.map +1 -0
  40. package/dist/commands/diff.d.ts +2 -0
  41. package/dist/commands/diff.d.ts.map +1 -0
  42. package/dist/commands/diff.js +252 -0
  43. package/dist/commands/diff.js.map +1 -0
  44. package/dist/commands/history.d.ts +2 -0
  45. package/dist/commands/history.d.ts.map +1 -0
  46. package/dist/commands/history.js +46 -0
  47. package/dist/commands/history.js.map +1 -0
  48. package/dist/commands/results-store.d.ts +15 -0
  49. package/dist/commands/results-store.d.ts.map +1 -0
  50. package/dist/commands/results-store.js +77 -0
  51. package/dist/commands/results-store.js.map +1 -0
  52. package/dist/commands/view.d.ts +2 -0
  53. package/dist/commands/view.d.ts.map +1 -0
  54. package/dist/commands/view.js +51 -0
  55. package/dist/commands/view.js.map +1 -0
  56. package/dist/commands/watch.d.ts +7 -0
  57. package/dist/commands/watch.d.ts.map +1 -0
  58. package/dist/commands/watch.js +84 -0
  59. package/dist/commands/watch.js.map +1 -0
  60. package/dist/core/scenario-parser.d.ts.map +1 -1
  61. package/dist/core/scenario-parser.js +47 -5
  62. package/dist/core/scenario-parser.js.map +1 -1
  63. package/dist/core/scenario-runner.d.ts +12 -0
  64. package/dist/core/scenario-runner.d.ts.map +1 -1
  65. package/dist/core/scenario-runner.js +372 -41
  66. package/dist/core/scenario-runner.js.map +1 -1
  67. package/dist/core/types.d.ts +63 -9
  68. package/dist/core/types.d.ts.map +1 -1
  69. package/dist/dataset.d.ts +6 -0
  70. package/dist/dataset.d.ts.map +1 -0
  71. package/dist/dataset.js +108 -0
  72. package/dist/dataset.js.map +1 -0
  73. package/dist/reporters/github-comment.d.ts +8 -0
  74. package/dist/reporters/github-comment.d.ts.map +1 -0
  75. package/dist/reporters/github-comment.js +114 -0
  76. package/dist/reporters/github-comment.js.map +1 -0
  77. package/dist/reporters/html-reporter.d.ts +3 -0
  78. package/dist/reporters/html-reporter.d.ts.map +1 -0
  79. package/dist/reporters/html-reporter.js +152 -0
  80. package/dist/reporters/html-reporter.js.map +1 -0
  81. package/dist/reporters/terminal-reporter.d.ts +10 -1
  82. package/dist/reporters/terminal-reporter.d.ts.map +1 -1
  83. package/dist/reporters/terminal-reporter.js +139 -8
  84. package/dist/reporters/terminal-reporter.js.map +1 -1
  85. package/package.json +2 -1
@@ -0,0 +1,252 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import chalk from 'chalk';
4
+ import * as yaml from 'js-yaml';
5
+ import { loadBaseline, loadBaselineYaml } from '../baseline.js';
6
+ /**
7
+ * Compute a simple line-by-line diff between two strings.
8
+ * Uses a basic LCS approach — O(n*m) time and space where n,m = line counts.
9
+ * Fine for scenario files which are typically <200 lines.
10
+ */
11
+ function computeLineDiff(oldText, newText) {
12
+ const oldLines = oldText.split('\n');
13
+ const newLines = newText.split('\n');
14
+ const n = oldLines.length;
15
+ const m = newLines.length;
16
+ // LCS table — O(n*m)
17
+ const dp = Array.from({ length: n + 1 }, () => new Array(m + 1).fill(0));
18
+ for (let i = 1; i <= n; i++) {
19
+ for (let j = 1; j <= m; j++) {
20
+ if (oldLines[i - 1] === newLines[j - 1]) {
21
+ dp[i][j] = dp[i - 1][j - 1] + 1;
22
+ }
23
+ else {
24
+ dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
25
+ }
26
+ }
27
+ }
28
+ // Backtrack to produce diff
29
+ const result = [];
30
+ let i = n, j = m;
31
+ while (i > 0 || j > 0) {
32
+ if (i > 0 && j > 0 && oldLines[i - 1] === newLines[j - 1]) {
33
+ result.push({ type: 'same', text: oldLines[i - 1] });
34
+ i--;
35
+ j--;
36
+ }
37
+ else if (j > 0 && (i === 0 || dp[i][j - 1] >= dp[i - 1][j])) {
38
+ result.push({ type: 'added', text: newLines[j - 1] });
39
+ j--;
40
+ }
41
+ else {
42
+ result.push({ type: 'removed', text: oldLines[i - 1] });
43
+ i--;
44
+ }
45
+ }
46
+ result.reverse();
47
+ return result;
48
+ }
49
+ function extractSteps(yamlContent) {
50
+ const map = new Map();
51
+ try {
52
+ const parsed = yaml.load(yamlContent);
53
+ if (!parsed || !Array.isArray(parsed.steps))
54
+ return map;
55
+ for (const step of parsed.steps) {
56
+ if (step && typeof step === 'object' && typeof step.id === 'string') {
57
+ map.set(step.id, {
58
+ id: step.id,
59
+ model: typeof step.model === 'string' ? step.model : undefined,
60
+ prompt: typeof step.prompt === 'string' ? step.prompt : undefined,
61
+ system: typeof step.system === 'string' ? step.system : undefined,
62
+ assertions: Array.isArray(step.assertions) ? step.assertions : undefined,
63
+ });
64
+ }
65
+ }
66
+ }
67
+ catch {
68
+ // If YAML parse fails, return empty
69
+ }
70
+ return map;
71
+ }
72
+ function formatPromptDiff(oldPrompt, newPrompt) {
73
+ const lines = [];
74
+ const diff = computeLineDiff(oldPrompt, newPrompt);
75
+ for (const d of diff) {
76
+ if (d.type === 'removed') {
77
+ lines.push(chalk.red(` - "${d.text}"`));
78
+ }
79
+ else if (d.type === 'added') {
80
+ lines.push(chalk.green(` + "${d.text}"`));
81
+ }
82
+ // skip 'same' lines for prompt diff — only show changes
83
+ }
84
+ return lines;
85
+ }
86
+ export function runDiff(scenarioPath) {
87
+ const resolvedPath = path.resolve(process.cwd(), scenarioPath);
88
+ // Read current scenario YAML
89
+ let currentYaml;
90
+ try {
91
+ currentYaml = fs.readFileSync(resolvedPath, 'utf-8');
92
+ }
93
+ catch {
94
+ console.error(`\nError: Cannot read scenario file: ${resolvedPath}\n`);
95
+ process.exit(2);
96
+ }
97
+ // Extract scenario name from current YAML
98
+ let scenarioName;
99
+ try {
100
+ const parsed = yaml.load(currentYaml);
101
+ scenarioName = parsed.name;
102
+ if (!scenarioName)
103
+ throw new Error('no name');
104
+ }
105
+ catch {
106
+ console.error('\nError: Cannot parse scenario name from YAML\n');
107
+ process.exit(2);
108
+ return; // unreachable, but TS needs it
109
+ }
110
+ // Load baseline YAML
111
+ const baselineYaml = loadBaselineYaml(scenarioName);
112
+ if (!baselineYaml) {
113
+ console.error(`\nNo baseline found for "${scenarioName}".`);
114
+ console.error('Run `stepproof run` first to create a baseline.\n');
115
+ process.exit(1);
116
+ return;
117
+ }
118
+ // Load baseline report for pass rates
119
+ const baselineReport = loadBaseline(scenarioName);
120
+ const baselineRates = new Map();
121
+ if (baselineReport) {
122
+ for (const s of baselineReport.steps) {
123
+ baselineRates.set(s.stepId, s.passRate);
124
+ }
125
+ }
126
+ // Extract steps from both versions
127
+ const oldSteps = extractSteps(baselineYaml);
128
+ const newSteps = extractSteps(currentYaml);
129
+ // Determine the baseline timestamp
130
+ const baselineDate = baselineReport?.completedAt ?? 'unknown';
131
+ console.log('');
132
+ console.log(chalk.bold(`stepproof diff — ${scenarioName}`));
133
+ console.log(chalk.dim(`Changes since last baseline (${baselineDate}):`));
134
+ console.log('');
135
+ // Collect all step IDs (union of old and new)
136
+ const allStepIds = new Set([...oldSteps.keys(), ...newSteps.keys()]);
137
+ let hasAnyChange = false;
138
+ for (const stepId of allStepIds) {
139
+ const oldStep = oldSteps.get(stepId);
140
+ const newStep = newSteps.get(stepId);
141
+ if (!oldStep && newStep) {
142
+ // New step added
143
+ hasAnyChange = true;
144
+ console.log(` ${chalk.bold(stepId)} ${chalk.green('(new step)')}`);
145
+ console.log('');
146
+ continue;
147
+ }
148
+ if (oldStep && !newStep) {
149
+ // Step removed
150
+ hasAnyChange = true;
151
+ console.log(` ${chalk.bold(stepId)} ${chalk.red('(removed)')}`);
152
+ console.log('');
153
+ continue;
154
+ }
155
+ if (!oldStep || !newStep)
156
+ continue;
157
+ const changes = [];
158
+ // Model change
159
+ if (oldStep.model !== newStep.model) {
160
+ changes.push(` ${chalk.dim('model:')} ${chalk.red(oldStep.model ?? '(none)')} → ${chalk.green(newStep.model ?? '(none)')} ${chalk.yellow('(changed)')}`);
161
+ }
162
+ // System prompt change
163
+ if (oldStep.system !== newStep.system) {
164
+ if (!oldStep.system && newStep.system) {
165
+ changes.push(` ${chalk.dim('system:')} ${chalk.green('(added)')}`);
166
+ changes.push(chalk.green(` + "${newStep.system}"`));
167
+ }
168
+ else if (oldStep.system && !newStep.system) {
169
+ changes.push(` ${chalk.dim('system:')} ${chalk.red('(removed)')}`);
170
+ }
171
+ else if (oldStep.system && newStep.system) {
172
+ changes.push(` ${chalk.dim('system:')}`);
173
+ changes.push(...formatPromptDiff(oldStep.system, newStep.system));
174
+ }
175
+ }
176
+ // Prompt change
177
+ if (oldStep.prompt !== newStep.prompt) {
178
+ if (oldStep.prompt && newStep.prompt) {
179
+ changes.push(` ${chalk.dim('prompt:')}`);
180
+ changes.push(...formatPromptDiff(oldStep.prompt, newStep.prompt));
181
+ }
182
+ else if (!oldStep.prompt && newStep.prompt) {
183
+ changes.push(` ${chalk.dim('prompt:')} ${chalk.green('(added)')}`);
184
+ }
185
+ else if (oldStep.prompt && !newStep.prompt) {
186
+ changes.push(` ${chalk.dim('prompt:')} ${chalk.red('(removed)')}`);
187
+ }
188
+ }
189
+ // Assertions change
190
+ const oldAssertStr = JSON.stringify(oldStep.assertions ?? []);
191
+ const newAssertStr = JSON.stringify(newStep.assertions ?? []);
192
+ if (oldAssertStr !== newAssertStr) {
193
+ changes.push(` ${chalk.dim('assertions:')} ${chalk.yellow('(changed)')}`);
194
+ }
195
+ if (changes.length > 0) {
196
+ hasAnyChange = true;
197
+ console.log(` ${chalk.bold(stepId)}`);
198
+ for (const line of changes) {
199
+ console.log(line);
200
+ }
201
+ // Show pass rate change if baseline has rates
202
+ const oldRate = baselineRates.get(stepId);
203
+ if (oldRate !== undefined) {
204
+ const pct = (oldRate * 100).toFixed(0);
205
+ console.log(` ${chalk.dim(`pass rate at baseline: ${pct}%`)}`);
206
+ }
207
+ console.log('');
208
+ }
209
+ else {
210
+ // No changes for this step — show it as unchanged with pass rate if available
211
+ const rate = baselineRates.get(stepId);
212
+ if (rate !== undefined) {
213
+ const pct = (rate * 100).toFixed(0);
214
+ console.log(` ${chalk.bold(stepId)} ${chalk.dim('(no changes)')}`);
215
+ console.log(` ${chalk.dim(`pass rate at baseline: ${pct}%`)}`);
216
+ console.log('');
217
+ }
218
+ else {
219
+ console.log(` ${chalk.bold(stepId)} ${chalk.dim('(no changes)')}`);
220
+ console.log('');
221
+ }
222
+ }
223
+ }
224
+ // Full raw diff
225
+ if (hasAnyChange) {
226
+ console.log(chalk.dim('─'.repeat(50)));
227
+ console.log(chalk.dim('Raw YAML diff:'));
228
+ console.log('');
229
+ const rawDiff = computeLineDiff(baselineYaml, currentYaml);
230
+ let contextWindow = 0;
231
+ for (let idx = 0; idx < rawDiff.length; idx++) {
232
+ const d = rawDiff[idx];
233
+ if (d.type === 'removed') {
234
+ console.log(chalk.red(` - ${d.text}`));
235
+ contextWindow = 3;
236
+ }
237
+ else if (d.type === 'added') {
238
+ console.log(chalk.green(` + ${d.text}`));
239
+ contextWindow = 3;
240
+ }
241
+ else if (contextWindow > 0) {
242
+ console.log(chalk.dim(` ${d.text}`));
243
+ contextWindow--;
244
+ }
245
+ }
246
+ }
247
+ else {
248
+ console.log(chalk.dim('No changes detected between current scenario and baseline.'));
249
+ }
250
+ console.log('');
251
+ }
252
+ //# sourceMappingURL=diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/commands/diff.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function runHistory(scenario?: string): void;
2
+ //# sourceMappingURL=history.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../../src/commands/history.ts"],"names":[],"mappings":"AAKA,wBAAgB,UAAU,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAqClD"}
@@ -0,0 +1,46 @@
1
+ import * as fs from 'node:fs';
2
+ import { getResultsDir, listReports } from './results-store.js';
3
+ export function runHistory(scenario) {
4
+ const resultsDir = getResultsDir();
5
+ if (!fs.existsSync(resultsDir)) {
6
+ console.error('\nNo results found. Run a scenario first: stepproof run ./scenarios/first-test.yaml\n');
7
+ process.exit(2);
8
+ }
9
+ const files = listReports(scenario);
10
+ if (files.length === 0) {
11
+ if (scenario) {
12
+ console.error(`\nNo results found for scenario "${scenario}"\n`);
13
+ }
14
+ else {
15
+ console.error('\nNo results found. Run a scenario first.\n');
16
+ }
17
+ process.exit(2);
18
+ }
19
+ console.log('');
20
+ console.log(scenario ? `History for: ${scenario}` : 'Recent runs');
21
+ console.log('─'.repeat(60));
22
+ for (const file of files) {
23
+ try {
24
+ const report = JSON.parse(fs.readFileSync(file, 'utf8'));
25
+ const date = new Date(report.startedAt).toLocaleString();
26
+ const verdict = report.allPassed ? '\x1b[32mPASS\x1b[0m' : '\x1b[31mFAIL\x1b[0m';
27
+ const duration = formatDuration(report.durationMs);
28
+ const stepsInfo = `${report.steps.filter(s => !s.belowThreshold).length}/${report.steps.length} steps`;
29
+ console.log(` ${verdict} ${report.scenarioName} ${date} ${duration} ${stepsInfo}`);
30
+ }
31
+ catch {
32
+ // Skip corrupted files
33
+ }
34
+ }
35
+ console.log('');
36
+ }
37
+ function formatDuration(ms) {
38
+ if (ms < 1000)
39
+ return `${ms}ms`;
40
+ if (ms < 60_000)
41
+ return `${(ms / 1000).toFixed(1)}s`;
42
+ const mins = Math.floor(ms / 60_000);
43
+ const secs = ((ms % 60_000) / 1000).toFixed(0);
44
+ return `${mins}m ${secs}s`;
45
+ }
46
+ //# sourceMappingURL=history.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.js","sourceRoot":"","sources":["../../src/commands/history.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAE9B,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGhE,MAAM,UAAU,UAAU,CAAC,QAAiB;IAC1C,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IAEnC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,OAAO,CAAC,KAAK,CAAC,uFAAuF,CAAC,CAAC;QACvG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,KAAK,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;IAEpC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,oCAAoC,QAAQ,KAAK,CAAC,CAAC;QACnE,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,6CAA6C,CAAC,CAAC;QAC/D,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,gBAAgB,QAAQ,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC;IACnE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAE5B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,MAAM,GAAmB,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;YACzE,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,cAAc,EAAE,CAAC;YACzD,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,qBAAqB,CAAC;YACjF,MAAM,QAAQ,GAAG,cAAc,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YACnD,MAAM,SAAS,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,MAAM,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC;YACvG,OAAO,CAAC,GAAG,CAAC,KAAK,OAAO,KAAK,MAAM,CAAC,YAAY,KAAK,IAAI,KAAK,QAAQ,KAAK,SAAS,EAAE,CAAC,CAAC;QAC1F,CAAC;QAAC,MAAM,CAAC;YACP,uBAAuB;QACzB,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAClB,CAAC;AAED,SAAS,cAAc,CAAC,EAAU;IAChC,IAAI,EAAE,GAAG,IAAI;QAAE,OAAO,GAAG,EAAE,IAAI,CAAC;IAChC,IAAI,EAAE,GAAG,MAAM;QAAE,OAAO,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IACrD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,MAAM,CAAC,CAAC;IACrC,MAAM,IAAI,GAAG,CAAC,CAAC,EAAE,GAAG,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAC/C,OAAO,GAAG,IAAI,KAAK,IAAI,GAAG,CAAC;AAC7B,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { ScenarioReport } from '../core/types.js';
2
+ /** Get results directory path (relative to cwd) */
3
+ export declare function getResultsDir(): string;
4
+ /**
5
+ * Save a report to .stepproof/results/{slug}-{timestamp}.json
6
+ * Prunes old reports to keep only the last MAX_REPORTS_PER_SCENARIO per scenario.
7
+ */
8
+ export declare function saveReport(report: ScenarioReport): string;
9
+ /** Find the most recent report file across all scenarios */
10
+ export declare function findLatestReport(): string | undefined;
11
+ /** Find the most recent report for a specific scenario (by name or slug prefix match) */
12
+ export declare function findLatestReportForScenario(scenario: string): string | undefined;
13
+ /** List recent report files, optionally filtered by scenario. Returns newest first. */
14
+ export declare function listReports(scenario?: string): string[];
15
+ //# sourceMappingURL=results-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"results-store.d.ts","sourceRoot":"","sources":["../../src/commands/results-store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAKvD,mDAAmD;AACnD,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAOD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAwBzD;AAED,4DAA4D;AAC5D,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,SAAS,CAUrD;AAED,yFAAyF;AACzF,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAahF;AAED,uFAAuF;AACvF,wBAAgB,WAAW,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAavD"}
@@ -0,0 +1,77 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ const RESULTS_DIR_NAME = '.stepproof/results';
4
+ const MAX_REPORTS_PER_SCENARIO = 10;
5
+ /** Get results directory path (relative to cwd) */
6
+ export function getResultsDir() {
7
+ return path.resolve(process.cwd(), RESULTS_DIR_NAME);
8
+ }
9
+ /** Slugify scenario name for use in filenames */
10
+ function slugify(name) {
11
+ return name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
12
+ }
13
+ /**
14
+ * Save a report to .stepproof/results/{slug}-{timestamp}.json
15
+ * Prunes old reports to keep only the last MAX_REPORTS_PER_SCENARIO per scenario.
16
+ */
17
+ export function saveReport(report) {
18
+ const dir = getResultsDir();
19
+ fs.mkdirSync(dir, { recursive: true });
20
+ const slug = slugify(report.scenarioName);
21
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
22
+ const filename = `${slug}-${timestamp}.json`;
23
+ const filepath = path.join(dir, filename);
24
+ fs.writeFileSync(filepath, JSON.stringify(report, null, 2), 'utf8');
25
+ // Prune: keep only last MAX_REPORTS_PER_SCENARIO for this scenario slug
26
+ const prefix = slug + '-';
27
+ const allForScenario = fs.readdirSync(dir)
28
+ .filter(f => f.startsWith(prefix) && f.endsWith('.json'))
29
+ .sort()
30
+ .reverse(); // newest first (ISO timestamps sort lexicographically)
31
+ // O(n) single pass — n is bounded by report count per scenario
32
+ for (let i = MAX_REPORTS_PER_SCENARIO; i < allForScenario.length; i++) {
33
+ try {
34
+ fs.unlinkSync(path.join(dir, allForScenario[i]));
35
+ }
36
+ catch { /* ignore */ }
37
+ }
38
+ return filepath;
39
+ }
40
+ /** Find the most recent report file across all scenarios */
41
+ export function findLatestReport() {
42
+ const dir = getResultsDir();
43
+ if (!fs.existsSync(dir))
44
+ return undefined;
45
+ const files = fs.readdirSync(dir)
46
+ .filter(f => f.endsWith('.json'))
47
+ .sort()
48
+ .reverse();
49
+ return files.length > 0 ? path.join(dir, files[0]) : undefined;
50
+ }
51
+ /** Find the most recent report for a specific scenario (by name or slug prefix match) */
52
+ export function findLatestReportForScenario(scenario) {
53
+ const dir = getResultsDir();
54
+ if (!fs.existsSync(dir))
55
+ return undefined;
56
+ const slug = slugify(scenario);
57
+ const prefix = slug + '-';
58
+ const files = fs.readdirSync(dir)
59
+ .filter(f => f.startsWith(prefix) && f.endsWith('.json'))
60
+ .sort()
61
+ .reverse();
62
+ return files.length > 0 ? path.join(dir, files[0]) : undefined;
63
+ }
64
+ /** List recent report files, optionally filtered by scenario. Returns newest first. */
65
+ export function listReports(scenario) {
66
+ const dir = getResultsDir();
67
+ if (!fs.existsSync(dir))
68
+ return [];
69
+ let files = fs.readdirSync(dir).filter(f => f.endsWith('.json'));
70
+ if (scenario) {
71
+ const slug = slugify(scenario);
72
+ const prefix = slug + '-';
73
+ files = files.filter(f => f.startsWith(prefix));
74
+ }
75
+ return files.sort().reverse().map(f => path.join(dir, f));
76
+ }
77
+ //# sourceMappingURL=results-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"results-store.js","sourceRoot":"","sources":["../../src/commands/results-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function runView(scenario?: string): void;
2
+ //# sourceMappingURL=view.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../../src/commands/view.ts"],"names":[],"mappings":"AAQA,wBAAgB,OAAO,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAgD/C"}
@@ -0,0 +1,51 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import * as os from 'node:os';
4
+ import { exec } from 'node:child_process';
5
+ import { generateHtmlReport } from '../reporters/html-reporter.js';
6
+ import { getResultsDir, findLatestReport, findLatestReportForScenario } from './results-store.js';
7
+ export function runView(scenario) {
8
+ const resultsDir = getResultsDir();
9
+ if (!fs.existsSync(resultsDir)) {
10
+ console.error('\nNo results found. Run a scenario first: stepproof run ./scenarios/first-test.yaml\n');
11
+ process.exit(2);
12
+ }
13
+ let reportPath;
14
+ if (scenario) {
15
+ reportPath = findLatestReportForScenario(scenario);
16
+ if (!reportPath) {
17
+ console.error(`\nNo results found for scenario "${scenario}"\n`);
18
+ process.exit(2);
19
+ }
20
+ }
21
+ else {
22
+ reportPath = findLatestReport();
23
+ if (!reportPath) {
24
+ console.error('\nNo results found. Run a scenario first.\n');
25
+ process.exit(2);
26
+ }
27
+ }
28
+ let report;
29
+ try {
30
+ report = JSON.parse(fs.readFileSync(reportPath, 'utf8'));
31
+ }
32
+ catch {
33
+ console.error(`\nFailed to read report: ${reportPath}\n`);
34
+ process.exit(2);
35
+ }
36
+ const html = generateHtmlReport(report);
37
+ const tmpDir = path.join(os.tmpdir(), 'stepproof');
38
+ fs.mkdirSync(tmpDir, { recursive: true });
39
+ const htmlPath = path.join(tmpDir, `report-${Date.now()}.html`);
40
+ fs.writeFileSync(htmlPath, html, 'utf8');
41
+ const openCmd = process.platform === 'darwin' ? 'open'
42
+ : process.platform === 'win32' ? 'start'
43
+ : 'xdg-open';
44
+ console.log(`\nOpening report: ${htmlPath}\n`);
45
+ exec(`${openCmd} "${htmlPath}"`, (err) => {
46
+ if (err) {
47
+ console.log(`Could not open browser automatically. Open this file manually:\n ${htmlPath}\n`);
48
+ }
49
+ });
50
+ }
51
+ //# sourceMappingURL=view.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"view.js","sourceRoot":"","sources":["../../src/commands/view.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,2BAA2B,EAAE,MAAM,oBAAoB,CAAC;AAGlG,MAAM,UAAU,OAAO,CAAC,QAAiB;IACvC,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IAEnC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,OAAO,CAAC,KAAK,CAAC,uFAAuF,CAAC,CAAC;QACvG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,UAA8B,CAAC;IAEnC,IAAI,QAAQ,EAAE,CAAC;QACb,UAAU,GAAG,2BAA2B,CAAC,QAAQ,CAAC,CAAC;QACnD,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,OAAO,CAAC,KAAK,CAAC,oCAAoC,QAAQ,KAAK,CAAC,CAAC;YACjE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;SAAM,CAAC;QACN,UAAU,GAAG,gBAAgB,EAAE,CAAC;QAChC,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,OAAO,CAAC,KAAK,CAAC,6CAA6C,CAAC,CAAC;YAC7D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED,IAAI,MAAsB,CAAC;IAC3B,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,KAAK,CAAC,4BAA4B,UAAU,IAAI,CAAC,CAAC;QAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,IAAI,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,WAAW,CAAC,CAAC;IACnD,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAChE,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IAEzC,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM;QACpD,CAAC,CAAC,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO;YACxC,CAAC,CAAC,UAAU,CAAC;IAEf,OAAO,CAAC,GAAG,CAAC,qBAAqB,QAAQ,IAAI,CAAC,CAAC;IAC/C,IAAI,CAAC,GAAG,OAAO,KAAK,QAAQ,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE;QACvC,IAAI,GAAG,EAAE,CAAC;YACR,OAAO,CAAC,GAAG,CAAC,qEAAqE,QAAQ,IAAI,CAAC,CAAC;QACjG,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,7 @@
1
+ export interface WatchOptions {
2
+ iterations?: number;
3
+ noCache?: boolean;
4
+ dataset?: string;
5
+ }
6
+ export declare function startWatch(scenarioPath: string, opts: WatchOptions): void;
7
+ //# sourceMappingURL=watch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../src/commands/watch.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,YAAY;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,UAAU,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,GAAG,IAAI,CAoFzE"}
@@ -0,0 +1,84 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import chalk from 'chalk';
4
+ import { parseScenario } from '../core/scenario-parser.js';
5
+ import { runScenario } from '../core/scenario-runner.js';
6
+ import { printReport } from '../reporters/terminal-reporter.js';
7
+ import { loadDataset } from '../dataset.js';
8
+ export function startWatch(scenarioPath, opts) {
9
+ const resolvedPath = path.resolve(process.cwd(), scenarioPath);
10
+ if (!fs.existsSync(resolvedPath)) {
11
+ console.error(`\nError: Scenario not found: ${resolvedPath}\n`);
12
+ process.exit(2);
13
+ }
14
+ let running = false;
15
+ let debounceTimer = null;
16
+ async function executeRun() {
17
+ if (running)
18
+ return;
19
+ running = true;
20
+ // Clear terminal
21
+ process.stdout.write('\x1Bc');
22
+ console.log(chalk.dim(`Watching ${path.basename(resolvedPath)}... (press Ctrl+C to stop)\n`));
23
+ try {
24
+ const scenario = parseScenario(resolvedPath);
25
+ let dataset;
26
+ if (opts.dataset) {
27
+ const datasetPath = path.resolve(process.cwd(), opts.dataset);
28
+ dataset = loadDataset(datasetPath);
29
+ }
30
+ const iterations = opts.iterations ?? scenario.iterations ?? 10;
31
+ const runOptions = {
32
+ iterations: opts.iterations,
33
+ noCache: opts.noCache,
34
+ dataset,
35
+ datasetPath: opts.dataset,
36
+ onIterationComplete: (iteration, total) => {
37
+ process.stdout.write(`\r Completed iteration ${iteration}/${total}...`);
38
+ if (iteration === total) {
39
+ process.stdout.write('\r' + ' '.repeat(50) + '\r');
40
+ }
41
+ },
42
+ };
43
+ const report = await runScenario(scenario, resolvedPath, runOptions);
44
+ printReport(report, { cacheStats: runOptions.cacheStats });
45
+ }
46
+ catch (e) {
47
+ console.error(chalk.red(`\nError: ${e.message}\n`));
48
+ }
49
+ running = false;
50
+ console.log(chalk.dim(`\nWaiting for changes to ${path.basename(resolvedPath)}...`));
51
+ }
52
+ function onFileChange() {
53
+ if (debounceTimer)
54
+ clearTimeout(debounceTimer);
55
+ debounceTimer = setTimeout(() => {
56
+ void executeRun();
57
+ }, 500);
58
+ }
59
+ // Initial run
60
+ void executeRun();
61
+ // Watch the scenario file
62
+ try {
63
+ fs.watch(resolvedPath, { persistent: true }, (_eventType) => {
64
+ onFileChange();
65
+ });
66
+ }
67
+ catch (e) {
68
+ console.error(chalk.red(`\nError watching file: ${e.message}\n`));
69
+ process.exit(2);
70
+ }
71
+ // Also watch the dataset file if provided
72
+ if (opts.dataset) {
73
+ const datasetResolved = path.resolve(process.cwd(), opts.dataset);
74
+ try {
75
+ fs.watch(datasetResolved, { persistent: true }, (_eventType) => {
76
+ onFileChange();
77
+ });
78
+ }
79
+ catch {
80
+ // Dataset file watch is best-effort
81
+ }
82
+ }
83
+ }
84
+ //# sourceMappingURL=watch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watch.js","sourceRoot":"","sources":["../../src/commands/watch.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"scenario-parser.d.ts","sourceRoot":"","sources":["../../src/core/scenario-parser.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAQ,MAAM,YAAY,CAAC;AAEjD,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,CAuCxD;AA0CD,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACjC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAClC,MAAM,CAyBR"}
1
+ {"version":3,"file":"scenario-parser.d.ts","sourceRoot":"","sources":["../../src/core/scenario-parser.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAoB,QAAQ,EAAQ,MAAM,YAAY,CAAC;AAEnE,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,CAuCxD;AAwFD,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACjC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAClC,MAAM,CAyBR"}