@sema-agent/core 7.34.0 → 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 +123 -3
- package/dist/brain/errors.d.ts +23 -1
- package/dist/brain/errors.js +19 -2
- package/dist/brain/status-sink.d.ts +7 -1
- package/dist/brain/stream-shared.d.ts +3 -1
- package/dist/brain/stream-shared.js +16 -4
- package/dist/core/ask-origin.d.ts +34 -6
- package/dist/core/ask-origin.js +24 -23
- package/dist/core/ask-question.js +2 -1
- package/dist/core/checkpoint-store.d.ts +4 -0
- package/dist/core/gate-fold.js +2 -2
- package/dist/core/gate-lanes.js +5 -4
- package/dist/core/governance-codes.d.ts +17 -1
- package/dist/core/governance-codes.js +11 -1
- package/dist/core/hooks.d.ts +3 -0
- package/dist/core/message-utils.d.ts +2 -1
- package/dist/core/message-utils.js +2 -1
- package/dist/core/mode-policy.d.ts +3 -0
- package/dist/core/mode-policy.js +5 -0
- package/dist/core/permission-rule-model.d.ts +4 -0
- package/dist/core/permission-rule-model.js +4 -0
- package/dist/core/permission-rules.js +21 -1
- package/dist/core/persisted-rule-arms.d.ts +4 -1
- package/dist/core/persisted-rule-arms.js +4 -0
- package/dist/core/retired-keys.js +1 -1
- package/dist/core/runner/active-skill-scope.js +5 -4
- package/dist/core/runner/assemble-result.js +2 -2
- package/dist/core/runner/contracts.d.ts +25 -3
- package/dist/core/runner/denial-limit-arms.d.ts +6 -1
- package/dist/core/runner/denial-limit-arms.js +4 -4
- 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/permission-rule-lanes.d.ts +2 -1
- package/dist/core/runner/permission-rule-lanes.js +14 -11
- package/dist/core/runner/prepare-ask-lane.d.ts +1 -1
- package/dist/core/runner/prepare-ask-lane.js +2 -2
- 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 +4 -3
- package/dist/core/runner/prepare-gate-stations.js +15 -11
- package/dist/core/runner/prepare-inherited-gate.d.ts +8 -1
- package/dist/core/runner/prepare-inherited-gate.js +10 -4
- package/dist/core/runner/prepare-park-ask.d.ts +4 -2
- package/dist/core/runner/prepare-park-ask.js +5 -4
- package/dist/core/runner/prepare-policy-chain.d.ts +3 -2
- package/dist/core/runner/prepare-policy-chain.js +171 -175
- package/dist/core/runner/prepare-task.js +7 -4
- package/dist/core/runner/run-brain-sinks.js +3 -1
- package/dist/core/runner/run-leg.js +5 -3
- package/dist/core/runner/run-notification-lane.d.ts +3 -0
- package/dist/core/runner/run-notification-lane.js +2 -1
- package/dist/core/runner/runtask.d.ts +1 -0
- package/dist/core/runner/runtask.js +5 -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/secret-env.d.ts +30 -58
- package/dist/core/secret-env.js +149 -586
- package/dist/core/sensitive-path-policy.js +2 -1
- package/dist/core/store-contracts/checkpoint-store-contract.js +2 -1
- package/dist/core/tool-policy.d.ts +31 -6
- package/dist/core/tool-policy.js +35 -16
- package/dist/core/tool-registry.d.ts +36 -0
- package/dist/core/tool-registry.js +22 -1
- package/dist/core/tool-roster.d.ts +17 -2
- package/dist/core/tool-roster.js +11 -1
- package/dist/core/trace.d.ts +11 -0
- package/dist/engine/execution-env/node-execution-env.d.ts +3 -1
- package/dist/engine/execution-env/node-execution-env.js +5 -2
- package/dist/engine/harness/agent-harness.js +2 -1
- package/dist/engine/lsp/node-lsp-manager.js +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +4 -4
- 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/fs/file-read-check.d.ts +2 -1
- package/dist/tools/fs/file-read-check.js +15 -7
- package/dist/tools/fs/shell-read-check.d.ts +10 -2
- package/dist/tools/fs/shell-read-check.js +12 -8
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +15 -1
- package/wire-changes/core@7.35.0.json +584 -0
|
@@ -35,6 +35,7 @@ import type { InheritedGate, IrreversibilityTier, PrepareResume, RunInternals, S
|
|
|
35
35
|
import { type Arbitration } from "../ask-origin.js";
|
|
36
36
|
import { type ModeGateSeats, type PermissionModeController } from "../mode-policy.js";
|
|
37
37
|
import { createRuleOffersOf, type PermissionRuleLanes } from "./permission-rule-lanes.js";
|
|
38
|
+
import type { ToolCallLike } from "../tool-registry.js";
|
|
38
39
|
export interface PreparePolicyChainInput {
|
|
39
40
|
/** borrowed-readonly — the REBOUND spec. Read: `sessionId` / `principal` (the session-rule read and the lanes' identity),
|
|
40
41
|
* `hooks` (spec over deps), `durableApproval` / `checkpointStore` (the mandate-park facility test and the sandbox arming's park prerequisites), `taskId` (the late-ask observer's detail).
|
|
@@ -199,7 +200,7 @@ export interface PreparePolicyChainResult {
|
|
|
199
200
|
isDelegatedChild?: true;
|
|
200
201
|
};
|
|
201
202
|
/** owned — the engine-judged risk axes for an ask, from the same resolved sources the safety tightens use. */
|
|
202
|
-
riskAxesOf: (
|
|
203
|
+
riskAxesOf: (call: Pick<ToolCallLike, "toolName" | "face">) => {
|
|
203
204
|
riskAxes?: {
|
|
204
205
|
irreversible?: boolean;
|
|
205
206
|
egress?: boolean;
|
|
@@ -214,7 +215,7 @@ export interface PreparePolicyChainResult {
|
|
|
214
215
|
/** owned — whether the sandbox-admission mode armed (declared isolation with its park prerequisites). */
|
|
215
216
|
sandboxAdmissionArmed: boolean;
|
|
216
217
|
/** owned — the NOT-CONTAINED classification: a call the declared sandbox does not contain. */
|
|
217
|
-
sandboxBoundaryCapable: (
|
|
218
|
+
sandboxBoundaryCapable: (call: Pick<ToolCallLike, "toolName" | "face">) => boolean;
|
|
218
219
|
/** owned — the admission disclosure's trace emitter (the gate station emits it once the fold settles). */
|
|
219
220
|
emitSandboxAdmitted: (info: {
|
|
220
221
|
toolCallId: string;
|
|
@@ -6,7 +6,7 @@ import { cloneObserverInput, resolveHookTimeoutMs } from "../hooks.js";
|
|
|
6
6
|
import { assertHookSeatsCallable } from "../hook-seats.js";
|
|
7
7
|
import { isNamespacedCoveringRuleName, namespacedRuleNameCovers } from "../permission-rules.js";
|
|
8
8
|
import { isIsolated } from "../remote-env.js";
|
|
9
|
-
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";
|
|
10
10
|
import { RETIRED_TOOL_NAMES } from "../tool-name-aliases.js";
|
|
11
11
|
import { NAMESPACED_NAME_SHAPES, protocolOf } from "../protocol-table.js";
|
|
12
12
|
import { emitTrace } from "../trace.js";
|
|
@@ -20,6 +20,7 @@ import { askGrantShapeOf } from "./inherited-ask-grants.js";
|
|
|
20
20
|
import { createPermissionRuleLanes, inheritedAskRuleEvidence, createRuleOffersOf } from "./permission-rule-lanes.js";
|
|
21
21
|
import { createLiveSessionRules, createSessionRulePolicy } from "./session-rule-policy.js";
|
|
22
22
|
import { thrownText } from "../thrown-value.js";
|
|
23
|
+
import { anyNamed, firstNamed, ruleNamesOf } from "../tool-roster.js";
|
|
23
24
|
export async function preparePolicyChain(input) {
|
|
24
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;
|
|
25
26
|
const ancestorArbitrations = new Map();
|
|
@@ -232,7 +233,7 @@ export async function preparePolicyChain(input) {
|
|
|
232
233
|
list.push({ cls, layer });
|
|
233
234
|
foldAskClasses.set(toolCallId, list);
|
|
234
235
|
};
|
|
235
|
-
const sandboxBoundaryCapable = (
|
|
236
|
+
const sandboxBoundaryCapable = (call) => anyNamed(egressTools, ruleNamesOf(call)) || !envHandToolNames.has(call.toolName);
|
|
236
237
|
const emitSandboxAdmitted = (info) => {
|
|
237
238
|
emitTrace(deps.tracer, () => ({
|
|
238
239
|
kind: "permission.sandbox_admitted",
|
|
@@ -256,18 +257,16 @@ export async function preparePolicyChain(input) {
|
|
|
256
257
|
void toolName;
|
|
257
258
|
};
|
|
258
259
|
const callerPolicyLayer = policy !== undefined && sameInstanceAncestorCount > 0
|
|
259
|
-
? {
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
},
|
|
270
|
-
}
|
|
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
|
+
})
|
|
271
270
|
: policy;
|
|
272
271
|
const askSourceIdentity = () => ({
|
|
273
272
|
principal: spec.principal,
|
|
@@ -278,11 +277,12 @@ export async function preparePolicyChain(input) {
|
|
|
278
277
|
: {}),
|
|
279
278
|
...(delegation.isDelegatedChild ? { isDelegatedChild: true } : {}),
|
|
280
279
|
});
|
|
281
|
-
const riskAxesOf = (
|
|
282
|
-
const
|
|
283
|
-
const
|
|
280
|
+
const riskAxesOf = (call) => {
|
|
281
|
+
const names = ruleNamesOf(call);
|
|
282
|
+
const tier = firstNamed(irreversibilityTier, names)?.value;
|
|
283
|
+
const negatives = firstNamed(axisExplicitNegatives, names)?.value;
|
|
284
284
|
const irreversible = tier === "always" || tier === "maybe" ? true : tier === "never" ? false : negatives?.irreversible;
|
|
285
|
-
const egress = egressTools
|
|
285
|
+
const egress = anyNamed(egressTools, names) ? true : negatives?.egress;
|
|
286
286
|
if (irreversible === undefined && egress === undefined)
|
|
287
287
|
return {};
|
|
288
288
|
return { riskAxes: { ...(irreversible !== undefined ? { irreversible } : {}), ...(egress !== undefined ? { egress } : {}) } };
|
|
@@ -314,7 +314,9 @@ export async function preparePolicyChain(input) {
|
|
|
314
314
|
cwdRef: handsCwdRef,
|
|
315
315
|
deniesDirectoryRead: readDenyMatcher !== undefined ? (d) => readDenyMatcher.matchPath(d) !== null : undefined,
|
|
316
316
|
});
|
|
317
|
-
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;
|
|
318
320
|
let editArgs = edit;
|
|
319
321
|
let settledBy = approved;
|
|
320
322
|
const vetoed = (d) => {
|
|
@@ -350,7 +352,7 @@ export async function preparePolicyChain(input) {
|
|
|
350
352
|
}
|
|
351
353
|
if (re.updatedInput !== undefined)
|
|
352
354
|
editArgs = re.updatedInput;
|
|
353
|
-
const judged = await judgeInheritedClassifier({ liveMode: () => permissionMode.current, autoMode:
|
|
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 }) });
|
|
354
356
|
if (judged.kind === "allow") {
|
|
355
357
|
const cleared = { ...judged.result };
|
|
356
358
|
carryEngineAttestations(judged.result, cleared);
|
|
@@ -371,10 +373,10 @@ export async function preparePolicyChain(input) {
|
|
|
371
373
|
toolName: creq.toolName,
|
|
372
374
|
toolCallId: creq.toolCallId,
|
|
373
375
|
args: editArgs,
|
|
374
|
-
...ruleOffersOf(creq
|
|
376
|
+
...ruleOffersOf(creq, editArgs, ancestorFacts(re)),
|
|
375
377
|
message: re.message ?? `approval required for "${creq.toolName}" (inherited parent policy)`,
|
|
376
378
|
...askSourceIdentity(),
|
|
377
|
-
...riskAxesOf(creq
|
|
379
|
+
...riskAxesOf(creq),
|
|
378
380
|
...(re.requiresRealApproval === true ? { requiresRealApproval: true } : {}),
|
|
379
381
|
...askMandateMember(ancestorFacts(re)),
|
|
380
382
|
...(re.persistedRuleShadowed !== undefined ? { persistedRuleShadowed: re.persistedRuleShadowed } : {}),
|
|
@@ -438,7 +440,7 @@ export async function preparePolicyChain(input) {
|
|
|
438
440
|
if (judged.kind === "deny")
|
|
439
441
|
return judged.result;
|
|
440
442
|
const { ask: inheritedAsk, fallback, mintedHere } = judged;
|
|
441
|
-
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) {
|
|
442
444
|
recordAncestorSandboxAdmission(creq.toolCallId, creq.toolName);
|
|
443
445
|
return { action: "allow" };
|
|
444
446
|
}
|
|
@@ -451,10 +453,10 @@ export async function preparePolicyChain(input) {
|
|
|
451
453
|
toolName: creq.toolName,
|
|
452
454
|
toolCallId: creq.toolCallId,
|
|
453
455
|
args: presentedArgs,
|
|
454
|
-
...ruleOffersOf(creq
|
|
456
|
+
...ruleOffersOf(creq, presentedArgs, ancestorFacts(inheritedAsk.action === "ask" ? inheritedAsk : undefined)),
|
|
455
457
|
message: inheritedAsk.message ?? `approval required for "${creq.toolName}" (inherited parent policy)`,
|
|
456
458
|
...askSourceIdentity(),
|
|
457
|
-
...riskAxesOf(creq
|
|
459
|
+
...riskAxesOf(creq),
|
|
458
460
|
...(inheritedAsk.action === "ask" && inheritedAsk.requiresRealApproval === true ? { requiresRealApproval: true } : {}),
|
|
459
461
|
...askMandateMember(ancestorFacts(inheritedAsk.action === "ask" ? inheritedAsk : undefined)),
|
|
460
462
|
...(inheritedAsk.action === "ask" && inheritedAsk.persistedRuleShadowed !== undefined ? { persistedRuleShadowed: inheritedAsk.persistedRuleShadowed } : {}),
|
|
@@ -472,92 +474,90 @@ export async function preparePolicyChain(input) {
|
|
|
472
474
|
if (resolved.action !== "allow")
|
|
473
475
|
return resolved;
|
|
474
476
|
if (resolved.updatedInput !== undefined) {
|
|
475
|
-
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);
|
|
476
478
|
}
|
|
477
479
|
recordInheritedAskGrant(creq.toolCallId, pc.onAsk, resolved.presentedInput, askWaitMs, resolved);
|
|
478
480
|
return { action: "allow" };
|
|
479
481
|
},
|
|
480
482
|
}
|
|
481
|
-
: {
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
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))
|
|
494
498
|
return decision;
|
|
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
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
carryEngineAttestations(resolved, approvedWithRewrite);
|
|
558
|
-
return approvedWithRewrite;
|
|
559
|
-
},
|
|
560
|
-
});
|
|
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
|
+
}));
|
|
561
561
|
const rewriteCapableLayers = policy !== undefined || parentConstraintWrappers.length > 0;
|
|
562
562
|
const rewriteEmitterIndex = new Map();
|
|
563
563
|
const rewriteCapableChain = [
|
|
@@ -570,16 +570,14 @@ export async function preparePolicyChain(input) {
|
|
|
570
570
|
if (policy !== undefined && pc.policy === policy)
|
|
571
571
|
sameInstanceAdapterIndices.add(j + callerSlotOffset);
|
|
572
572
|
});
|
|
573
|
-
const instrumentedChain = rewriteCapableChain.map((layer, idx) => ({
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
return d;
|
|
582
|
-
},
|
|
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;
|
|
583
581
|
}));
|
|
584
582
|
const modeGateLayer = createModeGatePolicy(permissionMode, { env: executionEnv, rootPath: taskRootFinal, acceptDirs: [taskRootFinal, ...additionalRootsCanonical], roster: toolRosterDeltas, readOnlyDeclared: (name) => mountedToolDeclaresReadOnly(tools, name), ...(scratchpadDir !== undefined ? { exemptDirs: [scratchpadDir] } : {}) });
|
|
585
583
|
const policyLayers = [
|
|
@@ -593,70 +591,68 @@ export async function preparePolicyChain(input) {
|
|
|
593
591
|
: [...integrityGuardLayers, ...policyLayers, modeGateLayer];
|
|
594
592
|
const foldedPolicy = guardedPolicyLayers.length === 1 ? guardedPolicyLayers[0] : combinePolicies(...guardedPolicyLayers);
|
|
595
593
|
const effectivePolicy = foldedPolicy !== undefined && rewriteCapableLayers
|
|
596
|
-
? {
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
catch (err) {
|
|
603
|
-
rewriteEmitterIndex.delete(req.toolCallId);
|
|
604
|
-
throw err;
|
|
605
|
-
}
|
|
606
|
-
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) {
|
|
607
600
|
rewriteEmitterIndex.delete(req.toolCallId);
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
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]);
|
|
617
613
|
}
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
if (d.updatedInput !== undefined) {
|
|
632
|
-
return {
|
|
633
|
-
action: "deny",
|
|
634
|
-
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)",
|
|
635
|
-
updatedInput: decision.updatedInput,
|
|
636
|
-
};
|
|
637
|
-
}
|
|
638
|
-
if (d.action === "ask" && asked === undefined)
|
|
639
|
-
asked = d;
|
|
640
|
-
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;
|
|
641
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);
|
|
642
638
|
}
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
}
|
|
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
|
+
})
|
|
660
656
|
: foldedPolicy;
|
|
661
657
|
return { hooks, hookTimeoutMs, preToolUseObservational, ownGatePreToolUse, basePolicyForResumeEdit, denyNarrowingPolicy, policyLayers, effectivePolicy, inheritedUnavailableAsks, inheritedAskGrants, askSourceIdentity, riskAxesOf, ruleOffersOf, permissionRuleLane, permissionRuleOrgLane, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, foldAskClasses, ancestorSandboxAdmissions, ancestorArbitrations };
|
|
662
658
|
}
|
|
@@ -44,6 +44,7 @@ import { parkContaminationMarker } from "./park-commit.js";
|
|
|
44
44
|
export { gatedCallIdOf, USAGE_WINDOW_REAP_MARGIN_MS } from "./park-commit.js";
|
|
45
45
|
import { prepareOffloadWrappers } from "./prepare-offload-wrappers.js";
|
|
46
46
|
import { prepareFileHistory } from "./prepare-file-history.js";
|
|
47
|
+
import { resolveFileHistoryRequest } from "./file-history-request.js";
|
|
47
48
|
import { prepareExecutionEnv } from "./prepare-execution-env.js";
|
|
48
49
|
import { prepareRunRefs } from "./prepare-run-refs.js";
|
|
49
50
|
import { prepareInheritedGate } from "./prepare-inherited-gate.js";
|
|
@@ -304,6 +305,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
304
305
|
let shellGatedTools = new Set();
|
|
305
306
|
refuseRequireExistingWithoutSession(spec);
|
|
306
307
|
refuseRegistryScopeMismatch(spec, internals);
|
|
308
|
+
const fileHistoryRequest = resolveFileHistoryRequest(spec, deps);
|
|
307
309
|
const { acquired, session, conflictRef, wakeRecovered } = await prepareAcquireReconcile({ sessions, spec, resume, toolEffects, ...(internals?.sessionPlacement !== undefined ? { placement: internals.sessionPlacement } : {}), ...(() => { const g = durableParkGapFor(deps, spec); return g !== undefined ? { durableParkGap: g } : {}; })() });
|
|
308
310
|
const sessionId = acquired.sessionId;
|
|
309
311
|
const onceLedger = await loadAnnounceOnceLedger(session, resume?.seed.announcedListings, deps.onError);
|
|
@@ -403,7 +405,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
403
405
|
const ownedEnv = ownedEnvSeat.current;
|
|
404
406
|
const { taskRootFinal, rebaseRestoredPath } = await prepareWorkspaceRestore({ ownedEnv, deps, spec, internals, resume, taskRootInitial, abortController, sessionId });
|
|
405
407
|
const { canonical: taskRootCanonical } = await resolveTaskRootCanonical({ env: executionEnv, given: taskRootFinal, onNotice: deps.onNotice, sessionId, runId });
|
|
406
|
-
const { trackFileEdit, fileHistoryBoundary, restoredFilePaths, rewindNotes, fileHistoryEnabled, fileHistoryFact, historyScope, historyRoot, historyFs } = await prepareFileHistory({ deps, spec, internals, executionEnv, taskRootFinal, handsEnabled, sessionId, session, abortController });
|
|
408
|
+
const { trackFileEdit, fileHistoryBoundary, restoredFilePaths, rewindNotes, fileHistoryEnabled, fileHistoryFact, historyScope, historyRoot, historyFs } = await prepareFileHistory({ deps, spec, request: fileHistoryRequest, internals, executionEnv, taskRootFinal, handsEnabled, sessionId, session, abortController });
|
|
407
409
|
const { noteFileEdited, editedFilesSnapshot, harnessRef, toolProgressRef, skillScope, forwardEvent, reviewRequestRef, requestReview, stopRequestedRef, requestStopAfterTurn, bindPermissionModeSeat, enterPlanMode, subagentRetain, worktreeIsolation } = prepareRunRefs({ spec, internals, executionEnv, taskRootFinal });
|
|
408
410
|
const legContextOverlay = () => runnerSelf?.contextOverlayOf?.(harnessRef.current?.getModelRef() ?? resolvedRole.modelRef);
|
|
409
411
|
let resolvedReadFace;
|
|
@@ -411,7 +413,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
411
413
|
let readDenyAdditionsNormalized = [];
|
|
412
414
|
let handsLessResolvedFace;
|
|
413
415
|
let handsLessResolvedWriteFace;
|
|
414
|
-
const { liveInheritedGate, seedInheritedGate, inheritedAncestorRules, inheritedShellGate, inheritedParentConstraints, permissionMode, inheritedAdmittedOrgScopes, priorOwnOrgVerdict, orgGovernedProvenance, effectiveShellGate, ownSessionRulesRef, ancestorSessionRulesRef, ancestorRulesNow, memoryAdmittedOrgScopesRef, ownOrgVerdictRef, orgAdmissionCheckpointState, faceCheckpointSection, faceCheckpointState, writeFaceCheckpointSection, f012CheckpointState, frozenOnAsk, hookEnvSource, notifyOwnHookCrash, frozenOnQuestion, parentSpecSeat, provenanceForChildrenRef, delegationSettlementRef, inheritedGateForChildren, carrierReadFace, carrierWriteFace, fullShellReachable, gateStopRef, stopForDenialLimit, enrichSpecToolCtx } = prepareInheritedGate({ spec, deps, internals, resume, sessions, sessionId, runId, hostTaskId, taskRootFinal, executionEnv, ownedEnv, lockedPreflight, checkpointSeat, toolFaceSnapshot, mountsCallerTool, promptProfile, resolvedInteractionPosture, permissionModeSeat, handsEnabled, reportUsage, harnessRef, skillScope, forwardEvent, subagentRetain, worktreeIsolation, requestReview, requestStopAfterTurn, enterPlanMode, reminderMark, reminderDisclosureCounts, fileHistoryEnabled, historyScope, historyRoot, historyFs, abortRun: () => { abortController.abort(); void harness.abort(); }, runtimeCaps: () => runtimeCaps, hooks: () => hooks, preToolUseObservational: () => preToolUseObservational, hookTimeoutMs: () => hookTimeoutMs, hookEnvFace: () => hookEnvFace, autoModeDecider: () => autoModeDeciderRef.current, autoModeDenialTracking: () => autoModeDenialTrackingRef.current, autoModeArming: () => autoModeArmingRef.current, agentForkDenial: () => agentForkDenial, observersActive: () => observersActive, resolvedReadFace: () => resolvedReadFace, resolvedWriteFace: () => resolvedWriteFace, readDenyAdditionsNormalized: () => readDenyAdditionsNormalized, handsLessResolvedFace: () => handsLessResolvedFace, handsLessResolvedWriteFace: () => handsLessResolvedWriteFace, centerAdoption: () => centerAdoptionRef.current, memoryEngineSession: () => memoryEngineSession });
|
|
416
|
+
const { liveInheritedGate, seedInheritedGate, inheritedAncestorRules, inheritedShellGate, inheritedParentConstraints, permissionMode, commitModeSeats, endModeCeiling, inheritedAdmittedOrgScopes, priorOwnOrgVerdict, orgGovernedProvenance, effectiveShellGate, ownSessionRulesRef, ancestorSessionRulesRef, ancestorRulesNow, memoryAdmittedOrgScopesRef, ownOrgVerdictRef, orgAdmissionCheckpointState, faceCheckpointSection, faceCheckpointState, writeFaceCheckpointSection, f012CheckpointState, frozenOnAsk, hookEnvSource, notifyOwnHookCrash, frozenOnQuestion, parentSpecSeat, provenanceForChildrenRef, delegationSettlementRef, inheritedGateForChildren, carrierReadFace, carrierWriteFace, fullShellReachable, gateStopRef, stopForDenialLimit, enrichSpecToolCtx } = prepareInheritedGate({ spec, deps, internals, resume, sessions, sessionId, runId, hostTaskId, taskRootFinal, executionEnv, ownedEnv, lockedPreflight, checkpointSeat, toolFaceSnapshot, mountsCallerTool, promptProfile, resolvedInteractionPosture, permissionModeSeat, handsEnabled, reportUsage, harnessRef, skillScope, forwardEvent, subagentRetain, worktreeIsolation, requestReview, requestStopAfterTurn, enterPlanMode, reminderMark, reminderDisclosureCounts, fileHistoryEnabled, historyScope, historyRoot, historyFs, abortRun: () => { abortController.abort(); void harness.abort(); }, runtimeCaps: () => runtimeCaps, hooks: () => hooks, preToolUseObservational: () => preToolUseObservational, hookTimeoutMs: () => hookTimeoutMs, hookEnvFace: () => hookEnvFace, autoModeDecider: () => autoModeDeciderRef.current, autoModeDenialTracking: () => autoModeDenialTrackingRef.current, autoModeArming: () => autoModeArmingRef.current, agentForkDenial: () => agentForkDenial, observersActive: () => observersActive, resolvedReadFace: () => resolvedReadFace, resolvedWriteFace: () => resolvedWriteFace, readDenyAdditionsNormalized: () => readDenyAdditionsNormalized, handsLessResolvedFace: () => handsLessResolvedFace, handsLessResolvedWriteFace: () => handsLessResolvedWriteFace, centerAdoption: () => centerAdoptionRef.current, memoryEngineSession: () => memoryEngineSession });
|
|
415
417
|
bindPermissionModeSeat(permissionMode);
|
|
416
418
|
const announceRuleStoreSkipped = ruleStoreUnreadableNotice(deps.onNotice, { sessionId, runId });
|
|
417
419
|
const persistedPathRowsRead = persistedPathRowsOfTask({ deps, principal: spec.principal, sessionId, root: taskRootFinal, home: executionEnv.homeDir, taskId: hostTaskId, handsEnabled, signals: [abortController.signal, ...(spec.signal !== undefined ? [spec.signal] : [])], onUnread: announceRuleStoreSkipped });
|
|
@@ -750,15 +752,16 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
750
752
|
const { askLane } = prepareAskLane({ gateMachineryActive, abortController, effectivePolicy, budgetSnapshot, handsCwdRef, advertisedWritableDirs, tools, inheritedUnavailableAsks, inheritedAskGrants, onAsk, humanReviewRef, now, ruleOffersOf, askSourceIdentity, riskAxesOf, autoModeDenialTracking: autoModeDenialTrackingRef, spec, deps, sessionId, runId, hooks, hookTimeoutMs, notifyOwnHookCrash, grantReadRoot: handsReadFace.grantReadRoot });
|
|
751
753
|
const { saga } = prepareSuspendSaga({ gateMachineryActive, abortController, harness, checkpointStore, deps, sessionId, hostTaskId, taskScope, liveSpendRef, resume, nestedStats, internals, activeTools, outputRef, readFileStateForCheckpoint, faceCheckpointSection, writeFaceCheckpointSection, reminderMark, handsCwdRef, worktreeSessionRef, undeliveredContinuationRef, inheritedParentConstraints, seedInheritedGate, ancestorRulesNow, inheritedShellGate, permissionMode, inheritedAdmittedOrgScopes, ownOrgVerdictRef, orgGovernedProvenance, announcedListingsRef, gitStatusRef, hookIdentity, placementRootResolved, externalContentTargetActive, remoteEnvFailures, memoryEngineSession, suspendLoopRef, ownedEnv, incompleteSuspendAdapter });
|
|
752
754
|
const { suspendForResource, suspendForPlatformLimit, suspendForReview } = prepareBoundaryParks({ saga, spec, checkpointStore, abortController, harness, session, sessions, sessionId, deps, priorLedger, maxSlices, maxSuspends, resourceTotal, priorSuspendCount, suspendChainBase, humanReviewRef, liveSpendRef, now, faceCheckpointState, f012CheckpointState, orgAdmissionCheckpointState, pausedRef, remoteEnvFailures, resourceSuspendEligible, durableSuspendInfraReady, incompleteSuspendAdapter });
|
|
753
|
-
const { parkAsk } = prepareParkAsk({ askLane, saga, spec, deps, sessionId, checkpointStore, toolRosterDeltas: rosterSeat, parkLaneArmed, contentAskRoutable, liveQuestionFace, mountedQuestionTool, contentAskBindings, lateStrandedAnswers, discloseStrandedAnswers, onAsk, runtimeCaps, inheritedUnavailableAsks, basePolicyForResumeEdit, budgetSnapshot, handsCwdRef, advertisedWritableDirs, offloadStore, ownedEnv, incompleteSuspendAdapter, session, sessions, suspendChainBase, maxSuspends, remoteEnvFailures, shellGatedTools, effectiveShellGate, durableApproval, priorLedger, liveSpendRef, resourceTotal, faceCheckpointState, f012CheckpointState, orgAdmissionCheckpointState, ruleOffersOf, now, humanReviewRef, abortController, harness, pausedRef });
|
|
755
|
+
const { parkAsk } = prepareParkAsk({ askLane, saga, spec, deps, sessionId, checkpointStore, toolRosterDeltas: rosterSeat, parkLaneArmed, contentAskRoutable, liveQuestionFace, mountedQuestionTool, contentAskBindings, lateStrandedAnswers, discloseStrandedAnswers, onAsk, runtimeCaps, inheritedUnavailableAsks, basePolicyForResumeEdit, budgetSnapshot, handsCwdRef, advertisedWritableDirs, offloadStore, ownedEnv, incompleteSuspendAdapter, session, sessions, suspendChainBase, maxSuspends, remoteEnvFailures, shellGatedTools, irreversibilityTier, effectiveShellGate, durableApproval, priorLedger, liveSpendRef, resourceTotal, faceCheckpointState, f012CheckpointState, orgAdmissionCheckpointState, ruleOffersOf, now, humanReviewRef, abortController, harness, pausedRef });
|
|
754
756
|
prepareGateStations({ askLane, parkAsk, tools, toolRosterDeltas: rosterSeat, toolEffects, deps, toolCallGateArmedRef, effectivePolicy, hooks, egressTools, irreversibleTools, spec, complianceDenies, harness, blockedToolCalls, inheritedAskGrants, inheritedUnavailableAsks, foldAskClasses, ancestorSandboxAdmissions, preToolContexts, gateOutcomes, batchHaltRef, blockedTracked, hookIdentity, reminderMark, hostTaskId, sessionId, ownGatePreToolUse, hookTimeoutMs, handsCwdRef, readDenyInForce: () => ({ tiers: handsReadFace.readDenyBuiltinTiersActive, rows: [...readDenyAdditionsNormalized.map((e) => e.pattern), ...handsReadFaceInput.pathDenyRules.filter((r) => r.faces.includes("read")).map((r) => r.rule)] }), hookEnvFace, writeProtectionCheck, shellReadCheck, irreversibilityTier, reversibilityProbes, abortController, shellGatedTools, autoModeDecider: autoModeDeciderRef, autoModeDenialTracking: autoModeDenialTrackingRef, askRoute: wiringManifest.ask, permissionMode, toolMarkSources, ...(deps.a2a?.isolatePeers === true ? { a2aIsolatePeers: true } : {}), ancestorArbitrations, runId, stopForDenialLimit, permissionRuleLane, permissionRuleOrgLane, questionToolMounted, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, delegation, notifyOwnHookCrash, frameSettlement });
|
|
755
757
|
const postureFrameRef = {};
|
|
756
758
|
const { microCompact, charsPerToken } = prepareContextLane({ model, deps, sessionId, runId, hostTaskId, offloadStore, microCompactKnob, harness, batchHaltRef, gitStatusRef, postureFrameRef, requestLossyRef, trimPressureRef, contextOverlay: legContextOverlay, ...(readFileStateForCheckpoint !== undefined ? { readFileState: readFileStateForCheckpoint } : {}) });
|
|
757
759
|
const preparedHolder = {};
|
|
758
760
|
const { cacheBreakDetector, cacheFingerprint, promptOverheadTokens, readTaskFile, normalizeAttachmentPath, isDedupStubResult, recentlyReadFiles, onCompactionApplied, detectExternalChanges, listBackgroundTasks, centerCompactionCandidate, effectiveReadFaceObserved, effectiveWriteFaceObserved, effectiveReadDenyObserved } = prepareTurnWiring({ deps, systemPromptSeat, harnessTools, fpRef, model, epochArtifactDigestForSnapshot, promptProfile, fableMitigations, systemBlocks, thinking, spec, sessionId, turnSnapshotRef, promptManifest, charsPerToken, handsEnabled, executionEnv, attachmentRootCanonical, additionalRootsCanonical, additionalReadRootsCanonical, readDenyMatcher, resolvedReadFace, handsCwdRef, readFileStateForCheckpoint, denyNarrowingPolicy, abortController, hostTaskId, taskScope, buildAssembleInputs, centerAdoptionRef, harnessRef, epochDeclaredSections, carrierReadFace, carrierWriteFace, readDenyAdditionsNormalized, preparedHolder });
|
|
759
761
|
await onceLedger.settle(session, announcedListingsRef);
|
|
760
|
-
const buildPrepared = () => ({ harness, session, sessionId, runId, registryAccess: { owner: hostTaskId, scope: taskScope }, reminderMark, reminderDisclosureCounts, fullShellReachable, approvalPosture: { get mode() { return permissionMode.current; }, askEffective: wiringManifest.ask.effective ?? "unresolved" }, permissionMode, editedFilesSnapshot, taskRootPath: taskRootFinal, model, thinking, compModel: effectiveCompModel, mcp, ...(mcpRedial !== undefined ? { mcpRedial } : {}), ...(a2a.tools.length > 0 ? { a2a } : {}), blockedRef, outputRef, abortController, conflictRef, blockedToolCalls, gateOutcomes, batchHaltRef, nestedStats, ...(rewindNotes.length > 0 ? { rewindNotes } : {}), ...(fileHistoryBoundary !== undefined ? { fileHistoryBoundary } : {}), ...(effectiveReadFaceObserved !== undefined ? { effectiveReadFace: effectiveReadFaceObserved, effectiveWriteFace: effectiveWriteFaceObserved } : {}), ...(effectiveReadDenyObserved !== undefined ? { effectiveReadDenyPatterns: effectiveReadDenyObserved } : {}), effectiveMemoryScopes: memoryEffectiveScopes, cwdRef: handsCwdRef, toolProgressRef, ...(advertisedWritableDirs !== undefined ? { advertisedWritableDirs } : {}), ...(worktreeSessionRef !== undefined ? { worktreeSessionRef } : {}), ...(workspaceStateSettle !== undefined ? { workspaceStateSettle } : {}), ...(sealReadStateSeat !== undefined ? { sealReadStateSeat } : {}), denyNarrowingPolicy, ...(permissionRuleLane !== undefined ? { persistedRuleLane: permissionRuleLane } : {}), ...(basePolicyForResumeEdit !== undefined ? { basePolicyForResumeEdit } : {}), ...(permissionRuleOrgLane !== undefined ? { permissionRuleOrg: permissionRuleOrgLane } : {}), releaseSignal, settleContentAskBindings, cacheBreakDetector, cacheFingerprint, wiringManifest, promptManifest, epochDeclaredSections, activeTools, ...(deferred.size > 0 ? { deferredToolNames: deferred } : {}), toolMaterializeStatic, deferDirectCall, ...(staticFaceForRef.current !== undefined ? { staticFaceFor: staticFaceForRef.current } : {}), ownedEnv, pausedRef, undeliveredContinuationRef, suspendProgressRef, remoteEnvFailures, reviewRequestRef, suspendLoopRef, suspendForResource, ...(suspendForPlatformLimit !== undefined ? { suspendForPlatformLimit } : {}), ...(envLifetimeSuspendAt !== undefined ? { envLifetimeSuspendAt } : {}), ...(usageGovernance !== undefined ? { usageGovernance } : {}), callIssuedAtRef, workCutRef, brainCallGuardrailRef, gateStopRef, stopForDenialLimit, suspendForReview, ...(readFileStateForCheckpoint !== undefined ? { readFileState: readFileStateForCheckpoint } : {}), resourceLedger: priorLedger, liveSpendRef, humanReviewRef, now, tools, toolRoster, toolRosterDeltas: rosterSeat, structuredProjector, toolEffects, wakeRecovered, promptOverheadTokens, lastBrainContext, readTaskFile, recentlyReadFiles, normalizeAttachmentPath, isDedupStubResult, ...(onCompactionApplied ? { onCompactionApplied } : {}), compactionReuseRef, trimPressureRef, microCompact, ...(memoryEngineSession ? { memoryEngineSession } : {}), ...(subagentRetain ? { subagentRetain } : {}), ...(lspDiagnostics && nudgeLspOnEdit ? { lspDiagnostics: { registry: lspDiagnostics, nudge: nudgeLspOnEdit, runIdent: lspRunIdent } } : {}), stopRequestedRef, announcedSnapshotRecovered: onceLedger.recovered, ...(dateChange ? { dateChange } : {}), ...(instructionSources ? { instructionSources } : {}), ...(projectInstructionContent !== undefined ? { projectInstructionContent } : {}), ...(workflowSizeGuideline ? { workflowSizeGuideline } : {}), ...(detectExternalChanges ? { detectExternalChanges } : {}), ...(toolsDeltaRef ? { toolsDeltaRef } : {}), ...(agentListing ? { agentListing } : {}), ...(skillsListing ? { skillsListing } : {}), announcedListingsRef, frameReceipts: { pending: [], listingSnapshotOwed: false }, frameSettlement, ...(peerLaneRefs.boundaryRound !== undefined ? { peerBoundaryRound: peerLaneRefs.boundaryRound } : {}), gitStatusRef, postureFrameRef, listBackgroundTasks, hookIdentity, ...(sessionBoxBound !== undefined ? { sessionBox: sessionBoxBound } : {}), hookTimeoutMs, ...(turnSnapshotRef.current !== undefined ? { turnSnapshot: turnSnapshotRef.current } : {}), ...(centerCompactionCandidate !== undefined ? { centerCompactionCandidate } : {}), ...(shellReadCheck !== undefined ? { shellReadCheck } : {}), ...(toolDisclosureSeat !== undefined ? { toolDisclosure: toolDisclosureSeat } : {}) });
|
|
762
|
+
const buildPrepared = () => ({ harness, session, sessionId, runId, registryAccess: { owner: hostTaskId, scope: taskScope }, reminderMark, reminderDisclosureCounts, fullShellReachable, approvalPosture: { get mode() { return permissionMode.current; }, askEffective: wiringManifest.ask.effective ?? "unresolved" }, permissionMode, editedFilesSnapshot, taskRootPath: taskRootFinal, model, thinking, compModel: effectiveCompModel, mcp, ...(mcpRedial !== undefined ? { mcpRedial } : {}), ...(a2a.tools.length > 0 ? { a2a } : {}), blockedRef, outputRef, abortController, conflictRef, blockedToolCalls, gateOutcomes, batchHaltRef, nestedStats, ...(rewindNotes.length > 0 ? { rewindNotes } : {}), ...(fileHistoryBoundary !== undefined ? { fileHistoryBoundary } : {}), ...(effectiveReadFaceObserved !== undefined ? { effectiveReadFace: effectiveReadFaceObserved, effectiveWriteFace: effectiveWriteFaceObserved } : {}), ...(effectiveReadDenyObserved !== undefined ? { effectiveReadDenyPatterns: effectiveReadDenyObserved } : {}), effectiveMemoryScopes: memoryEffectiveScopes, cwdRef: handsCwdRef, toolProgressRef, ...(advertisedWritableDirs !== undefined ? { advertisedWritableDirs } : {}), ...(worktreeSessionRef !== undefined ? { worktreeSessionRef } : {}), ...(workspaceStateSettle !== undefined ? { workspaceStateSettle } : {}), ...(sealReadStateSeat !== undefined ? { sealReadStateSeat } : {}), denyNarrowingPolicy, ...(permissionRuleLane !== undefined ? { persistedRuleLane: permissionRuleLane } : {}), ...(basePolicyForResumeEdit !== undefined ? { basePolicyForResumeEdit } : {}), ...(permissionRuleOrgLane !== undefined ? { permissionRuleOrg: permissionRuleOrgLane } : {}), releaseSignal, endModeCeiling, settleContentAskBindings, cacheBreakDetector, cacheFingerprint, wiringManifest, promptManifest, epochDeclaredSections, activeTools, ...(deferred.size > 0 ? { deferredToolNames: deferred } : {}), toolMaterializeStatic, deferDirectCall, ...(staticFaceForRef.current !== undefined ? { staticFaceFor: staticFaceForRef.current } : {}), ownedEnv, pausedRef, undeliveredContinuationRef, suspendProgressRef, remoteEnvFailures, reviewRequestRef, suspendLoopRef, suspendForResource, ...(suspendForPlatformLimit !== undefined ? { suspendForPlatformLimit } : {}), ...(envLifetimeSuspendAt !== undefined ? { envLifetimeSuspendAt } : {}), ...(usageGovernance !== undefined ? { usageGovernance } : {}), callIssuedAtRef, workCutRef, brainCallGuardrailRef, gateStopRef, stopForDenialLimit, suspendForReview, ...(readFileStateForCheckpoint !== undefined ? { readFileState: readFileStateForCheckpoint } : {}), resourceLedger: priorLedger, liveSpendRef, humanReviewRef, now, tools, toolRoster, toolRosterDeltas: rosterSeat, structuredProjector, toolEffects, wakeRecovered, promptOverheadTokens, lastBrainContext, readTaskFile, recentlyReadFiles, normalizeAttachmentPath, isDedupStubResult, ...(onCompactionApplied ? { onCompactionApplied } : {}), compactionReuseRef, trimPressureRef, microCompact, ...(memoryEngineSession ? { memoryEngineSession } : {}), ...(subagentRetain ? { subagentRetain } : {}), ...(lspDiagnostics && nudgeLspOnEdit ? { lspDiagnostics: { registry: lspDiagnostics, nudge: nudgeLspOnEdit, runIdent: lspRunIdent } } : {}), stopRequestedRef, announcedSnapshotRecovered: onceLedger.recovered, ...(dateChange ? { dateChange } : {}), ...(instructionSources ? { instructionSources } : {}), ...(projectInstructionContent !== undefined ? { projectInstructionContent } : {}), ...(workflowSizeGuideline ? { workflowSizeGuideline } : {}), ...(detectExternalChanges ? { detectExternalChanges } : {}), ...(toolsDeltaRef ? { toolsDeltaRef } : {}), ...(agentListing ? { agentListing } : {}), ...(skillsListing ? { skillsListing } : {}), announcedListingsRef, frameReceipts: { pending: [], listingSnapshotOwed: false }, frameSettlement, ...(peerLaneRefs.boundaryRound !== undefined ? { peerBoundaryRound: peerLaneRefs.boundaryRound } : {}), gitStatusRef, postureFrameRef, listBackgroundTasks, hookIdentity, ...(sessionBoxBound !== undefined ? { sessionBox: sessionBoxBound } : {}), hookTimeoutMs, ...(turnSnapshotRef.current !== undefined ? { turnSnapshot: turnSnapshotRef.current } : {}), ...(centerCompactionCandidate !== undefined ? { centerCompactionCandidate } : {}), ...(shellReadCheck !== undefined ? { shellReadCheck } : {}), ...(toolDisclosureSeat !== undefined ? { toolDisclosure: toolDisclosureSeat } : {}) });
|
|
761
763
|
rollback.commit();
|
|
764
|
+
commitModeSeats(abortController.signal);
|
|
762
765
|
const prepared = buildPrepared();
|
|
763
766
|
preparedHolder.current = prepared;
|
|
764
767
|
return prepared;
|
|
@@ -54,7 +54,9 @@ export function runBrainSinks(input) {
|
|
|
54
54
|
...(t.nextDelayMs !== undefined ? { nextDelayMs: t.nextDelayMs } : {}),
|
|
55
55
|
ts: Date.now(),
|
|
56
56
|
}
|
|
57
|
-
:
|
|
57
|
+
: t.kind === "echo_dropped"
|
|
58
|
+
? { kind: "brain.echo_dropped", version: 1, taskId: rs.telemetry.taskId, field: t.field, ts: Date.now() }
|
|
59
|
+
: { kind: "vision.placeholder", version: 1, taskId: rs.telemetry.taskId, count: t.count, ts: Date.now() });
|
|
58
60
|
};
|
|
59
61
|
const withBrainSinks = (fn) => runWithStatusSink(statusEmit, () => runWithBrainTelemetry(telemetryEmit, () => runWithReasoningWireFacts(observeReasoningWireFacts, fn)));
|
|
60
62
|
return { subagentName, withBrainSinks };
|