@sema-agent/core 7.33.8 → 7.35.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 +462 -3
- 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/errors.d.ts +23 -1
- package/dist/brain/errors.js +19 -2
- package/dist/brain/open-responses.js +1 -0
- package/dist/brain/openai.js +1 -0
- package/dist/brain/status-sink.d.ts +7 -1
- package/dist/brain/stream-engine.d.ts +3 -0
- package/dist/brain/stream-engine.js +2 -1
- package/dist/brain/stream-shared.d.ts +3 -1
- package/dist/brain/stream-shared.js +16 -4
- package/dist/core/a2a.d.ts +3 -1
- package/dist/core/a2a.js +1 -1
- package/dist/core/ask-origin.d.ts +379 -154
- package/dist/core/ask-origin.js +224 -45
- package/dist/core/ask-question.js +2 -1
- 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 +54 -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 +19 -3
- package/dist/core/gate-lanes.js +116 -50
- package/dist/core/gate-outcome.d.ts +40 -7
- package/dist/core/gate-outcome.js +26 -4
- package/dist/core/governance-codes.d.ts +18 -2
- package/dist/core/governance-codes.js +23 -1
- package/dist/core/hooks.d.ts +53 -29
- package/dist/core/hooks.js +1 -3
- package/dist/core/mcp.js +1 -1
- package/dist/core/message-utils.d.ts +2 -1
- package/dist/core/message-utils.js +2 -1
- package/dist/core/mode-policy.d.ts +185 -0
- package/dist/core/mode-policy.js +184 -0
- package/dist/core/oracle-isolation.d.ts +3 -3
- package/dist/core/permission-rule-model.d.ts +20 -3
- package/dist/core/permission-rule-model.js +40 -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 +56 -9
- package/dist/core/persisted-rule-arms.d.ts +14 -10
- package/dist/core/persisted-rule-arms.js +13 -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/active-skill-scope.js +5 -4
- package/dist/core/runner/assemble-result.js +2 -2
- 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 +62 -38
- package/dist/core/runner/denial-limit-arms.d.ts +35 -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/file-history-request.d.ts +26 -0
- package/dist/core/runner/file-history-request.js +90 -0
- 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 +11 -6
- package/dist/core/runner/permission-rule-lanes.js +55 -48
- 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 +6 -4
- package/dist/core/runner/prepare-ask-lane.js +3 -3
- 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-file-history.d.ts +9 -3
- package/dist/core/runner/prepare-file-history.js +4 -90
- package/dist/core/runner/prepare-gate-stations.d.ts +37 -9
- package/dist/core/runner/prepare-gate-stations.js +46 -29
- 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 +30 -23
- package/dist/core/runner/prepare-inherited-gate.js +45 -25
- package/dist/core/runner/prepare-park-ask.d.ts +6 -4
- package/dist/core/runner/prepare-park-ask.js +7 -5
- package/dist/core/runner/prepare-policy-chain.d.ts +25 -4
- package/dist/core/runner/prepare-policy-chain.js +203 -180
- 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 +56 -24
- 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-brain-sinks.js +3 -1
- package/dist/core/runner/run-identity-wiring.js +1 -1
- package/dist/core/runner/run-leg.js +29 -18
- package/dist/core/runner/run-notification-lane.d.ts +3 -0
- package/dist/core/runner/run-notification-lane.js +3 -1
- 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.d.ts +1 -0
- package/dist/core/runner/runtask.js +8 -11
- package/dist/core/runner/session-mode-seats.d.ts +48 -0
- package/dist/core/runner/session-mode-seats.js +73 -0
- package/dist/core/runner/session-rule-policy.js +3 -2
- 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 +30 -58
- package/dist/core/secret-env.js +149 -586
- package/dist/core/sensitive-path-policy.d.ts +4 -2
- package/dist/core/sensitive-path-policy.js +41 -31
- package/dist/core/store-contracts/checkpoint-store-contract.js +2 -1
- 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 +84 -30
- package/dist/core/tool-policy.js +76 -16
- package/dist/core/tool-registry.d.ts +38 -0
- package/dist/core/tool-registry.js +25 -1
- package/dist/core/tool-roster.d.ts +17 -2
- package/dist/core/tool-roster.js +11 -1
- package/dist/core/tool-spec.d.ts +8 -9
- package/dist/core/trace.d.ts +18 -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/node-execution-env.d.ts +6 -1
- package/dist/engine/execution-env/node-execution-env.js +16 -3
- package/dist/engine/harness/agent-harness.js +2 -1
- 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/engine/lsp/node-lsp-manager.js +1 -1
- package/dist/index.d.ts +18 -8
- package/dist/index.js +15 -6
- 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/index.d.ts +5 -3
- package/dist/stores/file/session-store.d.ts +8 -2
- package/dist/stores/file/session-store.js +5 -5
- 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 +50 -0
- package/dist/tools/fs/file-read-check.js +79 -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 +52 -13
- package/dist/tools/fs/shell-read-check.js +199 -20
- 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 +1 -1
- package/test/export-surface.snapshot.json +117 -11
- package/wire-changes/core@7.34.0.json +2621 -0
- package/wire-changes/core@7.35.0.json +584 -0
|
@@ -1,25 +1,38 @@
|
|
|
1
1
|
import { policyAskClassOf } from "../ask-class.js";
|
|
2
2
|
import { ASK_USER_QUESTION_TOOL_NAME } from "../ask-question.js";
|
|
3
|
+
import { classifierUnavailableSeat } from "./classifier-ladder.js";
|
|
3
4
|
import { resolveCheckpointStore } from "../checkpoint-store.js";
|
|
4
5
|
import { cloneObserverInput, resolveHookTimeoutMs } from "../hooks.js";
|
|
5
6
|
import { assertHookSeatsCallable } from "../hook-seats.js";
|
|
6
7
|
import { isNamespacedCoveringRuleName, namespacedRuleNameCovers } from "../permission-rules.js";
|
|
7
8
|
import { isIsolated } from "../remote-env.js";
|
|
8
|
-
import { askApproverIdentity, carryEngineAttestations, carryPrecedingSettlement, checkToolPolicyProjection, combinePolicies, createTranscriptIntegrityPolicy, createUnverifiableDeletePolicy, durableParkOptInDeclared, isLiveApproverSeat, resolveAsk, toolPolicyNameSets, attestAskUnresolvableCause } from "../tool-policy.js";
|
|
9
|
+
import { askApproverIdentity, carryEngineAttestations, carryPrecedingSettlement, checkToolPolicyProjection, combinePolicies, createTranscriptIntegrityPolicy, createUnverifiableDeletePolicy, durableParkOptInDeclared, isLiveApproverSeat, resolveAsk, toolPolicyNameSets, wrapToolPolicy, attestAskUnresolvableCause } from "../tool-policy.js";
|
|
9
10
|
import { RETIRED_TOOL_NAMES } from "../tool-name-aliases.js";
|
|
10
11
|
import { NAMESPACED_NAME_SHAPES, protocolOf } from "../protocol-table.js";
|
|
11
12
|
import { emitTrace } from "../trace.js";
|
|
12
13
|
import { createActiveSkillScopePolicy } from "./active-skill-scope.js";
|
|
13
|
-
import { askMandateMember,
|
|
14
|
+
import { arbitrateByMode, askMandateMember, classifyAsk } from "../ask-origin.js";
|
|
15
|
+
import { createModeGatePolicy, mountedToolDeclaresReadOnly } from "../mode-policy.js";
|
|
14
16
|
const ancestorFacts = (ask) => ({ ...(ask ?? {}), ancestorResolved: true });
|
|
15
|
-
import { headlessDenyAtFold, headlessDenyAtRecheck, inheritedAskCarry, judgeInheritedClassifier, lateAskSettlementObserver, settleDenialLimitFallback } from "./denial-limit-arms.js";
|
|
17
|
+
import { headlessDenyAtFold, headlessDenyAtRecheck, INHERITED_STATION_FACTS, inheritedAskCarry, judgeInheritedClassifier, lateAskSettlementObserver, settleDenialLimitFallback } from "./denial-limit-arms.js";
|
|
16
18
|
import { settleReadRootGrant } from "./read-root-grant.js";
|
|
17
19
|
import { askGrantShapeOf } from "./inherited-ask-grants.js";
|
|
18
20
|
import { createPermissionRuleLanes, inheritedAskRuleEvidence, createRuleOffersOf } from "./permission-rule-lanes.js";
|
|
19
21
|
import { createLiveSessionRules, createSessionRulePolicy } from "./session-rule-policy.js";
|
|
20
22
|
import { thrownText } from "../thrown-value.js";
|
|
23
|
+
import { anyNamed, firstNamed, ruleNamesOf } from "../tool-roster.js";
|
|
21
24
|
export async function preparePolicyChain(input) {
|
|
22
|
-
const { 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 } = input;
|
|
25
|
+
const { 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, permissionMode, scratchpadDir, toolRosterDeltas, stopForDenialLimit, delegation, abortController, now, ownSessionRulesRef } = input;
|
|
26
|
+
const ancestorArbitrations = new Map();
|
|
27
|
+
const arbitrateInherited = (ask, toolCallId) => {
|
|
28
|
+
const verdict = arbitrateByMode(permissionMode.current, classifyAsk(ask, INHERITED_STATION_FACTS), { ...(ask.origin !== undefined ? { origin: ask.origin } : {}), ...(ask.mandate !== undefined ? { mandate: ask.mandate } : {}) });
|
|
29
|
+
if (verdict.kind === "ask" || verdict.kind === "accepted")
|
|
30
|
+
return undefined;
|
|
31
|
+
ancestorArbitrations.set(toolCallId, verdict);
|
|
32
|
+
if (verdict.kind === "released")
|
|
33
|
+
return { action: "allow", message: `released by the ${verdict.mode} permission mode at an inherited ancestor layer (the ${verdict.askClass} ask was not put to anyone)`, decisionReason: "mode", ...(ask.updatedInput !== undefined ? { updatedInput: ask.updatedInput } : {}) };
|
|
34
|
+
return { action: "deny", message: `refused by the ${verdict.mode} permission mode at an inherited ancestor layer (${verdict.askClass})`, decisionReason: "mode" };
|
|
35
|
+
};
|
|
23
36
|
const policy = lockedPreflight.toolPolicy;
|
|
24
37
|
const auditPolicyNames = (auditee) => {
|
|
25
38
|
const nameGroups = toolPolicyNameSets(auditee);
|
|
@@ -220,7 +233,7 @@ export async function preparePolicyChain(input) {
|
|
|
220
233
|
list.push({ cls, layer });
|
|
221
234
|
foldAskClasses.set(toolCallId, list);
|
|
222
235
|
};
|
|
223
|
-
const sandboxBoundaryCapable = (
|
|
236
|
+
const sandboxBoundaryCapable = (call) => anyNamed(egressTools, ruleNamesOf(call)) || !envHandToolNames.has(call.toolName);
|
|
224
237
|
const emitSandboxAdmitted = (info) => {
|
|
225
238
|
emitTrace(deps.tracer, () => ({
|
|
226
239
|
kind: "permission.sandbox_admitted",
|
|
@@ -244,18 +257,16 @@ export async function preparePolicyChain(input) {
|
|
|
244
257
|
void toolName;
|
|
245
258
|
};
|
|
246
259
|
const callerPolicyLayer = policy !== undefined && sameInstanceAncestorCount > 0
|
|
247
|
-
? {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
},
|
|
258
|
-
}
|
|
260
|
+
? wrapToolPolicy(policy, async (creq, csignal) => {
|
|
261
|
+
const decision = await policy.check(creq, csignal ?? abortController.signal);
|
|
262
|
+
sharedFirstDecision.set(creq.toolCallId, decision);
|
|
263
|
+
if (sharedFirstDecision.size > SHARED_FIRST_DECISION_CAP) {
|
|
264
|
+
const oldest = sharedFirstDecision.keys().next().value;
|
|
265
|
+
if (oldest !== undefined)
|
|
266
|
+
sharedFirstDecision.delete(oldest);
|
|
267
|
+
}
|
|
268
|
+
return decision;
|
|
269
|
+
})
|
|
259
270
|
: policy;
|
|
260
271
|
const askSourceIdentity = () => ({
|
|
261
272
|
principal: spec.principal,
|
|
@@ -266,11 +277,12 @@ export async function preparePolicyChain(input) {
|
|
|
266
277
|
: {}),
|
|
267
278
|
...(delegation.isDelegatedChild ? { isDelegatedChild: true } : {}),
|
|
268
279
|
});
|
|
269
|
-
const riskAxesOf = (
|
|
270
|
-
const
|
|
271
|
-
const
|
|
280
|
+
const riskAxesOf = (call) => {
|
|
281
|
+
const names = ruleNamesOf(call);
|
|
282
|
+
const tier = firstNamed(irreversibilityTier, names)?.value;
|
|
283
|
+
const negatives = firstNamed(axisExplicitNegatives, names)?.value;
|
|
272
284
|
const irreversible = tier === "always" || tier === "maybe" ? true : tier === "never" ? false : negatives?.irreversible;
|
|
273
|
-
const egress = egressTools
|
|
285
|
+
const egress = anyNamed(egressTools, names) ? true : negatives?.egress;
|
|
274
286
|
if (irreversible === undefined && egress === undefined)
|
|
275
287
|
return {};
|
|
276
288
|
return { riskAxes: { ...(irreversible !== undefined ? { irreversible } : {}), ...(egress !== undefined ? { egress } : {}) } };
|
|
@@ -288,6 +300,8 @@ export async function preparePolicyChain(input) {
|
|
|
288
300
|
questionToolName: ASK_USER_QUESTION_TOOL_NAME,
|
|
289
301
|
onRevisionDefect: (message) => deps.onError?.(new Error(message), { phase: "config", sessionId }),
|
|
290
302
|
onDisclosure: (message) => emitTrace(deps.tracer, () => ({ kind: "permission.rule_store_unreadable", version: 1, taskId: hostTaskId, message, ts: Date.now() })),
|
|
303
|
+
onStoreUnreadable: announceRuleStoreSkipped,
|
|
304
|
+
signal: abortController.signal,
|
|
291
305
|
});
|
|
292
306
|
const ruleOffersOf = createRuleOffersOf({
|
|
293
307
|
laneArmed: permissionRuleLane !== undefined,
|
|
@@ -300,7 +314,9 @@ export async function preparePolicyChain(input) {
|
|
|
300
314
|
cwdRef: handsCwdRef,
|
|
301
315
|
deniesDirectoryRead: readDenyMatcher !== undefined ? (d) => readDenyMatcher.matchPath(d) !== null : undefined,
|
|
302
316
|
});
|
|
303
|
-
const recheckApprovedEdit = async (pol, onAskOf, creq, edit, approved, csignal,
|
|
317
|
+
const recheckApprovedEdit = async (pol, onAskOf, creq, edit, approved, csignal, ancestorAutoMode) => {
|
|
318
|
+
const ancestorDecider = ancestorAutoMode?.decider;
|
|
319
|
+
const ancestorTracker = ancestorAutoMode?.denialTracking;
|
|
304
320
|
let editArgs = edit;
|
|
305
321
|
let settledBy = approved;
|
|
306
322
|
const vetoed = (d) => {
|
|
@@ -336,7 +352,7 @@ export async function preparePolicyChain(input) {
|
|
|
336
352
|
}
|
|
337
353
|
if (re.updatedInput !== undefined)
|
|
338
354
|
editArgs = re.updatedInput;
|
|
339
|
-
const judged = await judgeInheritedClassifier({
|
|
355
|
+
const judged = await judgeInheritedClassifier({ liveMode: () => permissionMode.current, autoMode: ancestorAutoMode, ask: re, req: { ...creq, args: editArgs }, signal: csignal ?? abortController.signal, subject: "the approved edit", allowRewrite: editArgs, unavailableSeat: classifierUnavailableSeat({ station: "ancestor", ...(ancestorDecider?.timeoutMs !== undefined ? { budgetMs: ancestorDecider.timeoutMs } : {}), approvalSeat: isLiveApproverSeat(onAskOf), onNotice: deps.onNotice, sessionId, runId }) });
|
|
340
356
|
if (judged.kind === "allow") {
|
|
341
357
|
const cleared = { ...judged.result };
|
|
342
358
|
carryEngineAttestations(judged.result, cleared);
|
|
@@ -347,14 +363,20 @@ export async function preparePolicyChain(input) {
|
|
|
347
363
|
return vetoed(judged.result);
|
|
348
364
|
const { ask: editAsk, fallback: editFallback, mintedHere: editMintedHere } = judged;
|
|
349
365
|
re = editAsk;
|
|
366
|
+
const editArbitrated = arbitrateInherited(re, creq.toolCallId);
|
|
367
|
+
if (editArbitrated !== undefined) {
|
|
368
|
+
const out = editArbitrated.action === "allow" ? { action: "allow", updatedInput: editArgs } : editArbitrated;
|
|
369
|
+
carryPrecedingSettlement(settledBy, out);
|
|
370
|
+
return out;
|
|
371
|
+
}
|
|
350
372
|
const rr = await resolveAsk({
|
|
351
373
|
toolName: creq.toolName,
|
|
352
374
|
toolCallId: creq.toolCallId,
|
|
353
375
|
args: editArgs,
|
|
354
|
-
...ruleOffersOf(creq
|
|
376
|
+
...ruleOffersOf(creq, editArgs, ancestorFacts(re)),
|
|
355
377
|
message: re.message ?? `approval required for "${creq.toolName}" (inherited parent policy)`,
|
|
356
378
|
...askSourceIdentity(),
|
|
357
|
-
...riskAxesOf(creq
|
|
379
|
+
...riskAxesOf(creq),
|
|
358
380
|
...(re.requiresRealApproval === true ? { requiresRealApproval: true } : {}),
|
|
359
381
|
...askMandateMember(ancestorFacts(re)),
|
|
360
382
|
...(re.persistedRuleShadowed !== undefined ? { persistedRuleShadowed: re.persistedRuleShadowed } : {}),
|
|
@@ -381,7 +403,7 @@ export async function preparePolicyChain(input) {
|
|
|
381
403
|
pc.contentMandate !== true &&
|
|
382
404
|
askApproverIdentity(pc.onAsk) === askApproverIdentity(frozenOnAsk) &&
|
|
383
405
|
pc.hookEnv === hookEnvSource &&
|
|
384
|
-
pc.autoMode?.decider === autoModeDecider
|
|
406
|
+
pc.autoMode?.decider === autoModeDecider()
|
|
385
407
|
? { check: () => ({ action: "allow" }) }
|
|
386
408
|
: policy !== undefined && pc.policy === policy
|
|
387
409
|
? {
|
|
@@ -412,26 +434,29 @@ export async function preparePolicyChain(input) {
|
|
|
412
434
|
return first;
|
|
413
435
|
return mandateUnreconstructibleDeny(creq);
|
|
414
436
|
}
|
|
415
|
-
const judged = await judgeInheritedClassifier({ autoMode: pc.autoMode, ask: first, req: creq, signal: csignal ?? abortController.signal, subject: "this call" });
|
|
437
|
+
const judged = await judgeInheritedClassifier({ liveMode: () => permissionMode.current, autoMode: pc.autoMode, ask: first, req: creq, signal: csignal ?? abortController.signal, subject: "this call", unavailableSeat: classifierUnavailableSeat({ station: "ancestor", ...(pc.autoMode?.decider.timeoutMs !== undefined ? { budgetMs: pc.autoMode.decider.timeoutMs } : {}), approvalSeat: isLiveApproverSeat(pc.onAsk), onNotice: deps.onNotice, sessionId, runId }) });
|
|
416
438
|
if (judged.kind === "allow")
|
|
417
439
|
return judged.result;
|
|
418
440
|
if (judged.kind === "deny")
|
|
419
441
|
return judged.result;
|
|
420
442
|
const { ask: inheritedAsk, fallback, mintedHere } = judged;
|
|
421
|
-
if (fallback === undefined && sandboxAdmissionArmed && policyAskClassOf(pc.policy) === "sandbox_local" && !sandboxBoundaryCapable(creq
|
|
443
|
+
if (fallback === undefined && sandboxAdmissionArmed && policyAskClassOf(pc.policy) === "sandbox_local" && !sandboxBoundaryCapable(creq) && classifyAsk(inheritedAsk, INHERITED_STATION_FACTS).row.sandboxAdmission) {
|
|
422
444
|
recordAncestorSandboxAdmission(creq.toolCallId, creq.toolName);
|
|
423
445
|
return { action: "allow" };
|
|
424
446
|
}
|
|
447
|
+
const arbitrated = arbitrateInherited(inheritedAsk, creq.toolCallId);
|
|
448
|
+
if (arbitrated !== undefined)
|
|
449
|
+
return arbitrated;
|
|
425
450
|
const presentedArgs = creq.args;
|
|
426
451
|
const askT0 = now();
|
|
427
452
|
const resolved = await resolveAsk({
|
|
428
453
|
toolName: creq.toolName,
|
|
429
454
|
toolCallId: creq.toolCallId,
|
|
430
455
|
args: presentedArgs,
|
|
431
|
-
...ruleOffersOf(creq
|
|
456
|
+
...ruleOffersOf(creq, presentedArgs, ancestorFacts(inheritedAsk.action === "ask" ? inheritedAsk : undefined)),
|
|
432
457
|
message: inheritedAsk.message ?? `approval required for "${creq.toolName}" (inherited parent policy)`,
|
|
433
458
|
...askSourceIdentity(),
|
|
434
|
-
...riskAxesOf(creq
|
|
459
|
+
...riskAxesOf(creq),
|
|
435
460
|
...(inheritedAsk.action === "ask" && inheritedAsk.requiresRealApproval === true ? { requiresRealApproval: true } : {}),
|
|
436
461
|
...askMandateMember(ancestorFacts(inheritedAsk.action === "ask" ? inheritedAsk : undefined)),
|
|
437
462
|
...(inheritedAsk.action === "ask" && inheritedAsk.persistedRuleShadowed !== undefined ? { persistedRuleShadowed: inheritedAsk.persistedRuleShadowed } : {}),
|
|
@@ -449,89 +474,90 @@ export async function preparePolicyChain(input) {
|
|
|
449
474
|
if (resolved.action !== "allow")
|
|
450
475
|
return resolved;
|
|
451
476
|
if (resolved.updatedInput !== undefined) {
|
|
452
|
-
return recheckApprovedEdit(pc.policy, pc.onAsk, creq, resolved.updatedInput, resolved, csignal, pc.autoMode
|
|
477
|
+
return recheckApprovedEdit(pc.policy, pc.onAsk, creq, resolved.updatedInput, resolved, csignal, pc.autoMode);
|
|
453
478
|
}
|
|
454
479
|
recordInheritedAskGrant(creq.toolCallId, pc.onAsk, resolved.presentedInput, askWaitMs, resolved);
|
|
455
480
|
return { action: "allow" };
|
|
456
481
|
},
|
|
457
482
|
}
|
|
458
|
-
: {
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
483
|
+
: wrapToolPolicy(pc.policy, async (creq, csignal) => {
|
|
484
|
+
let decision;
|
|
485
|
+
try {
|
|
486
|
+
decision = await pc.policy.check(creq, csignal ?? abortController.signal);
|
|
487
|
+
}
|
|
488
|
+
catch (err) {
|
|
489
|
+
return {
|
|
490
|
+
action: "deny",
|
|
491
|
+
message: `inherited parent policy errored for "${creq.toolName}": ${thrownText(err)}`,
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
if (decision.action !== "ask")
|
|
495
|
+
return decision;
|
|
496
|
+
if (creq.toolName === ASK_USER_QUESTION_TOOL_NAME) {
|
|
497
|
+
if (pc.contentMandate !== true || markInheritedUnavailable(creq.toolCallId))
|
|
471
498
|
return decision;
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
});
|
|
499
|
+
return {
|
|
500
|
+
action: "deny",
|
|
501
|
+
message: `inherited parent policy requires durable handling of the question raised for "${creq.toolName}" and the marker channel is at capacity — ` +
|
|
502
|
+
`denied fail-closed (tighten-only)`,
|
|
503
|
+
};
|
|
504
|
+
}
|
|
505
|
+
if (pc.durableMandate === true) {
|
|
506
|
+
if (mandatedCallFloats(creq.toolCallId))
|
|
507
|
+
return decision;
|
|
508
|
+
return mandateUnreconstructibleDeny(creq);
|
|
509
|
+
}
|
|
510
|
+
const presentedArgs = decision.updatedInput !== undefined ? decision.updatedInput : creq.args;
|
|
511
|
+
const judged = await judgeInheritedClassifier({ liveMode: () => permissionMode.current, autoMode: pc.autoMode, ask: decision, req: { ...creq, args: presentedArgs }, signal: csignal ?? abortController.signal, subject: "this call", allowRewrite: decision.updatedInput, unavailableSeat: classifierUnavailableSeat({ station: "ancestor", ...(pc.autoMode?.decider.timeoutMs !== undefined ? { budgetMs: pc.autoMode.decider.timeoutMs } : {}), approvalSeat: isLiveApproverSeat(pc.onAsk), onNotice: deps.onNotice, sessionId, runId }) });
|
|
512
|
+
if (judged.kind === "allow")
|
|
513
|
+
return judged.result;
|
|
514
|
+
if (judged.kind === "deny")
|
|
515
|
+
return judged.result;
|
|
516
|
+
const { ask: inheritedAsk, fallback, mintedHere } = judged;
|
|
517
|
+
if (fallback === undefined && sandboxAdmissionArmed && policyAskClassOf(pc.policy) === "sandbox_local" && !sandboxBoundaryCapable(creq) && classifyAsk(inheritedAsk, INHERITED_STATION_FACTS).row.sandboxAdmission) {
|
|
518
|
+
recordAncestorSandboxAdmission(creq.toolCallId, creq.toolName);
|
|
519
|
+
return decision.updatedInput !== undefined ? { action: "allow", updatedInput: decision.updatedInput } : { action: "allow" };
|
|
520
|
+
}
|
|
521
|
+
const arbitrated = arbitrateInherited(inheritedAsk.action === "ask" ? { ...inheritedAsk, ...(decision.updatedInput !== undefined ? { updatedInput: decision.updatedInput } : {}) } : inheritedAsk, creq.toolCallId);
|
|
522
|
+
if (arbitrated !== undefined)
|
|
523
|
+
return arbitrated;
|
|
524
|
+
const askT0 = now();
|
|
525
|
+
const resolved = await resolveAsk({
|
|
526
|
+
toolName: creq.toolName,
|
|
527
|
+
toolCallId: creq.toolCallId,
|
|
528
|
+
args: presentedArgs,
|
|
529
|
+
...ruleOffersOf(creq, presentedArgs, ancestorFacts(inheritedAsk.action === "ask" ? inheritedAsk : undefined)),
|
|
530
|
+
message: inheritedAsk.message ?? `approval required for "${creq.toolName}" (inherited parent policy)`,
|
|
531
|
+
...askSourceIdentity(),
|
|
532
|
+
...riskAxesOf(creq),
|
|
533
|
+
...(inheritedAsk.action === "ask" && inheritedAsk.requiresRealApproval === true ? { requiresRealApproval: true } : {}),
|
|
534
|
+
...askMandateMember(ancestorFacts(inheritedAsk.action === "ask" ? inheritedAsk : undefined)),
|
|
535
|
+
...(inheritedAsk.action === "ask" && inheritedAsk.persistedRuleShadowed !== undefined ? { persistedRuleShadowed: inheritedAsk.persistedRuleShadowed } : {}),
|
|
536
|
+
...inheritedAskCarry(judged, isLiveApproverSeat(pc.onAsk), pc.autoMode?.denialTracking),
|
|
537
|
+
ruleEvidence: inheritedAskEvidence,
|
|
538
|
+
}, pc.onAsk, csignal ?? abortController.signal, lateAskSettlementObserver({ toolName: creq.toolName, toolCallId: creq.toolCallId, sessionId, runId, ...(spec.taskId !== undefined ? { taskId: spec.taskId } : {}), onNotice: deps.onNotice, onError: deps.onError }));
|
|
539
|
+
void settleReadRootGrant(resolved.readRootGrant, undefined, { toolName: creq.toolName, toolCallId: creq.toolCallId, sessionId, runId, ...(spec.taskId !== undefined ? { taskId: spec.taskId } : {}), onNotice: deps.onNotice });
|
|
540
|
+
const askWaitMs = Math.max(0, now() - askT0);
|
|
541
|
+
if (resolved.action === "deny" && resolved.approverUnavailable === true) {
|
|
542
|
+
if (markInheritedUnavailable(creq.toolCallId))
|
|
543
|
+
return inheritedAsk;
|
|
544
|
+
return markerChannelFullDeny(creq);
|
|
545
|
+
}
|
|
546
|
+
settleDenialLimitFallback({ fallback, mintedHere, tracker: pc.autoMode?.denialTracking, resolved, headless: headlessDenyAtFold, stop: stopForDenialLimit, toolName: creq.toolName, toolCallId: creq.toolCallId });
|
|
547
|
+
if (resolved.action !== "allow")
|
|
548
|
+
return resolved;
|
|
549
|
+
if (resolved.updatedInput !== undefined) {
|
|
550
|
+
return recheckApprovedEdit(pc.policy, pc.onAsk, creq, resolved.updatedInput, resolved, csignal, pc.autoMode);
|
|
551
|
+
}
|
|
552
|
+
if (pc.preToolUse === undefined) {
|
|
553
|
+
recordInheritedAskGrant(creq.toolCallId, pc.onAsk, resolved.presentedInput, askWaitMs, resolved);
|
|
554
|
+
}
|
|
555
|
+
if (decision.updatedInput === undefined)
|
|
556
|
+
return resolved;
|
|
557
|
+
const approvedWithRewrite = { ...resolved, updatedInput: decision.updatedInput };
|
|
558
|
+
carryEngineAttestations(resolved, approvedWithRewrite);
|
|
559
|
+
return approvedWithRewrite;
|
|
560
|
+
}));
|
|
535
561
|
const rewriteCapableLayers = policy !== undefined || parentConstraintWrappers.length > 0;
|
|
536
562
|
const rewriteEmitterIndex = new Map();
|
|
537
563
|
const rewriteCapableChain = [
|
|
@@ -544,17 +570,16 @@ export async function preparePolicyChain(input) {
|
|
|
544
570
|
if (policy !== undefined && pc.policy === policy)
|
|
545
571
|
sameInstanceAdapterIndices.add(j + callerSlotOffset);
|
|
546
572
|
});
|
|
547
|
-
const instrumentedChain = rewriteCapableChain.map((layer, idx) => ({
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
return d;
|
|
556
|
-
},
|
|
573
|
+
const instrumentedChain = rewriteCapableChain.map((layer, idx) => wrapToolPolicy(layer, async (creq, csignal) => {
|
|
574
|
+
const d = await layer.check(creq, csignal);
|
|
575
|
+
if (d.updatedInput !== undefined)
|
|
576
|
+
rewriteEmitterIndex.set(creq.toolCallId, idx);
|
|
577
|
+
if (d.action === "ask") {
|
|
578
|
+
recordFoldAskClass(creq.toolCallId, idx < callerSlotOffset ? policyAskClassOf(policy) : "mandate", idx < callerSlotOffset ? "caller_policy" : "ancestor_constraint");
|
|
579
|
+
}
|
|
580
|
+
return d;
|
|
557
581
|
}));
|
|
582
|
+
const modeGateLayer = createModeGatePolicy(permissionMode, { env: executionEnv, rootPath: taskRootFinal, acceptDirs: [taskRootFinal, ...additionalRootsCanonical], roster: toolRosterDeltas, readOnlyDeclared: (name) => mountedToolDeclaresReadOnly(tools, name), ...(scratchpadDir !== undefined ? { exemptDirs: [scratchpadDir] } : {}) });
|
|
558
583
|
const policyLayers = [
|
|
559
584
|
...narrowingLayers,
|
|
560
585
|
...instrumentedChain,
|
|
@@ -562,76 +587,74 @@ export async function preparePolicyChain(input) {
|
|
|
562
587
|
];
|
|
563
588
|
const integrityGuardLayers = [createTranscriptIntegrityPolicy(), createUnverifiableDeletePolicy()];
|
|
564
589
|
const guardedPolicyLayers = rewriteCapableLayers
|
|
565
|
-
? [...integrityGuardLayers, ...policyLayers, ...integrityGuardLayers]
|
|
566
|
-
: [...integrityGuardLayers, ...policyLayers];
|
|
590
|
+
? [...integrityGuardLayers, ...policyLayers, modeGateLayer, ...integrityGuardLayers]
|
|
591
|
+
: [...integrityGuardLayers, ...policyLayers, modeGateLayer];
|
|
567
592
|
const foldedPolicy = guardedPolicyLayers.length === 1 ? guardedPolicyLayers[0] : combinePolicies(...guardedPolicyLayers);
|
|
568
593
|
const effectivePolicy = foldedPolicy !== undefined && rewriteCapableLayers
|
|
569
|
-
? {
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
catch (err) {
|
|
576
|
-
rewriteEmitterIndex.delete(req.toolCallId);
|
|
577
|
-
throw err;
|
|
578
|
-
}
|
|
579
|
-
const emitterIdx = rewriteEmitterIndex.get(req.toolCallId);
|
|
594
|
+
? wrapToolPolicy(foldedPolicy, async (req, signal) => {
|
|
595
|
+
let decision;
|
|
596
|
+
try {
|
|
597
|
+
decision = await foldedPolicy.check(req, signal);
|
|
598
|
+
}
|
|
599
|
+
catch (err) {
|
|
580
600
|
rewriteEmitterIndex.delete(req.toolCallId);
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
601
|
+
throw err;
|
|
602
|
+
}
|
|
603
|
+
const emitterIdx = rewriteEmitterIndex.get(req.toolCallId);
|
|
604
|
+
rewriteEmitterIndex.delete(req.toolCallId);
|
|
605
|
+
if (decision.action === "deny" || decision.updatedInput === undefined)
|
|
606
|
+
return decision;
|
|
607
|
+
const recheckPrefix = rewriteCapableChain.slice(0, emitterIdx ?? rewriteCapableChain.length);
|
|
608
|
+
const postEmitterSameInstanceAdapters = [];
|
|
609
|
+
if (emitterIdx !== undefined && emitterIdx > 0) {
|
|
610
|
+
for (let i = emitterIdx + 1; i < rewriteCapableChain.length; i++) {
|
|
611
|
+
if (sameInstanceAdapterIndices.has(i))
|
|
612
|
+
postEmitterSameInstanceAdapters.push(rewriteCapableChain[i]);
|
|
590
613
|
}
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
if (d.updatedInput !== undefined) {
|
|
605
|
-
return {
|
|
606
|
-
action: "deny",
|
|
607
|
-
message: "policy required a rewrite during final-form re-check — the arguments that would execute were not accepted as-is (fail-closed; rewrite chains are not iterated to a fixpoint)",
|
|
608
|
-
updatedInput: decision.updatedInput,
|
|
609
|
-
};
|
|
610
|
-
}
|
|
611
|
-
if (d.action === "ask" && asked === undefined)
|
|
612
|
-
asked = d;
|
|
613
|
-
carryEngineAttestations(d, revalidated);
|
|
614
|
+
}
|
|
615
|
+
const recheckLayers = [...recheckPrefix, ...postEmitterSameInstanceAdapters];
|
|
616
|
+
const finalReq = { ...req, args: decision.updatedInput };
|
|
617
|
+
let asked;
|
|
618
|
+
const revalidated = {};
|
|
619
|
+
try {
|
|
620
|
+
for (const layer of recheckLayers) {
|
|
621
|
+
const d = await layer.check(finalReq, signal);
|
|
622
|
+
if (d.action === "deny") {
|
|
623
|
+
const carried = { ...d, updatedInput: decision.updatedInput };
|
|
624
|
+
carryEngineAttestations(d, carried);
|
|
625
|
+
carryPrecedingSettlement(decision, carried);
|
|
626
|
+
return carried;
|
|
614
627
|
}
|
|
628
|
+
if (d.updatedInput !== undefined) {
|
|
629
|
+
return {
|
|
630
|
+
action: "deny",
|
|
631
|
+
message: "policy required a rewrite during final-form re-check — the arguments that would execute were not accepted as-is (fail-closed; rewrite chains are not iterated to a fixpoint)",
|
|
632
|
+
updatedInput: decision.updatedInput,
|
|
633
|
+
};
|
|
634
|
+
}
|
|
635
|
+
if (d.action === "ask" && asked === undefined)
|
|
636
|
+
asked = d;
|
|
637
|
+
carryEngineAttestations(d, revalidated);
|
|
615
638
|
}
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
}
|
|
639
|
+
}
|
|
640
|
+
finally {
|
|
641
|
+
rewriteEmitterIndex.delete(req.toolCallId);
|
|
642
|
+
}
|
|
643
|
+
if (asked !== undefined && decision.action === "allow") {
|
|
644
|
+
const surfaced = { ...asked, updatedInput: decision.updatedInput };
|
|
645
|
+
carryEngineAttestations(asked, surfaced);
|
|
646
|
+
return surfaced;
|
|
647
|
+
}
|
|
648
|
+
if (decision.action === "allow") {
|
|
649
|
+
const owned = { ...decision };
|
|
650
|
+
carryEngineAttestations(decision, owned);
|
|
651
|
+
carryEngineAttestations(revalidated, owned);
|
|
652
|
+
return owned;
|
|
653
|
+
}
|
|
654
|
+
return decision;
|
|
655
|
+
})
|
|
633
656
|
: foldedPolicy;
|
|
634
|
-
return { hooks, hookTimeoutMs, preToolUseObservational, ownGatePreToolUse, basePolicyForResumeEdit, denyNarrowingPolicy, policyLayers, effectivePolicy, inheritedUnavailableAsks, inheritedAskGrants, askSourceIdentity, riskAxesOf, ruleOffersOf, permissionRuleLane, permissionRuleOrgLane, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, foldAskClasses, ancestorSandboxAdmissions };
|
|
657
|
+
return { hooks, hookTimeoutMs, preToolUseObservational, ownGatePreToolUse, basePolicyForResumeEdit, denyNarrowingPolicy, policyLayers, effectivePolicy, inheritedUnavailableAsks, inheritedAskGrants, askSourceIdentity, riskAxesOf, ruleOffersOf, permissionRuleLane, permissionRuleOrgLane, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, foldAskClasses, ancestorSandboxAdmissions, ancestorArbitrations };
|
|
635
658
|
}
|
|
636
659
|
const advisedPolicyNames = new WeakMap();
|
|
637
660
|
const ADVISED_KEYS_CAP = 64;
|
|
@@ -1,3 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PrepareTask's PROTOCOL-TOOLS phase, verbatim from the driver: the MCP materialization
|
|
3
|
+
* with its operator face (fail-open warnings once per session, the intake drops, the announce-lane prune), the
|
|
4
|
+
* reserved-name refusal, the roster push through the large-result wrapper, the RefreshMcpTools seam with its
|
|
5
|
+
* refresh closure, the two run-time seats the rebuild closures reach (`rebuildHarnessToolsRef`,
|
|
6
|
+
* `contentOriginWrapRef`) and the gate-armed honesty flag, the protocol-SHARED axis fold, and the A2A twin
|
|
7
|
+
* (materialize, warnings straight to the sink, its own reserved-name refusal, the same fold). The interface
|
|
8
|
+
* is the dependency list the segment had implicitly.
|
|
9
|
+
*
|
|
10
|
+
* ASYNC PHASE: the segment awaits the two materializers, exactly where the driver awaited them; the phase adds
|
|
11
|
+
* no yield BEFORE the first of those awaits. Read-stability of the host handles for the call:
|
|
12
|
+
* {@link RunInternals} (`@contract prepare.deps-read-stable`).
|
|
13
|
+
*
|
|
14
|
+
* The handles and the rollback stack. This phase is the first that acquires a handle INSIDE
|
|
15
|
+
* its body: the driver used to see `mcp` / `a2a` only because they were hoisted `let`s at function scope, so
|
|
16
|
+
* its catch could dispose a half-acquired pair. Those hoists are gone. The moment a materializer returns a
|
|
17
|
+
* real handle the phase pushes its `dispose` onto the driver-owned `rollback`; a prepare that throws AFTER
|
|
18
|
+
* this phase reaches the driver's catch, whose `unwindAll` disposes the peers, then the clients — the reverse
|
|
19
|
+
* acquisition order the hoisted legs kept, each bounded and reported. The two reserved-name arms only THROW:
|
|
20
|
+
* the release of what they refused is the rollback entry, called exactly once by that unwind (they used to
|
|
21
|
+
* dispose inline as well — a hoist-era leftover that leaned on dispose being idempotent; the transcript pins
|
|
22
|
+
* the single call). On the success path the stack is committed and the handles belong to `Prepared` (the
|
|
23
|
+
* Runner's finish releases them).
|
|
24
|
+
*/
|
|
25
|
+
import type { ToolMarkSource } from "../ask-origin.js";
|
|
1
26
|
import type { AgentTool } from "../../internal/harness.js";
|
|
2
27
|
import { type MaterializedMcp, type McpDroppedTool, type McpReconnectResult } from "../mcp.js";
|
|
3
28
|
import { type MaterializedA2a } from "../a2a.js";
|
|
@@ -59,6 +84,9 @@ export interface PrepareProtocolToolsInput {
|
|
|
59
84
|
irreversibleTools: Set<string>;
|
|
60
85
|
/** borrowed-mutable — the egress set, added to by the fold (tighten-only; the effect:"write" invariant). */
|
|
61
86
|
egressTools: Set<string>;
|
|
87
|
+
/** borrowed-mutable — WHO marked each tool (the safety scan's map); the protocol fold adds its own source word per
|
|
88
|
+
* axis it tightens (`mcp_annotation` for a server's self-report, `a2a_default` for a peer skill's egress default). */
|
|
89
|
+
toolMarkSources: Map<string, Set<ToolMarkSource>>;
|
|
62
90
|
/** borrowed-readonly — the run's abort controller; its `signal` rides into the A2A materialization. */
|
|
63
91
|
abortController: Pick<AbortController, "signal">;
|
|
64
92
|
/** borrowed-mutable — the driver-owned prepare-failure stack; this phase pushes one entry per REAL handle
|
|
@@ -11,7 +11,14 @@ import { mintNamespacePrefix } from "../protocol-naming.js";
|
|
|
11
11
|
import { applyMcpToolFaces } from "./tool-face-overlay.js";
|
|
12
12
|
import { thrownText } from "../thrown-value.js";
|
|
13
13
|
export async function prepareProtocolTools(input) {
|
|
14
|
-
const { lockedPreflight, spec, deps, reminderMark, reminderDisclosureCounts, runId, sessionId, onceLedger, roster, rosterSeat, remoteToolOffload, toolFaceSnapshot, toolEffects, axisExplicitNegatives, irreversibilityTier, irreversibleTools, egressTools, abortController, rollback } = input;
|
|
14
|
+
const { lockedPreflight, spec, deps, reminderMark, reminderDisclosureCounts, runId, sessionId, onceLedger, roster, rosterSeat, remoteToolOffload, toolFaceSnapshot, toolEffects, axisExplicitNegatives, irreversibilityTier, irreversibleTools, egressTools, toolMarkSources, abortController, rollback } = input;
|
|
15
|
+
const markedBy = (name, source) => {
|
|
16
|
+
const set = toolMarkSources.get(name);
|
|
17
|
+
if (set !== undefined)
|
|
18
|
+
set.add(source);
|
|
19
|
+
else
|
|
20
|
+
toolMarkSources.set(name, new Set([source]));
|
|
21
|
+
};
|
|
15
22
|
const overPeer = (lockedPreflight.mcp ?? []).find((s) => s.name.length > TOOL_WIRE_NAME_MAX_CHARS);
|
|
16
23
|
if (overPeer !== undefined) {
|
|
17
24
|
throw Object.assign(new Error(`MCP server name ${JSON.stringify(overPeer.name.slice(0, 40) + "…")} is ${overPeer.name.length} characters; a peer rides every roster row of its tools and the roster's bound on a name is ${TOOL_WIRE_NAME_MAX_CHARS}.`), { code: "config.tool_name_too_long" });
|
|
@@ -123,10 +130,12 @@ export async function prepareProtocolTools(input) {
|
|
|
123
130
|
}, { source: "builtin", mountedBy: "optional" });
|
|
124
131
|
}
|
|
125
132
|
const foldProtocolAxes = (axes, protocolLabel) => {
|
|
133
|
+
const source = protocolLabel === "A2A" ? "a2a_default" : "mcp_annotation";
|
|
126
134
|
for (const axis of axes) {
|
|
127
135
|
if (axis.irreversibility === "always") {
|
|
128
136
|
irreversibilityTier.set(axis.name, "always");
|
|
129
137
|
irreversibleTools.add(axis.name);
|
|
138
|
+
markedBy(axis.name, source);
|
|
130
139
|
}
|
|
131
140
|
if (axis.irreversibility === "never") {
|
|
132
141
|
axisExplicitNegatives.set(axis.name, { ...axisExplicitNegatives.get(axis.name), irreversible: false });
|
|
@@ -141,9 +150,10 @@ export async function prepareProtocolTools(input) {
|
|
|
141
150
|
throw e;
|
|
142
151
|
}
|
|
143
152
|
egressTools.add(axis.name);
|
|
153
|
+
markedBy(axis.name, source);
|
|
144
154
|
}
|
|
145
|
-
if (!toolEffects.has(axis.name))
|
|
146
|
-
toolEffects.set(axis.name, axis.effect
|
|
155
|
+
if (axis.effect !== undefined && !toolEffects.has(axis.name))
|
|
156
|
+
toolEffects.set(axis.name, axis.effect);
|
|
147
157
|
}
|
|
148
158
|
};
|
|
149
159
|
foldProtocolAxes(mcp.toolAxes, "MCP");
|