@sema-agent/core 7.19.0 → 7.20.1
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/CHANGELOG.md +199 -2
- package/dist/agents/subagent.js +12 -20
- package/dist/agents/teacher.js +2 -5
- package/dist/agents/verify.js +21 -10
- package/dist/brain/anthropic.js +3 -1
- package/dist/brain/open-responses.js +4 -2
- package/dist/brain/openai.js +3 -1
- package/dist/brain/stream-engine.d.ts +4 -0
- package/dist/brain/stream-engine.js +4 -0
- package/dist/core/auto-mode.d.ts +37 -18
- package/dist/core/auto-mode.js +1 -1
- package/dist/core/child-clamp-seats.d.ts +79 -0
- package/dist/core/child-clamp-seats.js +29 -0
- package/dist/core/engine-notice.d.ts +76 -49
- package/dist/core/fs-write-gate-policy.d.ts +17 -9
- package/dist/core/fs-write-gate-policy.js +51 -4
- package/dist/core/gate-bounded-await.d.ts +38 -0
- package/dist/core/gate-bounded-await.js +53 -0
- package/dist/core/gate-fold.js +16 -48
- package/dist/core/gate-lanes.js +11 -3
- package/dist/core/gate-outcome.d.ts +9 -6
- package/dist/core/governance-codes.d.ts +16 -1
- package/dist/core/governance-codes.js +14 -0
- package/dist/core/hooks.d.ts +8 -8
- package/dist/core/memory-engine/engine.d.ts +14 -9
- package/dist/core/memory-engine/engine.js +21 -8
- package/dist/core/memory-engine/layout.d.ts +31 -0
- package/dist/core/memory-engine/layout.js +68 -3
- package/dist/core/memory-engine/tools.js +6 -0
- package/dist/core/memory-engine/types.d.ts +24 -0
- package/dist/core/memory.d.ts +19 -0
- package/dist/core/memory.js +12 -0
- package/dist/core/remote-env.d.ts +32 -0
- package/dist/core/remote-env.js +4 -1
- package/dist/core/runner/advertised-writable-dirs.d.ts +59 -1
- package/dist/core/runner/advertised-writable-dirs.js +51 -3
- package/dist/core/runner/announce-once-ledger.d.ts +15 -0
- package/dist/core/runner/announce-once-ledger.js +8 -0
- package/dist/core/runner/classifier-ladder.d.ts +5 -0
- package/dist/core/runner/classifier-ladder.js +13 -2
- package/dist/core/runner/contracts.d.ts +44 -1
- package/dist/core/runner/denial-limit-arms.d.ts +14 -1
- package/dist/core/runner/denial-limit-arms.js +5 -4
- package/dist/core/runner/env-capability-census.d.ts +30 -0
- package/dist/core/runner/env-capability-census.js +38 -0
- package/dist/core/runner/forward-sink.d.ts +32 -0
- package/dist/core/runner/forward-sink.js +41 -0
- package/dist/core/runner/gate-exit.d.ts +4 -0
- package/dist/core/runner/gate-exit.js +4 -1
- package/dist/core/runner/git-status-frame.d.ts +0 -9
- package/dist/core/runner/listing-fold.d.ts +57 -0
- package/dist/core/runner/listing-fold.js +75 -0
- package/dist/core/runner/prepare-execution-env.d.ts +1 -1
- package/dist/core/runner/prepare-execution-env.js +2 -0
- package/dist/core/runner/prepare-gate-stations.d.ts +6 -0
- package/dist/core/runner/prepare-gate-stations.js +1 -3
- package/dist/core/runner/prepare-hands-readface.d.ts +4 -0
- package/dist/core/runner/prepare-hands-readface.js +3 -5
- package/dist/core/runner/prepare-listings.d.ts +3 -0
- package/dist/core/runner/prepare-listings.js +4 -2
- package/dist/core/runner/prepare-memory.js +7 -1
- package/dist/core/runner/prepare-policy-chain.js +5 -5
- package/dist/core/runner/prepare-prompt-inputs.d.ts +2 -2
- package/dist/core/runner/prepare-run-refs.d.ts +4 -2
- package/dist/core/runner/prepare-run-refs.js +5 -4
- package/dist/core/runner/prepare-task.js +8 -6
- package/dist/core/runner/prepare-wiring-manifest.d.ts +8 -1
- package/dist/core/runner/prepare-wiring-manifest.js +5 -2
- package/dist/core/runner/run-clock-and-content.js +3 -7
- package/dist/core/runner/run-harness-handlers.js +10 -10
- package/dist/core/runner/run-leg.js +28 -19
- package/dist/core/runner/run-settle-and-teardown.js +2 -5
- package/dist/core/runner/run-turn-boundary.js +44 -33
- package/dist/core/runner/runtask.js +2 -1
- package/dist/core/runner/synthetic-tools.d.ts +13 -39
- package/dist/core/runner/synthetic-tools.js +15 -59
- package/dist/core/runner/task-root-canonical.d.ts +45 -0
- package/dist/core/runner/task-root-canonical.js +18 -0
- package/dist/core/runner/turn-attachments.d.ts +125 -49
- package/dist/core/runner/turn-attachments.js +124 -66
- package/dist/core/runner/write-protection-station.d.ts +59 -0
- package/dist/core/runner/write-protection-station.js +32 -0
- package/dist/core/safe-notify.d.ts +5 -0
- package/dist/core/safe-notify.js +24 -2
- package/dist/core/sensitive-path-policy.d.ts +53 -27
- package/dist/core/sensitive-path-policy.js +16 -26
- package/dist/core/skill-listing-budget.d.ts +34 -40
- package/dist/core/skill-listing-budget.js +25 -26
- package/dist/core/skills-directory.js +17 -10
- package/dist/core/task-registry.js +2 -1
- package/dist/core/task-spec.d.ts +8 -7
- package/dist/core/tool-policy.d.ts +12 -1
- package/dist/core/tool-policy.js +39 -25
- package/dist/core/wiring-manifest.d.ts +31 -0
- package/dist/core/wiring-manifest.js +1 -0
- package/dist/core/write-protect.d.ts +124 -18
- package/dist/core/write-protect.js +91 -34
- package/dist/index.d.ts +6 -5
- package/dist/index.js +6 -5
- package/dist/orchestration/workflow-primitives.js +10 -20
- package/dist/stores/file/memory-store.d.ts +5 -2
- package/dist/stores/file/memory-store.js +8 -4
- package/dist/tools/fs/bash-readonly-classifier.d.ts +13 -2
- package/dist/tools/fs/bash-readonly-classifier.js +318 -36
- package/dist/tools/fs/fs-bash.d.ts +1 -1
- package/dist/tools/fs/fs-bash.js +12 -25
- package/dist/tools/fs/fs-shared.d.ts +22 -0
- package/dist/tools/fs/fs-shared.js +30 -0
- package/dist/tools/fs/index.d.ts +1 -1
- package/dist/tools/fs/index.js +1 -1
- package/package.json +2 -1
- package/test/export-surface.snapshot.json +25 -3
- package/wire-changes/core@7.20.0.json +568 -0
- package/wire-changes/core@7.20.1.json +183 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ONE folding engine every listing frame renders through — the `<skills>` block, the skills drift
|
|
3
|
+
* frame's add arm, the agent-type roster and its drift frame's add arm. A listing is an intact-class
|
|
4
|
+
* turn attachment (`turn-attachments.ts` `ATTACHMENT_DELIVERY_CLASS`): the delivery lane never clips
|
|
5
|
+
* it, so this engine is the frame's whole bound, byte-exact over the caller's `frame` (headers, fences,
|
|
6
|
+
* markers, joiners included).
|
|
7
|
+
*
|
|
8
|
+
* Three honesty tiers over ONE set of items, each chosen with the LATER tiers' fixed overhead already
|
|
9
|
+
* reserved so the final render never blows the budget it was sized against:
|
|
10
|
+
* A. everything fits → every item gets its full line;
|
|
11
|
+
* B. reserve the cap marker + EVERY item's name-only line first, then spend the remaining slack on
|
|
12
|
+
* full lines in PRIORITY order (`rank` ascending; absent ⇒ index), admitting each full line whose
|
|
13
|
+
* incremental cost still fits and skipping (not stopping at) the ones that do not — every item stays
|
|
14
|
+
* listed, the low-priority ones lose their detail;
|
|
15
|
+
* C. even all-name-only overflows → the longest name-only prefix that fits, closed by the caller's
|
|
16
|
+
* overflow count line.
|
|
17
|
+
* Pure: the same items, spec and frame always render the same bytes.
|
|
18
|
+
*/
|
|
19
|
+
export interface ListingFoldSpec<T> {
|
|
20
|
+
/** The whole frame's byte budget, honoured as given. */
|
|
21
|
+
blockMaxBytes: number;
|
|
22
|
+
/** One item's full line (tier A, and tier B's admitted lines). */
|
|
23
|
+
full: (item: T) => string;
|
|
24
|
+
/** One item's name-only line (tier B's degraded form, tier C's listed prefix). */
|
|
25
|
+
nameOnly: (item: T) => string;
|
|
26
|
+
/** The raw name reported for an item the budget degraded (host-facing data, not prompt text). */
|
|
27
|
+
nameOf: (item: T) => string;
|
|
28
|
+
/** Priority for keeping the full line: ascending, 0 = first. Absent ⇒ the item's index. */
|
|
29
|
+
rank?: (item: T, index: number) => number;
|
|
30
|
+
/** The marker line that opens a degraded (tier B/C) body. */
|
|
31
|
+
capMarker: string;
|
|
32
|
+
/** Tier C's closing line for `n` items that could not be listed at all. */
|
|
33
|
+
overflowLine: (n: number) => string;
|
|
34
|
+
/** Renders body lines into the lane's frame; its fixed cost is priced once by rendering it empty. */
|
|
35
|
+
frame: (lines: readonly string[]) => string;
|
|
36
|
+
}
|
|
37
|
+
/** What one fold produced: the frame, and which items the budget degraded (display order). */
|
|
38
|
+
export interface ListingFoldRender {
|
|
39
|
+
text: string;
|
|
40
|
+
/** Items listed WITHOUT their full line. */
|
|
41
|
+
nameOnly: readonly string[];
|
|
42
|
+
/** Items the frame could not list at all (tier C's overflow tail). */
|
|
43
|
+
dropped: readonly string[];
|
|
44
|
+
}
|
|
45
|
+
export declare function foldListingWithin<T>(items: ReadonlyArray<T>, spec: ListingFoldSpec<T>): ListingFoldRender | undefined;
|
|
46
|
+
/** The removal arm's FLOOR — the departure fact with none of the names; constant-size, which is what
|
|
47
|
+
* keeps the fact from being starved by a budget the names cannot fit. */
|
|
48
|
+
export declare function removalArmFloor(header: string, count: number): string;
|
|
49
|
+
/**
|
|
50
|
+
* A listing frame's REMOVAL arm rendered INSIDE a byte budget: every departed name when they fit,
|
|
51
|
+
* otherwise the longest prefix that does, closed by an honest count line — tier C over a list whose
|
|
52
|
+
* lines have one form, so there is no name-only tier between them. Names are neutralized on the way
|
|
53
|
+
* out: the announced map holds raw names from the commit half. Cost of the bound, stated: a name that
|
|
54
|
+
* does not fit is never announced (the commit half advances past it), so the model can still hold an
|
|
55
|
+
* entry that is gone — one failed call, against a frame that would otherwise never fit its budget.
|
|
56
|
+
*/
|
|
57
|
+
export declare function foldRemovalArmWithin(removed: readonly string[], header: string, maxBytes: number): string;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { sanitizeUntrustedText, SHELLED_BODY_ENVELOPE_TAGS } from "../untrusted-text.js";
|
|
2
|
+
export function foldListingWithin(items, spec) {
|
|
3
|
+
if (items.length === 0)
|
|
4
|
+
return undefined;
|
|
5
|
+
const bytes = (s) => Buffer.byteLength(s, "utf8");
|
|
6
|
+
const render = spec.frame;
|
|
7
|
+
const lineCost = (l) => bytes(l) + 1;
|
|
8
|
+
const bodyBudget = spec.blockMaxBytes - bytes(render([]));
|
|
9
|
+
const fullLines = items.map((it) => spec.full(it));
|
|
10
|
+
const fullTotal = fullLines.reduce((acc, l) => acc + lineCost(l), 0);
|
|
11
|
+
if (fullTotal <= bodyBudget)
|
|
12
|
+
return { text: render(fullLines), nameOnly: [], dropped: [] };
|
|
13
|
+
const nameLines = items.map((it) => spec.nameOnly(it));
|
|
14
|
+
const namePrefix = new Array(nameLines.length + 1);
|
|
15
|
+
namePrefix[0] = 0;
|
|
16
|
+
for (let i = 0; i < nameLines.length; i++)
|
|
17
|
+
namePrefix[i + 1] = namePrefix[i] + lineCost(nameLines[i]);
|
|
18
|
+
const markerCost = lineCost(spec.capMarker);
|
|
19
|
+
const floorCost = markerCost + namePrefix[nameLines.length];
|
|
20
|
+
if (floorCost <= bodyBudget) {
|
|
21
|
+
let slack = bodyBudget - floorCost;
|
|
22
|
+
const byPriority = items
|
|
23
|
+
.map((it, i) => ({ i, rank: spec.rank?.(it, i) ?? i }))
|
|
24
|
+
.toSorted((a, b) => a.rank - b.rank || a.i - b.i);
|
|
25
|
+
const withFull = new Set();
|
|
26
|
+
for (const { i } of byPriority) {
|
|
27
|
+
const delta = lineCost(fullLines[i]) - lineCost(nameLines[i]);
|
|
28
|
+
if (delta <= slack) {
|
|
29
|
+
withFull.add(i);
|
|
30
|
+
slack -= delta;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
text: render([spec.capMarker, ...items.map((_it, i) => (withFull.has(i) ? fullLines[i] : nameLines[i]))]),
|
|
35
|
+
nameOnly: items.filter((_it, i) => !withFull.has(i)).map((it) => spec.nameOf(it)),
|
|
36
|
+
dropped: [],
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
for (let m = items.length - 1; m >= 0; m--) {
|
|
40
|
+
const overflow = spec.overflowLine(items.length - m);
|
|
41
|
+
if (markerCost + namePrefix[m] + lineCost(overflow) <= bodyBudget) {
|
|
42
|
+
return {
|
|
43
|
+
text: render([spec.capMarker, ...nameLines.slice(0, m), overflow]),
|
|
44
|
+
nameOnly: items.slice(0, m).map((it) => spec.nameOf(it)),
|
|
45
|
+
dropped: items.slice(m).map((it) => spec.nameOf(it)),
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
text: render([spec.capMarker, spec.overflowLine(items.length)]),
|
|
51
|
+
nameOnly: [],
|
|
52
|
+
dropped: items.map((it) => spec.nameOf(it)),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
export function removalArmFloor(header, count) {
|
|
56
|
+
return [header, `(… +${count} more are no longer available)`].join("\n");
|
|
57
|
+
}
|
|
58
|
+
export function foldRemovalArmWithin(removed, header, maxBytes) {
|
|
59
|
+
const bytes = (s) => Buffer.byteLength(s, "utf8");
|
|
60
|
+
const lines = removed.map((n) => `- ${sanitizeUntrustedText(n, SHELLED_BODY_ENVELOPE_TAGS)}`);
|
|
61
|
+
const head = bytes(header);
|
|
62
|
+
const lineCost = (l) => bytes(l) + 1;
|
|
63
|
+
const prefix = new Array(lines.length + 1);
|
|
64
|
+
prefix[0] = 0;
|
|
65
|
+
for (let i = 0; i < lines.length; i++)
|
|
66
|
+
prefix[i + 1] = prefix[i] + lineCost(lines[i]);
|
|
67
|
+
if (head + prefix[lines.length] <= maxBytes)
|
|
68
|
+
return [header, ...lines].join("\n");
|
|
69
|
+
for (let m = lines.length - 1; m >= 0; m--) {
|
|
70
|
+
const tail = `(… +${lines.length - m} more are no longer available)`;
|
|
71
|
+
if (head + prefix[m] + lineCost(tail) <= maxBytes)
|
|
72
|
+
return [header, ...lines.slice(0, m), tail].join("\n");
|
|
73
|
+
}
|
|
74
|
+
return removalArmFloor(header, lines.length);
|
|
75
|
+
}
|
|
@@ -14,7 +14,7 @@ export interface OwnedEnvSeat {
|
|
|
14
14
|
export interface PrepareExecutionEnvInput {
|
|
15
15
|
/** borrowed-readonly — the deployment's env seats: the per-task factory (wins), the static env, the
|
|
16
16
|
* declared root fence, and the incident sink for the bounded teardown legs. */
|
|
17
|
-
deps: Pick<RunnerDeps, "executionEnvFactory" | "executionEnv" | "rootPath" | "onError">;
|
|
17
|
+
deps: Pick<RunnerDeps, "executionEnvFactory" | "executionEnv" | "rootPath" | "onError" | "onNotice">;
|
|
18
18
|
/** borrowed-readonly — the REBOUND spec; only the caller's task id rides into the factory ctx. */
|
|
19
19
|
spec: Pick<TaskSpec, "taskId">;
|
|
20
20
|
/** borrowed-readonly — the trusted spawn-side requests: the explicit cwd (a contract), the isolation
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { StubExecutionEnv } from "../stub-env.js";
|
|
2
2
|
import { hasDestroy } from "../remote-env.js";
|
|
3
|
+
import { announceMalformedCapabilities } from "./env-capability-census.js";
|
|
3
4
|
import { settleTeardownLeg } from "./teardown-bounded.js";
|
|
4
5
|
export async function prepareExecutionEnv(input) {
|
|
5
6
|
const { deps, spec, internals, resume, placementRootResolved, sessionId, forgetOnThrow, rollback } = input;
|
|
@@ -39,6 +40,7 @@ export async function prepareExecutionEnv(input) {
|
|
|
39
40
|
});
|
|
40
41
|
}
|
|
41
42
|
const executionEnv = ownedEnv ?? deps.executionEnv ?? new StubExecutionEnv();
|
|
43
|
+
announceMalformedCapabilities(executionEnv, deps.onNotice);
|
|
42
44
|
if (internals?.requestedCwd !== undefined) {
|
|
43
45
|
const canon = async (p) => {
|
|
44
46
|
const r = await executionEnv.canonicalPath(p);
|
|
@@ -30,6 +30,7 @@ import { type HookEnvCapabilities, type HookInvocationIdentity, type Hooks } fro
|
|
|
30
30
|
import type { ToolPolicy } from "../tool-policy.js";
|
|
31
31
|
import { type GateOutcome } from "../gate-outcome.js";
|
|
32
32
|
import type { RunnerDeps, TaskSpec, ToolEffect } from "../types.js";
|
|
33
|
+
import type { WriteProtectionCheck } from "../write-protect.js";
|
|
33
34
|
import type { CwdRef } from "../../tools/fs/fs-shared.js";
|
|
34
35
|
import type { AskLane, IrreversibilityTier, ParkAsk, Prepared, ReversibilityProbes } from "./contracts.js";
|
|
35
36
|
import type { StopForDenialLimit } from "./denial-limit-arms.js";
|
|
@@ -147,6 +148,11 @@ export interface PrepareGateStationsInput {
|
|
|
147
148
|
handsCwdRef: CwdRef | undefined;
|
|
148
149
|
/** borrowed-readonly — the read-only env capability face every hook context carries, or undefined. */
|
|
149
150
|
hookEnvFace: HookEnvCapabilities | undefined;
|
|
151
|
+
/** borrowed-readonly — the leg's write-protection gate input, compiled ONCE by the wiring-manifest phase
|
|
152
|
+
* (which runs first and has to report the judge's own target view), or undefined when the deployment
|
|
153
|
+
* emptied the table: no judge, and no tighten mounted at all. Carried rather than compiled a second time
|
|
154
|
+
* here — two compiles are two judges, free to disagree about the seats they were handed. */
|
|
155
|
+
writeProtectionCheck: WriteProtectionCheck | undefined;
|
|
150
156
|
/** borrowed-readonly — the per-tool irreversibility tier handed to the gate per call. */
|
|
151
157
|
irreversibilityTier: IrreversibilityTier;
|
|
152
158
|
/** borrowed-readonly — the per-tool reversibility probes handed to the gate per call. */
|
|
@@ -7,7 +7,6 @@ import { directDeny } from "./gate-exit.js";
|
|
|
7
7
|
import { emitTrace } from "../trace.js";
|
|
8
8
|
import { deliverEngineNotice } from "../engine-notice.js";
|
|
9
9
|
import { askUnresolvableNotice } from "../ask-unresolvable-notice.js";
|
|
10
|
-
import { createWriteProtectionCheck } from "../write-protect.js";
|
|
11
10
|
import { PATH_CONFINABLE_WRITE_TOOLS } from "./session-rule-policy.js";
|
|
12
11
|
import { toolCallFaceOf } from "../tool-roster.js";
|
|
13
12
|
function screenGateResult(result) {
|
|
@@ -42,7 +41,7 @@ export function maybeHumanRejectionHalt(input) {
|
|
|
42
41
|
};
|
|
43
42
|
}
|
|
44
43
|
export function prepareGateStations(input) {
|
|
45
|
-
const { askLane, parkAsk, tools, toolRosterDeltas, toolEffects, deps, toolCallGateArmedRef, effectivePolicy, hooks, egressTools, irreversibleTools, spec, complianceDenies, harness, blockedToolCalls, inheritedAskGrants, inheritedUnavailableAsks, foldAskClasses, ancestorSandboxAdmissions, preToolContexts, gateOutcomes, batchHaltRef, blockedTracked, hookIdentity, reminderMark, planModeRef, hostTaskId, sessionId, ownGatePreToolUse, hookTimeoutMs, handsCwdRef, hookEnvFace, irreversibilityTier, reversibilityProbes, abortController, shellGatedTools, autoModeDecider, autoModeDenialTracking, stopForDenialLimit, permissionRuleLane, permissionRuleOrgLane, questionToolMounted, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, delegation, notifyOwnHookCrash } = input;
|
|
44
|
+
const { askLane, parkAsk, tools, toolRosterDeltas, toolEffects, deps, toolCallGateArmedRef, effectivePolicy, hooks, egressTools, irreversibleTools, spec, complianceDenies, harness, blockedToolCalls, inheritedAskGrants, inheritedUnavailableAsks, foldAskClasses, ancestorSandboxAdmissions, preToolContexts, gateOutcomes, batchHaltRef, blockedTracked, hookIdentity, reminderMark, planModeRef, hostTaskId, sessionId, ownGatePreToolUse, hookTimeoutMs, handsCwdRef, hookEnvFace, writeProtectionCheck, irreversibilityTier, reversibilityProbes, abortController, shellGatedTools, autoModeDecider, autoModeDenialTracking, stopForDenialLimit, permissionRuleLane, permissionRuleOrgLane, questionToolMounted, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, delegation, notifyOwnHookCrash } = input;
|
|
46
45
|
if (askLane !== undefined && parkAsk !== undefined) {
|
|
47
46
|
const { adjudicate, resolveAskBound, notifyPermissionDenied, notifyHookError } = askLane;
|
|
48
47
|
const { resolveContentAsk, suspendAsk } = parkAsk;
|
|
@@ -51,7 +50,6 @@ export function prepareGateStations(input) {
|
|
|
51
50
|
if (eff !== undefined && !toolEffects.has(t.name))
|
|
52
51
|
toolEffects.set(t.name, eff);
|
|
53
52
|
}
|
|
54
|
-
const writeProtectionCheck = createWriteProtectionCheck(deps.writeProtectedPaths, deps.memoryEngineDir !== undefined ? { dataRoot: deps.memoryEngineDir } : undefined);
|
|
55
53
|
const writeProtectionArmed = writeProtectionCheck !== undefined && tools.some((t) => PATH_CONFINABLE_WRITE_TOOLS.has(t.name));
|
|
56
54
|
toolCallGateArmedRef.armed =
|
|
57
55
|
effectivePolicy !== undefined ||
|
|
@@ -110,6 +110,10 @@ export interface PrepareHandsReadFaceInput {
|
|
|
110
110
|
/** borrowed-readonly — B-4's settled root (T6 FINAL semantics); the containment root every face
|
|
111
111
|
* in this phase canonicalizes from. */
|
|
112
112
|
taskRootFinal: string;
|
|
113
|
+
/** borrowed-readonly — the same root, resolved to the spelling the fence compares with, by the ONE
|
|
114
|
+
* resolver at the driver's root receiving point ({@link import("./task-root-canonical.js").resolveTaskRootCanonical}):
|
|
115
|
+
* taken as an input, never re-canonicalized here, so the fence and the root notice cannot disagree. */
|
|
116
|
+
taskRootCanonical: string;
|
|
113
117
|
/** borrowed-readonly — B-4's checkpoint-path rebaser (T7): identity unless a divergent restore
|
|
114
118
|
* armed it; applied to the readFileState seed keys and the handsCwd seed. */
|
|
115
119
|
rebaseRestoredPath: (p: string) => string;
|
|
@@ -152,7 +152,7 @@ export function resolveHandsLessReadFace(input) {
|
|
|
152
152
|
}
|
|
153
153
|
export async function prepareHandsMount(input) {
|
|
154
154
|
const envHandToolNames = new Set();
|
|
155
|
-
const { handsEnabled, executionEnv,
|
|
155
|
+
const { handsEnabled, executionEnv, taskRootCanonical, rebaseRestoredPath, resume, session, sessionId, hostTaskId, taskScope, fullShellReachable, effectiveShellGate, toolFaceSnapshot, model, spec, deps, internals, memoryWriteGate, advertisedWritableDirs, firstPartyOffload, roster, egressTools, irreversibilityTier, irreversibleTools, reversibilityProbes } = input;
|
|
156
156
|
assertStringArraySeat(spec.additionalDirectories, "TaskSpec.additionalDirectories", "strings");
|
|
157
157
|
assertStringArraySeat(spec.additionalReadDirectories, "TaskSpec.additionalReadDirectories", "strings");
|
|
158
158
|
assertStringArraySeat(deps.readDenyPatterns, "RunnerDeps.readDenyPatterns", "compiler-owned");
|
|
@@ -176,15 +176,13 @@ export async function prepareHandsMount(input) {
|
|
|
176
176
|
let attachmentRootCanonical;
|
|
177
177
|
let readDenyMatcher;
|
|
178
178
|
if (handsEnabled) {
|
|
179
|
-
const
|
|
180
|
-
const canon = await executionEnv.canonicalPath(rootRaw);
|
|
181
|
-
const rootCanonical = canon.ok ? canon.value : rootRaw;
|
|
179
|
+
const rootCanonical = taskRootCanonical;
|
|
182
180
|
attachmentRootCanonical = rootCanonical;
|
|
183
181
|
const canonicalizeExtraDirs = async (dirs, field, sink) => {
|
|
184
182
|
for (const dir of dirs ?? []) {
|
|
185
183
|
if (!dir || !dir.trim())
|
|
186
184
|
continue;
|
|
187
|
-
const c = await executionEnv.canonicalPath(dir);
|
|
185
|
+
const c = await (advertisedWritableDirs?.canonicalizeDeclaredRoot(dir) ?? executionEnv.canonicalPath(dir));
|
|
188
186
|
if (c.ok) {
|
|
189
187
|
sink.push(c.value);
|
|
190
188
|
}
|
|
@@ -17,6 +17,7 @@ import type { AgentTool } from "../../internal/harness.js";
|
|
|
17
17
|
import type { TaskSpec } from "../types.js";
|
|
18
18
|
import type { AnnounceOnceSink, Prepared, PrepareResume, ToolFaceSnapshot } from "./contracts.js";
|
|
19
19
|
import type { AnnouncedListingSnapshot } from "../../internal/harness.js";
|
|
20
|
+
import type { ResolvedSkillListingBudget } from "../skill-listing-budget.js";
|
|
20
21
|
export interface PrepareListingsInput {
|
|
21
22
|
/** borrowed-readonly — the REBOUND spec (`spec′`). Read: `agents` (the audit's subject), `tools`
|
|
22
23
|
* (the roster-bearing delegation tool, by its `agentListing` marker), `sessionId` (continuation
|
|
@@ -44,6 +45,8 @@ export interface PrepareListingsInput {
|
|
|
44
45
|
/** borrowed-readonly — the project-context phase's skills-listing projection; read only for the
|
|
45
46
|
* skills opt-out advisory (entries.length). */
|
|
46
47
|
skillsListing: Prepared["skillsListing"];
|
|
48
|
+
/** borrowed-readonly — the listing family's resolved budget; the agent roster frames fold into it. */
|
|
49
|
+
listingBudget: ResolvedSkillListingBudget;
|
|
47
50
|
/** borrowed-mutable — the deferred roster's ToolSearch RIDE seat (declared by the disclosure
|
|
48
51
|
* mount, read at activation time through `listingRideRef.current?.(newly)`). Written here, once,
|
|
49
52
|
* on a deferred roster face; no later writer. Identity is the contract (the mount's closures read
|
|
@@ -2,7 +2,7 @@ import { formatLocalDate } from "../../prompts/default.js";
|
|
|
2
2
|
import { SKILL_TOOL_NAME } from "./synthetic-tools.js";
|
|
3
3
|
import { renderAgentListingDelta } from "./turn-attachments.js";
|
|
4
4
|
export function prepareListings(input) {
|
|
5
|
-
const { spec, tools, onceLedger, sessionId, toolFaceSnapshot, activeTools, resume, skillsListing, listingRideRef, renderWithDate, envFacts, tzValid, userTz } = input;
|
|
5
|
+
const { spec, tools, onceLedger, sessionId, toolFaceSnapshot, activeTools, resume, skillsListing, listingBudget, listingRideRef, renderWithDate, envFacts, tzValid, userTz } = input;
|
|
6
6
|
if (spec.agents !== undefined && spec.agents.length > 0) {
|
|
7
7
|
const known = new Set(tools.flatMap((t) => [t.name, ...(t.aliases ?? [])]));
|
|
8
8
|
for (const def of spec.agents) {
|
|
@@ -39,6 +39,7 @@ export function prepareListings(input) {
|
|
|
39
39
|
? {
|
|
40
40
|
entries: agentListingSpec.agentListing,
|
|
41
41
|
toolName: agentListingSpec.name,
|
|
42
|
+
budget: listingBudget,
|
|
42
43
|
seedAnnounced: resume !== undefined || spec.sessionId !== undefined,
|
|
43
44
|
...(agentListingSpec.agentModels !== undefined ? { models: agentListingSpec.agentModels } : {}),
|
|
44
45
|
}
|
|
@@ -48,6 +49,7 @@ export function prepareListings(input) {
|
|
|
48
49
|
{
|
|
49
50
|
entries: [],
|
|
50
51
|
toolName: (spec.tools ?? []).find((t) => t.agentListing !== undefined)?.name ?? "Agent",
|
|
52
|
+
budget: listingBudget,
|
|
51
53
|
seedAnnounced: true,
|
|
52
54
|
}
|
|
53
55
|
: undefined;
|
|
@@ -66,7 +68,7 @@ export function prepareListings(input) {
|
|
|
66
68
|
return undefined;
|
|
67
69
|
if ((announcedListingsRef.agents?.length ?? 0) > 0)
|
|
68
70
|
return undefined;
|
|
69
|
-
return renderAgentListingDelta({ announcedAgentTypes: undefined }, rideEntries, rosterBearingSpec.name, rideModels);
|
|
71
|
+
return renderAgentListingDelta({ announcedAgentTypes: undefined }, rideEntries, rosterBearingSpec.name, rideModels, listingBudget);
|
|
70
72
|
};
|
|
71
73
|
}
|
|
72
74
|
const dateChange = renderWithDate
|
|
@@ -4,7 +4,7 @@ import { admitMemoryScopes } from "../memory-admission.js";
|
|
|
4
4
|
import { adoptLegacyRepoDirs, canonicalize, deriveRepoControlPlaneDir, deriveProjectControlDir, deriveProjectMemoryDir, deriveRepoMemoryDir, drainMemoryAnnouncements, enqueueMemoryAnnouncement, isContainedIn, lookupProjectIdHint, recordProjectIdHint, resolveMemoryEngineRoot } from "../memory-engine/layout.js";
|
|
5
5
|
import { classifyScopePlanes, derivePersonalControlDir, derivePersonalMemoryDir, mergeHarvestReports, mergeInjections, needsDualRoots, parsedProjectPlane } from "../memory-engine/dual-root.js";
|
|
6
6
|
import { normalizeMemorySpec } from "../memory.js";
|
|
7
|
-
import { MEMORY_ANNOUNCEMENT_CAPTURE_OPTOUT_CODA, MEMORY_ANNOUNCEMENT_READONLY_CODA, MEMORY_CAPTURE_INDETERMINATE_NOTICE, MEMORY_CAPTURE_OPTOUT_NOTICE, MEMORY_PREFERENCE_DISCIPLINE, MEMORY_READONLY_NOTICE, MemoryEngine, entryFileHeadCarriesOrigin, memoryCaptureOptedOutNotice, memoryCaptureOptOutUnpersistedNotice, memoryConsolidationRecommendedNotice, memoryHarvestQuarantinedNotice, memoryHoldNotices, memoryRecallDisciplineSegment, memorySessionPollutedNotice, pollutionContainmentCounts, } from "../memory-engine/engine.js";
|
|
7
|
+
import { MEMORY_ANNOUNCEMENT_CAPTURE_OPTOUT_CODA, MEMORY_ANNOUNCEMENT_READONLY_CODA, MEMORY_CAPTURE_INDETERMINATE_NOTICE, MEMORY_CAPTURE_OPTOUT_NOTICE, MEMORY_PREFERENCE_DISCIPLINE, MEMORY_READONLY_NOTICE, MemoryEngine, entryFileHeadCarriesOrigin, memoryCaptureOptedOutNotice, memoryCaptureOptOutUnpersistedNotice, memoryConsolidationRecommendedNotice, memoryHarvestQuarantinedNotice, memoryHoldNotices, memoryRecallDisciplineSegment, memoryRestoreWithheldNotice, memorySessionPollutedNotice, pollutionContainmentCounts, } from "../memory-engine/engine.js";
|
|
8
8
|
import { adjudicateCaptureOptOut, captureOptOutDeniedError, captureOptOutUnpersistedError } from "./memory-capture-optout.js";
|
|
9
9
|
import { readSessionCaptureOptOut } from "../memory-engine/layout.js";
|
|
10
10
|
import { createMemoryEngineTools } from "../memory-engine/tools.js";
|
|
@@ -522,6 +522,9 @@ export async function prepareMemory(input) {
|
|
|
522
522
|
}
|
|
523
523
|
deliverEngineNotice(deps.onNotice, memoryHarvestQuarantinedNotice({ count, moved, escalated, ...(report.reportId !== undefined ? { reportId: report.reportId } : {}), ...(reason !== undefined ? { reason } : {}), sessionId, provenance: input.memoryProvenance, ...(indexOnly ? { indexRolledBack: true } : {}) }));
|
|
524
524
|
}
|
|
525
|
+
if (report.restoreWithheld !== undefined && report.restoreWithheld.length > 0) {
|
|
526
|
+
deliverEngineNotice(deps.onNotice, memoryRestoreWithheldNotice({ paths: report.restoreWithheld, sessionId }));
|
|
527
|
+
}
|
|
525
528
|
for (const notice of memoryHoldNotices(report, sessionId))
|
|
526
529
|
deliverEngineNotice(deps.onNotice, notice);
|
|
527
530
|
const consolidationNotice = memoryConsolidationRecommendedNotice(report, sessionId);
|
|
@@ -615,6 +618,9 @@ export async function prepareMemory(input) {
|
|
|
615
618
|
}
|
|
616
619
|
}
|
|
617
620
|
const sweep = await writeEngine.sweepSessionCaptureResidue(writeHandle);
|
|
621
|
+
if (sweep.withheld.length > 0) {
|
|
622
|
+
deliverEngineNotice(deps.onNotice, memoryRestoreWithheldNotice({ paths: sweep.withheld, sessionId }));
|
|
623
|
+
}
|
|
618
624
|
if (sweep.failures.length > 0) {
|
|
619
625
|
const named = sweep.failures
|
|
620
626
|
.slice(0, 5)
|
|
@@ -303,9 +303,9 @@ export async function preparePolicyChain(input) {
|
|
|
303
303
|
}
|
|
304
304
|
if (re.updatedInput !== undefined)
|
|
305
305
|
editArgs = re.updatedInput;
|
|
306
|
-
const judged = await judgeInheritedClassifier({ autoMode: ancestorDecider !== undefined ? { decider: ancestorDecider, denialTracking: ancestorTracker } : undefined, ask: re, req: { ...creq, args: editArgs }, signal: csignal ?? abortController.signal, subject: "the approved edit" });
|
|
306
|
+
const judged = await judgeInheritedClassifier({ autoMode: ancestorDecider !== undefined ? { decider: ancestorDecider, denialTracking: ancestorTracker } : undefined, ask: re, req: { ...creq, args: editArgs }, signal: csignal ?? abortController.signal, subject: "the approved edit", allowRewrite: editArgs });
|
|
307
307
|
if (judged.kind === "allow")
|
|
308
|
-
return
|
|
308
|
+
return judged.result;
|
|
309
309
|
if (judged.kind === "deny")
|
|
310
310
|
return judged.result;
|
|
311
311
|
const { ask: editAsk, fallback: editFallback, mintedHere: editMintedHere } = judged;
|
|
@@ -371,7 +371,7 @@ export async function preparePolicyChain(input) {
|
|
|
371
371
|
}
|
|
372
372
|
const judged = await judgeInheritedClassifier({ autoMode: pc.autoMode, ask: first, req: creq, signal: csignal ?? abortController.signal, subject: "this call" });
|
|
373
373
|
if (judged.kind === "allow")
|
|
374
|
-
return
|
|
374
|
+
return judged.result;
|
|
375
375
|
if (judged.kind === "deny")
|
|
376
376
|
return judged.result;
|
|
377
377
|
const { ask: inheritedAsk, fallback, mintedHere } = judged;
|
|
@@ -439,9 +439,9 @@ export async function preparePolicyChain(input) {
|
|
|
439
439
|
return mandateUnreconstructibleDeny(creq);
|
|
440
440
|
}
|
|
441
441
|
const presentedArgs = decision.updatedInput !== undefined ? decision.updatedInput : creq.args;
|
|
442
|
-
const judged = await judgeInheritedClassifier({ autoMode: pc.autoMode, ask: decision, req: { ...creq, args: presentedArgs }, signal: csignal ?? abortController.signal, subject: "this call" });
|
|
442
|
+
const judged = await judgeInheritedClassifier({ autoMode: pc.autoMode, ask: decision, req: { ...creq, args: presentedArgs }, signal: csignal ?? abortController.signal, subject: "this call", allowRewrite: decision.updatedInput });
|
|
443
443
|
if (judged.kind === "allow")
|
|
444
|
-
return
|
|
444
|
+
return judged.result;
|
|
445
445
|
if (judged.kind === "deny")
|
|
446
446
|
return judged.result;
|
|
447
447
|
const { ask: inheritedAsk, fallback, mintedHere } = judged;
|
|
@@ -117,8 +117,8 @@ export interface PreparePromptInputsResult {
|
|
|
117
117
|
tzValid: boolean;
|
|
118
118
|
/** owned — the client's declared zone as given (paired with `tzValid`; unvalidated on its own). */
|
|
119
119
|
userTz: string | undefined;
|
|
120
|
-
/** owned — the git-status lane's run-local state (empty on a hands-less leg); the run loop and the
|
|
121
|
-
*
|
|
120
|
+
/** owned — the git-status lane's run-local state (empty on a hands-less leg); the run loop and the checkpoint
|
|
121
|
+
* serializer mutate its fields from here on (`announced`, `mirrorOwed`, …; the frame's receipt rides the leg's shared `Prepared.frameReceipts`). */
|
|
122
122
|
gitStatusRef: GitStatusLaneRef;
|
|
123
123
|
}
|
|
124
124
|
/** The M10 phase body — prepareTask's prompt-inputs stretch, verbatim (see the module header). */
|
|
@@ -28,8 +28,10 @@ export interface PrepareRunRefsInput {
|
|
|
28
28
|
* worktree helper). Never mutated. */
|
|
29
29
|
spec: Pick<TaskSpec, "forwardSubagentEvents" | "retainSubagentSessions" | "handsReadOnly">;
|
|
30
30
|
/** borrowed-readonly — the trusted spawn-side channel; only `onForwardEvent` (the deployment's display
|
|
31
|
-
* sink) is read,
|
|
32
|
-
|
|
31
|
+
* sink) is read, to decide whether a forwarding wrapper exists at all, and `forwardScope` (the run's
|
|
32
|
+
* forwarding containment, read by the door). The OBJECT is what the wrapper hands the door rather than
|
|
33
|
+
* the pulled-out function: the sink keeps its receiver and the run keeps one failure count. */
|
|
34
|
+
internals: Pick<RunInternals, "onForwardEvent" | "forwardScope"> | undefined;
|
|
33
35
|
/** borrowed-readonly — the run's resolved env; the worktree helper closes over it (lazy: no I/O until a
|
|
34
36
|
* delegation actually mints a worktree). */
|
|
35
37
|
executionEnv: ExecutionEnv;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createSubagentWorktreeHelper } from "../../agents/subagent.js";
|
|
2
2
|
import { SubagentRetainLedger } from "../../agents/retain-ledger.js";
|
|
3
3
|
import { ActiveSkillScope } from "./active-skill-scope.js";
|
|
4
|
+
import { forwardSafely } from "./forward-sink.js";
|
|
4
5
|
import { createEditedFilesLedger } from "./edited-files-ledger.js";
|
|
5
6
|
export function forwardsSubagentEvents(spec) {
|
|
6
7
|
return spec.forwardSubagentEvents === true;
|
|
@@ -14,14 +15,14 @@ export function prepareRunRefs(input) {
|
|
|
14
15
|
const harnessRef = {};
|
|
15
16
|
const toolProgressRef = {};
|
|
16
17
|
const skillScope = new ActiveSkillScope();
|
|
17
|
-
const
|
|
18
|
-
const forwardEvent =
|
|
18
|
+
const sinkWired = internals?.onForwardEvent !== undefined;
|
|
19
|
+
const forwardEvent = sinkWired
|
|
19
20
|
? (e) => {
|
|
20
21
|
if (e.type === "task_progress")
|
|
21
|
-
|
|
22
|
+
forwardSafely(internals, e);
|
|
22
23
|
else if (spec.forwardSubagentEvents === true &&
|
|
23
24
|
(e.type === "text_delta" || e.type === "text_end" || e.type === "reasoning_delta" || e.type === "tool_start" || e.type === "tool_progress" || e.type === "tool_end")) {
|
|
24
|
-
|
|
25
|
+
forwardSafely(internals, e);
|
|
25
26
|
}
|
|
26
27
|
}
|
|
27
28
|
: undefined;
|
|
@@ -78,6 +78,7 @@ import { ToolRosterDeltaSeat } from "../tool-roster.js";
|
|
|
78
78
|
import { faceOf } from "../tool-roster.js";
|
|
79
79
|
import { catalogEntriesNamed, pathTargetOf } from "../tool-registry.js";
|
|
80
80
|
import { AdvertisedWritableDirs } from "./advertised-writable-dirs.js";
|
|
81
|
+
import { resolveTaskRootCanonical } from "./task-root-canonical.js";
|
|
81
82
|
import { createStructuredProjector } from "./tool-output-projection.js";
|
|
82
83
|
function warnCompactionWindowHazard(tracer, spec, model, compModel, hostTaskId) {
|
|
83
84
|
if (compModel === undefined)
|
|
@@ -365,6 +366,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
365
366
|
}
|
|
366
367
|
const ownedEnv = ownedEnvSeat.current;
|
|
367
368
|
const { taskRootFinal, rebaseRestoredPath } = await prepareWorkspaceRestore({ ownedEnv, deps, spec, internals, resume, taskRootInitial, abortController, sessionId });
|
|
369
|
+
const { canonical: taskRootCanonical } = await resolveTaskRootCanonical({ env: executionEnv, given: taskRootFinal, onNotice: deps.onNotice, sessionId, runId });
|
|
368
370
|
const { trackFileEdit, fileHistoryBoundary, restoredFilePaths, rewindNotes, fileHistoryEnabled, historyScope, historyRoot, historyFs } = await prepareFileHistory({ deps, spec, internals, executionEnv, taskRootFinal, handsEnabled, sessionId, session, resumeAtBeforeParentId, abortController });
|
|
369
371
|
const { noteFileEdited, editedFilesSnapshot, harnessRef, toolProgressRef, skillScope, forwardEvent, reviewRequestRef, requestReview, stopRequestedRef, requestStopAfterTurn, planModeRef, enterPlanMode, subagentRetain, worktreeIsolation } = prepareRunRefs({ spec, internals, executionEnv, taskRootFinal });
|
|
370
372
|
let resolvedReadFace;
|
|
@@ -438,7 +440,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
438
440
|
const callIssuedAtRef = {};
|
|
439
441
|
const workCutRef = { continuation: false, abortedBeforeTurnEnd: false };
|
|
440
442
|
const advertisedWritableDirs = handsEnabled
|
|
441
|
-
? new AdvertisedWritableDirs(executionEnv, (dir, reason) => deps.onError?.(new Error(`${dir.advertiser} advertised writable directory skipped
|
|
443
|
+
? new AdvertisedWritableDirs(executionEnv, (dir, reason) => deps.onError?.(new Error(`${dir.advertiser} advertised writable directory skipped: ${dir.path} — ${reason}`), { phase: "config", sessionId }), taskRootCanonical, [...(spec.additionalDirectories ?? []), ...(spec.additionalReadDirectories ?? [])])
|
|
442
444
|
: undefined;
|
|
443
445
|
const handsWriteHalfPlanned = handsEnabled && handsWriteHalfMounts({ readOnly: spec.handsReadOnly === true });
|
|
444
446
|
const memoryPairNameDomain = new Set();
|
|
@@ -508,7 +510,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
508
510
|
if (internals?.ownOrgAdmissionRef !== undefined && ownOrgVerdictRef.current !== undefined) {
|
|
509
511
|
internals.ownOrgAdmissionRef.current = ownOrgVerdictRef.current;
|
|
510
512
|
}
|
|
511
|
-
const handsReadFaceInput = { handsEnabled, executionEnv, taskRootFinal, rebaseRestoredPath, resume, session, sessionId, hostTaskId, taskScope, fullShellReachable, effectiveShellGate, toolFaceSnapshot, model, spec, deps, internals, memoryWriteGate, ...(advertisedWritableDirs !== undefined ? { advertisedWritableDirs } : {}), firstPartyOffload, roster, egressTools, irreversibilityTier, irreversibleTools, reversibilityProbes, reminderMark, reminderDisclosureCounts, ...(trackFileEdit !== undefined ? { trackFileEdit } : {}), onFileEdited: noteFileEdited, harnessRef, toolProgressRef, ...(restoredFilePaths.length > 0 ? { restoredFilePaths } : {}) };
|
|
513
|
+
const handsReadFaceInput = { handsEnabled, executionEnv, taskRootFinal, taskRootCanonical, rebaseRestoredPath, resume, session, sessionId, hostTaskId, taskScope, fullShellReachable, effectiveShellGate, toolFaceSnapshot, model, spec, deps, internals, memoryWriteGate, ...(advertisedWritableDirs !== undefined ? { advertisedWritableDirs } : {}), firstPartyOffload, roster, egressTools, irreversibilityTier, irreversibleTools, reversibilityProbes, reminderMark, reminderDisclosureCounts, ...(trackFileEdit !== undefined ? { trackFileEdit } : {}), onFileEdited: noteFileEdited, harnessRef, toolProgressRef, ...(restoredFilePaths.length > 0 ? { restoredFilePaths } : {}) };
|
|
512
514
|
const handsReadFace = handsEnabled ? await prepareHandsMount(handsReadFaceInput) : resolveHandsLessReadFace(handsReadFaceInput);
|
|
513
515
|
const { readFileStateForCheckpoint, seedContextFiles, handsCwdRef, workspaceStateSettle, wsSnapshot, rebaseWsPath, backgroundTaskToolsActive, additionalRootsCanonical, additionalReadRootsCanonical, attachmentRootCanonical, readDenyMatcher, envHandToolNames, sealReadStateSeat } = handsReadFace;
|
|
514
516
|
resolvedReadFace = handsReadFace.resolvedReadFace;
|
|
@@ -590,7 +592,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
590
592
|
declaredCards: toolRoster.entries.flatMap((e) => e.renderHints?.resultCards ?? []),
|
|
591
593
|
onUndeclared: (type) => deliverEngineNotice(deps.onNotice, { code: "config.tool_card_undeclared", message: `a tool minted a \`details.type\` card ${JSON.stringify(type)} its definition never declared — dropped from tool_end.structured (declare it on the definition's catalog row or the caller's renderHints.resultCards)`, detail: { type, sessionId, runId } }),
|
|
592
594
|
});
|
|
593
|
-
const { agentListing, announcedListingsRef, dateChange } = prepareListings({ spec, tools, onceLedger, sessionId, toolFaceSnapshot, activeTools, resume, skillsListing, listingRideRef, renderWithDate, envFacts, tzValid, userTz });
|
|
595
|
+
const { agentListing, announcedListingsRef, dateChange } = prepareListings({ spec, tools, onceLedger, sessionId, toolFaceSnapshot, activeTools, resume, skillsListing, listingBudget: doors.skillListingBudget, listingRideRef, renderWithDate, envFacts, tzValid, userTz });
|
|
594
596
|
const lastBrainContextRef = {};
|
|
595
597
|
const requestLossyRef = { current: false };
|
|
596
598
|
const staleOffloadWrittenRefs = new Set();
|
|
@@ -688,7 +690,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
688
690
|
}
|
|
689
691
|
}
|
|
690
692
|
const { hooks, hookTimeoutMs, preToolUseObservational, ownGatePreToolUse, basePolicyForResumeEdit, denyNarrowingPolicy, policyLayers, effectivePolicy, inheritedUnavailableAsks, inheritedAskGrants, askSourceIdentity, riskAxesOf, ruleOffersOf, permissionRuleLane, permissionRuleOrgLane, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, foldAskClasses, ancestorSandboxAdmissions } = await preparePolicyChain({ spec, deps, internals, sessionId, runId, hostTaskId, taskRootFinal, executionEnv, lockedPreflight, tools, harnessTools, toolEffects, egressTools, irreversibilityTier, axisExplicitNegatives, shellGatedTools, envHandToolNames, handsCwdRef, readDenyMatcher, questionToolMounted, runtimeCaps, inheritedAncestorRules, inheritedParentConstraints, seedInheritedGate, hasSkillManifest, skillScope, frozenOnAsk, hookEnvSource, notifyOwnHookCrash, autoModeDecider, stopForDenialLimit, delegation, abortController, now, ownSessionRulesRef });
|
|
691
|
-
const { onAsk, preToolContexts, blockedToolCalls, gateOutcomes, batchHaltRef, blockedTracked, incompleteSuspendAdapter, durableSuspendInfraReady, resourceSuspendEligible, usageGovernance, durableApproval, wiringManifest, parkLaneArmed, gateMachineryActive, hookIdentity, hookEnvFace } = prepareWiringManifest({ spec, deps, internals, resume, sessionId, runId, hostTaskId, taskScope, hooks, preToolUseObservational, policyLayers, effectivePolicy, handsEnabled, mcp, irreversibleTools, egressTools, toolEffects, ownedEnv, executionEnv, offloadStore, onceLedger, usageWindows, envLifetimeSuspendAt, runtimeCaps, resolvedInteractionPosture, durableQuestionFace, liveQuestionFace, checkpointStore, sessions, modelGateManifest, autoModeArmReason, lockedPreflight, peerLaneRefs, peerLaneActive, harness, pausedRef, frozenOnAsk, liveInheritedGate, delegation, toolRoster, lspManagerWired, lspDiagnosticsLive: lspDiagnostics !== undefined });
|
|
693
|
+
const { onAsk, preToolContexts, blockedToolCalls, gateOutcomes, batchHaltRef, blockedTracked, incompleteSuspendAdapter, durableSuspendInfraReady, resourceSuspendEligible, usageGovernance, durableApproval, wiringManifest, writeProtectionCheck, parkLaneArmed, gateMachineryActive, hookIdentity, hookEnvFace } = prepareWiringManifest({ spec, deps, internals, resume, sessionId, runId, hostTaskId, taskScope, hooks, preToolUseObservational, policyLayers, effectivePolicy, handsEnabled, taskRootFinal, mcp, irreversibleTools, egressTools, toolEffects, ownedEnv, executionEnv, offloadStore, onceLedger, usageWindows, envLifetimeSuspendAt, runtimeCaps, resolvedInteractionPosture, durableQuestionFace, liveQuestionFace, checkpointStore, sessions, modelGateManifest, autoModeArmReason, lockedPreflight, peerLaneRefs, peerLaneActive, harness, pausedRef, frozenOnAsk, liveInheritedGate, delegation, toolRoster, lspManagerWired, lspDiagnosticsLive: lspDiagnostics !== undefined });
|
|
692
694
|
if (fileHistoryBoundary !== undefined) {
|
|
693
695
|
harness.on("tool_call", async () => {
|
|
694
696
|
await fileHistoryBoundary.settle();
|
|
@@ -699,12 +701,12 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
699
701
|
const { saga } = prepareSuspendSaga({ gateMachineryActive, abortController, harness, checkpointStore, deps, sessionId, hostTaskId, taskScope, liveSpendRef, resume, nestedStats, internals, activeTools, outputRef, readFileStateForCheckpoint, faceCheckpointSection, writeFaceCheckpointSection, reminderMark, handsCwdRef, worktreeSessionRef, undeliveredContinuationRef, inheritedParentConstraints, seedInheritedGate, inheritedAncestorRules, inheritedShellGate, autoModeIntent, inheritedAdmittedOrgScopes, ownOrgVerdictRef, orgGovernedProvenance, announcedListingsRef, gitStatusRef, hookIdentity, placementRootResolved, externalContentTargetActive, remoteEnvFailures, memoryEngineSession, suspendLoopRef, ownedEnv, incompleteSuspendAdapter });
|
|
700
702
|
const { suspendForResource, suspendForPlatformLimit, suspendForReview } = prepareBoundaryParks({ saga, spec, checkpointStore, abortController, harness, session, sessions, sessionId, deps, priorLedger, maxSlices, maxSuspends, resourceTotal, priorSuspendCount, suspendChainBase, humanReviewRef, liveSpendRef, now, faceCheckpointState, f012CheckpointState, orgAdmissionCheckpointState, pausedRef, remoteEnvFailures, resourceSuspendEligible, durableSuspendInfraReady, incompleteSuspendAdapter });
|
|
701
703
|
const { parkAsk } = prepareParkAsk({ askLane, saga, spec, deps, sessionId, checkpointStore, toolRosterDeltas: rosterSeat, parkLaneArmed, contentAskRoutable, liveQuestionFace, mountedQuestionTool, contentAskBindings, lateStrandedAnswers, discloseStrandedAnswers, onAsk, runtimeCaps, inheritedUnavailableAsks, basePolicyForResumeEdit, budgetSnapshot, handsCwdRef, advertisedWritableDirs, offloadStore, ownedEnv, incompleteSuspendAdapter, session, sessions, suspendChainBase, maxSuspends, remoteEnvFailures, shellGatedTools, effectiveShellGate, durableApproval, priorLedger, liveSpendRef, resourceTotal, faceCheckpointState, f012CheckpointState, orgAdmissionCheckpointState, ruleOffersOf, now, humanReviewRef, abortController, harness, pausedRef });
|
|
702
|
-
prepareGateStations({ askLane, parkAsk, tools, toolRosterDeltas: rosterSeat, toolEffects, deps, toolCallGateArmedRef, effectivePolicy, hooks, egressTools, irreversibleTools, spec, complianceDenies, harness, blockedToolCalls, inheritedAskGrants, inheritedUnavailableAsks, foldAskClasses, ancestorSandboxAdmissions, preToolContexts, gateOutcomes, batchHaltRef, blockedTracked, hookIdentity, reminderMark, planModeRef, hostTaskId, sessionId, ownGatePreToolUse, hookTimeoutMs, handsCwdRef, hookEnvFace, irreversibilityTier, reversibilityProbes, abortController, shellGatedTools, autoModeDecider, autoModeDenialTracking, stopForDenialLimit, permissionRuleLane, permissionRuleOrgLane, questionToolMounted, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, delegation, notifyOwnHookCrash });
|
|
704
|
+
prepareGateStations({ askLane, parkAsk, tools, toolRosterDeltas: rosterSeat, toolEffects, deps, toolCallGateArmedRef, effectivePolicy, hooks, egressTools, irreversibleTools, spec, complianceDenies, harness, blockedToolCalls, inheritedAskGrants, inheritedUnavailableAsks, foldAskClasses, ancestorSandboxAdmissions, preToolContexts, gateOutcomes, batchHaltRef, blockedTracked, hookIdentity, reminderMark, planModeRef, hostTaskId, sessionId, ownGatePreToolUse, hookTimeoutMs, handsCwdRef, hookEnvFace, writeProtectionCheck, irreversibilityTier, reversibilityProbes, abortController, shellGatedTools, autoModeDecider, autoModeDenialTracking, stopForDenialLimit, permissionRuleLane, permissionRuleOrgLane, questionToolMounted, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, delegation, notifyOwnHookCrash });
|
|
703
705
|
const { microCompact, charsPerToken } = prepareContextLane({ model, deps, sessionId, runId, hostTaskId, offloadStore, microCompactKnob, harness, batchHaltRef, gitStatusRef, requestLossyRef, trimPressureRef });
|
|
704
706
|
const preparedHolder = {};
|
|
705
707
|
const { cacheBreakDetector, cacheFingerprint, promptOverheadTokens, readTaskFile, normalizeAttachmentPath, isDedupStubResult, recentlyReadFiles, onCompactionApplied, detectExternalChanges, listBackgroundTasks, centerCompactionCandidate, effectiveReadFaceObserved, effectiveWriteFaceObserved, effectiveReadDenyObserved } = prepareTurnWiring({ deps, systemPromptSeat, harnessTools, fpRef, model, epochArtifactDigestForSnapshot, promptProfile, fableMitigations, systemBlocks, thinking, spec, sessionId, turnSnapshotRef, promptManifest, charsPerToken, handsEnabled, executionEnv, attachmentRootCanonical, additionalRootsCanonical, additionalReadRootsCanonical, readDenyMatcher, resolvedReadFace, handsCwdRef, readFileStateForCheckpoint, denyNarrowingPolicy, abortController, hostTaskId, taskScope, buildAssembleInputs, centerAdoptionRef, harnessRef, epochDeclaredSections, carrierReadFace, carrierWriteFace, readDenyAdditionsNormalized, preparedHolder });
|
|
706
708
|
await onceLedger.settle(session, announcedListingsRef);
|
|
707
|
-
const buildPrepared = () => ({ harness, session, sessionId, runId, reminderMark, reminderDisclosureCounts, editedFilesSnapshot, taskRootPath: taskRootFinal, model, thinking, compModel: effectiveCompModel, mcp, ...(a2a.tools.length > 0 ? { a2a } : {}), blockedRef, outputRef, abortController, conflictRef, blockedToolCalls, gateOutcomes, batchHaltRef, nestedStats, ...(rewindNotes.length > 0 ? { rewindNotes } : {}), ...(fileHistoryBoundary !== undefined ? { fileHistoryBoundary } : {}), ...(effectiveReadFaceObserved !== undefined ? { effectiveReadFace: effectiveReadFaceObserved, effectiveWriteFace: effectiveWriteFaceObserved } : {}), ...(effectiveReadDenyObserved !== undefined ? { effectiveReadDenyPatterns: effectiveReadDenyObserved } : {}), effectiveMemoryScopes: memoryEffectiveScopes, cwdRef: handsCwdRef, toolProgressRef, ...(advertisedWritableDirs !== undefined ? { advertisedWritableDirs } : {}), ...(worktreeSessionRef !== undefined ? { worktreeSessionRef } : {}), ...(workspaceStateSettle !== undefined ? { workspaceStateSettle } : {}), ...(sealReadStateSeat !== undefined ? { sealReadStateSeat } : {}), denyNarrowingPolicy, ...(permissionRuleLane !== undefined ? { persistedRuleLane: permissionRuleLane } : {}), ...(basePolicyForResumeEdit !== undefined ? { basePolicyForResumeEdit } : {}), ...(permissionRuleOrgLane !== undefined ? { permissionRuleOrg: permissionRuleOrgLane } : {}), releaseSignal, settleContentAskBindings, cacheBreakDetector, cacheFingerprint, wiringManifest, promptManifest, epochDeclaredSections, activeTools, ...(deferred.size > 0 ? { deferredToolNames: deferred } : {}), toolMaterializeStatic, deferDirectCall, ...(staticFaceForRef.current !== undefined ? { staticFaceFor: staticFaceForRef.current } : {}), ownedEnv, pausedRef, undeliveredContinuationRef, suspendProgressRef, remoteEnvFailures, reviewRequestRef, suspendLoopRef, suspendForResource, ...(suspendForPlatformLimit !== undefined ? { suspendForPlatformLimit } : {}), ...(envLifetimeSuspendAt !== undefined ? { envLifetimeSuspendAt } : {}), ...(usageGovernance !== undefined ? { usageGovernance } : {}), callIssuedAtRef, workCutRef, brainCallGuardrailRef, gateStopRef, suspendForReview, resourceLedger: priorLedger, liveSpendRef, humanReviewRef, now, tools, toolRoster, toolRosterDeltas: rosterSeat, structuredProjector, toolEffects, wakeRecovered, promptOverheadTokens, lastBrainContext, readTaskFile, recentlyReadFiles, normalizeAttachmentPath, isDedupStubResult, ...(onCompactionApplied ? { onCompactionApplied } : {}), compactionReuseRef, trimPressureRef, microCompact, ...(memoryEngineSession ? { memoryEngineSession } : {}), ...(subagentRetain ? { subagentRetain } : {}), ...(lspDiagnostics && nudgeLspOnEdit ? { lspDiagnostics: { registry: lspDiagnostics, nudge: nudgeLspOnEdit, runIdent: lspRunIdent } } : {}), planModeRef, stopRequestedRef, announcedSnapshotRecovered: onceLedger.recovered, ...(dateChange ? { dateChange } : {}), ...(instructionSources ? { instructionSources } : {}), ...(projectInstructionContent !== undefined ? { projectInstructionContent } : {}), ...(workflowSizeGuideline ? { workflowSizeGuideline } : {}), ...(detectExternalChanges ? { detectExternalChanges } : {}), ...(toolsDeltaRef ? { toolsDeltaRef } : {}), ...(agentListing ? { agentListing } : {}), ...(skillsListing ? { skillsListing } : {}), announcedListingsRef, gitStatusRef, listBackgroundTasks, hookIdentity, hookTimeoutMs, ...(turnSnapshotRef.current !== undefined ? { turnSnapshot: turnSnapshotRef.current } : {}), ...(centerCompactionCandidate !== undefined ? { centerCompactionCandidate } : {}), ...(toolDisclosureSeat !== undefined ? { toolDisclosure: toolDisclosureSeat } : {}) });
|
|
709
|
+
const buildPrepared = () => ({ harness, session, sessionId, runId, reminderMark, reminderDisclosureCounts, editedFilesSnapshot, taskRootPath: taskRootFinal, model, thinking, compModel: effectiveCompModel, mcp, ...(a2a.tools.length > 0 ? { a2a } : {}), blockedRef, outputRef, abortController, conflictRef, blockedToolCalls, gateOutcomes, batchHaltRef, nestedStats, ...(rewindNotes.length > 0 ? { rewindNotes } : {}), ...(fileHistoryBoundary !== undefined ? { fileHistoryBoundary } : {}), ...(effectiveReadFaceObserved !== undefined ? { effectiveReadFace: effectiveReadFaceObserved, effectiveWriteFace: effectiveWriteFaceObserved } : {}), ...(effectiveReadDenyObserved !== undefined ? { effectiveReadDenyPatterns: effectiveReadDenyObserved } : {}), effectiveMemoryScopes: memoryEffectiveScopes, cwdRef: handsCwdRef, toolProgressRef, ...(advertisedWritableDirs !== undefined ? { advertisedWritableDirs } : {}), ...(worktreeSessionRef !== undefined ? { worktreeSessionRef } : {}), ...(workspaceStateSettle !== undefined ? { workspaceStateSettle } : {}), ...(sealReadStateSeat !== undefined ? { sealReadStateSeat } : {}), denyNarrowingPolicy, ...(permissionRuleLane !== undefined ? { persistedRuleLane: permissionRuleLane } : {}), ...(basePolicyForResumeEdit !== undefined ? { basePolicyForResumeEdit } : {}), ...(permissionRuleOrgLane !== undefined ? { permissionRuleOrg: permissionRuleOrgLane } : {}), releaseSignal, settleContentAskBindings, cacheBreakDetector, cacheFingerprint, wiringManifest, promptManifest, epochDeclaredSections, activeTools, ...(deferred.size > 0 ? { deferredToolNames: deferred } : {}), toolMaterializeStatic, deferDirectCall, ...(staticFaceForRef.current !== undefined ? { staticFaceFor: staticFaceForRef.current } : {}), ownedEnv, pausedRef, undeliveredContinuationRef, suspendProgressRef, remoteEnvFailures, reviewRequestRef, suspendLoopRef, suspendForResource, ...(suspendForPlatformLimit !== undefined ? { suspendForPlatformLimit } : {}), ...(envLifetimeSuspendAt !== undefined ? { envLifetimeSuspendAt } : {}), ...(usageGovernance !== undefined ? { usageGovernance } : {}), callIssuedAtRef, workCutRef, brainCallGuardrailRef, gateStopRef, suspendForReview, resourceLedger: priorLedger, liveSpendRef, humanReviewRef, now, tools, toolRoster, toolRosterDeltas: rosterSeat, structuredProjector, toolEffects, wakeRecovered, promptOverheadTokens, lastBrainContext, readTaskFile, recentlyReadFiles, normalizeAttachmentPath, isDedupStubResult, ...(onCompactionApplied ? { onCompactionApplied } : {}), compactionReuseRef, trimPressureRef, microCompact, ...(memoryEngineSession ? { memoryEngineSession } : {}), ...(subagentRetain ? { subagentRetain } : {}), ...(lspDiagnostics && nudgeLspOnEdit ? { lspDiagnostics: { registry: lspDiagnostics, nudge: nudgeLspOnEdit, runIdent: lspRunIdent } } : {}), planModeRef, stopRequestedRef, announcedSnapshotRecovered: onceLedger.recovered, ...(dateChange ? { dateChange } : {}), ...(instructionSources ? { instructionSources } : {}), ...(projectInstructionContent !== undefined ? { projectInstructionContent } : {}), ...(workflowSizeGuideline ? { workflowSizeGuideline } : {}), ...(detectExternalChanges ? { detectExternalChanges } : {}), ...(toolsDeltaRef ? { toolsDeltaRef } : {}), ...(agentListing ? { agentListing } : {}), ...(skillsListing ? { skillsListing } : {}), announcedListingsRef, frameReceipts: { pending: [], listingSnapshotOwed: false }, gitStatusRef, listBackgroundTasks, hookIdentity, hookTimeoutMs, ...(turnSnapshotRef.current !== undefined ? { turnSnapshot: turnSnapshotRef.current } : {}), ...(centerCompactionCandidate !== undefined ? { centerCompactionCandidate } : {}), ...(toolDisclosureSeat !== undefined ? { toolDisclosure: toolDisclosureSeat } : {}) });
|
|
708
710
|
rollback.commit();
|
|
709
711
|
const prepared = buildPrepared();
|
|
710
712
|
preparedHolder.current = prepared;
|
|
@@ -28,6 +28,7 @@ import { type ToolResultStore } from "../tool-result-store.js";
|
|
|
28
28
|
import { type OnAsk, type ToolPolicy } from "../tool-policy.js";
|
|
29
29
|
import type { GateOutcome } from "../gate-outcome.js";
|
|
30
30
|
import type { RunnerDeps, RuntimeCaps, TaskSpec, ToolEffect, ToolExecuteContext } from "../types.js";
|
|
31
|
+
import type { WriteProtectionCheck } from "../write-protect.js";
|
|
31
32
|
import { type UsageWindow } from "../usage-window-store.js";
|
|
32
33
|
import type { ToolRoster } from "../tool-roster.js";
|
|
33
34
|
import { type AutoModeArmFact, type WiringManifest, type WiringManifestMcpEntry } from "../wiring-manifest.js";
|
|
@@ -41,7 +42,8 @@ export interface PrepareWiringManifestInput {
|
|
|
41
42
|
/** borrowed-readonly — the deployment seats, whole: `onAsk` (the seat's deps half), `onError` (the warning), `executionEnv`
|
|
42
43
|
* (the hook-env predicate), `checkpointStore` (durable infra), the manifest's dozen wiring facts (`backgroundAgentStore`,
|
|
43
44
|
* `permissionRuleStore`, `permissionRuleSyncWired`, `onBackgroundChildEvent`, `lockedConfig`, `compliancePostureResolver`,
|
|
44
|
-
* `memoryScopeAdmission`, `retentionPolicy`, `onElicit`), `onNotice`,
|
|
45
|
+
* `memoryScopeAdmission`, `retentionPolicy`, `onElicit`), `onNotice`, the write-protection judge's compile seats
|
|
46
|
+
* (`writeProtectedPaths`, `memoryEngineDir`), and the usage-governance seats (`usageWindowStore`,
|
|
45
47
|
* `now`, `onUsageGovernance`…) the helper reads through the whole record. */
|
|
46
48
|
deps: RunnerDeps;
|
|
47
49
|
/** borrowed-readonly — the trusted spawn-side channel: `questionFaceStripped`, `isDelegatedChild`, `onTaskNotification`,
|
|
@@ -67,6 +69,8 @@ export interface PrepareWiringManifestInput {
|
|
|
67
69
|
effectivePolicy: ToolPolicy | undefined;
|
|
68
70
|
/** borrowed-readonly — whether an execution env is wired (the hand band exists at all). */
|
|
69
71
|
handsEnabled: boolean;
|
|
72
|
+
/** borrowed-readonly — the resolved task root: the base a `base: "root"` write tool's relative spelling resolves against. */
|
|
73
|
+
taskRootFinal: string;
|
|
70
74
|
/** borrowed-readonly — the materialized MCP handle: `tools` (the destructive-ungated scan) and `statuses` (the manifest face). */
|
|
71
75
|
mcp: Pick<MaterializedMcp, "tools" | "statuses">;
|
|
72
76
|
/** borrowed-readonly — the assembled safety vocabulary (the ungated scans and the manifest's armed cell). Read only. */
|
|
@@ -158,6 +162,9 @@ export interface PrepareWiringManifestResult {
|
|
|
158
162
|
durableApproval: TaskSpec["durableApproval"];
|
|
159
163
|
/** owned — this leg's EFFECTIVE wiring manifest (`Prepared.wiringManifest`). */
|
|
160
164
|
wiringManifest: WiringManifest;
|
|
165
|
+
/** owned — the leg's write-protection gate input, or undefined when the table was emptied (no judge, no
|
|
166
|
+
* tighten mounted); handed to the gate station rather than compiled a second time there. */
|
|
167
|
+
writeProtectionCheck: WriteProtectionCheck | undefined;
|
|
161
168
|
/** owned — THE park predicate as one named const (`parkLane.effective === true`). */
|
|
162
169
|
parkLaneArmed: boolean;
|
|
163
170
|
/** owned — THE gate-machinery activation predicate as one named const: a policy, a screening hook, an egress or
|
|
@@ -7,6 +7,7 @@ import { isVolatileOffloadStore } from "../tool-result-store.js";
|
|
|
7
7
|
import { durableMandateSourceOf, isLiveApproverSeat } from "../tool-policy.js";
|
|
8
8
|
import { deliverEngineNotice } from "../types.js";
|
|
9
9
|
import { inlineUntrusted } from "../untrusted-text.js";
|
|
10
|
+
import { mountWriteProtection } from "./write-protection-station.js";
|
|
10
11
|
import { GLOBAL_USAGE_KEY, usageRetryAfterMs, windowsGovernCost } from "../usage-window-store.js";
|
|
11
12
|
import { LSP_CONTRACT_ID, countElicitOptIns, deriveLspSeam, deriveWiringManifest, resolveAskSeamForm, resolveDeclaredDurability, resolveElicitSeam, resolveQuestionSeam, resolveSubagentTranscriptTier } from "../wiring-manifest.js";
|
|
12
13
|
import { DEFAULT_IRREVERSIBLE_SCOPE } from "./checkpoint-scope.js";
|
|
@@ -111,7 +112,7 @@ function announceDurableGateUnavailable(args) {
|
|
|
111
112
|
});
|
|
112
113
|
}
|
|
113
114
|
export function prepareWiringManifest(input) {
|
|
114
|
-
const { spec, deps, internals, resume, sessionId, runId, hostTaskId, taskScope, hooks, preToolUseObservational, policyLayers, effectivePolicy, mcp, irreversibleTools, egressTools, toolEffects, ownedEnv, executionEnv, offloadStore, onceLedger, usageWindows, envLifetimeSuspendAt, runtimeCaps, resolvedInteractionPosture, durableQuestionFace, liveQuestionFace, checkpointStore, sessions, modelGateManifest, autoModeArmReason, lockedPreflight, peerLaneRefs, peerLaneActive, harness, pausedRef, frozenOnAsk, liveInheritedGate, delegation, toolRoster, lspManagerWired, lspDiagnosticsLive } = input;
|
|
115
|
+
const { spec, deps, internals, resume, sessionId, runId, hostTaskId, taskScope, hooks, preToolUseObservational, policyLayers, effectivePolicy, handsEnabled, taskRootFinal, mcp, irreversibleTools, egressTools, toolEffects, ownedEnv, executionEnv, offloadStore, onceLedger, usageWindows, envLifetimeSuspendAt, runtimeCaps, resolvedInteractionPosture, durableQuestionFace, liveQuestionFace, checkpointStore, sessions, modelGateManifest, autoModeArmReason, lockedPreflight, peerLaneRefs, peerLaneActive, harness, pausedRef, frozenOnAsk, liveInheritedGate, delegation, toolRoster, lspManagerWired, lspDiagnosticsLive } = input;
|
|
115
116
|
const onAsk = spec.onAsk ?? deps.onAsk;
|
|
116
117
|
const handWriteTools = toolRoster.entries.filter((e) => e.mountedBy === "hands" && (e.effect === "write" || e.effect === "idempotent")).map((e) => e.name);
|
|
117
118
|
const hasEffectAwareGate = Boolean(policyLayers.length > 0 || (hooks?.preToolUse !== undefined && !preToolUseObservational));
|
|
@@ -168,6 +169,7 @@ export function prepareWiringManifest(input) {
|
|
|
168
169
|
const platformSuspendArmed = durableSuspendInfraReady && (envLifetimeSuspendAt !== undefined || usageGovernance !== undefined);
|
|
169
170
|
const durableApproval = spec.durableApproval ??
|
|
170
171
|
(runtimeCaps?.forceDurableGate ? { scope: spec.principal || DEFAULT_IRREVERSIBLE_SCOPE } : undefined);
|
|
172
|
+
const writeProtection = mountWriteProtection({ deps, env: handsEnabled ? executionEnv : undefined, rootPath: taskRootFinal, roster: toolRoster, sessionId, runId });
|
|
171
173
|
const wiringQuestionSeam = resolveQuestionSeam(spec, deps);
|
|
172
174
|
const wiringQuestionStripped = internals?.questionFaceStripped === true;
|
|
173
175
|
const wiringAskSeam = resolveAskSeamForm(spec, deps);
|
|
@@ -204,6 +206,7 @@ export function prepareWiringManifest(input) {
|
|
|
204
206
|
...(modelGateManifest !== undefined ? { modelGate: modelGateManifest } : {}),
|
|
205
207
|
autoMode: { ...autoModeArmReason },
|
|
206
208
|
mcp: mcpManifestEntries(lockedPreflight.mcp, mcp.statuses),
|
|
209
|
+
...(writeProtection !== undefined ? { writeProtectionTargetView: writeProtection.targetView } : {}),
|
|
207
210
|
tools: toolRoster,
|
|
208
211
|
hooks: wiredHookEntries(hooks, spec.hooks !== undefined ? "spec" : "deps", preToolUseObservational),
|
|
209
212
|
...(lspManagerWired ? { lsp: deriveLspSeam(toolRoster.entries.some((e) => e.contract.contractId === LSP_CONTRACT_ID), lspDiagnosticsLive) } : {}),
|
|
@@ -242,5 +245,5 @@ export function prepareWiringManifest(input) {
|
|
|
242
245
|
});
|
|
243
246
|
const hookContextConsumerWired = hooks?.preToolUse !== undefined || hooks?.postToolUse !== undefined || hooks?.postToolUseFailure !== undefined;
|
|
244
247
|
const hookEnvFace = hookContextConsumerWired && (ownedEnv ?? deps.executionEnv) != null ? createHookEnvCapabilities(executionEnv) : undefined;
|
|
245
|
-
return { onAsk, preToolContexts, blockedToolCalls, gateOutcomes, batchHaltRef, blockedTracked, incompleteSuspendAdapter, durableSuspendInfraReady, resourceSuspendEligible, usageGovernance, platformSuspendArmed, durableApproval, wiringManifest, parkLaneArmed, gateMachineryActive, hookIdentity, hookEnvFace };
|
|
248
|
+
return { onAsk, preToolContexts, blockedToolCalls, gateOutcomes, batchHaltRef, blockedTracked, incompleteSuspendAdapter, durableSuspendInfraReady, resourceSuspendEligible, usageGovernance, platformSuspendArmed, durableApproval, wiringManifest, writeProtectionCheck: writeProtection?.check, parkLaneArmed, gateMachineryActive, hookIdentity, hookEnvFace };
|
|
246
249
|
}
|