@sema-agent/core 5.64.0 → 6.0.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 +70 -0
- package/dist/agents/subagent.d.ts +2 -2
- package/dist/agents/subagent.js +11 -0
- package/dist/agents/verify.d.ts +1 -1
- package/dist/brain/anthropic.js +1 -1
- package/dist/brain/errors.d.ts +29 -0
- package/dist/brain/errors.js +20 -0
- package/dist/brain/open-responses.js +2 -2
- package/dist/brain/route-adjudicator.d.ts +8 -1
- package/dist/brain/route-adjudicator.js +1 -0
- package/dist/brain/status-sink.js +12 -1
- package/dist/brain/stream-engine.js +17 -6
- package/dist/core/auto-compaction.d.ts +26 -0
- package/dist/core/auto-compaction.js +7 -2
- package/dist/core/auto-mode-arming.d.ts +138 -0
- package/dist/core/auto-mode-arming.js +181 -0
- package/dist/core/auto-mode-defaults.d.ts +13 -0
- package/dist/core/auto-mode-defaults.js +5 -0
- package/dist/core/auto-mode-prompt.d.ts +14 -3
- package/dist/core/auto-mode-prompt.js +10 -7
- package/dist/core/auto-mode-rebuild.d.ts +75 -0
- package/dist/core/auto-mode-rebuild.js +41 -0
- package/dist/core/auto-mode.d.ts +15 -0
- package/dist/core/auto-mode.js +4 -2
- package/dist/core/checkpoint-store.d.ts +113 -4
- package/dist/core/context-edit.d.ts +47 -5
- package/dist/core/context-guard.d.ts +1 -1
- package/dist/core/file-history-retention.d.ts +106 -0
- package/dist/core/file-history-retention.js +36 -0
- package/dist/core/file-history-store.d.ts +768 -0
- package/dist/core/file-history-store.js +880 -0
- package/dist/core/governance-codes.d.ts +2 -1
- package/dist/core/governance-codes.js +14 -0
- package/dist/core/hooks.d.ts +48 -8
- package/dist/core/hooks.js +39 -22
- package/dist/core/lsp.d.ts +2 -2
- package/dist/core/mcp.d.ts +29 -7
- package/dist/core/memory-engine/consolidation-driver.d.ts +11 -0
- package/dist/core/memory-engine/consolidation-driver.js +71 -4
- package/dist/core/memory-engine/consolidation.d.ts +25 -2
- package/dist/core/memory-engine/consolidation.js +4 -1
- package/dist/core/memory-engine/distiller.d.ts +84 -1
- package/dist/core/memory-engine/distiller.js +68 -0
- package/dist/core/memory-engine/dual-root.js +6 -0
- package/dist/core/memory-engine/engine.d.ts +329 -15
- package/dist/core/memory-engine/engine.js +364 -34
- package/dist/core/memory-engine/file-backend.d.ts +30 -0
- package/dist/core/memory-engine/file-backend.js +14 -13
- package/dist/core/memory-engine/frontmatter.d.ts +22 -1
- package/dist/core/memory-engine/frontmatter.js +3 -0
- package/dist/core/memory-engine/header-hints.d.ts +5 -0
- package/dist/core/memory-engine/index.d.ts +5 -4
- package/dist/core/memory-engine/index.js +5 -4
- package/dist/core/memory-engine/layout.d.ts +88 -2
- package/dist/core/memory-engine/layout.js +112 -3
- package/dist/core/memory-engine/provenance-wording.d.ts +7 -0
- package/dist/core/memory-engine/provenance-wording.js +3 -0
- package/dist/core/memory-engine/tools.d.ts +89 -8
- package/dist/core/memory-engine/tools.js +263 -22
- package/dist/core/memory-engine/types.d.ts +80 -1
- package/dist/core/memory-recall.d.ts +6 -0
- package/dist/core/memory.d.ts +27 -1
- package/dist/core/memory.js +16 -2
- package/dist/core/permission-rule-consent.d.ts +20 -0
- package/dist/core/permission-rule-consent.js +12 -3
- package/dist/core/permission-rule-model.d.ts +67 -7
- package/dist/core/permission-rule-model.js +53 -7
- package/dist/core/permission-rule-store.js +15 -10
- package/dist/core/permission-rule-sync.js +15 -11
- package/dist/core/remote-env.d.ts +3 -3
- package/dist/core/retention-policy.d.ts +9 -0
- package/dist/core/retention-policy.js +5 -2
- package/dist/core/retention.d.ts +13 -2
- package/dist/core/runner/assemble-result.d.ts +19 -1
- package/dist/core/runner/assemble-result.js +17 -2
- package/dist/core/runner/compaction-call-options.d.ts +93 -0
- package/dist/core/runner/compaction-call-options.js +3 -0
- package/dist/core/runner/memory-capture-optout.d.ts +80 -0
- package/dist/core/runner/memory-capture-optout.js +53 -0
- package/dist/core/runner/prepare-config-doors.d.ts +5 -0
- package/dist/core/runner/prepare-config-doors.js +16 -0
- package/dist/core/runner/prepare-hands-readface.d.ts +119 -5
- package/dist/core/runner/prepare-hands-readface.js +103 -8
- package/dist/core/runner/prepare-memory.d.ts +88 -0
- package/dist/core/runner/prepare-memory.js +306 -25
- package/dist/core/runner/prepare-task.d.ts +156 -5
- package/dist/core/runner/prepare-task.js +488 -98
- package/dist/core/runner/runtask.d.ts +27 -20
- package/dist/core/runner/runtask.js +283 -99
- package/dist/core/runner/session-file-state-replay.d.ts +18 -10
- package/dist/core/runner/session-file-state-replay.js +52 -1
- package/dist/core/runner/tool-disclosure.js +2 -1
- package/dist/core/runner/turn-attachments.d.ts +22 -12
- package/dist/core/session-store.d.ts +1 -1
- package/dist/core/session-store.js +6 -1
- package/dist/core/session.d.ts +34 -1
- package/dist/core/store-contracts/file-history-store-contract.d.ts +3 -0
- package/dist/core/store-contracts/file-history-store-contract.js +720 -0
- package/dist/core/stub-env.d.ts +4 -0
- package/dist/core/stub-env.js +1 -0
- package/dist/core/task-registry-shared.js +30 -2
- package/dist/core/tool-errors.js +1 -0
- package/dist/core/tool-policy.d.ts +172 -1
- package/dist/core/tool-policy.js +32 -1
- package/dist/core/tool-result-store.js +2 -1
- package/dist/core/trace.d.ts +24 -0
- package/dist/core/types.d.ts +875 -97
- package/dist/core/types.js +4 -3
- package/dist/core/untrusted-text.d.ts +1 -1
- package/dist/core/untrusted-text.js +8 -0
- package/dist/core/workflow-run-store-contract.js +17 -0
- package/dist/core/workflow-run-store.d.ts +20 -0
- package/dist/core/workflow-run-store.js +1 -0
- package/dist/engine/compaction/compaction.d.ts +88 -10
- package/dist/engine/compaction/compaction.js +109 -30
- package/dist/engine/execution-env/node-execution-env.d.ts +9 -1
- package/dist/engine/execution-env/node-execution-env.js +28 -0
- package/dist/engine/harness/agent-harness.d.ts +52 -1
- package/dist/engine/harness/agent-harness.js +36 -1
- package/dist/engine/harness/types.d.ts +44 -1
- package/dist/engine/llm/types.d.ts +50 -4
- package/dist/engine/loop/agent-loop.d.ts +5 -1
- package/dist/engine/loop/agent-loop.js +25 -0
- package/dist/engine/loop/types.d.ts +19 -0
- package/dist/engine/lsp/node-lsp-manager.d.ts +1 -1
- package/dist/engine/session/session.js +1 -1
- package/dist/index.d.ts +18 -8
- package/dist/index.js +14 -6
- package/dist/orchestration/run-workflow-tool.d.ts +20 -2
- package/dist/orchestration/run-workflow-tool.js +22 -3
- package/dist/orchestration/workflow-governance.d.ts +59 -1
- package/dist/orchestration/workflow-governance.js +61 -8
- package/dist/orchestration/workflow-meta.d.ts +4 -2
- package/dist/orchestration/workflow-primitives.js +56 -13
- package/dist/orchestration/workflow-types.d.ts +112 -1
- package/dist/orchestration/workflow-types.js +2 -2
- package/dist/orchestration/workflow.d.ts +20 -0
- package/dist/orchestration/workflow.js +182 -14
- package/dist/prompt-assembly/event-registry.js +1 -1
- package/dist/prompts/default.d.ts +15 -7
- package/dist/prompts/default.js +3 -0
- package/dist/stores/file/file-history-store.d.ts +368 -0
- package/dist/stores/file/file-history-store.js +1248 -0
- package/dist/stores/file/index.d.ts +22 -13
- package/dist/stores/file/index.js +4 -4
- package/dist/stores/file/permission-rule-store.js +1 -0
- package/dist/stores/file/strategy-store.d.ts +3 -3
- package/dist/tools/fs/bash-readonly-classifier.d.ts +87 -3
- package/dist/tools/fs/bash-readonly-classifier.js +106 -4
- package/dist/tools/fs/fs-bash.js +9 -5
- package/dist/tools/fs/fs-shared.d.ts +52 -1
- package/dist/tools/fs/fs-shared.js +14 -0
- package/dist/tools/fs/fs-write.d.ts +5 -5
- package/dist/tools/fs/fs-write.js +71 -14
- package/dist/tools/fs/index.d.ts +6 -1
- package/dist/tools/fs/index.js +1 -1
- package/dist/tools/web.js +2 -1
- package/package.json +5 -1
- package/test/export-surface.snapshot.json +159 -23
- package/dist/core/file-snapshot-store.d.ts +0 -165
- package/dist/core/file-snapshot-store.js +0 -259
- package/dist/core/store-contracts/file-snapshot-store-contract.d.ts +0 -13
- package/dist/core/store-contracts/file-snapshot-store-contract.js +0 -134
- package/dist/stores/file/file-snapshot-store.d.ts +0 -58
- package/dist/stores/file/file-snapshot-store.js +0 -353
|
@@ -6,6 +6,7 @@ const PROMPT_HASH_SALT = randomBytes(16);
|
|
|
6
6
|
import { sanitizeCompactionSettings } from "../auto-compaction.js";
|
|
7
7
|
import { projectStaleToolResults, resolveStaleToolResultOffload } from "./compaction-call-options.js";
|
|
8
8
|
import { createAutoModeDecider } from "../auto-mode.js";
|
|
9
|
+
import { autoModeArmingRecipeOf } from "../auto-mode-arming.js";
|
|
9
10
|
import { buildAutoModePrompt, renderAutoModeAction, renderAutoModeWindow } from "../auto-mode-prompt.js";
|
|
10
11
|
import { resolveTaskModel } from "../roles.js";
|
|
11
12
|
import { primaryActivityArg } from "../arg-summary.js";
|
|
@@ -20,7 +21,7 @@ import { createSubagentWorktreeHelper, forkGovernanceDenial, resolveDelegationEn
|
|
|
20
21
|
import { createAgentTranscriptTool, AGENT_TRANSCRIPT_TOOL_NAME } from "../../agents/agent-transcript-tool.js";
|
|
21
22
|
import { createSendMessageTool, SEND_MESSAGE_TOOL_NAME } from "../../agents/send-message-tool.js";
|
|
22
23
|
import { SubagentRetainLedger } from "../../agents/retain-ledger.js";
|
|
23
|
-
import { askApproverIdentity, carriesBidiControls, checkToolPolicyProjection, combinePolicies, constraintChainDigest,
|
|
24
|
+
import { askApproverIdentity, carriesBidiControls, checkToolPolicyProjection, combinePolicies, constraintChainDigest, constraintChainEntryOfLayer, isApprovalSettledBy, isAskDenyResolution, screenApproverAttribution, createTranscriptIntegrityPolicy, createUnverifiableDeletePolicy, describeThrown, refuseOutOfContractDecision, resolveAsk, toolPolicyNameSets, tryCloneArgs } from "../tool-policy.js";
|
|
24
25
|
const PERSISTED_RULE_TOOL = "Bash";
|
|
25
26
|
import { findAdmittingRule, segmentCoverageOf, suggestRulesForCommand } from "../permission-rule-model.js";
|
|
26
27
|
import { ActiveSkillScope, createActiveSkillScopePolicy } from "./active-skill-scope.js";
|
|
@@ -49,7 +50,6 @@ import { TOOL_SEARCH_NAME, buildDeferredRegistry, classifyDeferred, extractDisco
|
|
|
49
50
|
import { createSharedMemoryTools } from "../shared-memory/tools.js";
|
|
50
51
|
import { SHARED_MEMORY_TOOL_NAMES } from "../shared-memory/types.js";
|
|
51
52
|
import { MEMORY_ENGINE_TOOL_NAMES } from "../memory-engine/tools.js";
|
|
52
|
-
import { memoryRecallDisciplineSegment } from "../memory-engine/engine.js";
|
|
53
53
|
import { classifyToolContentOrigin, contentOriginPollutes, delegationCallIsExternal } from "../memory-engine/content-origin.js";
|
|
54
54
|
import { narrowContentSafety, readCardAttestation } from "../memory-engine/delegation-provenance.js";
|
|
55
55
|
import { recordSyncUnattestable, sessionSettlements } from "../memory-engine/delegation-settlement.js";
|
|
@@ -97,6 +97,7 @@ import { countElicitOptIns, deriveWiringManifest, resolveAskSeamForm, resolveDec
|
|
|
97
97
|
import { durableParkGapFor } from "../park-selfcheck.js";
|
|
98
98
|
import { GLOBAL_USAGE_KEY, usageRetryAfterMs, windowsGovernCost } from "../usage-window-store.js";
|
|
99
99
|
import { deliverEngineNotice } from "../types.js";
|
|
100
|
+
import { resolveTrackKey } from "../file-history-store.js";
|
|
100
101
|
let announcedMaterializeEnvBySink = new WeakMap();
|
|
101
102
|
const announcedMaterializeEnvConsole = new Set();
|
|
102
103
|
function materializeEnvLedger(onNotice) {
|
|
@@ -218,6 +219,7 @@ function announceDeclaredMcpContentClasses(args) {
|
|
|
218
219
|
toolCount,
|
|
219
220
|
...(declaredClass === "execution" ? { execIsExternalContent: args.execIsExternalContent } : {}),
|
|
220
221
|
sessionId: args.sessionId,
|
|
222
|
+
runId: args.runId,
|
|
221
223
|
},
|
|
222
224
|
});
|
|
223
225
|
}
|
|
@@ -324,7 +326,7 @@ class ParkRefusal extends Error {
|
|
|
324
326
|
export { resolveCheckpointStore } from "../checkpoint-store.js";
|
|
325
327
|
export { isFableFamilyModelId, resolveAttachmentsConfig, resolveModelPromptTraits, resolveTaskLimits } from "./prepare-config-doors.js";
|
|
326
328
|
export { rebaseWorkspacePath, rebaseWorkspacePathAcross } from "./prepare-workspace-restore.js";
|
|
327
|
-
function buildMicroCompactState(deps, model, sessionId, offloadStore, knob) {
|
|
329
|
+
function buildMicroCompactState(deps, model, sessionId, runId, offloadStore, knob) {
|
|
328
330
|
const triggerWindow = resolveTriggerWindow(model);
|
|
329
331
|
if (triggerWindow.clamped) {
|
|
330
332
|
deliverEngineNotice(deps.onNotice, {
|
|
@@ -337,6 +339,7 @@ function buildMicroCompactState(deps, model, sessionId, offloadStore, knob) {
|
|
|
337
339
|
declaredAutoCompactTokens: triggerWindow.declaredAutoCompactTokens,
|
|
338
340
|
physicalWindow: triggerWindow.physicalWindow,
|
|
339
341
|
sessionId,
|
|
342
|
+
runId,
|
|
340
343
|
},
|
|
341
344
|
});
|
|
342
345
|
}
|
|
@@ -433,6 +436,187 @@ export async function runGuardChain(args) {
|
|
|
433
436
|
const t = applyGuardTrim(working, anchoredWorking);
|
|
434
437
|
return { working, trimmed: t.trimmed, trimDroppedMessages: t.dropped };
|
|
435
438
|
}
|
|
439
|
+
function restoredAbsPathsOf(restored, root) {
|
|
440
|
+
const out = [];
|
|
441
|
+
for (const key of [...restored.filesChanged, ...restored.failed.map((f) => f.path)]) {
|
|
442
|
+
const abs = resolveTrackKey(root, key);
|
|
443
|
+
if (abs.ok)
|
|
444
|
+
out.push(abs.abs);
|
|
445
|
+
}
|
|
446
|
+
return out;
|
|
447
|
+
}
|
|
448
|
+
function resolveWiredFileHistoryStore(candidate) {
|
|
449
|
+
if (candidate === undefined)
|
|
450
|
+
return undefined;
|
|
451
|
+
const verbs = ["trackEdit", "annulTrack", "snapshot", "restore", "canRestore", "reap", "adoptScope"];
|
|
452
|
+
const verbOf = (v) => {
|
|
453
|
+
try {
|
|
454
|
+
return candidate[v];
|
|
455
|
+
}
|
|
456
|
+
catch {
|
|
457
|
+
return undefined;
|
|
458
|
+
}
|
|
459
|
+
};
|
|
460
|
+
const probeable = (typeof candidate === "object" && candidate !== null) || typeof candidate === "function";
|
|
461
|
+
const missing = probeable ? verbs.filter((v) => typeof verbOf(v) !== "function") : [...verbs];
|
|
462
|
+
if (missing.length > 0) {
|
|
463
|
+
const shape = candidate === null ? "null" : probeable ? "a value that is not a FileHistoryStore" : `a ${typeof candidate}`;
|
|
464
|
+
const e = new Error(`RunnerDeps.fileHistoryStore was wired with ${shape} — missing contract verbs: ${missing.join(", ")}. Refusing prepare rather than half-wiring the rewind seat (a present-but-unusable store makes every Edit/Write/NotebookEdit fail its first-touch backup while restore requests report "no store wired"). Omit the key to run without file history.`);
|
|
465
|
+
e.code = "config.invalid_file_history_store";
|
|
466
|
+
throw e;
|
|
467
|
+
}
|
|
468
|
+
return candidate;
|
|
469
|
+
}
|
|
470
|
+
const LEGACY_PROBE_TIMEOUT_MS = 2_000;
|
|
471
|
+
const LEGACY_PROBE_TIMED_OUT = Symbol("legacy-rewind-probe-timeout");
|
|
472
|
+
async function legacyRewindEpochTail(deps, sessionId, entryId, form) {
|
|
473
|
+
const probe = deps.legacyRewindBoundaryProbe;
|
|
474
|
+
let verdict;
|
|
475
|
+
if (probe !== undefined) {
|
|
476
|
+
try {
|
|
477
|
+
let timer;
|
|
478
|
+
const timeout = new Promise((resolve) => {
|
|
479
|
+
timer = setTimeout(() => resolve(LEGACY_PROBE_TIMED_OUT), LEGACY_PROBE_TIMEOUT_MS);
|
|
480
|
+
});
|
|
481
|
+
try {
|
|
482
|
+
verdict = await Promise.race([Promise.resolve(probe({ sessionId, entryId })), timeout]);
|
|
483
|
+
}
|
|
484
|
+
finally {
|
|
485
|
+
clearTimeout(timer);
|
|
486
|
+
}
|
|
487
|
+
if (verdict === LEGACY_PROBE_TIMED_OUT) {
|
|
488
|
+
verdict = undefined;
|
|
489
|
+
try {
|
|
490
|
+
deps.onError?.(new Error(`RunnerDeps.legacyRewindBoundaryProbe did not answer within ${LEGACY_PROBE_TIMEOUT_MS}ms while explaining a rewind refusal — the refusal stands and names both possibilities`), { phase: "rewind", sessionId });
|
|
491
|
+
}
|
|
492
|
+
catch {
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
catch (err) {
|
|
497
|
+
verdict = undefined;
|
|
498
|
+
try {
|
|
499
|
+
deps.onError?.(new Error(`RunnerDeps.legacyRewindBoundaryProbe threw while explaining a rewind refusal (${err.message}) — the refusal stands and names both possibilities`), { phase: "rewind", sessionId });
|
|
500
|
+
}
|
|
501
|
+
catch {
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
if (verdict !== undefined && typeof verdict !== "boolean") {
|
|
505
|
+
try {
|
|
506
|
+
deps.onError?.(new Error(`RunnerDeps.legacyRewindBoundaryProbe answered ${JSON.stringify(String(verdict))} for entry "${entryId}" — only true/false/undefined are meaningful, so the refusal names both possibilities instead of trusting it`), { phase: "rewind", sessionId });
|
|
507
|
+
}
|
|
508
|
+
catch {
|
|
509
|
+
}
|
|
510
|
+
verdict = undefined;
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
if (verdict === true) {
|
|
514
|
+
return `This deployment's legacy-epoch probe reports that entry "${entryId}" DOES carry a boundary from the retired whole-tree snapshot era, which this engine's per-edited-file seat does not restore — the two epochs are not interchangeable (a whole-tree manifest carries no tracked-set provenance, so replaying it here would converge files this session never edited). Restore it with the whole-tree-era tooling this deployment kept, or re-run the turns under the current engine.`;
|
|
515
|
+
}
|
|
516
|
+
if (verdict === false) {
|
|
517
|
+
return `This deployment's legacy-epoch probe reports no whole-tree-era boundary for entry "${entryId}" either, so the boundary simply does not exist: its turns ran without a RunnerDeps.fileHistoryStore wired, or it was reaped.`;
|
|
518
|
+
}
|
|
519
|
+
return form === "keyed"
|
|
520
|
+
? `Boundaries are keyed by a turn's INITIAL entry and exist only for turns that ran with a RunnerDeps.fileHistoryStore wired; a boundary from the retired whole-tree snapshot era is not restorable by this seat, and reaped boundaries have none.`
|
|
521
|
+
: `Either the boundary does not exist (its turns ran without a RunnerDeps.fileHistoryStore, or it was reaped), or it was produced in the retired whole-tree snapshot era, which this engine's per-edited-file seat does not restore.`;
|
|
522
|
+
}
|
|
523
|
+
const FILE_HISTORY_BOUNDARY_TIMEOUT_MS = 30_000;
|
|
524
|
+
const FILE_HISTORY_CARRY_MEMO = new WeakMap();
|
|
525
|
+
async function adoptForkedFileHistory(store, session, sessionId, onError) {
|
|
526
|
+
const memo = FILE_HISTORY_CARRY_MEMO.get(store) ?? { settled: new Set(), disclosed: new Set(), inFlight: new Map() };
|
|
527
|
+
FILE_HISTORY_CARRY_MEMO.set(store, memo);
|
|
528
|
+
const discloseOnce = (err) => {
|
|
529
|
+
if (memo.disclosed.has(sessionId))
|
|
530
|
+
return;
|
|
531
|
+
memo.disclosed.add(sessionId);
|
|
532
|
+
onError?.(err, { phase: "rewind", sessionId });
|
|
533
|
+
};
|
|
534
|
+
try {
|
|
535
|
+
if (memo.settled.has(sessionId))
|
|
536
|
+
return;
|
|
537
|
+
const forkedFrom = (await session.getMetadata()).forkedFrom;
|
|
538
|
+
if (forkedFrom === undefined || forkedFrom === sessionId)
|
|
539
|
+
return;
|
|
540
|
+
const shared = memo.inFlight.get(sessionId);
|
|
541
|
+
if (shared !== undefined)
|
|
542
|
+
return await shared;
|
|
543
|
+
if (memo.settled.has(sessionId))
|
|
544
|
+
return;
|
|
545
|
+
const attempt = store.adoptScope(forkedFrom, sessionId).then((carried) => {
|
|
546
|
+
if (carried.ok || carried.error.code === "conflict") {
|
|
547
|
+
memo.settled.add(sessionId);
|
|
548
|
+
return;
|
|
549
|
+
}
|
|
550
|
+
discloseOnce(new Error(`file-history fork carry from session "${forkedFrom}" failed (${carried.error.code}): ${carried.error.message} — this forked session starts with an EMPTY rewind history, so boundaries recorded before the fork are not restorable from it (the run itself proceeds; the carry is retried on this session's next turn while its scope is still empty)`));
|
|
551
|
+
}, (err) => discloseOnce(err));
|
|
552
|
+
memo.inFlight.set(sessionId, attempt);
|
|
553
|
+
try {
|
|
554
|
+
await attempt;
|
|
555
|
+
}
|
|
556
|
+
finally {
|
|
557
|
+
memo.inFlight.delete(sessionId);
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
catch (err) {
|
|
561
|
+
try {
|
|
562
|
+
discloseOnce(err);
|
|
563
|
+
}
|
|
564
|
+
catch {
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
function createFileHistoryBoundarySeat(opts) {
|
|
569
|
+
let inFlight;
|
|
570
|
+
let begun = false;
|
|
571
|
+
return {
|
|
572
|
+
begin(entryId) {
|
|
573
|
+
if (begun)
|
|
574
|
+
return;
|
|
575
|
+
begun = true;
|
|
576
|
+
const ac = new AbortController();
|
|
577
|
+
let timer;
|
|
578
|
+
const timeout = new Promise((resolve) => {
|
|
579
|
+
timer = setTimeout(() => {
|
|
580
|
+
ac.abort();
|
|
581
|
+
resolve({ ok: false });
|
|
582
|
+
}, FILE_HISTORY_BOUNDARY_TIMEOUT_MS);
|
|
583
|
+
});
|
|
584
|
+
let work;
|
|
585
|
+
try {
|
|
586
|
+
work = opts.store.snapshot(opts.sessionId, entryId, opts.env, opts.root, ac.signal);
|
|
587
|
+
}
|
|
588
|
+
catch (err) {
|
|
589
|
+
work = Promise.resolve({ ok: false, error: { code: "snapshot_failed", message: `history store threw synchronously: ${err.message}` } });
|
|
590
|
+
}
|
|
591
|
+
work.catch(() => { });
|
|
592
|
+
inFlight = Promise.race([
|
|
593
|
+
work.then((r) => (r.ok ? undefined : `boundary capture failed (${r.error.code}): ${r.error.message}`)),
|
|
594
|
+
timeout.then(() => `boundary capture timed out after ${FILE_HISTORY_BOUNDARY_TIMEOUT_MS / 1000}s (fenced — the attempt can never publish)`),
|
|
595
|
+
])
|
|
596
|
+
.then((failure) => {
|
|
597
|
+
if (failure !== undefined) {
|
|
598
|
+
try {
|
|
599
|
+
opts.onError?.(new Error(`file-history ${failure} — this turn has no boundary and cannot be rewound to (the turn itself proceeds)`), { phase: "rewind", sessionId: opts.sessionId });
|
|
600
|
+
}
|
|
601
|
+
catch {
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
})
|
|
605
|
+
.catch((err) => {
|
|
606
|
+
try {
|
|
607
|
+
opts.onError?.(err, { phase: "rewind", sessionId: opts.sessionId });
|
|
608
|
+
}
|
|
609
|
+
catch {
|
|
610
|
+
}
|
|
611
|
+
})
|
|
612
|
+
.finally(() => clearTimeout(timer));
|
|
613
|
+
},
|
|
614
|
+
async settle() {
|
|
615
|
+
if (inFlight !== undefined)
|
|
616
|
+
await inFlight;
|
|
617
|
+
},
|
|
618
|
+
};
|
|
619
|
+
}
|
|
436
620
|
export function gatedCallIdOf(p) {
|
|
437
621
|
if (p.suspendRef.token !== undefined)
|
|
438
622
|
return p.suspendRef.gatedCallId;
|
|
@@ -508,7 +692,7 @@ function createDenyObserverNotifier(hooks, hookTimeoutMs, signal, report) {
|
|
|
508
692
|
}
|
|
509
693
|
};
|
|
510
694
|
}
|
|
511
|
-
function mcpRevocationWiring(deps) {
|
|
695
|
+
function mcpRevocationWiring(deps, runId) {
|
|
512
696
|
if (deps.mcpRevocations === undefined)
|
|
513
697
|
return undefined;
|
|
514
698
|
const ledger = deps.mcpRevocations;
|
|
@@ -517,7 +701,7 @@ function mcpRevocationWiring(deps) {
|
|
|
517
701
|
onProbeFailure: (e) => deliverEngineNotice(deps.onNotice, {
|
|
518
702
|
code: "mcp.revocation_probe_failed",
|
|
519
703
|
message: `the mcpRevocations.isRevoked probe threw — MCP dispatch fails OPEN (no server treated as revoked) until the probe recovers: ${e instanceof Error ? e.message : String(e)}`,
|
|
520
|
-
detail: { message: e instanceof Error ? e.message : String(e) },
|
|
704
|
+
detail: { message: e instanceof Error ? e.message : String(e), runId },
|
|
521
705
|
}),
|
|
522
706
|
};
|
|
523
707
|
}
|
|
@@ -674,43 +858,69 @@ async function derivedRouteFallsBack(args) {
|
|
|
674
858
|
const verdict = await adjudicateDerivedRoute({ brain: args.brain, model: args.derived, getApiKeyAndHeaders: args.getApiKeyAndHeaders });
|
|
675
859
|
if (verdict === undefined || verdict.ok)
|
|
676
860
|
return false;
|
|
677
|
-
deliverEngineNotice(args.onNotice, fallbackToPrimaryNotice({ seat: args.seat, from: args.derived.id, to: args.primary.id, verdict, ...(args.sessionId !== undefined ? { sessionId: args.sessionId } : {}) }));
|
|
861
|
+
deliverEngineNotice(args.onNotice, fallbackToPrimaryNotice({ seat: args.seat, from: args.derived.id, to: args.primary.id, verdict, ...(args.sessionId !== undefined ? { sessionId: args.sessionId } : {}), ...(args.runId !== undefined ? { runId: args.runId } : {}) }));
|
|
678
862
|
return true;
|
|
679
863
|
}
|
|
680
864
|
catch {
|
|
681
865
|
return false;
|
|
682
866
|
}
|
|
683
867
|
}
|
|
684
|
-
function mintPlacementRootSessionId(
|
|
685
|
-
|
|
686
|
-
if (placementRootSessionId === "") {
|
|
868
|
+
function mintPlacementRootSessionId(placementRootResolved) {
|
|
869
|
+
if (placementRootResolved === "") {
|
|
687
870
|
const e = new Error("placement root resolved EMPTY (internals.placementRoot / internals.rootSessionId carries an empty string) — an empty fixed point cannot key a placement lookup; fix the spawning lane instead of defaulting around it.");
|
|
688
871
|
e.code = "config.placement_root_invalid";
|
|
689
872
|
throw e;
|
|
690
873
|
}
|
|
691
|
-
return
|
|
874
|
+
return placementRootResolved;
|
|
875
|
+
}
|
|
876
|
+
function restorePlacementRoot(internals, seedPlacementRoot) {
|
|
877
|
+
if (internals?.placementRoot !== undefined)
|
|
878
|
+
return internals;
|
|
879
|
+
const seed = placementValueOrAbsent(seedPlacementRoot);
|
|
880
|
+
if (seed === undefined)
|
|
881
|
+
return internals;
|
|
882
|
+
return { ...(internals ?? {}), placementRoot: seed };
|
|
883
|
+
}
|
|
884
|
+
export function placementValueOrAbsent(value) {
|
|
885
|
+
return value || undefined;
|
|
886
|
+
}
|
|
887
|
+
function stampPlacementRootSessionId(placementRootResolved) {
|
|
888
|
+
return placementValueOrAbsent(placementRootResolved);
|
|
889
|
+
}
|
|
890
|
+
function explicitlyDeferredMemoryTrio(mounted, roster, deferNames) {
|
|
891
|
+
return mounted ? MEMORY_ENGINE_TOOL_NAMES.filter((n) => roster.some((t) => t.name === n) && (deferNames ?? []).includes(n)) : [];
|
|
892
|
+
}
|
|
893
|
+
function memoryGroupRetractionSet(builtinDeferPairNames, engineTrioInPlay) {
|
|
894
|
+
return new Set([...builtinDeferPairNames, ...(engineTrioInPlay ? MEMORY_ENGINE_TOOL_NAMES : [])]);
|
|
895
|
+
}
|
|
896
|
+
function refuseRequireExistingWithoutSession(spec) {
|
|
897
|
+
if (spec.requireExistingSession && !spec.sessionId) {
|
|
898
|
+
const e = new Error(`requireExistingSession requires a sessionId — cannot require an existing session without one (design/114 Phase3)`);
|
|
899
|
+
e.code = "resume.session_not_found";
|
|
900
|
+
throw e;
|
|
901
|
+
}
|
|
692
902
|
}
|
|
693
|
-
export async function prepareTask(spec, deps, sessions, resume, internals, runnerSelf) {
|
|
903
|
+
export async function prepareTask(spec, deps, sessions, resume, internals, runnerSelf, runIdSink) {
|
|
904
|
+
const runId = uuidv7();
|
|
905
|
+
if (runIdSink !== undefined)
|
|
906
|
+
runIdSink.runId = runId;
|
|
694
907
|
const doors = prepareConfigDoors({ spec, deps, sessions, resume, internals });
|
|
695
908
|
spec = doors.spec;
|
|
696
|
-
const { toolFaceSnapshot, promptProfile, lockedPreflight, resolvedInteractionPosture, microCompactKnob, resolvedRole, model, thinking, compModel, fableMitigations, memoryDelegationEvidence, memoryProvenance, usageWindows, brainCallGuardrailRef, brainCallGuardrailMs } = doors;
|
|
909
|
+
const { toolFaceSnapshot, promptProfile, lockedPreflight, resolvedInteractionPosture, microCompactKnob, resolvedRole, model, thinking, compModel, fableMitigations, memoryDelegationEvidence, memoryProvenance, memoryCapturePolicy, usageWindows, brainCallGuardrailRef, brainCallGuardrailMs } = doors;
|
|
697
910
|
announceToolModelGate(deps.onNotice, model.id, doors.modelGate);
|
|
698
911
|
const { toolEffects, egressTools, irreversibleTools, irreversibilityTier, axisExplicitNegatives, reversibilityProbes, ownToolNames } = prepareSafetyScan({ spec, deps });
|
|
699
912
|
let shellGatedBash = false;
|
|
700
913
|
let shellGatedMonitor = false;
|
|
701
|
-
|
|
702
|
-
const e = new Error(`requireExistingSession requires a sessionId — cannot require an existing session without one (design/114 Phase3)`);
|
|
703
|
-
e.code = "resume.session_not_found";
|
|
704
|
-
throw e;
|
|
705
|
-
}
|
|
914
|
+
refuseRequireExistingWithoutSession(spec);
|
|
706
915
|
const { acquired, session, conflictRef, wakeRecovered, resumeAtBeforeParentId } = await prepareAcquireReconcile({ sessions, spec, resume, toolEffects, ...(internals?.sessionPlacement !== undefined ? { placement: internals.sessionPlacement } : {}), ...(() => { const g = durableParkGapFor(deps, spec); return g !== undefined ? { durableParkGap: g } : {}; })() });
|
|
707
916
|
const sessionId = acquired.sessionId;
|
|
708
917
|
const hostTaskId = spec.taskId ?? sessionId;
|
|
709
918
|
const delegation = effectiveDelegationFacts(internals, resume?.seed.isDelegatedChild);
|
|
919
|
+
const placementRootResolved = (internals = restorePlacementRoot(internals, resume?.seed.placementRootSessionId))?.placementRoot ?? internals?.rootSessionId ?? sessionId;
|
|
710
920
|
let effectiveCompModel = compModel;
|
|
711
921
|
if (spec.compactionModel === undefined &&
|
|
712
922
|
compModel !== undefined &&
|
|
713
|
-
(await derivedRouteFallsBack({ seat: "compaction-summary", derived: compModel, primary: model, brain: deps.brain, getApiKeyAndHeaders: spec.getApiKeyAndHeaders, onNotice: deps.onNotice, sessionId }))) {
|
|
923
|
+
(await derivedRouteFallsBack({ seat: "compaction-summary", derived: compModel, primary: model, brain: deps.brain, getApiKeyAndHeaders: spec.getApiKeyAndHeaders, onNotice: deps.onNotice, sessionId, runId }))) {
|
|
714
924
|
effectiveCompModel = undefined;
|
|
715
925
|
}
|
|
716
926
|
warnCompactionWindowHazard(deps.tracer, spec, model, effectiveCompModel, hostTaskId);
|
|
@@ -798,7 +1008,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
798
1008
|
try {
|
|
799
1009
|
ownedEnv = deps.executionEnvFactory
|
|
800
1010
|
? await deps.executionEnvFactory({
|
|
801
|
-
sessionId, placementRootSessionId: mintPlacementRootSessionId(
|
|
1011
|
+
sessionId, placementRootSessionId: mintPlacementRootSessionId(placementRootResolved),
|
|
802
1012
|
taskId: spec.taskId,
|
|
803
1013
|
...(internals?.isolation ? { isolation: internals.isolation } : {}),
|
|
804
1014
|
...(internals?.parentCwd ? { parentCwd: internals.parentCwd } : {}),
|
|
@@ -812,6 +1022,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
812
1022
|
throw factoryErr;
|
|
813
1023
|
}
|
|
814
1024
|
const executionEnv = ownedEnv ?? deps.executionEnv ?? new StubExecutionEnv();
|
|
1025
|
+
const externalContentTargetActive = executionEnv.externalContentTarget === true || resume?.seed.externalContentTarget === true;
|
|
815
1026
|
if (internals?.requestedCwd !== undefined) {
|
|
816
1027
|
const canon = async (p) => {
|
|
817
1028
|
const r = await executionEnv.canonicalPath(p);
|
|
@@ -889,79 +1100,165 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
889
1100
|
}
|
|
890
1101
|
const { taskRootFinal, rebaseRestoredPath } = await prepareWorkspaceRestore({ ownedEnv, deps, spec, internals, resume, taskRootInitial, abortController, sessionId });
|
|
891
1102
|
const rewindNotes = [];
|
|
892
|
-
const
|
|
1103
|
+
const onTrackFailure = deps.onTrackFailure === undefined ? "refuse" : deps.onTrackFailure;
|
|
1104
|
+
if (onTrackFailure !== "refuse" && onTrackFailure !== "proceed-unprotected") {
|
|
1105
|
+
const e = new Error(`RunnerDeps.onTrackFailure must be "refuse" or "proceed-unprotected"; got ${JSON.stringify(deps.onTrackFailure)} — refusing prepare rather than silently defaulting a first-touch-failure policy.`);
|
|
1106
|
+
e.code = "config.invalid_on_track_failure";
|
|
1107
|
+
throw e;
|
|
1108
|
+
}
|
|
1109
|
+
const fileHistoryStore = resolveWiredFileHistoryStore(deps.fileHistoryStore);
|
|
1110
|
+
if (fileHistoryStore !== undefined) {
|
|
1111
|
+
await adoptForkedFileHistory(fileHistoryStore, session, sessionId, deps.onError);
|
|
1112
|
+
}
|
|
1113
|
+
const legacyRewindFiles = spec.rewindFiles;
|
|
1114
|
+
if (legacyRewindFiles === true) {
|
|
1115
|
+
if (spec.resumeAt !== undefined) {
|
|
1116
|
+
const e = new Error(`rewind-files: TaskSpec.rewindFiles is retired (design/381 — rewind now converges the per-edited-file history, not a whole-tree snapshot). This request pairs it with resumeAt, i.e. the RESTORE sense: set restoreFiles: true instead. (The capture sense needs no request anymore — first-touch tracking is always on when a RunnerDeps.fileHistoryStore is wired.)`);
|
|
1117
|
+
e.code = "rewind.rewind_files_retired";
|
|
1118
|
+
throw e;
|
|
1119
|
+
}
|
|
1120
|
+
try {
|
|
1121
|
+
deps.onError?.(new Error(`TaskSpec.rewindFiles (capture sense) is retired and was ignored: per-edited-file first-touch tracking is always on when RunnerDeps.fileHistoryStore is wired, so a per-turn capture request has nothing left to ask for. Drop the field; the restore sense moved to TaskSpec.restoreFiles.`), { phase: "config", sessionId });
|
|
1122
|
+
}
|
|
1123
|
+
catch {
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
if (spec.restoreFiles === true && spec.resumeAt === undefined) {
|
|
1127
|
+
const e = new Error(`rewind-files: restoreFiles: true needs a resumeAt anchor — restoring files means converging them to a specific prior entry's boundary, and this spec names none. Use resumeAt + restoreFiles to move conversation and files together, or rewindFilesTo alone for a code-only restore.`);
|
|
1128
|
+
e.code = "rewind.invalid_spec";
|
|
1129
|
+
throw e;
|
|
1130
|
+
}
|
|
893
1131
|
if (spec.resumeAt !== undefined && spec.rewindFilesTo !== undefined) {
|
|
894
|
-
const e = new Error(`rewind-files: resumeAt ("${spec.resumeAt}") and rewindFilesTo ("${spec.rewindFilesTo}") were both set — resumeAt already anchors the file restore when
|
|
1132
|
+
const e = new Error(`rewind-files: resumeAt ("${spec.resumeAt}") and rewindFilesTo ("${spec.rewindFilesTo}") were both set — resumeAt already anchors the file restore when restoreFiles is true, so a separate rewindFilesTo target is a conflicting request. Drop one of the two.`);
|
|
895
1133
|
e.code = "rewind.conflicting_targets";
|
|
896
1134
|
throw e;
|
|
897
1135
|
}
|
|
898
|
-
let rewindTarget = spec.resumeAt !== undefined ? (
|
|
1136
|
+
let rewindTarget = spec.resumeAt !== undefined ? (spec.restoreFiles === true ? spec.resumeAt : undefined) : spec.rewindFilesTo;
|
|
899
1137
|
const rewindBefore = rewindTarget !== undefined && spec.resumeAt !== undefined && spec.resumeAtMode === "before";
|
|
900
|
-
if (spec.resumeAt !== undefined &&
|
|
1138
|
+
if (spec.resumeAt !== undefined && spec.restoreFiles !== true) {
|
|
901
1139
|
rewindNotes.push({
|
|
902
1140
|
code: "conversation_only",
|
|
903
|
-
message: `the conversation was branched at entry "${spec.resumeAt}" but the working tree was NOT rewound — this task set resumeAt without
|
|
1141
|
+
message: `the conversation was branched at entry "${spec.resumeAt}" but the working tree was NOT rewound — this task set resumeAt without restoreFiles, so files remain at their current state`,
|
|
904
1142
|
});
|
|
905
1143
|
}
|
|
906
|
-
|
|
1144
|
+
const fileHistoryEnabled = fileHistoryStore !== undefined && handsEnabled;
|
|
1145
|
+
let historyRoot = taskRootFinal;
|
|
1146
|
+
if (fileHistoryEnabled) {
|
|
1147
|
+
const canonRoot = await executionEnv.canonicalPath(taskRootFinal);
|
|
1148
|
+
if (canonRoot.ok)
|
|
1149
|
+
historyRoot = canonRoot.value;
|
|
1150
|
+
}
|
|
1151
|
+
if (fileHistoryStore === undefined) {
|
|
907
1152
|
if (rewindTarget !== undefined) {
|
|
908
|
-
const e = new Error(`rewind-files: restoring
|
|
1153
|
+
const e = new Error(`rewind-files: restoring files to entry "${rewindTarget}" requires a history backend, but this deployment wired no RunnerDeps.fileHistoryStore — no file history was ever recorded, so the files were NOT rewound`);
|
|
909
1154
|
e.code = "rewind.store_unconfigured";
|
|
910
1155
|
throw e;
|
|
911
1156
|
}
|
|
912
|
-
if (rewindCaptureRequested) {
|
|
913
|
-
rewindNotes.push({
|
|
914
|
-
code: "snapshot_store_unconfigured",
|
|
915
|
-
message: "rewindFiles was requested but no RunnerDeps.fileSnapshotStore is wired — no working-tree snapshot was captured for this turn, so it cannot be rewound to later",
|
|
916
|
-
});
|
|
917
|
-
}
|
|
918
1157
|
}
|
|
919
1158
|
else if (!handsEnabled) {
|
|
920
|
-
if (rewindTarget !== undefined
|
|
1159
|
+
if (rewindTarget !== undefined) {
|
|
921
1160
|
rewindNotes.push({
|
|
922
1161
|
code: "files_env_unsupported",
|
|
923
|
-
message: "the file side of rewind was inert: this deployment mounts no filesystem-capable ExecutionEnv, so no
|
|
1162
|
+
message: "the file side of rewind was inert: this deployment mounts no filesystem-capable ExecutionEnv, so no file history was recorded or restored",
|
|
924
1163
|
});
|
|
925
1164
|
}
|
|
926
1165
|
}
|
|
927
|
-
|
|
1166
|
+
const legacyEpochTail = (entryId, form = "at-or-above") => legacyRewindEpochTail(deps, sessionId, entryId, form);
|
|
1167
|
+
let restoredFilePaths = [];
|
|
1168
|
+
if (rewindTarget !== undefined && fileHistoryStore !== undefined && handsEnabled) {
|
|
1169
|
+
const historyStore = fileHistoryStore;
|
|
928
1170
|
if (rewindBefore) {
|
|
929
1171
|
let anchor;
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
1172
|
+
if (await historyStore.canRestore(sessionId, rewindTarget)) {
|
|
1173
|
+
anchor = rewindTarget;
|
|
1174
|
+
}
|
|
1175
|
+
else {
|
|
1176
|
+
const walked = new Set();
|
|
1177
|
+
let cursor = resumeAtBeforeParentId;
|
|
1178
|
+
while (cursor !== null && !walked.has(cursor)) {
|
|
1179
|
+
walked.add(cursor);
|
|
1180
|
+
if (await historyStore.canRestore(sessionId, cursor)) {
|
|
1181
|
+
anchor = cursor;
|
|
1182
|
+
break;
|
|
1183
|
+
}
|
|
1184
|
+
cursor = (await session.getEntry(cursor))?.parentId ?? null;
|
|
937
1185
|
}
|
|
938
|
-
cursor = (await session.getEntry(cursor))?.parentId ?? null;
|
|
939
1186
|
}
|
|
940
1187
|
if (anchor === undefined) {
|
|
941
|
-
const e = new Error(`rewind-files: no file
|
|
1188
|
+
const e = new Error(`rewind-files: no file-history boundary exists at or above the "before" branch point on session "${sessionId}" — cannot restore files consistent with the rewound context. ${await legacyEpochTail(rewindTarget)}`);
|
|
942
1189
|
e.code = "rewind_snapshot.unresolvable";
|
|
943
1190
|
throw e;
|
|
944
1191
|
}
|
|
945
1192
|
rewindTarget = anchor;
|
|
946
1193
|
}
|
|
947
|
-
const restoreRoot =
|
|
1194
|
+
const restoreRoot = historyRoot;
|
|
948
1195
|
const restoreSignal = spec.signal ? AbortSignal.any([abortController.signal, spec.signal]) : abortController.signal;
|
|
949
|
-
const restored = await
|
|
950
|
-
|
|
951
|
-
|
|
1196
|
+
const restored = await historyStore.restore(sessionId, rewindTarget, executionEnv, restoreRoot, restoreSignal);
|
|
1197
|
+
const ledgerLine = (r) => `applied ${r.filesChanged.length}, identical ${r.identicalSkipped.length}, refused ${r.refused.length}${r.refused.length > 0 ? ` (${r.refused.map((f) => `${f.path}: ${f.reason}`).join("; ")})` : ""}, failed ${r.failed.length}${r.failed.length > 0 ? ` (${r.failed.map((f) => `${f.path}: ${f.reason}`).join("; ")})` : ""}`;
|
|
1198
|
+
if (restored.outcome === "failed") {
|
|
1199
|
+
if (restored.error?.code === "not_found") {
|
|
952
1200
|
const e = new Error(rewindBefore
|
|
953
|
-
? `rewind-files: the resolved "before"
|
|
954
|
-
: `rewind-files: no file
|
|
1201
|
+
? `rewind-files: the resolved "before" history anchor "${rewindTarget}" disappeared before restore — files were NOT rewound`
|
|
1202
|
+
: `rewind-files: no file-history boundary exists for entry "${rewindTarget}" on session "${sessionId}" — the working tree was NOT rewound. ${await legacyEpochTail(rewindTarget, "keyed")}`);
|
|
955
1203
|
e.code = "rewind_snapshot.unresolvable";
|
|
956
1204
|
throw e;
|
|
957
1205
|
}
|
|
1206
|
+
const e = new Error(`rewind-files restore failed (${restored.error?.code ?? "restore_failed"}): ${restored.error?.message ?? "unknown"} — ledger: ${ledgerLine(restored)}`);
|
|
1207
|
+
e.code = "rewind.restore_failed";
|
|
1208
|
+
throw e;
|
|
1209
|
+
}
|
|
1210
|
+
if (restored.outcome === "partial") {
|
|
1211
|
+
if (spec.acceptPartialRestore === true) {
|
|
1212
|
+
rewindNotes.push({
|
|
1213
|
+
code: "restore_partial",
|
|
1214
|
+
message: `file restore to entry "${rewindTarget}" was PARTIAL and was tolerated by acceptPartialRestore — ledger: ${ledgerLine(restored)}. Re-running the same restore converges (per-file idempotent).`,
|
|
1215
|
+
});
|
|
1216
|
+
}
|
|
958
1217
|
else {
|
|
959
|
-
const e = new Error(`rewind-files restore
|
|
1218
|
+
const e = new Error(`rewind-files: restore to entry "${rewindTarget}" was PARTIAL — ledger: ${ledgerLine(restored)}. The task is refused rather than run on a mixed-state tree (set acceptPartialRestore: true to tolerate and disclose instead); re-running the same restore converges (per-file idempotent).`);
|
|
960
1219
|
e.code = "rewind.restore_failed";
|
|
961
1220
|
throw e;
|
|
962
1221
|
}
|
|
963
1222
|
}
|
|
1223
|
+
restoredFilePaths = restoredAbsPathsOf(restored, restoreRoot);
|
|
964
1224
|
}
|
|
1225
|
+
const trackFileEdit = fileHistoryEnabled
|
|
1226
|
+
? async (req) => {
|
|
1227
|
+
const r = await fileHistoryStore.trackEdit(sessionId, req.key, executionEnv, historyRoot, req.signal);
|
|
1228
|
+
if (r.ok) {
|
|
1229
|
+
if (!r.minted)
|
|
1230
|
+
return { ok: true };
|
|
1231
|
+
return {
|
|
1232
|
+
ok: true,
|
|
1233
|
+
annul: async (proof) => {
|
|
1234
|
+
const a = await fileHistoryStore.annulTrack(sessionId, req.key, historyRoot, proof === "verify" ? { env: executionEnv, ...(req.signal !== undefined ? { signal: req.signal } : {}) } : undefined);
|
|
1235
|
+
if (a.ok)
|
|
1236
|
+
return;
|
|
1237
|
+
try {
|
|
1238
|
+
deps.onError?.(new Error(`file-history could not retract the first-touch record for "${req.key}" after its edit failed to land (${a.error.code}: ${a.error.message}) — the path stays tracked, so a rewind to a boundary below it may converge bytes this engine never wrote`), { phase: "rewind", sessionId });
|
|
1239
|
+
}
|
|
1240
|
+
catch {
|
|
1241
|
+
}
|
|
1242
|
+
},
|
|
1243
|
+
};
|
|
1244
|
+
}
|
|
1245
|
+
if (onTrackFailure === "proceed-unprotected") {
|
|
1246
|
+
try {
|
|
1247
|
+
deps.onError?.(new Error(`file-history first-touch backup for "${req.key}" failed (${r.error.code}: ${r.error.message}) — proceeding UNPROTECTED per RunnerDeps.onTrackFailure: the pristine promise for this path is void, and only in this process's memory (no durable trace exists, so after a process restart the next edit can still mint already-modified bytes as pristine v1)`), { phase: "rewind", sessionId });
|
|
1248
|
+
}
|
|
1249
|
+
catch {
|
|
1250
|
+
}
|
|
1251
|
+
return { ok: true };
|
|
1252
|
+
}
|
|
1253
|
+
return {
|
|
1254
|
+
ok: false,
|
|
1255
|
+
refusal: `Error (${req.tool}): the edit was refused because its first-touch file-history backup could not be persisted (${r.error.code}: ${r.error.message}). Proceeding would leave "${req.path}" with no durable pristine record — after the history store recovers, a retried edit would mint already-modified bytes as the pristine baseline. Retry when the file-history store is healthy.`,
|
|
1256
|
+
};
|
|
1257
|
+
}
|
|
1258
|
+
: undefined;
|
|
1259
|
+
const fileHistoryBoundary = fileHistoryEnabled
|
|
1260
|
+
? createFileHistoryBoundarySeat({ store: fileHistoryStore, sessionId, env: executionEnv, root: historyRoot, onError: deps.onError })
|
|
1261
|
+
: undefined;
|
|
965
1262
|
const harnessRef = {};
|
|
966
1263
|
const skillScope = new ActiveSkillScope();
|
|
967
1264
|
const forwardSink = internals?.onForwardEvent;
|
|
@@ -1103,7 +1400,9 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1103
1400
|
...(frozenOnAsk !== undefined ? { onAsk: frozenOnAsk } : {}),
|
|
1104
1401
|
...(durableMandate ? { durableMandate: true } : {}),
|
|
1105
1402
|
...(contentMandate ? { contentMandate: true } : {}),
|
|
1106
|
-
...(autoModeDecider !== undefined
|
|
1403
|
+
...(autoModeDecider !== undefined
|
|
1404
|
+
? { autoMode: { decider: autoModeDecider, ...(autoModeArming !== undefined ? { arming: autoModeArming } : {}) } }
|
|
1405
|
+
: {}),
|
|
1107
1406
|
},
|
|
1108
1407
|
]
|
|
1109
1408
|
: [];
|
|
@@ -1117,7 +1416,9 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1117
1416
|
...(frozenOnAsk !== undefined ? { onAsk: frozenOnAsk } : {}),
|
|
1118
1417
|
...(durableMandate ? { durableMandate: true } : {}),
|
|
1119
1418
|
...(contentMandate ? { contentMandate: true } : {}),
|
|
1120
|
-
...(autoModeDecider !== undefined
|
|
1419
|
+
...(autoModeDecider !== undefined
|
|
1420
|
+
? { autoMode: { decider: autoModeDecider, ...(autoModeArming !== undefined ? { arming: autoModeArming } : {}) } }
|
|
1421
|
+
: {}),
|
|
1121
1422
|
},
|
|
1122
1423
|
]
|
|
1123
1424
|
: []),
|
|
@@ -1141,6 +1442,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1141
1442
|
spec.handsReadOnly !== true &&
|
|
1142
1443
|
!(toolFaceSnapshot.exclude?.includes("Bash") ?? false);
|
|
1143
1444
|
let autoModeDecider;
|
|
1445
|
+
let autoModeArming;
|
|
1144
1446
|
const delegationEntryCapsResolved = resolveDelegationEntryCaps(deps.delegationEntryCaps);
|
|
1145
1447
|
const enrichSpecToolCtx = (ctx) => ({
|
|
1146
1448
|
...ctx,
|
|
@@ -1166,6 +1468,19 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1166
1468
|
...(spec.additionalReadDirectories !== undefined ? { additionalReadDirectories: Object.freeze([...spec.additionalReadDirectories]) } : {}),
|
|
1167
1469
|
...(spec.envFacts !== undefined ? { envFacts: { ...spec.envFacts } } : {}),
|
|
1168
1470
|
...(spec.memoryPersistenceCapable !== undefined ? { memoryPersistenceCapable: spec.memoryPersistenceCapable } : {}),
|
|
1471
|
+
get memoryCaptureOptedOut() {
|
|
1472
|
+
return memoryEngineSession?.captureOptOut?.optedOut() === true;
|
|
1473
|
+
},
|
|
1474
|
+
get memoryCaptureIndeterminate() {
|
|
1475
|
+
return memoryEngineSession?.captureOptOut?.indeterminate() === true;
|
|
1476
|
+
},
|
|
1477
|
+
get memoryCaptureControlDir() {
|
|
1478
|
+
return memoryEngineSession?.engine.controlPlaneDir;
|
|
1479
|
+
},
|
|
1480
|
+
get memoryCaptureAncestors() {
|
|
1481
|
+
const ctl = memoryEngineSession?.engine.controlPlaneDir;
|
|
1482
|
+
return [...(internals?.memoryCaptureAncestors ?? []), { sessionId, ...(ctl !== undefined ? { controlDir: ctl } : {}) }];
|
|
1483
|
+
},
|
|
1169
1484
|
getApiKeyAndHeaders: spec.getApiKeyAndHeaders,
|
|
1170
1485
|
parentCwd: taskRootFinal,
|
|
1171
1486
|
reminderMark,
|
|
@@ -1244,6 +1559,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1244
1559
|
}
|
|
1245
1560
|
}
|
|
1246
1561
|
let runtimeCaps;
|
|
1562
|
+
let runtimeCapsFaulted = false;
|
|
1247
1563
|
if (deps.runtimeCapsResolver) {
|
|
1248
1564
|
try {
|
|
1249
1565
|
runtimeCaps = (await deps.runtimeCapsResolver(spec.principal)) ?? undefined;
|
|
@@ -1251,6 +1567,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1251
1567
|
catch (err) {
|
|
1252
1568
|
deps.onError?.(err instanceof Error ? err : new Error(String(err)), { phase: "config", sessionId });
|
|
1253
1569
|
runtimeCaps = { allowWorkflows: false, allowFork: false };
|
|
1570
|
+
runtimeCapsFaulted = true;
|
|
1254
1571
|
}
|
|
1255
1572
|
}
|
|
1256
1573
|
let complianceDenies = new Set();
|
|
@@ -1297,7 +1614,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1297
1614
|
catch {
|
|
1298
1615
|
classifierModel = model;
|
|
1299
1616
|
}
|
|
1300
|
-
if (await derivedRouteFallsBack({ seat: "auto-mode-classifier", derived: classifierModel, primary: model, brain: deps.brain, getApiKeyAndHeaders: spec.getApiKeyAndHeaders, onNotice: deps.onNotice, sessionId })) {
|
|
1617
|
+
if (await derivedRouteFallsBack({ seat: "auto-mode-classifier", derived: classifierModel, primary: model, brain: deps.brain, getApiKeyAndHeaders: spec.getApiKeyAndHeaders, onNotice: deps.onNotice, sessionId, runId })) {
|
|
1301
1618
|
classifierModel = model;
|
|
1302
1619
|
}
|
|
1303
1620
|
const classifierSystemPrompt = buildAutoModePrompt(am);
|
|
@@ -1322,6 +1639,17 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1322
1639
|
.join("");
|
|
1323
1640
|
},
|
|
1324
1641
|
});
|
|
1642
|
+
if (am.persistArming === true) {
|
|
1643
|
+
autoModeArming = autoModeArmingRecipeOf(am, {
|
|
1644
|
+
promptDigest: `apv1:${createHash("sha256").update(classifierSystemPrompt).digest("hex")}`,
|
|
1645
|
+
});
|
|
1646
|
+
if (autoModeArming === undefined) {
|
|
1647
|
+
deps.onError?.(new Error("RunnerDeps.autoMode.persistArming is set but the auto-mode face did not canonicalize into an arming recipe " +
|
|
1648
|
+
"(a rule list carrying a non-string, or a non-finite/out-of-range timeoutMs / failureThreshold / window bound) — " +
|
|
1649
|
+
"NO arming recipe is recorded on this run's parked constraint chain, and a cross-process redemption keeps the " +
|
|
1650
|
+
"conservative behavior (the ancestor classifier answers unavailable and the inherited ask flows to a human)"), { phase: "config", sessionId });
|
|
1651
|
+
}
|
|
1652
|
+
}
|
|
1325
1653
|
}
|
|
1326
1654
|
const deploymentWorkflowReady = runnerSelf !== undefined && isSelfOrchestrationActive(spec, deps);
|
|
1327
1655
|
const selfOrchestrationActive = deploymentWorkflowReady && runtimeCaps?.allowWorkflows !== false;
|
|
@@ -1369,6 +1697,15 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1369
1697
|
principal: spec.principal,
|
|
1370
1698
|
oneShot: spec.oneShot,
|
|
1371
1699
|
...(resolvedInteractionPosture !== undefined ? { parentInteractionPosture: resolvedInteractionPosture } : {}),
|
|
1700
|
+
parentMemoryCaptureState: () => {
|
|
1701
|
+
const ctl = memoryEngineSession?.engine.controlPlaneDir;
|
|
1702
|
+
return {
|
|
1703
|
+
optedOut: memoryEngineSession?.captureOptOut?.optedOut() === true,
|
|
1704
|
+
indeterminate: memoryEngineSession?.captureOptOut?.indeterminate() === true,
|
|
1705
|
+
...(ctl !== undefined ? { controlDir: ctl } : {}),
|
|
1706
|
+
ancestors: [...(internals?.memoryCaptureAncestors ?? []), { sessionId, ...(ctl !== undefined ? { controlDir: ctl } : {}) }],
|
|
1707
|
+
};
|
|
1708
|
+
},
|
|
1372
1709
|
autoModeReview: () => (autoModeDecider !== undefined ? { decider: autoModeDecider } : undefined),
|
|
1373
1710
|
workflowDepth: internals?.workflowDepth,
|
|
1374
1711
|
parentCwd: taskRootFinal,
|
|
@@ -1447,7 +1784,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1447
1784
|
tools.push(createOutputTool(outputRef, spec.outputSchema, compiled.strict ? compiled.modelSchema : undefined));
|
|
1448
1785
|
}
|
|
1449
1786
|
mcp = lockedPreflight.mcp?.length
|
|
1450
|
-
? await materializeMcpTools(lockedPreflight.mcp, spec.principal, deps.onElicit, deps.mcpImageResizer, { reminderMark, counts: reminderDisclosureCounts }, mcpRevocationWiring(deps))
|
|
1787
|
+
? await materializeMcpTools(lockedPreflight.mcp, spec.principal, deps.onElicit, deps.mcpImageResizer, { reminderMark, counts: reminderDisclosureCounts }, mcpRevocationWiring(deps, runId))
|
|
1451
1788
|
: { tools: [], toolAxes: [], warnings: [], serverInstructions: [], instructionsDelta: { pendingAdds: [], pendingRemovals: [] }, droppedTools: [], statuses: [], refresh: async () => [], dispose: async () => { } };
|
|
1452
1789
|
for (const w of mcp.warnings)
|
|
1453
1790
|
deps.onError?.(w, { phase: "mcp", sessionId });
|
|
@@ -1603,9 +1940,9 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1603
1940
|
foldProtocolAxes(a2a.toolAxes, "A2A");
|
|
1604
1941
|
const callIssuedAtRef = {};
|
|
1605
1942
|
const memoryWriteGateRef = {};
|
|
1606
|
-
const handsReadFaceInput = { handsEnabled, executionEnv, taskRootFinal, rebaseRestoredPath, resume, session, sessionId, hostTaskId, taskScope, fullShellReachable, effectiveShellGate, toolFaceSnapshot, model, spec, deps, internals, memoryWriteGateRef, firstPartyOffload, tools, egressTools, irreversibilityTier, irreversibleTools, reversibilityProbes, reminderMark, reminderDisclosureCounts };
|
|
1943
|
+
const handsReadFaceInput = { handsEnabled, executionEnv, taskRootFinal, rebaseRestoredPath, resume, session, sessionId, hostTaskId, taskScope, fullShellReachable, effectiveShellGate, toolFaceSnapshot, model, spec, deps, internals, memoryWriteGateRef, firstPartyOffload, tools, egressTools, irreversibilityTier, irreversibleTools, reversibilityProbes, reminderMark, reminderDisclosureCounts, ...(trackFileEdit !== undefined ? { trackFileEdit } : {}), ...(restoredFilePaths.length > 0 ? { restoredFilePaths } : {}) };
|
|
1607
1944
|
const handsReadFace = handsEnabled ? await prepareHandsMount(handsReadFaceInput) : resolveHandsLessReadFace(handsReadFaceInput);
|
|
1608
|
-
const { readFileStateForCheckpoint, seedContextFiles, handsCwdRef, workspaceStateSettle, wsSnapshot, rebaseWsPath, backgroundTaskToolsActive, additionalRootsCanonical, additionalReadRootsCanonical, attachmentRootCanonical, readDenyMatcher } = handsReadFace;
|
|
1945
|
+
const { readFileStateForCheckpoint, seedContextFiles, handsCwdRef, workspaceStateSettle, wsSnapshot, rebaseWsPath, backgroundTaskToolsActive, additionalRootsCanonical, additionalReadRootsCanonical, attachmentRootCanonical, readDenyMatcher, envHandToolNames, sealReadStateSeat } = handsReadFace;
|
|
1609
1946
|
resolvedReadFace = handsReadFace.resolvedReadFace;
|
|
1610
1947
|
readDenyAdditionsNormalized = handsReadFace.readDenyAdditionsNormalized;
|
|
1611
1948
|
handsLessResolvedFace = handsReadFace.handsLessResolvedFace;
|
|
@@ -1689,6 +2026,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1689
2026
|
}
|
|
1690
2027
|
if (backgroundTaskToolsActive) {
|
|
1691
2028
|
toolEffects.set("Monitor", "write");
|
|
2029
|
+
envHandToolNames.add("Monitor");
|
|
1692
2030
|
tools.push(firstPartyOffload(createMonitorTool(executionEnv, {
|
|
1693
2031
|
registry: defaultTaskRegistry,
|
|
1694
2032
|
owner: hostTaskId,
|
|
@@ -1724,7 +2062,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1724
2062
|
};
|
|
1725
2063
|
if (workspaceStateSettle !== undefined)
|
|
1726
2064
|
workspaceStateSettle.restoredWorktreeDir = worktreeSessionRef.current?.worktreeDir;
|
|
1727
|
-
tools.push(...createWorktreeTools(executionEnv, { repoRoot: taskRootFinal, cwdRef: handsCwdRef, session: worktreeSessionRef }).map((t) => firstPartyOffload(t)));
|
|
2065
|
+
tools.push(...createWorktreeTools(executionEnv, { repoRoot: taskRootFinal, cwdRef: handsCwdRef, session: worktreeSessionRef }).map((t) => (envHandToolNames.add(t.name), firstPartyOffload(t))));
|
|
1728
2066
|
}
|
|
1729
2067
|
if (offloadStore)
|
|
1730
2068
|
tools.push(createReadToolResultTool(offloadStore));
|
|
@@ -1809,7 +2147,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1809
2147
|
...(spec.principal !== undefined ? { principal: spec.principal } : {}),
|
|
1810
2148
|
...(sessionId !== undefined ? { sessionId } : {}),
|
|
1811
2149
|
requestStopAfterTurn,
|
|
1812
|
-
}));
|
|
2150
|
+
}).map((t) => (envHandToolNames.add(t.name), t)));
|
|
1813
2151
|
}
|
|
1814
2152
|
if (internals?.insideFork !== true &&
|
|
1815
2153
|
runnerSelf &&
|
|
@@ -1823,6 +2161,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1823
2161
|
if (lspManager) {
|
|
1824
2162
|
const lspRoot = taskRootFinal;
|
|
1825
2163
|
tools.push(createLspTool(lspManager, { isPathIgnored: gitCheckIgnoreFilter(executionEnv, lspRoot), env: executionEnv }));
|
|
2164
|
+
envHandToolNames.add("LSP");
|
|
1826
2165
|
}
|
|
1827
2166
|
const lspDiagnostics = spec.lspDiagnostics !== false && lspManager?.diagnostics !== undefined && handsEnabled && spec.handsReadOnly !== true
|
|
1828
2167
|
? lspManager.diagnostics
|
|
@@ -1848,7 +2187,16 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1848
2187
|
const memoryPairExcludedName = MEMORY_ENGINE_TOOL_NAMES.find((n) => (toolFaceSnapshot.exclude ?? []).includes(n));
|
|
1849
2188
|
const memoryPairOccupiedName = MEMORY_ENGINE_TOOL_NAMES.find((n) => memoryPairNameDomain.has(n));
|
|
1850
2189
|
const memorySearchToolsPlanned = memoryPairExcludedName === undefined && memoryPairOccupiedName === undefined;
|
|
1851
|
-
const
|
|
2190
|
+
const captureLineage = await (async () => {
|
|
2191
|
+
try {
|
|
2192
|
+
const ff = (await session.getMetadata()).forkedFrom;
|
|
2193
|
+
return { ...(ff !== undefined && ff !== sessionId ? { origin: ff } : {}), fault: false };
|
|
2194
|
+
}
|
|
2195
|
+
catch {
|
|
2196
|
+
return { fault: true };
|
|
2197
|
+
}
|
|
2198
|
+
})();
|
|
2199
|
+
const { memoryEngineSession, memoryBlock: memoryBlockFromEngine, memoryTools, recallDisciplineSegment: memoryRecallSegment, seedFiles: memorySeedFiles, admittedOrgScopes: memoryAdmittedOrgScopes, ownOrgVerdict: memoryOwnOrgVerdict, effectiveMemoryScopes: memoryEffectiveScopes, } = await prepareMemory({
|
|
1852
2200
|
spec,
|
|
1853
2201
|
deps,
|
|
1854
2202
|
sessionId,
|
|
@@ -1859,6 +2207,20 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1859
2207
|
!(toolFaceSnapshot.exclude?.includes("Write") ?? false) &&
|
|
1860
2208
|
!(handsEnabled && isRemoteExecutionEnv(executionEnv) && spec.memoryPersistenceCapable !== true),
|
|
1861
2209
|
memoryProvenance,
|
|
2210
|
+
memoryCapturePolicy,
|
|
2211
|
+
memoryCapturePolicyDeclared: deps.memoryCapturePolicy !== undefined,
|
|
2212
|
+
captureEntitlement: {
|
|
2213
|
+
value: typeof runtimeCaps?.allowMemoryOptOut === "boolean" ? runtimeCaps.allowMemoryOptOut : undefined,
|
|
2214
|
+
faulted: runtimeCapsFaulted || (runtimeCaps?.allowMemoryOptOut !== undefined && typeof runtimeCaps.allowMemoryOptOut !== "boolean"),
|
|
2215
|
+
},
|
|
2216
|
+
captureCarrierUnsupported: isRemoteExecutionEnv(executionEnv) && deps.memoryCaptureRecordStore === undefined,
|
|
2217
|
+
...(internals?.parentSessionId !== undefined ? { parentSessionId: internals.parentSessionId } : {}),
|
|
2218
|
+
captureFloor: internals?.memoryCaptureFloor === true,
|
|
2219
|
+
...(internals?.memoryCaptureFloorIndeterminate === true ? { captureFloorIndeterminate: true } : {}),
|
|
2220
|
+
...(captureLineage.origin !== undefined ? { captureForkOrigin: captureLineage.origin } : {}),
|
|
2221
|
+
...(captureLineage.fault ? { captureLineageFault: true } : {}),
|
|
2222
|
+
...(internals?.memoryCaptureQueryDir !== undefined ? { parentCaptureQueryDir: internals.memoryCaptureQueryDir } : {}),
|
|
2223
|
+
...(internals?.memoryCaptureAncestors !== undefined ? { captureAncestors: internals.memoryCaptureAncestors } : {}),
|
|
1862
2224
|
memoryPersistenceDeclared: spec.memoryPersistenceCapable,
|
|
1863
2225
|
rosterCanPersist: spec.memoryPersistenceCapable ??
|
|
1864
2226
|
tools.some((t) => {
|
|
@@ -1917,6 +2279,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1917
2279
|
}
|
|
1918
2280
|
}
|
|
1919
2281
|
let instructionSources;
|
|
2282
|
+
let projectInstructionContent;
|
|
1920
2283
|
if (deps.loadProjectMemory) {
|
|
1921
2284
|
let projectMemoryPhase = spec.sessionId ? "resume" : "fresh";
|
|
1922
2285
|
if (spec.sessionId) {
|
|
@@ -1968,6 +2331,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1968
2331
|
}
|
|
1969
2332
|
}
|
|
1970
2333
|
if (projectMem != null && projectMem.trim()) {
|
|
2334
|
+
projectInstructionContent = projectMem;
|
|
1971
2335
|
const projectBlock = `${PROJECT_CONTEXT_FRAMING}\n\n${composeMemoryBlock(projectMem, "project")}`;
|
|
1972
2336
|
memoryBlock = memoryBlock ? `${memoryBlock}\n\n${projectBlock}` : projectBlock;
|
|
1973
2337
|
}
|
|
@@ -2032,7 +2396,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2032
2396
|
(memoryPairExcludedName !== undefined
|
|
2033
2397
|
? `excludeTools removes "${memoryPairExcludedName}"`
|
|
2034
2398
|
: `this task already declares a tool named "${memoryPairOccupiedName}" (the built-in yields to it)`) +
|
|
2035
|
-
" —
|
|
2399
|
+
" — these tools mount together or not at all."), { phase: "config", sessionId, classification: "memory-tools-not-mounted" });
|
|
2036
2400
|
}
|
|
2037
2401
|
const skillsListing = skillSpecs.length > 0
|
|
2038
2402
|
? {
|
|
@@ -2098,6 +2462,8 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2098
2462
|
envFacts.sandboxEgress = spec.envFacts.egress;
|
|
2099
2463
|
if (spec.envFacts?.scratchpadDir)
|
|
2100
2464
|
envFacts.scratchpadDir = spec.envFacts.scratchpadDir;
|
|
2465
|
+
if (externalContentTargetActive)
|
|
2466
|
+
envFacts.externalContentTarget = true;
|
|
2101
2467
|
if (resume !== undefined && spec.envFacts?.resumeFacts) {
|
|
2102
2468
|
const rf = spec.envFacts.resumeFacts;
|
|
2103
2469
|
const copy = {};
|
|
@@ -2229,7 +2595,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2229
2595
|
return deferredSet;
|
|
2230
2596
|
};
|
|
2231
2597
|
const sharedMemoryPair = sharedMemoryPairMounted ? SHARED_MEMORY_TOOL_NAMES.filter((n) => tools.some((t) => t.name === n)) : [];
|
|
2232
|
-
const memoryEnginePair = memoryEnginePairMounted
|
|
2598
|
+
const memoryEnginePair = explicitlyDeferredMemoryTrio(memoryEnginePairMounted, tools, toolFaceSnapshot.defer);
|
|
2233
2599
|
const builtinDeferPairNames = [...sharedMemoryPair, ...memoryEnginePair];
|
|
2234
2600
|
let deferred;
|
|
2235
2601
|
if (builtinDeferPairNames.length > 0) {
|
|
@@ -2239,8 +2605,9 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2239
2605
|
const soleCause = d0.size === 0 && d1.size > 0;
|
|
2240
2606
|
const supportNameTaken = tools.some((t) => t.name === TOOL_SEARCH_NAME || (t.aliases ?? []).includes(TOOL_SEARCH_NAME));
|
|
2241
2607
|
if (soleCause && supportNameTaken) {
|
|
2608
|
+
const retractNames = memoryGroupRetractionSet(builtinDeferPairNames, memoryEnginePair.length > 0);
|
|
2242
2609
|
for (let i = tools.length - 1; i >= 0; i--) {
|
|
2243
|
-
if (
|
|
2610
|
+
if (retractNames.has(tools[i].name))
|
|
2244
2611
|
tools.splice(i, 1);
|
|
2245
2612
|
}
|
|
2246
2613
|
if (sharedMemoryPair.length > 0) {
|
|
@@ -2250,8 +2617,8 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2250
2617
|
}
|
|
2251
2618
|
if (memoryEnginePair.length > 0) {
|
|
2252
2619
|
memoryEnginePairMounted = false;
|
|
2253
|
-
if (memoryBlock !== undefined) {
|
|
2254
|
-
const segment =
|
|
2620
|
+
if (memoryBlock !== undefined && memoryRecallSegment !== undefined) {
|
|
2621
|
+
const segment = memoryRecallSegment;
|
|
2255
2622
|
if (memoryBlock === segment)
|
|
2256
2623
|
memoryBlock = undefined;
|
|
2257
2624
|
else if (memoryBlock.includes(`\n\n${segment}`))
|
|
@@ -2260,7 +2627,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2260
2627
|
memoryBlock = memoryBlock.slice(segment.length + 2);
|
|
2261
2628
|
}
|
|
2262
2629
|
deps.onError?.(new Error(`Memory tools ${MEMORY_ENGINE_TOOL_NAMES.join("/")} were NOT mounted: mounting them would inject ` +
|
|
2263
|
-
`the "${TOOL_SEARCH_NAME}" tool, whose name this task already declares —
|
|
2630
|
+
`the "${TOOL_SEARCH_NAME}" tool, whose name this task already declares — these tools mount together or not at all.`), { phase: "config", sessionId, classification: "memory-tools-not-mounted" });
|
|
2264
2631
|
}
|
|
2265
2632
|
deferred = d0;
|
|
2266
2633
|
}
|
|
@@ -2278,13 +2645,14 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2278
2645
|
let staticMarkWaiverAnnounced = false;
|
|
2279
2646
|
const effectiveSafety = narrowContentSafety(delegationProvenanceChannel?.contentSafety, memoryEngineSession?.contentSafety);
|
|
2280
2647
|
const trustedTools = effectiveSafety.trustedTools;
|
|
2281
|
-
const execIsExternalContent = effectiveSafety.execIsExternalContent;
|
|
2648
|
+
const execIsExternalContent = effectiveSafety.execIsExternalContent || externalContentTargetActive;
|
|
2282
2649
|
provenanceForChildrenRef.current = { trustedTools: [...trustedTools], execIsExternalContent };
|
|
2283
2650
|
announceDeclaredMcpContentClasses({
|
|
2284
2651
|
entries: lockedPreflight.mcp,
|
|
2285
2652
|
statuses: mcp?.statuses,
|
|
2286
2653
|
execIsExternalContent,
|
|
2287
2654
|
sessionId,
|
|
2655
|
+
runId,
|
|
2288
2656
|
onNotice: deps.onNotice,
|
|
2289
2657
|
});
|
|
2290
2658
|
if (memoryEngineSession?.settlement !== undefined) {
|
|
@@ -2300,12 +2668,14 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2300
2668
|
};
|
|
2301
2669
|
const callerToolNames = new Set((spec.tools ?? []).map((t) => t.name));
|
|
2302
2670
|
const contentOriginWrapped = new WeakSet();
|
|
2303
|
-
const classOf = (t) =>
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2671
|
+
const classOf = (t) => externalContentTargetActive && envHandToolNames.has(t.name)
|
|
2672
|
+
? "external"
|
|
2673
|
+
: classifyToolContentOrigin({
|
|
2674
|
+
declared: t.contentOrigin,
|
|
2675
|
+
isProtocolTool: protocolOf(t.name) !== undefined,
|
|
2676
|
+
isCallerTool: callerToolNames.has(t.name),
|
|
2677
|
+
trusted: trustedTools.has(t.name),
|
|
2678
|
+
});
|
|
2309
2679
|
const delegationByName = new Map();
|
|
2310
2680
|
for (const t of spec.tools ?? []) {
|
|
2311
2681
|
const withFaces = t;
|
|
@@ -2446,6 +2816,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2446
2816
|
reason: waivedReason,
|
|
2447
2817
|
...(typeof requested === "string" ? { subagentType: inlineUntrusted(requested, 120) } : {}),
|
|
2448
2818
|
sessionId,
|
|
2819
|
+
runId,
|
|
2449
2820
|
},
|
|
2450
2821
|
});
|
|
2451
2822
|
}
|
|
@@ -2906,7 +3277,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2906
3277
|
emitTrace(deps.tracer, () => ({
|
|
2907
3278
|
kind: "loop.recovery",
|
|
2908
3279
|
version: 1,
|
|
2909
|
-
taskId:
|
|
3280
|
+
taskId: hostTaskId,
|
|
2910
3281
|
reason: step.reason,
|
|
2911
3282
|
ts: Date.now(),
|
|
2912
3283
|
}));
|
|
@@ -3137,7 +3508,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3137
3508
|
emitTrace(deps.tracer, () => ({
|
|
3138
3509
|
kind: "permission.sandbox_admitted",
|
|
3139
3510
|
version: 1,
|
|
3140
|
-
taskId:
|
|
3511
|
+
taskId: hostTaskId,
|
|
3141
3512
|
toolCallId: info.toolCallId,
|
|
3142
3513
|
toolName: info.toolName,
|
|
3143
3514
|
askClasses: info.askClasses.map((a) => a.cls),
|
|
@@ -3223,7 +3594,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3223
3594
|
emitTrace(deps.tracer, () => ({
|
|
3224
3595
|
kind: "permission.rule_store_unreadable",
|
|
3225
3596
|
version: 1,
|
|
3226
|
-
taskId:
|
|
3597
|
+
taskId: hostTaskId,
|
|
3227
3598
|
message: err instanceof Error ? err.message : String(err),
|
|
3228
3599
|
ts: Date.now(),
|
|
3229
3600
|
}));
|
|
@@ -3268,26 +3639,36 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3268
3639
|
return {};
|
|
3269
3640
|
if ((spec.principal === undefined || spec.principal === "") && deps.localOwnerRules !== true)
|
|
3270
3641
|
return {};
|
|
3271
|
-
|
|
3272
|
-
ask?.
|
|
3273
|
-
|
|
3274
|
-
ask?.
|
|
3275
|
-
|
|
3276
|
-
ask?.
|
|
3277
|
-
|
|
3278
|
-
|
|
3642
|
+
const closedDoor = (() => {
|
|
3643
|
+
if (ask?.requiresRealApproval === true)
|
|
3644
|
+
return "mandated";
|
|
3645
|
+
if (ask?.persistedRuleShadowed !== undefined)
|
|
3646
|
+
return "shadowed";
|
|
3647
|
+
if (ask?.decisionReason === "hook")
|
|
3648
|
+
return "mandated";
|
|
3649
|
+
if (ask?.matchedAskRule !== undefined)
|
|
3650
|
+
return "shadowed";
|
|
3651
|
+
if (ask?.inheritedUnresolved === true)
|
|
3652
|
+
return "mandated";
|
|
3653
|
+
if (ask?.ancestorResolved === true)
|
|
3654
|
+
return "mandated";
|
|
3655
|
+
return undefined;
|
|
3656
|
+
})();
|
|
3657
|
+
if (closedDoor !== undefined)
|
|
3658
|
+
return { ruleOffersAbsence: closedDoor };
|
|
3279
3659
|
if (persistedRuleMandateOf({
|
|
3280
3660
|
egress: egressTools.has(toolName),
|
|
3281
3661
|
irreversibility: irreversibilityTier.get(toolName),
|
|
3282
3662
|
shellGated: shellGatedBash,
|
|
3663
|
+
probeMandated: ask?.probeMandated === true,
|
|
3283
3664
|
}) !== undefined) {
|
|
3284
|
-
return {};
|
|
3665
|
+
return { ruleOffersAbsence: "mandated" };
|
|
3285
3666
|
}
|
|
3286
3667
|
const command = args?.command;
|
|
3287
3668
|
if (typeof command !== "string")
|
|
3288
|
-
return {};
|
|
3669
|
+
return { ruleOffersAbsence: "lane_cannot_speak" };
|
|
3289
3670
|
const offers = suggestRulesForCommand(command, ask?.segmentCoverage !== undefined ? { coverage: ask.segmentCoverage } : undefined);
|
|
3290
|
-
return offers.length > 0 ? { ruleOffers: offers } : {};
|
|
3671
|
+
return offers.length > 0 ? { ruleOffers: offers } : { ruleOffersAbsence: "lane_cannot_speak" };
|
|
3291
3672
|
};
|
|
3292
3673
|
const frozenClassifierExcluded = (d) => d.decisionReason === "hook" || d.matchedAskRule !== undefined;
|
|
3293
3674
|
const recheckApprovedEdit = async (pol, onAskOf, creq, edit, csignal, ancestorDecider) => {
|
|
@@ -3724,7 +4105,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3724
4105
|
const parkLaneArmed = wiringManifest.parkLane.effective === true;
|
|
3725
4106
|
const hookIdentity = mintHookInvocationIdentity({
|
|
3726
4107
|
sessionId,
|
|
3727
|
-
taskId:
|
|
4108
|
+
taskId: hostTaskId,
|
|
3728
4109
|
legKind: wiringManifest.leg.kind,
|
|
3729
4110
|
isDelegatedChild: delegation.isDelegatedChild,
|
|
3730
4111
|
...(internals?.insideFork === true ? { insideFork: true } : {}),
|
|
@@ -3733,6 +4114,12 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3733
4114
|
});
|
|
3734
4115
|
const hookContextConsumerWired = hooks?.preToolUse !== undefined || hooks?.postToolUse !== undefined || hooks?.postToolUseFailure !== undefined;
|
|
3735
4116
|
const hookEnvFace = hookContextConsumerWired && (ownedEnv ?? deps.executionEnv) != null ? createHookEnvCapabilities(executionEnv) : undefined;
|
|
4117
|
+
if (fileHistoryBoundary !== undefined) {
|
|
4118
|
+
harness.on("tool_call", async () => {
|
|
4119
|
+
await fileHistoryBoundary.settle();
|
|
4120
|
+
return undefined;
|
|
4121
|
+
});
|
|
4122
|
+
}
|
|
3736
4123
|
if (effectivePolicy || hooks?.preToolUse || egressTools.size > 0 || irreversibleTools.size > 0 || resourceSuspendEligible || platformSuspendArmed || spec.enablePlanMode === true) {
|
|
3737
4124
|
const adjudicate = effectivePolicy
|
|
3738
4125
|
? (req) => raceAbort(Promise.resolve(effectivePolicy.check({ ...req, budget: budgetSnapshot, ...(handsCwdRef !== undefined ? { cwd: handsCwdRef.current } : {}) }, abortController.signal)), abortController.signal, () => ({
|
|
@@ -3860,7 +4247,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3860
4247
|
const requiresParentConstraint = (inheritedParentConstraints?.length ?? 0) > 0 || seedInheritedGate?.requiresParentConstraint === true;
|
|
3861
4248
|
const parentConstraintCount = (inheritedParentConstraints?.length ?? 0) > 0 ? inheritedParentConstraints.length : seedInheritedGate?.parentConstraintCount;
|
|
3862
4249
|
const constraintChain = (inheritedParentConstraints?.length ?? 0) > 0
|
|
3863
|
-
? inheritedParentConstraints.map((pc) =>
|
|
4250
|
+
? inheritedParentConstraints.map((pc) => constraintChainEntryOfLayer(pc))
|
|
3864
4251
|
: seedInheritedGate?.constraintChain;
|
|
3865
4252
|
const constraintDigest = (inheritedParentConstraints?.length ?? 0) > 0
|
|
3866
4253
|
? constraintChainDigest(constraintChain)
|
|
@@ -3897,6 +4284,8 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3897
4284
|
gitAnnouncement: gitStatusRef.announced !== undefined ? { ...gitStatusRef.announced } : undefined,
|
|
3898
4285
|
delegationProvenance: internals?.delegationProvenance !== undefined ? { ...internals.delegationProvenance.ref.current } : undefined,
|
|
3899
4286
|
isDelegatedChild: hookIdentity.isDelegatedChild ? true : undefined,
|
|
4287
|
+
placementRootSessionId: stampPlacementRootSessionId(placementRootResolved),
|
|
4288
|
+
externalContentTarget: externalContentTargetActive ? true : undefined,
|
|
3900
4289
|
});
|
|
3901
4290
|
const commitSuspendSaga = async (token, cp, remoteEnv, remoteHandle) => {
|
|
3902
4291
|
if (!checkpointStore)
|
|
@@ -4256,7 +4645,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
4256
4645
|
}
|
|
4257
4646
|
};
|
|
4258
4647
|
const suspendAsk = parkLaneArmed && checkpointStore !== undefined
|
|
4259
|
-
? async (req, postHookArgs, safety, liveFaceUnavailable, realApproval, shadowedRule, askDecisionReason, probeReason, probeCause, segmentCoverage, matchedAskRule) => {
|
|
4648
|
+
? async (req, postHookArgs, safety, liveFaceUnavailable, realApproval, shadowedRule, askDecisionReason, probeReason, probeCause, segmentCoverage, matchedAskRule, probeMandated) => {
|
|
4260
4649
|
const syncFirstEligible = req.toolName === ASK_USER_QUESTION_TOOL_NAME ? contentAskRoutable(req.toolCallId) : isLiveApproverSeat(onAsk);
|
|
4261
4650
|
if (syncFirstEligible &&
|
|
4262
4651
|
runtimeCaps?.forceDurableGate !== true &&
|
|
@@ -4427,6 +4816,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
4427
4816
|
...(shadowedRule !== undefined ? { persistedRuleShadowed: shadowedRule } : {}),
|
|
4428
4817
|
...(askDecisionReason !== undefined ? { decisionReason: askDecisionReason } : {}),
|
|
4429
4818
|
...(matchedAskRule !== undefined ? { matchedAskRule } : {}),
|
|
4819
|
+
...(probeMandated === true ? { probeMandated: true } : {}),
|
|
4430
4820
|
...(inheritedUnavailableAsks.has(req.toolCallId) ? { inheritedUnresolved: true } : {}),
|
|
4431
4821
|
...(segmentCoverage !== undefined ? { segmentCoverage } : {}),
|
|
4432
4822
|
}),
|
|
@@ -4526,7 +4916,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
4526
4916
|
let humanBareRejection = false;
|
|
4527
4917
|
try {
|
|
4528
4918
|
result = await runToolGate({
|
|
4529
|
-
onNotifyError: (f) => emitTrace(deps.tracer, () => ({ kind: "observer.notify_failed", version: 1, taskId:
|
|
4919
|
+
onNotifyError: (f) => emitTrace(deps.tracer, () => ({ kind: "observer.notify_failed", version: 1, taskId: hostTaskId, site: f.site, message: f.error.message, ts: Date.now() })),
|
|
4530
4920
|
event: e,
|
|
4531
4921
|
identity: hookIdentity,
|
|
4532
4922
|
reminderMark,
|
|
@@ -4555,7 +4945,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
4555
4945
|
onResolved: (info) => emitTrace(deps.tracer, () => ({
|
|
4556
4946
|
kind: "permission.persisted_rule_allowed",
|
|
4557
4947
|
version: 2,
|
|
4558
|
-
taskId:
|
|
4948
|
+
taskId: hostTaskId,
|
|
4559
4949
|
toolName: info.toolName,
|
|
4560
4950
|
toolCallId: info.toolCallId,
|
|
4561
4951
|
rules: [...info.rules],
|
|
@@ -4572,7 +4962,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
4572
4962
|
onUnavailable: (info) => emitTrace(deps.tracer, () => ({
|
|
4573
4963
|
kind: "permission.org_snapshot_unavailable",
|
|
4574
4964
|
version: 1,
|
|
4575
|
-
taskId:
|
|
4965
|
+
taskId: hostTaskId,
|
|
4576
4966
|
toolName: info.toolName,
|
|
4577
4967
|
toolCallId: info.toolCallId,
|
|
4578
4968
|
message: info.message,
|
|
@@ -4694,7 +5084,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
4694
5084
|
}
|
|
4695
5085
|
const editAt = editBudget(model);
|
|
4696
5086
|
const guardAt = guardBudget(model);
|
|
4697
|
-
const microCompact = buildMicroCompactState(deps, model, sessionId, offloadStore, microCompactKnob);
|
|
5087
|
+
const microCompact = buildMicroCompactState(deps, model, sessionId, runId, offloadStore, microCompactKnob);
|
|
4698
5088
|
const charsPerToken = model.charsPerToken ?? DEFAULT_CHARS_PER_TOKEN;
|
|
4699
5089
|
harness.on("context", async ({ messages, recheck, signal }) => {
|
|
4700
5090
|
batchHaltRef.current = undefined;
|
|
@@ -4709,7 +5099,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
4709
5099
|
onCapped: (info) => pendingProjectionObservations.push(() => emitTrace(deps.tracer, () => ({
|
|
4710
5100
|
kind: "tool_result.capped",
|
|
4711
5101
|
version: 1,
|
|
4712
|
-
taskId:
|
|
5102
|
+
taskId: hostTaskId,
|
|
4713
5103
|
...(info.tool !== undefined ? { tool: info.tool } : {}),
|
|
4714
5104
|
sizeChars: info.sizeChars,
|
|
4715
5105
|
storeFallback: info.storeFallback,
|
|
@@ -4746,11 +5136,11 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
4746
5136
|
: {}),
|
|
4747
5137
|
});
|
|
4748
5138
|
if (ccPass !== undefined) {
|
|
4749
|
-
recordFrontierClears({ pass: ccPass, index: replay.index, edited, ledger: microCompact.ledger, tracer: deps.tracer, taskId:
|
|
5139
|
+
recordFrontierClears({ pass: ccPass, index: replay.index, edited, ledger: microCompact.ledger, tracer: deps.tracer, taskId: hostTaskId, trigger: "frontier" });
|
|
4750
5140
|
}
|
|
4751
5141
|
const chain = await runGuardChain({
|
|
4752
5142
|
edited, replayed, index: replay.index, microCompact, guardAt, charsPerToken, offloadStore,
|
|
4753
|
-
sessionId, taskId:
|
|
5143
|
+
sessionId, taskId: hostTaskId, deps, trimPressureRef, recheck, signal,
|
|
4754
5144
|
pendingProjectionObservations,
|
|
4755
5145
|
});
|
|
4756
5146
|
if ("earlyReturn" in chain) {
|
|
@@ -4985,7 +5375,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
4985
5375
|
const effectiveReadFaceObserved = carrierReadFace();
|
|
4986
5376
|
const effectiveReadDenyObserved = readDenyAdditionsNormalized.length > 0 ? readDenyAdditionsNormalized.map((e) => ({ ...e })) : undefined;
|
|
4987
5377
|
const preparedHolder = {};
|
|
4988
|
-
const buildPrepared = () => ({ harness, session, sessionId, reminderMark, reminderDisclosureCounts, taskRootPath: taskRootFinal, model, thinking, compModel: effectiveCompModel, mcp: mcp, ...(a2a !== undefined && a2a.tools.length > 0 ? { a2a } : {}), blockedRef, outputRef, abortController, conflictRef, blockedToolCalls, approvalSettlement, batchHaltRef, nestedStats, ...(rewindNotes.length > 0 ? { rewindNotes } : {}), ...(effectiveReadFaceObserved !== undefined ? { effectiveReadFace: effectiveReadFaceObserved } : {}), ...(effectiveReadDenyObserved !== undefined ? { effectiveReadDenyPatterns: effectiveReadDenyObserved } : {}), effectiveMemoryScopes: memoryEffectiveScopes, cwdRef: handsCwdRef, ...(worktreeSessionRef !== undefined ? { worktreeSessionRef } : {}), ...(workspaceStateSettle !== undefined ? { workspaceStateSettle } : {}), denyNarrowingPolicy, ...(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, 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, microCompact, ...(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, gitStatusRef, listBackgroundTasks, hookIdentity, hookTimeoutMs, ...(turnSnapshotRef.current !== undefined ? { turnSnapshot: turnSnapshotRef.current } : {}), ...(centerCompactionCandidate !== undefined ? { centerCompactionCandidate } : {}) });
|
|
5378
|
+
const buildPrepared = () => ({ harness, session, sessionId, runId, reminderMark, reminderDisclosureCounts, taskRootPath: taskRootFinal, model, thinking, compModel: effectiveCompModel, mcp: mcp, ...(a2a !== undefined && a2a.tools.length > 0 ? { a2a } : {}), blockedRef, outputRef, abortController, conflictRef, blockedToolCalls, approvalSettlement, batchHaltRef, nestedStats, ...(rewindNotes.length > 0 ? { rewindNotes } : {}), ...(fileHistoryBoundary !== undefined ? { fileHistoryBoundary } : {}), ...(effectiveReadFaceObserved !== undefined ? { effectiveReadFace: effectiveReadFaceObserved } : {}), ...(effectiveReadDenyObserved !== undefined ? { effectiveReadDenyPatterns: effectiveReadDenyObserved } : {}), effectiveMemoryScopes: memoryEffectiveScopes, cwdRef: handsCwdRef, ...(worktreeSessionRef !== undefined ? { worktreeSessionRef } : {}), ...(workspaceStateSettle !== undefined ? { workspaceStateSettle } : {}), ...(sealReadStateSeat !== undefined ? { sealReadStateSeat } : {}), denyNarrowingPolicy, ...(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, 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, microCompact, ...(memoryEngineSession ? { memoryEngineSession } : {}), ...(subagentRetain ? { subagentRetain } : {}), ...(lspDiagnostics && nudgeLspOnEdit ? { lspDiagnostics: { registry: lspDiagnostics, nudge: nudgeLspOnEdit, runIdent: lspRunIdent } } : {}), planModeRef, ...(dateChange ? { dateChange } : {}), ...(instructionSources ? { instructionSources } : {}), ...(projectInstructionContent !== undefined ? { projectInstructionContent } : {}), ...(workflowSizeGuideline ? { workflowSizeGuideline } : {}), ...(detectExternalChanges ? { detectExternalChanges } : {}), ...(toolsDeltaRef ? { toolsDeltaRef } : {}), ...(agentListing ? { agentListing } : {}), ...(skillsListing ? { skillsListing } : {}), announcedListingsRef, gitStatusRef, listBackgroundTasks, hookIdentity, hookTimeoutMs, ...(turnSnapshotRef.current !== undefined ? { turnSnapshot: turnSnapshotRef.current } : {}), ...(centerCompactionCandidate !== undefined ? { centerCompactionCandidate } : {}) });
|
|
4989
5379
|
const prepared = buildPrepared();
|
|
4990
5380
|
preparedHolder.current = prepared;
|
|
4991
5381
|
return prepared;
|