harnery 0.25.0 → 0.27.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/commands/harness.d.ts.map +1 -1
- package/dist/commands/harness.js +12 -2
- package/dist/commands/workflow.d.ts.map +1 -1
- package/dist/commands/workflow.js +64 -0
- package/dist/core/harnesses/attest-projection.d.ts +44 -0
- package/dist/core/harnesses/attest-projection.d.ts.map +1 -0
- package/dist/core/harnesses/attest-projection.js +113 -0
- package/dist/core/harnesses/attest.d.ts +14 -0
- package/dist/core/harnesses/attest.d.ts.map +1 -1
- package/dist/core/harnesses/attest.js +27 -4
- package/dist/core/harnesses/attestation.d.ts +10 -3
- package/dist/core/harnesses/attestation.d.ts.map +1 -1
- package/dist/core/harnesses/attestation.js +13 -4
- package/dist/core/harnesses/bench.d.ts +3 -0
- package/dist/core/harnesses/bench.d.ts.map +1 -1
- package/dist/core/harnesses/bench.js +16 -1
- package/dist/core/harnesses/profiles.d.ts +13 -6
- package/dist/core/harnesses/profiles.d.ts.map +1 -1
- package/dist/core/harnesses/profiles.js +12 -3
- package/dist/core/harnesses/types.d.ts +14 -1
- package/dist/core/harnesses/types.d.ts.map +1 -1
- package/dist/core/harnesses/types.js +1 -0
- package/dist/core/workflow/engine.d.ts.map +1 -1
- package/dist/core/workflow/engine.js +41 -0
- package/dist/core/workflow/index.d.ts +1 -1
- package/dist/core/workflow/index.d.ts.map +1 -1
- package/dist/core/workflow/index.js +1 -1
- package/dist/core/workflow/proof.d.ts +3 -1
- package/dist/core/workflow/proof.d.ts.map +1 -1
- package/dist/core/workflow/proof.js +1 -0
- package/dist/core/workflow/sandbox-projection.d.ts +57 -0
- package/dist/core/workflow/sandbox-projection.d.ts.map +1 -0
- package/dist/core/workflow/sandbox-projection.js +95 -0
- package/dist/core/workflow/spawn-claude.d.ts.map +1 -1
- package/dist/core/workflow/spawn-claude.js +8 -2
- package/dist/core/workflow/spawn-codex.d.ts.map +1 -1
- package/dist/core/workflow/spawn-codex.js +12 -3
- package/dist/core/workflow/spawn-cursor.d.ts.map +1 -1
- package/dist/core/workflow/spawn-cursor.js +8 -2
- package/dist/core/workflow/spawn-failure.d.ts +18 -0
- package/dist/core/workflow/spawn-failure.d.ts.map +1 -0
- package/dist/core/workflow/spawn-failure.js +24 -0
- package/dist/core/workflow/types.d.ts +51 -0
- package/dist/core/workflow/types.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/index.d.ts +2 -0
- package/dist/core/workflow/workspaces/index.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/index.js +1 -0
- package/dist/core/workflow/workspaces/inspect.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/inspect.js +14 -0
- package/dist/core/workflow/workspaces/reclaim.d.ts +50 -0
- package/dist/core/workflow/workspaces/reclaim.d.ts.map +1 -0
- package/dist/core/workflow/workspaces/reclaim.js +88 -0
- package/dist/lib/tunnel/error-page.d.ts +15 -0
- package/dist/lib/tunnel/error-page.d.ts.map +1 -0
- package/dist/lib/tunnel/error-page.js +98 -0
- package/dist/lib/tunnel/gate.d.ts +1 -12
- package/dist/lib/tunnel/gate.d.ts.map +1 -1
- package/dist/lib/tunnel/gate.js +59 -4
- package/package.json +4 -2
- package/src/commands/harness.ts +20 -2
- package/src/commands/workflow.ts +74 -0
- package/src/core/harnesses/attest-projection.ts +151 -0
- package/src/core/harnesses/attest.ts +45 -4
- package/src/core/harnesses/attestation.ts +27 -3
- package/src/core/harnesses/bench.ts +22 -1
- package/src/core/harnesses/profiles.ts +14 -3
- package/src/core/harnesses/types.ts +15 -0
- package/src/core/workflow/engine.ts +58 -0
- package/src/core/workflow/index.ts +1 -0
- package/src/core/workflow/proof.ts +4 -0
- package/src/core/workflow/sandbox-projection.ts +150 -0
- package/src/core/workflow/spawn-claude.ts +12 -2
- package/src/core/workflow/spawn-codex.ts +19 -3
- package/src/core/workflow/spawn-cursor.ts +12 -2
- package/src/core/workflow/spawn-failure.ts +28 -0
- package/src/core/workflow/types.ts +54 -0
- package/src/core/workflow/workspaces/index.ts +2 -0
- package/src/core/workflow/workspaces/inspect.ts +15 -0
- package/src/core/workflow/workspaces/reclaim.ts +109 -0
- package/src/lib/tunnel/error-page.ts +114 -0
- package/src/lib/tunnel/gate.ts +66 -3
|
@@ -13,6 +13,7 @@ function capabilities(overrides) {
|
|
|
13
13
|
cost: unsupported(),
|
|
14
14
|
toolEvidence: unsupported("The final-result adapter does not retain tool events."),
|
|
15
15
|
policyMapping: unsupported("No ALLOW/DENY/ASK translation at the workflow boundary."),
|
|
16
|
+
filesystemPolicyProjection: unsupported("The adapter declares no sandbox projection."),
|
|
16
17
|
interruption: partial("Timeout kills the subprocess; no caller-driven interrupt handle."),
|
|
17
18
|
streaming: unsupported("Workflow children return one normalized final result."),
|
|
18
19
|
steering: unsupported("One prompt is fixed at subprocess launch."),
|
|
@@ -39,7 +40,7 @@ export const BUILTIN_HARNESS_PROFILES = {
|
|
|
39
40
|
authModel: "own-auth",
|
|
40
41
|
modelFamily: "claude",
|
|
41
42
|
effortValues: ["low", "medium", "high", "xhigh", "max"],
|
|
42
|
-
verified: { date: "2026-07-
|
|
43
|
+
verified: { date: "2026-07-25", version: "2.1.197 (Claude Code)" },
|
|
43
44
|
capabilities: capabilities({
|
|
44
45
|
effortSelection: supported("Mapped to `--effort <level>`."),
|
|
45
46
|
maxTurns: supported("Mapped to `--max-turns <n>`."),
|
|
@@ -61,9 +62,17 @@ export const BUILTIN_HARNESS_PROFILES = {
|
|
|
61
62
|
authModel: "own-auth",
|
|
62
63
|
modelFamily: "gpt",
|
|
63
64
|
effortValues: ["none", "minimal", "low", "medium", "high", "xhigh"],
|
|
64
|
-
verified: { date: "2026-07-
|
|
65
|
+
verified: { date: "2026-07-25", version: "codex-cli 0.144.5" },
|
|
66
|
+
// Verified against codex-cli 0.144.5: `--sandbox <mode>` plus
|
|
67
|
+
// `sandbox_workspace_write.writable_roots`. Without the writable-root entry
|
|
68
|
+
// a workspace-write child still cannot write a repository's .git directory.
|
|
69
|
+
sandboxProjection: {
|
|
70
|
+
modes: { "read-only": "read-only", "workspace-write": "workspace-write" },
|
|
71
|
+
writableRoots: true,
|
|
72
|
+
},
|
|
65
73
|
capabilities: capabilities({
|
|
66
74
|
effortSelection: supported('Mapped to `-c model_reasoning_effort="<level>"`.'),
|
|
75
|
+
filesystemPolicyProjection: supported("Mode renders to --sandbox; writable roots to sandbox_workspace_write.writable_roots."),
|
|
67
76
|
maxTurns: unsupported("codex exec exposes no turn-ceiling flag."),
|
|
68
77
|
sessionId: unsupported("--output-last-message carries no session id."),
|
|
69
78
|
cost: unsupported("The final-message path carries no usage or cost."),
|
|
@@ -83,7 +92,7 @@ export const BUILTIN_HARNESS_PROFILES = {
|
|
|
83
92
|
authModel: "own-auth",
|
|
84
93
|
modelFamily: "multi",
|
|
85
94
|
effortValues: [],
|
|
86
|
-
verified: { date: "2026-07-
|
|
95
|
+
verified: { date: "2026-07-25", version: "2026.07.23-e383d2b" },
|
|
87
96
|
capabilities: capabilities({
|
|
88
97
|
effortSelection: unsupported("Cursor embeds effort in some parameterized model ids; Harnery does not rewrite model ids."),
|
|
89
98
|
maxTurns: unsupported("cursor-agent exposes no turn-ceiling flag."),
|
|
@@ -3,7 +3,7 @@ import type { Spawner, SpawnRequest, SpawnResult } from "../workflow/types.js";
|
|
|
3
3
|
* repeated through closed unions in every consumer. */
|
|
4
4
|
export type HarnessId = string;
|
|
5
5
|
export type CapabilitySupport = "supported" | "partial" | "unsupported" | "unknown";
|
|
6
|
-
export declare const HARNESS_CAPABILITY_DIMENSIONS: readonly ["invocation", "modelSelection", "effortSelection", "maxTurns", "finalResult", "sessionId", "cost", "toolEvidence", "policyMapping", "interruption", "streaming", "steering", "resume", "images", "contextTelemetry", "preCompactionSignal", "postCompactionSignal", "compaction"];
|
|
6
|
+
export declare const HARNESS_CAPABILITY_DIMENSIONS: readonly ["invocation", "modelSelection", "effortSelection", "maxTurns", "finalResult", "sessionId", "cost", "toolEvidence", "policyMapping", "filesystemPolicyProjection", "interruption", "streaming", "steering", "resume", "images", "contextTelemetry", "preCompactionSignal", "postCompactionSignal", "compaction"];
|
|
7
7
|
export type HarnessCapabilityDimension = (typeof HARNESS_CAPABILITY_DIMENSIONS)[number];
|
|
8
8
|
export interface CapabilityClaim {
|
|
9
9
|
support: CapabilitySupport;
|
|
@@ -12,6 +12,16 @@ export interface CapabilityClaim {
|
|
|
12
12
|
note?: string;
|
|
13
13
|
}
|
|
14
14
|
export type HarnessCapabilities = Record<HarnessCapabilityDimension, CapabilityClaim>;
|
|
15
|
+
/** What one harness can represent of a filesystem-policy projection
|
|
16
|
+
* (ADR 0039). `null` means the harness does not distinguish that, which is a
|
|
17
|
+
* fact about the harness rather than something to paper over: a projection the
|
|
18
|
+
* adapter would silently drop must be refused instead. */
|
|
19
|
+
export interface HarnessSandboxProjection {
|
|
20
|
+
/** Native representation per canonical mode, or null when unrepresentable. */
|
|
21
|
+
modes: Record<"read-only" | "workspace-write", string | null>;
|
|
22
|
+
/** Whether the harness accepts an explicit writable-root set. */
|
|
23
|
+
writableRoots: boolean;
|
|
24
|
+
}
|
|
15
25
|
export interface HarnessProfile {
|
|
16
26
|
id: HarnessId;
|
|
17
27
|
displayName: string;
|
|
@@ -29,6 +39,9 @@ export interface HarnessProfile {
|
|
|
29
39
|
date: string;
|
|
30
40
|
version: string;
|
|
31
41
|
};
|
|
42
|
+
/** How this adapter projects host filesystem policy into the vendor's own
|
|
43
|
+
* sandbox (ADR 0039). Absent means it cannot project any of it. */
|
|
44
|
+
sandboxProjection?: HarnessSandboxProjection;
|
|
32
45
|
}
|
|
33
46
|
/** Fully planned child invocation. `resultFile` is used by adapters such as
|
|
34
47
|
* Codex that deliver the authoritative final answer out-of-band. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/harnesses/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAE/E;uDACuD;AACvD,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC;AAE/B,MAAM,MAAM,iBAAiB,GAAG,WAAW,GAAG,SAAS,GAAG,aAAa,GAAG,SAAS,CAAC;AAEpF,eAAO,MAAM,6BAA6B,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/harnesses/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAE/E;uDACuD;AACvD,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC;AAE/B,MAAM,MAAM,iBAAiB,GAAG,WAAW,GAAG,SAAS,GAAG,aAAa,GAAG,SAAS,CAAC;AAEpF,eAAO,MAAM,6BAA6B,2TAoBhC,CAAC;AAEX,MAAM,MAAM,0BAA0B,GAAG,CAAC,OAAO,6BAA6B,CAAC,CAAC,MAAM,CAAC,CAAC;AAExF,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,iBAAiB,CAAC;IAC3B;iFAC6E;IAC7E,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC,0BAA0B,EAAE,eAAe,CAAC,CAAC;AAEtF;;;0DAG0D;AAC1D,MAAM,WAAW,wBAAwB;IACvC,8EAA8E;IAC9E,KAAK,EAAE,MAAM,CAAC,WAAW,GAAG,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;IAC9D,iEAAiE;IACjE,aAAa,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,SAAS,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,gBAAgB,CAAC;IAClC,SAAS,EAAE,UAAU,CAAC;IACtB,WAAW,EAAE,QAAQ,GAAG,KAAK,GAAG,OAAO,CAAC;IACxC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,YAAY,EAAE,mBAAmB,CAAC;IAClC,2EAA2E;IAC3E,QAAQ,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C;uEACmE;IACnE,iBAAiB,CAAC,EAAE,wBAAwB,CAAC;CAC9C;AAED;oEACoE;AACpE,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,yEAAyE;AACzE,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,gBAAgB,CAAC;IACtB,QAAQ,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,GAAG,MAAM,CAAC,GAAG;QAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAED;;wDAEwD;AACxD,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,cAAc,CAAC;IACxB,KAAK,EAAE,OAAO,CAAC;IACf,eAAe,EAAE,CAAC,OAAO,EAAE,YAAY,EAAE,UAAU,CAAC,EAAE,MAAM,KAAK,iBAAiB,CAAC;IACnF,eAAe,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,WAAW,CAAC;IACxD,OAAO,EAAE,mBAAmB,CAAC;CAC9B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAwCH,OAAO,KAAK,EAEV,UAAU,EAGV,SAAS,EAYV,MAAM,YAAY,CAAC;AAwCpB,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;gBAEf,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAM/E;AAED,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;gBAEjB,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;CAOpF;AAED,wBAAsB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,CA6E1F"}
|
|
@@ -36,6 +36,7 @@ import { probeBilling } from "./billing.js";
|
|
|
36
36
|
import { stableDigest } from "./durable-record.js";
|
|
37
37
|
import { buildWorkflowProof, createEvidenceRecord, digestResult, normalizeWorkflowMeta, writeWorkflowProof, } from "./proof.js";
|
|
38
38
|
import { acquireWorkflowResumeLease, assertWorkflowRunResumable, assertWorkflowScriptUnchanged, workflowScriptDigest, writeWorkflowRunManifest, } from "./run-state.js";
|
|
39
|
+
import { assertProjectionWithinWorkspace, resolveGitGrantRoots } from "./sandbox-projection.js";
|
|
39
40
|
import { normalizeWorkflowSpecialists, resolveSpecialistAssignment } from "./specialists.js";
|
|
40
41
|
import { WORKFLOW_PROOF_SCHEMA_VERSION } from "./types.js";
|
|
41
42
|
import { parseStageOutput, validateAgainstSchema } from "./validate.js";
|
|
@@ -43,6 +44,18 @@ import { freezeWorkflowWorkContext } from "./work-context.js";
|
|
|
43
44
|
import { attestTerminal, attestWorkspaceFailure, resolveWorkspaceBinding, } from "./workspaces/execution.js";
|
|
44
45
|
import { appendWorkflowJournalEvent } from "./workspaces/state.js";
|
|
45
46
|
import { isWorkspaceAttestation } from "./workspaces/validate.js";
|
|
47
|
+
/** Proof record of the filesystem projection a run applied (ADR 0039/0040).
|
|
48
|
+
* Absent when no policy was in force, which reads as "no projection applied"
|
|
49
|
+
* rather than "an empty one". */
|
|
50
|
+
function sandboxProjectionEvidence(policy, gitWrite) {
|
|
51
|
+
if (!policy)
|
|
52
|
+
return undefined;
|
|
53
|
+
return {
|
|
54
|
+
mode: policy.mode,
|
|
55
|
+
writable_roots: [...(policy.writableRoots ?? [])],
|
|
56
|
+
git_grant: gitWrite,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
46
59
|
const DEFAULT_MAX_AGENTS = 50;
|
|
47
60
|
const DEFAULT_CONCURRENCY = 4;
|
|
48
61
|
const DEFAULT_MAX_ATTEMPTS = 2;
|
|
@@ -246,6 +259,7 @@ async function executeWorkflow(scriptPath, absScript, opts, resumeState, workCon
|
|
|
246
259
|
evidence: [],
|
|
247
260
|
harnessEvidence: opts.harnessEvidence,
|
|
248
261
|
harnessAttestations: opts.harnessAttestations,
|
|
262
|
+
sandboxProjection: sandboxProjectionEvidence(opts.filesystemPolicy, opts.gitWrite ?? "none"),
|
|
249
263
|
policy: policy
|
|
250
264
|
? {
|
|
251
265
|
config: policy,
|
|
@@ -267,6 +281,30 @@ async function executeWorkflow(scriptPath, absScript, opts, resumeState, workCon
|
|
|
267
281
|
}
|
|
268
282
|
const effectiveIsolation = workspaceFallback?.effective_isolation ?? isolation;
|
|
269
283
|
const executionCwd = workspaceBinding?.active_root ?? cwd;
|
|
284
|
+
// Validate the projection once, before any child launches, so a policy that
|
|
285
|
+
// would reach outside the provider's validated root fails the run rather than
|
|
286
|
+
// silently widening one child's write access (ADR 0039).
|
|
287
|
+
const requestedPolicy = opts.filesystemPolicy;
|
|
288
|
+
if (requestedPolicy?.writableRoots?.length) {
|
|
289
|
+
if (!workspaceBinding) {
|
|
290
|
+
throw new Error("a filesystem policy with writable roots requires an isolated workspace; none is bound to this run");
|
|
291
|
+
}
|
|
292
|
+
assertProjectionWithinWorkspace("workflow", workspaceBinding.writable_root.realpath, requestedPolicy.writableRoots);
|
|
293
|
+
}
|
|
294
|
+
// The Git grant is resolved after containment on purpose: caller-supplied
|
|
295
|
+
// roots must stay inside the workspace, while these come from the verified
|
|
296
|
+
// binding and are the one sanctioned way out of it (ADR 0040).
|
|
297
|
+
const gitWrite = opts.gitWrite ?? "none";
|
|
298
|
+
const gitGrantRoots = resolveGitGrantRoots(gitWrite, workspaceBinding);
|
|
299
|
+
if (gitGrantRoots.length > 0 && !requestedPolicy) {
|
|
300
|
+
throw new Error(`gitWrite "${gitWrite}" has no effect without a filesystem policy to carry it; set filesystemPolicy or drop the grant`);
|
|
301
|
+
}
|
|
302
|
+
const filesystemPolicy = requestedPolicy
|
|
303
|
+
? {
|
|
304
|
+
...requestedPolicy,
|
|
305
|
+
writableRoots: [...(requestedPolicy.writableRoots ?? []), ...gitGrantRoots],
|
|
306
|
+
}
|
|
307
|
+
: undefined;
|
|
270
308
|
const executionRepoBefore = resumeState?.manifest.repository_before ?? snapshotRepo(executionCwd);
|
|
271
309
|
if (!resumeState) {
|
|
272
310
|
writeWorkflowRunManifest({
|
|
@@ -726,6 +764,7 @@ async function executeWorkflow(scriptPath, absScript, opts, resumeState, workCon
|
|
|
726
764
|
cwd: executionCwd,
|
|
727
765
|
runId,
|
|
728
766
|
subscriptionOnly,
|
|
767
|
+
filesystemPolicy,
|
|
729
768
|
});
|
|
730
769
|
agentProof.attempts = attempt;
|
|
731
770
|
agentProof.duration_ms += last.durationMs;
|
|
@@ -927,6 +966,7 @@ async function executeWorkflow(scriptPath, absScript, opts, resumeState, workCon
|
|
|
927
966
|
evidence: evidenceRecords,
|
|
928
967
|
harnessEvidence: opts.harnessEvidence,
|
|
929
968
|
harnessAttestations: opts.harnessAttestations,
|
|
969
|
+
sandboxProjection: sandboxProjectionEvidence(filesystemPolicy, gitWrite),
|
|
930
970
|
policy: policy
|
|
931
971
|
? {
|
|
932
972
|
config: policy,
|
|
@@ -1005,6 +1045,7 @@ async function executeWorkflow(scriptPath, absScript, opts, resumeState, workCon
|
|
|
1005
1045
|
evidence: evidenceRecords,
|
|
1006
1046
|
harnessEvidence: opts.harnessEvidence,
|
|
1007
1047
|
harnessAttestations: opts.harnessAttestations,
|
|
1048
|
+
sandboxProjection: sandboxProjectionEvidence(filesystemPolicy, gitWrite),
|
|
1008
1049
|
policy: policy
|
|
1009
1050
|
? {
|
|
1010
1051
|
config: policy,
|
|
@@ -8,5 +8,5 @@ export { acquireWorkflowResumeLease, assertWorkflowRunResumable, assertWorkflowS
|
|
|
8
8
|
export type { AcceptanceCriterion, AcceptanceResult, AcceptanceStatus, AcceptanceSummary, AgentOpts, EngineOpts, EvidenceKind, EvidenceSource, EvidenceStatus, HarnessEvidenceCapability, HarnessEvidenceCoverage, HarnessName, ResultDigest, RunReport, Spawner, SpawnRequest, SpawnResult, StageSchema, WorkflowAgentProof, WorkflowApprovalMode, WorkflowAttemptContext, WorkflowAttemptFailureCause, WorkflowAttemptPriorContext, WorkflowAttemptUnresolvedCriterion, WorkflowContext, WorkflowEvidenceInput, WorkflowEvidenceRecord, WorkflowMeta, WorkflowModule, WorkflowPolicyProof, WorkflowProof, WorkflowProofUnknown, WorkflowRepoEvidence, WorkflowRepoSnapshot, WorkflowRunStatus, WorkflowSpecialistProfile, WorkflowWorkContext, } from "./types.js";
|
|
9
9
|
export { WORKFLOW_ATTEMPT_CONTEXT_SCHEMA_VERSION, WORKFLOW_PROOF_SCHEMA_VERSION, WORKFLOW_WORK_CONTEXT_SCHEMA_VERSION, } from "./types.js";
|
|
10
10
|
export type { ApplyIntegrationInput, AuthorizedIntegrationPlan, AuthorizedProviderIntegrationInput, CancelWorkspaceInput, CleanupWorkspaceInput, FilesystemIdentity, IntegrationApplyAttempt, IntegrationApplyReceipt, IntegrationAuthorization, IntegrationPlan, IntegrationReviewRecord, IntegrationTarget, LocalGitWorktreeProviderOptions, PrepareIntegrationInput, ProviderIntegrationInput, ProviderIntegrationPreview, ProviderIntegrationResult, ProviderUnknown, ProviderUnsupportedReason, RepositoryBinding, ValidatedFilesystemPath, WorkflowWorkspaceInspection, WorkflowWorkspaceSelection, WorkflowWorkspaceStatus, WorkflowWorkspaceVerification, WorkspaceAllocationRequest, WorkspaceAttestation, WorkspaceBinding, WorkspaceBoundExecutionEvidence, WorkspaceCancellationReceipt, WorkspaceCancellationResult, WorkspaceCleanupAttempt, WorkspaceCleanupIntent, WorkspaceCleanupMode, WorkspaceCleanupReceipt, WorkspaceCleanupResult, WorkspaceCompatibilityExecutionEvidence, WorkspaceExecutionEvidence, WorkspaceIntegrationState, WorkspaceIsolation, WorkspaceLifecycleProjection, WorkspaceLifecycleProjectionInput, WorkspaceLifecycleState, WorkspaceObservation, WorkspaceOwner, WorkspaceProbeInput, WorkspaceProbeResult, WorkspaceProofOutcome, WorkspaceProvider, WorkspaceProviderCapabilities, WorkspaceProviderRef, WorkspaceResourceState, WorkspaceUnsupportedExecutionEvidence, } from "./workspaces/index.js";
|
|
11
|
-
export { applyIntegration, assertWorkspaceLifecycleTransition, cancelWorkspace, cleanupWorkspace, createLocalGitWorktreeProvider, deriveWorkspaceLifecycle, IntegrationPrepareParkedError, inspectWorkflowWorkspace, isWorkspaceLifecycleState, listWorkflowWorkspaceInspections, prepareIntegration, probeLocalGitWorktreeProvider, readWorkflowWorkspaceStatus, renderWorkflowWorkspaceStatus, validateProviderEventChain, WORKSPACE_BINDING_SCHEMA_VERSION, WORKSPACE_RECEIPT_SCHEMA_VERSION, } from "./workspaces/index.js";
|
|
11
|
+
export { applyIntegration, assertWorkspaceLifecycleTransition, cancelWorkspace, cleanupWorkspace, createLocalGitWorktreeProvider, deriveWorkspaceLifecycle, IntegrationPrepareParkedError, inspectWorkflowWorkspace, isWorkspaceLifecycleState, listWorkflowWorkspaceInspections, prepareIntegration, prepareReclaim, probeLocalGitWorktreeProvider, readWorkflowWorkspaceStatus, renderWorkflowWorkspaceStatus, validateProviderEventChain, WORKSPACE_BINDING_SCHEMA_VERSION, WORKSPACE_RECEIPT_SCHEMA_VERSION, } from "./workspaces/index.js";
|
|
12
12
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,4 +4,4 @@ export { runWorkflow, WorkflowParkedError, WorkflowRunError } from "./engine.js"
|
|
|
4
4
|
export { buildWorkflowProof, createEvidenceRecord, digestResult, normalizeWorkflowMeta, readWorkflowProof, renderWorkflowProof, rollupAcceptance, writeWorkflowProof, } from "./proof.js";
|
|
5
5
|
export { acquireWorkflowResumeLease, assertWorkflowRunResumable, assertWorkflowScriptUnchanged, readWorkflowRunManifest, WORKFLOW_RUN_MANIFEST_SCHEMA_VERSION, workflowRunManifestPath, workflowScriptDigest, writeWorkflowRunManifest, } from "./run-state.js";
|
|
6
6
|
export { WORKFLOW_ATTEMPT_CONTEXT_SCHEMA_VERSION, WORKFLOW_PROOF_SCHEMA_VERSION, WORKFLOW_WORK_CONTEXT_SCHEMA_VERSION, } from "./types.js";
|
|
7
|
-
export { applyIntegration, assertWorkspaceLifecycleTransition, cancelWorkspace, cleanupWorkspace, createLocalGitWorktreeProvider, deriveWorkspaceLifecycle, IntegrationPrepareParkedError, inspectWorkflowWorkspace, isWorkspaceLifecycleState, listWorkflowWorkspaceInspections, prepareIntegration, probeLocalGitWorktreeProvider, readWorkflowWorkspaceStatus, renderWorkflowWorkspaceStatus, validateProviderEventChain, WORKSPACE_BINDING_SCHEMA_VERSION, WORKSPACE_RECEIPT_SCHEMA_VERSION, } from "./workspaces/index.js";
|
|
7
|
+
export { applyIntegration, assertWorkspaceLifecycleTransition, cancelWorkspace, cleanupWorkspace, createLocalGitWorktreeProvider, deriveWorkspaceLifecycle, IntegrationPrepareParkedError, inspectWorkflowWorkspace, isWorkspaceLifecycleState, listWorkflowWorkspaceInspections, prepareIntegration, prepareReclaim, probeLocalGitWorktreeProvider, readWorkflowWorkspaceStatus, renderWorkflowWorkspaceStatus, validateProviderEventChain, WORKSPACE_BINDING_SCHEMA_VERSION, WORKSPACE_RECEIPT_SCHEMA_VERSION, } from "./workspaces/index.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { RepoSnapshot } from "../context/index.js";
|
|
2
2
|
import type { NormalizedPolicy, PolicyDecision, PolicyIsolation, PolicyNetworkAccess } from "../policy/index.js";
|
|
3
|
-
import type { AcceptanceCriterion, AcceptanceResult, AcceptanceSummary, HarnessAttestationCitation, HarnessEvidenceCapability, ResultDigest, WorkflowAgentProof, WorkflowAttemptContext, WorkflowEvidenceInput, WorkflowEvidenceRecord, WorkflowMeta, WorkflowProof, WorkflowWorkContext } from "./types.js";
|
|
3
|
+
import type { AcceptanceCriterion, AcceptanceResult, AcceptanceSummary, HarnessAttestationCitation, HarnessEvidenceCapability, ResultDigest, WorkflowAgentProof, WorkflowAttemptContext, WorkflowEvidenceInput, WorkflowEvidenceRecord, WorkflowMeta, WorkflowProof, WorkflowSandboxProjectionEvidence, WorkflowWorkContext } from "./types.js";
|
|
4
4
|
import type { WorkspaceAttestation, WorkspaceBinding, WorkspaceUnsupportedExecutionEvidence } from "./workspaces/index.js";
|
|
5
5
|
export interface NormalizedWorkflowMeta {
|
|
6
6
|
name: string;
|
|
@@ -24,6 +24,8 @@ export interface BuildWorkflowProofInput {
|
|
|
24
24
|
agents: WorkflowAgentProof[];
|
|
25
25
|
evidence: WorkflowEvidenceRecord[];
|
|
26
26
|
harnessEvidence?: Readonly<Record<string, HarnessEvidenceCapability | undefined>>;
|
|
27
|
+
/** Filesystem policy actually projected into children (ADR 0039). */
|
|
28
|
+
sandboxProjection?: WorkflowSandboxProjectionEvidence;
|
|
27
29
|
/** Live attestations backing each harness's claims (ADR 0038). Injected by
|
|
28
30
|
* the caller so proof stays free of filesystem lookups. */
|
|
29
31
|
harnessAttestations?: Readonly<Record<string, HarnessAttestationCitation | undefined>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proof.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/proof.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"proof.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/proof.ts"],"names":[],"mappings":"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"}
|
|
@@ -146,6 +146,7 @@ export function buildWorkflowProof(input) {
|
|
|
146
146
|
? buildExecutionEvidence(input.status, input.workspaceBinding, input.workspaceAttestation)
|
|
147
147
|
: input.workspaceFallback,
|
|
148
148
|
repository,
|
|
149
|
+
...(input.sandboxProjection ? { sandbox_projection: input.sandboxProjection } : {}),
|
|
149
150
|
harnesses,
|
|
150
151
|
unknowns,
|
|
151
152
|
integrity: {
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project the host's filesystem policy into a harness's own vendor sandbox
|
|
3
|
+
* (ADR 0039).
|
|
4
|
+
*
|
|
5
|
+
* Harnery decides where a workflow child may write. Until this existed it never
|
|
6
|
+
* told the child, so a child working in a provider-owned Git worktree could
|
|
7
|
+
* edit files and could not commit: the vendor excludes a repository's
|
|
8
|
+
* administrative directory from its writable set by policy, and Harnery had no
|
|
9
|
+
* way to name it as an exception.
|
|
10
|
+
*
|
|
11
|
+
* The one rule that matters here is that a projection an adapter cannot
|
|
12
|
+
* represent is refused before launch. Passing a policy that gets silently
|
|
13
|
+
* dropped would leave an operator believing a child was constrained when it was
|
|
14
|
+
* not, which is worse than refusing and worse than never offering the feature.
|
|
15
|
+
*/
|
|
16
|
+
import type { HarnessSandboxProjection } from "../harnesses/types.js";
|
|
17
|
+
import type { GitAdministrativeGrant, SpawnFilesystemPolicy } from "./types.js";
|
|
18
|
+
import type { WorkspaceBinding } from "./workspaces/types.js";
|
|
19
|
+
export declare class SandboxProjectionError extends Error {
|
|
20
|
+
readonly harness: string;
|
|
21
|
+
readonly reason: "mode_unrepresentable" | "writable_roots_unrepresentable" | "no_projection" | "writable_root_escapes_workspace" | "git_grant_unavailable";
|
|
22
|
+
constructor(harness: string, reason: SandboxProjectionError["reason"], message: string);
|
|
23
|
+
}
|
|
24
|
+
export interface ResolvedSandboxProjection {
|
|
25
|
+
/** Vendor-native name for the requested mode. */
|
|
26
|
+
nativeMode: string;
|
|
27
|
+
writableRoots: readonly string[];
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Resolve a requested policy against what the adapter declares it can carry.
|
|
31
|
+
* Throws rather than degrading; see the module note.
|
|
32
|
+
*/
|
|
33
|
+
export declare function resolveSandboxProjection(harness: string, declaration: HarnessSandboxProjection | undefined, policy: SpawnFilesystemPolicy): ResolvedSandboxProjection;
|
|
34
|
+
/**
|
|
35
|
+
* Refuse a projection that would grant write access outside the root the
|
|
36
|
+
* workspace provider already validated (ADR 0039).
|
|
37
|
+
*
|
|
38
|
+
* The renderer alone cannot do this: it never sees the binding. Granting a path
|
|
39
|
+
* the provider never sanctioned would let a projection quietly widen the blast
|
|
40
|
+
* radius of a run that the workspace lifecycle believes it has contained.
|
|
41
|
+
*/
|
|
42
|
+
export declare function assertProjectionWithinWorkspace(harness: string, allowedRootRealpath: string, writableRoots: readonly string[]): void;
|
|
43
|
+
/**
|
|
44
|
+
* Resolve a named Git administrative grant into concrete writable roots
|
|
45
|
+
* (ADR 0040).
|
|
46
|
+
*
|
|
47
|
+
* These are the only paths a run may write outside its workspace, and the
|
|
48
|
+
* caller never names them: they come from the binding the provider verified.
|
|
49
|
+
* A caller-supplied path is checked by `assertProjectionWithinWorkspace` and can
|
|
50
|
+
* never reach here, so asking for the grant is the whole of the widening.
|
|
51
|
+
*
|
|
52
|
+
* In a linked worktree both halves of the administrative directory live under
|
|
53
|
+
* the source repository, and a commit needs the shared half regardless, so the
|
|
54
|
+
* grant returns both rather than pretending the private half is useful alone.
|
|
55
|
+
*/
|
|
56
|
+
export declare function resolveGitGrantRoots(grant: GitAdministrativeGrant, binding: WorkspaceBinding | undefined): readonly string[];
|
|
57
|
+
//# sourceMappingURL=sandbox-projection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox-projection.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/sandbox-projection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,KAAK,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAChF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,qBAAa,sBAAuB,SAAQ,KAAK;IAC/C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EACX,sBAAsB,GACtB,gCAAgC,GAChC,eAAe,GACf,iCAAiC,GACjC,uBAAuB,CAAC;gBAEhB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,sBAAsB,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,MAAM;CAMvF;AAED,MAAM,WAAW,yBAAyB;IACxC,iDAAiD;IACjD,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;CAClC;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,wBAAwB,GAAG,SAAS,EACjD,MAAM,EAAE,qBAAqB,GAC5B,yBAAyB,CAoC3B;AASD;;;;;;;GAOG;AACH,wBAAgB,+BAA+B,CAC7C,OAAO,EAAE,MAAM,EACf,mBAAmB,EAAE,MAAM,EAC3B,aAAa,EAAE,SAAS,MAAM,EAAE,GAC/B,IAAI,CAUN;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,sBAAsB,EAC7B,OAAO,EAAE,gBAAgB,GAAG,SAAS,GACpC,SAAS,MAAM,EAAE,CAanB"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project the host's filesystem policy into a harness's own vendor sandbox
|
|
3
|
+
* (ADR 0039).
|
|
4
|
+
*
|
|
5
|
+
* Harnery decides where a workflow child may write. Until this existed it never
|
|
6
|
+
* told the child, so a child working in a provider-owned Git worktree could
|
|
7
|
+
* edit files and could not commit: the vendor excludes a repository's
|
|
8
|
+
* administrative directory from its writable set by policy, and Harnery had no
|
|
9
|
+
* way to name it as an exception.
|
|
10
|
+
*
|
|
11
|
+
* The one rule that matters here is that a projection an adapter cannot
|
|
12
|
+
* represent is refused before launch. Passing a policy that gets silently
|
|
13
|
+
* dropped would leave an operator believing a child was constrained when it was
|
|
14
|
+
* not, which is worse than refusing and worse than never offering the feature.
|
|
15
|
+
*/
|
|
16
|
+
export class SandboxProjectionError extends Error {
|
|
17
|
+
harness;
|
|
18
|
+
reason;
|
|
19
|
+
constructor(harness, reason, message) {
|
|
20
|
+
super(message);
|
|
21
|
+
this.name = "SandboxProjectionError";
|
|
22
|
+
this.harness = harness;
|
|
23
|
+
this.reason = reason;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Resolve a requested policy against what the adapter declares it can carry.
|
|
28
|
+
* Throws rather than degrading; see the module note.
|
|
29
|
+
*/
|
|
30
|
+
export function resolveSandboxProjection(harness, declaration, policy) {
|
|
31
|
+
if (!declaration) {
|
|
32
|
+
throw new SandboxProjectionError(harness, "no_projection", `${harness} cannot project a filesystem policy into its sandbox; remove the policy or use a harness that can`);
|
|
33
|
+
}
|
|
34
|
+
const nativeMode = declaration.modes[policy.mode];
|
|
35
|
+
if (!nativeMode) {
|
|
36
|
+
throw new SandboxProjectionError(harness, "mode_unrepresentable", `${harness} does not distinguish the "${policy.mode}" filesystem mode, so it cannot be enforced`);
|
|
37
|
+
}
|
|
38
|
+
const writableRoots = policy.writableRoots ?? [];
|
|
39
|
+
if (writableRoots.length > 0 && !declaration.writableRoots) {
|
|
40
|
+
throw new SandboxProjectionError(harness, "writable_roots_unrepresentable", `${harness} does not accept an explicit writable-root set, so ${writableRoots.length} declared path(s) could not be enforced`);
|
|
41
|
+
}
|
|
42
|
+
for (const root of writableRoots) {
|
|
43
|
+
// Relative paths cannot be validated against the provider's roots and are
|
|
44
|
+
// resolved differently by every vendor, so they are refused outright.
|
|
45
|
+
if (typeof root !== "string" || !root.startsWith("/")) {
|
|
46
|
+
throw new SandboxProjectionError(harness, "writable_roots_unrepresentable", `writable root ${JSON.stringify(root)} must be an absolute path`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return { nativeMode, writableRoots };
|
|
50
|
+
}
|
|
51
|
+
/** True when `candidate` is `root` or lies beneath it, comparing whole path
|
|
52
|
+
* segments so `/a/bc` is not treated as inside `/a/b`. */
|
|
53
|
+
function isWithin(root, candidate) {
|
|
54
|
+
const normalizedRoot = root.endsWith("/") ? root.slice(0, -1) : root;
|
|
55
|
+
return candidate === normalizedRoot || candidate.startsWith(`${normalizedRoot}/`);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Refuse a projection that would grant write access outside the root the
|
|
59
|
+
* workspace provider already validated (ADR 0039).
|
|
60
|
+
*
|
|
61
|
+
* The renderer alone cannot do this: it never sees the binding. Granting a path
|
|
62
|
+
* the provider never sanctioned would let a projection quietly widen the blast
|
|
63
|
+
* radius of a run that the workspace lifecycle believes it has contained.
|
|
64
|
+
*/
|
|
65
|
+
export function assertProjectionWithinWorkspace(harness, allowedRootRealpath, writableRoots) {
|
|
66
|
+
for (const root of writableRoots) {
|
|
67
|
+
if (!isWithin(allowedRootRealpath, root)) {
|
|
68
|
+
throw new SandboxProjectionError(harness, "writable_root_escapes_workspace", `writable root ${JSON.stringify(root)} is outside the workspace root ${JSON.stringify(allowedRootRealpath)} the provider validated`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Resolve a named Git administrative grant into concrete writable roots
|
|
74
|
+
* (ADR 0040).
|
|
75
|
+
*
|
|
76
|
+
* These are the only paths a run may write outside its workspace, and the
|
|
77
|
+
* caller never names them: they come from the binding the provider verified.
|
|
78
|
+
* A caller-supplied path is checked by `assertProjectionWithinWorkspace` and can
|
|
79
|
+
* never reach here, so asking for the grant is the whole of the widening.
|
|
80
|
+
*
|
|
81
|
+
* In a linked worktree both halves of the administrative directory live under
|
|
82
|
+
* the source repository, and a commit needs the shared half regardless, so the
|
|
83
|
+
* grant returns both rather than pretending the private half is useful alone.
|
|
84
|
+
*/
|
|
85
|
+
export function resolveGitGrantRoots(grant, binding) {
|
|
86
|
+
if (grant === "none")
|
|
87
|
+
return [];
|
|
88
|
+
const repository = binding?.repository;
|
|
89
|
+
if (!repository) {
|
|
90
|
+
throw new SandboxProjectionError("workflow", "git_grant_unavailable", `gitWrite "${grant}" needs a Git repository binding; this run has ${binding ? "a workspace with no repository" : "no isolated workspace"}`);
|
|
91
|
+
}
|
|
92
|
+
// Deduplicated: a full-clone topology reports the same path for both, and a
|
|
93
|
+
// repeated writable root is noise in the rendered argv and in proof.
|
|
94
|
+
return [...new Set([repository.gitdir.realpath, repository.common_dir.realpath])];
|
|
95
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spawn-claude.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/spawn-claude.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"spawn-claude.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/spawn-claude.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAKjF,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAYrE,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,YAAY,GAAG,iBAAiB,CAsB1E;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,gBAAgB,GAAG,WAAW,CAgDxE;AAED,eAAO,MAAM,iBAAiB,EAAE,OAc/B,CAAC"}
|
|
@@ -18,11 +18,17 @@
|
|
|
18
18
|
* (stop-hook.ts), keeping heartbeats + events on.
|
|
19
19
|
*/
|
|
20
20
|
import { exec } from "../../lib/exec.js";
|
|
21
|
-
import { validateHarnessEffort } from "../harnesses/profiles.js";
|
|
21
|
+
import { builtinHarnessProfile, validateHarnessEffort } from "../harnesses/profiles.js";
|
|
22
22
|
import { buildChildEnv } from "./child-env.js";
|
|
23
23
|
import { notFoundError } from "./harnesses.js";
|
|
24
|
+
import { resolveSandboxProjection } from "./sandbox-projection.js";
|
|
25
|
+
import { vendorFailureText } from "./spawn-failure.js";
|
|
24
26
|
export function buildClaudeInvocation(req) {
|
|
25
27
|
validateHarnessEffort("claude-code", req.effort);
|
|
28
|
+
if (req.filesystemPolicy) {
|
|
29
|
+
// Declared unrepresentable: refuse rather than drop it silently (ADR 0039).
|
|
30
|
+
resolveSandboxProjection("claude-code", builtinHarnessProfile("claude-code")?.sandboxProjection, req.filesystemPolicy);
|
|
31
|
+
}
|
|
26
32
|
const argv = [
|
|
27
33
|
"claude",
|
|
28
34
|
"-p",
|
|
@@ -52,7 +58,7 @@ export function normalizeClaudeResult(raw) {
|
|
|
52
58
|
ok: false,
|
|
53
59
|
text: "",
|
|
54
60
|
durationMs: raw.durationMs,
|
|
55
|
-
error: `claude exited ${raw.exitCode}: ${(raw
|
|
61
|
+
error: `claude exited ${raw.exitCode}: ${vendorFailureText(raw)}`,
|
|
56
62
|
};
|
|
57
63
|
}
|
|
58
64
|
let envelope;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spawn-codex.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/spawn-codex.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAQH,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"spawn-codex.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/spawn-codex.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAQH,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAKjF,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAErE,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,YAAY,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,iBAAiB,CA8B9F;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,gBAAgB,GAAG,WAAW,CAiBvE;AAED,eAAO,MAAM,YAAY,EAAE,OA2B1B,CAAC"}
|
|
@@ -19,13 +19,19 @@ import { existsSync, readFileSync, rmSync } from "node:fs";
|
|
|
19
19
|
import { tmpdir } from "node:os";
|
|
20
20
|
import { join } from "node:path";
|
|
21
21
|
import { exec } from "../../lib/exec.js";
|
|
22
|
-
import { validateHarnessEffort } from "../harnesses/profiles.js";
|
|
22
|
+
import { builtinHarnessProfile, validateHarnessEffort } from "../harnesses/profiles.js";
|
|
23
23
|
import { buildChildEnv } from "./child-env.js";
|
|
24
24
|
import { notFoundError } from "./harnesses.js";
|
|
25
|
+
import { resolveSandboxProjection } from "./sandbox-projection.js";
|
|
26
|
+
import { vendorFailureText } from "./spawn-failure.js";
|
|
25
27
|
export function buildCodexInvocation(req, resultFile) {
|
|
26
28
|
validateHarnessEffort("codex", req.effort);
|
|
27
29
|
if (!resultFile)
|
|
28
30
|
throw new Error("codex adapter requires a final-message result file");
|
|
31
|
+
// Default stays workspace-write so an unprojected request is unchanged.
|
|
32
|
+
const projection = req.filesystemPolicy
|
|
33
|
+
? resolveSandboxProjection("codex", builtinHarnessProfile("codex")?.sandboxProjection, req.filesystemPolicy)
|
|
34
|
+
: undefined;
|
|
29
35
|
const argv = [
|
|
30
36
|
"codex",
|
|
31
37
|
"exec",
|
|
@@ -34,8 +40,11 @@ export function buildCodexInvocation(req, resultFile) {
|
|
|
34
40
|
resultFile,
|
|
35
41
|
"--skip-git-repo-check",
|
|
36
42
|
"--sandbox",
|
|
37
|
-
"workspace-write",
|
|
43
|
+
projection?.nativeMode ?? "workspace-write",
|
|
38
44
|
];
|
|
45
|
+
if (projection && projection.writableRoots.length > 0) {
|
|
46
|
+
argv.push("-c", `sandbox_workspace_write.writable_roots=${JSON.stringify(projection.writableRoots)}`);
|
|
47
|
+
}
|
|
39
48
|
if (req.model)
|
|
40
49
|
argv.push("--model", req.model);
|
|
41
50
|
if (req.effort)
|
|
@@ -51,7 +60,7 @@ export function normalizeCodexResult(raw) {
|
|
|
51
60
|
ok: false,
|
|
52
61
|
text: "",
|
|
53
62
|
durationMs: raw.durationMs,
|
|
54
|
-
error: `codex exited ${raw.exitCode}: ${(raw
|
|
63
|
+
error: `codex exited ${raw.exitCode}: ${vendorFailureText(raw)}`,
|
|
55
64
|
};
|
|
56
65
|
}
|
|
57
66
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spawn-cursor.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/spawn-cursor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"spawn-cursor.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/spawn-cursor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAKjF,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AASrE,gEAAgE;AAChE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;CAClB,CAWA;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,YAAY,GAAG,iBAAiB,CAkB1E;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,gBAAgB,GAAG,WAAW,CA6BxE;AAED,eAAO,MAAM,aAAa,EAAE,OAe3B,CAAC"}
|
|
@@ -19,9 +19,11 @@
|
|
|
19
19
|
* accepted and ignored (documented in the CLI docs page).
|
|
20
20
|
*/
|
|
21
21
|
import { exec } from "../../lib/exec.js";
|
|
22
|
-
import { validateHarnessEffort } from "../harnesses/profiles.js";
|
|
22
|
+
import { builtinHarnessProfile, validateHarnessEffort } from "../harnesses/profiles.js";
|
|
23
23
|
import { buildChildEnv } from "./child-env.js";
|
|
24
24
|
import { notFoundError } from "./harnesses.js";
|
|
25
|
+
import { resolveSandboxProjection } from "./sandbox-projection.js";
|
|
26
|
+
import { vendorFailureText } from "./spawn-failure.js";
|
|
25
27
|
/** Exported for unit tests (no live binary to test against). */
|
|
26
28
|
export function parseCursorOutput(stdout) {
|
|
27
29
|
try {
|
|
@@ -38,6 +40,10 @@ export function parseCursorOutput(stdout) {
|
|
|
38
40
|
}
|
|
39
41
|
export function buildCursorInvocation(req) {
|
|
40
42
|
validateHarnessEffort("cursor", req.effort);
|
|
43
|
+
if (req.filesystemPolicy) {
|
|
44
|
+
// Declared unrepresentable: refuse rather than drop it silently (ADR 0039).
|
|
45
|
+
resolveSandboxProjection("cursor", builtinHarnessProfile("cursor")?.sandboxProjection, req.filesystemPolicy);
|
|
46
|
+
}
|
|
41
47
|
// --trust: headless cursor-agent refuses untrusted workspaces (exit 1,
|
|
42
48
|
// "Workspace Trust Required"). --force: a print-mode child has no interactive
|
|
43
49
|
// approval channel, so host-authorized workflow dispatch must let it run
|
|
@@ -57,7 +63,7 @@ export function normalizeCursorResult(raw) {
|
|
|
57
63
|
ok: false,
|
|
58
64
|
text: "",
|
|
59
65
|
durationMs: raw.durationMs,
|
|
60
|
-
error: `cursor-agent exited ${raw.exitCode}: ${(raw
|
|
66
|
+
error: `cursor-agent exited ${raw.exitCode}: ${vendorFailureText(raw)}`,
|
|
61
67
|
};
|
|
62
68
|
}
|
|
63
69
|
const parsed = parseCursorOutput(raw.stdout);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared failure-text extraction for the harness spawn adapters.
|
|
3
|
+
*
|
|
4
|
+
* A vendor CLI prints its banner, resolved config, and startup warnings first,
|
|
5
|
+
* and the reason it actually failed last. Every adapter used to keep the FIRST
|
|
6
|
+
* 500 characters of the transcript, which reliably preserved the banner and
|
|
7
|
+
* discarded the answer: a child that died with "your workspace is out of
|
|
8
|
+
* credits" reported a cosmetic startup warning instead.
|
|
9
|
+
*
|
|
10
|
+
* Two rules follow. Keep the tail. Include both streams, because which one
|
|
11
|
+
* carries the reason varies by vendor and by failure.
|
|
12
|
+
*/
|
|
13
|
+
/** Bounded failure text from a finished child, tail-preserving. */
|
|
14
|
+
export declare function vendorFailureText(raw: {
|
|
15
|
+
stdout?: string;
|
|
16
|
+
stderr?: string;
|
|
17
|
+
}, maxChars?: number): string;
|
|
18
|
+
//# sourceMappingURL=spawn-failure.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spawn-failure.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/spawn-failure.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,mEAAmE;AACnE,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,EACzC,QAAQ,SAAoB,GAC3B,MAAM,CAQR"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared failure-text extraction for the harness spawn adapters.
|
|
3
|
+
*
|
|
4
|
+
* A vendor CLI prints its banner, resolved config, and startup warnings first,
|
|
5
|
+
* and the reason it actually failed last. Every adapter used to keep the FIRST
|
|
6
|
+
* 500 characters of the transcript, which reliably preserved the banner and
|
|
7
|
+
* discarded the answer: a child that died with "your workspace is out of
|
|
8
|
+
* credits" reported a cosmetic startup warning instead.
|
|
9
|
+
*
|
|
10
|
+
* Two rules follow. Keep the tail. Include both streams, because which one
|
|
11
|
+
* carries the reason varies by vendor and by failure.
|
|
12
|
+
*/
|
|
13
|
+
const DEFAULT_MAX_CHARS = 500;
|
|
14
|
+
/** Bounded failure text from a finished child, tail-preserving. */
|
|
15
|
+
export function vendorFailureText(raw, maxChars = DEFAULT_MAX_CHARS) {
|
|
16
|
+
const parts = [raw.stderr, raw.stdout]
|
|
17
|
+
.map((part) => part?.trim())
|
|
18
|
+
.filter((part) => !!part);
|
|
19
|
+
if (parts.length === 0)
|
|
20
|
+
return "";
|
|
21
|
+
// Both streams, stderr first, so a reason on the unexpected stream survives.
|
|
22
|
+
const combined = parts.join("\n");
|
|
23
|
+
return combined.length > maxChars ? `…${combined.slice(-maxChars)}` : combined;
|
|
24
|
+
}
|