@sema-agent/core 5.12.0 → 5.14.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 +320 -0
- package/dist/agents/send-message-tool.js +1 -0
- package/dist/agents/subagent.d.ts +4 -0
- package/dist/agents/subagent.js +137 -43
- package/dist/brain/anthropic.js +33 -10
- package/dist/brain/context-overflow.d.ts +20 -0
- package/dist/brain/context-overflow.js +58 -0
- package/dist/brain/open-responses.js +24 -10
- package/dist/brain/openai.js +29 -11
- package/dist/brain/request-params.d.ts +2 -0
- package/dist/brain/request-params.js +16 -0
- package/dist/brain/stream-engine.d.ts +9 -1
- package/dist/brain/stream-engine.js +256 -27
- package/dist/brain/timeout.d.ts +1 -0
- package/dist/brain/timeout.js +1 -0
- package/dist/core/a2a.d.ts +2 -2
- package/dist/core/a2a.js +3 -3
- package/dist/core/ask-question.d.ts +47 -2
- package/dist/core/ask-question.js +209 -28
- package/dist/core/background-agent-store.d.ts +2 -0
- package/dist/core/checkpoint-store.d.ts +49 -18
- package/dist/core/checkpoint-store.js +117 -4
- package/dist/core/compliance.d.ts +11 -0
- package/dist/core/compliance.js +34 -0
- package/dist/core/governance-codes.d.ts +12 -0
- package/dist/core/governance-codes.js +24 -0
- package/dist/core/hooks.d.ts +24 -2
- package/dist/core/hooks.js +97 -10
- package/dist/core/human-input-projection.d.ts +12 -0
- package/dist/core/human-input-projection.js +27 -0
- package/dist/core/locked-config.d.ts +27 -0
- package/dist/core/locked-config.js +42 -0
- package/dist/core/mcp.d.ts +7 -2
- package/dist/core/mcp.js +7 -7
- package/dist/core/memory-admission.d.ts +51 -0
- package/dist/core/memory-admission.js +159 -0
- package/dist/core/memory.d.ts +2 -0
- package/dist/core/memory.js +3 -2
- package/dist/core/retention.d.ts +36 -0
- package/dist/core/retention.js +31 -0
- package/dist/core/runner/assemble-result.d.ts +1 -0
- package/dist/core/runner/assemble-result.js +2 -2
- package/dist/core/runner/prepare-memory.d.ts +9 -0
- package/dist/core/runner/prepare-memory.js +28 -2
- package/dist/core/runner/prepare-task.d.ts +18 -6
- package/dist/core/runner/prepare-task.js +428 -38
- package/dist/core/runner/runtask.d.ts +3 -6
- package/dist/core/runner/runtask.js +258 -77
- package/dist/core/runner/tool-output-projection.js +1 -0
- package/dist/core/session-store.d.ts +4 -0
- package/dist/core/session-store.js +5 -0
- package/dist/core/session.d.ts +1 -0
- package/dist/core/store-contracts/background-agent-store-contract.js +19 -0
- package/dist/core/store-contracts/checkpoint-store-contract.js +62 -3
- package/dist/core/task-notification.d.ts +2 -0
- package/dist/core/task-notification.js +5 -3
- package/dist/core/task-registry-agent.d.ts +1 -0
- package/dist/core/task-registry-agent.js +6 -0
- package/dist/core/task-registry.d.ts +1 -0
- package/dist/core/task-registry.js +4 -1
- package/dist/core/tool-policy.d.ts +5 -0
- package/dist/core/tool-policy.js +2 -1
- package/dist/core/tool-result-store.d.ts +2 -0
- package/dist/core/tool-result-store.js +1 -0
- package/dist/core/types.d.ts +38 -2
- package/dist/core/wiring-manifest.d.ts +97 -0
- package/dist/core/wiring-manifest.js +186 -0
- package/dist/engine/compaction/compaction.js +2 -2
- package/dist/engine/harness/agent-harness.d.ts +2 -1
- package/dist/engine/harness/agent-harness.js +19 -2
- package/dist/engine/harness/types.d.ts +3 -1
- package/dist/engine/llm/types.d.ts +7 -0
- package/dist/engine/llm/types.js +8 -1
- package/dist/engine/llm/validation.js +11 -1
- package/dist/engine/session/import-validate.d.ts +6 -1
- package/dist/engine/session/import-validate.js +29 -6
- package/dist/engine/session/memory-repo.d.ts +3 -1
- package/dist/engine/session/memory-repo.js +2 -2
- package/dist/index.d.ts +12 -4
- package/dist/index.js +12 -4
- package/dist/internal/harness-types.d.ts +1 -1
- package/dist/internal/llm.d.ts +2 -2
- package/dist/internal/llm.js +1 -1
- package/dist/orchestration/run-workflow-tool.d.ts +4 -0
- package/dist/orchestration/run-workflow-tool.js +3 -0
- package/dist/orchestration/workflow-types.d.ts +8 -0
- package/dist/orchestration/workflow-types.js +14 -0
- package/dist/orchestration/workflow.d.ts +4 -0
- package/dist/orchestration/workflow.js +134 -5
- package/dist/prompts/default.js +1 -1
- package/dist/stores/file/checkpoint-store.d.ts +3 -5
- package/dist/stores/file/checkpoint-store.js +31 -2
- package/dist/stores/file/index.js +1 -1
- package/dist/stores/file/session-store.d.ts +3 -1
- package/dist/stores/file/session-store.js +2 -2
- package/dist/stores/file/shared-ledger.js +8 -1
- package/dist/tools/fs/bash-readonly-classifier.d.ts +3 -0
- package/dist/tools/fs/bash-readonly-classifier.js +94 -0
- package/dist/tools/fs/fs-bash.js +31 -12
- package/dist/tools/fs/safety.js +34 -10
- package/package.json +1 -1
|
@@ -12,6 +12,8 @@ import { primaryActivityArg } from "../arg-summary.js";
|
|
|
12
12
|
import { materializeMcpTools } from "../mcp.js";
|
|
13
13
|
import { materializeA2aTools } from "../a2a.js";
|
|
14
14
|
import { Type } from "typebox";
|
|
15
|
+
import { Value } from "typebox/value";
|
|
16
|
+
import { uuidv7 } from "../../engine/session/uuid.js";
|
|
15
17
|
import { brainToRuntime } from "../runtime.js";
|
|
16
18
|
import { StoredSession, isSessionConflict, hasSessionFork } from "../session.js";
|
|
17
19
|
import { createSubagentWorktreeHelper, forkGovernanceDenial } from "../../agents/subagent.js";
|
|
@@ -24,7 +26,7 @@ import { CHANGED_FILES_MTIME_EPS_MS, fenceMcpServerInstructions, renderAgentList
|
|
|
24
26
|
import { inlineUntrusted } from "../untrusted-text.js";
|
|
25
27
|
import { emitTrace } from "../trace.js";
|
|
26
28
|
import { createSessionRulePolicy } from "./session-rule-policy.js";
|
|
27
|
-
import { cloneObserverInput, formatHookFeedback, runToolGate } from "../hooks.js";
|
|
29
|
+
import { cloneObserverInput, createHookEnvCapabilities, formatHookFeedback, runToolGate } from "../hooks.js";
|
|
28
30
|
import { reconcileInterruptedSession } from "../session-reconcile.js";
|
|
29
31
|
import { CacheBreakDetector, toolsToFingerprintInputs } from "../cache-break-detector.js";
|
|
30
32
|
import { reservedCollisions, reservedFor } from "../../brain/request-params.js";
|
|
@@ -38,6 +40,10 @@ import { OUTPUT_TOOL_NAME, REPORT_FINDINGS_TOOL_NAME, SKILL_CONTENT_MAX_CHARS, S
|
|
|
38
40
|
import { compileOutputSchema } from "./strict-output-schema.js";
|
|
39
41
|
import { TOOL_SEARCH_NAME, buildDeferredRegistry, classifyDeferred, extractDiscoveredToolNames, createPlaceholderTool, createToolSearchTool, } from "./tool-disclosure.js";
|
|
40
42
|
import { composeMemoryBlock } from "../memory.js";
|
|
43
|
+
import { preflightLockedConfig } from "../locked-config.js";
|
|
44
|
+
import { COMPLIANCE_CAPABILITIES, WEB_FETCH_TOOL_NAME, complianceCallDenial, resolveComplianceDenies } from "../compliance.js";
|
|
45
|
+
import { assertRetentionCapability } from "../retention.js";
|
|
46
|
+
import { foldAdmissionFreeze } from "../memory-admission.js";
|
|
41
47
|
import { prepareMemory } from "./prepare-memory.js";
|
|
42
48
|
import { defaultPromptProvider, buildEnvironmentContext, buildGitSnapshot, formatLocalDate, isValidTimeZone, PROJECT_CONTEXT_FRAMING } from "../../prompts/default.js";
|
|
43
49
|
import { assemblePrompt } from "../../prompt-assembly/assemble.js";
|
|
@@ -60,7 +66,7 @@ import { createMonitorTool } from "../../tools/monitor.js";
|
|
|
60
66
|
import { createWorktreeTools } from "../../tools/worktree.js";
|
|
61
67
|
import { applyCompactionToReadFileState, bashReversibilityProbe, createHandsToolkit, isReadDedupStubResult, seedReadFileStateFromContext, seedReadFileStateFromTranscript, HAND_TOOL_EFFECTS, pdfModelCapabilitiesOf } from "../../tools/fs/index.js";
|
|
62
68
|
import { decodeTextBytes } from "../../tools/fs/encoding.js";
|
|
63
|
-
import { ASK_USER_QUESTION_TOOL_NAME, createAskUserQuestionTool } from "../ask-question.js";
|
|
69
|
+
import { ASK_USER_QUESTION_TOOL_NAME, createAskUserQuestionTool, classifyQuestionOutcome, isLiveQuestionFace, validateAskQuestions, } from "../ask-question.js";
|
|
64
70
|
import { createSchedulerTools } from "../../tools/scheduler-tools.js";
|
|
65
71
|
import { createPresentPlanTool, createEnterPlanModeTool, PRESENT_PLAN_TOOL_NAME, ENTER_PLAN_MODE_TOOL_NAME } from "../present-plan-tool.js";
|
|
66
72
|
import { isSelfOrchestrationActive, selfOrchestrationFailClosedReason } from "../../orchestration/workflow-script-runner.js";
|
|
@@ -69,8 +75,9 @@ import { resolveWorkflowSizeGuideline } from "../../orchestration/workflow-size-
|
|
|
69
75
|
import { createLspTool, gitCheckIgnoreFilter, resolveLspPath } from "../lsp.js";
|
|
70
76
|
import { resolveKey } from "../../tools/fs/safety.js";
|
|
71
77
|
import { wholeFileRecordsFromTranscript } from "./session-file-state-replay.js";
|
|
72
|
-
import { BINDING_CHECKPOINT_VERSION, mintCheckpointToken, RESOURCE_CHECKPOINT_VERSION, TOKEN_CHECKPOINT_VERSION, buildRiskDescriptor, debitLedger, remainingBudgetMicroUsd, } from "../checkpoint-store.js";
|
|
78
|
+
import { BINDING_CHECKPOINT_VERSION, mintCheckpointToken, ORG_ADMISSION_CHECKPOINT_VERSION, RESOURCE_CHECKPOINT_VERSION, TOKEN_CHECKPOINT_VERSION, buildRiskDescriptor, debitLedger, remainingBudgetMicroUsd, resolveCheckpointStore, } from "../checkpoint-store.js";
|
|
73
79
|
import { boundInputHashOf } from "../canonical-json.js";
|
|
80
|
+
import { countElicitOptIns, deriveAskEffective, deriveWiringManifest, resolveAskSeamForm, resolveDeclaredDurability, resolveElicitSeam, resolveQuestionSeam } from "../wiring-manifest.js";
|
|
74
81
|
import { GLOBAL_USAGE_KEY, resolveUsageWindows, usageRetryAfterMs } from "../usage-window-store.js";
|
|
75
82
|
const RECONCILE_MAX_RETRIES = 3;
|
|
76
83
|
const DEFAULT_MAX_SUSPENDS = 5;
|
|
@@ -173,11 +180,7 @@ export const DEFAULT_IRREVERSIBLE_SCOPE = "irreversible";
|
|
|
173
180
|
export function checkpointScopeOf(spec) {
|
|
174
181
|
return spec.durableApproval?.scope || spec.principal || DEFAULT_IRREVERSIBLE_SCOPE;
|
|
175
182
|
}
|
|
176
|
-
export
|
|
177
|
-
if (spec.checkpointStore === null)
|
|
178
|
-
return undefined;
|
|
179
|
-
return spec.checkpointStore ?? deps.checkpointStore;
|
|
180
|
-
}
|
|
183
|
+
export { resolveCheckpointStore } from "../checkpoint-store.js";
|
|
181
184
|
export function isFableFamilyModelId(id) {
|
|
182
185
|
const tail = id.toLowerCase().split("/").pop() ?? "";
|
|
183
186
|
return /^claude-fable-\d/.test(tail) || /^claude-mythos-5(?!\d)/.test(tail);
|
|
@@ -337,6 +340,64 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
337
340
|
e.code = "config.empty_objective";
|
|
338
341
|
throw e;
|
|
339
342
|
}
|
|
343
|
+
const lockedPreflight = preflightLockedConfig(spec, deps);
|
|
344
|
+
assertRetentionCapability({
|
|
345
|
+
policy: deps.retentionPolicy,
|
|
346
|
+
locked: lockedPreflight.lockedKeys.has("retentionPolicy"),
|
|
347
|
+
stores: [
|
|
348
|
+
{ name: "sessionStore", store: sessions },
|
|
349
|
+
{ name: "checkpointStore", store: resolveCheckpointStore(spec, deps) },
|
|
350
|
+
{ name: "toolResultStore", store: deps.toolResultStore },
|
|
351
|
+
],
|
|
352
|
+
});
|
|
353
|
+
const resolvedInteractionPosture = spec.interactionPosture ?? internals?.parentInteractionPosture ?? deps.interactionPosture;
|
|
354
|
+
{
|
|
355
|
+
const interactionPosture = resolvedInteractionPosture;
|
|
356
|
+
const discloseInteractionPostureRefusal = (err) => {
|
|
357
|
+
try {
|
|
358
|
+
deps.onError?.(err, { phase: "config", sessionId: spec.sessionId ?? "(pre-session)", classification: "interaction-posture-refused" });
|
|
359
|
+
}
|
|
360
|
+
catch {
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
if (interactionPosture !== undefined && interactionPosture !== "interactive" && interactionPosture !== "headless") {
|
|
364
|
+
const e = new Error(`interactionPosture ${JSON.stringify(interactionPosture)} is not a recognized posture ("interactive" | "headless") — ` +
|
|
365
|
+
`an unevaluable declaration is refused loudly, never folded to either posture.`);
|
|
366
|
+
e.code = "config.interaction_posture";
|
|
367
|
+
discloseInteractionPostureRefusal(e);
|
|
368
|
+
throw e;
|
|
369
|
+
}
|
|
370
|
+
if (interactionPosture === "interactive") {
|
|
371
|
+
const askDoor = resolveAskSeamForm(spec, deps);
|
|
372
|
+
const humanReachable = deriveAskEffective(askDoor.form, "unresolved") === "human_reachable";
|
|
373
|
+
const questionDoor = resolveQuestionSeam(spec, deps);
|
|
374
|
+
const strippedByEngine = internals?.questionFaceStripped === true;
|
|
375
|
+
if (spec.interactiveTools === false) {
|
|
376
|
+
const e = new Error(`interaction posture "interactive" declared together with interactiveTools: false — the hard-headless ` +
|
|
377
|
+
`clamp removes the AskUserQuestion mount, so no content question can ever reach the human this posture ` +
|
|
378
|
+
`promises. Drop one of the two declarations.`);
|
|
379
|
+
e.code = "config.interaction_posture";
|
|
380
|
+
discloseInteractionPostureRefusal(e);
|
|
381
|
+
throw e;
|
|
382
|
+
}
|
|
383
|
+
if (!humanReachable || !(questionDoor.wired || strippedByEngine)) {
|
|
384
|
+
const missing = [];
|
|
385
|
+
if (!humanReachable) {
|
|
386
|
+
missing.push(askDoor.form === "absent"
|
|
387
|
+
? "no onAsk approver is wired (spec.onAsk ?? deps.onAsk is absent — asks would auto-deny or park)"
|
|
388
|
+
: `the resolved onAsk seat is the blanket policy "${askDoor.form}" (${askDoor.provenance ?? "?"}) — a policy setting is not a reachable human`);
|
|
389
|
+
}
|
|
390
|
+
if (!questionDoor.wired && !strippedByEngine) {
|
|
391
|
+
missing.push("no content-question channel (spec.onQuestion ?? deps.onQuestion is absent, and this leg is not an engine-stripped background lane)");
|
|
392
|
+
}
|
|
393
|
+
const e = new Error(`interaction posture "interactive" declared, but this assembly cannot reach a human: ${missing.join("; ")}. ` +
|
|
394
|
+
`Wire the missing seam(s), or drop the posture declaration (absent = no check).`);
|
|
395
|
+
e.code = "config.interaction_posture";
|
|
396
|
+
discloseInteractionPostureRefusal(e);
|
|
397
|
+
throw e;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
340
401
|
resolveTaskLimits(spec.limits);
|
|
341
402
|
if (spec.resourceSuspend !== undefined) {
|
|
342
403
|
const rsus = spec.resourceSuspend;
|
|
@@ -378,6 +439,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
378
439
|
const egressTools = new Set();
|
|
379
440
|
const irreversibleTools = new Set();
|
|
380
441
|
const irreversibilityTier = new Map();
|
|
442
|
+
const axisExplicitNegatives = new Map();
|
|
381
443
|
const reversibilityProbes = new Map();
|
|
382
444
|
let shellGatedBash = false;
|
|
383
445
|
let shellGatedMonitor = false;
|
|
@@ -940,9 +1002,35 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
940
1002
|
? liveShellGate
|
|
941
1003
|
: seedShellGate;
|
|
942
1004
|
const inheritedParentConstraints = liveInheritedGate?.parentConstraints;
|
|
1005
|
+
const liveAdmittedOrg = liveInheritedGate?.admittedOrgScopes;
|
|
1006
|
+
const seedAdmittedOrg = seedInheritedGate?.admittedOrgScopes;
|
|
1007
|
+
const inheritedAdmittedOrgScopes = liveAdmittedOrg === undefined ? seedAdmittedOrg : seedAdmittedOrg === undefined ? liveAdmittedOrg : liveAdmittedOrg.filter((s) => seedAdmittedOrg.includes(s));
|
|
1008
|
+
const inheritedOrgGoverned = liveInheritedGate?.orgAdmissionGoverned === true || seedInheritedGate?.orgAdmissionGoverned === true;
|
|
1009
|
+
const checkpointOwnOrgVerdict = resume?.seed.inheritedGate?.ownAdmittedOrgScopes !== undefined
|
|
1010
|
+
? { scopes: resume.seed.inheritedGate.ownAdmittedOrgScopes, writeScope: resume.seed.inheritedGate.ownAdmittedOrgWriteScope ?? null }
|
|
1011
|
+
: undefined;
|
|
1012
|
+
const refOwnOrgVerdict = internals?.ownOrgAdmissionRef?.current;
|
|
1013
|
+
const priorOwnOrgVerdict = checkpointOwnOrgVerdict === undefined
|
|
1014
|
+
? refOwnOrgVerdict
|
|
1015
|
+
: refOwnOrgVerdict === undefined
|
|
1016
|
+
? checkpointOwnOrgVerdict
|
|
1017
|
+
: {
|
|
1018
|
+
scopes: checkpointOwnOrgVerdict.scopes.filter((sc) => refOwnOrgVerdict.scopes.includes(sc)),
|
|
1019
|
+
writeScope: checkpointOwnOrgVerdict.writeScope !== null && checkpointOwnOrgVerdict.writeScope === refOwnOrgVerdict.writeScope
|
|
1020
|
+
? checkpointOwnOrgVerdict.writeScope
|
|
1021
|
+
: null,
|
|
1022
|
+
};
|
|
1023
|
+
const orgGovernedProvenance = deps.memoryScopeAdmission !== undefined ||
|
|
1024
|
+
(deps.deploymentMemoryScopes !== undefined && deps.deploymentMemoryScopes.length > 0) ||
|
|
1025
|
+
deps.compliancePostureResolver !== undefined ||
|
|
1026
|
+
inheritedOrgGoverned ||
|
|
1027
|
+
priorOwnOrgVerdict !== undefined;
|
|
943
1028
|
const specShellGate = spec.shellGate ?? "off";
|
|
944
1029
|
const effectiveShellGate = inheritedShellGate !== undefined && shellGateRank[inheritedShellGate] > shellGateRank[specShellGate] ? inheritedShellGate : specShellGate;
|
|
945
1030
|
const ownSessionRulesRef = {};
|
|
1031
|
+
const memoryAdmittedOrgScopesRef = { current: [] };
|
|
1032
|
+
const ownOrgVerdictRef = { current: undefined };
|
|
1033
|
+
const orgAdmissionCheckpointState = () => inheritedAdmittedOrgScopes !== undefined || ownOrgVerdictRef.current !== undefined || orgGovernedProvenance;
|
|
946
1034
|
const frozenOnAsk = spec.onAsk ?? deps.onAsk;
|
|
947
1035
|
const frozenOnQuestion = spec.onQuestion ?? deps.onQuestion;
|
|
948
1036
|
const inheritedGateForChildren = () => {
|
|
@@ -950,7 +1038,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
950
1038
|
...(inheritedAncestorRules ?? []),
|
|
951
1039
|
...(ownSessionRulesRef.current !== undefined ? [ownSessionRulesRef.current] : []),
|
|
952
1040
|
];
|
|
953
|
-
const ownCallerPolicy =
|
|
1041
|
+
const ownCallerPolicy = lockedPreflight.toolPolicy;
|
|
954
1042
|
const durableMandate = runtimeCaps?.forceDurableGate === true || (spec.durableApproval !== undefined && frozenOnAsk === undefined);
|
|
955
1043
|
const parentConstraints = [
|
|
956
1044
|
...(inheritedParentConstraints ?? []),
|
|
@@ -968,6 +1056,8 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
968
1056
|
...(ancestorRules.length > 0 ? { ancestorRules } : {}),
|
|
969
1057
|
...(effectiveShellGate !== "off" ? { shellGate: effectiveShellGate } : {}),
|
|
970
1058
|
...(parentConstraints.length > 0 ? { parentConstraints } : {}),
|
|
1059
|
+
admittedOrgScopes: memoryAdmittedOrgScopesRef.current,
|
|
1060
|
+
...(orgGovernedProvenance ? { orgAdmissionGoverned: true } : {}),
|
|
971
1061
|
};
|
|
972
1062
|
};
|
|
973
1063
|
let agentForkDenial;
|
|
@@ -1024,6 +1114,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1024
1114
|
: {}),
|
|
1025
1115
|
sessionId,
|
|
1026
1116
|
...(spec.backgroundScope !== undefined ? { backgroundScope: spec.backgroundScope } : {}),
|
|
1117
|
+
...(resolvedInteractionPosture !== undefined ? { interactionPosture: resolvedInteractionPosture } : {}),
|
|
1027
1118
|
...(deps.onBackgroundChildEvent ? { onBackgroundChildEvent: deps.onBackgroundChildEvent } : {}),
|
|
1028
1119
|
...(internals?.onTaskNotification ? { onTaskNotification: internals.onTaskNotification } : {}),
|
|
1029
1120
|
...(forwardEvent ? { forwardEvent } : {}),
|
|
@@ -1072,6 +1163,39 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1072
1163
|
runtimeCaps = { allowWorkflows: false, allowFork: false };
|
|
1073
1164
|
}
|
|
1074
1165
|
}
|
|
1166
|
+
let complianceDenies = new Set();
|
|
1167
|
+
let complianceDegraded = false;
|
|
1168
|
+
if (deps.compliancePostureResolver) {
|
|
1169
|
+
try {
|
|
1170
|
+
const posture = (await deps.compliancePostureResolver(spec.principal)) ?? undefined;
|
|
1171
|
+
if (posture !== undefined)
|
|
1172
|
+
complianceDenies = resolveComplianceDenies(posture);
|
|
1173
|
+
}
|
|
1174
|
+
catch (err) {
|
|
1175
|
+
deps.onError?.(err instanceof Error ? err : new Error(String(err)), { phase: "config", sessionId });
|
|
1176
|
+
complianceDenies = new Set(COMPLIANCE_CAPABILITIES);
|
|
1177
|
+
complianceDegraded = true;
|
|
1178
|
+
}
|
|
1179
|
+
const complianceRefuse = (capability, requested) => {
|
|
1180
|
+
const e = new Error(`${requested} is denied for this principal by the compliance posture (capability "${capability}"` +
|
|
1181
|
+
`${complianceDegraded ? "; the posture resolver is currently failing, so every managed capability is denied fail-closed" : ""}) — ` +
|
|
1182
|
+
`the task is refused rather than silently narrowed.`);
|
|
1183
|
+
e.code = complianceDegraded ? "config.compliance_required" : "config.compliance_denied";
|
|
1184
|
+
throw e;
|
|
1185
|
+
};
|
|
1186
|
+
if (complianceDenies.has("mcp_servers") && lockedPreflight.mcp?.length) {
|
|
1187
|
+
complianceRefuse("mcp_servers", "TaskSpec.mcp (MCP server materialization)");
|
|
1188
|
+
}
|
|
1189
|
+
if (complianceDenies.has("workflows") && spec.selfOrchestration === true) {
|
|
1190
|
+
complianceRefuse("workflows", "TaskSpec.selfOrchestration (workflow self-orchestration)");
|
|
1191
|
+
}
|
|
1192
|
+
if (complianceDenies.has("web_fetch")) {
|
|
1193
|
+
const webTool = (spec.tools ?? []).find((t) => t.name === WEB_FETCH_TOOL_NAME || (t.aliases ?? []).includes(WEB_FETCH_TOOL_NAME));
|
|
1194
|
+
if (webTool !== undefined) {
|
|
1195
|
+
complianceRefuse("web_fetch", `TaskSpec.tools["${webTool.name}"] (the WebFetch tool face)`);
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1075
1199
|
agentForkDenial = forkGovernanceDenial(spec.enableFork, runtimeCaps?.allowFork);
|
|
1076
1200
|
observersActive = runtimeCaps?.allowObservers === true;
|
|
1077
1201
|
if (runtimeCaps?.autoMode === true && deps.autoMode !== undefined) {
|
|
@@ -1144,6 +1268,8 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1144
1268
|
...(spec.getApiKeyAndHeaders !== undefined ? { parentGetApiKeyAndHeaders: spec.getApiKeyAndHeaders } : {}),
|
|
1145
1269
|
principal: spec.principal,
|
|
1146
1270
|
oneShot: spec.oneShot,
|
|
1271
|
+
...(resolvedInteractionPosture !== undefined ? { parentInteractionPosture: resolvedInteractionPosture } : {}),
|
|
1272
|
+
autoModeReview: () => (autoModeDecider !== undefined ? { decider: autoModeDecider } : undefined),
|
|
1147
1273
|
workflowDepth: internals?.workflowDepth,
|
|
1148
1274
|
parentCwd: taskRootPath,
|
|
1149
1275
|
parentThinking: () => harnessRef.current?.getThinkingLevel() ?? thinking,
|
|
@@ -1220,8 +1346,8 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1220
1346
|
}
|
|
1221
1347
|
tools.push(createOutputTool(outputRef, spec.outputSchema, compiled.strict ? compiled.modelSchema : undefined));
|
|
1222
1348
|
}
|
|
1223
|
-
mcp =
|
|
1224
|
-
? await materializeMcpTools(
|
|
1349
|
+
mcp = lockedPreflight.mcp?.length
|
|
1350
|
+
? await materializeMcpTools(lockedPreflight.mcp, spec.principal, deps.onElicit, deps.mcpImageResizer)
|
|
1225
1351
|
: { tools: [], toolAxes: [], warnings: [], serverInstructions: [], instructionsDelta: { pendingAdds: [], pendingRemovals: [] }, droppedTools: [], statuses: [], refresh: async () => [], dispose: async () => { } };
|
|
1226
1352
|
for (const w of mcp.warnings)
|
|
1227
1353
|
deps.onError?.(w, { phase: "mcp", sessionId });
|
|
@@ -1241,7 +1367,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1241
1367
|
tools.push(...mcp.tools.map((t) => remoteToolOffload(t)));
|
|
1242
1368
|
const rebuildHarnessToolsRef = {};
|
|
1243
1369
|
const toolCallGateArmedRef = { armed: false };
|
|
1244
|
-
if (
|
|
1370
|
+
if (lockedPreflight.mcp?.length) {
|
|
1245
1371
|
tools.push({
|
|
1246
1372
|
name: "RefreshMcpTools",
|
|
1247
1373
|
label: "RefreshMcpTools",
|
|
@@ -1316,6 +1442,12 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1316
1442
|
irreversibilityTier.set(axis.name, "always");
|
|
1317
1443
|
irreversibleTools.add(axis.name);
|
|
1318
1444
|
}
|
|
1445
|
+
if (axis.irreversibility === "never") {
|
|
1446
|
+
axisExplicitNegatives.set(axis.name, { ...axisExplicitNegatives.get(axis.name), irreversible: false });
|
|
1447
|
+
}
|
|
1448
|
+
if (axis.egress === false) {
|
|
1449
|
+
axisExplicitNegatives.set(axis.name, { ...axisExplicitNegatives.get(axis.name), egress: false });
|
|
1450
|
+
}
|
|
1319
1451
|
if (axis.egress) {
|
|
1320
1452
|
if (axis.effect !== undefined && axis.effect !== "write") {
|
|
1321
1453
|
const e = new Error(`${protocolLabel} tool "${axis.name}" resolves to egress:true with effect:"${axis.effect}" — an egress tool (external write) must have effect:"write". Clear egress (toolAxes egress:false) if it is a pure read, or set effect:"write".`);
|
|
@@ -1471,6 +1603,11 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1471
1603
|
}
|
|
1472
1604
|
tools.push(...band.map((t) => firstPartyOffload(t)));
|
|
1473
1605
|
const shellGate = effectiveShellGate;
|
|
1606
|
+
if (shellGate === "off" && !(executionEnv instanceof StubExecutionEnv) && spec.handsReadOnly !== true) {
|
|
1607
|
+
deps.onError?.(new Error(`shell gate doctrine is "off" while a real writable shell (Bash) is mounted — no shell safety-axis ` +
|
|
1608
|
+
`fold applies to this run (commands are adjudicated by the ordinary policy/hook chain only). ` +
|
|
1609
|
+
`Set spec.shellGate to "classify" or "always" if this deployment expects doctrine-gated shell behavior.`), { phase: "config", sessionId, classification: "shell-gate-off" });
|
|
1610
|
+
}
|
|
1474
1611
|
if (shellGate !== "off" && !(executionEnv instanceof StubExecutionEnv) && spec.handsReadOnly !== true) {
|
|
1475
1612
|
shellGatedBash = !egressTools.has("Bash") && !irreversibilityTier.has("Bash");
|
|
1476
1613
|
irreversibilityTier.set("Bash", shellGate === "always" ? "always" : "maybe");
|
|
@@ -1591,10 +1728,79 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1591
1728
|
if (offloadStore)
|
|
1592
1729
|
tools.push(createReadToolResultTool(offloadStore));
|
|
1593
1730
|
const onQuestion = frozenOnQuestion;
|
|
1731
|
+
const liveQuestionFace = isLiveQuestionFace(onQuestion) ? onQuestion : undefined;
|
|
1732
|
+
const contentAskBindings = new Map();
|
|
1733
|
+
const CONTENT_ASK_BINDING_CAP = 32;
|
|
1734
|
+
const contentAskRoutable = (toolCallId) => liveQuestionFace !== undefined &&
|
|
1735
|
+
mountedQuestionTool !== undefined &&
|
|
1736
|
+
tools.includes(mountedQuestionTool) &&
|
|
1737
|
+
runtimeCaps?.forceDurableGate !== true &&
|
|
1738
|
+
!inheritedUnavailableAsks.has(toolCallId);
|
|
1739
|
+
const lateStrandedAnswers = [];
|
|
1740
|
+
const discloseStrandedAnswers = (records, why) => {
|
|
1741
|
+
if (records.length === 0)
|
|
1742
|
+
return;
|
|
1743
|
+
try {
|
|
1744
|
+
deps.onError?.(new Error(`AskUserQuestion: ${records.length} question(s) were answered by a person but the call never ` +
|
|
1745
|
+
`executed to collect the answer (${records.map((r) => `${r.toolCallId} [delivery ${r.deliveryId}]`).join(", ")}) — ${why}. The answer(s) were NOT ` +
|
|
1746
|
+
`delivered to the model and are gone with this leg; re-ask if the decision is still needed.`), { phase: "degraded", sessionId, classification: "unconsumed-human-answer" });
|
|
1747
|
+
}
|
|
1748
|
+
catch {
|
|
1749
|
+
}
|
|
1750
|
+
};
|
|
1751
|
+
const settleContentAskBindings = () => {
|
|
1752
|
+
const stranded = [];
|
|
1753
|
+
for (const [callId, bound] of contentAskBindings) {
|
|
1754
|
+
if (bound.kind === "answered")
|
|
1755
|
+
stranded.push({ deliveryId: bound.deliveryId, toolCallId: callId });
|
|
1756
|
+
}
|
|
1757
|
+
contentAskBindings.clear();
|
|
1758
|
+
discloseStrandedAnswers(stranded, "the leg ended first (abort, batch teardown, or a loop failure)");
|
|
1759
|
+
const byDelivery = new Map();
|
|
1760
|
+
for (const r of [...stranded, ...lateStrandedAnswers])
|
|
1761
|
+
byDelivery.set(r.deliveryId, r);
|
|
1762
|
+
return [...byDelivery.values()];
|
|
1763
|
+
};
|
|
1594
1764
|
const durableQuestionFace = resolveCheckpointStore(spec, deps) !== undefined &&
|
|
1595
1765
|
(spec.durableApproval !== undefined || runtimeCaps?.forceDurableGate === true);
|
|
1596
|
-
|
|
1597
|
-
|
|
1766
|
+
const mountedQuestionFace = liveQuestionFace !== undefined
|
|
1767
|
+
? async (req, signal) => {
|
|
1768
|
+
const bound = contentAskBindings.get(req.toolCallId);
|
|
1769
|
+
if (bound !== undefined) {
|
|
1770
|
+
if (bound.questionsHash === boundInputHashOf(req.questions)) {
|
|
1771
|
+
contentAskBindings.delete(req.toolCallId);
|
|
1772
|
+
if (bound.kind === "answered")
|
|
1773
|
+
return bound.answer;
|
|
1774
|
+
throw bound.error;
|
|
1775
|
+
}
|
|
1776
|
+
contentAskBindings.delete(req.toolCallId);
|
|
1777
|
+
}
|
|
1778
|
+
return liveQuestionFace(req, signal);
|
|
1779
|
+
}
|
|
1780
|
+
: onQuestion;
|
|
1781
|
+
const questionToolMounted = spec.interactiveTools === true || (spec.interactiveTools !== false && (onQuestion !== undefined || durableQuestionFace));
|
|
1782
|
+
let mountedQuestionTool;
|
|
1783
|
+
if (questionToolMounted)
|
|
1784
|
+
tools.push((mountedQuestionTool =
|
|
1785
|
+
createAskUserQuestionTool(mountedQuestionFace, { principal: spec.principal, sourceTaskId: sessionId }, {
|
|
1786
|
+
...(resume?.redeemedContentAskCallId !== undefined
|
|
1787
|
+
? {
|
|
1788
|
+
redeemedApprovalCallId: resume.redeemedContentAskCallId,
|
|
1789
|
+
...(resume.redeemedContentAskQuestionsHash !== undefined ? { redeemedApprovalQuestionsHash: resume.redeemedContentAskQuestionsHash } : {}),
|
|
1790
|
+
}
|
|
1791
|
+
: {}),
|
|
1792
|
+
...(resolvedInteractionPosture !== undefined ? { posture: resolvedInteractionPosture } : {}),
|
|
1793
|
+
...(spec.interactiveQuestionFallback === true ? { interactiveFallback: true } : {}),
|
|
1794
|
+
onSyntheticContinuation: ({ questionId, reason }) => {
|
|
1795
|
+
deps.onError?.(new Error(`AskUserQuestion ${questionId}: no human answer was obtainable (` +
|
|
1796
|
+
(reason === "seam_absent"
|
|
1797
|
+
? "no onQuestion seam is wired"
|
|
1798
|
+
: reason === "declined_unavailable"
|
|
1799
|
+
? "the wired question channel reported nobody was reachable"
|
|
1800
|
+
: "the wired question channel failed") +
|
|
1801
|
+
`) — the model was instructed to self-answer and the run CONTINUES (warning, not a failure).`), { phase: "degraded", sessionId, classification: "no-human-autoanswered" });
|
|
1802
|
+
},
|
|
1803
|
+
})));
|
|
1598
1804
|
if (spec.handsReadOnly !== true) {
|
|
1599
1805
|
const sessionScope = sessionId ?? spec.principal ?? spec.taskId ?? "default";
|
|
1600
1806
|
tools.push(...createSchedulerTools(executionEnv, {
|
|
@@ -1632,7 +1838,34 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1632
1838
|
.catch(() => undefined);
|
|
1633
1839
|
}
|
|
1634
1840
|
: undefined;
|
|
1635
|
-
const { memoryEngineSession, memoryBlock: memoryBlockFromEngine, seedFiles: memorySeedFiles } = await prepareMemory({
|
|
1841
|
+
const { memoryEngineSession, memoryBlock: memoryBlockFromEngine, seedFiles: memorySeedFiles, admittedOrgScopes: memoryAdmittedOrgScopes, ownOrgVerdict: memoryOwnOrgVerdict, } = await prepareMemory({
|
|
1842
|
+
spec,
|
|
1843
|
+
deps,
|
|
1844
|
+
sessionId,
|
|
1845
|
+
taskRootPath,
|
|
1846
|
+
memoryWriteGateRef,
|
|
1847
|
+
admissionCtx: {
|
|
1848
|
+
orgMemoryDenied: complianceDenies.has("org_memory_mount"),
|
|
1849
|
+
complianceDegraded,
|
|
1850
|
+
parentAdmittedOrgScopes: foldAdmissionFreeze({
|
|
1851
|
+
delegated: internals?.isDelegatedChild === true ||
|
|
1852
|
+
internals?.inheritedGate !== undefined ||
|
|
1853
|
+
(resume?.seed.inheritedGate !== undefined &&
|
|
1854
|
+
(resume.seed.inheritedGate.ancestorRules !== undefined ||
|
|
1855
|
+
resume.seed.inheritedGate.shellGate !== undefined ||
|
|
1856
|
+
resume.seed.inheritedGate.admittedOrgScopes !== undefined ||
|
|
1857
|
+
resume.seed.inheritedGate.requiresParentConstraint)),
|
|
1858
|
+
inherited: inheritedAdmittedOrgScopes,
|
|
1859
|
+
}),
|
|
1860
|
+
priorOwnVerdict: priorOwnOrgVerdict,
|
|
1861
|
+
governedProvenance: orgGovernedProvenance,
|
|
1862
|
+
},
|
|
1863
|
+
});
|
|
1864
|
+
memoryAdmittedOrgScopesRef.current = memoryAdmittedOrgScopes;
|
|
1865
|
+
ownOrgVerdictRef.current = memoryOwnOrgVerdict ?? priorOwnOrgVerdict;
|
|
1866
|
+
if (internals?.ownOrgAdmissionRef !== undefined && ownOrgVerdictRef.current !== undefined) {
|
|
1867
|
+
internals.ownOrgAdmissionRef.current = ownOrgVerdictRef.current;
|
|
1868
|
+
}
|
|
1636
1869
|
let memoryBlock = memoryBlockFromEngine;
|
|
1637
1870
|
if (memorySeedFiles?.length && seedContextFiles) {
|
|
1638
1871
|
try {
|
|
@@ -1737,7 +1970,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1737
1970
|
{ entries: [], seedAnnounced: true }
|
|
1738
1971
|
: undefined;
|
|
1739
1972
|
const provider = spec.promptProvider ?? deps.promptProvider ?? defaultPromptProvider;
|
|
1740
|
-
const promptPolicyEnabled = Boolean(
|
|
1973
|
+
const promptPolicyEnabled = Boolean(lockedPreflight.toolPolicy);
|
|
1741
1974
|
const promptHooks = spec.hooks ?? deps.hooks;
|
|
1742
1975
|
const promptHooksEnabled = Boolean(promptHooks?.preToolUse || promptHooks?.postToolUse);
|
|
1743
1976
|
const failClosedReason = selfOrchestrationFailClosedReason(spec, deps);
|
|
@@ -2029,6 +2262,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2029
2262
|
model,
|
|
2030
2263
|
deferNames: (toolFaceSnapshot.defer ?? []).filter((n) => tools.some((t) => t.name === n)),
|
|
2031
2264
|
alwaysLoadNames: [
|
|
2265
|
+
ASK_USER_QUESTION_TOOL_NAME,
|
|
2032
2266
|
...(toolFaceSnapshot.alwaysLoad ?? []),
|
|
2033
2267
|
...mcp.tools
|
|
2034
2268
|
.filter((t) => t.mcpAlwaysLoad === true && !(toolFaceSnapshot.defer ?? []).includes(t.name))
|
|
@@ -2328,7 +2562,6 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2328
2562
|
}));
|
|
2329
2563
|
},
|
|
2330
2564
|
...(spec.streamingToolExecution === true ? { streamingToolExecution: true } : {}),
|
|
2331
|
-
followUpMode: "all",
|
|
2332
2565
|
env: executionEnv,
|
|
2333
2566
|
session,
|
|
2334
2567
|
tools: harnessTools,
|
|
@@ -2368,7 +2601,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2368
2601
|
releaseSignal = () => sig.removeEventListener("abort", onExternalAbort);
|
|
2369
2602
|
}
|
|
2370
2603
|
}
|
|
2371
|
-
const policy =
|
|
2604
|
+
const policy = lockedPreflight.toolPolicy;
|
|
2372
2605
|
const auditPolicyNames = (auditee) => {
|
|
2373
2606
|
const nameGroups = toolPolicyNameSets(auditee);
|
|
2374
2607
|
if (nameGroups.length > 0) {
|
|
@@ -2456,7 +2689,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2456
2689
|
for (const layer of narrowingLayers)
|
|
2457
2690
|
auditPolicyNames(layer);
|
|
2458
2691
|
const denyNarrowingPolicy = narrowingLayers.length === 0 ? undefined : narrowingLayers.length === 1 ? narrowingLayers[0] : combinePolicies(...narrowingLayers);
|
|
2459
|
-
const basePolicyForResumeEdit =
|
|
2692
|
+
const basePolicyForResumeEdit = lockedPreflight.toolPolicy;
|
|
2460
2693
|
const sameInstanceAncestorCount = policy === undefined ? 0 : (inheritedParentConstraints ?? []).reduce((n, pc) => (pc.policy === policy ? n + 1 : n), 0);
|
|
2461
2694
|
const sharedFirstDecision = new Map();
|
|
2462
2695
|
const SHARED_FIRST_DECISION_CAP = 256;
|
|
@@ -2511,6 +2744,15 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2511
2744
|
? { sourceAgentName: internals?.explicitAgentName ?? internals?.agentName }
|
|
2512
2745
|
: {}),
|
|
2513
2746
|
});
|
|
2747
|
+
const riskAxesOf = (toolName) => {
|
|
2748
|
+
const tier = irreversibilityTier.get(toolName);
|
|
2749
|
+
const negatives = axisExplicitNegatives.get(toolName);
|
|
2750
|
+
const irreversible = tier === "always" || tier === "maybe" ? true : tier === "never" ? false : negatives?.irreversible;
|
|
2751
|
+
const egress = egressTools.has(toolName) ? true : negatives?.egress;
|
|
2752
|
+
if (irreversible === undefined && egress === undefined)
|
|
2753
|
+
return {};
|
|
2754
|
+
return { riskAxes: { ...(irreversible !== undefined ? { irreversible } : {}), ...(egress !== undefined ? { egress } : {}) } };
|
|
2755
|
+
};
|
|
2514
2756
|
const recheckApprovedEdit = async (pol, onAskOf, creq, edit, csignal) => {
|
|
2515
2757
|
let editArgs = edit;
|
|
2516
2758
|
for (let round = 0;; round++) {
|
|
@@ -2543,6 +2785,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2543
2785
|
args: editArgs,
|
|
2544
2786
|
message: re.message ?? `approval required for "${creq.toolName}" (inherited parent policy)`,
|
|
2545
2787
|
...askSourceIdentity(),
|
|
2788
|
+
...riskAxesOf(creq.toolName),
|
|
2546
2789
|
...(re.requiresRealApproval === true ? { requiresRealApproval: true } : {}),
|
|
2547
2790
|
}, onAskOf, csignal ?? abortController.signal);
|
|
2548
2791
|
if (rr.action !== "allow")
|
|
@@ -2567,8 +2810,9 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2567
2810
|
return first;
|
|
2568
2811
|
if (first.action === "allow")
|
|
2569
2812
|
return { action: "allow" };
|
|
2570
|
-
if (creq.toolName === ASK_USER_QUESTION_TOOL_NAME)
|
|
2813
|
+
if (creq.toolName === ASK_USER_QUESTION_TOOL_NAME && (pc.durableMandate !== true || markInheritedUnavailable(creq.toolCallId))) {
|
|
2571
2814
|
return first;
|
|
2815
|
+
}
|
|
2572
2816
|
if (pc.durableMandate === true) {
|
|
2573
2817
|
if (resolveCheckpointStore(spec, deps) !== undefined &&
|
|
2574
2818
|
(spec.durableApproval !== undefined || runtimeCaps?.forceDurableGate === true) &&
|
|
@@ -2589,6 +2833,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2589
2833
|
args: presentedArgs,
|
|
2590
2834
|
message: first.message ?? `approval required for "${creq.toolName}" (inherited parent policy)`,
|
|
2591
2835
|
...askSourceIdentity(),
|
|
2836
|
+
...riskAxesOf(creq.toolName),
|
|
2592
2837
|
...(first.action === "ask" && first.requiresRealApproval === true ? { requiresRealApproval: true } : {}),
|
|
2593
2838
|
}, pc.onAsk, csignal ?? abortController.signal);
|
|
2594
2839
|
const askWaitMs = Math.max(0, now() - askT0);
|
|
@@ -2623,8 +2868,9 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2623
2868
|
}
|
|
2624
2869
|
if (decision.action !== "ask")
|
|
2625
2870
|
return decision;
|
|
2626
|
-
if (creq.toolName === ASK_USER_QUESTION_TOOL_NAME)
|
|
2871
|
+
if (creq.toolName === ASK_USER_QUESTION_TOOL_NAME && (pc.durableMandate !== true || markInheritedUnavailable(creq.toolCallId))) {
|
|
2627
2872
|
return decision;
|
|
2873
|
+
}
|
|
2628
2874
|
if (pc.durableMandate === true) {
|
|
2629
2875
|
if (resolveCheckpointStore(spec, deps) !== undefined &&
|
|
2630
2876
|
(spec.durableApproval !== undefined || runtimeCaps?.forceDurableGate === true) &&
|
|
@@ -2645,6 +2891,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2645
2891
|
args: presentedArgs,
|
|
2646
2892
|
message: decision.message ?? `approval required for "${creq.toolName}" (inherited parent policy)`,
|
|
2647
2893
|
...askSourceIdentity(),
|
|
2894
|
+
...riskAxesOf(creq.toolName),
|
|
2648
2895
|
...(decision.action === "ask" && decision.requiresRealApproval === true ? { requiresRealApproval: true } : {}),
|
|
2649
2896
|
}, pc.onAsk, csignal ?? abortController.signal);
|
|
2650
2897
|
const askWaitMs = Math.max(0, now() - askT0);
|
|
@@ -2830,6 +3077,42 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2830
3077
|
};
|
|
2831
3078
|
})();
|
|
2832
3079
|
const platformSuspendArmed = durableSuspendInfraReady && (envLifetimeSuspendAt !== undefined || usageGovernance !== undefined);
|
|
3080
|
+
const checkpointStore = resolveCheckpointStore(spec, deps);
|
|
3081
|
+
const durableApproval = spec.durableApproval ??
|
|
3082
|
+
(runtimeCaps?.forceDurableGate ? { scope: spec.principal || DEFAULT_IRREVERSIBLE_SCOPE } : undefined);
|
|
3083
|
+
const wiringQuestionSeam = resolveQuestionSeam(spec, deps);
|
|
3084
|
+
const wiringQuestionStripped = internals?.questionFaceStripped === true;
|
|
3085
|
+
const wiringAskSeam = resolveAskSeamForm(spec, deps);
|
|
3086
|
+
const wiringManifest = deriveWiringManifest({
|
|
3087
|
+
half: "effective",
|
|
3088
|
+
leg: resume !== undefined ? "resume" : internals?.isDelegatedChild === true ? "child" : "root",
|
|
3089
|
+
askForm: wiringAskSeam.form,
|
|
3090
|
+
...(wiringAskSeam.provenance !== undefined ? { askProvenance: wiringAskSeam.provenance } : {}),
|
|
3091
|
+
questionWired: wiringQuestionSeam.wired,
|
|
3092
|
+
...(wiringQuestionSeam.provenance !== undefined ? { questionProvenance: wiringQuestionSeam.provenance } : {}),
|
|
3093
|
+
...(wiringQuestionStripped ? { questionStrippedByEngine: true } : {}),
|
|
3094
|
+
...(resolvedInteractionPosture !== undefined ? { interactionPosture: resolvedInteractionPosture } : {}),
|
|
3095
|
+
...(spec.interactiveTools === true && !wiringQuestionSeam.wired && !durableQuestionFace && !wiringQuestionStripped
|
|
3096
|
+
? { interactiveToolsWithoutDeliveryFace: true }
|
|
3097
|
+
: {}),
|
|
3098
|
+
elicitSeamWired: resolveElicitSeam(deps),
|
|
3099
|
+
elicitServersOptedIn: countElicitOptIns(spec),
|
|
3100
|
+
parkCapable: checkpointStore !== undefined,
|
|
3101
|
+
parkDurableApprovalOptIn: spec.durableApproval !== undefined,
|
|
3102
|
+
parkForceDurableGate: runtimeCaps?.forceDurableGate === true,
|
|
3103
|
+
parkSafetyVocabularyArmed: irreversibleTools.size > 0 || egressTools.size > 0,
|
|
3104
|
+
...(checkpointStore !== undefined ? { checkpointDurability: resolveDeclaredDurability(checkpointStore, "checkpointStore") } : {}),
|
|
3105
|
+
sessionDurability: resolveDeclaredDurability(sessions, "sessionStore"),
|
|
3106
|
+
backgroundAgentStoreWired: deps.backgroundAgentStore !== undefined,
|
|
3107
|
+
hostChildEventSinkWired: deps.onBackgroundChildEvent !== undefined,
|
|
3108
|
+
lockedConfigWired: deps.lockedConfig !== undefined,
|
|
3109
|
+
complianceWired: deps.compliancePostureResolver !== undefined,
|
|
3110
|
+
memoryAdmissionWired: deps.memoryScopeAdmission !== undefined,
|
|
3111
|
+
retentionPolicyWired: deps.retentionPolicy !== undefined,
|
|
3112
|
+
});
|
|
3113
|
+
const parkLaneArmed = wiringManifest.parkLane.effective === true;
|
|
3114
|
+
const hookContextConsumerWired = hooks?.preToolUse !== undefined || hooks?.postToolUse !== undefined || hooks?.postToolUseFailure !== undefined;
|
|
3115
|
+
const hookEnvFace = hookContextConsumerWired && (ownedEnv ?? deps.executionEnv) != null ? createHookEnvCapabilities(executionEnv) : undefined;
|
|
2833
3116
|
if (effectivePolicy || hooks?.preToolUse || egressTools.size > 0 || irreversibleTools.size > 0 || resourceSuspendEligible || platformSuspendArmed || spec.enablePlanMode === true) {
|
|
2834
3117
|
const adjudicate = effectivePolicy
|
|
2835
3118
|
? (req) => raceAbort(Promise.resolve(effectivePolicy.check({ ...req, budget: budgetSnapshot }, abortController.signal)), abortController.signal, () => ({
|
|
@@ -2911,6 +3194,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2911
3194
|
})(),
|
|
2912
3195
|
message: decision.message ?? `approval required for "${req.toolName}"`,
|
|
2913
3196
|
...askSourceIdentity(),
|
|
3197
|
+
...riskAxesOf(req.toolName),
|
|
2914
3198
|
...(decision.action === "ask" && decision.requiresRealApproval === true ? { requiresRealApproval: true } : {}),
|
|
2915
3199
|
}, onAsk, abortController.signal);
|
|
2916
3200
|
const waitMs = Math.max(0, now() - t0);
|
|
@@ -2950,9 +3234,6 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2950
3234
|
catch {
|
|
2951
3235
|
}
|
|
2952
3236
|
};
|
|
2953
|
-
const checkpointStore = resolveCheckpointStore(spec, deps);
|
|
2954
|
-
const durableApproval = spec.durableApproval ??
|
|
2955
|
-
(runtimeCaps?.forceDurableGate ? { scope: spec.principal || DEFAULT_IRREVERSIBLE_SCOPE } : undefined);
|
|
2956
3237
|
const inFlightSpendMicroUsd = () => {
|
|
2957
3238
|
const own = liveSpendRef.get?.().costMicroUsd ?? 0;
|
|
2958
3239
|
const seededNested = resume?.seed.nestedStats.costMicroUsd;
|
|
@@ -2991,13 +3272,24 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2991
3272
|
return live.length > 0 ? live : undefined;
|
|
2992
3273
|
})(),
|
|
2993
3274
|
pendingSteer: undefined,
|
|
3275
|
+
pendingSteerQueue: undefined,
|
|
2994
3276
|
inheritedGate: (() => {
|
|
2995
3277
|
const requiresParentConstraint = (inheritedParentConstraints?.length ?? 0) > 0 || seedInheritedGate?.requiresParentConstraint === true;
|
|
2996
3278
|
const parentConstraintCount = (inheritedParentConstraints?.length ?? 0) > 0 ? inheritedParentConstraints.length : seedInheritedGate?.parentConstraintCount;
|
|
2997
|
-
return inheritedAncestorRules !== undefined ||
|
|
3279
|
+
return inheritedAncestorRules !== undefined ||
|
|
3280
|
+
inheritedShellGate !== undefined ||
|
|
3281
|
+
inheritedAdmittedOrgScopes !== undefined ||
|
|
3282
|
+
ownOrgVerdictRef.current !== undefined ||
|
|
3283
|
+
orgGovernedProvenance ||
|
|
3284
|
+
requiresParentConstraint
|
|
2998
3285
|
? {
|
|
2999
3286
|
...(inheritedAncestorRules !== undefined ? { ancestorRules: structuredClone(inheritedAncestorRules) } : {}),
|
|
3000
3287
|
...(inheritedShellGate !== undefined ? { shellGate: inheritedShellGate } : {}),
|
|
3288
|
+
...(inheritedAdmittedOrgScopes !== undefined ? { admittedOrgScopes: [...inheritedAdmittedOrgScopes] } : {}),
|
|
3289
|
+
...(ownOrgVerdictRef.current !== undefined
|
|
3290
|
+
? { ownAdmittedOrgScopes: [...ownOrgVerdictRef.current.scopes], ownAdmittedOrgWriteScope: ownOrgVerdictRef.current.writeScope }
|
|
3291
|
+
: {}),
|
|
3292
|
+
...(orgGovernedProvenance ? { orgAdmissionGoverned: true } : {}),
|
|
3001
3293
|
requiresParentConstraint,
|
|
3002
3294
|
...(requiresParentConstraint && parentConstraintCount !== undefined ? { parentConstraintCount } : {}),
|
|
3003
3295
|
}
|
|
@@ -3112,7 +3404,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3112
3404
|
const mintedAt = Date.now();
|
|
3113
3405
|
const cp = {
|
|
3114
3406
|
token,
|
|
3115
|
-
version: resourceLedgerOut.totalTokens !== undefined ? TOKEN_CHECKPOINT_VERSION : RESOURCE_CHECKPOINT_VERSION,
|
|
3407
|
+
version: orgAdmissionCheckpointState() ? ORG_ADMISSION_CHECKPOINT_VERSION : resourceLedgerOut.totalTokens !== undefined ? TOKEN_CHECKPOINT_VERSION : RESOURCE_CHECKPOINT_VERSION,
|
|
3116
3408
|
scope,
|
|
3117
3409
|
sessionId,
|
|
3118
3410
|
leafId,
|
|
@@ -3194,7 +3486,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3194
3486
|
const mintedAt = Date.now();
|
|
3195
3487
|
const cp = {
|
|
3196
3488
|
token,
|
|
3197
|
-
version: reviewLedger.totalTokens !== undefined ? TOKEN_CHECKPOINT_VERSION : BINDING_CHECKPOINT_VERSION,
|
|
3489
|
+
version: orgAdmissionCheckpointState() ? ORG_ADMISSION_CHECKPOINT_VERSION : reviewLedger.totalTokens !== undefined ? TOKEN_CHECKPOINT_VERSION : BINDING_CHECKPOINT_VERSION,
|
|
3198
3490
|
scope,
|
|
3199
3491
|
sessionId,
|
|
3200
3492
|
leafId,
|
|
@@ -3228,13 +3520,92 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3228
3520
|
return true;
|
|
3229
3521
|
}
|
|
3230
3522
|
: undefined;
|
|
3231
|
-
const
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3523
|
+
const resolveContentAsk = async (req) => {
|
|
3524
|
+
if (!contentAskRoutable(req.toolCallId) || liveQuestionFace === undefined || mountedQuestionTool === undefined) {
|
|
3525
|
+
return { kind: "unavailable", parkDeclined: false };
|
|
3526
|
+
}
|
|
3527
|
+
const deliveryId = uuidv7();
|
|
3528
|
+
const bindOutcome = (entry, questionsHash) => {
|
|
3529
|
+
if (contentAskBindings.size >= CONTENT_ASK_BINDING_CAP && !contentAskBindings.has(req.toolCallId))
|
|
3530
|
+
return;
|
|
3531
|
+
contentAskBindings.set(req.toolCallId, { ...entry, questionsHash, deliveryId });
|
|
3532
|
+
};
|
|
3533
|
+
const refuseBeforeDelivery = (code, presentedInput) => ({
|
|
3534
|
+
kind: "delivery_failure",
|
|
3535
|
+
code,
|
|
3536
|
+
...(presentedInput !== undefined ? { presentedInput } : {}),
|
|
3537
|
+
});
|
|
3538
|
+
let retained;
|
|
3539
|
+
let presented;
|
|
3540
|
+
try {
|
|
3541
|
+
retained = structuredClone(req.args);
|
|
3542
|
+
presented = structuredClone(retained.questions);
|
|
3543
|
+
}
|
|
3544
|
+
catch {
|
|
3545
|
+
return refuseBeforeDelivery("question.malformed_request");
|
|
3546
|
+
}
|
|
3547
|
+
const retainedQuestionsHash = boundInputHashOf(retained.questions);
|
|
3548
|
+
if (!Value.Check(mountedQuestionTool.parameters, retained) || validateAskQuestions(presented) !== undefined) {
|
|
3549
|
+
return refuseBeforeDelivery("question.malformed_request", retained);
|
|
3550
|
+
}
|
|
3551
|
+
if (contentAskBindings.size >= CONTENT_ASK_BINDING_CAP && !contentAskBindings.has(req.toolCallId)) {
|
|
3552
|
+
return { kind: "unavailable", parkDeclined: true };
|
|
3553
|
+
}
|
|
3554
|
+
if (abortController.signal.aborted) {
|
|
3555
|
+
return { kind: "delivery_failure", code: "question.aborted", presentedInput: retained };
|
|
3556
|
+
}
|
|
3557
|
+
try {
|
|
3558
|
+
const facePromise = (async () => liveQuestionFace({
|
|
3559
|
+
toolCallId: req.toolCallId,
|
|
3560
|
+
questions: presented,
|
|
3561
|
+
...(spec.principal !== undefined ? { principal: spec.principal } : {}),
|
|
3562
|
+
sourceTaskId: sessionId,
|
|
3563
|
+
boundInputHash: boundInputHashOf(retained),
|
|
3564
|
+
deliveryId,
|
|
3565
|
+
}, abortController.signal))();
|
|
3566
|
+
const settlement = await raceAbort(facePromise.then((outcome) => ({ tag: "outcome", outcome }), (error) => ({ tag: "threw", error })), abortController.signal, () => ({ tag: "aborted" }));
|
|
3567
|
+
if (settlement.tag === "aborted") {
|
|
3568
|
+
void facePromise.then((late) => {
|
|
3569
|
+
if (classifyQuestionOutcome(late).shape !== "answered")
|
|
3570
|
+
return;
|
|
3571
|
+
lateStrandedAnswers.push({ deliveryId, toolCallId: req.toolCallId });
|
|
3572
|
+
discloseStrandedAnswers([{ deliveryId, toolCallId: req.toolCallId }], "the task had already ended when the answer arrived");
|
|
3573
|
+
}, () => undefined).catch(() => undefined);
|
|
3574
|
+
}
|
|
3575
|
+
if (settlement.tag === "outcome") {
|
|
3576
|
+
const outcome = settlement.outcome;
|
|
3577
|
+
const reading = classifyQuestionOutcome(outcome);
|
|
3578
|
+
if (reading.shape === "contradictory") {
|
|
3579
|
+
bindOutcome({ kind: "failed", error: new Error("the question channel returned a contradictory outcome (an unavailable answer)") }, retainedQuestionsHash);
|
|
3580
|
+
return { kind: "delivery_failure", code: "question.human_channel_failed", presentedInput: retained };
|
|
3581
|
+
}
|
|
3582
|
+
if (reading.shape === "unavailable")
|
|
3583
|
+
return { kind: "unavailable", parkDeclined: true, presentedInput: retained };
|
|
3584
|
+
const answerSnapshot = reading.answer;
|
|
3585
|
+
bindOutcome({ kind: "answered", answer: answerSnapshot }, retainedQuestionsHash);
|
|
3586
|
+
return { kind: "answered", presentedInput: retained };
|
|
3587
|
+
}
|
|
3588
|
+
const error = settlement.tag === "threw"
|
|
3589
|
+
? settlement.error
|
|
3590
|
+
: Object.assign(new Error("the task ended while this question was still out"), { name: "AbortError" });
|
|
3591
|
+
bindOutcome({ kind: "failed", error }, retainedQuestionsHash);
|
|
3592
|
+
return {
|
|
3593
|
+
kind: "delivery_failure",
|
|
3594
|
+
code: settlement.tag === "aborted" || abortController.signal.aborted ? "question.aborted" : "question.human_channel_failed",
|
|
3595
|
+
presentedInput: retained,
|
|
3596
|
+
};
|
|
3597
|
+
}
|
|
3598
|
+
catch (err) {
|
|
3599
|
+
bindOutcome({ kind: "failed", error: err }, retainedQuestionsHash);
|
|
3600
|
+
return { kind: "delivery_failure", code: "question.human_channel_failed", presentedInput: retained };
|
|
3601
|
+
}
|
|
3602
|
+
};
|
|
3603
|
+
const suspendAsk = parkLaneArmed && checkpointStore !== undefined
|
|
3604
|
+
? async (req, postHookArgs, safety, liveFaceUnavailable) => {
|
|
3605
|
+
const syncFirstEligible = req.toolName === ASK_USER_QUESTION_TOOL_NAME ? contentAskRoutable(req.toolCallId) : onAsk !== undefined;
|
|
3606
|
+
if (syncFirstEligible &&
|
|
3235
3607
|
runtimeCaps?.forceDurableGate !== true &&
|
|
3236
|
-
|
|
3237
|
-
req.toolName !== ASK_USER_QUESTION_TOOL_NAME &&
|
|
3608
|
+
liveFaceUnavailable !== true &&
|
|
3238
3609
|
!inheritedUnavailableAsks.has(req.toolCallId)) {
|
|
3239
3610
|
return undefined;
|
|
3240
3611
|
}
|
|
@@ -3320,7 +3691,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3320
3691
|
const mintedAt = Date.now();
|
|
3321
3692
|
cp = {
|
|
3322
3693
|
token,
|
|
3323
|
-
version: approvalLedger.totalTokens !== undefined ? TOKEN_CHECKPOINT_VERSION : BINDING_CHECKPOINT_VERSION,
|
|
3694
|
+
version: orgAdmissionCheckpointState() ? ORG_ADMISSION_CHECKPOINT_VERSION : approvalLedger.totalTokens !== undefined ? TOKEN_CHECKPOINT_VERSION : BINDING_CHECKPOINT_VERSION,
|
|
3324
3695
|
scope,
|
|
3325
3696
|
sessionId,
|
|
3326
3697
|
leafId,
|
|
@@ -3381,11 +3752,28 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3381
3752
|
if (eff !== undefined && !toolEffects.has(t.name))
|
|
3382
3753
|
toolEffects.set(t.name, eff);
|
|
3383
3754
|
}
|
|
3384
|
-
toolCallGateArmedRef.armed =
|
|
3755
|
+
toolCallGateArmedRef.armed =
|
|
3756
|
+
effectivePolicy !== undefined ||
|
|
3757
|
+
hooks?.preToolUse !== undefined ||
|
|
3758
|
+
egressTools.size > 0 ||
|
|
3759
|
+
irreversibleTools.size > 0 ||
|
|
3760
|
+
spec.enablePlanMode === true ||
|
|
3761
|
+
complianceDenies.has("web_fetch");
|
|
3385
3762
|
if (toolCallGateArmedRef.armed) {
|
|
3386
3763
|
harness.on("tool_call", async (e) => {
|
|
3387
3764
|
blockedToolCalls.delete(e.toolCallId);
|
|
3388
3765
|
inheritedAskGrants.delete(e.toolCallId);
|
|
3766
|
+
{
|
|
3767
|
+
const complianceDeny = complianceCallDenial(complianceDenies, e.toolName);
|
|
3768
|
+
if (complianceDeny !== undefined) {
|
|
3769
|
+
if (blockedTracked)
|
|
3770
|
+
blockedToolCalls.add(e.toolCallId);
|
|
3771
|
+
if (notifyPermissionDenied) {
|
|
3772
|
+
await notifyPermissionDenied({ toolName: e.toolName, input: cloneObserverInput(e.input), toolCallId: e.toolCallId, reason: complianceDeny, source: "safety" });
|
|
3773
|
+
}
|
|
3774
|
+
return { block: true, reason: formatHookFeedback(complianceDeny), preToolContext: [] };
|
|
3775
|
+
}
|
|
3776
|
+
}
|
|
3389
3777
|
if (planModeRef.active && (toolEffects.get(e.toolName) ?? "write") !== "read") {
|
|
3390
3778
|
if (blockedTracked)
|
|
3391
3779
|
blockedToolCalls.add(e.toolCallId);
|
|
@@ -3406,9 +3794,11 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3406
3794
|
onNotifyError: (f) => emitTrace(deps.tracer, () => ({ kind: "observer.notify_failed", version: 1, taskId: spec.taskId ?? sessionId, site: f.site, message: f.error.message, ts: Date.now() })),
|
|
3407
3795
|
event: e,
|
|
3408
3796
|
preToolUse: hooks?.preToolUse,
|
|
3797
|
+
...(hookEnvFace !== undefined ? { hookEnv: hookEnvFace } : {}),
|
|
3409
3798
|
adjudicate,
|
|
3410
3799
|
resolveAsk: resolveAskBound,
|
|
3411
3800
|
suspendAsk,
|
|
3801
|
+
resolveContentAsk,
|
|
3412
3802
|
egress: egressTools.has(e.toolName),
|
|
3413
3803
|
irreversibility: irreversibilityTier.get(e.toolName),
|
|
3414
3804
|
reversibilityProbe: reversibilityProbes.get(e.toolName),
|
|
@@ -3461,7 +3851,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3461
3851
|
isInterrupt: abortController.signal.aborted || spec.signal?.aborted === true,
|
|
3462
3852
|
content: e.content.map((c) => ({ ...c })),
|
|
3463
3853
|
details: clonedDetails,
|
|
3464
|
-
}, { toolCallId: e.toolCallId, toolName: e.toolName });
|
|
3854
|
+
}, { toolCallId: e.toolCallId, toolName: e.toolName, ...(hookEnvFace !== undefined ? { env: hookEnvFace } : {}) });
|
|
3465
3855
|
if (patch?.additionalContext) {
|
|
3466
3856
|
content = [...content, { type: "text", text: formatHookFeedback(patch.additionalContext) }];
|
|
3467
3857
|
changed = true;
|
|
@@ -3469,7 +3859,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3469
3859
|
}
|
|
3470
3860
|
}
|
|
3471
3861
|
else if (hooks?.postToolUse) {
|
|
3472
|
-
const patch = await hooks.postToolUse(e.toolName, e.input, { content: e.content, details: e.details, isError: e.isError }, { toolCallId: e.toolCallId, toolName: e.toolName });
|
|
3862
|
+
const patch = await hooks.postToolUse(e.toolName, e.input, { content: e.content, details: e.details, isError: e.isError }, { toolCallId: e.toolCallId, toolName: e.toolName, ...(hookEnvFace !== undefined ? { env: hookEnvFace } : {}) });
|
|
3473
3863
|
if (patch?.updatedOutput) {
|
|
3474
3864
|
content = patch.updatedOutput;
|
|
3475
3865
|
changed = true;
|
|
@@ -3718,7 +4108,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3718
4108
|
: undefined;
|
|
3719
4109
|
overheadState.promptChars = systemPrompt.length;
|
|
3720
4110
|
const preparedHolder = {};
|
|
3721
|
-
const buildPrepared = () => ({ harness, session, sessionId, taskRootPath, model, thinking, compModel, mcp: mcp, ...(a2a !== undefined && a2a.tools.length > 0 ? { a2a } : {}), blockedRef, outputRef, abortController, conflictRef, blockedToolCalls, nestedStats, ...(rewindNotes.length > 0 ? { rewindNotes } : {}), cwdRef: handsCwdRef, ...(worktreeSessionRef !== undefined ? { worktreeSessionRef } : {}), ...(workspaceStateSettle !== undefined ? { workspaceStateSettle } : {}), denyNarrowingPolicy, ...(basePolicyForResumeEdit !== undefined ? { basePolicyForResumeEdit } : {}), releaseSignal, cacheBreakDetector, cacheFingerprint, promptManifest, epochDeclaredSections, activeTools, ...(deferred.size > 0 ? { deferredToolNames: deferred } : {}), toolMaterializeStatic, ownedEnv, suspendRef, suspendProgressRef, reviewRef, remoteEnvFailures, reviewRequestRef, suspendLoopRef, suspendForResource, ...(suspendForPlatformLimit !== undefined ? { suspendForPlatformLimit } : {}), ...(envLifetimeSuspendAt !== undefined ? { envLifetimeSuspendAt } : {}), ...(usageGovernance !== undefined ? { usageGovernance } : {}), callIssuedAtRef, brainCallGuardrailRef, suspendForReview, resourceLedger: priorLedger, liveSpendRef, humanReviewRef, now, tools, toolEffects, wakeRecovered, promptOverheadTokens, lastBrainContext, readTaskFile, recentlyReadFiles, normalizeAttachmentPath, isDedupStubResult, ...(onCompactionApplied ? { onCompactionApplied } : {}), compactionReuseRef, trimPressureRef, ...(memoryEngineSession ? { memoryEngineSession } : {}), ...(subagentRetain ? { subagentRetain } : {}), ...(lspDiagnostics && nudgeLspOnEdit ? { lspDiagnostics: { registry: lspDiagnostics, nudge: nudgeLspOnEdit, runIdent: lspRunIdent } } : {}), planModeRef, ...(dateChange ? { dateChange } : {}), ...(instructionSources ? { instructionSources } : {}), ...(workflowSizeGuideline ? { workflowSizeGuideline } : {}), ...(detectExternalChanges ? { detectExternalChanges } : {}), ...(toolsDeltaRef ? { toolsDeltaRef } : {}), ...(agentListing ? { agentListing } : {}), ...(skillsListing ? { skillsListing } : {}), announcedListingsRef, listBackgroundTasks, ...(turnSnapshotRef.current !== undefined ? { turnSnapshot: turnSnapshotRef.current } : {}), ...(centerCompactionCandidate !== undefined ? { centerCompactionCandidate } : {}) });
|
|
4111
|
+
const buildPrepared = () => ({ harness, session, sessionId, taskRootPath, model, thinking, compModel, mcp: mcp, ...(a2a !== undefined && a2a.tools.length > 0 ? { a2a } : {}), blockedRef, outputRef, abortController, conflictRef, blockedToolCalls, nestedStats, ...(rewindNotes.length > 0 ? { rewindNotes } : {}), cwdRef: handsCwdRef, ...(worktreeSessionRef !== undefined ? { worktreeSessionRef } : {}), ...(workspaceStateSettle !== undefined ? { workspaceStateSettle } : {}), denyNarrowingPolicy, ...(basePolicyForResumeEdit !== undefined ? { basePolicyForResumeEdit } : {}), releaseSignal, settleContentAskBindings, cacheBreakDetector, cacheFingerprint, wiringManifest, promptManifest, epochDeclaredSections, activeTools, ...(deferred.size > 0 ? { deferredToolNames: deferred } : {}), toolMaterializeStatic, ownedEnv, suspendRef, suspendProgressRef, reviewRef, remoteEnvFailures, reviewRequestRef, suspendLoopRef, suspendForResource, ...(suspendForPlatformLimit !== undefined ? { suspendForPlatformLimit } : {}), ...(envLifetimeSuspendAt !== undefined ? { envLifetimeSuspendAt } : {}), ...(usageGovernance !== undefined ? { usageGovernance } : {}), callIssuedAtRef, brainCallGuardrailRef, suspendForReview, resourceLedger: priorLedger, liveSpendRef, humanReviewRef, now, tools, toolEffects, wakeRecovered, promptOverheadTokens, lastBrainContext, readTaskFile, recentlyReadFiles, normalizeAttachmentPath, isDedupStubResult, ...(onCompactionApplied ? { onCompactionApplied } : {}), compactionReuseRef, trimPressureRef, ...(memoryEngineSession ? { memoryEngineSession } : {}), ...(subagentRetain ? { subagentRetain } : {}), ...(lspDiagnostics && nudgeLspOnEdit ? { lspDiagnostics: { registry: lspDiagnostics, nudge: nudgeLspOnEdit, runIdent: lspRunIdent } } : {}), planModeRef, ...(dateChange ? { dateChange } : {}), ...(instructionSources ? { instructionSources } : {}), ...(workflowSizeGuideline ? { workflowSizeGuideline } : {}), ...(detectExternalChanges ? { detectExternalChanges } : {}), ...(toolsDeltaRef ? { toolsDeltaRef } : {}), ...(agentListing ? { agentListing } : {}), ...(skillsListing ? { skillsListing } : {}), announcedListingsRef, listBackgroundTasks, ...(turnSnapshotRef.current !== undefined ? { turnSnapshot: turnSnapshotRef.current } : {}), ...(centerCompactionCandidate !== undefined ? { centerCompactionCandidate } : {}) });
|
|
3722
4112
|
const prepared = buildPrepared();
|
|
3723
4113
|
preparedHolder.current = prepared;
|
|
3724
4114
|
return prepared;
|