@post-print/agent-test 0.3.12 → 1.0.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 (97) hide show
  1. package/README.md +18 -4
  2. package/dist/cli.d.ts +9 -0
  3. package/dist/cli.d.ts.map +1 -1
  4. package/dist/cli.js +53 -3
  5. package/dist/cli.js.map +1 -1
  6. package/dist/command-allowlist.d.ts +9 -0
  7. package/dist/command-allowlist.d.ts.map +1 -0
  8. package/dist/command-allowlist.js +29 -0
  9. package/dist/command-allowlist.js.map +1 -0
  10. package/dist/compare-scenario.d.ts +14 -18
  11. package/dist/compare-scenario.d.ts.map +1 -1
  12. package/dist/compare-scenario.js +146 -257
  13. package/dist/compare-scenario.js.map +1 -1
  14. package/dist/debug-bundle.d.ts.map +1 -1
  15. package/dist/debug-bundle.js +2 -0
  16. package/dist/debug-bundle.js.map +1 -1
  17. package/dist/expect.d.ts +3 -0
  18. package/dist/expect.d.ts.map +1 -1
  19. package/dist/expect.js +36 -0
  20. package/dist/expect.js.map +1 -1
  21. package/dist/html-report.d.ts +1 -0
  22. package/dist/html-report.d.ts.map +1 -1
  23. package/dist/html-report.js +194 -38
  24. package/dist/html-report.js.map +1 -1
  25. package/dist/index.d.ts +8 -3
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +7 -2
  28. package/dist/index.js.map +1 -1
  29. package/dist/live-isolation.d.ts +8 -1
  30. package/dist/live-isolation.d.ts.map +1 -1
  31. package/dist/live-isolation.js +96 -8
  32. package/dist/live-isolation.js.map +1 -1
  33. package/dist/record-trace.d.ts +2 -2
  34. package/dist/record-trace.d.ts.map +1 -1
  35. package/dist/record-trace.js +6 -4
  36. package/dist/record-trace.js.map +1 -1
  37. package/dist/run-suite.d.ts +9 -1
  38. package/dist/run-suite.d.ts.map +1 -1
  39. package/dist/run-suite.js +190 -58
  40. package/dist/run-suite.js.map +1 -1
  41. package/dist/scenario-story.d.ts +4 -3
  42. package/dist/scenario-story.d.ts.map +1 -1
  43. package/dist/scenario-story.js +54 -71
  44. package/dist/scenario-story.js.map +1 -1
  45. package/dist/scenario-usage.d.ts.map +1 -1
  46. package/dist/scenario-usage.js +2 -3
  47. package/dist/scenario-usage.js.map +1 -1
  48. package/dist/types.d.ts +38 -22
  49. package/dist/types.d.ts.map +1 -1
  50. package/dist/validate-suite.d.ts.map +1 -1
  51. package/dist/validate-suite.js +65 -38
  52. package/dist/validate-suite.js.map +1 -1
  53. package/dist/viewer/catalog.d.ts +53 -0
  54. package/dist/viewer/catalog.d.ts.map +1 -0
  55. package/dist/viewer/catalog.js +116 -0
  56. package/dist/viewer/catalog.js.map +1 -0
  57. package/dist/viewer/cli.d.ts +17 -0
  58. package/dist/viewer/cli.d.ts.map +1 -0
  59. package/dist/viewer/cli.js +38 -0
  60. package/dist/viewer/cli.js.map +1 -0
  61. package/dist/viewer/compare-metrics.d.ts +30 -0
  62. package/dist/viewer/compare-metrics.d.ts.map +1 -0
  63. package/dist/viewer/compare-metrics.js +102 -0
  64. package/dist/viewer/compare-metrics.js.map +1 -0
  65. package/dist/viewer/context-files.d.ts +8 -0
  66. package/dist/viewer/context-files.d.ts.map +1 -0
  67. package/dist/viewer/context-files.js +56 -0
  68. package/dist/viewer/context-files.js.map +1 -0
  69. package/dist/viewer/emit.d.ts +7 -0
  70. package/dist/viewer/emit.d.ts.map +1 -0
  71. package/dist/viewer/emit.js +25 -0
  72. package/dist/viewer/emit.js.map +1 -0
  73. package/dist/viewer/events.d.ts +75 -0
  74. package/dist/viewer/events.d.ts.map +1 -0
  75. package/dist/viewer/events.js +47 -0
  76. package/dist/viewer/events.js.map +1 -0
  77. package/dist/viewer/live-runner.d.ts +20 -0
  78. package/dist/viewer/live-runner.d.ts.map +1 -0
  79. package/dist/viewer/live-runner.js +102 -0
  80. package/dist/viewer/live-runner.js.map +1 -0
  81. package/dist/viewer/page.d.ts +3 -0
  82. package/dist/viewer/page.d.ts.map +1 -0
  83. package/dist/viewer/page.js +1664 -0
  84. package/dist/viewer/page.js.map +1 -0
  85. package/dist/viewer/run-controller.d.ts +27 -0
  86. package/dist/viewer/run-controller.d.ts.map +1 -0
  87. package/dist/viewer/run-controller.js +154 -0
  88. package/dist/viewer/run-controller.js.map +1 -0
  89. package/dist/viewer/server.d.ts +16 -0
  90. package/dist/viewer/server.d.ts.map +1 -0
  91. package/dist/viewer/server.js +154 -0
  92. package/dist/viewer/server.js.map +1 -0
  93. package/dist/worker-pool.d.ts +8 -0
  94. package/dist/worker-pool.d.ts.map +1 -0
  95. package/dist/worker-pool.js +26 -0
  96. package/dist/worker-pool.js.map +1 -0
  97. package/package.json +7 -5
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/viewer/cli.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAgB3C,yEAAyE;AACzE,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAAyB;IAC7D,MAAM,OAAO,GAAG,MAAM,iBAAiB,CAAC;QACvC,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,UAAU,EAAE,OAAO,CAAC,UAAU;KAC9B,CAAC,CAAC;IACH,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACpB,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAClF,CAAC;IACD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,sBAAsB,CAAC;IAC1D,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC;QACjC,OAAO;QACP,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,cAAc,EAAE,OAAO,CAAC,cAAc;QACtC,IAAI,EAAE,OAAO,CAAC,UAAU;QACxB,OAAO;KACP,CAAC,CAAC;IACH,OAAO,CAAC,GAAG,CAAC,iBAAiB,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;IAC3C,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,oCAAoC,CAAC,CAAC;IAC5D,MAAM,IAAI,OAAO,CAAO,CAAC,YAAY,EAAE,EAAE;QACxC,MAAM,IAAI,GAAG,GAAS,EAAE;YACvB,KAAK,MAAM,CAAC,KAAK,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,YAAY,EAAE,CAAC,CAAC;QACnD,CAAC,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAC7B,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IACH,OAAO,CAAC,CAAC;AACV,CAAC"}
@@ -0,0 +1,30 @@
1
+ import type { CompareGateResult } from "../types.js";
2
+ export type ViewerCompareMetricId = "turns" | "tokens" | "tools" | "durationMs";
3
+ export interface ViewerArmMetricRow {
4
+ id: string;
5
+ label: string;
6
+ turns?: number;
7
+ tokens?: number;
8
+ tools?: number;
9
+ durationMs?: number;
10
+ }
11
+ export interface ViewerMetricSummary {
12
+ id: ViewerCompareMetricId;
13
+ label: string;
14
+ winnerIds: string[];
15
+ line: string;
16
+ }
17
+ export interface ViewerGateSummary {
18
+ metric: string;
19
+ passed: boolean;
20
+ line: string;
21
+ }
22
+ export interface ViewerCompareSummary {
23
+ metrics: ViewerMetricSummary[];
24
+ gates: ViewerGateSummary[];
25
+ }
26
+ /** Lower turns, tokens, tool counts, and duration win. Named pairs do not pick one overall winner. */
27
+ export declare function summarizeViewerCompare(arms: ViewerArmMetricRow[], gates?: CompareGateResult[]): ViewerCompareSummary;
28
+ /** Markup for the winners list under a compare cell or report. */
29
+ export declare function renderViewerCompareBoard(summary: ViewerCompareSummary): string;
30
+ //# sourceMappingURL=compare-metrics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compare-metrics.d.ts","sourceRoot":"","sources":["../../src/viewer/compare-metrics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD,MAAM,MAAM,qBAAqB,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,YAAY,CAAC;AAEhF,MAAM,WAAW,kBAAkB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IACnC,EAAE,EAAE,qBAAqB,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,iBAAiB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,oBAAoB;IACpC,OAAO,EAAE,mBAAmB,EAAE,CAAC;IAC/B,KAAK,EAAE,iBAAiB,EAAE,CAAC;CAC3B;AASD,sGAAsG;AACtG,wBAAgB,sBAAsB,CACrC,IAAI,EAAE,kBAAkB,EAAE,EAC1B,KAAK,GAAE,iBAAiB,EAAO,GAC7B,oBAAoB,CAStB;AAED,kEAAkE;AAClE,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,oBAAoB,GAAG,MAAM,CAe9E"}
@@ -0,0 +1,102 @@
1
+ const METRICS = [
2
+ { id: "turns", label: "Turns" },
3
+ { id: "tokens", label: "Tokens" },
4
+ { id: "tools", label: "Tools" },
5
+ { id: "durationMs", label: "Duration" },
6
+ ];
7
+ /** Lower turns, tokens, tool counts, and duration win. Named pairs do not pick one overall winner. */
8
+ export function summarizeViewerCompare(arms, gates = []) {
9
+ return {
10
+ metrics: METRICS.map((metric) => summarizeMetric(arms, metric.id, metric.label)),
11
+ gates: gates.map((gate) => ({
12
+ metric: gate.gate.metric,
13
+ passed: gate.passed,
14
+ line: `${gate.message}. ${gate.passed ? "Pass." : "Fail."}`,
15
+ })),
16
+ };
17
+ }
18
+ /** Markup for the winners list under a compare cell or report. */
19
+ export function renderViewerCompareBoard(summary) {
20
+ if (summary.metrics.length === 0 && summary.gates.length === 0) {
21
+ return "";
22
+ }
23
+ const lines = [
24
+ ...summary.metrics.map((metric) => `<li>${escapeHtml(metric.line)}</li>`),
25
+ ...summary.gates.map((gate) => {
26
+ const status = gate.passed ? "compare-winner-pass" : "compare-winner-fail";
27
+ return `<li class="${status}">${escapeHtml(gate.line)}</li>`;
28
+ }),
29
+ ];
30
+ return `<section class="compare-winners">
31
+ <h3>Winners</h3>
32
+ <ul>${lines.join("")}</ul>
33
+ </section>`;
34
+ }
35
+ function summarizeMetric(arms, id, label) {
36
+ const values = arms.map((arm) => arm[id]);
37
+ const numeric = values.filter((value) => typeof value === "number");
38
+ if (numeric.length < 2) {
39
+ return { id, label, winnerIds: [], line: `${label}: n/a.` };
40
+ }
41
+ const lowest = Math.min(...numeric);
42
+ const winners = arms.filter((arm) => arm[id] === lowest);
43
+ const shown = values
44
+ .map((value) => (typeof value === "number" ? String(value) : "n/a"))
45
+ .join(" vs ");
46
+ if (winners.length === 0) {
47
+ return { id, label, winnerIds: [], line: `${label}: n/a.` };
48
+ }
49
+ if (winners.length > 1) {
50
+ const names = joinLabels(winners.map((arm) => arm.label));
51
+ if (arms.length === 2) {
52
+ return {
53
+ id,
54
+ label,
55
+ winnerIds: winners.map((arm) => arm.id),
56
+ line: `${label}: tie (${shown}).`,
57
+ };
58
+ }
59
+ return {
60
+ id,
61
+ label,
62
+ winnerIds: winners.map((arm) => arm.id),
63
+ line: `${label}: lowest is a tie between ${names} (${shown}).`,
64
+ };
65
+ }
66
+ const winner = winners[0];
67
+ if (!winner) {
68
+ return { id, label, winnerIds: [], line: `${label}: n/a.` };
69
+ }
70
+ if (arms.length === 2) {
71
+ return {
72
+ id,
73
+ label,
74
+ winnerIds: [winner.id],
75
+ line: `${label}: ${winner.label} wins (${shown}).`,
76
+ };
77
+ }
78
+ return {
79
+ id,
80
+ label,
81
+ winnerIds: [winner.id],
82
+ line: `${label}: lowest is ${winner.label} (${shown}).`,
83
+ };
84
+ }
85
+ function joinLabels(labels) {
86
+ if (labels.length <= 1) {
87
+ return labels[0] ?? "";
88
+ }
89
+ if (labels.length === 2) {
90
+ return `${labels[0]} and ${labels[1]}`;
91
+ }
92
+ return `${labels.slice(0, -1).join(", ")}, and ${labels[labels.length - 1]}`;
93
+ }
94
+ function escapeHtml(value) {
95
+ return value
96
+ .replaceAll("&", "&amp;")
97
+ .replaceAll("<", "&lt;")
98
+ .replaceAll(">", "&gt;")
99
+ .replaceAll('"', "&quot;")
100
+ .replaceAll("'", "&#39;");
101
+ }
102
+ //# sourceMappingURL=compare-metrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compare-metrics.js","sourceRoot":"","sources":["../../src/viewer/compare-metrics.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { ViewerContextFile, ViewerContextReason } from "./events.js";
2
+ export declare const VIEWER_CONTEXT_FILE_CHARS = 4000;
3
+ export declare function truncateViewerText(text: string, max: number): string;
4
+ export declare function classifyContextReason(path: string, contextSources?: string[]): ViewerContextReason;
5
+ export declare function contextWhy(path: string, reason: ViewerContextReason): string;
6
+ /** Split a loaded preamble into path and text pairs for the viewer. */
7
+ export declare function viewerContextFiles(preamble: string, sources: string[], contextSources?: string[]): ViewerContextFile[];
8
+ //# sourceMappingURL=context-files.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-files.d.ts","sourceRoot":"","sources":["../../src/viewer/context-files.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAE1E,eAAO,MAAM,yBAAyB,OAAQ,CAAC;AAE/C,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAKpE;AAED,wBAAgB,qBAAqB,CACpC,IAAI,EAAE,MAAM,EACZ,cAAc,GAAE,MAAM,EAAO,GAC3B,mBAAmB,CAarB;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,mBAAmB,GAAG,MAAM,CAQ5E;AAYD,uEAAuE;AACvE,wBAAgB,kBAAkB,CACjC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EAAE,EACjB,cAAc,GAAE,MAAM,EAAO,GAC3B,iBAAiB,EAAE,CAgBrB"}
@@ -0,0 +1,56 @@
1
+ export const VIEWER_CONTEXT_FILE_CHARS = 4_000;
2
+ export function truncateViewerText(text, max) {
3
+ if (text.length <= max) {
4
+ return text;
5
+ }
6
+ return `${text.slice(0, max)}\n… (truncated)`;
7
+ }
8
+ export function classifyContextReason(path, contextSources = []) {
9
+ const needle = path.replace(/^\.\//, "");
10
+ if (contextSources.some((source) => source.replace(/^\.\//, "") === needle)) {
11
+ return "contextSources";
12
+ }
13
+ if (/(?:^|\/)SKILL\.md$/.test(needle) ||
14
+ /(?:^|\/)\.agents\/skills\//.test(needle) ||
15
+ /(?:^|\/)\.claude\/skills\//.test(needle)) {
16
+ return "skills";
17
+ }
18
+ return "profile";
19
+ }
20
+ export function contextWhy(path, reason) {
21
+ if (reason === "contextSources") {
22
+ return `The scenario lists ${path} in contextSources.`;
23
+ }
24
+ if (reason === "skills") {
25
+ return `The scenario skills setting loaded ${path}.`;
26
+ }
27
+ return `The host profile loaded ${path}.`;
28
+ }
29
+ function contextFile(path, text, contextSources) {
30
+ const reason = classifyContextReason(path, contextSources);
31
+ return {
32
+ path,
33
+ text: truncateViewerText(text, VIEWER_CONTEXT_FILE_CHARS),
34
+ reason,
35
+ why: contextWhy(path, reason),
36
+ };
37
+ }
38
+ /** Split a loaded preamble into path and text pairs for the viewer. */
39
+ export function viewerContextFiles(preamble, sources, contextSources = []) {
40
+ const chunks = preamble.split("\n\n---\n\n");
41
+ const files = [];
42
+ for (const chunk of chunks) {
43
+ const trimmed = chunk.trim();
44
+ if (!trimmed) {
45
+ continue;
46
+ }
47
+ const match = trimmed.match(/^<!-- ([^\n]+) -->\n?([\s\S]*)$/);
48
+ if (match?.[1]) {
49
+ files.push(contextFile(match[1].trim(), match[2].trimEnd(), contextSources));
50
+ continue;
51
+ }
52
+ files.push(contextFile(sources[files.length] ?? "context", trimmed, contextSources));
53
+ }
54
+ return files;
55
+ }
56
+ //# sourceMappingURL=context-files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-files.js","sourceRoot":"","sources":["../../src/viewer/context-files.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,yBAAyB,GAAG,KAAK,CAAC;AAE/C,MAAM,UAAU,kBAAkB,CAAC,IAAY,EAAE,GAAW;IAC3D,IAAI,IAAI,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;QACxB,OAAO,IAAI,CAAC;IACb,CAAC;IACD,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,iBAAiB,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,qBAAqB,CACpC,IAAY,EACZ,cAAc,GAAa,EAAE;IAE7B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IACzC,IAAI,cAAc,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,KAAK,MAAM,CAAC,EAAE,CAAC;QAC7E,OAAO,gBAAgB,CAAC;IACzB,CAAC;IACD,IACC,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC;QACjC,4BAA4B,CAAC,IAAI,CAAC,MAAM,CAAC;QACzC,4BAA4B,CAAC,IAAI,CAAC,MAAM,CAAC,EACxC,CAAC;QACF,OAAO,QAAQ,CAAC;IACjB,CAAC;IACD,OAAO,SAAS,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,MAA2B;IACnE,IAAI,MAAM,KAAK,gBAAgB,EAAE,CAAC;QACjC,OAAO,sBAAsB,IAAI,qBAAqB,CAAC;IACxD,CAAC;IACD,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;QACzB,OAAO,sCAAsC,IAAI,GAAG,CAAC;IACtD,CAAC;IACD,OAAO,2BAA2B,IAAI,GAAG,CAAC;AAC3C,CAAC;AAED,SAAS,WAAW,CAAC,IAAY,EAAE,IAAY,EAAE,cAAwB;IACxE,MAAM,MAAM,GAAG,qBAAqB,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;IAC3D,OAAO;QACN,IAAI;QACJ,IAAI,EAAE,kBAAkB,CAAC,IAAI,EAAE,yBAAyB,CAAC;QACzD,MAAM;QACN,GAAG,EAAE,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC;KAC7B,CAAC;AACH,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,kBAAkB,CACjC,QAAgB,EAChB,OAAiB,EACjB,cAAc,GAAa,EAAE;IAE7B,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAwB,EAAE,CAAC;IACtC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;QAC7B,IAAI,CAAC,OAAO,EAAE,CAAC;YACd,SAAS;QACV,CAAC;QACD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC;QAC/D,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAChB,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,EAAE,cAAc,CAAC,CAAC,CAAC;YAC7E,SAAS;QACV,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,SAAS,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC;IACtF,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { type ViewerEvent } from "./events.js";
2
+ export declare const VIEWER_EVENTS_FD = 3;
3
+ export declare const VIEWER_EVENTS_FD_ENV = "AGENT_TEST_EVENTS_FD";
4
+ export declare function viewerEventsFd(env?: NodeJS.ProcessEnv): number | undefined;
5
+ /** Write one NDJSON event to the parent pipe. No-op when the fd is unset. */
6
+ export declare function emitViewerEvent(event: ViewerEvent, fd?: number | undefined): void;
7
+ //# sourceMappingURL=emit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../../src/viewer/emit.ts"],"names":[],"mappings":"AAEA,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAElE,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAClC,eAAO,MAAM,oBAAoB,yBAAyB,CAAC;AAE3D,wBAAgB,cAAc,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,GAAG,SAAS,CAOvF;AAED,6EAA6E;AAC7E,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,qBAAmB,GAAG,IAAI,CAS/E"}
@@ -0,0 +1,25 @@
1
+ import { writeSync } from "node:fs";
2
+ import { encodeViewerEvent } from "./events.js";
3
+ export const VIEWER_EVENTS_FD = 3;
4
+ export const VIEWER_EVENTS_FD_ENV = "AGENT_TEST_EVENTS_FD";
5
+ export function viewerEventsFd(env = process.env) {
6
+ const raw = env[VIEWER_EVENTS_FD_ENV]?.trim();
7
+ if (!raw) {
8
+ return undefined;
9
+ }
10
+ const fd = Number(raw);
11
+ return Number.isInteger(fd) && fd >= 3 ? fd : undefined;
12
+ }
13
+ /** Write one NDJSON event to the parent pipe. No-op when the fd is unset. */
14
+ export function emitViewerEvent(event, fd = viewerEventsFd()) {
15
+ if (fd === undefined) {
16
+ return;
17
+ }
18
+ try {
19
+ writeSync(fd, `${encodeViewerEvent(event)}\n`);
20
+ }
21
+ catch {
22
+ // Parent closed the pipe.
23
+ }
24
+ }
25
+ //# sourceMappingURL=emit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emit.js","sourceRoot":"","sources":["../../src/viewer/emit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEpC,OAAO,EAAE,iBAAiB,EAAoB,MAAM,aAAa,CAAC;AAElE,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAClC,MAAM,CAAC,MAAM,oBAAoB,GAAG,sBAAsB,CAAC;AAE3D,MAAM,UAAU,cAAc,CAAC,GAAG,GAAsB,OAAO,CAAC,GAAG;IAClE,MAAM,GAAG,GAAG,GAAG,CAAC,oBAAoB,CAAC,EAAE,IAAI,EAAE,CAAC;IAC9C,IAAI,CAAC,GAAG,EAAE,CAAC;QACV,OAAO,SAAS,CAAC;IAClB,CAAC;IACD,MAAM,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IACvB,OAAO,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AACzD,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,eAAe,CAAC,KAAkB,EAAE,EAAE,GAAG,cAAc,EAAE;IACxE,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;QACtB,OAAO;IACR,CAAC;IACD,IAAI,CAAC;QACJ,SAAS,CAAC,EAAE,EAAE,GAAG,iBAAiB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACR,0BAA0B;IAC3B,CAAC;AACF,CAAC"}
@@ -0,0 +1,75 @@
1
+ export interface ViewerEventEnvelope {
2
+ suite: string;
3
+ scenario: string;
4
+ host: string;
5
+ arm?: string;
6
+ }
7
+ export interface ViewerFailureEvent {
8
+ matcher: string;
9
+ message: string;
10
+ }
11
+ export interface ViewerJudgeVerdictEvent {
12
+ id: string;
13
+ question: string;
14
+ pass: boolean;
15
+ rationale: string;
16
+ }
17
+ export type ViewerContextReason = "contextSources" | "profile" | "skills";
18
+ export interface ViewerContextFile {
19
+ path: string;
20
+ text: string;
21
+ reason: ViewerContextReason;
22
+ why: string;
23
+ }
24
+ export type ViewerEvent = {
25
+ type: "run_started";
26
+ runId: string;
27
+ } | {
28
+ type: "run_finished";
29
+ runId: string;
30
+ passed: number;
31
+ failed: number;
32
+ skipped: number;
33
+ } | ({
34
+ type: "cell_started";
35
+ } & ViewerEventEnvelope) | ({
36
+ type: "status";
37
+ text: string;
38
+ } & ViewerEventEnvelope) | ({
39
+ type: "prompt";
40
+ text: string;
41
+ } & ViewerEventEnvelope) | ({
42
+ type: "context";
43
+ files: ViewerContextFile[];
44
+ } & ViewerEventEnvelope) | ({
45
+ type: "text";
46
+ text: string;
47
+ } & ViewerEventEnvelope) | ({
48
+ type: "tool";
49
+ name: string;
50
+ args?: Record<string, unknown>;
51
+ } & ViewerEventEnvelope) | ({
52
+ type: "cell_finished";
53
+ passed: boolean;
54
+ skipped?: boolean;
55
+ durationMs: number;
56
+ failures?: ViewerFailureEvent[];
57
+ metrics?: {
58
+ turns?: number;
59
+ tokens?: number;
60
+ tools?: number;
61
+ durationMs?: number;
62
+ passed?: boolean;
63
+ };
64
+ } & ViewerEventEnvelope) | ({
65
+ type: "judge";
66
+ verdicts: ViewerJudgeVerdictEvent[];
67
+ } & ViewerEventEnvelope) | ({
68
+ type: "error";
69
+ message: string;
70
+ } & Partial<ViewerEventEnvelope>);
71
+ /** One NDJSON object with no trailing newline. */
72
+ export declare function encodeViewerEvent(event: ViewerEvent): string;
73
+ export declare function parseViewerEvent(line: string): ViewerEvent | undefined;
74
+ export declare function parseViewerEventLines(chunk: string): ViewerEvent[];
75
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/viewer/events.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ const EVENT_TYPES = new Set([
2
+ "run_started",
3
+ "run_finished",
4
+ "cell_started",
5
+ "status",
6
+ "prompt",
7
+ "context",
8
+ "text",
9
+ "tool",
10
+ "cell_finished",
11
+ "judge",
12
+ "error",
13
+ ]);
14
+ /** One NDJSON object with no trailing newline. */
15
+ export function encodeViewerEvent(event) {
16
+ return JSON.stringify(event);
17
+ }
18
+ export function parseViewerEvent(line) {
19
+ const trimmed = line.trim();
20
+ if (!trimmed) {
21
+ return undefined;
22
+ }
23
+ try {
24
+ const parsed = JSON.parse(trimmed);
25
+ if (!isViewerEvent(parsed)) {
26
+ return undefined;
27
+ }
28
+ return parsed;
29
+ }
30
+ catch {
31
+ return undefined;
32
+ }
33
+ }
34
+ export function parseViewerEventLines(chunk) {
35
+ return chunk.split("\n").flatMap((line) => {
36
+ const event = parseViewerEvent(line);
37
+ return event ? [event] : [];
38
+ });
39
+ }
40
+ function isViewerEvent(value) {
41
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
42
+ return false;
43
+ }
44
+ const type = value.type;
45
+ return typeof type === "string" && EVENT_TYPES.has(type);
46
+ }
47
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/viewer/events.ts"],"names":[],"mappings":"AAsDA,MAAM,WAAW,GAAG,IAAI,GAAG,CAAsB;IAChD,aAAa;IACb,cAAc;IACd,cAAc;IACd,QAAQ;IACR,QAAQ;IACR,SAAS;IACT,MAAM;IACN,MAAM;IACN,eAAe;IACf,OAAO;IACP,OAAO;CACP,CAAC,CAAC;AAEH,kDAAkD;AAClD,MAAM,UAAU,iBAAiB,CAAC,KAAkB;IACnD,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,IAAI,CAAC,OAAO,EAAE,CAAC;QACd,OAAO,SAAS,CAAC;IAClB,CAAC;IACD,IAAI,CAAC;QACJ,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC5C,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;YAC5B,OAAO,SAAS,CAAC;QAClB,CAAC;QACD,OAAO,MAAM,CAAC;IACf,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,SAAS,CAAC;IAClB,CAAC;AACF,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,KAAa;IAClD,OAAO,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QACzC,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;QACrC,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7B,CAAC,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACpC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzE,OAAO,KAAK,CAAC;IACd,CAAC;IACD,MAAM,IAAI,GAAI,KAA4B,CAAC,IAAI,CAAC;IAChD,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,WAAW,CAAC,GAAG,CAAC,IAA2B,CAAC,CAAC;AACjF,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { HostAuthMode } from "@post-print/agent-harness";
2
+ import { type SpawnLiveScenarioOptions, type SpawnLiveScenarioResult } from "../live-isolation.js";
3
+ import type { ViewerJob } from "./catalog.js";
4
+ import type { ViewerRunner } from "./run-controller.js";
5
+ export interface LiveViewerRunnerOptions {
6
+ cwd: string;
7
+ suitesDir: string;
8
+ rubricsDir?: string;
9
+ judge?: boolean;
10
+ timeoutMs?: number;
11
+ authMode?: HostAuthMode;
12
+ adapterModules?: string[];
13
+ /** Override host auth probe. Tests inject this. */
14
+ missingAuth?: (host: ViewerJob["host"]) => string | undefined;
15
+ /** Override isolated spawn. Tests inject this. */
16
+ spawnLiveScenario?: (options: SpawnLiveScenarioOptions) => Promise<SpawnLiveScenarioResult>;
17
+ }
18
+ /** Spawn one isolated child per viewer job. Forward NDJSON events to the UI. */
19
+ export declare function createLiveViewerRunner(options: LiveViewerRunnerOptions): ViewerRunner;
20
+ //# sourceMappingURL=live-runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live-runner.d.ts","sourceRoot":"","sources":["../../src/viewer/live-runner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAG9D,OAAO,EAEN,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,EAG5B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,MAAM,WAAW,uBAAuB;IACvC,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,mDAAmD;IACnD,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,KAAK,MAAM,GAAG,SAAS,CAAC;IAC9D,kDAAkD;IAClD,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,OAAO,CAAC,uBAAuB,CAAC,CAAC;CAC5F;AAWD,gFAAgF;AAChF,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,uBAAuB,GAAG,YAAY,CAsFrF"}
@@ -0,0 +1,102 @@
1
+ import { missingAgentAuth } from "../doctor.js";
2
+ import { killActiveLiveChildren, spawnLiveScenario, subprocessFailureMessage, } from "../live-isolation.js";
3
+ import { createLiveStagingSessionId } from "../record-trace.js";
4
+ function envelope(job) {
5
+ return {
6
+ suite: job.suite,
7
+ scenario: job.scenario,
8
+ host: job.host,
9
+ ...(job.arm ? { arm: job.arm } : {}),
10
+ };
11
+ }
12
+ /** Spawn one isolated child per viewer job. Forward NDJSON events to the UI. */
13
+ export function createLiveViewerRunner(options) {
14
+ return {
15
+ async runJob(job, emit, signal) {
16
+ const cell = envelope(job);
17
+ emit({ type: "cell_started", ...cell });
18
+ emit({ type: "status", text: "Starting isolated child.", ...cell });
19
+ const missing = (options.missingAuth ?? missingAgentAuth)(job.host);
20
+ if (missing) {
21
+ emit({ type: "error", message: missing, ...cell });
22
+ emit({
23
+ type: "cell_finished",
24
+ ...cell,
25
+ passed: false,
26
+ durationMs: 0,
27
+ failures: [{ matcher: "liveScenario", message: missing }],
28
+ });
29
+ return;
30
+ }
31
+ if (signal.aborted) {
32
+ return;
33
+ }
34
+ const onAbort = () => {
35
+ killActiveLiveChildren();
36
+ };
37
+ signal.addEventListener("abort", onAbort, { once: true });
38
+ const spawn = options.spawnLiveScenario ?? spawnLiveScenario;
39
+ let finished = false;
40
+ try {
41
+ const result = await spawn({
42
+ cwd: options.cwd,
43
+ suiteName: job.suite,
44
+ scenarioName: job.scenario,
45
+ suitesDir: options.suitesDir,
46
+ rubricsDir: options.rubricsDir,
47
+ suiteFilter: job.suite,
48
+ host: job.host,
49
+ compareArm: job.arm,
50
+ stagingSessionId: createLiveStagingSessionId(),
51
+ judge: options.judge,
52
+ timeoutMs: options.timeoutMs,
53
+ noTimeout: options.timeoutMs === 0,
54
+ authMode: options.authMode,
55
+ adapterModules: options.adapterModules,
56
+ signal,
57
+ onViewerEvent: (event) => {
58
+ if (event.type === "cell_finished") {
59
+ finished = true;
60
+ }
61
+ if (signal.aborted) {
62
+ return;
63
+ }
64
+ emit(event);
65
+ },
66
+ });
67
+ if (signal.aborted) {
68
+ return;
69
+ }
70
+ if (!finished && result.exitCode !== 0) {
71
+ const message = subprocessFailureMessage(result.exitCode, result.stderr);
72
+ emit({ type: "error", message, ...cell });
73
+ emit({
74
+ type: "cell_finished",
75
+ ...cell,
76
+ passed: false,
77
+ durationMs: 0,
78
+ failures: [{ matcher: "liveScenario", message }],
79
+ });
80
+ }
81
+ }
82
+ catch (error) {
83
+ if (signal.aborted) {
84
+ return;
85
+ }
86
+ const message = error instanceof Error ? error.message : String(error);
87
+ emit({ type: "error", message, ...cell });
88
+ emit({
89
+ type: "cell_finished",
90
+ ...cell,
91
+ passed: false,
92
+ durationMs: 0,
93
+ failures: [{ matcher: "liveScenario", message }],
94
+ });
95
+ }
96
+ finally {
97
+ signal.removeEventListener("abort", onAbort);
98
+ }
99
+ },
100
+ };
101
+ }
102
+ //# sourceMappingURL=live-runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live-runner.js","sourceRoot":"","sources":["../../src/viewer/live-runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ViewerCatalog } from "./catalog.js";
2
+ export declare function renderViewerPage(catalog: ViewerCatalog): string;
3
+ //# sourceMappingURL=page.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page.d.ts","sourceRoot":"","sources":["../../src/viewer/page.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAA6C,MAAM,cAAc,CAAC;AAklD7F,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CAiE/D"}