@inbrowser/agent 0.1.0 → 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 (90) hide show
  1. package/LICENSE +21 -0
  2. package/dist/diagnostics/index.d.ts +5 -0
  3. package/dist/diagnostics/index.d.ts.map +1 -0
  4. package/dist/diagnostics/index.js +3 -0
  5. package/dist/diagnostics/index.js.map +1 -0
  6. package/dist/diagnostics/timing.d.ts +48 -0
  7. package/dist/diagnostics/timing.d.ts.map +1 -0
  8. package/dist/diagnostics/timing.js +85 -0
  9. package/dist/diagnostics/timing.js.map +1 -0
  10. package/dist/diagnostics/truthfulness.d.ts +36 -0
  11. package/dist/diagnostics/truthfulness.d.ts.map +1 -0
  12. package/dist/diagnostics/truthfulness.js +180 -0
  13. package/dist/diagnostics/truthfulness.js.map +1 -0
  14. package/dist/dispatch-memoization.d.ts +84 -0
  15. package/dist/dispatch-memoization.d.ts.map +1 -0
  16. package/dist/dispatch-memoization.js +197 -0
  17. package/dist/dispatch-memoization.js.map +1 -0
  18. package/dist/eval/comparison-report.d.ts +164 -0
  19. package/dist/eval/comparison-report.d.ts.map +1 -0
  20. package/dist/eval/comparison-report.js +316 -0
  21. package/dist/eval/comparison-report.js.map +1 -0
  22. package/dist/eval/fixture.d.ts +74 -0
  23. package/dist/eval/fixture.d.ts.map +1 -0
  24. package/dist/eval/fixture.js +217 -0
  25. package/dist/eval/fixture.js.map +1 -0
  26. package/dist/eval/index.d.ts +13 -0
  27. package/dist/eval/index.d.ts.map +1 -0
  28. package/dist/eval/index.js +7 -0
  29. package/dist/eval/index.js.map +1 -0
  30. package/dist/eval/load-node.d.ts +16 -0
  31. package/dist/eval/load-node.d.ts.map +1 -0
  32. package/dist/eval/load-node.js +58 -0
  33. package/dist/eval/load-node.js.map +1 -0
  34. package/dist/eval/metric-collector.d.ts +209 -0
  35. package/dist/eval/metric-collector.d.ts.map +1 -0
  36. package/dist/eval/metric-collector.js +293 -0
  37. package/dist/eval/metric-collector.js.map +1 -0
  38. package/dist/eval/run-record.d.ts +76 -0
  39. package/dist/eval/run-record.d.ts.map +1 -0
  40. package/dist/eval/run-record.js +32 -0
  41. package/dist/eval/run-record.js.map +1 -0
  42. package/dist/eval/runner.d.ts +140 -0
  43. package/dist/eval/runner.d.ts.map +1 -0
  44. package/dist/eval/runner.js +310 -0
  45. package/dist/eval/runner.js.map +1 -0
  46. package/dist/eval/spec-framework.d.ts +113 -0
  47. package/dist/eval/spec-framework.d.ts.map +1 -0
  48. package/dist/eval/spec-framework.js +100 -0
  49. package/dist/eval/spec-framework.js.map +1 -0
  50. package/dist/eval/spec-helpers.d.ts +245 -0
  51. package/dist/eval/spec-helpers.d.ts.map +1 -0
  52. package/dist/eval/spec-helpers.js +605 -0
  53. package/dist/eval/spec-helpers.js.map +1 -0
  54. package/dist/index.d.ts +24 -3
  55. package/dist/index.d.ts.map +1 -1
  56. package/dist/index.js +11 -1
  57. package/dist/index.js.map +1 -1
  58. package/dist/node.d.ts +1 -0
  59. package/dist/node.d.ts.map +1 -1
  60. package/dist/node.js +1 -0
  61. package/dist/node.js.map +1 -1
  62. package/dist/planner-executor.d.ts +132 -0
  63. package/dist/planner-executor.d.ts.map +1 -0
  64. package/dist/planner-executor.js +274 -0
  65. package/dist/planner-executor.js.map +1 -0
  66. package/dist/skill-catalog.d.ts +81 -0
  67. package/dist/skill-catalog.d.ts.map +1 -0
  68. package/dist/skill-catalog.js +388 -0
  69. package/dist/skill-catalog.js.map +1 -0
  70. package/dist/skill-router.d.ts +95 -0
  71. package/dist/skill-router.d.ts.map +1 -0
  72. package/dist/skill-router.js +130 -0
  73. package/dist/skill-router.js.map +1 -0
  74. package/dist/strategy.d.ts +20 -1
  75. package/dist/strategy.d.ts.map +1 -1
  76. package/dist/strategy.js +333 -13
  77. package/dist/strategy.js.map +1 -1
  78. package/dist/tools.d.ts +15 -1
  79. package/dist/tools.d.ts.map +1 -1
  80. package/dist/tools.js +18 -0
  81. package/dist/tools.js.map +1 -1
  82. package/dist/types/strategy.d.ts +48 -0
  83. package/dist/types/strategy.d.ts.map +1 -1
  84. package/dist/types/tools.d.ts +18 -0
  85. package/dist/types/tools.d.ts.map +1 -1
  86. package/dist/types/trace.d.ts +59 -9
  87. package/dist/types/trace.d.ts.map +1 -1
  88. package/dist/types/trace.js +5 -3
  89. package/dist/types/trace.js.map +1 -1
  90. package/package.json +1 -1
@@ -0,0 +1,316 @@
1
+ /**
2
+ * `compareMetrics` — the eval harness's A/B comparison report.
3
+ *
4
+ * Consumes two named `MetricsTable[]`s (typically a "baseline" and a
5
+ * "variant"), pairs them by `fixtureId`, and for each per-metric
6
+ * column emits a row containing the inputs (mean +/- spread for both
7
+ * sides), the delta (`variantMean - baselineMean`), the threshold
8
+ * (`max(baselineSpread, variantSpread)`), and a label.
9
+ *
10
+ * The label uses the implementation plan's no-effect rule:
11
+ *
12
+ * - If `Math.abs(delta) < threshold`, label `no-effect`. This is the
13
+ * central discipline: noisy trial-to-trial variance must not be
14
+ * reported as a winner.
15
+ * - Otherwise consult the metric's polarity (see `POLARITY` below):
16
+ * higher-is-better -> sign of `delta` picks the winner;
17
+ * lower-is-better -> sign of `delta` picks the loser;
18
+ * neutral -> emit `changed` (no winner, just a flag).
19
+ *
20
+ * Polarity is a static map declared in this module. Adding a new
21
+ * metric to the collector forces an entry here because the map is
22
+ * keyed by a string-literal union derived from `MetricsTable` fields.
23
+ *
24
+ * Two renderers ship with the comparator:
25
+ *
26
+ * - `renderMarkdown(report)` — a human-readable markdown table for
27
+ * piping to stdout from a CLI consumer.
28
+ * - `renderJson(report)` — `JSON.stringify(report, null, 2)`. Plain
29
+ * data; round-trips through `JSON.parse(JSON.stringify(report))`
30
+ * without loss.
31
+ *
32
+ * No statistical sophistication beyond the no-effect rule. Confidence
33
+ * intervals, cross-fixture aggregation, and multi-variant comparisons
34
+ * are deliberately deferred to follow-up branches.
35
+ *
36
+ * Browser-safe — no Node imports.
37
+ *
38
+ * Note on naming: metric names match the collector exactly. Do not
39
+ * rename. The CLI, the report, and any later UI all key on these
40
+ * identifiers, and renaming in one layer without the others silently
41
+ * breaks consumers.
42
+ */
43
+ /**
44
+ * Static polarity table. Choices are documented per row; the
45
+ * neutral defaults are the metrics the implementation plan
46
+ * explicitly says are context-dependent.
47
+ *
48
+ * Adding a new metric to the collector requires adding an entry
49
+ * here. The `Record<ComparisonMetricName, Polarity>` shape keeps the
50
+ * compiler honest if `ComparisonMetricName` is extended.
51
+ */
52
+ export const POLARITY = {
53
+ // Higher success rate is strictly better.
54
+ taskSuccessRate: 'higher-is-better',
55
+ // Lower latency / token spend / context pressure is better.
56
+ wallClockMs: 'lower-is-better',
57
+ promptTokens: 'lower-is-better',
58
+ completionTokens: 'lower-is-better',
59
+ peakContextWindowBytes: 'lower-is-better',
60
+ // Lower violation rate is strictly better (zero is the goal).
61
+ truthfulnessViolationRate: 'lower-is-better',
62
+ // Tool-call counts are context-dependent: more reads can mean
63
+ // better grounding (good) or wasted effort (bad). Neutral by
64
+ // default. Specific experiments can re-interpret these via the
65
+ // `polarityOverrides` input.
66
+ 'toolCallCount.total': 'neutral',
67
+ 'toolCallCount.reads': 'neutral',
68
+ 'toolCallCount.mutations': 'neutral',
69
+ // Turn count is context-dependent for the same reason.
70
+ turnCount: 'neutral',
71
+ // Dispatch-vs-LLM ratio is a diagnostic, not a quality metric.
72
+ dispatchVsLlmRatio: 'neutral',
73
+ };
74
+ /**
75
+ * Build a `ComparisonReport` from two named metric tables.
76
+ *
77
+ * Fixtures present in both sides are paired; fixtures unique to one
78
+ * side surface with an explicit `status` and no rows. Within each
79
+ * paired fixture, every entry in `POLARITY` produces one row.
80
+ *
81
+ * Never throws on missing data — `undefined` means / spreads carry
82
+ * through to `undefined` deltas / thresholds and a `no-effect` label.
83
+ */
84
+ export function compareMetrics(input) {
85
+ const baselineName = input.baselineName ?? 'baseline';
86
+ const variantName = input.variantName ?? 'variant';
87
+ const overrides = input.polarityOverrides ?? {};
88
+ const baselineMap = byFixtureId(input.baseline);
89
+ const variantMap = byFixtureId(input.variant);
90
+ // Union order: baseline fixtures in their input order, then variant
91
+ // fixtures that did not appear in baseline (also in input order).
92
+ const ids = [];
93
+ const seen = new Set();
94
+ for (const t of input.baseline) {
95
+ if (seen.has(t.fixtureId))
96
+ continue;
97
+ seen.add(t.fixtureId);
98
+ ids.push(t.fixtureId);
99
+ }
100
+ for (const t of input.variant) {
101
+ if (seen.has(t.fixtureId))
102
+ continue;
103
+ seen.add(t.fixtureId);
104
+ ids.push(t.fixtureId);
105
+ }
106
+ const fixtures = [];
107
+ for (const fixtureId of ids) {
108
+ const b = baselineMap.get(fixtureId);
109
+ const v = variantMap.get(fixtureId);
110
+ if (b && !v) {
111
+ fixtures.push({ fixtureId, status: 'baseline-only', rows: [] });
112
+ continue;
113
+ }
114
+ if (!b && v) {
115
+ fixtures.push({ fixtureId, status: 'variant-only', rows: [] });
116
+ continue;
117
+ }
118
+ if (!b || !v)
119
+ continue; // Defensive: should not happen given the union build.
120
+ const rows = [];
121
+ for (const metric of METRIC_NAMES) {
122
+ const polarity = overrides[metric] ?? POLARITY[metric];
123
+ const baselineStat = readStat(b, metric);
124
+ const variantStat = readStat(v, metric);
125
+ rows.push(buildRow(fixtureId, metric, polarity, baselineStat, variantStat));
126
+ }
127
+ fixtures.push({ fixtureId, status: 'both', rows });
128
+ }
129
+ return { baselineName, variantName, fixtures };
130
+ }
131
+ /** Iteration order for metric rows in a fixture. Stable and matches `POLARITY`. */
132
+ const METRIC_NAMES = [
133
+ 'taskSuccessRate',
134
+ 'wallClockMs',
135
+ 'promptTokens',
136
+ 'completionTokens',
137
+ 'toolCallCount.total',
138
+ 'toolCallCount.reads',
139
+ 'toolCallCount.mutations',
140
+ 'turnCount',
141
+ 'peakContextWindowBytes',
142
+ 'truthfulnessViolationRate',
143
+ 'dispatchVsLlmRatio',
144
+ ];
145
+ function buildRow(fixtureId, metric, polarity, baseline, variant) {
146
+ if (baseline.mean === undefined ||
147
+ variant.mean === undefined ||
148
+ baseline.stdDev === undefined ||
149
+ variant.stdDev === undefined) {
150
+ return {
151
+ fixtureId,
152
+ metric,
153
+ polarity,
154
+ baseline,
155
+ variant,
156
+ delta: undefined,
157
+ threshold: undefined,
158
+ label: 'no-effect',
159
+ };
160
+ }
161
+ const delta = variant.mean - baseline.mean;
162
+ const threshold = Math.max(baseline.stdDev, variant.stdDev);
163
+ const label = classify(delta, threshold, polarity);
164
+ return { fixtureId, metric, polarity, baseline, variant, delta, threshold, label };
165
+ }
166
+ /**
167
+ * Apply the no-effect rule, then the polarity rule.
168
+ *
169
+ * No-effect rule: `Math.abs(delta) < threshold`. Strict `<` per the
170
+ * implementation plan — when `|delta|` exactly equals the spread, the
171
+ * row still rises to a winner. We add one degenerate carve-out: a
172
+ * delta of exactly zero is always no-effect regardless of threshold,
173
+ * because there is no direction to pick a winner from. This matters
174
+ * for single-trial inputs where both spreads are zero.
175
+ *
176
+ * Polarity rule:
177
+ * - higher-is-better: positive delta -> variant wins; negative -> baseline wins.
178
+ * - lower-is-better: positive delta -> baseline wins; negative -> variant wins.
179
+ * - neutral: movement gets `changed`; no winner is implied.
180
+ */
181
+ function classify(delta, threshold, polarity) {
182
+ if (delta === 0)
183
+ return 'no-effect';
184
+ if (Math.abs(delta) < threshold)
185
+ return 'no-effect';
186
+ if (polarity === 'neutral')
187
+ return 'changed';
188
+ if (polarity === 'higher-is-better') {
189
+ return delta > 0 ? 'winner-variant' : 'winner-baseline';
190
+ }
191
+ // lower-is-better
192
+ return delta > 0 ? 'winner-baseline' : 'winner-variant';
193
+ }
194
+ function byFixtureId(tables) {
195
+ const out = new Map();
196
+ for (const t of tables) {
197
+ // First-seen wins. Duplicate fixture ids in one input are unusual
198
+ // but not the comparator's problem to surface.
199
+ if (!out.has(t.fixtureId))
200
+ out.set(t.fixtureId, t);
201
+ }
202
+ return out;
203
+ }
204
+ function readStat(table, metric) {
205
+ switch (metric) {
206
+ case 'taskSuccessRate':
207
+ return table.aggregate.taskSuccessRate;
208
+ case 'wallClockMs':
209
+ return table.aggregate.wallClockMs;
210
+ case 'promptTokens':
211
+ return table.aggregate.promptTokens;
212
+ case 'completionTokens':
213
+ return table.aggregate.completionTokens;
214
+ case 'toolCallCount.total':
215
+ return table.aggregate.toolCallCount.total;
216
+ case 'toolCallCount.reads':
217
+ return table.aggregate.toolCallCount.reads;
218
+ case 'toolCallCount.mutations':
219
+ return table.aggregate.toolCallCount.mutations;
220
+ case 'turnCount':
221
+ return table.aggregate.turnCount;
222
+ case 'peakContextWindowBytes':
223
+ return table.aggregate.peakContextWindowBytes;
224
+ case 'truthfulnessViolationRate':
225
+ return table.aggregate.truthfulnessViolationRate;
226
+ case 'dispatchVsLlmRatio':
227
+ return table.aggregate.dispatchVsLlmRatio;
228
+ }
229
+ }
230
+ // ---------- renderers ----------
231
+ /**
232
+ * Render a `ComparisonReport` as plain JSON.
233
+ *
234
+ * Implementation is `JSON.stringify(report, null, 2)`. The report is
235
+ * pure data: no functions, no `undefined` in places where the
236
+ * renderer cares (numeric fields surface as `null` after a round-trip
237
+ * but the consumer treats `null` and missing the same way).
238
+ */
239
+ export function renderJson(report) {
240
+ return JSON.stringify(report, null, 2);
241
+ }
242
+ /**
243
+ * Render a `ComparisonReport` as a markdown document.
244
+ *
245
+ * One section per fixture. Each section has a header with the
246
+ * fixture id and its coverage status, then a table with seven
247
+ * columns: metric, baseline (mean +/- spread), variant (mean +/-
248
+ * spread), delta, threshold, polarity, label.
249
+ *
250
+ * Numeric formatting:
251
+ * - mean / spread use up to four significant digits;
252
+ * - `undefined` renders as `-`;
253
+ * - delta and threshold use the same formatter as mean.
254
+ */
255
+ export function renderMarkdown(report) {
256
+ const lines = [];
257
+ lines.push(`# Comparison: ${report.baselineName} vs ${report.variantName}`);
258
+ lines.push('');
259
+ if (report.fixtures.length === 0) {
260
+ lines.push('_No fixtures in either input._');
261
+ return lines.join('\n');
262
+ }
263
+ for (const fixture of report.fixtures) {
264
+ lines.push(`## ${fixture.fixtureId}`);
265
+ if (fixture.status === 'baseline-only') {
266
+ lines.push('');
267
+ lines.push(`_Present in ${report.baselineName} only — no comparison rows._`);
268
+ lines.push('');
269
+ continue;
270
+ }
271
+ if (fixture.status === 'variant-only') {
272
+ lines.push('');
273
+ lines.push(`_Present in ${report.variantName} only — no comparison rows._`);
274
+ lines.push('');
275
+ continue;
276
+ }
277
+ lines.push('');
278
+ lines.push(`| metric | ${report.baselineName} | ${report.variantName} | delta | threshold | polarity | label |`);
279
+ lines.push('|---|---|---|---|---|---|---|');
280
+ for (const row of fixture.rows) {
281
+ const cells = [
282
+ row.metric,
283
+ formatStat(row.baseline),
284
+ formatStat(row.variant),
285
+ formatNumber(row.delta),
286
+ formatNumber(row.threshold),
287
+ row.polarity,
288
+ row.label,
289
+ ];
290
+ lines.push(`| ${cells.join(' | ')} |`);
291
+ }
292
+ lines.push('');
293
+ }
294
+ return lines.join('\n').trimEnd();
295
+ }
296
+ function formatStat(stat) {
297
+ if (stat.mean === undefined || stat.stdDev === undefined)
298
+ return '-';
299
+ return `${formatNumber(stat.mean)} ± ${formatNumber(stat.stdDev)} (n=${stat.count})`;
300
+ }
301
+ function formatNumber(value) {
302
+ if (value === undefined)
303
+ return '-';
304
+ if (!Number.isFinite(value))
305
+ return String(value);
306
+ if (value === 0)
307
+ return '0';
308
+ const abs = Math.abs(value);
309
+ if (abs >= 1000)
310
+ return value.toFixed(0);
311
+ if (abs >= 1)
312
+ return value.toFixed(2);
313
+ // Small numbers: four significant digits keeps spreads readable.
314
+ return value.toPrecision(4);
315
+ }
316
+ //# sourceMappingURL=comparison-report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comparison-report.js","sourceRoot":"","sources":["../../src/eval/comparison-report.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Task fixture schema for the eval harness.
3
+ *
4
+ * A `TaskFixture` describes one reproducible evaluation case: a user
5
+ * prompt, an initial workspace state, and a reference to the success
6
+ * specification that decides whether a run passed.
7
+ *
8
+ * This file is browser-safe — types, `validateFixture`, `parseFixture`,
9
+ * `applyWorkspaceOverrides` only. File loading lives in
10
+ * `eval/load-node.ts` and is re-exported via `@inbrowser/agent/node`.
11
+ *
12
+ * Example fixture (JSON):
13
+ *
14
+ * {
15
+ * "id": "firestore-rules-audit/seed-open-write-01",
16
+ * "skill": "firestore-rules-audit",
17
+ * "description": "Detects open-write vulnerability on /users",
18
+ * "prompt": "Audit my Firestore rules for security issues.",
19
+ * "initialState": {
20
+ * "rules": "rules_version='2'; ..."
21
+ * },
22
+ * "successSpec": {
23
+ * "name": "firestore-rules-audit/names-planted-vulnerability",
24
+ * "args": { "vulnerability": "open-write-users" }
25
+ * }
26
+ * }
27
+ */
28
+ import type { StitchContext, Workspace } from '../types/workspace.js';
29
+ export type SkillName = 'firestore-rules-audit' | 'firebase-project-audit' | 'rtdb-data-modeling' | 'firebase-security-rules' | 'firebase-client-sdk' | 'pyric-agents' | 'playground-prompts' | 'rtdb-game-rules' | 'firestore-game-rules';
30
+ export declare const SKILL_NAMES: readonly SkillName[];
31
+ export interface PartialWorkspace {
32
+ presetId?: string;
33
+ rules?: string;
34
+ code?: string;
35
+ appSource?: string;
36
+ stitch?: Partial<StitchContext>;
37
+ }
38
+ export interface SuccessSpecReference {
39
+ /** Stable spec identifier in `family/spec-name` kebab-case form. */
40
+ name: string;
41
+ /** Optional structured arguments passed when the spec runs. */
42
+ args?: Record<string, unknown>;
43
+ }
44
+ export interface TaskFixture {
45
+ /** Stable identifier in `skill-prefix/case-name` kebab-case form. */
46
+ id: string;
47
+ /** The skill family this fixture exercises. */
48
+ skill: SkillName;
49
+ /** One-line human summary; shown in comparison reports. */
50
+ description: string;
51
+ /** Optional free-form prose; ignored by tooling. */
52
+ notes?: string;
53
+ /** The user prompt, verbatim. */
54
+ prompt: string;
55
+ /** Optional initial workspace state, applied on top of EMPTY_WORKSPACE. */
56
+ initialState?: PartialWorkspace;
57
+ /** Reference to the success spec that decides this fixture's pass/fail. */
58
+ successSpec: SuccessSpecReference;
59
+ }
60
+ export interface ValidationError {
61
+ path: string;
62
+ message: string;
63
+ }
64
+ export type ValidationResult = {
65
+ ok: true;
66
+ fixture: TaskFixture;
67
+ } | {
68
+ ok: false;
69
+ errors: ValidationError[];
70
+ };
71
+ export declare function validateFixture(input: unknown): ValidationResult;
72
+ export declare function parseFixture(json: string): ValidationResult;
73
+ export declare function applyWorkspaceOverrides(base: Workspace, overrides: PartialWorkspace | undefined): Workspace;
74
+ //# sourceMappingURL=fixture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixture.d.ts","sourceRoot":"","sources":["../../src/eval/fixture.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEtE,MAAM,MAAM,SAAS,GACjB,uBAAuB,GACvB,wBAAwB,GACxB,oBAAoB,GACpB,yBAAyB,GACzB,qBAAqB,GACrB,cAAc,GACd,oBAAoB,GACpB,iBAAiB,GACjB,sBAAsB,CAAC;AAE3B,eAAO,MAAM,WAAW,EAAE,SAAS,SAAS,EAU3C,CAAC;AAEF,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,oBAAoB;IACnC,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,WAAW;IAC1B,qEAAqE;IACrE,EAAE,EAAE,MAAM,CAAC;IACX,+CAA+C;IAC/C,KAAK,EAAE,SAAS,CAAC;IACjB,2DAA2D;IAC3D,WAAW,EAAE,MAAM,CAAC;IACpB,oDAAoD;IACpD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,YAAY,CAAC,EAAE,gBAAgB,CAAC;IAChC,2EAA2E;IAC3E,WAAW,EAAE,oBAAoB,CAAC;CACnC;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,gBAAgB,GACxB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,WAAW,CAAA;CAAE,GAClC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,eAAe,EAAE,CAAA;CAAE,CAAC;AAmB7C,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,gBAAgB,CAgDhE;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAS3D;AAED,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,SAAS,EACf,SAAS,EAAE,gBAAgB,GAAG,SAAS,GACtC,SAAS,CAaX"}
@@ -0,0 +1,217 @@
1
+ /**
2
+ * Task fixture schema for the eval harness.
3
+ *
4
+ * A `TaskFixture` describes one reproducible evaluation case: a user
5
+ * prompt, an initial workspace state, and a reference to the success
6
+ * specification that decides whether a run passed.
7
+ *
8
+ * This file is browser-safe — types, `validateFixture`, `parseFixture`,
9
+ * `applyWorkspaceOverrides` only. File loading lives in
10
+ * `eval/load-node.ts` and is re-exported via `@inbrowser/agent/node`.
11
+ *
12
+ * Example fixture (JSON):
13
+ *
14
+ * {
15
+ * "id": "firestore-rules-audit/seed-open-write-01",
16
+ * "skill": "firestore-rules-audit",
17
+ * "description": "Detects open-write vulnerability on /users",
18
+ * "prompt": "Audit my Firestore rules for security issues.",
19
+ * "initialState": {
20
+ * "rules": "rules_version='2'; ..."
21
+ * },
22
+ * "successSpec": {
23
+ * "name": "firestore-rules-audit/names-planted-vulnerability",
24
+ * "args": { "vulnerability": "open-write-users" }
25
+ * }
26
+ * }
27
+ */
28
+ export const SKILL_NAMES = [
29
+ 'firestore-rules-audit',
30
+ 'firebase-project-audit',
31
+ 'rtdb-data-modeling',
32
+ 'firebase-security-rules',
33
+ 'firebase-client-sdk',
34
+ 'pyric-agents',
35
+ 'playground-prompts',
36
+ 'rtdb-game-rules',
37
+ 'firestore-game-rules',
38
+ ];
39
+ const ID_PATTERN = /^[a-z][a-z0-9-]*\/[a-z][a-z0-9-]*$/;
40
+ const SPEC_NAME_PATTERN = /^[a-z][a-z0-9-]*\/[a-z][a-z0-9-]*$/;
41
+ const SKILL_NAME_SET = new Set(SKILL_NAMES);
42
+ const FIXTURE_KEYS = new Set([
43
+ 'id',
44
+ 'skill',
45
+ 'description',
46
+ 'notes',
47
+ 'prompt',
48
+ 'initialState',
49
+ 'successSpec',
50
+ ]);
51
+ const INITIAL_STATE_KEYS = new Set(['presetId', 'rules', 'code', 'appSource', 'stitch']);
52
+ const STITCH_KEYS = new Set(['projectId', 'latestScreenUrl', 'brief']);
53
+ const SPEC_KEYS = new Set(['name', 'args']);
54
+ export function validateFixture(input) {
55
+ if (!isPlainObject(input)) {
56
+ return { ok: false, errors: [{ path: '', message: 'fixture must be a plain object' }] };
57
+ }
58
+ const obj = input;
59
+ const errors = [];
60
+ requireString(obj, 'id', errors, (value) => {
61
+ if (!ID_PATTERN.test(value)) {
62
+ errors.push({
63
+ path: 'id',
64
+ message: 'id must match `skill-prefix/case-name` kebab-case (e.g., "firestore-rules-audit/seed-01")',
65
+ });
66
+ }
67
+ });
68
+ requireString(obj, 'skill', errors, (value) => {
69
+ if (!SKILL_NAME_SET.has(value)) {
70
+ errors.push({
71
+ path: 'skill',
72
+ message: `skill must be one of: ${SKILL_NAMES.join(', ')}`,
73
+ });
74
+ }
75
+ });
76
+ requireString(obj, 'description', errors);
77
+ optionalString(obj, 'notes', errors);
78
+ requireString(obj, 'prompt', errors);
79
+ if (obj.initialState !== undefined) {
80
+ validateInitialState(obj.initialState, 'initialState', errors);
81
+ }
82
+ if (obj.successSpec === undefined) {
83
+ errors.push({ path: 'successSpec', message: 'successSpec is required' });
84
+ }
85
+ else {
86
+ validateSpecRef(obj.successSpec, 'successSpec', errors);
87
+ }
88
+ for (const key of Object.keys(obj)) {
89
+ if (!FIXTURE_KEYS.has(key)) {
90
+ errors.push({ path: key, message: `unknown field "${key}"` });
91
+ }
92
+ }
93
+ if (errors.length > 0)
94
+ return { ok: false, errors };
95
+ return { ok: true, fixture: obj };
96
+ }
97
+ export function parseFixture(json) {
98
+ let parsed;
99
+ try {
100
+ parsed = JSON.parse(json);
101
+ }
102
+ catch (err) {
103
+ const message = err instanceof Error ? err.message : 'invalid JSON';
104
+ return { ok: false, errors: [{ path: '', message: `failed to parse JSON: ${message}` }] };
105
+ }
106
+ return validateFixture(parsed);
107
+ }
108
+ export function applyWorkspaceOverrides(base, overrides) {
109
+ if (!overrides)
110
+ return base;
111
+ return {
112
+ presetId: overrides.presetId ?? base.presetId,
113
+ rules: overrides.rules ?? base.rules,
114
+ code: overrides.code ?? base.code,
115
+ appSource: overrides.appSource ?? base.appSource,
116
+ stitch: {
117
+ projectId: overrides.stitch?.projectId ?? base.stitch.projectId,
118
+ latestScreenUrl: overrides.stitch?.latestScreenUrl ?? base.stitch.latestScreenUrl,
119
+ brief: overrides.stitch?.brief ?? base.stitch.brief,
120
+ },
121
+ };
122
+ }
123
+ function isPlainObject(value) {
124
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
125
+ }
126
+ function requireString(obj, key, errors, onValid) {
127
+ const value = obj[key];
128
+ if (value === undefined) {
129
+ errors.push({ path: key, message: `${key} is required` });
130
+ return;
131
+ }
132
+ if (typeof value !== 'string') {
133
+ errors.push({ path: key, message: `${key} must be a string` });
134
+ return;
135
+ }
136
+ if (value.length === 0) {
137
+ errors.push({ path: key, message: `${key} must not be empty` });
138
+ return;
139
+ }
140
+ if (onValid)
141
+ onValid(value);
142
+ }
143
+ function optionalString(obj, key, errors) {
144
+ const value = obj[key];
145
+ if (value === undefined)
146
+ return;
147
+ if (typeof value !== 'string') {
148
+ errors.push({ path: key, message: `${key} must be a string when present` });
149
+ }
150
+ }
151
+ function validateInitialState(value, path, errors) {
152
+ if (!isPlainObject(value)) {
153
+ errors.push({ path, message: `${path} must be an object` });
154
+ return;
155
+ }
156
+ for (const key of Object.keys(value)) {
157
+ if (!INITIAL_STATE_KEYS.has(key)) {
158
+ errors.push({ path: `${path}.${key}`, message: `unknown field "${key}"` });
159
+ }
160
+ }
161
+ for (const key of ['presetId', 'rules', 'code', 'appSource']) {
162
+ const v = value[key];
163
+ if (v !== undefined && typeof v !== 'string') {
164
+ errors.push({
165
+ path: `${path}.${key}`,
166
+ message: `${path}.${key} must be a string when present`,
167
+ });
168
+ }
169
+ }
170
+ if (value.stitch !== undefined) {
171
+ validateStitchOverrides(value.stitch, `${path}.stitch`, errors);
172
+ }
173
+ }
174
+ function validateStitchOverrides(value, path, errors) {
175
+ if (!isPlainObject(value)) {
176
+ errors.push({ path, message: `${path} must be an object when present` });
177
+ return;
178
+ }
179
+ for (const key of Object.keys(value)) {
180
+ if (!STITCH_KEYS.has(key)) {
181
+ errors.push({ path: `${path}.${key}`, message: `unknown field "${key}"` });
182
+ }
183
+ }
184
+ for (const key of ['projectId', 'latestScreenUrl', 'brief']) {
185
+ const v = value[key];
186
+ if (v !== undefined && v !== null && typeof v !== 'string') {
187
+ errors.push({
188
+ path: `${path}.${key}`,
189
+ message: `${path}.${key} must be a string or null when present`,
190
+ });
191
+ }
192
+ }
193
+ }
194
+ function validateSpecRef(value, path, errors) {
195
+ if (!isPlainObject(value)) {
196
+ errors.push({ path, message: `${path} must be an object` });
197
+ return;
198
+ }
199
+ for (const key of Object.keys(value)) {
200
+ if (!SPEC_KEYS.has(key)) {
201
+ errors.push({ path: `${path}.${key}`, message: `unknown field "${key}"` });
202
+ }
203
+ }
204
+ if (typeof value.name !== 'string') {
205
+ errors.push({ path: `${path}.name`, message: `${path}.name must be a string` });
206
+ }
207
+ else if (!SPEC_NAME_PATTERN.test(value.name)) {
208
+ errors.push({
209
+ path: `${path}.name`,
210
+ message: `${path}.name must match \`family/spec-name\` kebab-case`,
211
+ });
212
+ }
213
+ if (value.args !== undefined && !isPlainObject(value.args)) {
214
+ errors.push({ path: `${path}.args`, message: `${path}.args must be an object when present` });
215
+ }
216
+ }
217
+ //# sourceMappingURL=fixture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixture.js","sourceRoot":"","sources":["../../src/eval/fixture.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export type { PartialWorkspace, SkillName, SuccessSpecReference, TaskFixture, ValidationError, ValidationResult, } from './fixture.js';
2
+ export { SKILL_NAMES, applyWorkspaceOverrides, parseFixture, validateFixture } from './fixture.js';
3
+ export type { RunRecord } from './run-record.js';
4
+ export type { RunFixtureInput, RunFixturesDeps, RunFixturesOptions, } from './runner.js';
5
+ export { defaultSystemPromptBuilder, runFixture, runFixtures } from './runner.js';
6
+ export type { RunSnapshot, SpecFn, SpecRegistry, SpecResult } from './spec-framework.js';
7
+ export { createSpecRegistry, evaluateSpec } from './spec-framework.js';
8
+ export type { AggregateStat, AggregatedMetrics, CollectMetricsInput, MetricsTable, TrialMetrics, } from './metric-collector.js';
9
+ export { aggregateTrials, collectMetrics, extractTrialMetrics } from './metric-collector.js';
10
+ export type { CompareMetricsInput, ComparisonFixture, ComparisonLabel, ComparisonMetricName, ComparisonReport, ComparisonRow, Polarity, } from './comparison-report.js';
11
+ export { POLARITY, compareMetrics, renderJson, renderMarkdown } from './comparison-report.js';
12
+ export { CUSTOM_SPEC_NAMES, SPEC_FINAL_RULES_EXCLUDES_LITERAL, SPEC_FINAL_RULES_INCLUDES_LITERAL, SPEC_FINAL_RUNTIME_RUN_SUMMARY_OK, SPEC_GAME_RULES_SIMULATOR_ACCEPTS_POSITIVE_AND_REJECTS_CHEAT, SPEC_PYRIC_AGENTS_LINT_CLEAN_AND_RULE_REJECTS_CHEAT, SPEC_REPORT_MENTIONS_ALL_OF, SPEC_REPORT_MENTIONS_AT_LEAST_ONE_OF, SPEC_TRACE_CONTAINS_TOOL_CALL_BY_NAME, STARTER_SPEC_NAMES, finalRulesExcludesLiteral, finalRulesIncludesLiteral, finalRuntimeRunSummaryOk, gameRulesSimulatorAcceptsPositiveAndRejectsCheat, pyricAgentsLintCleanAndRuleRejectsCheat, registerAllSpecs, registerCustomSpecs, registerStarterSpecs, reportMentionsAllOf, reportMentionsAtLeastOneOf, traceContainsToolCallByName, } from './spec-helpers.js';
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/eval/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,gBAAgB,EAChB,SAAS,EACT,oBAAoB,EACpB,WAAW,EACX,eAAe,EACf,gBAAgB,GACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,WAAW,EAAE,uBAAuB,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEnG,YAAY,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,YAAY,EACV,eAAe,EACf,eAAe,EACf,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,0BAA0B,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAElF,YAAY,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACzF,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEvE,YAAY,EACV,aAAa,EACb,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,YAAY,GACb,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE7F,YAAY,EACV,mBAAmB,EACnB,iBAAiB,EACjB,eAAe,EACf,oBAAoB,EACpB,gBAAgB,EAChB,aAAa,EACb,QAAQ,GACT,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE9F,OAAO,EACL,iBAAiB,EACjB,iCAAiC,EACjC,iCAAiC,EACjC,iCAAiC,EACjC,4DAA4D,EAC5D,mDAAmD,EACnD,2BAA2B,EAC3B,oCAAoC,EACpC,qCAAqC,EACrC,kBAAkB,EAClB,yBAAyB,EACzB,yBAAyB,EACzB,wBAAwB,EACxB,gDAAgD,EAChD,uCAAuC,EACvC,gBAAgB,EAChB,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,0BAA0B,EAC1B,2BAA2B,GAC5B,MAAM,mBAAmB,CAAC"}