@post-print/agent-test 0.1.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 (50) hide show
  1. package/README.md +25 -0
  2. package/dist/cli.d.ts +3 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +194 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/discover-suites.d.ts +2 -0
  7. package/dist/discover-suites.d.ts.map +1 -0
  8. package/dist/discover-suites.js +19 -0
  9. package/dist/discover-suites.js.map +1 -0
  10. package/dist/expect.d.ts +35 -0
  11. package/dist/expect.d.ts.map +1 -0
  12. package/dist/expect.js +265 -0
  13. package/dist/expect.js.map +1 -0
  14. package/dist/index.d.ts +7 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +6 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/live-isolation.d.ts +19 -0
  19. package/dist/live-isolation.d.ts.map +1 -0
  20. package/dist/live-isolation.js +69 -0
  21. package/dist/live-isolation.js.map +1 -0
  22. package/dist/load-suite.d.ts +3 -0
  23. package/dist/load-suite.d.ts.map +1 -0
  24. package/dist/load-suite.js +29 -0
  25. package/dist/load-suite.js.map +1 -0
  26. package/dist/preflight.d.ts +3 -0
  27. package/dist/preflight.d.ts.map +1 -0
  28. package/dist/preflight.js +17 -0
  29. package/dist/preflight.js.map +1 -0
  30. package/dist/progress.d.ts +10 -0
  31. package/dist/progress.d.ts.map +1 -0
  32. package/dist/progress.js +39 -0
  33. package/dist/progress.js.map +1 -0
  34. package/dist/record-trace.d.ts +27 -0
  35. package/dist/record-trace.d.ts.map +1 -0
  36. package/dist/record-trace.js +97 -0
  37. package/dist/record-trace.js.map +1 -0
  38. package/dist/run-suite.d.ts +40 -0
  39. package/dist/run-suite.d.ts.map +1 -0
  40. package/dist/run-suite.js +344 -0
  41. package/dist/run-suite.js.map +1 -0
  42. package/dist/scenario-seed.d.ts +3 -0
  43. package/dist/scenario-seed.d.ts.map +1 -0
  44. package/dist/scenario-seed.js +38 -0
  45. package/dist/scenario-seed.js.map +1 -0
  46. package/dist/types.d.ts +65 -0
  47. package/dist/types.d.ts.map +1 -0
  48. package/dist/types.js +2 -0
  49. package/dist/types.js.map +1 -0
  50. package/package.json +45 -0
@@ -0,0 +1,69 @@
1
+ import { spawn } from "node:child_process";
2
+ import { resolve } from "node:path";
3
+ const DEFAULT_SCENARIO_SETTLE_MS = 5000;
4
+ /** Child process per live scenario (default) — avoids macOS OOM (exit 137) across council runs. */
5
+ export function liveScenarioIsolationEnabled() {
6
+ return process.env.AGENT_TEST_CHILD !== "1" && process.env.AGENT_TEST_NO_ISOLATE !== "1";
7
+ }
8
+ export function scenarioSettleMs() {
9
+ const raw = process.env.AGENT_TEST_SCENARIO_SETTLE_MS ?? String(DEFAULT_SCENARIO_SETTLE_MS);
10
+ const parsed = Number(raw);
11
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : DEFAULT_SCENARIO_SETTLE_MS;
12
+ }
13
+ function sleep(ms) {
14
+ return new Promise((resolveSleep) => {
15
+ setTimeout(resolveSleep, ms);
16
+ });
17
+ }
18
+ /** Run one live scenario in a fresh bun subprocess; inherit stdio for live progress. */
19
+ export async function spawnLiveScenario(options) {
20
+ const cliPath = process.argv[1] ?? resolve(options.cwd, "node_modules/@post-print/agent-test/dist/cli.js");
21
+ const args = [cliPath, "--live", "--scenario", options.scenarioName];
22
+ if (options.suiteFilter) {
23
+ args.push("--suite", options.suiteFilter);
24
+ }
25
+ if (options.suitesDir !== "agent-suites") {
26
+ args.push("--suites-dir", options.suitesDir);
27
+ }
28
+ if (options.stagingSessionId) {
29
+ args.push("--staging-session-id", options.stagingSessionId);
30
+ }
31
+ if (options.keepRecordings) {
32
+ args.push("--keep-recordings");
33
+ }
34
+ if (options.recordFixtures) {
35
+ args.push("--record-fixtures");
36
+ }
37
+ if (options.worktree === false) {
38
+ args.push("--no-worktree");
39
+ }
40
+ // Isolated child: agent + rubric only; parent runs judge (avoids OOM after heavy council runs).
41
+ args.push("--no-judge");
42
+ const exitCode = await new Promise((resolveExit, reject) => {
43
+ const child = spawn("bun", args, {
44
+ cwd: options.cwd,
45
+ env: { ...process.env, AGENT_TEST_CHILD: "1" },
46
+ stdio: "inherit",
47
+ });
48
+ child.on("error", reject);
49
+ child.on("close", (code, signal) => {
50
+ if (signal === "SIGKILL") {
51
+ resolveExit(137);
52
+ return;
53
+ }
54
+ resolveExit(code ?? 1);
55
+ });
56
+ });
57
+ const settleMs = scenarioSettleMs();
58
+ if (settleMs > 0) {
59
+ await sleep(settleMs);
60
+ }
61
+ return exitCode;
62
+ }
63
+ export function subprocessFailureMessage(exitCode) {
64
+ if (exitCode === 137) {
65
+ return "subprocess killed (137) — macOS OOM; close heavy apps or increase AGENT_TEST_SCENARIO_SETTLE_MS";
66
+ }
67
+ return `live scenario subprocess exited ${exitCode}`;
68
+ }
69
+ //# sourceMappingURL=live-isolation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live-isolation.js","sourceRoot":"","sources":["../src/live-isolation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { AgentSuiteFile } from "./types";
2
+ export declare function loadSuiteFile(path: string): Promise<AgentSuiteFile>;
3
+ //# sourceMappingURL=load-suite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-suite.d.ts","sourceRoot":"","sources":["../src/load-suite.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAiB,cAAc,EAAE,MAAM,SAAS,CAAC;AAE7D,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAOzE"}
@@ -0,0 +1,29 @@
1
+ import { readFile } from "node:fs/promises";
2
+ export async function loadSuiteFile(path) {
3
+ const raw = await readFile(path, "utf8");
4
+ const parsed = JSON.parse(raw);
5
+ if (!isSuiteFile(parsed)) {
6
+ throw new Error(`Invalid suite file: ${path}`);
7
+ }
8
+ return parsed;
9
+ }
10
+ function isScenario(value) {
11
+ if (typeof value !== "object" || value === null) {
12
+ return false;
13
+ }
14
+ const scenario = value;
15
+ return (typeof scenario.name === "string" &&
16
+ typeof scenario.prompt === "string" &&
17
+ typeof scenario.rubric === "object" &&
18
+ scenario.rubric !== null);
19
+ }
20
+ function isSuiteFile(value) {
21
+ if (typeof value !== "object" || value === null) {
22
+ return false;
23
+ }
24
+ const suite = value;
25
+ return (typeof suite.name === "string" &&
26
+ Array.isArray(suite.scenarios) &&
27
+ suite.scenarios.every(isScenario));
28
+ }
29
+ //# sourceMappingURL=load-suite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-suite.js","sourceRoot":"","sources":["../src/load-suite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAI5C,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAY;IAC/C,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACzC,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACxC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,uBAAuB,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC;IACD,OAAO,MAAM,CAAC;AACf,CAAC;AAED,SAAS,UAAU,CAAC,KAAc;IACjC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACjD,OAAO,KAAK,CAAC;IACd,CAAC;IACD,MAAM,QAAQ,GAAG,KAAsB,CAAC;IACxC,OAAO,CACN,OAAO,QAAQ,CAAC,IAAI,KAAK,QAAQ;QACjC,OAAO,QAAQ,CAAC,MAAM,KAAK,QAAQ;QACnC,OAAO,QAAQ,CAAC,MAAM,KAAK,QAAQ;QACnC,QAAQ,CAAC,MAAM,KAAK,IAAI,CACxB,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,KAAc;IAClC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACjD,OAAO,KAAK,CAAC;IACd,CAAC;IACD,MAAM,KAAK,GAAG,KAAuB,CAAC;IACtC,OAAO,CACN,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ;QAC9B,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC;QAC9B,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,UAAU,CAAC,CACjC,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** Fail fast when live dogfood cannot find suite definitions. */
2
+ export declare function assertLiveDogfoodPreflight(repoRoot: string, suitesDir?: string): Promise<void>;
3
+ //# sourceMappingURL=preflight.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preflight.d.ts","sourceRoot":"","sources":["../src/preflight.ts"],"names":[],"mappings":"AAGA,iEAAiE;AACjE,wBAAsB,0BAA0B,CAC/C,QAAQ,EAAE,MAAM,EAChB,SAAS,SAAiB,GACxB,OAAO,CAAC,IAAI,CAAC,CAaf"}
@@ -0,0 +1,17 @@
1
+ import { access } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ /** Fail fast when live dogfood cannot find suite definitions. */
4
+ export async function assertLiveDogfoodPreflight(repoRoot, suitesDir = "agent-suites") {
5
+ const suitesRoot = join(repoRoot, suitesDir);
6
+ try {
7
+ await access(suitesRoot);
8
+ }
9
+ catch {
10
+ throw new Error([
11
+ `Live dogfood requires a suites directory (missing ${suitesDir}).`,
12
+ "Pass --suites-dir <path> or create agent-suites/<suite>/scenarios.json in the repo.",
13
+ "See @post-print/agent-test README § Live dogfood.",
14
+ ].join("\n"));
15
+ }
16
+ }
17
+ //# sourceMappingURL=preflight.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preflight.js","sourceRoot":"","sources":["../src/preflight.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,iEAAiE;AACjE,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC/C,QAAgB,EAChB,SAAS,GAAG,cAAc;IAE1B,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAC7C,IAAI,CAAC;QACJ,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACR,MAAM,IAAI,KAAK,CACd;YACC,qDAAqD,SAAS,IAAI;YAClE,qFAAqF;YACrF,mDAAmD;SACnD,CAAC,IAAI,CAAC,IAAI,CAAC,CACZ,CAAC;IACH,CAAC;AACF,CAAC"}
@@ -0,0 +1,10 @@
1
+ export declare function formatDuration(ms: number): string;
2
+ export declare function logProgress(message: string): void;
3
+ export declare function logPhase(message: string): void;
4
+ /** Log every `intervalMs` while `promise` is pending (live agent runs). */
5
+ export declare function withHeartbeat<T>(promise: Promise<T>, options: {
6
+ label: string;
7
+ intervalMs?: number;
8
+ started?: number;
9
+ }): Promise<T>;
10
+ //# sourceMappingURL=progress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress.d.ts","sourceRoot":"","sources":["../src/progress.ts"],"names":[],"mappings":"AAIA,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAKjD;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAKjD;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAK9C;AAED,2EAA2E;AAC3E,wBAAsB,aAAa,CAAC,CAAC,EACpC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnB,OAAO,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/D,OAAO,CAAC,CAAC,CAAC,CAgBZ"}
@@ -0,0 +1,39 @@
1
+ function enabled() {
2
+ return process.env.AGENT_TEST_QUIET !== "1" && !process.env.VITEST;
3
+ }
4
+ export function formatDuration(ms) {
5
+ if (ms < 1000) {
6
+ return `${Math.round(ms)}ms`;
7
+ }
8
+ return `${(ms / 1000).toFixed(1)}s`;
9
+ }
10
+ export function logProgress(message) {
11
+ if (!enabled()) {
12
+ return;
13
+ }
14
+ console.log(message);
15
+ }
16
+ export function logPhase(message) {
17
+ if (!enabled()) {
18
+ return;
19
+ }
20
+ console.log(` ${message}`);
21
+ }
22
+ /** Log every `intervalMs` while `promise` is pending (live agent runs). */
23
+ export async function withHeartbeat(promise, options) {
24
+ if (!enabled()) {
25
+ return promise;
26
+ }
27
+ const started = options.started ?? performance.now();
28
+ const intervalMs = options.intervalMs ?? 30_000;
29
+ const timer = setInterval(() => {
30
+ logPhase(`${options.label} … ${formatDuration(performance.now() - started)} elapsed`);
31
+ }, intervalMs);
32
+ try {
33
+ return await promise;
34
+ }
35
+ finally {
36
+ clearInterval(timer);
37
+ }
38
+ }
39
+ //# sourceMappingURL=progress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress.js","sourceRoot":"","sources":["../src/progress.ts"],"names":[],"mappings":"AAAA,SAAS,OAAO;IACf,OAAO,OAAO,CAAC,GAAG,CAAC,gBAAgB,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC;AACpE,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,EAAU;IACxC,IAAI,EAAE,GAAG,IAAI,EAAE,CAAC;QACf,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC;IAC9B,CAAC;IACD,OAAO,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,OAAe;IAC1C,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;QAChB,OAAO;IACR,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,OAAe;IACvC,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;QAChB,OAAO;IACR,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,KAAK,OAAO,EAAE,CAAC,CAAC;AAC7B,CAAC;AAED,2EAA2E;AAC3E,MAAM,CAAC,KAAK,UAAU,aAAa,CAClC,OAAmB,EACnB,OAAiE;IAEjE,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;QAChB,OAAO,OAAO,CAAC;IAChB,CAAC;IAED,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,WAAW,CAAC,GAAG,EAAE,CAAC;IACrD,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,MAAM,CAAC;IAChD,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;QAC9B,QAAQ,CAAC,GAAG,OAAO,CAAC,KAAK,MAAM,cAAc,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACvF,CAAC,EAAE,UAAU,CAAC,CAAC;IAEf,IAAI,CAAC;QACJ,OAAO,MAAM,OAAO,CAAC;IACtB,CAAC;YAAS,CAAC;QACV,aAAa,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;AACF,CAAC"}
@@ -0,0 +1,27 @@
1
+ import type { AgentTrace } from "@post-print/agent-harness";
2
+ export declare const LIVE_STAGING_DIR_NAME = "agent-spec";
3
+ export declare function getLiveStagingRoot(): string;
4
+ export declare function getLiveStagingSessionRoot(sessionId: string): string;
5
+ /** Staging JSON path for a live scenario trace (matches recordTrace layout). */
6
+ export declare function getStagingTracePath(stagingSessionId: string, suiteName: string, scenarioName: string): string;
7
+ export declare function createLiveStagingSessionId(): string;
8
+ export type RecordingPathKind = "staging" | "fixture";
9
+ export interface ResolvedRecordingPath {
10
+ path: string;
11
+ kind: RecordingPathKind;
12
+ }
13
+ export interface ResolveRecordingPathOptions {
14
+ repoRoot: string;
15
+ stagingSessionId?: string;
16
+ }
17
+ /** Staging lives under $TMPDIR; use --record-fixtures to overwrite committed replayTrace. */
18
+ export declare function resolveRecordingPath(suiteName: string, scenarioName: string, replayTrace: string | undefined, recordFixtures: boolean, options: ResolveRecordingPathOptions): ResolvedRecordingPath | undefined;
19
+ /** Persist a live trace for replay regression (strip raw SDK payload). */
20
+ export declare function recordTrace(outputPath: string, trace: AgentTrace): Promise<string>;
21
+ /** Load a staged live trace for parent-process judge after isolated child runs. */
22
+ export declare function loadStagingTrace(path: string): Promise<AgentTrace>;
23
+ /** Remove a live staging session directory under $TMPDIR. */
24
+ export declare function cleanupStagingSession(sessionRoot: string): Promise<void>;
25
+ /** Remove legacy in-repo staging dirs from before tmpdir staging (best-effort). */
26
+ export declare function cleanupLegacyRepoRecordings(repoRoot: string): Promise<string[]>;
27
+ //# sourceMappingURL=record-trace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"record-trace.d.ts","sourceRoot":"","sources":["../src/record-trace.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAG5D,eAAO,MAAM,qBAAqB,eAAe,CAAC;AAYlD,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEnE;AAED,gFAAgF;AAChF,wBAAgB,mBAAmB,CAClC,gBAAgB,EAAE,MAAM,EACxB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,GAClB,MAAM,CAMR;AAED,wBAAgB,0BAA0B,IAAI,MAAM,CAEnD;AAED,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,SAAS,CAAC;AAEtD,MAAM,WAAW,qBAAqB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,iBAAiB,CAAC;CACxB;AAED,MAAM,WAAW,2BAA2B;IAC3C,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,6FAA6F;AAC7F,wBAAgB,oBAAoB,CACnC,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,cAAc,EAAE,OAAO,EACvB,OAAO,EAAE,2BAA2B,GAClC,qBAAqB,GAAG,SAAS,CAqBnC;AAED,0EAA0E;AAC1E,wBAAsB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAiBxF;AAED,mFAAmF;AACnF,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAGxE;AAED,6DAA6D;AAC7D,wBAAsB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE9E;AAED,mFAAmF;AACnF,wBAAsB,2BAA2B,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAuBrF"}
@@ -0,0 +1,97 @@
1
+ import { mkdir, readdir, readFile, rm, stat, writeFile } from "node:fs/promises";
2
+ import { tmpdir } from "node:os";
3
+ import { dirname, join, resolve } from "node:path";
4
+ import { enrichTrace } from "@post-print/agent-harness";
5
+ export const LIVE_STAGING_DIR_NAME = "agent-spec";
6
+ function slugifyScenarioName(name) {
7
+ return (name
8
+ .toLowerCase()
9
+ .replace(/[^a-z0-9]+/g, "-")
10
+ .replace(/^-+|-+$/g, "")
11
+ .slice(0, 48) || "scenario");
12
+ }
13
+ export function getLiveStagingRoot() {
14
+ return join(tmpdir(), LIVE_STAGING_DIR_NAME, "sessions");
15
+ }
16
+ export function getLiveStagingSessionRoot(sessionId) {
17
+ return join(getLiveStagingRoot(), sessionId);
18
+ }
19
+ /** Staging JSON path for a live scenario trace (matches recordTrace layout). */
20
+ export function getStagingTracePath(stagingSessionId, suiteName, scenarioName) {
21
+ return join(getLiveStagingSessionRoot(stagingSessionId), suiteName, `${slugifyScenarioName(scenarioName)}.json`);
22
+ }
23
+ export function createLiveStagingSessionId() {
24
+ return `${process.pid}-${Date.now()}`;
25
+ }
26
+ /** Staging lives under $TMPDIR; use --record-fixtures to overwrite committed replayTrace. */
27
+ export function resolveRecordingPath(suiteName, scenarioName, replayTrace, recordFixtures, options) {
28
+ if (!replayTrace) {
29
+ return undefined;
30
+ }
31
+ if (recordFixtures) {
32
+ return {
33
+ path: resolve(options.repoRoot, replayTrace),
34
+ kind: "fixture",
35
+ };
36
+ }
37
+ if (!options.stagingSessionId) {
38
+ throw new Error("stagingSessionId required for live staging recordings");
39
+ }
40
+ const slug = slugifyScenarioName(scenarioName);
41
+ return {
42
+ path: join(getLiveStagingSessionRoot(options.stagingSessionId), suiteName, `${slug}.json`),
43
+ kind: "staging",
44
+ };
45
+ }
46
+ /** Persist a live trace for replay regression (strip raw SDK payload). */
47
+ export async function recordTrace(outputPath, trace) {
48
+ const enriched = enrichTrace(trace);
49
+ const payload = {
50
+ messages: enriched.messages,
51
+ toolCalls: enriched.toolCalls,
52
+ shellCommands: enriched.shellCommands,
53
+ gitDiff: enriched.gitDiff,
54
+ prBody: enriched.prBody,
55
+ artifacts: enriched.artifacts,
56
+ routing: enriched.routing,
57
+ skillsInvoked: enriched.skillsInvoked,
58
+ judgeVerdicts: enriched.judgeVerdicts,
59
+ };
60
+ await mkdir(dirname(outputPath), { recursive: true });
61
+ await writeFile(outputPath, `${JSON.stringify(payload, null, 2)}\n`, "utf8");
62
+ return outputPath;
63
+ }
64
+ /** Load a staged live trace for parent-process judge after isolated child runs. */
65
+ export async function loadStagingTrace(path) {
66
+ const raw = JSON.parse(await readFile(path, "utf8"));
67
+ return enrichTrace(raw);
68
+ }
69
+ /** Remove a live staging session directory under $TMPDIR. */
70
+ export async function cleanupStagingSession(sessionRoot) {
71
+ await rm(sessionRoot, { recursive: true, force: true });
72
+ }
73
+ /** Remove legacy in-repo staging dirs from before tmpdir staging (best-effort). */
74
+ export async function cleanupLegacyRepoRecordings(repoRoot) {
75
+ const suitesRoot = join(repoRoot, "agent-suites");
76
+ const removed = [];
77
+ let suiteNames;
78
+ try {
79
+ suiteNames = await readdir(suitesRoot);
80
+ }
81
+ catch {
82
+ return removed;
83
+ }
84
+ for (const suiteName of suiteNames) {
85
+ const recordingsDir = join(suitesRoot, suiteName, "fixtures", "recordings");
86
+ try {
87
+ await stat(recordingsDir);
88
+ await rm(recordingsDir, { recursive: true, force: true });
89
+ removed.push(recordingsDir);
90
+ }
91
+ catch {
92
+ // absent
93
+ }
94
+ }
95
+ return removed;
96
+ }
97
+ //# sourceMappingURL=record-trace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"record-trace.js","sourceRoot":"","sources":["../src/record-trace.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import type { AgentHost } from "@post-print/agent-harness";
2
+ import type { SuiteRunReport } from "./types";
3
+ /** Best-effort worktree cleanup when live runs are interrupted (SIGINT/SIGTERM). */
4
+ export declare function registerLiveRunHandlers(): void;
5
+ export interface RunSuiteOptions {
6
+ cwd: string;
7
+ suitePath: string;
8
+ host?: AgentHost;
9
+ /** Run only this scenario name (used by live subprocess isolation). */
10
+ scenarioFilter?: string;
11
+ /** Write live traces after a fully passing run. */
12
+ record?: boolean;
13
+ /** Overwrite committed replayTrace paths (default: write staging traces under $TMPDIR). */
14
+ recordFixtures?: boolean;
15
+ /** Run harness LLM judge for rubric.judge criteria (live hosts only). */
16
+ judge?: boolean;
17
+ /** Isolate each live scenario in a detached git worktree. */
18
+ worktree?: boolean;
19
+ /** Session id for live staging traces under $TMPDIR (see record-trace.ts). */
20
+ stagingSessionId?: string;
21
+ keepRecordings?: boolean;
22
+ suitesDir?: string;
23
+ suiteFilter?: string;
24
+ }
25
+ export declare function runSuite(options: RunSuiteOptions): Promise<SuiteRunReport>;
26
+ export declare function runAllSuites(options: {
27
+ cwd: string;
28
+ suitesDir: string;
29
+ host?: AgentHost;
30
+ filter?: string;
31
+ scenarioFilter?: string;
32
+ record?: boolean;
33
+ recordFixtures?: boolean;
34
+ judge?: boolean;
35
+ worktree?: boolean;
36
+ stagingSessionId?: string;
37
+ keepRecordings?: boolean;
38
+ }): Promise<SuiteRunReport[]>;
39
+ export { discoverSuites } from "./discover-suites";
40
+ //# sourceMappingURL=run-suite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-suite.d.ts","sourceRoot":"","sources":["../src/run-suite.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACX,SAAS,EAKT,MAAM,2BAA2B,CAAC;AA4BnC,OAAO,KAAK,EAMX,cAAc,EACd,MAAM,SAAS,CAAC;AAKjB,oFAAoF;AACpF,wBAAgB,uBAAuB,IAAI,IAAI,CAmB9C;AASD,MAAM,WAAW,eAAe;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,uEAAuE;IACvE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mDAAmD;IACnD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,2FAA2F;IAC3F,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,yEAAyE;IACzE,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,8EAA8E;IAC9E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAsBD,wBAAsB,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CAwHhF;AA0ND,wBAAsB,YAAY,CAAC,OAAO,EAAE;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAC;CACzB,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CA6B5B;AAED,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC"}