@sema-agent/core 7.53.0 → 7.54.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/CHANGELOG.md +277 -1
- package/LICENSE +3 -1
- package/dist/agents/peer-session-drain.d.ts +0 -1
- package/dist/agents/peer-session-drain.js +0 -2
- package/dist/agents/send-message-tool.js +3 -4
- package/dist/agents/subagent.d.ts +3 -5
- package/dist/agents/subagent.js +18 -11
- package/dist/agents/tool-filter.d.ts +7 -4
- package/dist/agents/tool-filter.js +7 -3
- package/dist/core/a2a.js +4 -2
- package/dist/core/allow-entry.d.ts +1 -0
- package/dist/core/allow-entry.js +1 -0
- package/dist/core/approval-object.d.ts +87 -0
- package/dist/core/approval-object.js +85 -0
- package/dist/core/arg-summary.d.ts +3 -2
- package/dist/core/arg-summary.js +17 -11
- package/dist/core/ask-origin.d.ts +43 -27
- package/dist/core/ask-origin.js +20 -11
- package/dist/core/ask-question.d.ts +0 -1
- package/dist/core/ask-question.js +4 -67
- package/dist/core/ask-unresolvable-notice.d.ts +3 -2
- package/dist/core/auto-compaction.d.ts +49 -50
- package/dist/core/auto-compaction.js +41 -51
- package/dist/core/auto-mode-prompt.d.ts +4 -2
- package/dist/core/auto-mode-prompt.js +4 -3
- package/dist/core/canonical-json.d.ts +69 -0
- package/dist/core/canonical-json.js +130 -8
- package/dist/core/checkpoint-requirements.d.ts +13 -7
- package/dist/core/checkpoint-requirements.js +4 -1
- package/dist/core/checkpoint-store.d.ts +33 -18
- package/dist/core/checkpoint-store.js +5 -4
- package/dist/core/child-clamp-seats.d.ts +45 -6
- package/dist/core/child-clamp-seats.js +56 -4
- package/dist/core/consolidate-scope.d.ts +1 -1
- package/dist/core/cross-boundary-taint.d.ts +213 -0
- package/dist/core/cross-boundary-taint.js +196 -0
- package/dist/core/decision-receipt.d.ts +44 -1
- package/dist/core/decision-receipt.js +16 -0
- package/dist/core/effective-path-target.d.ts +3 -0
- package/dist/core/effective-path-target.js +4 -0
- package/dist/core/engine-notice.d.ts +34 -2
- package/dist/core/engine-notice.js +17 -1
- package/dist/core/engine-storage-backend.d.ts +73 -0
- package/dist/core/engine-storage-backend.js +1 -0
- package/dist/core/file-history-store.d.ts +6 -2
- package/dist/core/file-history-store.js +1 -0
- package/dist/core/gate-fold.js +10 -2
- package/dist/core/gate-lanes.js +30 -21
- package/dist/core/gate-outcome.d.ts +7 -3
- package/dist/core/governance-codes.d.ts +7 -2
- package/dist/core/governance-codes.js +6 -0
- package/dist/core/hooks.d.ts +14 -14
- package/dist/core/hooks.js +1 -2
- package/dist/core/locked-config.d.ts +28 -1
- package/dist/core/locked-config.js +30 -3
- package/dist/core/lsp.d.ts +1 -1
- package/dist/core/mcp-server-spec.d.ts +66 -9
- package/dist/core/mcp-server-spec.js +52 -19
- package/dist/core/mcp.js +5 -4
- package/dist/core/memory-engine/engine.js +2 -1
- package/dist/core/memory-engine/export-bundle.d.ts +1 -1
- package/dist/core/memory-engine/export-bundle.js +1 -1
- package/dist/core/memory-engine/file-backend.d.ts +2 -6
- package/dist/core/memory-engine/file-backend.js +1 -12
- package/dist/core/memory.d.ts +3 -3
- package/dist/core/mode-policy.d.ts +13 -8
- package/dist/core/mode-policy.js +3 -2
- package/dist/core/mods/kernel/receive.d.ts +2 -1
- package/dist/core/mods/kernel/receive.js +7 -2
- package/dist/core/parent-spec-seat.d.ts +10 -13
- package/dist/core/parent-spec-seat.js +14 -6
- package/dist/core/pause-registry.d.ts +35 -1
- package/dist/core/pause-registry.js +10 -0
- package/dist/core/permission-rule-consent.d.ts +18 -5
- package/dist/core/permission-rule-consent.js +13 -8
- package/dist/core/permission-rule-model.d.ts +29 -6
- package/dist/core/permission-rule-model.js +6 -1
- package/dist/core/permission-rule-org.d.ts +37 -0
- package/dist/core/permission-rule-org.js +34 -42
- package/dist/core/permission-rule-session.js +2 -2
- package/dist/core/permission-rule-store.d.ts +8 -0
- package/dist/core/permission-rule-store.js +1 -0
- package/dist/core/permission-rule-sync.js +3 -2
- package/dist/core/read-only-shell.d.ts +1 -1
- package/dist/core/read-only-shell.js +30 -9
- package/dist/core/remote-env.d.ts +41 -1
- package/dist/core/remote-env.js +18 -0
- package/dist/core/resume-startup-cause.d.ts +18 -0
- package/dist/core/resume-startup-cause.js +12 -0
- package/dist/core/runner/approval-feedback.d.ts +46 -0
- package/dist/core/runner/approval-feedback.js +41 -0
- package/dist/core/runner/compaction-call-options.d.ts +3 -3
- package/dist/core/runner/compaction-call-options.js +2 -2
- package/dist/core/runner/contracts.d.ts +33 -41
- package/dist/core/runner/cross-boundary-lane.d.ts +87 -0
- package/dist/core/runner/cross-boundary-lane.js +190 -0
- package/dist/core/runner/decide-continuation.d.ts +4 -4
- package/dist/core/runner/decide-continuation.js +3 -1
- package/dist/core/runner/gate-exit.d.ts +32 -12
- package/dist/core/runner/gate-exit.js +75 -33
- package/dist/core/runner/inherited-ask-grants.js +2 -2
- package/dist/core/runner/person-path-rows.d.ts +2 -2
- package/dist/core/runner/prepare-acquire-reconcile.d.ts +3 -4
- package/dist/core/runner/prepare-acquire-reconcile.js +3 -3
- package/dist/core/runner/prepare-ask-lane.js +3 -3
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +6 -5
- package/dist/core/runner/prepare-caps-and-workflow.js +3 -3
- package/dist/core/runner/prepare-config-doors.d.ts +12 -15
- package/dist/core/runner/prepare-config-doors.js +8 -3
- package/dist/core/runner/prepare-context-lane.js +6 -3
- package/dist/core/runner/prepare-delegation-surface.d.ts +3 -2
- package/dist/core/runner/prepare-delegation-surface.js +2 -3
- package/dist/core/runner/prepare-execution-env.d.ts +1 -2
- package/dist/core/runner/prepare-execution-env.js +2 -1
- package/dist/core/runner/prepare-gate-stations.d.ts +2 -0
- package/dist/core/runner/prepare-gate-stations.js +4 -3
- package/dist/core/runner/prepare-hands-readface.d.ts +2 -2
- package/dist/core/runner/prepare-hands-readface.js +1 -1
- package/dist/core/runner/prepare-inherited-gate.d.ts +2 -0
- package/dist/core/runner/prepare-inherited-gate.js +1 -0
- package/dist/core/runner/prepare-park-ask.d.ts +1 -1
- package/dist/core/runner/prepare-park-ask.js +9 -3
- package/dist/core/runner/prepare-policy-chain.js +2 -7
- package/dist/core/runner/prepare-safety-scan.d.ts +7 -2
- package/dist/core/runner/prepare-safety-scan.js +34 -27
- package/dist/core/runner/prepare-suspend-saga.d.ts +2 -2
- package/dist/core/runner/prepare-suspend-saga.js +6 -2
- package/dist/core/runner/prepare-task.js +13 -10
- package/dist/core/runner/prepare-turn-wiring.d.ts +10 -5
- package/dist/core/runner/prepare-turn-wiring.js +14 -49
- package/dist/core/runner/prepare-wiring-manifest.d.ts +2 -2
- package/dist/core/runner/prepare-wiring-manifest.js +2 -2
- package/dist/core/runner/prepare-workspace-restore.js +2 -2
- package/dist/core/runner/resume-admission.js +9 -9
- package/dist/core/runner/resume-apply.js +4 -4
- package/dist/core/runner/resume-policy-outcome.d.ts +2 -2
- package/dist/core/runner/resume-policy-outcome.js +18 -15
- package/dist/core/runner/resume-preflight.js +2 -2
- package/dist/core/runner/resume-review-outcome.js +3 -3
- package/dist/core/runner/run-leg.js +57 -33
- package/dist/core/runner/run-settle-and-teardown.js +2 -0
- package/dist/core/runner/run-terminal-adoption.js +15 -4
- package/dist/core/runner/session-file-state-replay.d.ts +5 -2
- package/dist/core/runner/session-file-state-replay.js +3 -2
- package/dist/core/runner/stream-steer-verb.js +2 -2
- package/dist/core/runner/tool-face-overlay.d.ts +24 -6
- package/dist/core/runner/tool-face-overlay.js +24 -15
- package/dist/core/runner-deps.d.ts +9 -9
- package/dist/core/session-store.d.ts +35 -16
- package/dist/core/session-store.js +20 -12
- package/dist/core/{shell-lexer.d.ts → shell-run-candidates.d.ts} +36 -12
- package/dist/core/{shell-lexer.js → shell-run-candidates.js} +145 -225
- package/dist/core/shell-wrapper-table.d.ts +5 -3
- package/dist/core/shell-wrapper-table.js +1 -1
- package/dist/core/store-contracts/checkpoint-store-contract.js +2 -2
- package/dist/core/store-contracts/session-store-contract.d.ts +49 -0
- package/dist/core/store-contracts/session-store-contract.js +639 -0
- package/dist/core/store-contracts/session-store-incarnation-contract.d.ts +12 -0
- package/dist/core/store-contracts/session-store-incarnation-contract.js +5 -2
- package/dist/core/task-event.d.ts +6 -4
- package/dist/core/task-registry-agent.js +1 -0
- package/dist/core/task-registry-shared.d.ts +5 -0
- package/dist/core/task-registry.d.ts +7 -0
- package/dist/core/task-registry.js +17 -0
- package/dist/core/task-result.d.ts +1 -1
- package/dist/core/task-spec.d.ts +6 -6
- package/dist/core/tighten-task-spec.d.ts +6 -4
- package/dist/core/tighten-task-spec.js +2 -2
- package/dist/core/tool-catalog-entries.d.ts +1 -1
- package/dist/core/tool-catalog-entries.js +52 -52
- package/dist/core/tool-face-reader.d.ts +49 -0
- package/dist/core/tool-face-reader.js +94 -0
- package/dist/core/tool-face.d.ts +17 -8
- package/dist/core/tool-face.js +1 -0
- package/dist/core/tool-policy.d.ts +64 -23
- package/dist/core/tool-policy.js +62 -56
- package/dist/core/tool-roster.d.ts +46 -28
- package/dist/core/tool-roster.js +91 -14
- package/dist/core/tool-spec-members.js +2 -2
- package/dist/core/tool-spec.d.ts +20 -4
- package/dist/core/tools.js +2 -0
- package/dist/core/trace.d.ts +24 -2
- package/dist/core/types.d.ts +2 -2
- package/dist/core/types.js +1 -1
- package/dist/core/untrusted-text.d.ts +7 -0
- package/dist/core/untrusted-text.js +3 -8
- package/dist/core/user-attachment.d.ts +43 -0
- package/dist/core/user-attachment.js +92 -15
- package/dist/engine/compaction/compaction.d.ts +2 -2
- package/dist/engine/compaction/utils.d.ts +2 -2
- package/dist/engine/harness/types.d.ts +7 -4
- package/dist/engine/llm/types.d.ts +7 -2
- package/dist/engine/llm/types.js +2 -1
- package/dist/engine/session/repo-utils.d.ts +5 -0
- package/dist/engine/session/repo-utils.js +9 -0
- package/dist/engine/session/storage-base.js +2 -2
- package/dist/index.d.ts +23 -9
- package/dist/index.js +19 -8
- package/dist/internal/llm.d.ts +1 -1
- package/dist/internal/llm.js +1 -1
- package/dist/orchestration/run-workflow-tool.d.ts +3 -0
- package/dist/orchestration/run-workflow-tool.js +1 -0
- package/dist/orchestration/workflow-governance.d.ts +1 -1
- package/dist/orchestration/workflow.d.ts +3 -0
- package/dist/orchestration/workflow.js +2 -1
- package/dist/prompt-assembly/catalog/schema.d.ts +3 -0
- package/dist/prompt-assembly/catalog/schema.js +3 -0
- package/dist/prompt-assembly/overlay.js +2 -2
- package/dist/prompt-assembly/select.js +2 -2
- package/dist/prompts/default.d.ts +1 -1
- package/dist/shell/lex.d.ts +87 -8
- package/dist/shell/lex.js +283 -49
- package/dist/stores/file/index.d.ts +8 -6
- package/dist/tools/artifact/artifact-tool.js +10 -0
- package/dist/tools/fs/bash-program-position.d.ts +3 -15
- package/dist/tools/fs/bash-program-position.js +3 -10
- package/dist/tools/fs/bash-readonly-classifier.js +2 -0
- package/dist/tools/fs/fs-bash.d.ts +3 -3
- package/dist/tools/fs/fs-bash.js +72 -101
- package/dist/tools/fs/fs-read.d.ts +12 -0
- package/dist/tools/fs/fs-read.js +10 -9
- package/dist/tools/fs/fs-shared.d.ts +27 -31
- package/dist/tools/fs/fs-shared.js +12 -15
- package/dist/tools/fs/fs-write.js +1 -1
- package/dist/tools/fs/index.js +2 -2
- package/dist/tools/fs/read-deny-home.d.ts +1 -1
- package/dist/tools/fs/read-deny-home.js +5 -4
- package/dist/tools/fs/read-deny.d.ts +16 -3
- package/dist/tools/fs/read-deny.js +12 -9
- package/dist/tools/fs/safety.d.ts +7 -6
- package/dist/tools/fs/shell-read-bindings.d.ts +5 -3
- package/dist/tools/fs/shell-read-bindings.js +15 -16
- package/dist/tools/fs/shell-read-device.js +1 -1
- package/dist/tools/fs/shell-read-plan.js +36 -47
- package/dist/tools/fs/shell-read-word.d.ts +1 -6
- package/dist/tools/fs/shell-read-word.js +2 -20
- package/dist/tools/fs/shell-reentry-text.js +1 -1
- package/dist/tools/web.d.ts +2 -2
- package/package.json +4 -1
- package/test/export-surface.snapshot.json +5654 -5520
- package/wire-changes/core@7.53.0.json +30 -8
- package/wire-changes/core@7.54.0.json +2870 -0
- package/dist/core/shell-scan.d.ts +0 -60
- package/dist/core/shell-scan.js +0 -183
|
@@ -1,17 +1,40 @@
|
|
|
1
1
|
import { callerToolNameProblem } from "../caller-tool-name.js";
|
|
2
|
-
import {
|
|
3
|
-
import { callerCardIdOf,
|
|
2
|
+
import { describeToolCatalog } from "../tool-registry.js";
|
|
3
|
+
import { callerCardIdOf, rosterMemberBoundProblem, schemaKeyBoundProblem, survivorsByName } from "../tool-roster.js";
|
|
4
4
|
import { toolFaceProblem } from "./tool-face-overlay.js";
|
|
5
|
-
import { OFFLOAD_TOOL_NAME } from "../tool-result-store.js";
|
|
6
|
-
import { PRESENT_PLAN_TOOL_NAME, ENTER_PLAN_MODE_TOOL_NAME } from "../present-plan-tool.js";
|
|
7
5
|
const REPEAT_RISK = { read: 0, idempotent: 1, write: 2 };
|
|
8
6
|
const leastRepeatSafe = (a, b) => (REPEAT_RISK[a] >= REPEAT_RISK[b] ? a : b);
|
|
7
|
+
function engineCandidatesOf(spec, deps) {
|
|
8
|
+
const hands = Boolean(deps.executionEnvFactory || deps.executionEnv);
|
|
9
|
+
const readOnlyHands = spec.handsReadOnly === true;
|
|
10
|
+
const out = [];
|
|
11
|
+
for (const e of describeToolCatalog()) {
|
|
12
|
+
if (!e.mountedBy.some((t) => t !== "scenario" && (t !== "hands" || hands)))
|
|
13
|
+
continue;
|
|
14
|
+
if (e.mountedBy.includes("hands") && e.face.ruleFace?.grammar === "command" && (e.face.effect === "read") !== readOnlyHands)
|
|
15
|
+
continue;
|
|
16
|
+
const effect = e.face.effect ?? "write";
|
|
17
|
+
for (const name of [e.name, ...(e.face.aliases ?? [])])
|
|
18
|
+
out.push([name, effect]);
|
|
19
|
+
}
|
|
20
|
+
return out;
|
|
21
|
+
}
|
|
22
|
+
function wakeEffectsOf(table, claimed, candidates) {
|
|
23
|
+
const wakeEffects = new Map(table);
|
|
24
|
+
const claims = new Set(claimed);
|
|
25
|
+
for (const [name, effect] of candidates) {
|
|
26
|
+
const prior = wakeEffects.get(name) ?? (claims.has(name) ? "write" : undefined);
|
|
27
|
+
wakeEffects.set(name, prior === undefined ? effect : leastRepeatSafe(prior, effect));
|
|
28
|
+
}
|
|
29
|
+
return wakeEffects;
|
|
30
|
+
}
|
|
9
31
|
const tierOf = (t) => t.irreversibility ?? (t.reversibilityProbe ? "maybe" : undefined);
|
|
10
32
|
export function prepareSafetyScan(input) {
|
|
11
33
|
const { spec, deps } = input;
|
|
12
34
|
const toolEffects = new Map();
|
|
13
35
|
const survivors = survivorsByName(spec.tools ?? []);
|
|
14
36
|
const claimedAliases = new Set();
|
|
37
|
+
const aliasClaims = [];
|
|
15
38
|
const egressTools = new Set();
|
|
16
39
|
const irreversibleTools = new Set();
|
|
17
40
|
const irreversibilityTier = new Map();
|
|
@@ -52,18 +75,12 @@ export function prepareSafetyScan(input) {
|
|
|
52
75
|
...(t.ruleFace !== undefined ? { ruleFace: t.ruleFace } : {}),
|
|
53
76
|
...(t.renderHints !== undefined ? { renderHints: t.renderHints } : {}),
|
|
54
77
|
};
|
|
55
|
-
const faceProblem = toolFaceProblem(declared, t.parameters, { toolName: t.name });
|
|
78
|
+
const faceProblem = toolFaceProblem(declared, t.parameters, { toolName: t.name, cardId: callerCardIdOf(t) });
|
|
56
79
|
if (faceProblem !== undefined) {
|
|
57
80
|
const e = new Error(`Tool "${t.name}" declares a face its schema cannot carry: ${faceProblem}.`);
|
|
58
81
|
e.code = "config.tool_face_invalid";
|
|
59
82
|
throw e;
|
|
60
83
|
}
|
|
61
|
-
const foreignCard = offendingResultCard(t.renderHints, callerCardIdOf(t), engineCardTypes());
|
|
62
|
-
if (foreignCard !== undefined) {
|
|
63
|
-
const e = new Error(`Tool "${t.name}" declares a result card outside its own namespace: ${JSON.stringify(foreignCard)} (a caller card is "${callerCardIdOf(t)}/<card>"; engine cards and other contracts' namespaces are reserved).`);
|
|
64
|
-
e.code = "config.tool_face_invalid";
|
|
65
|
-
throw e;
|
|
66
|
-
}
|
|
67
84
|
}
|
|
68
85
|
for (const [what, n] of [["name", t.name], ...(t.aliases ?? []).map((a) => ["alias", a])]) {
|
|
69
86
|
const problem = callerToolNameProblem(n);
|
|
@@ -96,16 +113,21 @@ export function prepareSafetyScan(input) {
|
|
|
96
113
|
markedBy(t.name, "deployment");
|
|
97
114
|
}
|
|
98
115
|
}
|
|
116
|
+
const candidates = engineCandidatesOf(spec, deps);
|
|
117
|
+
const engineNames = new Set(candidates.map(([n]) => n));
|
|
99
118
|
for (const t of survivors.values()) {
|
|
100
119
|
const tier = tierOf(t);
|
|
101
120
|
for (const alias of t.aliases ?? []) {
|
|
102
121
|
if (alias === t.name || survivors.has(alias))
|
|
103
122
|
continue;
|
|
123
|
+
aliasClaims.push([alias, t.effect ?? "write"]);
|
|
104
124
|
if (claimedAliases.has(alias))
|
|
105
125
|
continue;
|
|
106
126
|
claimedAliases.add(alias);
|
|
107
127
|
if (t.effect)
|
|
108
128
|
toolEffects.set(alias, t.effect);
|
|
129
|
+
if (engineNames.has(alias))
|
|
130
|
+
continue;
|
|
109
131
|
if (tier !== undefined) {
|
|
110
132
|
irreversibilityTier.set(alias, tier);
|
|
111
133
|
if (tier === "always" || tier === "maybe") {
|
|
@@ -121,24 +143,9 @@ export function prepareSafetyScan(input) {
|
|
|
121
143
|
}
|
|
122
144
|
}
|
|
123
145
|
}
|
|
124
|
-
toolEffects.set(OFFLOAD_TOOL_NAME, "read");
|
|
125
|
-
const claimerEffects = new Map([...claimedAliases, ...survivors.keys()].map((a) => [a, toolEffects.get(a) ?? "write"]));
|
|
126
|
-
const recordHandEffect = (name, effect) => {
|
|
127
|
-
const claimed = claimerEffects.get(name);
|
|
128
|
-
toolEffects.set(name, claimed === undefined ? effect : leastRepeatSafe(claimed, effect));
|
|
129
|
-
};
|
|
130
|
-
if (deps.executionEnvFactory || deps.executionEnv) {
|
|
131
|
-
for (const [name, effect] of handBandEffects())
|
|
132
|
-
recordHandEffect(name, effect);
|
|
133
|
-
if (spec.handsReadOnly === true)
|
|
134
|
-
recordHandEffect("Bash", "read");
|
|
135
|
-
}
|
|
136
|
-
if (spec.enablePlanMode === true) {
|
|
137
|
-
toolEffects.set(PRESENT_PLAN_TOOL_NAME, "read");
|
|
138
|
-
toolEffects.set(ENTER_PLAN_MODE_TOOL_NAME, "read");
|
|
139
|
-
}
|
|
140
146
|
return {
|
|
141
147
|
toolEffects,
|
|
148
|
+
wakeEffects: wakeEffectsOf(toolEffects, [...claimedAliases, ...survivors.keys()], [...aliasClaims, ...candidates]),
|
|
142
149
|
egressTools,
|
|
143
150
|
irreversibleTools,
|
|
144
151
|
irreversibilityTier,
|
|
@@ -177,8 +177,8 @@ export interface PrepareSuspendSagaInput {
|
|
|
177
177
|
readonly definition?: string;
|
|
178
178
|
readonly lists: string;
|
|
179
179
|
} | undefined;
|
|
180
|
-
/** borrowed-readonly — the external-content-target fold (the row's monotonic bit). */
|
|
181
|
-
|
|
180
|
+
/** borrowed-readonly — the external-content-target fold (the row's monotonic bit). */ externalContentTargetActive: boolean;
|
|
181
|
+
/** borrowed-readonly — the leg's cross-boundary lane: the row's mark, and the record written before the row as the row's leaf. */ crossBoundary: import("./cross-boundary-lane.js").CrossBoundaryLane;
|
|
182
182
|
/** borrowed-mutable — the run-scoped remote-lifecycle failure log (`Prepared.remoteEnvFailures`). Writer here: the
|
|
183
183
|
* compensation's note binding (`push`). */
|
|
184
184
|
remoteEnvFailures: Prepared["remoteEnvFailures"];
|
|
@@ -82,7 +82,7 @@ function stampPlacementRootSessionId(placementRootResolved) {
|
|
|
82
82
|
return placementValueOrAbsent(placementRootResolved);
|
|
83
83
|
}
|
|
84
84
|
export function prepareSuspendSaga(input) {
|
|
85
|
-
const { gateMachineryActive, abortController, harness, checkpointStore, deps, sessionId, hostTaskId, taskScope, liveSpendRef, resume, nestedStats, internals, activeTools, outputRef, readFileStateForCheckpoint, faceCheckpointSection, writeFaceCheckpointSection, skillGrantCheckpointSection, reminderMark, handsCwdRef, handsRoot, handsHome, worktreeSessionRef, undeliveredContinuationRef, inheritedParentConstraints, seedInheritedGate, ancestorRulesNow, inheritedShellGate, permissionMode, inheritedAdmittedOrgScopes, inheritedPathRuleAnchors, inheritedPathRuleInstallations, ownOrgVerdictRef, orgGovernedProvenance, announcedListingsRef, gitStatusRef, hookIdentity, placementRootResolved, checkpointScope, toolCeiling, toolListsJudged, ownToolLists, externalContentTargetActive, remoteEnvFailures, memoryEngineSession, suspendLoopRef, ownedEnv, incompleteSuspendAdapter } = input;
|
|
85
|
+
const { gateMachineryActive, abortController, harness, checkpointStore, deps, sessionId, hostTaskId, taskScope, liveSpendRef, resume, nestedStats, internals, activeTools, outputRef, readFileStateForCheckpoint, faceCheckpointSection, writeFaceCheckpointSection, skillGrantCheckpointSection, reminderMark, handsCwdRef, handsRoot, handsHome, worktreeSessionRef, undeliveredContinuationRef, inheritedParentConstraints, seedInheritedGate, ancestorRulesNow, inheritedShellGate, permissionMode, inheritedAdmittedOrgScopes, inheritedPathRuleAnchors, inheritedPathRuleInstallations, ownOrgVerdictRef, orgGovernedProvenance, announcedListingsRef, gitStatusRef, hookIdentity, placementRootResolved, checkpointScope, toolCeiling, toolListsJudged, ownToolLists, externalContentTargetActive, crossBoundary, remoteEnvFailures, memoryEngineSession, suspendLoopRef, ownedEnv, incompleteSuspendAdapter } = input;
|
|
86
86
|
if (!gateMachineryActive)
|
|
87
87
|
return { saga: undefined };
|
|
88
88
|
const inFlightSpendMicroUsd = () => {
|
|
@@ -182,6 +182,7 @@ export function prepareSuspendSaga(input) {
|
|
|
182
182
|
toolCeiling: toolCeiling !== undefined ? toolCeiling.map((l) => ({ ...(l.allow !== undefined ? { allow: persistedToolNameList(l.allow, "allowed") } : {}), deny: persistedToolNameList(l.deny, "denied") })) : undefined,
|
|
183
183
|
toolListsJudged,
|
|
184
184
|
ownToolLists: ownToolLists !== undefined ? { toolName: ownToolLists.toolName, ...(ownToolLists.definition !== undefined ? { definition: ownToolLists.definition } : {}), lists: ownToolLists.lists } : undefined,
|
|
185
|
+
crossBoundaryRecorded: crossBoundary.recorded() ? true : undefined,
|
|
185
186
|
});
|
|
186
187
|
const compensatePausedVM = (remoteEnv, snapshotId) => compensateUnparkedPause(remoteEnv, snapshotId, {
|
|
187
188
|
boundMs: PARK_COMPENSATION_TIMEOUT_MS,
|
|
@@ -199,6 +200,7 @@ export function prepareSuspendSaga(input) {
|
|
|
199
200
|
return { tag: "absent" };
|
|
200
201
|
if (memoryEngineSession)
|
|
201
202
|
await memoryEngineSession.harvest("checkpoint");
|
|
203
|
+
const recordUnwritten = await crossBoundary.owe(cp.leafId).then((entryId) => void (entryId !== undefined && (cp = { ...cp, leafId: entryId })), (err) => ({ err }));
|
|
202
204
|
if (cutSignal?.aborted) {
|
|
203
205
|
if (remoteEnv !== undefined && remoteHandle?.snapshotId !== undefined) {
|
|
204
206
|
const back = await compensatePausedVM(remoteEnv, remoteHandle.snapshotId);
|
|
@@ -262,6 +264,8 @@ export function prepareSuspendSaga(input) {
|
|
|
262
264
|
const own = judgeAsStored(stamped, fidelity);
|
|
263
265
|
if (own.kind !== "ok")
|
|
264
266
|
throw new Error(`the checkpoint row was not written: ${own.kind === "damaged" ? own.why : "it lists words this engine lacks"}`);
|
|
267
|
+
if (recordUnwritten !== undefined)
|
|
268
|
+
throw new Error(`the checkpoint row was not written: the session's cross-boundary record it points at could not be written first (${thrownText(recordUnwritten.err)})`);
|
|
265
269
|
putAttempted = true;
|
|
266
270
|
await checkpointStore.put(token, stamped);
|
|
267
271
|
announceCommittedScreeningPark();
|
|
@@ -270,7 +274,7 @@ export function prepareSuspendSaga(input) {
|
|
|
270
274
|
catch (putErr) {
|
|
271
275
|
deps.onError?.(putErr, { phase: "config", sessionId });
|
|
272
276
|
if (!putAttempted)
|
|
273
|
-
return compensateNotWritten("the approval checkpoint was not written (the
|
|
277
|
+
return compensateNotWritten(recordUnwritten !== undefined ? `the session's cross-boundary record could not be written before its approval could be parked (${thrownText(recordUnwritten.err)}) — on a governed tree a row is not put without its record` : "the approval checkpoint was not written (a check before the write refused it — the row's own requirement judge; the deployment's error face carries why)");
|
|
274
278
|
const confirmed = await confirmPutOutcome(putErr);
|
|
275
279
|
if (confirmed === "committed") {
|
|
276
280
|
try {
|
|
@@ -43,6 +43,7 @@ import { prepareTurnWiring } from "./prepare-turn-wiring.js";
|
|
|
43
43
|
export { runGuardChain } from "./prepare-context-lane.js";
|
|
44
44
|
import { preparePromptAssembly } from "./prepare-prompt-assembly.js";
|
|
45
45
|
import { limitConfigError, prepareConfigDoors } from "./prepare-config-doors.js";
|
|
46
|
+
import { joinedCrossBoundaryTree, prepareCrossBoundaryLane } from "./cross-boundary-lane.js";
|
|
46
47
|
import { prepareSafetyScan } from "./prepare-safety-scan.js";
|
|
47
48
|
import { prepareAcquireReconcile } from "./prepare-acquire-reconcile.js";
|
|
48
49
|
import { settleBranchWriteBack } from "./branch-writeback.js";
|
|
@@ -305,7 +306,7 @@ export async function prepareTask(request, deps, sessions, resume, internals, ru
|
|
|
305
306
|
const { toolFaceLists, promptProfile, promptHost, promptBinding, lockedPreflight, resolvedInteractionPosture, microCompactKnob, resolvedRole, model, thinking, compModel, fableMitigations, memoryDelegationEvidence, memoryProvenance, memoryCapturePolicy, usageWindows, brainCallGuardrailRef, brainCallGuardrailMs } = doors;
|
|
306
307
|
announceToolModelGate(deps.onNotice, model.id, doors.modelGate);
|
|
307
308
|
const modelGateManifest = toolModelGateManifest(doors.modelGate);
|
|
308
|
-
const { toolEffects, egressTools, irreversibleTools, irreversibilityTier, axisExplicitNegatives, reversibilityProbes, toolMarkSources } = prepareSafetyScan({ spec, deps });
|
|
309
|
+
const { toolEffects, wakeEffects, egressTools, irreversibleTools, irreversibilityTier, axisExplicitNegatives, reversibilityProbes, toolMarkSources } = prepareSafetyScan({ spec, deps });
|
|
309
310
|
let shellGatedTools = new Set();
|
|
310
311
|
refuseRequireExistingWithoutSession(spec);
|
|
311
312
|
refuseRegistryScopeMismatch(spec, internals);
|
|
@@ -318,7 +319,7 @@ export async function prepareTask(request, deps, sessions, resume, internals, ru
|
|
|
318
319
|
throw e;
|
|
319
320
|
}
|
|
320
321
|
const fileHistoryRequest = resolveFileHistoryRequest(spec, deps);
|
|
321
|
-
const { acquired, session, conflictRef, wakeRecovered, branch } = await prepareAcquireReconcile({ sessions, spec, resume,
|
|
322
|
+
const { acquired, session, conflictRef, wakeRecovered, branch } = await prepareAcquireReconcile({ sessions, spec, resume, wakeEffects, report: (e, id) => deps.onError?.(e, { phase: "config", sessionId: id }), ...(internals?.sessionPlacement !== undefined ? { placement: internals.sessionPlacement } : {}), ...(() => { const g = durableParkGapFor(deps, spec); return g !== undefined ? { durableParkGap: g } : {}; })() });
|
|
322
323
|
const sessionId = acquired.sessionId;
|
|
323
324
|
await holdSessionLock?.(sessionId);
|
|
324
325
|
const onceLedger = await loadAnnounceOnceLedger(session, resume?.seed.announcedListings, deps.onError);
|
|
@@ -377,6 +378,7 @@ export async function prepareTask(request, deps, sessions, resume, internals, ru
|
|
|
377
378
|
if (!handsEnabled)
|
|
378
379
|
refuseUserAttachmentPathsWithoutWorkspace(userAttachmentsSeat);
|
|
379
380
|
const externalContentTargetActive = executionEnv.externalContentTarget === true || resume?.seed.externalContentTarget === true;
|
|
381
|
+
const crossBoundaryTree = joinedCrossBoundaryTree(internals?.crossBoundaryTree, (m) => deps.onError?.(new Error(m), { phase: "config", sessionId }));
|
|
380
382
|
const abortController = new AbortController();
|
|
381
383
|
if (spec.signal?.aborted)
|
|
382
384
|
abortController.abort();
|
|
@@ -457,7 +459,7 @@ export async function prepareTask(request, deps, sessions, resume, internals, ru
|
|
|
457
459
|
let handsLessResolvedWriteFace;
|
|
458
460
|
const mcpPool = installedPreflight.mcp?.length ? { pool: internals?.mcpPool ?? new McpConnectionPool(), owned: internals?.mcpPool === undefined } : undefined;
|
|
459
461
|
const mountedMcpNow = mcpPool !== undefined ? () => mountedMcpOf({ declared: installedPreflight.mcp, roster: roster.tools, aggregateNames: new Set(mcp.tools.filter((t) => t.mcpRemoteName === undefined).map((t) => t.name)), pool: mcpPool.pool }) : undefined;
|
|
460
|
-
const { liveInheritedGate, seedInheritedGate, inheritedAncestorRules, inheritedShellGate, inheritedParentConstraints, permissionMode, commitModeSeats, endModeCeiling, inheritedAdmittedOrgScopes, priorOwnOrgVerdict, orgGovernedProvenance, effectiveShellGate, ownSessionRulesRef, ancestorSessionRulesRef, ancestorRulesNow, memoryAdmittedOrgScopesRef, ownOrgVerdictRef, runClampSource, faceCheckpointSection, writeFaceCheckpointSection, skillGrantCheckpointSection, frozenOnAsk, hookEnvSource, frozenOnQuestion, parentSpecSeat, provenanceForChildrenRef, delegationSettlementRef, inheritedGateForChildren, carrierReadFace, carrierWriteFace, fullShellReachable, gateStopRef, stopForDenialLimit, enrichSpecToolCtx } = prepareInheritedGate({ spec, deps, askSeat: doors.askSeat, internals, resume, sessions, sessionId, runId, hostTaskId, taskRootFinal, executionEnv, ownedEnv, lockedPreflight: installedPreflight, pathRuleAnchors: { chainTop, onLeg: onLeg.chained }, checkpointSeat, checkpointScope, toolFaceSnapshot, mountsCallerTool, ...(mountedMcpNow !== undefined ? { mountedMcp: mountedMcpNow } : {}), promptProfile, resolvedInteractionPosture, permissionModeSeat, handsEnabled, reportUsage, harnessRef, skillGrants, requestAllowedTools: allowedToolTables.request, forwardEvent, subagentRetain, worktreeIsolation, requestReview, requestStopAfterTurn, enterPlanMode, reminderMark, reminderDisclosureCounts, fileHistoryEnabled, historyScope, historyRoot, historyFs, abortRun: () => { abortController.abort(); void harness.abort(); }, runtimeCaps: () => runtimeCaps, modBus: legMods.bus, ownModChain, hookEnvFace: () => hookEnvFace, autoModeDecider: () => autoModeDeciderRef.current, autoModeDenialTracking: () => autoModeDenialTrackingRef.current, autoModeArming: () => autoModeArmingRef.current, agentForkDenial: () => agentForkDenial, observersActive: () => observersActive, resolvedReadFace: () => resolvedReadFace, resolvedWriteFace: () => resolvedWriteFace, readDenyAdditionsNormalized: () => readDenyAdditionsNormalized, handsLessResolvedFace: () => handsLessResolvedFace, handsLessResolvedWriteFace: () => handsLessResolvedWriteFace, centerAdoption: () => centerAdoptionRef.current, memoryEngineSession: () => memoryEngineSession });
|
|
462
|
+
const { liveInheritedGate, seedInheritedGate, inheritedAncestorRules, inheritedShellGate, inheritedParentConstraints, permissionMode, commitModeSeats, endModeCeiling, inheritedAdmittedOrgScopes, priorOwnOrgVerdict, orgGovernedProvenance, effectiveShellGate, ownSessionRulesRef, ancestorSessionRulesRef, ancestorRulesNow, memoryAdmittedOrgScopesRef, ownOrgVerdictRef, runClampSource, faceCheckpointSection, writeFaceCheckpointSection, skillGrantCheckpointSection, frozenOnAsk, hookEnvSource, frozenOnQuestion, parentSpecSeat, provenanceForChildrenRef, delegationSettlementRef, inheritedGateForChildren, carrierReadFace, carrierWriteFace, fullShellReachable, gateStopRef, stopForDenialLimit, enrichSpecToolCtx } = prepareInheritedGate({ spec, deps, askSeat: doors.askSeat, crossBoundaryTree, internals, resume, sessions, sessionId, runId, hostTaskId, taskRootFinal, executionEnv, ownedEnv, lockedPreflight: installedPreflight, pathRuleAnchors: { chainTop, onLeg: onLeg.chained }, checkpointSeat, checkpointScope, toolFaceSnapshot, mountsCallerTool, ...(mountedMcpNow !== undefined ? { mountedMcp: mountedMcpNow } : {}), promptProfile, resolvedInteractionPosture, permissionModeSeat, handsEnabled, reportUsage, harnessRef, skillGrants, requestAllowedTools: allowedToolTables.request, forwardEvent, subagentRetain, worktreeIsolation, requestReview, requestStopAfterTurn, enterPlanMode, reminderMark, reminderDisclosureCounts, fileHistoryEnabled, historyScope, historyRoot, historyFs, abortRun: () => { abortController.abort(); void harness.abort(); }, runtimeCaps: () => runtimeCaps, modBus: legMods.bus, ownModChain, hookEnvFace: () => hookEnvFace, autoModeDecider: () => autoModeDeciderRef.current, autoModeDenialTracking: () => autoModeDenialTrackingRef.current, autoModeArming: () => autoModeArmingRef.current, agentForkDenial: () => agentForkDenial, observersActive: () => observersActive, resolvedReadFace: () => resolvedReadFace, resolvedWriteFace: () => resolvedWriteFace, readDenyAdditionsNormalized: () => readDenyAdditionsNormalized, handsLessResolvedFace: () => handsLessResolvedFace, handsLessResolvedWriteFace: () => handsLessResolvedWriteFace, centerAdoption: () => centerAdoptionRef.current, memoryEngineSession: () => memoryEngineSession });
|
|
461
463
|
bindPermissionModeSeat(permissionMode);
|
|
462
464
|
const personRowNotices = { onUnread: ruleStoreUnreadableNotice(deps.onNotice, { sessionId, runId }), onRowsDropped: ruleRowsDroppedNotice(deps.onNotice, { sessionId, runId }) };
|
|
463
465
|
const readerOf = (signals) => personPathRowsOfTask({ deps, notices: personRowNotices, principal: spec.principal, ids: { sessionId, runId, taskId: hostTaskId }, root: taskRootFinal, rootCanonical: taskRootCanonical, leads: headLeads, chainTop, occurrences: toolOccurrences, signals });
|
|
@@ -475,8 +477,9 @@ export async function prepareTask(request, deps, sessions, resume, internals, ru
|
|
|
475
477
|
const legExemptRoots = Object.freeze(dataRootSpellings(deps.memoryEngineDir));
|
|
476
478
|
const legWriteGuard = { exemptRoots: legExemptRoots, rows: toolPolicyWriteGuardRows([installedToolPolicy, ...(inheritedParentConstraints ?? []).map((c) => c.policy)]) };
|
|
477
479
|
const sideCallBookRef = {};
|
|
478
|
-
const { roster, blockedRef, runtimeCaps, runtimeCapsFaulted, complianceDenies, complianceDegraded, agentForkDenial, observersActive, autoModeArmReason, autoModeDeciderRef, autoModeDenialTrackingRef, autoModeArmingRef, armAutoMode, selfOrchestrationActive, workflowToolsActive, workflowSizeGuideline } = await prepareCapsAndWorkflow({ spec, deps, askSeat: doors.askSeat, internals, session, sessionId, runId, hostTaskId, taskScope, taskRootFinal, model, thinking, lockedPreflight, checkpointSeat, toolEffects, toolFaceSnapshot, promptProfile, resolvedInteractionPosture, harnessRef, parentSpecSeat, runClampSource, forwardEvent, inheritedGateForChildren, enrichSpecToolCtx, maybeOffload, requestReview, enterPlanMode, permissionMode, readDenyEntries: () => personRows.tablesReady().then(() => ({ entries: readDenyMatcher?.entries ?? [], ruleRows: pathTables?.ruleRows() ?? effectivePathDenyRules })), peerLaneActive, peerSendMessageBuiltIn, runnerSelf, memoryEngineSession: () => memoryEngineSession, centerAdoption: () => centerAdoptionRef.current, delegated: delegation.isDelegatedChild, sideCallBookRef });
|
|
480
|
+
const { roster, blockedRef, runtimeCaps, runtimeCapsFaulted, complianceDenies, complianceDegraded, agentForkDenial, observersActive, autoModeArmReason, autoModeDeciderRef, autoModeDenialTrackingRef, autoModeArmingRef, armAutoMode, selfOrchestrationActive, workflowToolsActive, workflowSizeGuideline } = await prepareCapsAndWorkflow({ spec, deps, askSeat: doors.askSeat, internals, crossBoundaryTree, session, sessionId, runId, hostTaskId, taskScope, taskRootFinal, model, thinking, lockedPreflight, checkpointSeat, toolEffects, safetyAxes: { irreversibilityTier, irreversibleTools, reversibilityProbes, egressTools, toolMarkSources }, toolFaceSnapshot, promptProfile, resolvedInteractionPosture, harnessRef, parentSpecSeat, runClampSource, forwardEvent, inheritedGateForChildren, enrichSpecToolCtx, maybeOffload, requestReview, enterPlanMode, permissionMode, readDenyEntries: () => personRows.tablesReady().then(() => ({ entries: readDenyMatcher?.entries ?? [], ruleRows: pathTables?.ruleRows() ?? effectivePathDenyRules })), peerLaneActive, peerSendMessageBuiltIn, runnerSelf, memoryEngineSession: () => memoryEngineSession, centerAdoption: () => centerAdoptionRef.current, delegated: delegation.isDelegatedChild, sideCallBookRef });
|
|
479
481
|
const tools = roster.tools;
|
|
482
|
+
const crossBoundary = await prepareCrossBoundaryLane({ token: crossBoundaryTree, posture: doors.crossBoundaryPosture, externalContentTargetActive, env: executionEnv, session, resumeLeg: resume !== undefined, sessionId, runId, hostTaskId, deps });
|
|
480
483
|
const pausedRef = {};
|
|
481
484
|
const undeliveredContinuationRef = { current: { parkedSteers: [], orphanTasks: [] } };
|
|
482
485
|
const remoteEnvFailures = [];
|
|
@@ -786,7 +789,7 @@ export async function prepareTask(request, deps, sessions, resume, internals, ru
|
|
|
786
789
|
}
|
|
787
790
|
}
|
|
788
791
|
const { basePolicyForResumeEdit, denyNarrowingPolicy, skillGrantLane, allowEntryLanes, policyLayers, effectivePolicy, inheritedUnavailableAsks, inheritedAskGrants, askSourceIdentity, riskAxesOf, ruleOffersOf, grantBindingOf, permissionRuleLane, ruleLaneFacts, permissionRuleOrgLane, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, foldAskClasses, ancestorSandboxAdmissions, ancestorArbitrations, inheritedToolChecks } = await preparePolicyChain({ spec, deps, internals, sessionId, runId, hostTaskId, taskRootFinal, additionalRootsCanonical, executionEnv, lockedPreflight: installedPreflight, pathRuleAnchors: { leg: legAnchors, chainTop }, headLeads, tools, harnessTools, selector: toolFaceSnapshot.selector, toolEffects, egressTools, irreversibilityTier, axisExplicitNegatives, shellGatedTools, toolMarkSources, envHandToolNames, handsCwdRef, readDenyMatcher, personRows, questionToolMounted, runtimeCaps, inheritedAncestorRules, ancestorSessionRulesRef, inheritedParentConstraints, seedInheritedGate, skillGrants, skillSpecs, allowedToolTables, frozenOnAsk, hookEnvSource, notifyOwnHookCrash, modBus: legMods.bus, ownModChain, autoModeDecider: () => autoModeDeciderRef.current, readFace: () => resolvedReadFace, permissionMode, scratchpadDir: spec.envFacts?.scratchpadDir, toolRosterDeltas: rosterSeat, stopForDenialLimit, delegation, abortController, now, ownSessionRulesRef });
|
|
789
|
-
const { onAsk, preToolContexts, blockedToolCalls, batchHaltRef, blockedTracked, incompleteSuspendAdapter, durableSuspendInfraReady, resourceSuspendEligible, usageGovernance, durableApproval, wiringManifest, writeProtection, parkLaneArmed, gateMachineryActive, hookIdentity, hookEnvFace, sessionBoxBound } = prepareWiringManifest({ spec, deps, askSeat: doors.askSeat, internals, resume, sessionId, runId, hostTaskId, taskScope, modBus: legMods.bus, policyLayers, effectivePolicy, handsEnabled, taskRootFinal, legWriteGuard, mcp, irreversibleTools, egressTools, shellReadStationArmed: handsReadFace.shellReadStationArmed, toolEffects, ownedEnv, executionEnv, offloadStore, onceLedger, usageWindows, envLifetimeSuspendAt, runtimeCaps, resolvedInteractionPosture, durableQuestionFace, liveQuestionFace, checkpointStore, sessions, modelGateManifest, autoModeArmReason, permissionMode, lockedPreflight, peerLaneRefs, frameSettlement, harness, pausedRef, liveInheritedGate, delegation, toolRoster, readDenyBuiltinTiersActive: handsReadFace.readDenyBuiltinTiersActive, lspManagerWired, lspDiagnosticsLive: lspDiagnostics !== undefined, fileHistoryFact, sessionBox, checkpointScope, memoryPollution: () => memoryEngineSession?.pollution });
|
|
792
|
+
const { onAsk, preToolContexts, blockedToolCalls, batchHaltRef, blockedTracked, incompleteSuspendAdapter, durableSuspendInfraReady, resourceSuspendEligible, usageGovernance, durableApproval, wiringManifest, writeProtection, parkLaneArmed, gateMachineryActive, hookIdentity, hookEnvFace, sessionBoxBound } = prepareWiringManifest({ spec, deps, askSeat: doors.askSeat, crossBoundaryStationEngaged: crossBoundary.stationEngaged, internals, resume, sessionId, runId, hostTaskId, taskScope, modBus: legMods.bus, policyLayers, effectivePolicy, handsEnabled, taskRootFinal, legWriteGuard, mcp, irreversibleTools, egressTools, shellReadStationArmed: handsReadFace.shellReadStationArmed, toolEffects, ownedEnv, executionEnv, offloadStore, onceLedger, usageWindows, envLifetimeSuspendAt, runtimeCaps, resolvedInteractionPosture, durableQuestionFace, liveQuestionFace, checkpointStore, sessions, modelGateManifest, autoModeArmReason, permissionMode, lockedPreflight, peerLaneRefs, frameSettlement, harness, pausedRef, liveInheritedGate, delegation, toolRoster, readDenyBuiltinTiersActive: handsReadFace.readDenyBuiltinTiersActive, lspManagerWired, lspDiagnosticsLive: lspDiagnostics !== undefined, fileHistoryFact, sessionBox, checkpointScope, memoryPollution: () => memoryEngineSession?.pollution });
|
|
790
793
|
const writeProtectionCheck = writeProtection.mount?.check;
|
|
791
794
|
writeTargetJudgeRef.current = writeProtection.judgeWriteTarget;
|
|
792
795
|
if (fileHistoryBoundary !== undefined) {
|
|
@@ -796,20 +799,20 @@ export async function prepareTask(request, deps, sessions, resume, internals, ru
|
|
|
796
799
|
});
|
|
797
800
|
}
|
|
798
801
|
const listPathRows = () => skillSpecs.flatMap((s) => compileSkillGrant(s, "model").rows).flatMap((r) => (r.behavior === "deny" && r.compiled.kind === "path" ? [r.compiled.rule] : []));
|
|
799
|
-
const stampCallTarget = attachmentRootCanonical === undefined ? undefined : legCallTargetStamp({ env: executionEnv, root: attachmentRootCanonical, cwd: () => handsCwdRef?.current, judgesPaths: () => effectivePolicy?.pathRules !== undefined || basePolicyForResumeEdit?.pathRules !== undefined || permissionRuleLane !== undefined || skillSpecs.some((s) => compileSkillGrant(s, "model").rows.some((r) => r.compiled.kind === "path")) || allowedToolTables.request.holdsPathRows() || allowedToolTables.deployment.holdsPathRows(), leads: () => headLeads.resolve([...toolPolicyPathRules([effectivePolicy, basePolicyForResumeEdit, ...(inheritedParentConstraints ?? []).map((c) => c.policy)], legAnchors), ...bindPathRules(listPathRows().map((rule) => ({ parsed: rule, ruleText: rule.rule })), legAnchors)]) });
|
|
802
|
+
const stampCallTarget = attachmentRootCanonical === undefined ? undefined : legCallTargetStamp({ env: executionEnv, root: attachmentRootCanonical, cwd: () => handsCwdRef?.current, judgesPaths: () => parkLaneArmed || effectivePolicy?.pathRules !== undefined || basePolicyForResumeEdit?.pathRules !== undefined || permissionRuleLane !== undefined || skillSpecs.some((s) => compileSkillGrant(s, "model").rows.some((r) => r.compiled.kind === "path")) || allowedToolTables.request.holdsPathRows() || allowedToolTables.deployment.holdsPathRows(), leads: () => headLeads.resolve([...toolPolicyPathRules([effectivePolicy, basePolicyForResumeEdit, ...(inheritedParentConstraints ?? []).map((c) => c.policy)], legAnchors), ...bindPathRules(listPathRows().map((rule) => ({ parsed: rule, ruleText: rule.rule })), legAnchors)]) });
|
|
800
803
|
const { askLane } = prepareAskLane({ gateMachineryActive, abortController, effectivePolicy, budgetSnapshot, handsCwdRef, handsRoot: attachmentRootCanonical, stampCallTarget, advertisedWritableDirs, exemptRoots: legExemptRoots, tools, inheritedUnavailableAsks, inheritedAskGrants, onAsk, humanReviewRef, now, ruleOffersOf, grantBindingOf, askSourceIdentity, riskAxesOf, autoModeDenialTracking: autoModeDenialTrackingRef, spec, deps, sessionId, runId, modBus: legMods.bus, notifyOwnHookCrash, grantReadRoot: handsReadFace.grantReadRoot });
|
|
801
804
|
const inheritedAnchorRecords = chainAnchorRecords(chainTop, inheritedParentConstraints ?? []);
|
|
802
|
-
const { saga } = prepareSuspendSaga({ gateMachineryActive, abortController, harness, checkpointStore, deps, sessionId, hostTaskId, taskScope, liveSpendRef, resume, nestedStats, internals, activeTools, outputRef, readFileStateForCheckpoint, faceCheckpointSection, writeFaceCheckpointSection, skillGrantCheckpointSection, reminderMark, handsCwdRef, handsRoot: attachmentRootCanonical, handsHome: attachmentRootCanonical !== undefined ? legAnchors.home : undefined, worktreeSessionRef, undeliveredContinuationRef, inheritedParentConstraints, seedInheritedGate, ancestorRulesNow, inheritedShellGate, permissionMode, inheritedAdmittedOrgScopes, inheritedPathRuleAnchors: chainTop !== legAnchors ? inheritedAnchorRecords.pathRuleAnchors : undefined, inheritedPathRuleInstallations: inheritedAnchorRecords.pathRuleInstallations, ownOrgVerdictRef, orgGovernedProvenance, announcedListingsRef, gitStatusRef, hookIdentity, placementRootResolved, checkpointScope, toolCeiling, toolListsJudged, ownToolLists, externalContentTargetActive, remoteEnvFailures, memoryEngineSession, suspendLoopRef, ownedEnv, incompleteSuspendAdapter });
|
|
805
|
+
const { saga } = prepareSuspendSaga({ gateMachineryActive, crossBoundary, abortController, harness, checkpointStore, deps, sessionId, hostTaskId, taskScope, liveSpendRef, resume, nestedStats, internals, activeTools, outputRef, readFileStateForCheckpoint, faceCheckpointSection, writeFaceCheckpointSection, skillGrantCheckpointSection, reminderMark, handsCwdRef, handsRoot: attachmentRootCanonical, handsHome: attachmentRootCanonical !== undefined ? legAnchors.home : undefined, worktreeSessionRef, undeliveredContinuationRef, inheritedParentConstraints, seedInheritedGate, ancestorRulesNow, inheritedShellGate, permissionMode, inheritedAdmittedOrgScopes, inheritedPathRuleAnchors: chainTop !== legAnchors ? inheritedAnchorRecords.pathRuleAnchors : undefined, inheritedPathRuleInstallations: inheritedAnchorRecords.pathRuleInstallations, ownOrgVerdictRef, orgGovernedProvenance, announcedListingsRef, gitStatusRef, hookIdentity, placementRootResolved, checkpointScope, toolCeiling, toolListsJudged, ownToolLists, externalContentTargetActive, remoteEnvFailures, memoryEngineSession, suspendLoopRef, ownedEnv, incompleteSuspendAdapter });
|
|
803
806
|
const { suspendForResource, suspendForPlatformLimit, suspendForReview } = prepareBoundaryParks({ saga, spec, checkpointStore, checkpointScope, abortController, harness, session, sessions, sessionId, deps, priorLedger, maxSlices, maxSuspends, resourceTotal, priorSuspendCount, suspendChainBase, humanReviewRef, liveSpendRef, now, pausedRef, remoteEnvFailures, resourceSuspendEligible, durableSuspendInfraReady, incompleteSuspendAdapter });
|
|
804
807
|
const { parkAsk } = prepareParkAsk({ askLane, saga, spec, deps, sessionId, checkpointStore, checkpointScope, toolRosterDeltas: rosterSeat, parkLaneArmed, contentAskRoutable, liveQuestionFace, mountedQuestionTool, contentAskBindings, lateStrandedAnswers, discloseStrandedAnswers, onAsk, runtimeCaps, inheritedUnavailableAsks, basePolicyForResumeEdit, budgetSnapshot, handsCwdRef, handsRoot: attachmentRootCanonical, stampCallTarget, advertisedWritableDirs, exemptRoots: legExemptRoots, offloadStore, ownedEnv, incompleteSuspendAdapter, session, sessions, suspendChainBase, maxSuspends, remoteEnvFailures, shellGatedTools, irreversibilityTier, toolMarkSources, effectiveShellGate, durableApproval, priorLedger, liveSpendRef, resourceTotal, ruleOffersOf, grantBindingOf, now, humanReviewRef, abortController, harness, pausedRef });
|
|
805
808
|
const seatInputsFor = skillGateWiring({ tools, skillToolName: SKILL_TOOL_NAME, seatOf: skillSeatOf, mode: () => permissionMode.current, lane: skillGrantLane, onAllowed: (info) => emitTrace(deps.tracer, () => ({ kind: "permission.skill_allowed", version: 1, taskId: hostTaskId, ...info, entries: [...info.entries], ts: Date.now() })), allowEntries: { deploymentAllows: { ...allowEntryLanes.deployment, onAllowed: (info) => emitTrace(deps.tracer, () => ({ kind: "permission.allowed_tools_allowed", version: 1, taskId: hostTaskId, source: "deployment", ...info, entries: [...info.entries], ts: Date.now() })) }, requestAllows: { ...allowEntryLanes.request, onAllowed: (info) => emitTrace(deps.tracer, () => ({ kind: "permission.allowed_tools_allowed", version: 1, taskId: hostTaskId, source: "request", ...info, entries: [...info.entries], ts: Date.now() })) } } });
|
|
806
|
-
const { approvedCallScreen } = prepareGateStations({ askLane, parkAsk, tools, toolRosterDeltas: rosterSeat, toolEffects, deps, toolCallGateArmedRef, effectivePolicy, modBus: legMods.bus, inheritedToolChecks, egressTools, irreversibleTools, spec, complianceDenies, harness, blockedToolCalls, inheritedAskGrants, inheritedUnavailableAsks, foldAskClasses, ancestorSandboxAdmissions, preToolContexts, toolOccurrences, batchHaltRef, blockedTracked, hookIdentity, reminderMark, hostTaskId, sessionId, handsCwdRef, stampCallTarget, readDenyInForce: (toolCallId) => ({ tiers: handsReadFace.readDenyBuiltinTiersActive, rows: [...readDenyAdditionsNormalized.map((e) => e.pattern), ...(pathTables?.forCall(toolCallId).ruleRows ?? handsReadFaceInput.denyRuleRows).filter((r) => r.faces.includes("read")).map((r) => r.rule)] }), hookEnvFace, writeProtectionCheck, shellReadCheck, readFace: () => resolvedReadFace, irreversibilityTier, reversibilityProbes, abortController, shellGatedTools, autoModeDecider: autoModeDeciderRef, autoModeDenialTracking: autoModeDenialTrackingRef, askRoute: { ...wiringManifest.ask, effective: askSeatEffective(wiringManifest) }, permissionMode, toolMarkSources, ...(deps.a2a?.isolatePeers === true ? { a2aIsolatePeers: true } : {}), ancestorArbitrations, runId, stopForDenialLimit, permissionRuleLane, seatInputsFor, permissionRuleOrgLane, questionToolMounted, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, delegation, frameSettlement });
|
|
809
|
+
const { approvedCallScreen } = prepareGateStations({ askLane, parkAsk, tools, toolRosterDeltas: rosterSeat, crossBoundaryCheck: crossBoundary.seat({ tools, roster: rosterSeat }), toolEffects, deps, toolCallGateArmedRef, effectivePolicy, modBus: legMods.bus, inheritedToolChecks, egressTools, irreversibleTools, spec, complianceDenies, harness, blockedToolCalls, inheritedAskGrants, inheritedUnavailableAsks, foldAskClasses, ancestorSandboxAdmissions, preToolContexts, toolOccurrences, batchHaltRef, blockedTracked, hookIdentity, reminderMark, hostTaskId, sessionId, handsCwdRef, stampCallTarget, readDenyInForce: (toolCallId) => ({ tiers: handsReadFace.readDenyBuiltinTiersActive, rows: [...readDenyAdditionsNormalized.map((e) => e.pattern), ...(pathTables?.forCall(toolCallId).ruleRows ?? handsReadFaceInput.denyRuleRows).filter((r) => r.faces.includes("read")).map((r) => r.rule)] }), hookEnvFace, writeProtectionCheck, shellReadCheck, readFace: () => resolvedReadFace, irreversibilityTier, reversibilityProbes, abortController, shellGatedTools, autoModeDecider: autoModeDeciderRef, autoModeDenialTracking: autoModeDenialTrackingRef, askRoute: { ...wiringManifest.ask, effective: askSeatEffective(wiringManifest) }, permissionMode, toolMarkSources, ...(deps.a2a?.isolatePeers === true ? { a2aIsolatePeers: true } : {}), ancestorArbitrations, runId, stopForDenialLimit, permissionRuleLane, seatInputsFor, permissionRuleOrgLane, questionToolMounted, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, delegation, frameSettlement });
|
|
807
810
|
const postureFrameRef = { report: (err) => deps.onError?.(err, { phase: "degraded", sessionId }) };
|
|
808
811
|
const { microCompact, charsPerToken } = prepareContextLane({ model, deps, sessionId, runId, hostTaskId, offloadStore, toolRosterDeltas: rosterSeat, microCompactKnob, harness, batchHaltRef, gitStatusRef, postureFrameRef, requestLossyRef, trimPressureRef, contextOverlay: legContextOverlay, ...(readFileStateForCheckpoint !== undefined ? { readFileState: readFileStateForCheckpoint } : {}) });
|
|
809
812
|
const preparedHolder = {};
|
|
810
|
-
const { cacheBreakDetector, cacheFingerprint, promptOverheadTokens,
|
|
813
|
+
const { cacheBreakDetector, cacheFingerprint, promptOverheadTokens, compactionRestore, normalizeAttachmentPath, isDedupStubResult, recentlyReadFiles, onCompactionApplied, detectExternalChanges, syntheticReadVerdict, consolidationWriteJudge, listBackgroundTasks, centerCompactionCandidate, effectiveReadFaceObserved, effectiveWriteFaceObserved, effectiveReadDenyObserved } = prepareTurnWiring({ deps, systemPromptSeat, harnessTools, fpRef, model, promptIdentityDigest: promptManifest.identity.artifact, promptProfile, fableMitigations, systemBlocks, thinking, spec, sessionId, turnSnapshotRef, promptManifest, charsPerToken, handsEnabled, executionEnv, attachmentRootCanonical, readRoots, modelFileReader: modelFileReaderSeat.current, reminderMark, reminderDisclosureCounts, resolvedReadFace, handsCwdRef, readFileStateForCheckpoint, denyNarrowingPolicy, skillGrants: skillGrantLane, callerPolicy: installedToolPolicy, inheritedPolicies: (inheritedParentConstraints ?? []).map((c) => c.policy), persistedRuleLane: permissionRuleLane, ruleLaneFacts, personRowsBeyondRun, orgRuleLane: permissionRuleOrgLane, stampCallTarget, abortController, hostTaskId, taskScope, buildAssembleInputs, identityFor, adoptsCandidates, centerAdoptionRef, harnessRef, carrierReadFace, carrierWriteFace, readDenyAdditionsNormalized, preparedHolder });
|
|
811
814
|
await onceLedger.settle(session, announcedListingsRef);
|
|
812
|
-
const buildPrepared = () => ({ harness, session, sessionId, runId, registryAccess: { owner: hostTaskId, scope: taskScope }, reminderMark, reminderDisclosureCounts, fullShellReachable, approvalPosture: { get mode() { return permissionMode.current; }, askEffective: askSeatEffective(wiringManifest) }, ...(outputStyleFrame !== undefined ? { outputStyleFrame } : {}), permissionMode, editedFilesSnapshot, taskRootPath: taskRootFinal, model, thinking, compModel: effectiveCompModel, mcp, ...(mcpRedial !== undefined ? { mcpRedial } : {}), ...(a2a.tools.length > 0 ? { a2a } : {}), blockedRef, outputRef, abortController, conflictRef, blockedToolCalls, toolOccurrences, batchHaltRef, nestedStats, ...(rewindNotes.length > 0 ? { rewindNotes } : {}), ...(fileHistoryBoundary !== undefined ? { fileHistoryBoundary } : {}), ...(effectiveReadFaceObserved !== undefined ? { effectiveReadFace: effectiveReadFaceObserved, effectiveWriteFace: effectiveWriteFaceObserved } : {}), ...(effectiveReadDenyObserved !== undefined ? { effectiveReadDenyPatterns: effectiveReadDenyObserved } : {}), effectiveMemoryScopes: memoryEffectiveScopes, cwdRef: handsCwdRef, ...(attachmentRootCanonical !== undefined ? { handsRoot: attachmentRootCanonical } : {}), ...(stampCallTarget !== undefined ? { stampCallTarget } : {}), toolProgressRef, ...(advertisedWritableDirs !== undefined ? { advertisedWritableDirs } : {}), exemptRoots: legExemptRoots, ...(worktreeSessionRef !== undefined ? { worktreeSessionRef } : {}), ...(workspaceStateSettle !== undefined ? { workspaceStateSettle } : {}), ...(sealReadStateSeat !== undefined ? { sealReadStateSeat } : {}), denyNarrowingPolicy, skillGrants: skillGrantLane, skillSpecs, ...(permissionRuleLane !== undefined ? { persistedRuleLane: permissionRuleLane } : {}), ...(basePolicyForResumeEdit !== undefined ? { basePolicyForResumeEdit } : {}), consolidationWriteJudge, ...(permissionRuleOrgLane !== undefined ? { permissionRuleOrg: permissionRuleOrgLane } : {}), releaseSignal, endModeCeiling, settleContentAskBindings, cacheBreakDetector, cacheFingerprint, wiringManifest, promptManifest, promptIdentity, 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, stopForDenialLimit, suspendForReview, ...(readFileStateForCheckpoint !== undefined ? { readFileState: readFileStateForCheckpoint } : {}), resourceLedger: priorLedger, liveSpendRef, humanReviewRef, now, tools, toolRoster, toolRosterDeltas: rosterSeat, structuredProjector, toolEffects, wakeRecovered, promptOverheadTokens, lastBrainContext,
|
|
815
|
+
const buildPrepared = () => ({ harness, session, sessionId, runId, crossBoundary, registryAccess: { owner: hostTaskId, scope: taskScope }, reminderMark, reminderDisclosureCounts, fullShellReachable, approvalPosture: { get mode() { return permissionMode.current; }, askEffective: askSeatEffective(wiringManifest) }, ...(outputStyleFrame !== undefined ? { outputStyleFrame } : {}), permissionMode, editedFilesSnapshot, taskRootPath: taskRootFinal, model, thinking, compModel: effectiveCompModel, mcp, ...(mcpRedial !== undefined ? { mcpRedial } : {}), ...(a2a.tools.length > 0 ? { a2a } : {}), blockedRef, outputRef, abortController, conflictRef, blockedToolCalls, toolOccurrences, batchHaltRef, nestedStats, ...(rewindNotes.length > 0 ? { rewindNotes } : {}), ...(fileHistoryBoundary !== undefined ? { fileHistoryBoundary } : {}), ...(effectiveReadFaceObserved !== undefined ? { effectiveReadFace: effectiveReadFaceObserved, effectiveWriteFace: effectiveWriteFaceObserved } : {}), ...(effectiveReadDenyObserved !== undefined ? { effectiveReadDenyPatterns: effectiveReadDenyObserved } : {}), effectiveMemoryScopes: memoryEffectiveScopes, cwdRef: handsCwdRef, ...(attachmentRootCanonical !== undefined ? { handsRoot: attachmentRootCanonical } : {}), ...(stampCallTarget !== undefined ? { stampCallTarget } : {}), toolProgressRef, ...(advertisedWritableDirs !== undefined ? { advertisedWritableDirs } : {}), exemptRoots: legExemptRoots, ...(worktreeSessionRef !== undefined ? { worktreeSessionRef } : {}), ...(workspaceStateSettle !== undefined ? { workspaceStateSettle } : {}), ...(sealReadStateSeat !== undefined ? { sealReadStateSeat } : {}), denyNarrowingPolicy, skillGrants: skillGrantLane, skillSpecs, ...(permissionRuleLane !== undefined ? { persistedRuleLane: permissionRuleLane } : {}), ...(basePolicyForResumeEdit !== undefined ? { basePolicyForResumeEdit } : {}), consolidationWriteJudge, ...(permissionRuleOrgLane !== undefined ? { permissionRuleOrg: permissionRuleOrgLane } : {}), releaseSignal, endModeCeiling, settleContentAskBindings, cacheBreakDetector, cacheFingerprint, wiringManifest, promptManifest, promptIdentity, 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, stopForDenialLimit, suspendForReview, ...(readFileStateForCheckpoint !== undefined ? { readFileState: readFileStateForCheckpoint } : {}), resourceLedger: priorLedger, liveSpendRef, humanReviewRef, now, tools, toolRoster, toolRosterDeltas: rosterSeat, structuredProjector, toolEffects, wakeRecovered, promptOverheadTokens, lastBrainContext, ...(compactionRestore !== undefined ? { compactionRestore } : {}), recentlyReadFiles, normalizeAttachmentPath, isDedupStubResult, ...(onCompactionApplied ? { onCompactionApplied } : {}), compactionReuseRef, trimPressureRef, microCompact, ...(memoryEngineSession ? { memoryEngineSession } : {}), ...(subagentRetain ? { subagentRetain } : {}), ...(lspDiagnostics && nudgeLspOnEdit && withheldDiagnosticsOf ? { lspDiagnostics: { registry: lspDiagnostics, nudge: nudgeLspOnEdit, runIdent: lspRunIdent, withheldOf: withheldDiagnosticsOf } } : {}), 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 }, frameSettlement, ...(userAttachmentsSeat !== undefined ? { userAttachments: userAttachmentsSeat } : {}), attachmentDelivery: createAttachmentDelivery(), ...(modelFileReaderSeat.current !== undefined ? { modelFileReader: modelFileReaderSeat.current } : {}), syntheticReadVerdict, ...(peerLaneRefs.boundaryRound !== undefined ? { peerBoundaryRound: peerLaneRefs.boundaryRound } : {}), gitStatusRef, postureFrameRef, listBackgroundTasks, hookIdentity, modBus: legMods.bus, sideCallBookRef, ...(sessionBoxBound !== undefined ? { sessionBox: sessionBoxBound } : {}), ...(turnSnapshotRef.current !== undefined ? { turnSnapshot: turnSnapshotRef.current } : {}), ...(centerCompactionCandidate !== undefined ? { centerCompactionCandidate } : {}), ...(shellReadCheck !== undefined ? { shellReadCheck } : {}), ...(toolDisclosureSeat !== undefined ? { toolDisclosure: toolDisclosureSeat } : {}), ...(approvedCallScreen !== undefined ? { approvedCallScreen } : {}) });
|
|
813
816
|
refuseLateRosterChanges(callerRoster.roster);
|
|
814
817
|
rollback.commit();
|
|
815
818
|
commitModeSeats(abortController.signal);
|
|
@@ -12,10 +12,11 @@ import { type ConsolidationWriteJudgeLeg } from "./memory-consolidation-write-ju
|
|
|
12
12
|
import type { RunnerDeps, TaskSpec } from "../types.js";
|
|
13
13
|
import type { CwdRef } from "../../tools/fs/fs-shared.js";
|
|
14
14
|
import { type ContainmentFace } from "../../tools/fs/index.js";
|
|
15
|
-
import type { PlacedReadDenyMatcher } from "../../tools/fs/read-deny-home.js";
|
|
16
15
|
import type { ReadRootsSeat } from "./person-path-rows.js";
|
|
17
16
|
import { type ReadFileState } from "../../tools/fs/safety.js";
|
|
18
17
|
import type { Prepared } from "./contracts.js";
|
|
18
|
+
import type { ModelFileReader } from "../../tools/fs/fs-read.js";
|
|
19
|
+
import type { ReminderDisclosureCounts } from "../reminder-disclosure.js";
|
|
19
20
|
export interface PrepareTurnWiringInput {
|
|
20
21
|
/** borrowed-readonly — the deployment seats: `cacheBreakDetection` (the detector knob), `onError` (the attachment-skip
|
|
21
22
|
* degraded line), `promptSource` (the center candidate's state and current artifact), `permissionRuleStore` and
|
|
@@ -73,8 +74,12 @@ export interface PrepareTurnWiringInput {
|
|
|
73
74
|
/** borrowed-readonly — the read face's root set beside the attachment root, read per use: the write roots, the read
|
|
74
75
|
* roots with the run's grants, the person's read directories as the run read them last (no call: `ready` first). */
|
|
75
76
|
readRoots: (() => readonly string[]) & Pick<ReadRootsSeat, "ready">;
|
|
76
|
-
/** borrowed-readonly — the
|
|
77
|
-
|
|
77
|
+
/** borrowed-readonly — the leg's one file reader (the hands band's), or undefined without hands: the restore reads through it. */
|
|
78
|
+
modelFileReader: ModelFileReader | undefined;
|
|
79
|
+
/** borrowed-readonly — the run's reminder mark (the restore frames' marked blocks). */
|
|
80
|
+
reminderMark: string | undefined;
|
|
81
|
+
/** borrowed-mutable — the run's disclosure counters; the restore frames' scans bump them when a frame is delivered. */
|
|
82
|
+
reminderDisclosureCounts: ReminderDisclosureCounts | undefined;
|
|
78
83
|
/** borrowed-readonly — the resolved read face, or undefined (the fence's ninth argument). */
|
|
79
84
|
resolvedReadFace: ContainmentFace | undefined;
|
|
80
85
|
/** borrowed-readonly — the tracked-cwd seat, read per call by the kept-tail normalizer (never written here). */
|
|
@@ -148,8 +153,8 @@ export interface PrepareTurnWiringResult {
|
|
|
148
153
|
} | undefined;
|
|
149
154
|
/** owned — the fixed prompt-overhead term in the compaction trigger's coordinate (`Prepared.promptOverheadTokens`). */
|
|
150
155
|
promptOverheadTokens: number;
|
|
151
|
-
/** owned — the
|
|
152
|
-
|
|
156
|
+
/** owned — the post-compaction restore, or undefined without hands (`Prepared.compactionRestore`). */
|
|
157
|
+
compactionRestore: Prepared["compactionRestore"];
|
|
153
158
|
/** owned — the kept-tail path normalizer, or undefined without hands. */
|
|
154
159
|
normalizeAttachmentPath: Prepared["normalizeAttachmentPath"];
|
|
155
160
|
/** owned — the Read tool's dedup-stub predicate, or undefined without hands. */
|
|
@@ -8,14 +8,13 @@ import { createSyntheticReadJudge } from "../synthetic-read-verdict.js";
|
|
|
8
8
|
import { createConsolidationWriteJudge } from "./memory-consolidation-write-judge.js";
|
|
9
9
|
import { toolCallFaceOf } from "../tool-roster.js";
|
|
10
10
|
import { ORG_ADJUDICATION_TIMEOUT_MS } from "../permission-rule-org.js";
|
|
11
|
-
import {
|
|
12
|
-
import { applyContextShrinkToReadFileState, isReadDedupStubResult } from "../../tools/fs/index.js";
|
|
11
|
+
import { applyContextShrinkToReadFileState, isReadDedupStubResult, readFileStateAfterSummary } from "../../tools/fs/index.js";
|
|
13
12
|
import { resolveKey } from "../../tools/fs/safety.js";
|
|
14
13
|
import { PROMPT_HASH_SALT } from "./prompt-hash-salt.js";
|
|
15
14
|
import { CHANGED_FILES_MTIME_EPS_MS } from "./turn-attachments.js";
|
|
16
|
-
import {
|
|
15
|
+
import { readCompactionRestore } from "../user-attachment.js";
|
|
17
16
|
export function prepareTurnWiring(input) {
|
|
18
|
-
const { deps, systemPromptSeat, harnessTools, fpRef, model, promptIdentityDigest, promptProfile, fableMitigations, systemBlocks, thinking, spec, sessionId, turnSnapshotRef, promptManifest, charsPerToken, handsEnabled, executionEnv, attachmentRootCanonical, readRoots,
|
|
17
|
+
const { deps, systemPromptSeat, harnessTools, fpRef, model, promptIdentityDigest, promptProfile, fableMitigations, systemBlocks, thinking, spec, sessionId, turnSnapshotRef, promptManifest, charsPerToken, handsEnabled, executionEnv, attachmentRootCanonical, readRoots, modelFileReader, reminderMark, reminderDisclosureCounts, resolvedReadFace, handsCwdRef, readFileStateForCheckpoint, denyNarrowingPolicy, skillGrants, callerPolicy, inheritedPolicies, persistedRuleLane, ruleLaneFacts, personRowsBeyondRun, orgRuleLane, stampCallTarget, abortController, hostTaskId, taskScope, buildAssembleInputs, identityFor, adoptsCandidates, centerAdoptionRef, harnessRef, carrierReadFace, carrierWriteFace, readDenyAdditionsNormalized, preparedHolder } = input;
|
|
19
18
|
const cacheBreakDetector = deps.cacheBreakDetection === false ? undefined : new CacheBreakDetector();
|
|
20
19
|
const cacheFingerprint = cacheBreakDetector
|
|
21
20
|
? { systemPrompt: systemPromptSeat.current, tools: toolsToFingerprintInputs(harnessTools) }
|
|
@@ -41,49 +40,6 @@ export function prepareTurnWiring(input) {
|
|
|
41
40
|
promptManifest.lowering = turnSnapshot.lowering;
|
|
42
41
|
const promptOverheadTokens = Math.ceil((systemPromptSeat.current.length +
|
|
43
42
|
harnessTools.reduce((a, t) => a + t.name.length + (t.description?.length ?? 0) + JSON.stringify(t.parameters ?? {}).length, 0)) / charsPerToken);
|
|
44
|
-
const announceAttachmentSkip = (path, reason) => {
|
|
45
|
-
deps.onError?.(new Error(`working-file attachment skipped — ${path}: ${reason}`), {
|
|
46
|
-
phase: "degraded",
|
|
47
|
-
sessionId,
|
|
48
|
-
classification: "attachment-read",
|
|
49
|
-
});
|
|
50
|
-
};
|
|
51
|
-
const readTaskFile = handsEnabled
|
|
52
|
-
? async (path) => {
|
|
53
|
-
try {
|
|
54
|
-
let key = path;
|
|
55
|
-
if (attachmentRootCanonical !== undefined) {
|
|
56
|
-
await readRoots.ready(abortController.signal);
|
|
57
|
-
if (abortController.signal.aborted)
|
|
58
|
-
return null;
|
|
59
|
-
const rk = await resolveKey(executionEnv, attachmentRootCanonical, path, abortController.signal, undefined, readRoots(), undefined, readDenyMatcher, resolvedReadFace);
|
|
60
|
-
if (!rk.ok) {
|
|
61
|
-
announceAttachmentSkip(path, rk.violation.message);
|
|
62
|
-
if (rk.violation.code === "read_path_denied" && rk.violation.pattern !== undefined) {
|
|
63
|
-
return { withheld: { pattern: rk.violation.pattern } };
|
|
64
|
-
}
|
|
65
|
-
return null;
|
|
66
|
-
}
|
|
67
|
-
key = rk.key;
|
|
68
|
-
}
|
|
69
|
-
const r = await executionEnv.readBinaryFile(key, abortController.signal);
|
|
70
|
-
if (!r.ok) {
|
|
71
|
-
announceAttachmentSkip(path, r.error.message);
|
|
72
|
-
return null;
|
|
73
|
-
}
|
|
74
|
-
const d = decodeTextBytes(r.value);
|
|
75
|
-
if (d.malformed) {
|
|
76
|
-
announceAttachmentSkip(path, "malformed text encoding (truncated UTF-16 body)");
|
|
77
|
-
return null;
|
|
78
|
-
}
|
|
79
|
-
return d.text;
|
|
80
|
-
}
|
|
81
|
-
catch (err) {
|
|
82
|
-
announceAttachmentSkip(path, thrownText(err));
|
|
83
|
-
return null;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
: undefined;
|
|
87
43
|
const normalizeAttachmentPath = handsEnabled
|
|
88
44
|
? async (path) => {
|
|
89
45
|
if (attachmentRootCanonical === undefined)
|
|
@@ -108,7 +64,7 @@ export function prepareTurnWiring(input) {
|
|
|
108
64
|
.map(([path]) => path)
|
|
109
65
|
: undefined;
|
|
110
66
|
const onCompactionApplied = handsEnabled && readFileStateForCheckpoint
|
|
111
|
-
? (
|
|
67
|
+
? (preserveReadState) => applyContextShrinkToReadFileState(readFileStateForCheckpoint, { kind: "summarized", preserveKeys: preserveReadState })
|
|
112
68
|
: undefined;
|
|
113
69
|
const syntheticLayers = {
|
|
114
70
|
skillGrants,
|
|
@@ -120,6 +76,15 @@ export function prepareTurnWiring(input) {
|
|
|
120
76
|
...(stampCallTarget !== undefined ? { stampCallTarget } : {}),
|
|
121
77
|
};
|
|
122
78
|
const syntheticReadVerdict = createSyntheticReadJudge({ ...syntheticLayers, signal: abortController.signal });
|
|
79
|
+
const announceRestoreSkip = (path, reason) => {
|
|
80
|
+
deps.onError?.(new Error(`compaction restore did not deliver ${path}: ${reason}`), { phase: "degraded", sessionId, classification: "attachment-read" });
|
|
81
|
+
};
|
|
82
|
+
const compactionRestore = handsEnabled && modelFileReader !== undefined
|
|
83
|
+
? {
|
|
84
|
+
restore: (ask) => readCompactionRestore({ reader: modelFileReader, judge: syntheticReadVerdict, cwd: () => handsCwdRef?.current, mark: reminderMark, counts: reminderDisclosureCounts, signal: abortController.signal, report: announceRestoreSkip }, { candidates: ask.candidates, maxFiles: ask.maxFiles, perFileChars: ask.perFileChars, totalChars: ask.totalChars, charsPerToken: ask.charsPerToken, dedupAgainst: readFileStateAfterSummary(readFileStateForCheckpoint ?? new Map(), ask.preserveKeys) }),
|
|
85
|
+
undelivered: announceRestoreSkip,
|
|
86
|
+
}
|
|
87
|
+
: undefined;
|
|
123
88
|
const consolidationWriteJudge = createConsolidationWriteJudge({ ruleStoreProvider: deps.permissionRuleStore, principal: spec.principal, localOwnerDeclared: deps.localOwnerRules === true, ...(callerPolicy !== undefined ? { callerPolicy } : {}) }, { rows: personRowsBeyondRun, lanes: ruleLaneFacts, layers: { skillGrants, ...(denyNarrowingPolicy !== undefined ? { denyNarrowingPolicy } : {}), inheritedPolicies, ...(stampCallTarget !== undefined ? { stampCallTarget } : {}) }, facts: () => {
|
|
124
89
|
const p = preparedHolder.current;
|
|
125
90
|
return { face: toolCallFaceOf(p?.toolRoster, "Write"), cwd: p?.cwdRef?.current, root: p?.handsRoot, advertisedWritableDirs: p?.advertisedWritableDirs, exemptRoots: p?.exemptRoots };
|
|
@@ -218,5 +183,5 @@ export function prepareTurnWiring(input) {
|
|
|
218
183
|
const effectiveReadFaceObserved = carrierReadFace();
|
|
219
184
|
const effectiveWriteFaceObserved = carrierWriteFace();
|
|
220
185
|
const effectiveReadDenyObserved = readDenyAdditionsNormalized.length > 0 ? readDenyAdditionsNormalized.map((e) => ({ ...e })) : undefined;
|
|
221
|
-
return { cacheBreakDetector, cacheFingerprint, promptOverheadTokens,
|
|
186
|
+
return { cacheBreakDetector, cacheFingerprint, promptOverheadTokens, compactionRestore, normalizeAttachmentPath, isDedupStubResult, recentlyReadFiles, onCompactionApplied, detectExternalChanges, syntheticReadVerdict, consolidationWriteJudge, listBackgroundTasks, centerCompactionCandidate, effectiveReadFaceObserved, effectiveWriteFaceObserved, effectiveReadDenyObserved };
|
|
222
187
|
}
|
|
@@ -82,9 +82,9 @@ export interface PrepareWiringManifestInput {
|
|
|
82
82
|
irreversibleTools: ReadonlySet<string>;
|
|
83
83
|
/** borrowed-readonly — see `irreversibleTools`. */
|
|
84
84
|
egressTools: ReadonlySet<string>;
|
|
85
|
-
/** borrowed-readonly — the hands phase mounted the shell READ STATION (a real shell was mounted): the gate
|
|
86
|
-
* machinery must run for it, under every doctrine — the read-only face's containment IS that station. */
|
|
85
|
+
/** borrowed-readonly — the hands phase mounted the shell READ STATION (a real shell was mounted): the gate machinery must run for it, under every doctrine. */
|
|
87
86
|
shellReadStationArmed: boolean;
|
|
87
|
+
/** borrowed-readonly — the leg's cross-boundary station is engaged (a declared posture, a target leg, a governed tree): the gate machinery runs for it. */ crossBoundaryStationEngaged: boolean;
|
|
88
88
|
/** borrowed-readonly — the effect collection; read only here (the ungated scans). */
|
|
89
89
|
toolEffects: ReadonlyMap<string, ToolEffect>;
|
|
90
90
|
/** borrowed-readonly — the per-task owned env when a factory minted one (durable infra, the hook-env predicate). */
|
|
@@ -117,7 +117,7 @@ function announceDurableGateUnavailable(args) {
|
|
|
117
117
|
});
|
|
118
118
|
}
|
|
119
119
|
export function prepareWiringManifest(input) {
|
|
120
|
-
const { spec, deps, internals, resume, sessionId, runId, hostTaskId, taskScope, modBus, checkpointScope, policyLayers, effectivePolicy, handsEnabled, taskRootFinal, legWriteGuard, mcp, irreversibleTools, egressTools, toolEffects, ownedEnv, executionEnv, offloadStore, onceLedger, usageWindows, envLifetimeSuspendAt, runtimeCaps, resolvedInteractionPosture, durableQuestionFace, liveQuestionFace, checkpointStore, sessions, modelGateManifest, autoModeArmReason, permissionMode, lockedPreflight, peerLaneRefs, frameSettlement, sessionBox, harness, pausedRef, askSeat, liveInheritedGate, delegation, toolRoster, readDenyBuiltinTiersActive, lspManagerWired, shellReadStationArmed, lspDiagnosticsLive, fileHistoryFact, memoryPollution } = input;
|
|
120
|
+
const { spec, deps, internals, resume, sessionId, runId, hostTaskId, taskScope, modBus, checkpointScope, policyLayers, effectivePolicy, handsEnabled, taskRootFinal, legWriteGuard, mcp, irreversibleTools, egressTools, toolEffects, ownedEnv, executionEnv, offloadStore, onceLedger, usageWindows, envLifetimeSuspendAt, runtimeCaps, resolvedInteractionPosture, durableQuestionFace, liveQuestionFace, checkpointStore, sessions, modelGateManifest, autoModeArmReason, permissionMode, lockedPreflight, peerLaneRefs, frameSettlement, sessionBox, harness, pausedRef, askSeat, liveInheritedGate, delegation, toolRoster, readDenyBuiltinTiersActive, lspManagerWired, shellReadStationArmed, crossBoundaryStationEngaged, lspDiagnosticsLive, fileHistoryFact, memoryPollution } = input;
|
|
121
121
|
const onAsk = askSeat.value;
|
|
122
122
|
const handWriteTools = toolRoster.entries.filter((e) => e.mountedBy === "hands" && (e.effect === "write" || e.effect === "idempotent")).map((e) => e.name);
|
|
123
123
|
const hasEffectAwareGate = policyLayers.length > 0 || chainJudges(modBus);
|
|
@@ -249,7 +249,7 @@ export function prepareWiringManifest(input) {
|
|
|
249
249
|
modBus.hasHandlers("classic.PreToolUse") ||
|
|
250
250
|
egressTools.size > 0 ||
|
|
251
251
|
irreversibleTools.size > 0 ||
|
|
252
|
-
shellReadStationArmed ||
|
|
252
|
+
shellReadStationArmed || crossBoundaryStationEngaged ||
|
|
253
253
|
resourceSuspendEligible ||
|
|
254
254
|
platformSuspendArmed ||
|
|
255
255
|
spec.enablePlanMode === true;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isRemoteExecutionEnv, missingRestoreSurface } from "../remote-env.js";
|
|
1
|
+
import { frozenHandleCopy, isRemoteExecutionEnv, missingRestoreSurface } from "../remote-env.js";
|
|
2
2
|
import { remoteEnvFailureNote, restoreWorkspaceWithRetry } from "./remote-env-retry.js";
|
|
3
3
|
import { rebaseWorkspacePathAcross } from "./workspace-path.js";
|
|
4
4
|
export { remoteEnvFailureNote, restoreWorkspaceWithRetry } from "./remote-env-retry.js";
|
|
@@ -49,7 +49,7 @@ export async function prepareWorkspaceRestore(input) {
|
|
|
49
49
|
refuseIdentityMismatch(ownedEnv.workspaceHandle());
|
|
50
50
|
const { outcome: restored, attempts: restoreAttempts } = await restoreWorkspaceWithRetry(ownedEnv, handle.snapshotId, {
|
|
51
51
|
abortSignal: restoreSignal,
|
|
52
|
-
priorHandle: handle,
|
|
52
|
+
priorHandle: frozenHandleCopy(handle),
|
|
53
53
|
});
|
|
54
54
|
if (!restored.ok) {
|
|
55
55
|
failResume(`resumeVM failed after ${restoreAttempts} attempt(s) (${restored.error.code}): ${restored.error.message}`, restored.error, remoteEnvFailureNote("resumeVM", restored.error, restoreAttempts));
|
|
@@ -3,6 +3,14 @@ import { assertResumeConfigRecord, checkpointStoreSeat, refuseResumeDoors } from
|
|
|
3
3
|
import { asResumeConfigRefusal } from "../mode-policy.js";
|
|
4
4
|
import { describeSuppliedValue } from "./decide-continuation.js";
|
|
5
5
|
import { detachSkillLists } from "../skill-grant.js";
|
|
6
|
+
import { isGateKind, PAUSE_REGISTRY } from "../pause-registry.js";
|
|
7
|
+
const DECIDE_ENTRY_BY_RESUME_GATE = {
|
|
8
|
+
policy_ask: "a `policy_ask` outcome (decision allow/deny bound to the pending tool call)",
|
|
9
|
+
dry_run_review: "a `dry_run_review` outcome (decision approve/reject)",
|
|
10
|
+
plan_review: "a `plan_review` outcome (decision approve/edit/reject)",
|
|
11
|
+
resource_limit: 'a `resource_limit` outcome (decision "continue")',
|
|
12
|
+
task_done: undefined,
|
|
13
|
+
};
|
|
6
14
|
export async function resumeAdmission(input) {
|
|
7
15
|
const { token, outcome, taskConfig, runner, sessions, parentConstraintRegistry } = input;
|
|
8
16
|
let internals = input.internals;
|
|
@@ -46,15 +54,7 @@ export async function resumeAdmission(input) {
|
|
|
46
54
|
if (outcomeGate === "wake") {
|
|
47
55
|
suppliedMessage = outcome.message;
|
|
48
56
|
const gk = cp.gate.kind;
|
|
49
|
-
const decideEntry = gk
|
|
50
|
-
? 'a `policy_ask` outcome (decision allow/deny bound to the pending tool call)'
|
|
51
|
-
: gk === "needs_review"
|
|
52
|
-
? 'a `dry_run_review` outcome (decision approve/reject)'
|
|
53
|
-
: gk === "plan_review"
|
|
54
|
-
? 'a `plan_review` outcome (decision approve/edit/reject)'
|
|
55
|
-
: gk === "resource_limit"
|
|
56
|
-
? 'a `resource_limit` outcome (decision "continue")'
|
|
57
|
-
: undefined;
|
|
57
|
+
const decideEntry = isGateKind(gk) ? DECIDE_ENTRY_BY_RESUME_GATE[PAUSE_REGISTRY[gk].resume] : undefined;
|
|
58
58
|
if (gk !== "task_done") {
|
|
59
59
|
throw new CheckpointError("wake.gate_pending", `cannot wake: this checkpoint awaits a pending gate decision (gate "${gk}") — wake is not a decision ` +
|
|
60
60
|
`channel; resume it with ${decideEntry ?? "its own gate outcome"} instead`);
|
|
@@ -13,7 +13,7 @@ import { orgVerdictBeforeClaim } from "./permission-rule-lanes.js";
|
|
|
13
13
|
import { chainCannotJudge } from "./call-hook-stations.js";
|
|
14
14
|
import { thrownText } from "../thrown-value.js";
|
|
15
15
|
import { wireOf } from "../tool-name-readings.js";
|
|
16
|
-
import {
|
|
16
|
+
import { judgeApprovalObject } from "../approval-object.js";
|
|
17
17
|
import { SKILL_CONTENT_MAX_CHARS, SKILL_TOOL_NAME, normalizeSkills } from "./synthetic-tools.js";
|
|
18
18
|
import { skillLoadReading } from "./skill-base-dir.js";
|
|
19
19
|
export async function resumeApply(input) {
|
|
@@ -76,9 +76,9 @@ export async function resumeApply(input) {
|
|
|
76
76
|
};
|
|
77
77
|
if (plainPolicyOutcome?.decision === "allow" && cp.pendingAction.kind === "tool_approval") {
|
|
78
78
|
const servedSkills = normalizeSkills(config.skills).filter((s) => skillLoadReading(s, SKILL_CONTENT_MAX_CHARS).loads);
|
|
79
|
-
const
|
|
80
|
-
if (
|
|
81
|
-
throw new CheckpointError("checkpoint.invalid_outcome",
|
|
79
|
+
const claimed = judgeApprovalObject(cp.pendingAction, { args: plainPolicyOutcome.updatedInput ?? cp.pendingAction.args, skills: servedSkills, skillToolName: SKILL_TOOL_NAME }, "claim");
|
|
80
|
+
if (claimed !== "match")
|
|
81
|
+
throw new CheckpointError("checkpoint.invalid_outcome", claimed.message, { field: "boundGrantDigest" });
|
|
82
82
|
}
|
|
83
83
|
if (plainPolicyOutcome !== undefined &&
|
|
84
84
|
plainPolicyOutcome.decision === "allow" &&
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The resume ladder's APPROVAL-LANE capture and binding rung (E4), verbatim from
|
|
3
3
|
* `Runner.resumeStream`: on a human / irreversible_ask row every deployment-supplied field of the
|
|
4
|
-
* `policy_ask` decide is read exactly once into a plain twin (answer
|
|
5
|
-
* JSON
|
|
4
|
+
* `policy_ask` decide is read exactly once into a plain twin (answer and updatedInput by the one capture, in their
|
|
5
|
+
* JSON form, the decision word, the refused keys, the host's decision facts and attribution, the deny note),
|
|
6
6
|
* then the decision-action binding (boundCallId, boundInputHash by version), the env_failed replay guard and
|
|
7
7
|
* the content-ask answer binding. Synchronous; every refusal throws pre-CAS.
|
|
8
8
|
*/
|