@probemap/experiment-runner 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.
@@ -0,0 +1,55 @@
1
+ import { type ChangeUnitRef, type RunnerJobLease } from "@probemap/shared";
2
+ import type { OracleOutcome } from "./oracle.js";
3
+ type Progress = (phase: string, percent: number, message?: string, checkpoint?: Record<string, unknown>) => Promise<void>;
4
+ export interface CommitAncestryResolver {
5
+ commitsBetween(goodCommit: string, badCommit: string): Promise<string[]>;
6
+ }
7
+ export interface CommitOracle {
8
+ evaluate(commit: string, signal: AbortSignal): Promise<{
9
+ outcome: OracleOutcome;
10
+ durationMs: number;
11
+ }>;
12
+ }
13
+ export interface DeltaCandidateOracle {
14
+ evaluate(units: ChangeUnitRef[], signal: AbortSignal): Promise<OracleOutcome>;
15
+ }
16
+ export declare function executeBisectLease(lease: RunnerJobLease, signal: AbortSignal, progress: Progress, ancestry: CommitAncestryResolver, oracle: CommitOracle): Promise<{
17
+ schemaVersion: 1;
18
+ bisectRunId: string;
19
+ runFingerprint: string;
20
+ status: "budget_exhausted" | "canceled" | "found" | "inconclusive";
21
+ firstBadCommit?: string | undefined;
22
+ tested: {
23
+ commit: string;
24
+ outcome: "fail" | "inconclusive" | "pass";
25
+ durationMs: number;
26
+ }[];
27
+ algorithmState: Record<string, unknown>;
28
+ }>;
29
+ export declare function executeDeltaDebugLease(lease: RunnerJobLease, signal: AbortSignal, progress: Progress, oracle: DeltaCandidateOracle): Promise<{
30
+ schemaVersion: 1;
31
+ deltaDebugRunId: string;
32
+ runFingerprint: string;
33
+ status: "budget_exhausted" | "canceled" | "inconclusive" | "minimal";
34
+ minimalUnits: ({
35
+ type: "change_session";
36
+ id: string;
37
+ } | {
38
+ type: "file";
39
+ id: string;
40
+ } | {
41
+ type: "diff_hunk";
42
+ id: string;
43
+ } | {
44
+ type: "symbol";
45
+ id: string;
46
+ } | {
47
+ type: "change_group";
48
+ id: string;
49
+ })[];
50
+ tests: number;
51
+ algorithmState: Record<string, unknown>;
52
+ generatedFixTask?: string | undefined;
53
+ }>;
54
+ export {};
55
+ //# sourceMappingURL=algorithm-handlers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"algorithm-handlers.d.ts","sourceRoot":"","sources":["../src/algorithm-handlers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoI,KAAK,aAAa,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAC7M,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,KAAK,QAAQ,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAC1H,MAAM,WAAW,sBAAsB;IAAG,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;CAAE;AACpH,MAAM,WAAW,YAAY;IAAG,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,aAAa,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE;AACxI,MAAM,WAAW,oBAAoB;IAAG,QAAQ,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,CAAA;CAAE;AAEvH,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,sBAAsB,EAAE,MAAM,EAAE,YAAY;;;;;;;;;;;;GAAuxF;AACt7F,wBAAsB,sBAAsB,CAAC,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;GAAqzE"}
@@ -0,0 +1,56 @@
1
+ import { bisectExecuteJobPayloadSchema, bisectExecuteJobResultSchema, deltaDebugExecuteJobPayloadSchema, deltaDebugExecuteJobResultSchema } from "@probemap/shared";
2
+ function testedMap(value) { const map = new Map(); if (Array.isArray(value))
3
+ for (const item of value)
4
+ if (typeof item === "object" && item !== null && typeof item.commit === "string" && ["pass", "fail", "inconclusive"].includes(item.outcome) && typeof item.durationMs === "number")
5
+ map.set(item.commit, { outcome: item.outcome, durationMs: item.durationMs }); return map; }
6
+ export async function executeBisectLease(lease, signal, progress, ancestry, oracle) { const payload = bisectExecuteJobPayloadSchema.parse(lease.payload); const commits = await ancestry.commitsBetween(payload.goodCommit, payload.badCommit); if (commits[0] !== payload.goodCommit || commits.at(-1) !== payload.badCommit || new Set(commits).size !== commits.length)
7
+ throw new Error("Resolved bisect ancestry does not match immutable good/bad boundaries."); const previous = lease.resumeState ?? {}; let good = typeof previous["goodIndex"] === "number" ? previous["goodIndex"] : 0; let bad = typeof previous["badIndex"] === "number" ? previous["badIndex"] : commits.length - 1; const tested = testedMap(previous["tested"]); const evaluate = async (index) => { const commit = commits[index]; const cached = tested.get(commit); if (cached !== undefined)
8
+ return cached.outcome; if (tested.size >= payload.budget)
9
+ return "inconclusive"; const result = await oracle.evaluate(commit, signal); tested.set(commit, result); const checkpoint = { goodIndex: good, badIndex: bad, commits, tested: [...tested].map(([testedCommit, item]) => ({ commit: testedCommit, ...item })) }; await progress("bisect", Math.round((tested.size / payload.budget) * 100), `Tested ${tested.size}/${payload.budget}`, checkpoint); return result.outcome; }; if (await evaluate(good) !== "pass" || await evaluate(bad) !== "fail")
10
+ return bisectExecuteJobResultSchema.parse({ schemaVersion: 1, bisectRunId: payload.bisectRunId, runFingerprint: payload.runFingerprint, status: "inconclusive", tested: [...tested].map(([commit, item]) => ({ commit, ...item })), algorithmState: { goodIndex: good, badIndex: bad, commits, tested: [...tested].map(([commit, item]) => ({ commit, ...item })) } }); while (bad - good > 1 && tested.size < payload.budget && !signal.aborted) {
11
+ const middle = Math.floor((good + bad) / 2);
12
+ const outcome = await evaluate(middle);
13
+ if (outcome === "pass")
14
+ good = middle;
15
+ else if (outcome === "fail")
16
+ bad = middle;
17
+ else {
18
+ const alternatives = [middle + 1, middle - 1].filter((index) => index > good && index < bad && !tested.has(commits[index]));
19
+ if (alternatives.length === 0)
20
+ break;
21
+ const alternate = alternatives[0];
22
+ const alternateOutcome = await evaluate(alternate);
23
+ if (alternateOutcome === "pass")
24
+ good = alternate;
25
+ else if (alternateOutcome === "fail")
26
+ bad = alternate;
27
+ else
28
+ break;
29
+ }
30
+ } const status = signal.aborted ? "canceled" : bad - good === 1 ? "found" : tested.size >= payload.budget ? "budget_exhausted" : "inconclusive"; const state = { goodIndex: good, badIndex: bad, commits, tested: [...tested].map(([commit, item]) => ({ commit, ...item })) }; return bisectExecuteJobResultSchema.parse({ schemaVersion: 1, bisectRunId: payload.bisectRunId, runFingerprint: payload.runFingerprint, status, ...(status === "found" ? { firstBadCommit: commits[bad] } : {}), tested: state.tested, algorithmState: state }); }
31
+ export async function executeDeltaDebugLease(lease, signal, progress, oracle) { const payload = deltaDebugExecuteJobPayloadSchema.parse(lease.payload); const previous = lease.resumeState ?? {}; let current = Array.isArray(previous["currentUnits"]) ? previous["currentUnits"] : payload.units; let granularity = typeof previous["granularity"] === "number" ? previous["granularity"] : 2; let tests = typeof previous["tests"] === "number" ? previous["tests"] : 0; const started = Date.now(); let inconclusive = false; while (current.length >= 2 && tests < payload.budget.maxExperiments && Date.now() - started < payload.budget.maxDurationMs && !signal.aborted) {
32
+ const size = Math.ceil(current.length / granularity);
33
+ let reduced = false;
34
+ for (let start = 0; start < current.length && tests < payload.budget.maxExperiments; start += size) {
35
+ const complement = current.filter((_, index) => index < start || index >= start + size);
36
+ tests += 1;
37
+ const outcome = await oracle.evaluate(complement, signal);
38
+ if (outcome === "inconclusive")
39
+ inconclusive = true;
40
+ if (outcome === "fail") {
41
+ current = complement;
42
+ granularity = Math.max(2, granularity - 1);
43
+ reduced = true;
44
+ }
45
+ const checkpoint = { currentUnits: current, granularity, tests };
46
+ await progress("delta_debug", Math.round((tests / payload.budget.maxExperiments) * 100), `${current.length} units remain after ${tests} tests`, checkpoint);
47
+ if (reduced)
48
+ break;
49
+ }
50
+ if (!reduced) {
51
+ if (granularity >= current.length)
52
+ break;
53
+ granularity = Math.min(current.length, granularity * 2);
54
+ }
55
+ } const status = signal.aborted ? "canceled" : tests >= payload.budget.maxExperiments || Date.now() - started >= payload.budget.maxDurationMs ? "budget_exhausted" : inconclusive && current.length === payload.units.length ? "inconclusive" : "minimal"; const state = { currentUnits: current, granularity, tests }; const generatedFixTask = `ProbeMap experimentally reduced the failure-inducing change set to ${current.length} unit(s).\n\nReview only these immutable Change Unit references:\n${current.map((unit) => `- ${unit.type}:${unit.id}`).join("\n")}\n\nPreserve unrelated behavior and run the registered oracle ${payload.oracleId}@${payload.oracleVersion}.`; return deltaDebugExecuteJobResultSchema.parse({ schemaVersion: 1, deltaDebugRunId: payload.deltaDebugRunId, runFingerprint: payload.runFingerprint, status, minimalUnits: current, tests, algorithmState: state, generatedFixTask }); }
56
+ //# sourceMappingURL=algorithm-handlers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"algorithm-handlers.js","sourceRoot":"","sources":["../src/algorithm-handlers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { OracleOutcome } from "./oracle.js";
2
+ export interface BisectResult {
3
+ status: "found" | "inconclusive" | "budget_exhausted";
4
+ firstBadIndex?: number;
5
+ tested: Array<{
6
+ index: number;
7
+ outcome: OracleOutcome;
8
+ }>;
9
+ }
10
+ export declare function bisectCommits(commits: string[], verify: (commit: string) => Promise<OracleOutcome>, budget?: number): Promise<BisectResult>;
11
+ export interface DeltaDebugResult<T> {
12
+ status: "minimal" | "budget_exhausted" | "inconclusive";
13
+ units: T[];
14
+ tests: number;
15
+ }
16
+ export declare function deltaDebug<T>(units: T[], fails: (candidate: T[]) => Promise<OracleOutcome>, budget?: number): Promise<DeltaDebugResult<T>>;
17
+ //# sourceMappingURL=algorithms.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"algorithms.d.ts","sourceRoot":"","sources":["../src/algorithms.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,MAAM,WAAW,YAAY;IAAG,MAAM,EAAE,OAAO,GAAG,cAAc,GAAG,kBAAkB,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,aAAa,CAAA;KAAE,CAAC,CAAA;CAAE;AACzK,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,aAAa,CAAC,EAAE,MAAM,SAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAA+2B;AAC9/B,MAAM,WAAW,gBAAgB,CAAC,CAAC;IAAI,MAAM,EAAE,SAAS,GAAG,kBAAkB,GAAG,cAAc,CAAC;IAAC,KAAK,EAAE,CAAC,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE;AAC3H,wBAAsB,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,SAAS,EAAE,CAAC,EAAE,KAAK,OAAO,CAAC,aAAa,CAAC,EAAE,MAAM,SAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAkxB"}
@@ -0,0 +1,42 @@
1
+ export async function bisectCommits(commits, verify, budget = 100) { if (commits.length < 2)
2
+ return { status: "inconclusive", tested: [] }; let good = 0; let bad = commits.length - 1; const tested = []; while (bad - good > 1 && tested.length < budget) {
3
+ const index = Math.floor((good + bad) / 2);
4
+ const outcome = await verify(commits[index]);
5
+ tested.push({ index, outcome });
6
+ if (outcome === "pass")
7
+ good = index;
8
+ else if (outcome === "fail")
9
+ bad = index;
10
+ else {
11
+ const alternate = index + 1 < bad ? index + 1 : index - 1;
12
+ const alternateOutcome = await verify(commits[alternate]);
13
+ tested.push({ index: alternate, outcome: alternateOutcome });
14
+ if (alternateOutcome === "pass")
15
+ good = alternate;
16
+ else if (alternateOutcome === "fail")
17
+ bad = alternate;
18
+ else
19
+ return { status: "inconclusive", tested };
20
+ }
21
+ } return bad - good === 1 ? { status: "found", firstBadIndex: bad, tested } : { status: "budget_exhausted", tested }; }
22
+ export async function deltaDebug(units, fails, budget = 100) { let current = [...units]; let granularity = 2; let tests = 0; while (current.length >= 2 && tests < budget) {
23
+ const size = Math.ceil(current.length / granularity);
24
+ let reduced = false;
25
+ for (let start = 0; start < current.length && tests < budget; start += size) {
26
+ const complement = current.filter((_, index) => index < start || index >= start + size);
27
+ tests += 1;
28
+ const outcome = await fails(complement);
29
+ if (outcome === "fail") {
30
+ current = complement;
31
+ granularity = Math.max(2, granularity - 1);
32
+ reduced = true;
33
+ break;
34
+ }
35
+ }
36
+ if (!reduced) {
37
+ if (granularity >= current.length)
38
+ return { status: "minimal", units: current, tests };
39
+ granularity = Math.min(current.length, granularity * 2);
40
+ }
41
+ } return { status: tests >= budget ? "budget_exhausted" : "minimal", units: current, tests }; }
42
+ //# sourceMappingURL=algorithms.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"algorithms.js","sourceRoot":"","sources":["../src/algorithms.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { type RegisteredVerificationCommand } from "@probemap/shared";
2
+ export declare function commandHash(command: Omit<RegisteredVerificationCommand, "commandHash">): string;
3
+ export declare function runRegisteredCommand(rootPath: string, raw: RegisteredVerificationCommand, environment?: NodeJS.ProcessEnv, signal?: AbortSignal): Promise<{
4
+ outcome: "fail" | "inconclusive" | "pass";
5
+ exitCode: number | null;
6
+ stdout: string;
7
+ stderr: string;
8
+ durationMs: number;
9
+ timedOut: boolean;
10
+ }>;
11
+ //# sourceMappingURL=command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":"AAMA,OAAO,EAAuC,KAAK,6BAA6B,EAAE,MAAM,kBAAkB,CAAC;AAI3G,wBAAgB,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,6BAA6B,EAAE,aAAa,CAAC,GAAG,MAAM,CAA0E;AAE1K,wBAAsB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,6BAA6B,EAAE,WAAW,GAAE,MAAM,CAAC,UAAwB,EAAE,MAAM,CAAC,EAAE,WAAW;;;;;;;GAKlK"}
@@ -0,0 +1,37 @@
1
+ import { createHash } from "node:crypto";
2
+ import { execFile } from "node:child_process";
3
+ import { realpath } from "node:fs/promises";
4
+ import path from "node:path";
5
+ import { promisify } from "node:util";
6
+ import { registeredVerificationCommandSchema } from "@probemap/shared";
7
+ const execute = promisify(execFile);
8
+ function canonical(value) { if (Array.isArray(value))
9
+ return `[${value.map(canonical).join(",")}]`; if (value !== null && typeof value === "object")
10
+ return `{${Object.entries(value).sort(([a], [b]) => a.localeCompare(b)).map(([key, item]) => `${JSON.stringify(key)}:${canonical(item)}`).join(",")}}`; return JSON.stringify(value); }
11
+ export function commandHash(command) { return createHash("sha256").update(canonical(command)).digest("hex"); }
12
+ export async function runRegisteredCommand(rootPath, raw, environment = process.env, signal) {
13
+ const command = registeredVerificationCommandSchema.parse(raw);
14
+ const { commandHash: declaredHash, ...definition } = command;
15
+ if (declaredHash !== commandHash(definition))
16
+ throw new Error("Registered command hash does not match its immutable definition.");
17
+ const root = await realpath(rootPath);
18
+ const cwd = await realpath(path.resolve(root, command.cwd));
19
+ if (cwd !== root && !cwd.startsWith(`${root}${path.sep}`))
20
+ throw new Error("Registered command cwd escapes the sandbox.");
21
+ const env = {};
22
+ for (const key of ["PATH", "Path", "SYSTEMROOT", "SystemRoot", "TEMP", "TMP", "PROBEMAP_EXPERIMENT_ID", "PROBEMAP_VARIANT_ROLE", ...command.environmentAllowlist])
23
+ if (environment[key] !== undefined)
24
+ env[key] = environment[key];
25
+ const started = Date.now();
26
+ try {
27
+ const result = await execute(command.command, command.args, { cwd, env, timeout: command.timeoutMs, maxBuffer: 8 * 1_024 * 1_024, windowsHide: true, ...(signal === undefined ? {} : { signal }) });
28
+ const exitCode = 0;
29
+ return { outcome: command.expectedExitCodes.includes(exitCode) ? "pass" : "fail", exitCode, stdout: result.stdout, stderr: result.stderr, durationMs: Date.now() - started, timedOut: false };
30
+ }
31
+ catch (error) {
32
+ const value = error;
33
+ const exitCode = typeof value.code === "number" ? value.code : null;
34
+ return { outcome: value.name === "AbortError" ? "inconclusive" : exitCode !== null && command.expectedExitCodes.includes(exitCode) ? "pass" : "fail", exitCode, stdout: value.stdout ?? "", stderr: value.stderr ?? value.message, durationMs: Date.now() - started, timedOut: value.killed === true };
35
+ }
36
+ }
37
+ //# sourceMappingURL=command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command.js","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ import { type ExperimentExecuteJobPayload, type ExperimentNetworkPolicy, type RegisteredVerificationCommand } from "@probemap/shared";
2
+ import { WorktreeSandboxManager } from "./worktree.js";
3
+ export interface SourceVariantApplier {
4
+ applyTargetAndMutes(sandboxId: string, payload: ExperimentExecuteJobPayload): Promise<void>;
5
+ }
6
+ export interface NetworkIsolationLease {
7
+ environment: NodeJS.ProcessEnv;
8
+ release(): Promise<void>;
9
+ }
10
+ export interface NetworkIsolationController {
11
+ acquire(policy: ExperimentNetworkPolicy, sandboxRoot: string): Promise<NetworkIsolationLease>;
12
+ }
13
+ export interface ExperimentExecutionDependencies {
14
+ sandboxes: WorktreeSandboxManager;
15
+ command: RegisteredVerificationCommand;
16
+ networkPolicy: ExperimentNetworkPolicy;
17
+ preflight?: Array<{
18
+ command: RegisteredVerificationCommand;
19
+ networkPolicy: ExperimentNetworkPolicy;
20
+ }>;
21
+ networkIsolation: NetworkIsolationController;
22
+ sourceVariantApplier?: SourceVariantApplier;
23
+ signal?: AbortSignal;
24
+ environment?: NodeJS.ProcessEnv;
25
+ onCommandLog?(input: {
26
+ role: "baseline" | "variant";
27
+ repetition: number;
28
+ stdout: string;
29
+ stderr: string;
30
+ }): Promise<void>;
31
+ }
32
+ export declare function executeExperimentJob(rawPayload: ExperimentExecuteJobPayload, dependencies: ExperimentExecutionDependencies): Promise<{
33
+ schemaVersion: 1;
34
+ experimentId: string;
35
+ planHash: string;
36
+ status: "canceled" | "completed" | "failed" | "inconclusive";
37
+ baselineOutcomes: ("fail" | "inconclusive" | "pass")[];
38
+ variantOutcomes: ("fail" | "inconclusive" | "pass")[];
39
+ baselineRuntimeSessionIds: (string | null)[];
40
+ variantRuntimeSessionIds: (string | null)[];
41
+ comparison: Record<string, unknown>;
42
+ sandboxFingerprintHash: string;
43
+ networkPolicyEnforced: true;
44
+ worktreeSandboxed: true;
45
+ mainTreeUnchanged: true;
46
+ cleanupCompleted: true;
47
+ artifactIds: string[];
48
+ }>;
49
+ //# sourceMappingURL=execute.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../src/execute.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,2BAA2B,EAChC,KAAK,uBAAuB,EAC5B,KAAK,6BAA6B,EACnC,MAAM,kBAAkB,CAAC;AAI1B,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAkBvD,MAAM,WAAW,oBAAoB;IACnC,mBAAmB,CACjB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,IAAI,CAAC,CAAC;CAClB;AACD,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,MAAM,CAAC,UAAU,CAAC;IAC/B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AACD,MAAM,WAAW,0BAA0B;IACzC,OAAO,CACL,MAAM,EAAE,uBAAuB,EAC/B,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,qBAAqB,CAAC,CAAC;CACnC;AACD,MAAM,WAAW,+BAA+B;IAC9C,SAAS,EAAE,sBAAsB,CAAC;IAClC,OAAO,EAAE,6BAA6B,CAAC;IACvC,aAAa,EAAE,uBAAuB,CAAC;IACvC,SAAS,CAAC,EAAE,KAAK,CAAC;QAChB,OAAO,EAAE,6BAA6B,CAAC;QACvC,aAAa,EAAE,uBAAuB,CAAC;KACxC,CAAC,CAAC;IACH,gBAAgB,EAAE,0BAA0B,CAAC;IAC7C,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IAChC,YAAY,CAAC,CAAC,KAAK,EAAE;QACnB,IAAI,EAAE,UAAU,GAAG,SAAS,CAAC;QAC7B,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;KAChB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnB;AAED,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,2BAA2B,EACvC,YAAY,EAAE,+BAA+B;;;;;;;;;;;;;;;;GAiL9C"}
@@ -0,0 +1,159 @@
1
+ import { createHash } from "node:crypto";
2
+ import { experimentExecuteJobPayloadSchema, experimentExecuteJobResultSchema, } from "@probemap/shared";
3
+ import { runRegisteredCommand } from "./command.js";
4
+ import { summarizeOracle } from "./oracle.js";
5
+ import { WorktreeSandboxManager } from "./worktree.js";
6
+ function canonical(value) {
7
+ if (Array.isArray(value))
8
+ return `[${value.map(canonical).join(",")}]`;
9
+ if (value !== null && typeof value === "object")
10
+ return `{${Object.entries(value)
11
+ .sort(([a], [b]) => a.localeCompare(b))
12
+ .map(([key, item]) => `${JSON.stringify(key)}:${canonical(item)}`)
13
+ .join(",")}}`;
14
+ return JSON.stringify(value);
15
+ }
16
+ function hash(value) {
17
+ return createHash("sha256").update(canonical(value)).digest("hex");
18
+ }
19
+ function runtimeSessionId(stdout, stderr) {
20
+ const matches = [...`${stdout}\n${stderr}`.matchAll(/::probemap-runtime-session::([a-f0-9]{8}-[a-f0-9]{4}-[1-8][a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12})/giu)];
21
+ return matches.at(-1)?.[1]?.toLowerCase() ?? null;
22
+ }
23
+ export async function executeExperimentJob(rawPayload, dependencies) {
24
+ const payload = experimentExecuteJobPayloadSchema.parse(rawPayload);
25
+ const mainTreeBefore = await dependencies.sandboxes.repositoryStateHash();
26
+ if (dependencies.command.id !== payload.commandId ||
27
+ dependencies.command.commandHash !== payload.commandHash)
28
+ throw new Error("Runner command registry does not match the approved command ID/hash.");
29
+ if (dependencies.networkPolicy.id !== payload.networkPolicyId)
30
+ throw new Error("Runner network policy does not match the approved policy.");
31
+ const baseline = await dependencies.sandboxes.create({
32
+ repositoryId: payload.projectId,
33
+ commit: payload.baselineCommit,
34
+ });
35
+ let variant;
36
+ const outcomes = {
37
+ baseline: [],
38
+ variant: [],
39
+ };
40
+ const runtimeSessions = { baseline: [], variant: [] };
41
+ let completed;
42
+ try {
43
+ variant = await dependencies.sandboxes.create({
44
+ repositoryId: payload.projectId,
45
+ commit: payload.changeSessionId === undefined
46
+ ? (payload.targetCommit ?? payload.baselineCommit)
47
+ : payload.baselineCommit,
48
+ });
49
+ if ((payload.changeSessionId !== undefined ||
50
+ payload.mutedChangeUnits.length > 0 ||
51
+ payload.includedChangeUnits.length > 0) &&
52
+ dependencies.sourceVariantApplier === undefined)
53
+ throw new Error("Source bundle/change-unit applier is required for this experiment plan.");
54
+ await dependencies.sourceVariantApplier?.applyTargetAndMutes(variant.id, payload);
55
+ for (const [role, sandbox] of [
56
+ ["baseline", baseline],
57
+ ["variant", variant],
58
+ ])
59
+ for (const step of dependencies.preflight ?? []) {
60
+ if (dependencies.signal?.aborted === true)
61
+ break;
62
+ const isolation = await dependencies.networkIsolation.acquire(step.networkPolicy, sandbox.root);
63
+ try {
64
+ const result = await runRegisteredCommand(sandbox.root, step.command, { ...isolation.environment, ...dependencies.environment, PROBEMAP_EXPERIMENT_ID: payload.experimentId, PROBEMAP_VARIANT_ROLE: role }, dependencies.signal);
65
+ await dependencies.onCommandLog?.({
66
+ role,
67
+ repetition: 0,
68
+ stdout: result.stdout.slice(0, payload.limits.maxLogBytes),
69
+ stderr: result.stderr.slice(0, payload.limits.maxLogBytes),
70
+ });
71
+ if (result.outcome !== "pass")
72
+ throw Object.assign(new Error(`Preflight command ${step.command.id} did not pass.`), {
73
+ code: step.command.phase === "dependency"
74
+ ? "dependency_break"
75
+ : "build_failed",
76
+ });
77
+ }
78
+ finally {
79
+ await isolation.release();
80
+ }
81
+ }
82
+ for (const [role, sandbox, count] of [
83
+ ["baseline", baseline, payload.repetitionPolicy.baselineRuns],
84
+ ["variant", variant, payload.repetitionPolicy.variantRuns],
85
+ ]) {
86
+ const isolation = await dependencies.networkIsolation.acquire(dependencies.networkPolicy, sandbox.root);
87
+ try {
88
+ for (let repetition = 1; repetition <= count && dependencies.signal?.aborted !== true; repetition += 1) {
89
+ const result = await runRegisteredCommand(sandbox.root, dependencies.command, { ...isolation.environment, ...dependencies.environment, PROBEMAP_EXPERIMENT_ID: payload.experimentId, PROBEMAP_VARIANT_ROLE: role }, dependencies.signal);
90
+ const sessionId = runtimeSessionId(result.stdout, result.stderr);
91
+ runtimeSessions[role].push(sessionId);
92
+ outcomes[role].push(payload.oracleType === "command" || sessionId !== null ? result.outcome : "inconclusive");
93
+ await dependencies.onCommandLog?.({
94
+ role,
95
+ repetition,
96
+ stdout: result.stdout.slice(0, payload.limits.maxLogBytes),
97
+ stderr: result.stderr.slice(0, payload.limits.maxLogBytes),
98
+ });
99
+ }
100
+ }
101
+ finally {
102
+ await isolation.release();
103
+ }
104
+ }
105
+ const baselineSummary = summarizeOracle(outcomes.baseline, payload.repetitionPolicy.maxFlakyRate);
106
+ const variantSummary = summarizeOracle(outcomes.variant, payload.repetitionPolicy.maxFlakyRate);
107
+ const status = dependencies.signal?.aborted === true
108
+ ? "canceled"
109
+ : baselineSummary.outcome === "flaky" ||
110
+ variantSummary.outcome === "flaky" ||
111
+ baselineSummary.outcome === "inconclusive" ||
112
+ variantSummary.outcome === "inconclusive"
113
+ ? "inconclusive"
114
+ : "completed";
115
+ const fingerprintHash = hash({
116
+ baseline: baseline.fingerprint,
117
+ variant: variant.fingerprint,
118
+ networkPolicyId: payload.networkPolicyId,
119
+ commandHash: payload.commandHash,
120
+ });
121
+ completed = {
122
+ schemaVersion: 1,
123
+ experimentId: payload.experimentId,
124
+ planHash: payload.planHash,
125
+ status,
126
+ baselineOutcomes: outcomes.baseline,
127
+ variantOutcomes: outcomes.variant,
128
+ baselineRuntimeSessionIds: runtimeSessions.baseline,
129
+ variantRuntimeSessionIds: runtimeSessions.variant,
130
+ comparison: {
131
+ baseline: baselineSummary,
132
+ variant: variantSummary,
133
+ oracleType: payload.oracleType,
134
+ baselineRuntimeSessionIds: runtimeSessions.baseline,
135
+ variantRuntimeSessionIds: runtimeSessions.variant,
136
+ regressionStatus: baselineSummary.outcome === "fail" &&
137
+ variantSummary.outcome === "pass"
138
+ ? "resolved"
139
+ : baselineSummary.outcome === variantSummary.outcome
140
+ ? "unchanged"
141
+ : "moved",
142
+ },
143
+ sandboxFingerprintHash: fingerprintHash,
144
+ artifactIds: [],
145
+ };
146
+ }
147
+ finally {
148
+ if (variant !== undefined)
149
+ await dependencies.sandboxes.cleanup(variant.id);
150
+ await dependencies.sandboxes.cleanup(baseline.id);
151
+ }
152
+ if (completed === undefined)
153
+ throw new Error("Experiment did not produce a bounded result.");
154
+ const mainTreeAfter = await dependencies.sandboxes.repositoryStateHash();
155
+ if (mainTreeAfter !== mainTreeBefore)
156
+ throw Object.assign(new Error("The main repository tree changed during isolated experiment execution."), { code: "internal_error" });
157
+ return experimentExecuteJobResultSchema.parse({ ...completed, networkPolicyEnforced: true, worktreeSandboxed: true, mainTreeUnchanged: true, cleanupCompleted: true });
158
+ }
159
+ //# sourceMappingURL=execute.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execute.js","sourceRoot":"","sources":["../src/execute.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export * from "./oracle.js";
2
+ export * from "./algorithms.js";
3
+ export * from "./command.js";
4
+ export * from "./worktree.js";
5
+ export * from "./execute.js";
6
+ export * from "./algorithm-handlers.js";
7
+ export * from "./variant-applier.js";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ export * from "./oracle.js";
2
+ export * from "./algorithms.js";
3
+ export * from "./command.js";
4
+ export * from "./worktree.js";
5
+ export * from "./execute.js";
6
+ export * from "./algorithm-handlers.js";
7
+ export * from "./variant-applier.js";
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC"}
@@ -0,0 +1,10 @@
1
+ export type OracleOutcome = "pass" | "fail" | "inconclusive";
2
+ export interface OracleSummary {
3
+ outcome: OracleOutcome | "flaky";
4
+ passRate: number;
5
+ failRate: number;
6
+ inconclusiveRate: number;
7
+ confidence: number;
8
+ }
9
+ export declare function summarizeOracle(outcomes: OracleOutcome[], maxFlakyRate: number): OracleSummary;
10
+ //# sourceMappingURL=oracle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oracle.d.ts","sourceRoot":"","sources":["../src/oracle.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,MAAM,GAAG,cAAc,CAAC;AAC7D,MAAM,WAAW,aAAa;IAAG,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE;AACrJ,wBAAgB,eAAe,CAAC,QAAQ,EAAE,aAAa,EAAE,EAAE,YAAY,EAAE,MAAM,GAAG,aAAa,CAAqtB"}
package/dist/oracle.js ADDED
@@ -0,0 +1,3 @@
1
+ export function summarizeOracle(outcomes, maxFlakyRate) { if (outcomes.length === 0)
2
+ return { outcome: "inconclusive", passRate: 0, failRate: 0, inconclusiveRate: 1, confidence: 0 }; const count = (value) => outcomes.filter((item) => item === value).length / outcomes.length; const passRate = count("pass"); const failRate = count("fail"); const inconclusiveRate = count("inconclusive"); const minority = Math.min(passRate, failRate); const outcome = inconclusiveRate === 1 ? "inconclusive" : passRate > 0 && failRate > 0 && minority > maxFlakyRate ? "flaky" : failRate > passRate ? "fail" : passRate > failRate ? "pass" : "inconclusive"; return { outcome, passRate, failRate, inconclusiveRate, confidence: Math.max(passRate, failRate) * (1 - inconclusiveRate) }; }
3
+ //# sourceMappingURL=oracle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oracle.js","sourceRoot":"","sources":["../src/oracle.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,eAAe,CAAC,QAAyB,EAAE,YAAoB,IAAmB,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;IAAE,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,gBAAgB,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,KAAK,GAAG,CAAC,KAAoB,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,gBAAgB,GAAG,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,MAAM,OAAO,GAAG,gBAAgB,KAAK,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,IAAI,QAAQ,GAAG,CAAC,IAAI,QAAQ,GAAG,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,gBAAgB,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,gBAAgB,CAAC,EAAE,CAAC,CAAC,CAAC"}
@@ -0,0 +1,23 @@
1
+ import { type ExperimentExecuteJobPayload } from "@probemap/shared";
2
+ import type { SourceVariantApplier } from "./execute.js";
3
+ import type { WorktreeSandboxManager } from "./worktree.js";
4
+ export interface SourceBundleReader {
5
+ readArtifact(artifactId: string): Promise<Uint8Array>;
6
+ }
7
+ export interface SourceVariantPlan {
8
+ projectId: string;
9
+ baselineCommit: string;
10
+ sourceBundleArtifactId?: string | undefined;
11
+ sourceBundleHash?: string | undefined;
12
+ mutedChangeUnits: ExperimentExecuteJobPayload["mutedChangeUnits"];
13
+ includedChangeUnits?: ExperimentExecuteJobPayload["includedChangeUnits"];
14
+ changeUnitDefinitions: ExperimentExecuteJobPayload["changeUnitDefinitions"];
15
+ }
16
+ export declare class BundleSourceVariantApplier implements SourceVariantApplier {
17
+ private readonly sandboxes;
18
+ private readonly source;
19
+ constructor(sandboxes: WorktreeSandboxManager, source: SourceBundleReader);
20
+ applyTargetAndMutes(sandboxId: string, payload: ExperimentExecuteJobPayload): Promise<void>;
21
+ applyPlan(sandboxId: string, payload: SourceVariantPlan): Promise<void>;
22
+ }
23
+ //# sourceMappingURL=variant-applier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"variant-applier.d.ts","sourceRoot":"","sources":["../src/variant-applier.ts"],"names":[],"mappings":"AAQA,OAAO,EAEL,KAAK,2BAA2B,EACjC,MAAM,kBAAkB,CAAC;AAE1B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAE5D,MAAM,WAAW,kBAAkB;IACjC,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CACvD;AACD,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,sBAAsB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,gBAAgB,EAAE,2BAA2B,CAAC,kBAAkB,CAAC,CAAC;IAClE,mBAAmB,CAAC,EAAE,2BAA2B,CAAC,qBAAqB,CAAC,CAAC;IACzE,qBAAqB,EAAE,2BAA2B,CAAC,uBAAuB,CAAC,CAAC;CAC7E;AAwED,qBAAa,0BAA2B,YAAW,oBAAoB;IAEnE,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,MAAM;IAFzB,YACmB,SAAS,EAAE,sBAAsB,EACjC,MAAM,EAAE,kBAAkB,EACzC;IACG,mBAAmB,CACxB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,IAAI,CAAC,CAEf;IACY,SAAS,CACpB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,IAAI,CAAC,CAqIf;CACF"}
@@ -0,0 +1,184 @@
1
+ import { createHash } from "node:crypto";
2
+ import { createMutedSymbolSource, parseUnifiedDiff, } from "@probemap/change-history";
3
+ import { changeCaptureBundleManifestSchema, } from "@probemap/shared";
4
+ function canonical(value) {
5
+ if (Array.isArray(value))
6
+ return `[${value.map(canonical).join(",")}]`;
7
+ if (value !== null && typeof value === "object")
8
+ return `{${Object.entries(value)
9
+ .sort(([a], [b]) => a.localeCompare(b))
10
+ .map(([key, item]) => `${JSON.stringify(key)}:${canonical(item)}`)
11
+ .join(",")}}`;
12
+ return JSON.stringify(value);
13
+ }
14
+ function digest(value) {
15
+ return createHash("sha256").update(value).digest("hex");
16
+ }
17
+ function hunkPatch(file, hunk) {
18
+ const oldPath = file.changeType === "added"
19
+ ? "/dev/null"
20
+ : `a/${file.oldPath ?? file.path}`;
21
+ const newPath = file.changeType === "deleted" ? "/dev/null" : `b/${file.path}`;
22
+ return `diff --git a/${file.oldPath ?? file.path} b/${file.path}\n--- ${oldPath}\n+++ ${newPath}\n${hunk.patch}`;
23
+ }
24
+ function decodeBundle(body, payload) {
25
+ let serialized;
26
+ try {
27
+ serialized = JSON.parse(Buffer.from(body).toString("utf8"));
28
+ }
29
+ catch {
30
+ throw new Error("Source bundle is not valid JSON.");
31
+ }
32
+ const manifest = changeCaptureBundleManifestSchema.parse(serialized.manifest);
33
+ const { sha256: _declared, ...unsigned } = manifest;
34
+ if (manifest.sha256 !== payload.sourceBundleHash ||
35
+ digest(canonical(unsigned)) !== manifest.sha256 ||
36
+ manifest.projectId !== payload.projectId)
37
+ throw new Error("Source bundle manifest identity/hash mismatch.");
38
+ if (serialized.parts === null ||
39
+ typeof serialized.parts !== "object" ||
40
+ Array.isArray(serialized.parts))
41
+ throw new Error("Source bundle parts are missing.");
42
+ const encoded = serialized.parts;
43
+ const parts = new Map();
44
+ for (const part of [
45
+ manifest.stagedPatch,
46
+ manifest.unstagedPatch,
47
+ manifest.untrackedManifest,
48
+ manifest.untrackedBlobs,
49
+ manifest.rawChangeList,
50
+ manifest.submodules,
51
+ manifest.lfsPointers,
52
+ ].filter((item) => item !== undefined)) {
53
+ const value = encoded[part.path];
54
+ if (typeof value !== "string")
55
+ throw new Error(`Source bundle part is missing: ${part.path}`);
56
+ const bytes = Buffer.from(value, "base64");
57
+ if (bytes.byteLength !== part.sizeBytes || digest(bytes) !== part.sha256)
58
+ throw new Error(`Source bundle part failed integrity verification: ${part.path}`);
59
+ parts.set(part.path, bytes);
60
+ }
61
+ return { manifest, parts };
62
+ }
63
+ export class BundleSourceVariantApplier {
64
+ sandboxes;
65
+ source;
66
+ constructor(sandboxes, source) {
67
+ this.sandboxes = sandboxes;
68
+ this.source = source;
69
+ }
70
+ applyTargetAndMutes(sandboxId, payload) {
71
+ return this.applyPlan(sandboxId, payload);
72
+ }
73
+ async applyPlan(sandboxId, payload) {
74
+ let parsedFiles = [];
75
+ if (payload.sourceBundleArtifactId !== undefined) {
76
+ const bundle = decodeBundle(await this.source.readArtifact(payload.sourceBundleArtifactId), payload);
77
+ if (bundle.manifest.baseCommit !== undefined &&
78
+ bundle.manifest.baseCommit !== payload.baselineCommit)
79
+ throw new Error("Source bundle baseline commit does not match the experiment plan.");
80
+ const staged = Buffer.from(bundle.parts.get(bundle.manifest.stagedPatch.path) ?? []).toString("utf8");
81
+ const unstaged = Buffer.from(bundle.parts.get(bundle.manifest.unstagedPatch.path) ?? []).toString("utf8");
82
+ if (staged !== "")
83
+ await this.sandboxes.applyPatch(sandboxId, staged);
84
+ if (unstaged !== "")
85
+ await this.sandboxes.applyPatch(sandboxId, unstaged);
86
+ parsedFiles = [
87
+ ...parseUnifiedDiff(staged),
88
+ ...parseUnifiedDiff(unstaged),
89
+ ];
90
+ if (bundle.manifest.untrackedBlobs !== undefined) {
91
+ const raw = Buffer.from(bundle.parts.get(bundle.manifest.untrackedBlobs.path) ?? []).toString("utf8");
92
+ const blobs = JSON.parse(raw);
93
+ if (!Array.isArray(blobs))
94
+ throw new Error("Untracked source bundle payload is invalid.");
95
+ for (const entry of blobs) {
96
+ if (entry === null ||
97
+ typeof entry !== "object" ||
98
+ typeof entry.path !== "string" ||
99
+ typeof entry.content !== "string")
100
+ throw new Error("Untracked source bundle entry is invalid.");
101
+ await this.sandboxes.writeFile(sandboxId, entry.path, Buffer.from(entry.content, "base64"));
102
+ }
103
+ }
104
+ }
105
+ const definitions = new Map(payload.changeUnitDefinitions.map((definition) => [
106
+ `${definition.type}:${definition.id}`,
107
+ definition,
108
+ ]));
109
+ const pending = [...payload.mutedChangeUnits];
110
+ const expanded = new Set();
111
+ while (pending.length > 0) {
112
+ const ref = pending.shift();
113
+ const key = `${ref.type}:${ref.id}`;
114
+ if (expanded.has(key))
115
+ continue;
116
+ expanded.add(key);
117
+ const definition = definitions.get(key);
118
+ if (definition?.type === "change_group")
119
+ pending.push(...definition.memberRefs);
120
+ }
121
+ const includedPending = [...(payload.includedChangeUnits ?? [])];
122
+ const included = new Set();
123
+ const includedTypes = new Set();
124
+ while (includedPending.length > 0) {
125
+ const ref = includedPending.shift();
126
+ const key = `${ref.type}:${ref.id}`;
127
+ if (included.has(key))
128
+ continue;
129
+ included.add(key);
130
+ const definition = definitions.get(key);
131
+ if (definition?.type === "change_group")
132
+ includedPending.push(...definition.memberRefs);
133
+ else if (ref.type !== "change_session" && ref.type !== "change_group")
134
+ includedTypes.add(ref.type);
135
+ }
136
+ if (includedTypes.size > 0)
137
+ for (const [key, definition] of definitions)
138
+ if (definition.type !== "change_group" && includedTypes.has(definition.type) && !included.has(key))
139
+ expanded.add(key);
140
+ const mutedFiles = new Set();
141
+ const reversedHunks = new Set();
142
+ for (const key of expanded) {
143
+ const definition = definitions.get(key);
144
+ if (definition?.type !== "file")
145
+ continue;
146
+ await this.sandboxes.muteFile(sandboxId, payload.baselineCommit, definition.path, definition.oldPath);
147
+ mutedFiles.add(definition.path);
148
+ }
149
+ for (const key of expanded) {
150
+ const definition = definitions.get(key);
151
+ if (definition === undefined ||
152
+ definition.type === "file" ||
153
+ definition.type === "change_group" ||
154
+ mutedFiles.has(definition.path))
155
+ continue;
156
+ if (definition.type === "symbol") {
157
+ const baseline = await this.sandboxes.readFileAtCommit(sandboxId, payload.baselineCommit, definition.path);
158
+ const target = await this.sandboxes.readFile(sandboxId, definition.path);
159
+ const result = createMutedSymbolSource({
160
+ filePath: definition.path,
161
+ qualifiedName: definition.qualifiedName,
162
+ baselineSource: baseline,
163
+ targetSource: target,
164
+ });
165
+ if (result.status !== "isolated")
166
+ throw new Error(`Symbol cannot be isolated (${result.reason}): ${definition.qualifiedName}`);
167
+ await this.sandboxes.writeFile(sandboxId, definition.path, result.source);
168
+ for (const hash of definition.coveringHunkHashes)
169
+ reversedHunks.add(hash);
170
+ continue;
171
+ }
172
+ if (reversedHunks.has(definition.patchHash))
173
+ continue;
174
+ const match = parsedFiles
175
+ .flatMap((file) => file.hunks.map((hunk) => ({ file, hunk })))
176
+ .find((item) => item.hunk.patchHash === definition.patchHash);
177
+ if (match === undefined)
178
+ throw new Error(`Approved hunk patch is absent from the verified source bundle: ${definition.patchHash}`);
179
+ await this.sandboxes.reversePatch(sandboxId, hunkPatch(match.file, match.hunk));
180
+ reversedHunks.add(definition.patchHash);
181
+ }
182
+ }
183
+ }
184
+ //# sourceMappingURL=variant-applier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"variant-applier.js","sourceRoot":"","sources":["../src/variant-applier.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ export interface SandboxFingerprint {
2
+ repositoryId: string;
3
+ commit: string;
4
+ operatingSystem: string;
5
+ architecture: string;
6
+ nodeVersion: string;
7
+ lockfileHash?: string;
8
+ }
9
+ export interface WorktreeSandboxHandle {
10
+ id: string;
11
+ opaquePathId: string;
12
+ root: string;
13
+ fingerprint: SandboxFingerprint;
14
+ }
15
+ export declare class WorktreeSandboxManager {
16
+ private readonly repositoryRoot;
17
+ private readonly sandboxRoot;
18
+ private readonly active;
19
+ constructor(repositoryRoot: string, sandboxRoot: string);
20
+ create(input: {
21
+ repositoryId: string;
22
+ commit: string;
23
+ lockfileHash?: string;
24
+ }): Promise<WorktreeSandboxHandle>;
25
+ muteFile(id: string, baselineCommit: string, file: string, oldPath?: string): Promise<void>;
26
+ applyPatch(id: string, patch: string): Promise<void>;
27
+ reversePatch(id: string, patch: string): Promise<void>;
28
+ readFile(id: string, file: string): Promise<string>;
29
+ readFileAtCommit(id: string, commit: string, file: string): Promise<string>;
30
+ writeFile(id: string, file: string, body: string | Uint8Array): Promise<void>;
31
+ status(id: string): Promise<string>;
32
+ repositoryStateHash(): Promise<string>;
33
+ cleanup(id: string): Promise<void>;
34
+ reconcileOrphans(): Promise<number>;
35
+ private require;
36
+ private assertPortablePath;
37
+ }
38
+ //# sourceMappingURL=worktree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worktree.d.ts","sourceRoot":"","sources":["../src/worktree.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,kBAAkB;IAAG,YAAY,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE;AACvK,MAAM,WAAW,qBAAqB;IAAG,EAAE,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,kBAAkB,CAAA;CAAE;AAE1H,qBAAa,sBAAsB;IAEd,OAAO,CAAC,QAAQ,CAAC,cAAc;IAAU,OAAO,CAAC,QAAQ,CAAC,WAAW;IADxF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA4C;IACnE,YAAoC,cAAc,EAAE,MAAM,EAAmB,WAAW,EAAE,MAAM,EAAI;IAEvF,MAAM,CAAC,KAAK,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAS1H;IAEY,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMvG;IACY,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAA6N;IACjR,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAA0O;IAChS,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAuG;IAC1J,gBAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAyN;IACpS,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAwW;IACrb,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAA8F;IACjI,mBAAmB,IAAI,OAAO,CAAC,MAAM,CAAC,CAAic;IACve,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAomB;IACtoB,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC,CAA40B;IAC53B,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,kBAAkB;CAC3B"}
@@ -0,0 +1,95 @@
1
+ import { execFile, spawn } from "node:child_process";
2
+ import { createHash, randomUUID } from "node:crypto";
3
+ import { mkdir, readFile, realpath, rm, stat, writeFile } from "node:fs/promises";
4
+ import path from "node:path";
5
+ import { promisify } from "node:util";
6
+ const execute = promisify(execFile);
7
+ const commitPattern = /^[a-f0-9]{40,64}$/u;
8
+ function opaqueId(value) { return createHash("sha256").update(value).digest("hex"); }
9
+ async function git(root, args) { const result = await execute("git", ["-c", "core.quotepath=false", "-c", "color.ui=false", ...args], { cwd: root, encoding: "utf8", maxBuffer: 32 * 1024 * 1024, windowsHide: true }); return result.stdout.trim(); }
10
+ async function gitRaw(root, args) { const result = await execute("git", ["-c", "core.quotepath=false", "-c", "color.ui=false", ...args], { cwd: root, encoding: "utf8", maxBuffer: 32 * 1024 * 1024, windowsHide: true }); return result.stdout.replaceAll("\r\n", "\n"); }
11
+ async function applyWithStdin(root, args, patch) { await new Promise((resolve, reject) => { const child = spawn("git", ["-c", "core.quotepath=false", "apply", ...args], { cwd: root, shell: false, windowsHide: true, stdio: ["pipe", "pipe", "pipe"] }); let stderr = ""; child.stderr.setEncoding("utf8"); child.stderr.on("data", (chunk) => { if (stderr.length < 64_000)
12
+ stderr += chunk; }); child.once("error", reject); child.once("close", (code) => code === 0 ? resolve() : reject(new Error(`git apply failed (${code ?? "signal"}): ${stderr.slice(0, 8_000)}`))); child.stdin.end(patch); }); }
13
+ export class WorktreeSandboxManager {
14
+ repositoryRoot;
15
+ sandboxRoot;
16
+ active = new Map();
17
+ constructor(repositoryRoot, sandboxRoot) {
18
+ this.repositoryRoot = repositoryRoot;
19
+ this.sandboxRoot = sandboxRoot;
20
+ }
21
+ async create(input) {
22
+ if (!commitPattern.test(input.commit))
23
+ throw new Error("Sandbox commit must be an immutable full commit hash.");
24
+ const repository = await realpath(this.repositoryRoot);
25
+ const root = path.resolve(this.sandboxRoot);
26
+ await mkdir(root, { recursive: true });
27
+ const canonicalRoot = await realpath(root);
28
+ const top = await realpath(await git(repository, ["rev-parse", "--show-toplevel"]));
29
+ if (top !== repository)
30
+ throw new Error("Sandbox repository root must be the explicit Git worktree root.");
31
+ const resolved = await git(repository, ["rev-parse", `${input.commit}^{commit}`]);
32
+ if (resolved !== input.commit)
33
+ throw new Error("Sandbox commit did not resolve to the requested immutable commit.");
34
+ const id = randomUUID();
35
+ const destination = path.resolve(canonicalRoot, id);
36
+ if (!destination.startsWith(`${canonicalRoot}${path.sep}`))
37
+ throw new Error("Sandbox destination escaped its configured root.");
38
+ await git(repository, ["worktree", "add", "--detach", "--no-checkout", destination, input.commit]);
39
+ try {
40
+ await git(destination, ["checkout", "--detach", input.commit]);
41
+ }
42
+ catch (error) {
43
+ await git(repository, ["worktree", "remove", "--force", destination]).catch(() => undefined);
44
+ await rm(destination, { recursive: true, force: true });
45
+ throw error;
46
+ }
47
+ const handle = { id, opaquePathId: opaqueId(`${input.repositoryId}:${id}`), root: destination, fingerprint: { repositoryId: input.repositoryId, commit: input.commit, operatingSystem: process.platform, architecture: process.arch, nodeVersion: process.version, ...(input.lockfileHash === undefined ? {} : { lockfileHash: input.lockfileHash }) } };
48
+ this.active.set(id, handle);
49
+ return handle;
50
+ }
51
+ async muteFile(id, baselineCommit, file, oldPath) {
52
+ const sandbox = this.require(id);
53
+ this.assertPortablePath(file);
54
+ if (oldPath !== undefined)
55
+ this.assertPortablePath(oldPath);
56
+ if (!commitPattern.test(baselineCommit))
57
+ throw new Error("File mute requires an immutable baseline.");
58
+ const baselinePath = oldPath ?? file;
59
+ const exists = await git(sandbox.root, ["cat-file", "-e", `${baselineCommit}:${baselinePath}`]).then(() => true, () => false);
60
+ if (!exists) {
61
+ await git(sandbox.root, ["rm", "-f", "--ignore-unmatch", "--", file]);
62
+ return;
63
+ }
64
+ if (baselinePath !== file)
65
+ await git(sandbox.root, ["rm", "-f", "--ignore-unmatch", "--", file]);
66
+ await git(sandbox.root, ["checkout", baselineCommit, "--", baselinePath]);
67
+ }
68
+ async applyPatch(id, patch) { const sandbox = this.require(id); if (Buffer.byteLength(patch) > 64 * 1_024 * 1_024)
69
+ throw new Error("Patch exceeds the sandbox limit."); await applyWithStdin(sandbox.root, ["--index", "--whitespace=nowarn"], patch); }
70
+ async reversePatch(id, patch) { const sandbox = this.require(id); if (Buffer.byteLength(patch) > 10 * 1_024 * 1_024)
71
+ throw new Error("Patch exceeds the sandbox limit."); await applyWithStdin(sandbox.root, ["--reverse", "--index", "--whitespace=nowarn"], patch); }
72
+ async readFile(id, file) { this.assertPortablePath(file); return readFile(path.resolve(this.require(id).root, file), "utf8"); }
73
+ async readFileAtCommit(id, commit, file) { this.require(id); this.assertPortablePath(file); if (!commitPattern.test(commit))
74
+ throw new Error("Source read requires an immutable commit."); return gitRaw(this.require(id).root, ["show", `${commit}:${file}`]); }
75
+ async writeFile(id, file, body) { const sandbox = this.require(id); this.assertPortablePath(file); const target = path.resolve(sandbox.root, file); if (!target.startsWith(`${sandbox.root}${path.sep}`))
76
+ throw new Error("Sandbox file escaped its worktree."); await mkdir(path.dirname(target), { recursive: true }); await writeFile(target, body); await git(sandbox.root, ["add", "--", file]); }
77
+ async status(id) { return git(this.require(id).root, ["status", "--porcelain=v1", "--untracked-files=all"]); }
78
+ async repositoryStateHash() { const repository = await realpath(this.repositoryRoot); const [head, status, working, staged] = await Promise.all([git(repository, ["rev-parse", "HEAD"]), gitRaw(repository, ["status", "--porcelain=v1", "--untracked-files=all"]), gitRaw(repository, ["diff", "--binary", "HEAD"]), gitRaw(repository, ["diff", "--binary", "--cached", "HEAD"])]); return createHash("sha256").update(JSON.stringify({ head, status, working, staged })).digest("hex"); }
79
+ async cleanup(id) { const sandbox = this.require(id); const repository = await realpath(this.repositoryRoot); const root = await realpath(this.sandboxRoot); const resolved = path.resolve(sandbox.root); if (!resolved.startsWith(`${root}${path.sep}`))
80
+ throw new Error("Refusing cleanup outside the configured sandbox root."); await git(repository, ["worktree", "remove", "--force", resolved]).catch(async () => { if ((await stat(resolved).catch(() => undefined)) !== undefined)
81
+ throw new Error("Git could not detach the sandbox worktree safely."); }); await rm(resolved, { recursive: true, force: true }); this.active.delete(id); }
82
+ async reconcileOrphans() { const repository = await realpath(this.repositoryRoot); await mkdir(this.sandboxRoot, { recursive: true }); const root = await realpath(this.sandboxRoot); const listed = await gitRaw(repository, ["worktree", "list", "--porcelain"]); const candidates = listed.split("\n").filter((line) => line.startsWith("worktree ")).map((line) => path.resolve(line.slice("worktree ".length))); let cleaned = 0; for (const candidate of candidates) {
83
+ if (path.dirname(candidate) !== root)
84
+ continue;
85
+ await git(repository, ["worktree", "remove", "--force", candidate]).catch(async () => { if ((await stat(candidate).catch(() => undefined)) !== undefined)
86
+ throw new Error("Git could not detach an orphan sandbox safely."); });
87
+ await rm(candidate, { recursive: true, force: true });
88
+ cleaned += 1;
89
+ } await git(repository, ["worktree", "prune"]); return cleaned; }
90
+ require(id) { const sandbox = this.active.get(id); if (sandbox === undefined)
91
+ throw new Error("Sandbox is unknown or already cleaned."); return sandbox; }
92
+ assertPortablePath(file) { if (!/^(?![/\\])(?!.+:)(?!.*(?:^|[/\\])\.\.(?:[/\\]|$)).+$/u.test(file) || file.includes("\0"))
93
+ throw new Error("Sandbox operation requires a portable repository path."); }
94
+ }
95
+ //# sourceMappingURL=worktree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worktree.js","sourceRoot":"","sources":["../src/worktree.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClF,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,OAAO,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AACpC,MAAM,aAAa,GAAG,oBAAoB,CAAC;AAC3C,SAAS,QAAQ,CAAC,KAAa,IAAY,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAErG,KAAK,UAAU,GAAG,CAAC,IAAY,EAAE,IAAc,IAAqB,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,sBAAsB,EAAE,IAAI,EAAE,gBAAgB,EAAE,GAAG,IAAI,CAAC,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;AACzR,KAAK,UAAU,MAAM,CAAC,IAAY,EAAE,IAAc,IAAqB,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,sBAAsB,EAAE,IAAI,EAAE,gBAAgB,EAAE,GAAG,IAAI,CAAC,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,OAAO,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;AAC9S,KAAK,UAAU,cAAc,CAAC,IAAY,EAAE,IAAc,EAAE,KAAa,IAAmB,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,GAAG,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,MAAM,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,GAAG,IAAI,MAAM,CAAC,MAAM,GAAG,MAAM;IAAE,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,qBAAqB,IAAI,IAAI,QAAQ,MAAM,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAKroB,MAAM,OAAO,sBAAsB;IAEG,cAAc;IAA2B,WAAW;IADvE,MAAM,GAAG,IAAI,GAAG,EAAiC,CAAC;IACnE,YAAoC,cAAsB,EAAmB,WAAmB;8BAA5D,cAAc;2BAA2B,WAAW;IAAW,CAAC;IAE7F,KAAK,CAAC,MAAM,CAAC,KAAsE;QACxF,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;QAChH,MAAM,UAAU,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAAC,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAAC,MAAM,KAAK,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAAC,MAAM,aAAa,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;QACxL,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,MAAM,GAAG,CAAC,UAAU,EAAE,CAAC,WAAW,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC;QAAC,IAAI,GAAG,KAAK,UAAU;YAAE,MAAM,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAC;QAChM,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,UAAU,EAAE,CAAC,WAAW,EAAE,GAAG,KAAK,CAAC,MAAM,WAAW,CAAC,CAAC,CAAC;QAAC,IAAI,QAAQ,KAAK,KAAK,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,mEAAmE,CAAC,CAAC;QACvM,MAAM,EAAE,GAAG,UAAU,EAAE,CAAC;QAAC,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;QAAC,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,GAAG,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;QAC9M,MAAM,GAAG,CAAC,UAAU,EAAE,CAAC,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;QACnG,IAAI,CAAC;YAAC,MAAM,GAAG,CAAC,WAAW,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;QAAC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAAC,MAAM,GAAG,CAAC,UAAU,EAAE,CAAC,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YAAC,MAAM,EAAE,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YAAC,MAAM,KAAK,CAAC;QAAC,CAAC;QAC7P,MAAM,MAAM,GAA0B,EAAE,EAAE,EAAE,YAAY,EAAE,QAAQ,CAAC,GAAG,KAAK,CAAC,YAAY,IAAI,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,EAAE,YAAY,EAAE,KAAK,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,eAAe,EAAE,OAAO,CAAC,QAAQ,EAAE,YAAY,EAAE,OAAO,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,KAAK,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,KAAK,CAAC,YAAY,EAAE,CAAC,EAAE,EAAE,CAAC;QAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QAAC,OAAO,MAAM,CAAC;IAC9Z,CAAC;IAEM,KAAK,CAAC,QAAQ,CAAC,EAAU,EAAE,cAAsB,EAAE,IAAY,EAAE,OAAgB;QACtF,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;QAAC,IAAI,OAAO,KAAK,SAAS;YAAE,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;QAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,cAAc,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;QACpO,MAAM,YAAY,GAAG,OAAO,IAAI,IAAI,CAAC;QAAC,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,UAAU,EAAE,IAAI,EAAE,GAAG,cAAc,IAAI,YAAY,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;QACpK,IAAI,CAAC,MAAM,EAAE,CAAC;YAAC,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,kBAAkB,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;YAAC,OAAO;QAAC,CAAC;QAC/F,IAAI,YAAY,KAAK,IAAI;YAAE,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,kBAAkB,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;QACjG,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,UAAU,EAAE,cAAc,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC;IAC5E,CAAC;IACM,KAAK,CAAC,UAAU,CAAC,EAAU,EAAE,KAAa,IAAmB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC,CAAC,MAAM,cAAc,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,SAAS,EAAE,qBAAqB,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IACvR,KAAK,CAAC,YAAY,CAAC,EAAU,EAAE,KAAa,IAAmB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC,CAAC,MAAM,cAAc,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,SAAS,EAAE,qBAAqB,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IACtS,KAAK,CAAC,QAAQ,CAAC,EAAU,EAAE,IAAY,IAAqB,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;IAChK,KAAK,CAAC,gBAAgB,CAAC,EAAU,EAAE,MAAc,EAAE,IAAY,IAAqB,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC,CAAC,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,GAAG,MAAM,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1S,KAAK,CAAC,SAAS,CAAC,EAAU,EAAE,IAAY,EAAE,IAAyB,IAAmB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3b,KAAK,CAAC,MAAM,CAAC,EAAU,IAAqB,OAAO,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE,gBAAgB,EAAE,uBAAuB,CAAC,CAAC,CAAC,CAAC,CAAC;IACvI,KAAK,CAAC,mBAAmB,KAAsB,MAAM,UAAU,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC,QAAQ,EAAE,gBAAgB,EAAE,uBAAuB,CAAC,CAAC,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC7e,KAAK,CAAC,OAAO,CAAC,EAAU,IAAmB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,UAAU,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,UAAU,EAAE,CAAC,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5oB,KAAK,CAAC,gBAAgB,KAAsB,MAAM,UAAU,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,UAAU,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,OAAO,GAAG,CAAC,CAAC,CAAC,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QAAC,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,IAAI;YAAE,SAAS;QAAC,MAAM,GAAG,CAAC,UAAU,EAAE,CAAC,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,KAAK,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAAC,MAAM,EAAE,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAAC,OAAO,IAAI,CAAC,CAAC;IAAC,CAAC,CAAC,MAAM,GAAG,CAAC,UAAU,EAAE,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,CAAC;IACp3B,OAAO,CAAC,EAAU,IAA2B,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,OAAO,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,CAAC;IACzL,kBAAkB,CAAC,IAAY,IAAU,IAAI,CAAC,uDAAuD,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC,CAAC,CAAC;CAC9N"}
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@probemap/experiment-runner",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "exports": {
6
+ ".": {
7
+ "types": "./dist/index.d.ts",
8
+ "import": "./dist/index.js"
9
+ }
10
+ },
11
+ "files": [
12
+ "dist"
13
+ ],
14
+ "publishConfig": {
15
+ "access": "public",
16
+ "provenance": true
17
+ },
18
+ "dependencies": {
19
+ "@probemap/change-history": "0.1.0",
20
+ "@probemap/shared": "0.1.0"
21
+ },
22
+ "devDependencies": {
23
+ "@types/node": "25.5.0",
24
+ "vitest": "4.1.10"
25
+ },
26
+ "scripts": {
27
+ "build": "tsc -p tsconfig.json",
28
+ "typecheck": "tsc -p tsconfig.json --noEmit",
29
+ "test": "vitest run --passWithNoTests"
30
+ }
31
+ }