@sema-agent/core 7.33.7 → 7.34.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 +357 -0
- package/dist/agents/cross-session-judge.d.ts +16 -7
- package/dist/agents/cross-session-judge.js +18 -15
- package/dist/agents/peer-session-drain.d.ts +4 -0
- package/dist/agents/peer-session-drain.js +5 -2
- package/dist/agents/repair-loop.d.ts +1 -1
- package/dist/agents/subagent.d.ts +3 -0
- package/dist/agents/subagent.js +12 -3
- package/dist/brain/anthropic.js +1 -0
- package/dist/brain/open-responses.js +1 -0
- package/dist/brain/openai.js +1 -0
- package/dist/brain/stream-engine.d.ts +3 -0
- package/dist/brain/stream-engine.js +2 -1
- package/dist/core/a2a.d.ts +3 -1
- package/dist/core/a2a.js +1 -1
- package/dist/core/ask-origin.d.ts +351 -154
- package/dist/core/ask-origin.js +223 -45
- package/dist/core/ask-unresolvable-notice.d.ts +5 -2
- package/dist/core/ask-unresolvable-notice.js +4 -3
- package/dist/core/auto-mode-arming.d.ts +17 -4
- package/dist/core/auto-mode-arming.js +31 -6
- package/dist/core/auto-mode-defaults.d.ts +16 -7
- package/dist/core/auto-mode-defaults.js +2 -1
- package/dist/core/auto-mode-directive.d.ts +18 -30
- package/dist/core/auto-mode-directive.js +9 -18
- package/dist/core/auto-mode-prompt.d.ts +62 -1
- package/dist/core/auto-mode-prompt.js +42 -4
- package/dist/core/auto-mode-rebuild.d.ts +2 -1
- package/dist/core/auto-mode-rebuild.js +1 -0
- package/dist/core/auto-mode.d.ts +32 -3
- package/dist/core/auto-mode.js +80 -41
- package/dist/core/checkpoint-store.d.ts +50 -35
- package/dist/core/checkpoint-store.js +58 -3
- package/dist/core/child-clamp-seats.js +1 -0
- package/dist/core/classifier-unavailable-arm.d.ts +57 -0
- package/dist/core/classifier-unavailable-arm.js +17 -0
- package/dist/core/effective-path-target.d.ts +12 -0
- package/dist/core/effective-path-target.js +18 -7
- package/dist/core/engine-notice.d.ts +53 -2
- package/dist/core/fs-write-gate-policy.d.ts +5 -1
- package/dist/core/fs-write-gate-policy.js +4 -1
- package/dist/core/gate-fold.js +17 -1
- package/dist/core/gate-lanes.js +111 -46
- package/dist/core/gate-outcome.d.ts +40 -7
- package/dist/core/gate-outcome.js +26 -4
- package/dist/core/governance-codes.d.ts +1 -1
- package/dist/core/governance-codes.js +12 -0
- package/dist/core/hooks.d.ts +50 -29
- package/dist/core/hooks.js +1 -3
- package/dist/core/mcp.js +1 -1
- package/dist/core/mode-policy.d.ts +182 -0
- package/dist/core/mode-policy.js +179 -0
- package/dist/core/oracle-isolation.d.ts +3 -3
- package/dist/core/permission-rule-model.d.ts +16 -3
- package/dist/core/permission-rule-model.js +36 -3
- package/dist/core/permission-rule-provider.d.ts +22 -11
- package/dist/core/permission-rule-provider.js +17 -7
- package/dist/core/permission-rules.d.ts +23 -1
- package/dist/core/permission-rules.js +35 -8
- package/dist/core/persisted-rule-arms.d.ts +10 -9
- package/dist/core/persisted-rule-arms.js +9 -6
- package/dist/core/present-plan-tool.d.ts +1 -1
- package/dist/core/present-plan-tool.js +3 -3
- package/dist/core/read-only-shell.d.ts +19 -19
- package/dist/core/read-only-shell.js +38 -12
- package/dist/core/retired-keys.d.ts +9 -3
- package/dist/core/retired-keys.js +5 -1
- package/dist/core/runner/classifier-ladder.d.ts +43 -1
- package/dist/core/runner/classifier-ladder.js +29 -0
- package/dist/core/runner/contracts.d.ts +37 -35
- package/dist/core/runner/denial-limit-arms.d.ts +30 -7
- package/dist/core/runner/denial-limit-arms.js +15 -9
- package/dist/core/runner/env-capability-census.js +1 -1
- package/dist/core/runner/gate-exit.d.ts +30 -4
- package/dist/core/runner/gate-exit.js +28 -7
- package/dist/core/runner/permission-rule-lanes.d.ts +9 -5
- package/dist/core/runner/permission-rule-lanes.js +44 -40
- package/dist/core/runner/persisted-path-rows.d.ts +64 -0
- package/dist/core/runner/persisted-path-rows.js +89 -0
- package/dist/core/runner/prepare-artifact.d.ts +5 -1
- package/dist/core/runner/prepare-artifact.js +9 -3
- package/dist/core/runner/prepare-ask-lane.d.ts +5 -3
- package/dist/core/runner/prepare-ask-lane.js +1 -1
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +39 -13
- package/dist/core/runner/prepare-caps-and-workflow.js +58 -29
- package/dist/core/runner/prepare-gate-stations.d.ts +33 -6
- package/dist/core/runner/prepare-gate-stations.js +32 -19
- package/dist/core/runner/prepare-hands-readface.d.ts +40 -17
- package/dist/core/runner/prepare-hands-readface.js +64 -53
- package/dist/core/runner/prepare-inherited-gate.d.ts +22 -22
- package/dist/core/runner/prepare-inherited-gate.js +37 -23
- package/dist/core/runner/prepare-park-ask.d.ts +2 -2
- package/dist/core/runner/prepare-park-ask.js +2 -1
- package/dist/core/runner/prepare-policy-chain.d.ts +22 -2
- package/dist/core/runner/prepare-policy-chain.js +39 -12
- package/dist/core/runner/prepare-protocol-tools.d.ts +28 -0
- package/dist/core/runner/prepare-protocol-tools.js +13 -3
- package/dist/core/runner/prepare-run-refs.d.ts +6 -6
- package/dist/core/runner/prepare-run-refs.js +9 -4
- package/dist/core/runner/prepare-safety-scan.d.ts +5 -0
- package/dist/core/runner/prepare-safety-scan.js +19 -3
- package/dist/core/runner/prepare-suspend-saga.d.ts +5 -5
- package/dist/core/runner/prepare-suspend-saga.js +6 -6
- package/dist/core/runner/prepare-task.js +51 -22
- package/dist/core/runner/prepare-wiring-manifest.d.ts +10 -6
- package/dist/core/runner/prepare-wiring-manifest.js +5 -3
- package/dist/core/runner/read-root-grant.d.ts +9 -0
- package/dist/core/runner/read-root-grant.js +12 -0
- package/dist/core/runner/retired-runner-deps.js +1 -0
- package/dist/core/runner/run-identity-wiring.js +1 -1
- package/dist/core/runner/run-leg.js +24 -15
- package/dist/core/runner/run-notification-lane.js +1 -0
- package/dist/core/runner/run-telemetry-and-budget-seats.d.ts +2 -2
- package/dist/core/runner/run-telemetry-and-budget-seats.js +1 -1
- package/dist/core/runner/run-turn-boundary.js +1 -1
- package/dist/core/runner/runtask.js +3 -0
- package/dist/core/runner/stream-mode-verb.d.ts +27 -0
- package/dist/core/runner/stream-mode-verb.js +19 -0
- package/dist/core/runner/turn-attachments.d.ts +3 -3
- package/dist/core/runner/turn-attachments.js +1 -1
- package/dist/core/runner/write-protection-station.d.ts +7 -1
- package/dist/core/runner/write-protection-station.js +6 -3
- package/dist/core/runner-deps.d.ts +31 -34
- package/dist/core/runtime-caps.d.ts +12 -3
- package/dist/core/safety-axis-vocab.d.ts +2 -2
- package/dist/core/safety-axis-vocab.js +1 -1
- package/dist/core/secret-env.d.ts +16 -2
- package/dist/core/secret-env.js +25 -1
- package/dist/core/sensitive-path-policy.d.ts +4 -2
- package/dist/core/sensitive-path-policy.js +39 -30
- package/dist/core/spec-contract.d.ts +15 -0
- package/dist/core/spec-contract.js +19 -10
- package/dist/core/task-event.d.ts +1 -1
- package/dist/core/task-result.d.ts +1 -1
- package/dist/core/task-spec.d.ts +41 -89
- package/dist/core/task-stream.d.ts +16 -0
- package/dist/core/terminal-cause.js +1 -0
- package/dist/core/tighten-task-spec.d.ts +2 -2
- package/dist/core/tighten-task-spec.js +12 -14
- package/dist/core/tool-catalog-entries.js +4 -3
- package/dist/core/tool-policy.d.ts +54 -25
- package/dist/core/tool-policy.js +43 -2
- package/dist/core/tool-registry.d.ts +2 -0
- package/dist/core/tool-registry.js +3 -0
- package/dist/core/tool-spec.d.ts +8 -9
- package/dist/core/trace.d.ts +7 -6
- package/dist/core/types.d.ts +2 -1
- package/dist/core/wiring-manifest.d.ts +31 -5
- package/dist/core/wiring-manifest.js +28 -1
- package/dist/core/write-protect.d.ts +11 -1
- package/dist/core/write-protect.js +26 -15
- package/dist/engine/execution-env/kill-tree.js +4 -1
- package/dist/engine/execution-env/node-execution-env.d.ts +3 -0
- package/dist/engine/execution-env/node-execution-env.js +34 -35
- package/dist/engine/harness/types.d.ts +6 -7
- package/dist/engine/llm/types.d.ts +2 -4
- package/dist/engine/loop/types.d.ts +7 -0
- package/dist/index.d.ts +15 -5
- package/dist/index.js +12 -3
- package/dist/orchestration/run-spec.d.ts +4 -0
- package/dist/orchestration/run-spec.js +4 -3
- package/dist/orchestration/workflow-governance.js +1 -1
- package/dist/orchestration/workflow-primitives.d.ts +1 -1
- package/dist/orchestration/workflow-size-guideline.js +2 -2
- package/dist/stores/file/fs-atomic.js +2 -1
- package/dist/tools/artifact/artifact-tool.d.ts +17 -0
- package/dist/tools/artifact/artifact-tool.js +16 -1
- package/dist/tools/fs/bash-readonly-classifier.d.ts +28 -7
- package/dist/tools/fs/bash-readonly-classifier.js +88 -0
- package/dist/tools/fs/containment-face.d.ts +9 -3
- package/dist/tools/fs/containment-face.js +2 -0
- package/dist/tools/fs/file-read-check.d.ts +49 -0
- package/dist/tools/fs/file-read-check.js +71 -0
- package/dist/tools/fs/fs-bash.d.ts +3 -3
- package/dist/tools/fs/fs-read.d.ts +1 -0
- package/dist/tools/fs/fs-search-tools.d.ts +2 -2
- package/dist/tools/fs/fs-search-tools.js +4 -4
- package/dist/tools/fs/fs-shared.js +20 -6
- package/dist/tools/fs/fs-write.d.ts +4 -3
- package/dist/tools/fs/fs-write.js +9 -9
- package/dist/tools/fs/index.d.ts +39 -3
- package/dist/tools/fs/index.js +38 -15
- package/dist/tools/fs/read-deny-home.d.ts +93 -0
- package/dist/tools/fs/read-deny-home.js +225 -0
- package/dist/tools/fs/read-deny.d.ts +176 -34
- package/dist/tools/fs/read-deny.js +268 -61
- package/dist/tools/fs/safety.d.ts +6 -1
- package/dist/tools/fs/safety.js +18 -5
- package/dist/tools/fs/search.d.ts +3 -0
- package/dist/tools/fs/search.js +47 -9
- package/dist/tools/fs/shell-read-check.d.ts +42 -11
- package/dist/tools/fs/shell-read-check.js +188 -13
- package/dist/tools/fs/shell-read-establish.d.ts +7 -3
- package/dist/tools/fs/shell-read-establish.js +134 -21
- package/dist/tools/fs/shell-read-identity.d.ts +7 -0
- package/dist/tools/fs/shell-read-identity.js +21 -0
- package/dist/tools/fs/shell-read-judge.d.ts +92 -32
- package/dist/tools/fs/shell-read-judge.js +43 -18
- package/dist/tools/fs/shell-read-plan.d.ts +4 -0
- package/dist/tools/fs/shell-read-plan.js +26 -4
- package/dist/tools/fs/shell-read-write-targets.d.ts +73 -0
- package/dist/tools/fs/shell-read-write-targets.js +173 -0
- package/package.json +3 -1
- package/test/export-surface.snapshot.json +103 -11
- package/wire-changes/core@7.33.8.json +165 -0
- package/wire-changes/core@7.34.0.json +2621 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { RunnerDeps, TaskSpec, ToolEffect } from "../types.js";
|
|
2
2
|
import type { IrreversibilityTier, ReversibilityProbes } from "./contracts.js";
|
|
3
|
+
import type { ToolMarkSource } from "../ask-origin.js";
|
|
3
4
|
export interface PrepareSafetyScanInput {
|
|
4
5
|
/** borrowed-readonly — the REBOUND spec (`spec′`, the config-doors result). The scan reads
|
|
5
6
|
* `tools`, `handsReadOnly` and `enablePlanMode`; it never mutates. */
|
|
@@ -42,6 +43,10 @@ export interface PrepareSafetyScanResult {
|
|
|
42
43
|
}>;
|
|
43
44
|
/** borrowed-mutable — declared reversibility probes by tool name. */
|
|
44
45
|
reversibilityProbes: ReversibilityProbes;
|
|
46
|
+
/** borrowed-mutable — WHO put each tool's egress / irreversibility mark on its seat (the caller roster's marks are
|
|
47
|
+
* the deployment's own; the protocol fold adds `mcp_annotation` / `a2a_default`). Read by the gate's class
|
|
48
|
+
* derivation: a mark with no recorded source reads as the deployment's (fail-closed). */
|
|
49
|
+
toolMarkSources: Map<string, Set<ToolMarkSource>>;
|
|
45
50
|
/** borrowed-readonly — the caller roster's own names, snapshotted before the first await. */
|
|
46
51
|
ownToolNames: ReadonlySet<string>;
|
|
47
52
|
}
|
|
@@ -14,6 +14,14 @@ export function prepareSafetyScan(input) {
|
|
|
14
14
|
const irreversibilityTier = new Map();
|
|
15
15
|
const axisExplicitNegatives = new Map();
|
|
16
16
|
const reversibilityProbes = new Map();
|
|
17
|
+
const toolMarkSources = new Map();
|
|
18
|
+
const markedBy = (name, source) => {
|
|
19
|
+
const set = toolMarkSources.get(name);
|
|
20
|
+
if (set !== undefined)
|
|
21
|
+
set.add(source);
|
|
22
|
+
else
|
|
23
|
+
toolMarkSources.set(name, new Set([source]));
|
|
24
|
+
};
|
|
17
25
|
for (const t of spec.tools ?? []) {
|
|
18
26
|
{
|
|
19
27
|
const bound = rosterMemberBoundProblem({
|
|
@@ -72,8 +80,10 @@ export function prepareSafetyScan(input) {
|
|
|
72
80
|
const tier = t.irreversibility ?? (t.reversibilityProbe ? "maybe" : undefined);
|
|
73
81
|
if (tier !== undefined) {
|
|
74
82
|
irreversibilityTier.set(t.name, tier);
|
|
75
|
-
if (tier === "always" || tier === "maybe")
|
|
83
|
+
if (tier === "always" || tier === "maybe") {
|
|
76
84
|
irreversibleTools.add(t.name);
|
|
85
|
+
markedBy(t.name, "deployment");
|
|
86
|
+
}
|
|
77
87
|
}
|
|
78
88
|
if (t.reversibilityProbe)
|
|
79
89
|
reversibilityProbes.set(t.name, t.reversibilityProbe);
|
|
@@ -84,6 +94,7 @@ export function prepareSafetyScan(input) {
|
|
|
84
94
|
throw e;
|
|
85
95
|
}
|
|
86
96
|
egressTools.add(t.name);
|
|
97
|
+
markedBy(t.name, "deployment");
|
|
87
98
|
}
|
|
88
99
|
for (const alias of t.aliases ?? []) {
|
|
89
100
|
if (alias === t.name || ownToolNames.has(alias))
|
|
@@ -95,13 +106,17 @@ export function prepareSafetyScan(input) {
|
|
|
95
106
|
toolEffects.set(alias, t.effect);
|
|
96
107
|
if (tier !== undefined) {
|
|
97
108
|
irreversibilityTier.set(alias, tier);
|
|
98
|
-
if (tier === "always" || tier === "maybe")
|
|
109
|
+
if (tier === "always" || tier === "maybe") {
|
|
99
110
|
irreversibleTools.add(alias);
|
|
111
|
+
markedBy(alias, "deployment");
|
|
112
|
+
}
|
|
100
113
|
}
|
|
101
114
|
if (t.reversibilityProbe)
|
|
102
115
|
reversibilityProbes.set(alias, t.reversibilityProbe);
|
|
103
|
-
if (t.egress)
|
|
116
|
+
if (t.egress) {
|
|
104
117
|
egressTools.add(alias);
|
|
118
|
+
markedBy(alias, "deployment");
|
|
119
|
+
}
|
|
105
120
|
}
|
|
106
121
|
}
|
|
107
122
|
toolEffects.set(OFFLOAD_TOOL_NAME, "read");
|
|
@@ -122,6 +137,7 @@ export function prepareSafetyScan(input) {
|
|
|
122
137
|
irreversibilityTier,
|
|
123
138
|
axisExplicitNegatives,
|
|
124
139
|
reversibilityProbes,
|
|
140
|
+
toolMarkSources,
|
|
125
141
|
ownToolNames,
|
|
126
142
|
};
|
|
127
143
|
}
|
|
@@ -26,6 +26,7 @@ import type { ReadFileState } from "../../tools/fs/safety.js";
|
|
|
26
26
|
import type { OutputRef } from "./synthetic-tools.js";
|
|
27
27
|
import type { HookInvocationIdentity } from "../hooks.js";
|
|
28
28
|
import type { InheritedGate, Prepared, PrepareResume, RunInternals, SuspendSaga } from "./contracts.js";
|
|
29
|
+
import type { PermissionModeController } from "../mode-policy.js";
|
|
29
30
|
/**
|
|
30
31
|
* The ONE compensation for a paused-but-unparked VM, shared by the fence's
|
|
31
32
|
* post-pause checkpoints (③ in the park closure, ④ in the saga) and the saga's put-failure absent
|
|
@@ -130,12 +131,11 @@ export interface PrepareSuspendSagaInput {
|
|
|
130
131
|
* mid-run and enforced here has to survive suspend exactly as it survives a spawn, and the same
|
|
131
132
|
* projection serves both). Cloned onto the row. */
|
|
132
133
|
ancestorRulesNow: () => InheritedGate["ancestorRules"];
|
|
133
|
-
/** borrowed-readonly — the inherited shell
|
|
134
|
+
/** borrowed-readonly — the inherited shell floor, persisted verbatim. */
|
|
134
135
|
inheritedShellGate: InheritedGate["shellGate"];
|
|
135
|
-
/** borrowed-readonly — the
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
approverPosture: InheritedGate["approverPosture"];
|
|
136
|
+
/** borrowed-readonly — the leg's live permission-mode seat; the DECLARED mode (request clamped under the chain's ceiling,
|
|
137
|
+
* before the deployment's fold) is what the row records — the resume leg re-judges the fold for its own deployment. */
|
|
138
|
+
permissionMode: PermissionModeController;
|
|
139
139
|
/** borrowed-readonly — the auto-mode decider, or undefined (the latch-health reading only). */
|
|
140
140
|
/** borrowed-readonly — the inherited admitted org scopes, or undefined (copied onto the row). */
|
|
141
141
|
inheritedAdmittedOrgScopes: readonly string[] | undefined;
|
|
@@ -79,7 +79,7 @@ function stampPlacementRootSessionId(placementRootResolved) {
|
|
|
79
79
|
return placementValueOrAbsent(placementRootResolved);
|
|
80
80
|
}
|
|
81
81
|
export function prepareSuspendSaga(input) {
|
|
82
|
-
const { gateMachineryActive, abortController, harness, checkpointStore, deps, sessionId, hostTaskId, taskScope, liveSpendRef, resume, nestedStats, internals, activeTools, outputRef, readFileStateForCheckpoint, faceCheckpointSection, writeFaceCheckpointSection, reminderMark, handsCwdRef, worktreeSessionRef, undeliveredContinuationRef, inheritedParentConstraints, seedInheritedGate, ancestorRulesNow, inheritedShellGate,
|
|
82
|
+
const { gateMachineryActive, abortController, harness, checkpointStore, deps, sessionId, hostTaskId, taskScope, liveSpendRef, resume, nestedStats, internals, activeTools, outputRef, readFileStateForCheckpoint, faceCheckpointSection, writeFaceCheckpointSection, reminderMark, handsCwdRef, worktreeSessionRef, undeliveredContinuationRef, inheritedParentConstraints, seedInheritedGate, ancestorRulesNow, inheritedShellGate, permissionMode, inheritedAdmittedOrgScopes, ownOrgVerdictRef, orgGovernedProvenance, announcedListingsRef, gitStatusRef, hookIdentity, placementRootResolved, externalContentTargetActive, remoteEnvFailures, memoryEngineSession, suspendLoopRef, ownedEnv, incompleteSuspendAdapter } = input;
|
|
83
83
|
if (!gateMachineryActive)
|
|
84
84
|
return { saga: undefined };
|
|
85
85
|
const inFlightSpendMicroUsd = () => {
|
|
@@ -134,12 +134,12 @@ export function prepareSuspendSaga(input) {
|
|
|
134
134
|
const constraintDigest = (inheritedParentConstraints?.length ?? 0) > 0
|
|
135
135
|
? constraintChainDigest(constraintChain)
|
|
136
136
|
: seedInheritedGate?.constraintDigest;
|
|
137
|
-
const
|
|
137
|
+
const declaredMode = permissionMode.declared;
|
|
138
|
+
const modeRecorded = declaredMode !== "default" || permissionMode.requested !== undefined || seedInheritedGate?.permissionMode !== undefined;
|
|
138
139
|
const ancestorRulesAtMint = ancestorRulesNow();
|
|
139
140
|
return ancestorRulesAtMint !== undefined ||
|
|
140
141
|
inheritedShellGate !== undefined ||
|
|
141
|
-
|
|
142
|
-
approverPosture !== undefined ||
|
|
142
|
+
modeRecorded ||
|
|
143
143
|
inheritedAdmittedOrgScopes !== undefined ||
|
|
144
144
|
ownOrgVerdictRef.current !== undefined ||
|
|
145
145
|
orgGovernedProvenance ||
|
|
@@ -147,8 +147,8 @@ export function prepareSuspendSaga(input) {
|
|
|
147
147
|
? {
|
|
148
148
|
...(ancestorRulesAtMint !== undefined ? { ancestorRules: structuredClone(ancestorRulesAtMint) } : {}),
|
|
149
149
|
...(inheritedShellGate !== undefined ? { shellGate: inheritedShellGate } : {}),
|
|
150
|
-
...(
|
|
151
|
-
...(
|
|
150
|
+
...(modeRecorded ? { permissionMode: declaredMode } : {}),
|
|
151
|
+
...(permissionMode.prePlanMode !== undefined ? { prePlanMode: permissionMode.prePlanMode } : {}),
|
|
152
152
|
...(inheritedAdmittedOrgScopes !== undefined ? { admittedOrgScopes: [...inheritedAdmittedOrgScopes] } : {}),
|
|
153
153
|
...(ownOrgVerdictRef.current !== undefined
|
|
154
154
|
? { ownAdmittedOrgScopes: [...ownOrgVerdictRef.current.scopes], ownAdmittedOrgWriteScope: ownOrgVerdictRef.current.writeScope }
|
|
@@ -8,10 +8,15 @@ import { brainToRuntime } from "../runtime.js";
|
|
|
8
8
|
import { hasSessionFork } from "../session.js";
|
|
9
9
|
import { SEND_MESSAGE_TOOL_NAME } from "../../agents/send-message-tool.js";
|
|
10
10
|
import { callerToolMembership } from "../../agents/inherited-tool-pool.js";
|
|
11
|
+
import { toolPolicyPathDenyRules, toolPolicyWriteTargetGuard } from "../tool-policy.js";
|
|
11
12
|
import { loadAnnounceOnceLedger } from "./announce-once-ledger.js";
|
|
12
13
|
import { isValidReminderMark, mintReminderMark } from "../reminder-mint.js";
|
|
13
|
-
import {
|
|
14
|
+
import { clampPermissionMode, isPermissionMode, PERMISSION_MODES } from "../ask-origin.js";
|
|
15
|
+
import { modePolicyOf, modeRequestAfterResume } from "../mode-policy.js";
|
|
16
|
+
import { assertNoRetiredKeys, RETIRED_TASK_SPEC_KEYS } from "../retired-keys.js";
|
|
17
|
+
import { migrateLegacyModeSeed } from "../checkpoint-store.js";
|
|
14
18
|
import { emitTrace } from "../trace.js";
|
|
19
|
+
import { persistedPathRowsOfTask, ruleStoreUnreadableNotice } from "./persisted-path-rows.js";
|
|
15
20
|
import { reservedCollisions, reservedFor } from "../../brain/request-params.js";
|
|
16
21
|
import { STALL_FIRST_BYTE_MS, STALL_FIRST_TOKEN_MS, STALL_IDLE_MS, withBrainCallGuardrail } from "../../brain/timeout.js";
|
|
17
22
|
import { OFFLOAD_TOOL_NAME } from "../tool-result-store.js";
|
|
@@ -260,13 +265,21 @@ function refuseRegistryScopeMismatch(spec, internals) {
|
|
|
260
265
|
function validateInputFaultNotice(onError, sessionId) {
|
|
261
266
|
return ({ toolName, toolCallId, error }) => onError?.(new Error(`tool input pre-validation (validateInput) threw for ${toolName} (call ${toolCallId}) — read as no verdict; the call proceeded to the gate: ${thrownText(error)}`), { phase: "hook", sessionId });
|
|
262
267
|
}
|
|
263
|
-
function
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
268
|
+
function refusePermissionModeDoors(spec) {
|
|
269
|
+
assertNoRetiredKeys(spec, RETIRED_TASK_SPEC_KEYS, "TaskSpec");
|
|
270
|
+
const mode = spec.permissionMode;
|
|
271
|
+
if (mode !== undefined && !isPermissionMode(mode)) {
|
|
272
|
+
const e = new Error(`permissionMode must be one of ${PERMISSION_MODES.map((w) => JSON.stringify(w)).join(", ")} when present (got ${JSON.stringify(mode)}) — omit it for the default mode; an unrecognized word is refused rather than read as any mode.`);
|
|
273
|
+
e.code = "config.permission_mode_invalid";
|
|
267
274
|
throw e;
|
|
268
275
|
}
|
|
269
|
-
|
|
276
|
+
const floor = spec.shellGate;
|
|
277
|
+
if (floor !== undefined && floor !== "always") {
|
|
278
|
+
const e = new Error(`shellGate must be the floor word "always" when present (got ${JSON.stringify(floor)}) — the doctrine values "off" / "classify" are retired: the shell's shape tier is installed on every full shell and the permission mode (permissionMode) decides what its asks become; omit shellGate for no operator floor.`);
|
|
279
|
+
e.code = "config.shell_gate_value_retired";
|
|
280
|
+
throw e;
|
|
281
|
+
}
|
|
282
|
+
return mode;
|
|
270
283
|
}
|
|
271
284
|
export async function prepareTask(spec, deps, sessions, resume, internals, runnerSelf, runIdSink) {
|
|
272
285
|
const runId = uuidv7();
|
|
@@ -276,12 +289,18 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
276
289
|
const doors = prepareConfigDoors({ spec, deps, sessions, resume, internals });
|
|
277
290
|
spec = doors.spec;
|
|
278
291
|
const checkpointStore = resolveCheckpointStore(spec, deps), checkpointSeat = checkpointSeatOf(spec, checkpointStore);
|
|
279
|
-
const
|
|
280
|
-
const
|
|
292
|
+
const permissionModeSeat = refusePermissionModeDoors(spec);
|
|
293
|
+
const declaredModeAtDoor = (() => {
|
|
294
|
+
const requested = modeRequestAfterResume(permissionModeSeat, migrateLegacyModeSeed(resume?.seed.inheritedGate), resume?.outcome);
|
|
295
|
+
const ceiling = internals?.inheritedGate?.permissionModeCeiling?.current ?? internals?.inheritedGate?.permissionMode;
|
|
296
|
+
return ceiling === undefined ? (requested ?? "default") : clampPermissionMode(requested, ceiling).effective;
|
|
297
|
+
})();
|
|
298
|
+
if (modePolicyOf(declaredModeAtDoor).enablePlanMode)
|
|
299
|
+
spec = { ...spec, enablePlanMode: true };
|
|
281
300
|
const { toolFaceSnapshot, promptProfile, lockedPreflight, resolvedInteractionPosture, microCompactKnob, resolvedRole, model, thinking, compModel, fableMitigations, memoryDelegationEvidence, memoryProvenance, memoryCapturePolicy, usageWindows, brainCallGuardrailRef, brainCallGuardrailMs } = doors;
|
|
282
301
|
announceToolModelGate(deps.onNotice, model.id, doors.modelGate);
|
|
283
302
|
const modelGateManifest = toolModelGateManifest(doors.modelGate);
|
|
284
|
-
const { toolEffects, egressTools, irreversibleTools, irreversibilityTier, axisExplicitNegatives, reversibilityProbes } = prepareSafetyScan({ spec, deps });
|
|
303
|
+
const { toolEffects, egressTools, irreversibleTools, irreversibilityTier, axisExplicitNegatives, reversibilityProbes, toolMarkSources } = prepareSafetyScan({ spec, deps });
|
|
285
304
|
let shellGatedTools = new Set();
|
|
286
305
|
refuseRequireExistingWithoutSession(spec);
|
|
287
306
|
refuseRegistryScopeMismatch(spec, internals);
|
|
@@ -385,15 +404,22 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
385
404
|
const { taskRootFinal, rebaseRestoredPath } = await prepareWorkspaceRestore({ ownedEnv, deps, spec, internals, resume, taskRootInitial, abortController, sessionId });
|
|
386
405
|
const { canonical: taskRootCanonical } = await resolveTaskRootCanonical({ env: executionEnv, given: taskRootFinal, onNotice: deps.onNotice, sessionId, runId });
|
|
387
406
|
const { trackFileEdit, fileHistoryBoundary, restoredFilePaths, rewindNotes, fileHistoryEnabled, fileHistoryFact, historyScope, historyRoot, historyFs } = await prepareFileHistory({ deps, spec, internals, executionEnv, taskRootFinal, handsEnabled, sessionId, session, abortController });
|
|
388
|
-
const { noteFileEdited, editedFilesSnapshot, harnessRef, toolProgressRef, skillScope, forwardEvent, reviewRequestRef, requestReview, stopRequestedRef, requestStopAfterTurn,
|
|
407
|
+
const { noteFileEdited, editedFilesSnapshot, harnessRef, toolProgressRef, skillScope, forwardEvent, reviewRequestRef, requestReview, stopRequestedRef, requestStopAfterTurn, bindPermissionModeSeat, enterPlanMode, subagentRetain, worktreeIsolation } = prepareRunRefs({ spec, internals, executionEnv, taskRootFinal });
|
|
389
408
|
const legContextOverlay = () => runnerSelf?.contextOverlayOf?.(harnessRef.current?.getModelRef() ?? resolvedRole.modelRef);
|
|
390
409
|
let resolvedReadFace;
|
|
391
410
|
let resolvedWriteFace;
|
|
392
411
|
let readDenyAdditionsNormalized = [];
|
|
393
412
|
let handsLessResolvedFace;
|
|
394
413
|
let handsLessResolvedWriteFace;
|
|
395
|
-
const { liveInheritedGate, seedInheritedGate, inheritedAncestorRules, inheritedShellGate, inheritedParentConstraints,
|
|
396
|
-
|
|
414
|
+
const { liveInheritedGate, seedInheritedGate, inheritedAncestorRules, inheritedShellGate, inheritedParentConstraints, permissionMode, inheritedAdmittedOrgScopes, priorOwnOrgVerdict, orgGovernedProvenance, effectiveShellGate, ownSessionRulesRef, ancestorSessionRulesRef, ancestorRulesNow, memoryAdmittedOrgScopesRef, ownOrgVerdictRef, orgAdmissionCheckpointState, faceCheckpointSection, faceCheckpointState, writeFaceCheckpointSection, f012CheckpointState, frozenOnAsk, hookEnvSource, notifyOwnHookCrash, frozenOnQuestion, parentSpecSeat, provenanceForChildrenRef, delegationSettlementRef, inheritedGateForChildren, carrierReadFace, carrierWriteFace, fullShellReachable, gateStopRef, stopForDenialLimit, enrichSpecToolCtx } = prepareInheritedGate({ spec, deps, internals, resume, sessions, sessionId, runId, hostTaskId, taskRootFinal, executionEnv, ownedEnv, lockedPreflight, checkpointSeat, toolFaceSnapshot, mountsCallerTool, promptProfile, resolvedInteractionPosture, permissionModeSeat, handsEnabled, reportUsage, harnessRef, skillScope, forwardEvent, subagentRetain, worktreeIsolation, requestReview, requestStopAfterTurn, enterPlanMode, reminderMark, reminderDisclosureCounts, fileHistoryEnabled, historyScope, historyRoot, historyFs, abortRun: () => { abortController.abort(); void harness.abort(); }, runtimeCaps: () => runtimeCaps, hooks: () => hooks, preToolUseObservational: () => preToolUseObservational, hookTimeoutMs: () => hookTimeoutMs, 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 });
|
|
415
|
+
bindPermissionModeSeat(permissionMode);
|
|
416
|
+
const announceRuleStoreSkipped = ruleStoreUnreadableNotice(deps.onNotice, { sessionId, runId });
|
|
417
|
+
const persistedPathRowsRead = persistedPathRowsOfTask({ deps, principal: spec.principal, sessionId, root: taskRootFinal, home: executionEnv.homeDir, taskId: hostTaskId, handsEnabled, signals: [abortController.signal, ...(spec.signal !== undefined ? [spec.signal] : [])], onUnread: announceRuleStoreSkipped });
|
|
418
|
+
const persistedPathRows = persistedPathRowsRead === undefined ? { readDirectories: [], denyRows: [] } : await persistedPathRowsRead;
|
|
419
|
+
const effectivePathDenyRules = [...toolPolicyPathDenyRules([lockedPreflight.toolPolicy, ...(inheritedParentConstraints ?? []).map((c) => c.policy)]), ...persistedPathRows.denyRows];
|
|
420
|
+
const writeProtectionJudgeRef = {};
|
|
421
|
+
const writeGuards = { protection: () => writeProtectionJudgeRef.current, target: toolPolicyWriteTargetGuard([lockedPreflight.toolPolicy, ...(inheritedParentConstraints ?? []).map((c) => c.policy)]) };
|
|
422
|
+
const { roster, blockedRef, runtimeCaps, runtimeCapsFaulted, complianceDenies, complianceDegraded, agentForkDenial, observersActive, autoModeArmReason, autoModeDeciderRef, autoModeDenialTrackingRef, autoModeArmingRef, armAutoMode, selfOrchestrationActive, workflowToolsActive, workflowSizeGuideline } = await prepareCapsAndWorkflow({ spec, deps, internals, session, sessionId, runId, hostTaskId, taskScope, taskRootFinal, model, thinking, lockedPreflight, checkpointSeat, toolEffects, toolFaceSnapshot, promptProfile, resolvedInteractionPosture, harnessRef, frozenOnAsk, parentSpecSeat, carrierReadFace, carrierWriteFace, forwardEvent, inheritedGateForChildren, enrichSpecToolCtx, maybeOffload, requestReview, enterPlanMode, permissionMode, readDenyEntries: () => ({ entries: readDenyMatcher?.entries ?? [], ruleRows: effectivePathDenyRules }), peerLaneActive, peerSendMessageBuiltIn, runnerSelf, memoryEngineSession: () => memoryEngineSession, centerAdoption: () => centerAdoptionRef.current, readDenyAdditionsNormalized: () => readDenyAdditionsNormalized });
|
|
397
423
|
const tools = roster.tools;
|
|
398
424
|
const pausedRef = {};
|
|
399
425
|
const undeliveredContinuationRef = { current: { parkedSteers: [], orphanTasks: [] } };
|
|
@@ -454,7 +480,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
454
480
|
roster.mount(createOutputTool(outputRef, spec.outputSchema, compiled.strict ? compiled.modelSchema : undefined), { source: "synthetic", mountedBy: "optional" });
|
|
455
481
|
}
|
|
456
482
|
const rosterSeat = new ToolRosterDeltaSeat();
|
|
457
|
-
const { mcp, a2a, rebuildHarnessToolsRef, contentOriginWrapRef, toolCallGateArmedRef, mcpRedial } = await prepareProtocolTools({ lockedPreflight, spec, deps, reminderMark, reminderDisclosureCounts, runId, sessionId, onceLedger, roster, rosterSeat, remoteToolOffload, toolFaceSnapshot, toolEffects, axisExplicitNegatives, irreversibilityTier, irreversibleTools, egressTools, abortController, rollback });
|
|
483
|
+
const { mcp, a2a, rebuildHarnessToolsRef, contentOriginWrapRef, toolCallGateArmedRef, mcpRedial } = await prepareProtocolTools({ lockedPreflight, spec, deps, reminderMark, reminderDisclosureCounts, runId, sessionId, onceLedger, roster, rosterSeat, remoteToolOffload, toolFaceSnapshot, toolEffects, axisExplicitNegatives, irreversibilityTier, irreversibleTools, egressTools, toolMarkSources, abortController, rollback });
|
|
458
484
|
const callIssuedAtRef = {};
|
|
459
485
|
const workCutRef = { continuation: false, abortedBeforeTurnEnd: false };
|
|
460
486
|
const advertisedWritableDirs = handsEnabled
|
|
@@ -530,7 +556,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
530
556
|
if (internals?.ownOrgAdmissionRef !== undefined && ownOrgVerdictRef.current !== undefined) {
|
|
531
557
|
internals.ownOrgAdmissionRef.current = ownOrgVerdictRef.current;
|
|
532
558
|
}
|
|
533
|
-
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 } : {}) };
|
|
559
|
+
const handsReadFaceInput = { permissionMode, pathDenyRules: effectivePathDenyRules, writeGuards, persistedReadDirectories: persistedPathRows.readDirectories, 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 } : {}) };
|
|
534
560
|
const handsReadFace = handsEnabled ? await prepareHandsMount(handsReadFaceInput) : resolveHandsLessReadFace(handsReadFaceInput);
|
|
535
561
|
const { readFileStateForCheckpoint, seedContextFiles, handsCwdRef, workspaceStateSettle, wsSnapshot, rebaseWsPath, backgroundTaskToolsActive, shellReadCheck, shellReadAdmission, additionalRootsCanonical, additionalReadRootsCanonical, attachmentRootCanonical, readDenyMatcher, envHandToolNames, sealReadStateSeat } = handsReadFace;
|
|
536
562
|
resolvedReadFace = handsReadFace.resolvedReadFace;
|
|
@@ -539,6 +565,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
539
565
|
handsLessResolvedFace = handsReadFace.handsLessResolvedFace;
|
|
540
566
|
handsLessResolvedWriteFace = handsReadFace.handsLessResolvedWriteFace;
|
|
541
567
|
shellGatedTools = handsReadFace.shellGatedTools;
|
|
568
|
+
await armAutoMode();
|
|
542
569
|
const { worktreeSessionRef } = prepareDelegationSurface({ spec, deps, internals, resume, sessionId, hostTaskId, taskScope, taskRootFinal, taskRootCanonical, executionEnv, runnerSelf, backgroundTaskToolsActive, shellReadAdmission, workflowToolsActive, peerLaneActive, peerSendMessageBuiltIn, peerLaneRefs, sessionBox, roster, toolEffects, axisExplicitNegatives, envHandToolNames, toolFaceSnapshot, firstPartyOffload, offloadStore, subagentRetain, enrichSpecToolCtx, handsCwdRef, wsSnapshot, rebaseWsPath, rebaseRestoredPath, workspaceStateSettle });
|
|
543
570
|
const { liveQuestionFace, contentAskBindings, contentAskRoutable, lateStrandedAnswers, discloseStrandedAnswers, settleContentAskBindings, durableQuestionFace, questionToolMounted, mountedQuestionTool } = prepareQuestionFace({ frozenOnQuestion, spec, deps, checkpointStore, runtimeCaps, resolvedInteractionPosture, resume, sessionId, roster, inheritedUnavailableAsks: () => inheritedUnavailableAsks });
|
|
544
571
|
if (spec.handsReadOnly !== true) {
|
|
@@ -559,7 +586,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
559
586
|
`(per-principal entitlement governance, not a misconfiguration — Agent(subagent_type:"fork") will refuse honestly)`), { phase: "config", sessionId });
|
|
560
587
|
}
|
|
561
588
|
const { lspDiagnostics, nudgeLspOnEdit, lspRunIdent, managerWired: lspManagerWired } = prepareLsp({ spec, deps, executionEnv, taskRootFinal, handsEnabled, sessionId, handsCwdRef, roster, envHandToolNames });
|
|
562
|
-
prepareArtifact({ deps, runId, taskId: hostTaskId, sessionId, agentName: internals?.explicitAgentName, onAsk: frozenOnAsk, executionEnv, rootCanonical: attachmentRootCanonical, additionalRootsCanonical: () => [...additionalRootsCanonical, ...additionalReadRootsCanonical], readDenyMatcher, resolvedReadFace, handsCwdRef, roster, firstPartyOffload, envHandToolNames, ...(handsReadFace.artifactStoreRef !== undefined ? { artifactStoreRef: handsReadFace.artifactStoreRef } : {}) });
|
|
589
|
+
prepareArtifact({ deps, runId, taskId: hostTaskId, sessionId, agentName: internals?.explicitAgentName, onAsk: frozenOnAsk, permissionMode, executionEnv, rootCanonical: attachmentRootCanonical, additionalRootsCanonical: () => [...additionalRootsCanonical, ...additionalReadRootsCanonical], readDenyMatcher, resolvedReadFace, handsCwdRef, roster, firstPartyOffload, envHandToolNames, ...(handsReadFace.artifactStoreRef !== undefined ? { artifactStoreRef: handsReadFace.artifactStoreRef } : {}) });
|
|
563
590
|
if (internals?.delegationProvenance !== undefined && resume !== undefined) {
|
|
564
591
|
const live = internals.delegationProvenance.ref.current;
|
|
565
592
|
const seed = resume.seed.delegationProvenance;
|
|
@@ -598,7 +625,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
598
625
|
}
|
|
599
626
|
const projectContext = await prepareProjectContext({ deps, spec, internals, session, sessionId, hostTaskId, taskRootFinal, handsEnabled, delegation, seedContextFiles, memoryBlockFromEngine, skillScope, roster, toolFaceSnapshot, onceLedger, memoryTools, memoryEngineSession, memorySearchToolsPlanned, memoryPairExcludedName, memoryPairOccupiedName, resume, skillListingBudget: doors.skillListingBudget });
|
|
600
627
|
const { memoryBlock: memoryBlockWithProject, instructionSources, projectInstructionContent, hasSkillManifest, skillsListing, sharedMemoryPairMounted, memoryEnginePairMounted } = projectContext;
|
|
601
|
-
const { provider, featureFlags, userSystemPrompt, userAppendSystemPrompt, mcpInstructionsBlock, envFacts, tzValid, userTz, dateAnchor, gitStatusRef } = await preparePromptInputs({ spec, deps, contextOverlay: legContextOverlay(), failClosedReason: selfOrchestrationFailClosedReason(spec, deps), lockedPreflight, selfOrchestrationActive, executionEnv, reminderMark, resolvedReadFace, resolvedWriteFace, toolFaceSnapshot, promptProfile, fableMitigations, internals, thinking, ownedEnv, delegation, resolvedRole, mcp, model, externalContentTargetActive, resume, handsEnabled, taskRootFinal, additionalRootsCanonical, additionalReadRootsCanonical, sessionId, session, ...(advertisedWritableDirs !== undefined ? { advertisedWritableDirs } : {}) });
|
|
628
|
+
const { provider, featureFlags, userSystemPrompt, userAppendSystemPrompt, mcpInstructionsBlock, envFacts, tzValid, userTz, dateAnchor, gitStatusRef } = await preparePromptInputs({ spec, deps, contextOverlay: legContextOverlay(), failClosedReason: selfOrchestrationFailClosedReason(spec, deps), lockedPreflight, selfOrchestrationActive, executionEnv, reminderMark, resolvedReadFace, resolvedWriteFace: resolvedWriteFace?.inForce(), toolFaceSnapshot, promptProfile, fableMitigations, internals, thinking, ownedEnv, delegation, resolvedRole, mcp, model, externalContentTargetActive, resume, handsEnabled, taskRootFinal, additionalRootsCanonical, additionalReadRootsCanonical, sessionId, session, ...(advertisedWritableDirs !== undefined ? { advertisedWritableDirs } : {}) });
|
|
602
629
|
const { deferred, memoryBlock, toolSearch: toolSearchPolicy } = prepareDeferClassify({ spec, deps, roster, toolFaceSnapshot, handsEnabled, fullShellReachable, promptProfile, model, mcp, a2a, sharedMemoryPairMounted, memoryEnginePairMounted, memoryBlock: memoryBlockWithProject, memoryRecallSegment, onceLedger, sessionId });
|
|
603
630
|
prepareMemoryEngineSession({ memoryEngineSession, internals, memoryDelegationEvidence, externalContentTargetActive, lockedPreflight, mcp, sessionId, runId, deps, provenanceForChildrenRef, delegationSettlementRef, spec, envHandToolNames, roster, contentOriginWrapRef });
|
|
604
631
|
const { systemPromptSeat, renderWithDate, systemBlocks, promptManifest, epochDeclaredSections, epochArtifactDigestForSnapshot, buildAssembleInputs, centerAdoptionRef } = await preparePromptAssembly({ session, deps, internals, resume, provider, userSystemPrompt, userAppendSystemPrompt, featureFlags, mcpInstructionsBlock, memoryBlock, envFacts, promptProfile, fableMitigations, tools, model, sessionId, reminderMark, onceLedger });
|
|
@@ -710,25 +737,27 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
710
737
|
releaseSignal = () => sig.removeEventListener("abort", onExternalAbort);
|
|
711
738
|
}
|
|
712
739
|
}
|
|
713
|
-
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, ancestorSessionRulesRef, inheritedParentConstraints, seedInheritedGate, hasSkillManifest, skillScope, frozenOnAsk, hookEnvSource, notifyOwnHookCrash, autoModeDecider, stopForDenialLimit, delegation, abortController, now, ownSessionRulesRef });
|
|
714
|
-
const { onAsk, preToolContexts, blockedToolCalls, gateOutcomes, batchHaltRef, blockedTracked, incompleteSuspendAdapter, durableSuspendInfraReady, resourceSuspendEligible, usageGovernance, durableApproval, wiringManifest,
|
|
740
|
+
const { hooks, hookTimeoutMs, preToolUseObservational, ownGatePreToolUse, basePolicyForResumeEdit, denyNarrowingPolicy, policyLayers, effectivePolicy, inheritedUnavailableAsks, inheritedAskGrants, askSourceIdentity, riskAxesOf, ruleOffersOf, permissionRuleLane, permissionRuleOrgLane, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, foldAskClasses, ancestorSandboxAdmissions, ancestorArbitrations } = await preparePolicyChain({ spec, deps, internals, sessionId, runId, hostTaskId, taskRootFinal, additionalRootsCanonical, executionEnv, lockedPreflight, tools, harnessTools, toolEffects, egressTools, irreversibilityTier, axisExplicitNegatives, shellGatedTools, envHandToolNames, handsCwdRef, readDenyMatcher, announceRuleStoreSkipped, questionToolMounted, runtimeCaps, inheritedAncestorRules, ancestorSessionRulesRef, inheritedParentConstraints, seedInheritedGate, hasSkillManifest, skillScope, frozenOnAsk, hookEnvSource, notifyOwnHookCrash, autoModeDecider: () => autoModeDeciderRef.current, permissionMode, scratchpadDir: spec.envFacts?.scratchpadDir, toolRosterDeltas: rosterSeat, stopForDenialLimit, delegation, abortController, now, ownSessionRulesRef });
|
|
741
|
+
const { onAsk, preToolContexts, blockedToolCalls, gateOutcomes, batchHaltRef, blockedTracked, incompleteSuspendAdapter, durableSuspendInfraReady, resourceSuspendEligible, usageGovernance, durableApproval, wiringManifest, writeProtection, parkLaneArmed, gateMachineryActive, hookIdentity, hookEnvFace, sessionBoxBound } = prepareWiringManifest({ spec, deps, internals, resume, sessionId, runId, hostTaskId, taskScope, hooks, preToolUseObservational, policyLayers, effectivePolicy, handsEnabled, taskRootFinal, 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, frozenOnAsk, liveInheritedGate, delegation, toolRoster, readDenyBuiltinTiersActive: handsReadFace.readDenyBuiltinTiersActive, lspManagerWired, lspDiagnosticsLive: lspDiagnostics !== undefined, fileHistoryFact, sessionBox });
|
|
742
|
+
const writeProtectionCheck = writeProtection?.check;
|
|
743
|
+
writeProtectionJudgeRef.current = writeProtection?.judgeTarget;
|
|
715
744
|
if (fileHistoryBoundary !== undefined) {
|
|
716
745
|
harness.on("tool_call", async () => {
|
|
717
746
|
await fileHistoryBoundary.settle();
|
|
718
747
|
return undefined;
|
|
719
748
|
});
|
|
720
749
|
}
|
|
721
|
-
const { askLane } = prepareAskLane({ gateMachineryActive, abortController, effectivePolicy, budgetSnapshot, handsCwdRef, advertisedWritableDirs, tools, inheritedUnavailableAsks, inheritedAskGrants, onAsk, humanReviewRef, now, ruleOffersOf, askSourceIdentity, riskAxesOf, autoModeDenialTracking, spec, deps, sessionId, runId, hooks, hookTimeoutMs, notifyOwnHookCrash, grantReadRoot: handsReadFace.grantReadRoot });
|
|
722
|
-
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, ancestorRulesNow, inheritedShellGate,
|
|
750
|
+
const { askLane } = prepareAskLane({ gateMachineryActive, abortController, effectivePolicy, budgetSnapshot, handsCwdRef, advertisedWritableDirs, tools, inheritedUnavailableAsks, inheritedAskGrants, onAsk, humanReviewRef, now, ruleOffersOf, askSourceIdentity, riskAxesOf, autoModeDenialTracking: autoModeDenialTrackingRef, spec, deps, sessionId, runId, hooks, hookTimeoutMs, notifyOwnHookCrash, grantReadRoot: handsReadFace.grantReadRoot });
|
|
751
|
+
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, ancestorRulesNow, inheritedShellGate, permissionMode, inheritedAdmittedOrgScopes, ownOrgVerdictRef, orgGovernedProvenance, announcedListingsRef, gitStatusRef, hookIdentity, placementRootResolved, externalContentTargetActive, remoteEnvFailures, memoryEngineSession, suspendLoopRef, ownedEnv, incompleteSuspendAdapter });
|
|
723
752
|
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 });
|
|
724
753
|
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 });
|
|
725
|
-
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,
|
|
754
|
+
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, hostTaskId, sessionId, ownGatePreToolUse, hookTimeoutMs, handsCwdRef, readDenyInForce: () => ({ tiers: handsReadFace.readDenyBuiltinTiersActive, rows: [...readDenyAdditionsNormalized.map((e) => e.pattern), ...handsReadFaceInput.pathDenyRules.filter((r) => r.faces.includes("read")).map((r) => r.rule)] }), hookEnvFace, writeProtectionCheck, shellReadCheck, irreversibilityTier, reversibilityProbes, abortController, shellGatedTools, autoModeDecider: autoModeDeciderRef, autoModeDenialTracking: autoModeDenialTrackingRef, askRoute: wiringManifest.ask, permissionMode, toolMarkSources, ...(deps.a2a?.isolatePeers === true ? { a2aIsolatePeers: true } : {}), ancestorArbitrations, runId, stopForDenialLimit, permissionRuleLane, permissionRuleOrgLane, questionToolMounted, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, delegation, notifyOwnHookCrash, frameSettlement });
|
|
726
755
|
const postureFrameRef = {};
|
|
727
756
|
const { microCompact, charsPerToken } = prepareContextLane({ model, deps, sessionId, runId, hostTaskId, offloadStore, microCompactKnob, harness, batchHaltRef, gitStatusRef, postureFrameRef, requestLossyRef, trimPressureRef, contextOverlay: legContextOverlay, ...(readFileStateForCheckpoint !== undefined ? { readFileState: readFileStateForCheckpoint } : {}) });
|
|
728
757
|
const preparedHolder = {};
|
|
729
758
|
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 });
|
|
730
759
|
await onceLedger.settle(session, announcedListingsRef);
|
|
731
|
-
const buildPrepared = () => ({ harness, session, sessionId, runId, registryAccess: { owner: hostTaskId, scope: taskScope }, reminderMark, reminderDisclosureCounts, fullShellReachable, approvalPosture: {
|
|
760
|
+
const buildPrepared = () => ({ harness, session, sessionId, runId, registryAccess: { owner: hostTaskId, scope: taskScope }, reminderMark, reminderDisclosureCounts, fullShellReachable, approvalPosture: { get mode() { return permissionMode.current; }, askEffective: wiringManifest.ask.effective ?? "unresolved" }, permissionMode, editedFilesSnapshot, taskRootPath: taskRootFinal, model, thinking, compModel: effectiveCompModel, mcp, ...(mcpRedial !== undefined ? { mcpRedial } : {}), ...(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, stopForDenialLimit, suspendForReview, ...(readFileStateForCheckpoint !== undefined ? { readFileState: readFileStateForCheckpoint } : {}), 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 } } : {}), 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, ...(peerLaneRefs.boundaryRound !== undefined ? { peerBoundaryRound: peerLaneRefs.boundaryRound } : {}), gitStatusRef, postureFrameRef, listBackgroundTasks, hookIdentity, ...(sessionBoxBound !== undefined ? { sessionBox: sessionBoxBound } : {}), hookTimeoutMs, ...(turnSnapshotRef.current !== undefined ? { turnSnapshot: turnSnapshotRef.current } : {}), ...(centerCompactionCandidate !== undefined ? { centerCompactionCandidate } : {}), ...(shellReadCheck !== undefined ? { shellReadCheck } : {}), ...(toolDisclosureSeat !== undefined ? { toolDisclosure: toolDisclosureSeat } : {}) });
|
|
732
761
|
rollback.commit();
|
|
733
762
|
const prepared = buildPrepared();
|
|
734
763
|
preparedHolder.current = prepared;
|
|
@@ -29,10 +29,11 @@ import { type ToolResultStore } from "../tool-result-store.js";
|
|
|
29
29
|
import { type OnAsk, type ToolPolicy } from "../tool-policy.js";
|
|
30
30
|
import type { GateOutcome } from "../gate-outcome.js";
|
|
31
31
|
import type { RunnerDeps, RuntimeCaps, TaskSpec, ToolEffect, ToolExecuteContext } from "../types.js";
|
|
32
|
-
import type
|
|
32
|
+
import { type LegWriteProtection } from "./write-protection-station.js";
|
|
33
33
|
import { type UsageWindow } from "../usage-window-store.js";
|
|
34
34
|
import type { ToolRoster } from "../tool-roster.js";
|
|
35
35
|
import { type AutoModeArmFact, type WiringManifest, type WiringManifestMcpEntry } from "../wiring-manifest.js";
|
|
36
|
+
import type { PermissionModeController } from "../mode-policy.js";
|
|
36
37
|
import type { AnnounceOnceSink, Prepared, PrepareResume, RunInternals, UsageGovernance } from "./contracts.js";
|
|
37
38
|
export interface PrepareWiringManifestInput {
|
|
38
39
|
/** borrowed-readonly — the REBOUND spec. Read: `onAsk` (the own seat), `onQuestion` (the question seam), `handsReadOnly` / `tools` (the ungated scan),
|
|
@@ -119,8 +120,11 @@ export interface PrepareWiringManifestInput {
|
|
|
119
120
|
/** borrowed-readonly — from the LSP phase's manager fold: gates the manifest's LSP section (absent ⇒ byte-identical manifest). */ lspManagerWired: boolean;
|
|
120
121
|
/** borrowed-readonly — from the LSP phase: is the diagnostics lane live? The `lane` word's only input. */ lspDiagnosticsLive: boolean;
|
|
121
122
|
/** borrowed-readonly — from the file-history phase's one fold of the two off switches: the manifest's word, relayed. */ fileHistoryFact: NonNullable<WiringManifest["fileHistory"]>;
|
|
122
|
-
/** borrowed-readonly — the arming outcome the caps phase
|
|
123
|
-
autoModeArmReason: AutoModeArmFact;
|
|
123
|
+
/** borrowed-readonly — the arming outcome the caps phase reads live (the manifest's auto-mode face at this leg's start). */
|
|
124
|
+
autoModeArmReason: () => AutoModeArmFact;
|
|
125
|
+
/** borrowed-readonly — the leg's live permission-mode seat: its receipt at this leg's start rides the manifest, and the
|
|
126
|
+
* peer lane reads the effective mode through the refs filled here. */
|
|
127
|
+
permissionMode: PermissionModeController;
|
|
124
128
|
/** borrowed-readonly — the frozen preflight; only `mcp` (the declared servers the manifest face joins). */
|
|
125
129
|
lockedPreflight: Pick<LockedPreflight, "mcp">;
|
|
126
130
|
/** borrowed-mutable — the peer lane's late-bound facts. Writer here: `askEffective` ← the manifest's ask derivation (the
|
|
@@ -176,9 +180,9 @@ export interface PrepareWiringManifestResult {
|
|
|
176
180
|
durableApproval: TaskSpec["durableApproval"];
|
|
177
181
|
/** owned — this leg's EFFECTIVE wiring manifest (`Prepared.wiringManifest`). */
|
|
178
182
|
wiringManifest: WiringManifest;
|
|
179
|
-
/** owned — the leg's write-protection
|
|
180
|
-
*
|
|
181
|
-
|
|
183
|
+
/** owned — the leg's write-protection judge, or undefined when the table was emptied (no judge, no tighten mounted):
|
|
184
|
+
* its gate input (`check`) for the gate station and its target judge for the shell station — one compile, never two. */
|
|
185
|
+
writeProtection: LegWriteProtection | undefined;
|
|
182
186
|
/** owned — THE park predicate as one named const (`parkLane.effective === true`). */
|
|
183
187
|
parkLaneArmed: boolean;
|
|
184
188
|
/** owned — THE gate-machinery activation predicate as one named const: a policy, a screening hook, an egress or
|
|
@@ -116,7 +116,7 @@ function announceDurableGateUnavailable(args) {
|
|
|
116
116
|
});
|
|
117
117
|
}
|
|
118
118
|
export function prepareWiringManifest(input) {
|
|
119
|
-
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, frameSettlement, sessionBox, harness, pausedRef, frozenOnAsk, liveInheritedGate, delegation, toolRoster, readDenyBuiltinTiersActive, lspManagerWired, shellReadStationArmed, lspDiagnosticsLive, fileHistoryFact } = input;
|
|
119
|
+
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, permissionMode, lockedPreflight, peerLaneRefs, frameSettlement, sessionBox, harness, pausedRef, frozenOnAsk, liveInheritedGate, delegation, toolRoster, readDenyBuiltinTiersActive, lspManagerWired, shellReadStationArmed, lspDiagnosticsLive, fileHistoryFact } = input;
|
|
120
120
|
const onAsk = spec.onAsk ?? deps.onAsk;
|
|
121
121
|
const handWriteTools = toolRoster.entries.filter((e) => e.mountedBy === "hands" && (e.effect === "write" || e.effect === "idempotent")).map((e) => e.name);
|
|
122
122
|
const hasEffectAwareGate = Boolean(policyLayers.length > 0 || (hooks?.preToolUse !== undefined && !preToolUseObservational));
|
|
@@ -210,7 +210,8 @@ export function prepareWiringManifest(input) {
|
|
|
210
210
|
memoryAdmissionWired: deps.memoryScopeAdmission !== undefined,
|
|
211
211
|
retentionPolicyWired: deps.retentionPolicy !== undefined,
|
|
212
212
|
...(modelGateManifest !== undefined ? { modelGate: modelGateManifest } : {}),
|
|
213
|
-
autoMode: { ...autoModeArmReason },
|
|
213
|
+
autoMode: { ...autoModeArmReason() },
|
|
214
|
+
permissionMode: permissionMode.receipt(),
|
|
214
215
|
mcp: mcpManifestEntries(lockedPreflight.mcp, mcp.statuses),
|
|
215
216
|
...(writeProtection !== undefined ? { writeProtectionTargetView: writeProtection.targetView } : {}),
|
|
216
217
|
readDenyBuiltinTiersActive,
|
|
@@ -222,6 +223,7 @@ export function prepareWiringManifest(input) {
|
|
|
222
223
|
fileHistory: fileHistoryFact,
|
|
223
224
|
});
|
|
224
225
|
peerLaneRefs.askEffective = wiringManifest.ask.effective;
|
|
226
|
+
peerLaneRefs.permissionMode = () => permissionMode.current;
|
|
225
227
|
const sessionBoxBound = sessionBox !== undefined && internals?.onTaskNotification !== undefined ? sessionBox : undefined;
|
|
226
228
|
if (sessionBoxBound !== undefined && internals?.onTaskNotification !== undefined) {
|
|
227
229
|
bindPeerLaneDrain(harness, {
|
|
@@ -261,5 +263,5 @@ export function prepareWiringManifest(input) {
|
|
|
261
263
|
});
|
|
262
264
|
const hookContextConsumerWired = hooks?.preToolUse !== undefined || hooks?.postToolUse !== undefined || hooks?.postToolUseFailure !== undefined;
|
|
263
265
|
const hookEnvFace = hookContextConsumerWired && (ownedEnv ?? deps.executionEnv) != null ? createHookEnvCapabilities(executionEnv) : undefined;
|
|
264
|
-
return { onAsk, preToolContexts, blockedToolCalls, gateOutcomes, batchHaltRef, blockedTracked, incompleteSuspendAdapter, durableSuspendInfraReady, resourceSuspendEligible, usageGovernance, platformSuspendArmed, durableApproval, wiringManifest,
|
|
266
|
+
return { onAsk, preToolContexts, blockedToolCalls, gateOutcomes, batchHaltRef, blockedTracked, incompleteSuspendAdapter, durableSuspendInfraReady, resourceSuspendEligible, usageGovernance, platformSuspendArmed, durableApproval, wiringManifest, writeProtection, parkLaneArmed, gateMachineryActive, hookIdentity, hookEnvFace, sessionBoxBound };
|
|
265
267
|
}
|
|
@@ -25,7 +25,16 @@ export declare function rootAdmittingArtifactStore(storePhysical: string, rootsC
|
|
|
25
25
|
* reader of the hosting seat) once the declaration validates. */
|
|
26
26
|
export interface ArtifactStoreRef {
|
|
27
27
|
current: string | undefined;
|
|
28
|
+
/** The person's STANDING read grants — their persisted `Read(//dir/**)` rows, joined to the live read set at prepare —
|
|
29
|
+
* held to the in-flight grant's store rule by {@link withdrawStandingGrantsAdmitting} once the store is known. */
|
|
30
|
+
standing?: {
|
|
31
|
+
readonly keys: readonly string[];
|
|
32
|
+
readonly readRoots: string[];
|
|
33
|
+
};
|
|
28
34
|
}
|
|
35
|
+
/** The store rule applied to the standing grants: each one that admits `storePhysical` leaves the live read set (so no
|
|
36
|
+
* read face reaches the store through it); returns the withdrawn keys, for the caller to announce. */
|
|
37
|
+
export declare function withdrawStandingGrantsAdmitting(storePhysical: string, ref: ArtifactStoreRef): string[];
|
|
29
38
|
/** Why the run's station applied no grant: the spelling did not resolve (or its lookup was cut), it no longer
|
|
30
39
|
* resolves to itself (a directory swapped for a link while the card waited), or it would admit the local artifact
|
|
31
40
|
* store (the store-isolation rule the Artifact phase judges its mount by). */
|
|
@@ -7,6 +7,18 @@ export function rootAdmittingArtifactStore(storePhysical, rootsCanonical) {
|
|
|
7
7
|
const storeFamily = pathFamilyOf({ root: storePhysical });
|
|
8
8
|
return rootsCanonical.find((root) => pathFamilyOf({ root }) === storeFamily && (withinAnyRoot([root], storePhysical) || withinAnyRoot([storePhysical], root)));
|
|
9
9
|
}
|
|
10
|
+
export function withdrawStandingGrantsAdmitting(storePhysical, ref) {
|
|
11
|
+
const standing = ref.standing;
|
|
12
|
+
if (standing === undefined)
|
|
13
|
+
return [];
|
|
14
|
+
const withdrawn = standing.keys.filter((key) => rootAdmittingArtifactStore(storePhysical, [key]) !== undefined);
|
|
15
|
+
for (const key of withdrawn) {
|
|
16
|
+
const at = standing.readRoots.indexOf(key);
|
|
17
|
+
if (at >= 0)
|
|
18
|
+
standing.readRoots.splice(at, 1);
|
|
19
|
+
}
|
|
20
|
+
return withdrawn;
|
|
21
|
+
}
|
|
10
22
|
export function readRootGrantOver(seats) {
|
|
11
23
|
const { env, writeRoots, readRoots, artifactStore } = seats;
|
|
12
24
|
return async (candidate, signal) => {
|
|
@@ -2,6 +2,7 @@ import { assertNoRetiredKeys } from "../retired-keys.js";
|
|
|
2
2
|
const RETIRED_RUNNER_DEPS_KEYS = {
|
|
3
3
|
legacyRewindBoundaryProbe: "the rewind refusal always names both possibilities (never existed / retired whole-tree era); a deployment that holds that era's table answers the question on its own surface",
|
|
4
4
|
peerAdmission: "the peer lane's knob table is `RunnerDeps.peerLane` (the same fields: admission gate, delivery budgets, listing window)",
|
|
5
|
+
graderEnvFactory: "the grader env reaches the repair loop as `RepairLoopConfig.graderEnv`, minted by the trusted control plane (`assertOracleIsolation` / `GraderEnv` unchanged)",
|
|
5
6
|
};
|
|
6
7
|
export function assertNoRetiredRunnerDeps(deps) {
|
|
7
8
|
assertNoRetiredKeys(deps, RETIRED_RUNNER_DEPS_KEYS, "RunnerDeps");
|
|
@@ -111,7 +111,7 @@ export function runIdentityWiring(input) {
|
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
113
|
const loopLatch = { ended: false, userInterrupted: false, userHalted: false };
|
|
114
|
-
onReady({ harness: prepared.harness, abortController: prepared.abortController, loop: loopLatch, reminderMark: prepared.reminderMark, sessionId: prepared.sessionId, runId: prepared.runId, hookTimeoutMs: prepared.hookTimeoutMs, hookIdentity: prepared.hookIdentity });
|
|
114
|
+
onReady({ harness: prepared.harness, abortController: prepared.abortController, loop: loopLatch, reminderMark: prepared.reminderMark, sessionId: prepared.sessionId, runId: prepared.runId, hookTimeoutMs: prepared.hookTimeoutMs, hookIdentity: prepared.hookIdentity, permissionMode: prepared.permissionMode });
|
|
115
115
|
const stats = { turns: 0, tokens: 0, toolCalls: 0, promptTokens: 0, totalInputTokens: 0, cachedTokens: 0, cacheWriteTokens: 0, cacheWriteTokensLong: 0, outputTokens: 0, costMicroUsd: 0 };
|
|
116
116
|
return { runSourceTaskId, parentToolCallId, ident, emitDelegationLifecycle, loopLatch, stats, internalsNotifier, undrainedUserAtEnd: { get current() { return undrainedUserAtEnd; } }, userInputLostAtEnd: { get current() { return userInputLostAtEnd; } } };
|
|
117
117
|
}
|
|
@@ -683,22 +683,30 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
|
|
|
683
683
|
}
|
|
684
684
|
if (prepared.persistedRuleLane !== undefined) {
|
|
685
685
|
const unreadable = { unreadable: true };
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
686
|
+
let laneWaitCancelled = false;
|
|
687
|
+
let laneRead;
|
|
688
|
+
try {
|
|
689
|
+
laneRead = Promise.resolve(prepared.persistedRuleLane.adjudicate({
|
|
690
|
+
toolName: pendingAction.toolName,
|
|
691
|
+
args: resolvedArgs,
|
|
692
|
+
toolCallId: pendingAction.toolCallId,
|
|
693
|
+
...callFaceSeat(toolCallFaceOf(prepared.toolRosterDeltas.current, pendingAction.toolName)),
|
|
694
|
+
budget: beltBudget,
|
|
695
|
+
...(prepared.cwdRef !== undefined ? { cwd: prepared.cwdRef.current } : {}),
|
|
696
|
+
...advertisedWritableRootsSeat(prepared.advertisedWritableDirs),
|
|
697
|
+
})).then((answer) => normalizePersistedRuleHit(answer));
|
|
698
|
+
}
|
|
699
|
+
catch {
|
|
700
|
+
laneRead = Promise.resolve(unreadable);
|
|
701
|
+
}
|
|
702
|
+
const read = await settleOrgVerdictWithin(laneRead, unreadable, { signal: prepared.abortController.signal, timeoutMs: ORG_ADJUDICATION_TIMEOUT_MS, onFallback: (cause) => void (laneWaitCancelled = cause === "aborted") });
|
|
697
703
|
const tightened = applyPersistedTightening({ action: "allow" }, read);
|
|
698
|
-
if (tightened.tightened === "deny" || tightened.tightened === "unreadable") {
|
|
699
|
-
const why =
|
|
700
|
-
?
|
|
701
|
-
:
|
|
704
|
+
if (laneWaitCancelled || tightened.tightened === "deny" || tightened.tightened === "unreadable") {
|
|
705
|
+
const why = laneWaitCancelled
|
|
706
|
+
? "the task was cancelled before your persisted permission rules could be read"
|
|
707
|
+
: tightened.tightened === "deny"
|
|
708
|
+
? `a standing deny rule of yours (${disclosedRuleSet(read.hit?.rules ?? [])}) now refuses it`
|
|
709
|
+
: `it could not be read against your standing deny/ask rules (${read.reason})`;
|
|
702
710
|
const ruleDenial = formatHookFeedback(`The approved tool call "${pendingAction.toolName}" was not executed: ${why}. This approval is spent — the call has to be re-issued and approved again.`, prepared.reminderMark);
|
|
703
711
|
await settleEnd(true, { content: ruleDenial }, vetoed("persisted_rule"));
|
|
704
712
|
const eid = await prepared.session.appendMessage(toolResultMsg(pendingAction.toolCallId, pendingAction.toolName, ruleDenial, true));
|
|
@@ -729,6 +737,7 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
|
|
|
729
737
|
emitCommitted(eid, "toolResult", pendingAction.toolCallId);
|
|
730
738
|
return;
|
|
731
739
|
}
|
|
740
|
+
verdict.admit?.();
|
|
732
741
|
}
|
|
733
742
|
}
|
|
734
743
|
const tool = prepared.tools.find((t) => t.name === pendingAction.toolName);
|
|
@@ -14,6 +14,7 @@ async function runNotificationLaneAs(input, obligations) {
|
|
|
14
14
|
leafId: resume.cp.leafId,
|
|
15
15
|
suspendedBatch: new Set(resume.cp.pendingAction.kind === "tool_approval" ? resume.cp.pendingAction.batchToolCallIds : []),
|
|
16
16
|
seed: resume.cp.state,
|
|
17
|
+
outcome: resume.outcome,
|
|
17
18
|
priorSuspendCount: resume.cp.suspendCount,
|
|
18
19
|
priorLedger: resume.cp.resourceLedger,
|
|
19
20
|
priorHumanReview: resume.cp.humanReview,
|
|
@@ -6,8 +6,8 @@ import type { Prepared, ResumeRun, RunnerDepsSeat, RunState, TaskIdRef } from ".
|
|
|
6
6
|
export interface RunTelemetryAndBudgetSeatsInput {
|
|
7
7
|
/** borrowed-readonly — the task spec: limits, degrade, tracer, output retries, the resource-suspend totals. */
|
|
8
8
|
spec: TaskSpec;
|
|
9
|
-
/** borrowed-mutable — the leg's prepared seat: `liveSpendRef.get` is installed, `humanReviewRef` and
|
|
10
|
-
*
|
|
9
|
+
/** borrowed-mutable — the leg's prepared seat: `liveSpendRef.get` is installed, `humanReviewRef` is written and the
|
|
10
|
+
* mode seat steered on a resume; the model, the ledger, the session id and the usage governance are read. */
|
|
11
11
|
prepared: Prepared;
|
|
12
12
|
/** borrowed-readonly — the resume plan when this leg resumes a checkpoint (the human-review latency, the plan re-arm). */
|
|
13
13
|
resume: ResumeRun | undefined;
|
|
@@ -33,7 +33,7 @@ export function runTelemetryAndBudgetSeats(input) {
|
|
|
33
33
|
});
|
|
34
34
|
}
|
|
35
35
|
if (resume !== undefined && resume.outcome.gate === "plan_review" && resume.outcome.decision === "reject") {
|
|
36
|
-
prepared.
|
|
36
|
+
void prepared.permissionMode.steer("plan");
|
|
37
37
|
}
|
|
38
38
|
rs.telemetry.cacheFamily = cacheFamilyOf(prepared.model);
|
|
39
39
|
rs.telemetry.pricing = runner.deps.pricing?.[prepared.model.id] ?? modelCostToPricing(prepared.model.cost);
|