@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.
- package/dist/algorithm-handlers.d.ts +55 -0
- package/dist/algorithm-handlers.d.ts.map +1 -0
- package/dist/algorithm-handlers.js +56 -0
- package/dist/algorithm-handlers.js.map +1 -0
- package/dist/algorithms.d.ts +17 -0
- package/dist/algorithms.d.ts.map +1 -0
- package/dist/algorithms.js +42 -0
- package/dist/algorithms.js.map +1 -0
- package/dist/command.d.ts +11 -0
- package/dist/command.d.ts.map +1 -0
- package/dist/command.js +37 -0
- package/dist/command.js.map +1 -0
- package/dist/execute.d.ts +49 -0
- package/dist/execute.d.ts.map +1 -0
- package/dist/execute.js +159 -0
- package/dist/execute.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/oracle.d.ts +10 -0
- package/dist/oracle.d.ts.map +1 -0
- package/dist/oracle.js +3 -0
- package/dist/oracle.js.map +1 -0
- package/dist/variant-applier.d.ts +23 -0
- package/dist/variant-applier.d.ts.map +1 -0
- package/dist/variant-applier.js +184 -0
- package/dist/variant-applier.js.map +1 -0
- package/dist/worktree.d.ts +38 -0
- package/dist/worktree.d.ts.map +1 -0
- package/dist/worktree.js +95 -0
- package/dist/worktree.js.map +1 -0
- package/package.json +31 -0
|
@@ -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"}
|
package/dist/command.js
ADDED
|
@@ -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"}
|
package/dist/execute.js
ADDED
|
@@ -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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"}
|
package/dist/index.d.ts
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.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"}
|
package/dist/oracle.d.ts
ADDED
|
@@ -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"}
|
package/dist/worktree.js
ADDED
|
@@ -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":"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"}
|
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
|
+
}
|