@sema-agent/core 7.30.1 → 7.31.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 +242 -0
- package/dist/agents/cross-session-judge.d.ts +4 -12
- package/dist/agents/cross-session-judge.js +4 -11
- package/dist/agents/peer-session-drain.js +0 -5
- package/dist/agents/send-message-tool.js +1 -0
- package/dist/agents/subagent.d.ts +1 -0
- package/dist/agents/subagent.js +1 -0
- package/dist/core/ask-origin.d.ts +6 -0
- package/dist/core/ask-origin.js +10 -0
- package/dist/core/checkpoint-store.d.ts +14 -0
- package/dist/core/checkpoint-store.js +1 -0
- package/dist/core/engine-notice.d.ts +4 -0
- package/dist/core/governance-codes.d.ts +1 -1
- package/dist/core/governance-codes.js +3 -0
- package/dist/core/memory-engine/data-plane.d.ts +3 -1
- package/dist/core/memory-engine/data-plane.js +1 -1
- package/dist/core/memory-engine/delegation-settlement.d.ts +44 -3
- package/dist/core/memory-engine/delegation-settlement.js +38 -3
- package/dist/core/memory-engine/engine.d.ts +123 -26
- package/dist/core/memory-engine/engine.js +426 -149
- package/dist/core/memory-engine/entry-scan.d.ts +23 -0
- package/dist/core/memory-engine/entry-scan.js +55 -0
- package/dist/core/memory-engine/file-backend.d.ts +16 -23
- package/dist/core/memory-engine/file-backend.js +122 -99
- package/dist/core/memory-engine/layer-observations.d.ts +109 -0
- package/dist/core/memory-engine/layer-observations.js +148 -0
- package/dist/core/memory-engine/layout.d.ts +11 -0
- package/dist/core/memory-engine/layout.js +20 -4
- package/dist/core/memory-engine/types.d.ts +26 -2
- package/dist/core/parent-spec-seat.d.ts +4 -1
- package/dist/core/parent-spec-seat.js +2 -0
- package/dist/core/park-selfcheck.js +1 -0
- package/dist/core/runner/announce-once-ledger.d.ts +26 -0
- package/dist/core/runner/announce-once-ledger.js +37 -0
- package/dist/core/runner/contracts.d.ts +22 -5
- package/dist/core/runner/denial-limit-arms.d.ts +2 -2
- package/dist/core/runner/prepare-acquire-reconcile.d.ts +0 -4
- package/dist/core/runner/prepare-acquire-reconcile.js +1 -3
- package/dist/core/runner/prepare-file-history.d.ts +13 -15
- package/dist/core/runner/prepare-file-history.js +57 -43
- package/dist/core/runner/prepare-hands-readface.d.ts +2 -2
- package/dist/core/runner/prepare-listings.d.ts +3 -1
- package/dist/core/runner/prepare-listings.js +2 -2
- package/dist/core/runner/prepare-memory.js +16 -5
- package/dist/core/runner/prepare-park-ask.js +27 -16
- package/dist/core/runner/prepare-prompt-inputs.d.ts +8 -1
- package/dist/core/runner/prepare-prompt-inputs.js +5 -3
- package/dist/core/runner/prepare-task.js +7 -5
- package/dist/core/runner/prepare-wiring-manifest.d.ts +1 -0
- package/dist/core/runner/prepare-wiring-manifest.js +2 -1
- package/dist/core/runner/run-attachment-seats.js +1 -1
- package/dist/core/runner/run-leg.js +61 -52
- package/dist/core/runner/run-settle-and-teardown.js +4 -0
- package/dist/core/runner/run-turn-boundary.js +6 -6
- package/dist/core/runner/turn-attachments.d.ts +6 -6
- package/dist/core/runner-deps.d.ts +3 -1
- package/dist/core/secret-env.d.ts +11 -0
- package/dist/core/secret-env.js +20 -0
- package/dist/core/store-contracts/checkpoint-store-contract.d.ts +2 -0
- package/dist/core/store-contracts/checkpoint-store-contract.js +22 -0
- package/dist/core/task-result.d.ts +1 -1
- package/dist/core/task-spec.d.ts +17 -8
- package/dist/core/tool-spec.d.ts +1 -1
- package/dist/core/wiring-manifest.d.ts +10 -0
- package/dist/core/wiring-manifest.js +7 -1
- package/dist/engine/execution-env/node-execution-env.d.ts +6 -0
- package/dist/engine/execution-env/node-execution-env.js +15 -17
- package/dist/engine/harness/agent-harness.js +7 -5
- package/dist/engine/lsp/node-lsp-manager.d.ts +4 -0
- package/dist/engine/lsp/node-lsp-manager.js +10 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +7 -1
- package/wire-changes/core@7.31.0.json +705 -0
|
@@ -2,7 +2,7 @@ import { NodeExecutionEnv } from "../../engine/execution-env/node-execution-env.
|
|
|
2
2
|
import { isRemoteExecutionEnv } from "../remote-env.js";
|
|
3
3
|
import { resolveTrackKey } from "../file-history-store.js";
|
|
4
4
|
export async function prepareFileHistory(input) {
|
|
5
|
-
const { deps, spec, internals, executionEnv, taskRootFinal, handsEnabled, sessionId, session,
|
|
5
|
+
const { deps, spec, internals, executionEnv, taskRootFinal, handsEnabled, sessionId, session, abortController } = input;
|
|
6
6
|
const rewindNotes = [];
|
|
7
7
|
const onTrackFailure = deps.onTrackFailure === undefined ? "refuse" : deps.onTrackFailure;
|
|
8
8
|
if (onTrackFailure !== "refuse" && onTrackFailure !== "proceed-unprotected") {
|
|
@@ -11,16 +11,20 @@ export async function prepareFileHistory(input) {
|
|
|
11
11
|
throw e;
|
|
12
12
|
}
|
|
13
13
|
const wiredSeat = resolveWiredFileHistoryStore(deps.fileHistoryStore);
|
|
14
|
-
const
|
|
14
|
+
const runDeclaredOff = resolveRunFileHistoryWord(spec.fileHistory);
|
|
15
|
+
const captureOff = resolveFileHistoryCaptureWord(deps.fileHistoryCapture, wiredSeat);
|
|
16
|
+
const declaredOff = wiredSeat === "disabled" || runDeclaredOff;
|
|
17
|
+
const fileHistoryStore = declaredOff ? undefined : wiredSeat;
|
|
18
|
+
const captureStore = captureOff ? undefined : fileHistoryStore;
|
|
15
19
|
const legacyRewindFiles = spec.rewindFiles;
|
|
16
20
|
if (legacyRewindFiles === true) {
|
|
17
21
|
if (spec.resumeAt !== undefined) {
|
|
18
|
-
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
|
|
22
|
+
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 on whenever a RunnerDeps.fileHistoryStore is wired and neither RunnerDeps.fileHistoryCapture nor TaskSpec.fileHistory turns it off.)`);
|
|
19
23
|
e.code = "rewind.rewind_files_retired";
|
|
20
24
|
throw e;
|
|
21
25
|
}
|
|
22
26
|
try {
|
|
23
|
-
deps.onError?.(new Error(`TaskSpec.rewindFiles (capture sense) is retired and was ignored: per-edited-file first-touch tracking is
|
|
27
|
+
deps.onError?.(new Error(`TaskSpec.rewindFiles (capture sense) is retired and was ignored: per-edited-file first-touch tracking is on whenever RunnerDeps.fileHistoryStore is wired and neither RunnerDeps.fileHistoryCapture nor TaskSpec.fileHistory turns it off, 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 });
|
|
24
28
|
}
|
|
25
29
|
catch {
|
|
26
30
|
}
|
|
@@ -35,7 +39,7 @@ export async function prepareFileHistory(input) {
|
|
|
35
39
|
e.code = "rewind.conflicting_targets";
|
|
36
40
|
throw e;
|
|
37
41
|
}
|
|
38
|
-
|
|
42
|
+
const rewindTarget = spec.resumeAt !== undefined ? (spec.restoreFiles === true ? spec.resumeAt : undefined) : spec.rewindFilesTo;
|
|
39
43
|
const rewindBefore = rewindTarget !== undefined && spec.resumeAt !== undefined && spec.resumeAtMode === "before";
|
|
40
44
|
if (spec.resumeAt !== undefined && spec.restoreFiles !== true) {
|
|
41
45
|
rewindNotes.push({
|
|
@@ -43,9 +47,9 @@ export async function prepareFileHistory(input) {
|
|
|
43
47
|
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`,
|
|
44
48
|
});
|
|
45
49
|
}
|
|
46
|
-
const fileHistoryEnabled =
|
|
50
|
+
const fileHistoryEnabled = captureStore !== undefined && handsEnabled;
|
|
47
51
|
const livenessArm = fileHistoryStore === undefined ? "file-history-no-store" : "file-history-no-env";
|
|
48
|
-
if (!fileHistoryEnabled &&
|
|
52
|
+
if (!fileHistoryEnabled && !declaredOff && !captureOff && (handsEnabled || fileHistoryStore !== undefined) && deps.onError !== undefined && !toldAlready(deps.onError, livenessArm)) {
|
|
49
53
|
const reason = livenessArm === "file-history-no-store"
|
|
50
54
|
? `this deployment wired no RunnerDeps.fileHistoryStore, so NOTHING is recorded: no first-touch snapshot before an edit, no turn boundary, and a later restoreFiles / rewindFilesTo has nothing to restore from and will refuse (rewind.store_unconfigured). Supply a store, or accept an unrecoverable working tree knowingly (fileHistoryStore: "disabled" says so and silences this line)`
|
|
51
55
|
: `RunnerDeps.fileHistoryStore is wired but this run mounts no filesystem-capable ExecutionEnv, so the store is INERT: there is no working tree to snapshot and nothing will ever be written to it. Wire RunnerDeps.executionEnv, or drop the store from this deployment shape`;
|
|
@@ -55,14 +59,18 @@ export async function prepareFileHistory(input) {
|
|
|
55
59
|
catch {
|
|
56
60
|
}
|
|
57
61
|
}
|
|
58
|
-
const { historyRoot, historyScope, historyFs } = await resolveFileHistoryCoordinates(
|
|
59
|
-
if (
|
|
60
|
-
await adoptForkedFileHistory(
|
|
62
|
+
const { historyRoot, historyScope, historyFs } = await resolveFileHistoryCoordinates(fileHistoryStore !== undefined && handsEnabled, executionEnv, taskRootFinal, internals?.fileHistoryLineage, sessionId);
|
|
63
|
+
if (captureStore !== undefined && internals?.fileHistoryLineage === undefined)
|
|
64
|
+
await adoptForkedFileHistory(captureStore, session, sessionId, deps.onError);
|
|
61
65
|
if (rewindTarget !== undefined && historyScope !== sessionId)
|
|
62
66
|
throw childScopeRewindRefusal(historyScope, rewindTarget);
|
|
63
67
|
if (fileHistoryStore === undefined) {
|
|
68
|
+
if (rewindTarget !== undefined && runDeclaredOff)
|
|
69
|
+
throw captureDisabledRefusal(rewindTarget);
|
|
64
70
|
if (rewindTarget !== undefined) {
|
|
65
|
-
const e = new Error(
|
|
71
|
+
const e = new Error(wiredSeat === "disabled"
|
|
72
|
+
? `rewind-files: restoring files to entry "${rewindTarget}" requires a history backend, but this deployment declared file history disabled (RunnerDeps.fileHistoryStore: "disabled"), so there is no history to restore — the files were NOT rewound`
|
|
73
|
+
: `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`);
|
|
66
74
|
e.code = "rewind.store_unconfigured";
|
|
67
75
|
throw e;
|
|
68
76
|
}
|
|
@@ -78,39 +86,17 @@ export async function prepareFileHistory(input) {
|
|
|
78
86
|
let restoredFilePaths = [];
|
|
79
87
|
if (rewindTarget !== undefined && fileHistoryStore !== undefined && handsEnabled) {
|
|
80
88
|
const historyStore = fileHistoryStore;
|
|
81
|
-
if (rewindBefore)
|
|
82
|
-
|
|
83
|
-
if (await historyStore.canRestore(sessionId, rewindTarget)) {
|
|
84
|
-
anchor = rewindTarget;
|
|
85
|
-
}
|
|
86
|
-
else {
|
|
87
|
-
const walked = new Set();
|
|
88
|
-
let cursor = resumeAtBeforeParentId;
|
|
89
|
-
while (cursor !== null && !walked.has(cursor)) {
|
|
90
|
-
walked.add(cursor);
|
|
91
|
-
if (await historyStore.canRestore(sessionId, cursor)) {
|
|
92
|
-
anchor = cursor;
|
|
93
|
-
break;
|
|
94
|
-
}
|
|
95
|
-
cursor = (await session.getEntry(cursor))?.parentId ?? null;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
if (anchor === undefined) {
|
|
99
|
-
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. ${rewindRefusalTail("at-or-above")}`);
|
|
100
|
-
e.code = "rewind_snapshot.unresolvable";
|
|
101
|
-
throw e;
|
|
102
|
-
}
|
|
103
|
-
rewindTarget = anchor;
|
|
104
|
-
}
|
|
89
|
+
if (rewindBefore && !(await historyStore.canRestore(sessionId, rewindTarget)))
|
|
90
|
+
throw beforeWithoutBoundaryRefusal(rewindTarget, sessionId);
|
|
105
91
|
const restoreRoot = historyRoot;
|
|
106
92
|
const restoreSignal = spec.signal ? AbortSignal.any([abortController.signal, spec.signal]) : abortController.signal;
|
|
107
93
|
const restored = await historyStore.restore(sessionId, rewindTarget, executionEnv, restoreRoot, restoreSignal);
|
|
108
94
|
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("; ")})` : ""}`;
|
|
109
95
|
if (restored.outcome === "failed") {
|
|
110
96
|
if (restored.error?.code === "not_found") {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
97
|
+
if (rewindBefore)
|
|
98
|
+
throw beforeWithoutBoundaryRefusal(rewindTarget, sessionId);
|
|
99
|
+
const e = new Error(`rewind-files: no file-history boundary exists for entry "${rewindTarget}" on session "${sessionId}" — the working tree was NOT rewound. ${rewindRefusalTail()}`);
|
|
114
100
|
e.code = "rewind_snapshot.unresolvable";
|
|
115
101
|
throw e;
|
|
116
102
|
}
|
|
@@ -170,7 +156,8 @@ export async function prepareFileHistory(input) {
|
|
|
170
156
|
const fileHistoryBoundary = fileHistoryEnabled && historyScope === sessionId
|
|
171
157
|
? createFileHistoryBoundarySeat({ store: fileHistoryStore, sessionId, env: executionEnv, root: historyRoot, onError: deps.onError })
|
|
172
158
|
: undefined;
|
|
173
|
-
|
|
159
|
+
const fileHistoryFact = fileHistoryEnabled ? "on" : "disabled";
|
|
160
|
+
return { trackFileEdit, fileHistoryBoundary, restoredFilePaths, rewindNotes, fileHistoryEnabled, fileHistoryFact, historyScope, historyRoot, historyFs };
|
|
174
161
|
}
|
|
175
162
|
function restoredAbsPathsOf(restored, root) {
|
|
176
163
|
const out = [];
|
|
@@ -203,10 +190,37 @@ function resolveWiredFileHistoryStore(candidate) {
|
|
|
203
190
|
}
|
|
204
191
|
return candidate;
|
|
205
192
|
}
|
|
206
|
-
function
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
193
|
+
function resolveRunFileHistoryWord(word) {
|
|
194
|
+
if (word === undefined || word === "disabled")
|
|
195
|
+
return word === "disabled";
|
|
196
|
+
const e = new Error(`rewind-files: TaskSpec.fileHistory holds ${shownWord(word)} — the only value is "disabled"; omit the key to leave the deployment's setting in force`);
|
|
197
|
+
e.code = "rewind.invalid_spec";
|
|
198
|
+
throw e;
|
|
199
|
+
}
|
|
200
|
+
function resolveFileHistoryCaptureWord(word, wiredSeat) {
|
|
201
|
+
if (word === undefined || (word === "off" && wiredSeat !== undefined && wiredSeat !== "disabled"))
|
|
202
|
+
return word === "off";
|
|
203
|
+
const e = new Error(word === "off"
|
|
204
|
+
? `RunnerDeps.fileHistoryCapture: "off" requires a wired RunnerDeps.fileHistoryStore — nothing to switch off; to drop history entirely write fileHistoryStore: "disabled"`
|
|
205
|
+
: `RunnerDeps.fileHistoryCapture holds ${shownWord(word)} — the only value is "off"; omit the key to record whenever a fileHistoryStore is wired`);
|
|
206
|
+
e.code = "config.invalid_file_history_capture";
|
|
207
|
+
throw e;
|
|
208
|
+
}
|
|
209
|
+
function shownWord(word) {
|
|
210
|
+
return typeof word === "string" ? JSON.stringify(word.slice(0, 40)) : word === null || typeof word === "boolean" || typeof word === "number" ? String(word) : `a ${typeof word}`;
|
|
211
|
+
}
|
|
212
|
+
function captureDisabledRefusal(target) {
|
|
213
|
+
const e = new Error(`rewind-files: this run set TaskSpec.fileHistory: "disabled", so it neither records nor restores file history — restoring files to entry "${target}" was refused and the files were NOT rewound`);
|
|
214
|
+
e.code = "rewind.capture_disabled";
|
|
215
|
+
return e;
|
|
216
|
+
}
|
|
217
|
+
function rewindRefusalTail() {
|
|
218
|
+
return `Boundaries are keyed by a turn's INITIAL entry and exist only for turns that recorded history (a RunnerDeps.fileHistoryStore wired, capture on, and the run's file history not disabled); a boundary from the retired whole-tree snapshot era is not restorable by this seat, and reaped boundaries have none.`;
|
|
219
|
+
}
|
|
220
|
+
function beforeWithoutBoundaryRefusal(target, sessionId) {
|
|
221
|
+
const e = new Error(`rewind-files: entry "${target}" has no file-history boundary on session "${sessionId}" — a before-restore needs the target's own boundary and never crosses into an earlier turn, so the working tree was NOT rewound. ${rewindRefusalTail()}`);
|
|
222
|
+
e.code = "rewind_snapshot.unresolvable";
|
|
223
|
+
return e;
|
|
210
224
|
}
|
|
211
225
|
const FILE_HISTORY_BOUNDARY_TIMEOUT_MS = 30_000;
|
|
212
226
|
const FILE_HISTORY_LIVENESS_MEMO = new WeakMap();
|
|
@@ -218,8 +218,8 @@ export interface PrepareHandsReadFaceInput {
|
|
|
218
218
|
* band's Read/notebook/PDF trailer outlets bump keys on it at tool-execute time (the driver owns
|
|
219
219
|
* the object and folds it into result stats). */
|
|
220
220
|
reminderDisclosureCounts: import("../reminder-disclosure.js").ReminderDisclosureCounts;
|
|
221
|
-
/** borrowed-readonly — the first-touch history hook prepare built (present iff
|
|
222
|
-
* wired and
|
|
221
|
+
/** borrowed-readonly — the first-touch history hook prepare built (present iff the run records file history into a
|
|
222
|
+
* wired store and mounts a real fs env); threaded to the write band's trackFileEdit seat. */
|
|
223
223
|
trackFileEdit?: import("../types.js").TrackFileEditHook;
|
|
224
224
|
/** borrowed-readonly — the mutation lane's LANDED observation seat (the accumulator behind
|
|
225
225
|
* `TaskResult.editedFiles`); threaded to the write band's onFileEdited seat. Unlike
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import type { AgentTool } from "../../internal/harness.js";
|
|
17
17
|
import type { TaskSpec } from "../types.js";
|
|
18
|
-
import type { AnnounceOnceSink, Prepared, PrepareResume, ToolFaceSnapshot } from "./contracts.js";
|
|
18
|
+
import type { AnnounceOnceSink, DateAnchorRead, Prepared, PrepareResume, ToolFaceSnapshot } from "./contracts.js";
|
|
19
19
|
import type { AnnouncedListingSnapshot } from "../../internal/harness.js";
|
|
20
20
|
import type { ResolvedSkillListingBudget } from "../skill-listing-budget.js";
|
|
21
21
|
export interface PrepareListingsInput {
|
|
@@ -65,6 +65,8 @@ export interface PrepareListingsInput {
|
|
|
65
65
|
tzValid: boolean;
|
|
66
66
|
/** borrowed-readonly — the client's declared zone (used only when `tzValid`). */
|
|
67
67
|
userTz: string | undefined;
|
|
68
|
+
/** borrowed-readonly — the session's date anchor as the prompt-inputs phase read it (rides the seam). */
|
|
69
|
+
dateAnchor: DateAnchorRead | undefined;
|
|
68
70
|
}
|
|
69
71
|
export interface PrepareListingsResult {
|
|
70
72
|
/** owned — the agent-listing announce projection (`Prepared.agentListing`): the roster off the
|
|
@@ -2,7 +2,7 @@ import { formatLocalDate } from "../../prompts/default.js";
|
|
|
2
2
|
import { SKILL_TOOL_NAME } from "./synthetic-tools.js";
|
|
3
3
|
import { renderAgentListingDelta } from "./turn-attachments.js";
|
|
4
4
|
export function prepareListings(input) {
|
|
5
|
-
const { spec, tools, onceLedger, sessionId, toolFaceSnapshot, activeTools, resume, skillsListing, listingBudget, listingRideRef, renderWithDate, envFacts, tzValid, userTz } = input;
|
|
5
|
+
const { spec, tools, onceLedger, sessionId, toolFaceSnapshot, activeTools, resume, skillsListing, listingBudget, listingRideRef, renderWithDate, envFacts, tzValid, userTz, dateAnchor } = input;
|
|
6
6
|
if (spec.agents !== undefined && spec.agents.length > 0) {
|
|
7
7
|
const known = new Set(tools.flatMap((t) => [t.name, ...(t.aliases ?? [])]));
|
|
8
8
|
for (const def of spec.agents) {
|
|
@@ -72,7 +72,7 @@ export function prepareListings(input) {
|
|
|
72
72
|
};
|
|
73
73
|
}
|
|
74
74
|
const dateChange = renderWithDate
|
|
75
|
-
? { legDate: envFacts.date, today: () => formatLocalDate(new Date(), tzValid ? userTz : undefined) }
|
|
75
|
+
? { legDate: envFacts.date, today: () => formatLocalDate(new Date(), tzValid ? userTz : undefined), anchor: dateAnchor }
|
|
76
76
|
: undefined;
|
|
77
77
|
return { agentListing, announcedListingsRef, dateChange };
|
|
78
78
|
}
|
|
@@ -81,6 +81,7 @@ export async function prepareMemory(input) {
|
|
|
81
81
|
let captureIndeterminate = false;
|
|
82
82
|
let captureLineageIndeterminate = false;
|
|
83
83
|
let memoryEngineSession;
|
|
84
|
+
const openedLegs = [];
|
|
84
85
|
let memoryTools;
|
|
85
86
|
let writeChannelOpen = false;
|
|
86
87
|
let memoryMarkedEntriesServed = false;
|
|
@@ -385,6 +386,7 @@ export async function prepareMemory(input) {
|
|
|
385
386
|
sessionId,
|
|
386
387
|
...(m.write === null && shadowNames !== undefined && shadowNames.size > 0 ? { shadowNames } : {}),
|
|
387
388
|
});
|
|
389
|
+
openedLegs.push(() => void m.engine.endSessionLeg(handle, sessionId));
|
|
388
390
|
mounted.push(handle);
|
|
389
391
|
materializedResidue.push(...planeScopes(m.scopes, m.write));
|
|
390
392
|
if (m.write !== null) {
|
|
@@ -425,10 +427,10 @@ export async function prepareMemory(input) {
|
|
|
425
427
|
committedHeaders: () => personalEngine.listCommittedHeaders(planeScopes(p.personal, p.writePlane === "personal" ? memorySpec.writeScope : null)),
|
|
426
428
|
},
|
|
427
429
|
];
|
|
428
|
-
harvestBoth = async () => {
|
|
430
|
+
harvestBoth = async (phase) => {
|
|
429
431
|
const writeFirst = writeIsPersonal ? [personalEngine, personalHandle] : [projectEngine, projectHandle];
|
|
430
432
|
const readOther = writeIsPersonal ? [projectEngine, projectHandle] : [personalEngine, personalHandle];
|
|
431
|
-
const writeReport = await writeFirst[0].harvest(writeFirst[1], { ...pollutedOpts(writeFirst[0]), sessionId, ...(await admitNothingOptsNow()) });
|
|
433
|
+
const writeReport = await writeFirst[0].harvest(writeFirst[1], { ...pollutedOpts(writeFirst[0]), sessionId, ...(await admitNothingOptsNow()), phase });
|
|
432
434
|
let readReport;
|
|
433
435
|
let readFailure;
|
|
434
436
|
try {
|
|
@@ -448,12 +450,13 @@ export async function prepareMemory(input) {
|
|
|
448
450
|
const personalEngine = personal.engine;
|
|
449
451
|
await armCaptureOptOut(personalEngine);
|
|
450
452
|
const handle = await personalEngine.materialize(memorySpec.scopes, memorySpec.writeScope, { adoptionRestricted: adoptionRestricted || captureOptedOut || captureIndeterminate, sessionId });
|
|
453
|
+
openedLegs.push(() => void personalEngine.endSessionLeg(handle, sessionId));
|
|
451
454
|
materializedResidue.push(...planeScopes(memorySpec.scopes, memorySpec.writeScope));
|
|
452
455
|
memoryMarkedEntriesServed = handle.markedEntriesPresent === true;
|
|
453
456
|
writeEngine = personalEngine;
|
|
454
457
|
writeHandle = handle;
|
|
455
458
|
injectFn = () => personalEngine.inject(handle, { writeToolMounted: writeChannelOpen, reminderMark: input.reminderMark });
|
|
456
|
-
harvestBoth = async () => personalEngine.harvest(handle, { ...pollutedOpts(personalEngine), sessionId, ...(await admitNothingOptsNow()) });
|
|
459
|
+
harvestBoth = async (phase) => personalEngine.harvest(handle, { ...pollutedOpts(personalEngine), sessionId, ...(await admitNothingOptsNow()), phase });
|
|
457
460
|
toolPlanes = [
|
|
458
461
|
{
|
|
459
462
|
backend: retrievalBackend(personal.backend, adoptionRestricted || captureOptedOut || captureIndeterminate || memorySpec.writeScope === null),
|
|
@@ -477,12 +480,13 @@ export async function prepareMemory(input) {
|
|
|
477
480
|
});
|
|
478
481
|
await armCaptureOptOut(engine);
|
|
479
482
|
const handle = await engine.materialize(memorySpec.scopes, memorySpec.writeScope, { adoptionRestricted: adoptionRestricted || captureOptedOut || captureIndeterminate, sessionId });
|
|
483
|
+
openedLegs.push(() => void engine.endSessionLeg(handle, sessionId));
|
|
480
484
|
materializedResidue.push(...planeScopes(memorySpec.scopes, memorySpec.writeScope));
|
|
481
485
|
memoryMarkedEntriesServed = handle.markedEntriesPresent === true;
|
|
482
486
|
writeEngine = engine;
|
|
483
487
|
writeHandle = handle;
|
|
484
488
|
injectFn = () => engine.inject(handle, { writeToolMounted: writeChannelOpen, reminderMark: input.reminderMark });
|
|
485
|
-
harvestBoth = async () => engine.harvest(handle, { ...pollutedOpts(engine), sessionId, ...(await admitNothingOptsNow()) });
|
|
489
|
+
harvestBoth = async (phase) => engine.harvest(handle, { ...pollutedOpts(engine), sessionId, ...(await admitNothingOptsNow()), phase });
|
|
486
490
|
toolPlanes = [
|
|
487
491
|
{
|
|
488
492
|
backend: retrievalBackend(backend, adoptionRestricted || captureOptedOut || captureIndeterminate || memorySpec.writeScope === null),
|
|
@@ -574,7 +578,7 @@ export async function prepareMemory(input) {
|
|
|
574
578
|
};
|
|
575
579
|
const harvestSafe = async (phase = "terminal") => {
|
|
576
580
|
try {
|
|
577
|
-
const report = await harvestBoth();
|
|
581
|
+
const report = await harvestBoth(phase);
|
|
578
582
|
if (!report.ok && report.incident) {
|
|
579
583
|
const named = report.reportId !== undefined ? `${report.incident.kind}, report ${report.reportId}` : report.incident.kind;
|
|
580
584
|
deps.onError?.(new Error(`memory harvest refused (${named}): ${report.incident.detail}`), { phase: "memory", sessionId });
|
|
@@ -615,6 +619,10 @@ export async function prepareMemory(input) {
|
|
|
615
619
|
handle: writeHandle,
|
|
616
620
|
inject: injectFn,
|
|
617
621
|
harvest: harvestSafe,
|
|
622
|
+
release: () => {
|
|
623
|
+
for (const end of openedLegs)
|
|
624
|
+
end();
|
|
625
|
+
},
|
|
618
626
|
captureOptOut: {
|
|
619
627
|
optedOut: () => {
|
|
620
628
|
if (captureOptedOut)
|
|
@@ -733,6 +741,9 @@ export async function prepareMemory(input) {
|
|
|
733
741
|
memoryTools = createMemoryEngineTools({ planes: toolPlanes, sessionPollution: () => writeEngine.sessionPollution(sessionId), provenance: input.memoryProvenance, writeScope: memorySpec.writeScope });
|
|
734
742
|
}
|
|
735
743
|
catch (err) {
|
|
744
|
+
if (memoryEngineSession === undefined)
|
|
745
|
+
for (const end of openedLegs)
|
|
746
|
+
end();
|
|
736
747
|
if (typeof err.code === "string" &&
|
|
737
748
|
(err.code.startsWith("config.memory_scope") ||
|
|
738
749
|
err.code.startsWith("config.memory_project") ||
|
|
@@ -6,6 +6,7 @@ import { boundInputHashOf } from "../canonical-json.js";
|
|
|
6
6
|
import { buildRiskDescriptor, checkpointVersionFor, debitLedger, encodeAtFidelity, mintCheckpointId, mintCheckpointToken, resolveDeclaredFidelity, samePlainValue, } from "../checkpoint-store.js";
|
|
7
7
|
import { pauseOf } from "../pause-registry.js";
|
|
8
8
|
import { askCarryRowMembers } from "../hooks.js";
|
|
9
|
+
import { askMandateMember, ownedClearanceFacts } from "../ask-origin.js";
|
|
9
10
|
import { defaultTaskRegistry } from "../task-registry.js";
|
|
10
11
|
import { advertisedWritableRootsSeat, isLiveApproverSeat, carriesBidiControls, describeThrown, refuseOutOfContractDecision, tryCloneArgs } from "../tool-policy.js";
|
|
11
12
|
import { InMemoryToolResultStore, ScopedToolResultStore, isVolatileOffloadStore } from "../tool-result-store.js";
|
|
@@ -21,6 +22,9 @@ class ParkRefusal extends Error {
|
|
|
21
22
|
this.name = "ParkRefusal";
|
|
22
23
|
}
|
|
23
24
|
}
|
|
25
|
+
const wordlessDemand = (toolName) => {
|
|
26
|
+
throw new Error(`a real-approval demand for "${toolName}" reached the park with no origin word — the origin stamp precedes every park`);
|
|
27
|
+
};
|
|
24
28
|
export function prepareParkAsk(input) {
|
|
25
29
|
const { askLane, saga, spec, deps, sessionId, checkpointStore, toolRosterDeltas, 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 } = input;
|
|
26
30
|
if (askLane === undefined || saga === undefined)
|
|
@@ -148,6 +152,7 @@ export function prepareParkAsk(input) {
|
|
|
148
152
|
throw new ParkRefusal(`the arguments of "${req.toolName}" change shape when stored by this checkpoint backend, and no policy is wired to re-adjudicate the stored shape ` +
|
|
149
153
|
`(no basePolicyForResumeEdit override and no caller toolPolicy) — refusing to file a row whose executable form nothing adjudicated`);
|
|
150
154
|
}
|
|
155
|
+
let storedShapeFacts;
|
|
151
156
|
if (projectionMovedArgs && basePolicyForResumeEdit !== undefined) {
|
|
152
157
|
const presented = encodeAtFidelity(backendFidelity, parkedArgs);
|
|
153
158
|
if (!presented.ok) {
|
|
@@ -177,7 +182,10 @@ export function prepareParkAsk(input) {
|
|
|
177
182
|
`${reprojected.action === "deny" && reprojected.message ? `: ${reprojected.message}` : ""} — ` +
|
|
178
183
|
`refusing to file a row whose executable form nothing adjudicated`);
|
|
179
184
|
}
|
|
185
|
+
if (reprojected.action === "ask")
|
|
186
|
+
storedShapeFacts = ownedClearanceFacts(reprojected);
|
|
180
187
|
}
|
|
188
|
+
const rowRealApproval = realApproval ?? (storedShapeFacts?.requiresRealApproval === true ? { origin: carry?.origin ?? wordlessDemand(req.toolName) } : undefined);
|
|
181
189
|
if (offloadStore && isVolatileOffloadStore(offloadStore) && !offloadStore.isEmpty()) {
|
|
182
190
|
throw new ParkRefusal("durable suspend requires a durable toolResultStore (the default InMemoryToolResultStore " +
|
|
183
191
|
"holds offloaded results that are lost across a cross-replica resume); inject " +
|
|
@@ -237,15 +245,15 @@ export function prepareParkAsk(input) {
|
|
|
237
245
|
shellGateDoctrine: effectiveShellGate,
|
|
238
246
|
});
|
|
239
247
|
gate =
|
|
240
|
-
safety !== undefined ||
|
|
248
|
+
safety !== undefined || rowRealApproval !== undefined
|
|
241
249
|
? {
|
|
242
250
|
kind: "irreversible_ask",
|
|
243
251
|
reason: safety !== undefined
|
|
244
252
|
? `human approval required before safety-tightened tool "${req.toolName}"`
|
|
245
|
-
: `real human approval required for tool "${req.toolName}" (non-budgetable: ${
|
|
253
|
+
: `real human approval required for tool "${req.toolName}" (non-budgetable: ${rowRealApproval.origin})`,
|
|
246
254
|
toolName: req.toolName,
|
|
247
255
|
...(safety !== undefined ? { safetyAxis: safety } : {}),
|
|
248
|
-
...(
|
|
256
|
+
...(rowRealApproval !== undefined ? { realApproval: rowRealApproval } : {}),
|
|
249
257
|
riskDescriptor,
|
|
250
258
|
}
|
|
251
259
|
: durableApproval
|
|
@@ -264,15 +272,26 @@ export function prepareParkAsk(input) {
|
|
|
264
272
|
const scope = durableApproval?.scope || checkpointScopeOf({ principal: spec.principal });
|
|
265
273
|
const ttlMs = sanitizedTtlMs(durableApproval?.ttlMs);
|
|
266
274
|
const checkpointState = serializeCheckpointState(remoteHandle, inFlightSpendMicroUsd());
|
|
267
|
-
if (
|
|
275
|
+
if (rowRealApproval !== undefined && checkpointState.readFace !== undefined) {
|
|
268
276
|
checkpointState.readFace = { ...checkpointState.readFace, realApproval: true };
|
|
269
277
|
}
|
|
270
278
|
const approvalLedger = debitLedger(priorLedger, liveSpendRef.get?.() ?? { costMicroUsd: 0, tokens: 0, turns: 0, walltimeMs: 0 }, resourceTotal, { countSlice: false });
|
|
279
|
+
const rowMatchedAskRule = matchedAskRule ?? storedShapeFacts?.matchedAskRule;
|
|
280
|
+
const clearanceFacts = {
|
|
281
|
+
...(carry?.mandated === true || askMandateMember(storedShapeFacts).mandated === true ? { mandated: true } : {}),
|
|
282
|
+
...(rowRealApproval !== undefined ? { requiresRealApproval: true } : {}),
|
|
283
|
+
...(shadowedRule !== undefined ? { persistedRuleShadowed: shadowedRule } : {}),
|
|
284
|
+
...(askDecisionReason !== undefined ? { decisionReason: askDecisionReason } : {}),
|
|
285
|
+
...(rowMatchedAskRule !== undefined ? { matchedAskRule: rowMatchedAskRule } : {}),
|
|
286
|
+
...(probeMandated === true ? { probeMandated: true } : {}),
|
|
287
|
+
...(inheritedUnavailableAsks.has(req.toolCallId) ? { inheritedUnresolved: true } : {}),
|
|
288
|
+
...(segmentCoverage !== undefined ? { segmentCoverage } : {}),
|
|
289
|
+
};
|
|
271
290
|
const mintedAt = Date.now();
|
|
272
291
|
cp = {
|
|
273
292
|
token,
|
|
274
293
|
checkpointId: mintCheckpointId(),
|
|
275
|
-
version: checkpointVersionFor({ resource: false, binding: true, token: approvalLedger.totalTokens !== undefined, orgAdmission: orgAdmissionCheckpointState(), f012: f012CheckpointState(), realApproval:
|
|
294
|
+
version: checkpointVersionFor({ resource: false, binding: true, token: approvalLedger.totalTokens !== undefined, orgAdmission: orgAdmissionCheckpointState(), f012: f012CheckpointState(), realApproval: rowRealApproval !== undefined, face: faceCheckpointState() }),
|
|
276
295
|
scope,
|
|
277
296
|
sessionId,
|
|
278
297
|
leafId,
|
|
@@ -291,18 +310,10 @@ export function prepareParkAsk(input) {
|
|
|
291
310
|
...(bidi ? { hasBidiControls: true } : {}),
|
|
292
311
|
};
|
|
293
312
|
})(),
|
|
294
|
-
...(
|
|
313
|
+
...(rowRealApproval !== undefined ? { requiresRealApproval: true } : {}),
|
|
314
|
+
...askMandateMember(clearanceFacts),
|
|
295
315
|
...askCarryRowMembers(carry),
|
|
296
|
-
...ruleOffersOf(req.toolName, parkedArgs,
|
|
297
|
-
...(carry?.mandated === true ? { mandated: true } : {}),
|
|
298
|
-
...(realApproval !== undefined ? { requiresRealApproval: true } : {}),
|
|
299
|
-
...(shadowedRule !== undefined ? { persistedRuleShadowed: shadowedRule } : {}),
|
|
300
|
-
...(askDecisionReason !== undefined ? { decisionReason: askDecisionReason } : {}),
|
|
301
|
-
...(matchedAskRule !== undefined ? { matchedAskRule } : {}),
|
|
302
|
-
...(probeMandated === true ? { probeMandated: true } : {}),
|
|
303
|
-
...(inheritedUnavailableAsks.has(req.toolCallId) ? { inheritedUnresolved: true } : {}),
|
|
304
|
-
...(segmentCoverage !== undefined ? { segmentCoverage } : {}),
|
|
305
|
-
}),
|
|
316
|
+
...ruleOffersOf(req.toolName, parkedArgs, clearanceFacts),
|
|
306
317
|
boundInputHash: boundInputHashOf(parkedArgs),
|
|
307
318
|
batchToolCallIds,
|
|
308
319
|
completedCallIds,
|
|
@@ -27,7 +27,8 @@ import type { LockedPreflight } from "../locked-config.js";
|
|
|
27
27
|
import type { MaterializedMcp } from "../mcp.js";
|
|
28
28
|
import type { ResolvedRole } from "../roles.js";
|
|
29
29
|
import type { RunnerDeps, TaskSpec } from "../types.js";
|
|
30
|
-
import type {
|
|
30
|
+
import type { SessionTreeEntry } from "../../internal/harness-types.js";
|
|
31
|
+
import type { DateAnchorRead, PrepareResume, PromptFeatureFlags, RunInternals, ToolFaceSnapshot } from "./contracts.js";
|
|
31
32
|
import type { AdvertisedWritableDirs } from "./advertised-writable-dirs.js";
|
|
32
33
|
import { type GitStatusLaneRef } from "./git-status-frame.js";
|
|
33
34
|
import { type ContextWindowOverlay } from "../context-settings.js";
|
|
@@ -99,6 +100,10 @@ export interface PreparePromptInputsInput {
|
|
|
99
100
|
advertisedWritableDirs?: AdvertisedWritableDirs;
|
|
100
101
|
/** borrowed-readonly — the acquired session's id (operator-line context). */
|
|
101
102
|
sessionId: string;
|
|
103
|
+
/** borrowed-readonly — the acquired session; only `getBranch` is read (the date anchor). */
|
|
104
|
+
session: {
|
|
105
|
+
getBranch(): Promise<ReadonlyArray<SessionTreeEntry>>;
|
|
106
|
+
};
|
|
102
107
|
/** borrowed-readonly — the deployment's window overlay for this leg, as it reads at PREPARE. The prompt's
|
|
103
108
|
* context-management sentence must not claim mid-task summarization a deployment has turned off for this
|
|
104
109
|
* model; the seat is live, so a later swap's effect on the SENTENCE lands at the next prepare while its
|
|
@@ -123,6 +128,8 @@ export interface PreparePromptInputsResult {
|
|
|
123
128
|
tzValid: boolean;
|
|
124
129
|
/** owned — the client's declared zone as given (paired with `tzValid`; unvalidated on its own). */
|
|
125
130
|
userTz: string | undefined;
|
|
131
|
+
/** owned — the session's date anchor as read here; `envFacts.date` is its prefix date when present. */
|
|
132
|
+
dateAnchor: DateAnchorRead | undefined;
|
|
126
133
|
/** owned — the git-status lane's run-local state (empty on a hands-less leg); the run loop and the checkpoint
|
|
127
134
|
* serializer mutate its fields from here on (`announced`, `mirrorOwed`, …; the frame's receipt rides the leg's shared `Prepared.frameReceipts`). */
|
|
128
135
|
gitStatusRef: GitStatusLaneRef;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { defaultPromptProvider, formatLocalDate, isValidTimeZone } from "../../prompts/default.js";
|
|
2
2
|
import { isIsolated } from "../remote-env.js";
|
|
3
|
+
import { readDateAnchor } from "./announce-once-ledger.js";
|
|
3
4
|
import { probeGitStatusLane } from "./git-status-frame.js";
|
|
4
5
|
import { fenceMcpServerInstructions } from "./turn-attachments.js";
|
|
5
6
|
const ULTRA_REASONING_TIERS = new Set(["xhigh", "max"]);
|
|
6
7
|
import { compactionEnabled } from "../context-settings.js";
|
|
7
8
|
export async function preparePromptInputs(input) {
|
|
8
|
-
const { spec, deps, failClosedReason, lockedPreflight, selfOrchestrationActive, executionEnv, reminderMark, resolvedReadFace, resolvedWriteFace, toolFaceSnapshot, promptProfile, fableMitigations, internals, thinking, ownedEnv, delegation, resolvedRole, mcp, model, externalContentTargetActive, resume, handsEnabled, taskRootFinal, additionalRootsCanonical, additionalReadRootsCanonical, sessionId, advertisedWritableDirs } = input;
|
|
9
|
+
const { spec, deps, failClosedReason, lockedPreflight, selfOrchestrationActive, executionEnv, reminderMark, resolvedReadFace, resolvedWriteFace, toolFaceSnapshot, promptProfile, fableMitigations, internals, thinking, ownedEnv, delegation, resolvedRole, mcp, model, externalContentTargetActive, resume, handsEnabled, taskRootFinal, additionalRootsCanonical, additionalReadRootsCanonical, sessionId, session, advertisedWritableDirs } = input;
|
|
9
10
|
const provider = spec.promptProvider ?? deps.promptProvider ?? defaultPromptProvider;
|
|
10
11
|
const promptPolicyEnabled = Boolean(lockedPreflight.toolPolicy);
|
|
11
12
|
const promptHooks = spec.hooks ?? deps.hooks;
|
|
@@ -37,7 +38,8 @@ export async function preparePromptInputs(input) {
|
|
|
37
38
|
: undefined;
|
|
38
39
|
const userTz = spec.clientContext?.timeZone;
|
|
39
40
|
const tzValid = userTz !== undefined && isValidTimeZone(userTz);
|
|
40
|
-
const
|
|
41
|
+
const dateAnchor = await readDateAnchor(session);
|
|
42
|
+
const envFacts = { date: dateAnchor?.current?.prefixDate ?? formatLocalDate(new Date(), tzValid ? userTz : undefined), modelId: model.id };
|
|
41
43
|
if (tzValid)
|
|
42
44
|
envFacts.timeZone = userTz;
|
|
43
45
|
if (spec.clientContext?.userEmail)
|
|
@@ -141,5 +143,5 @@ export async function preparePromptInputs(input) {
|
|
|
141
143
|
taskRoot: taskRootFinal,
|
|
142
144
|
onDegrade: (reason) => deps.onError?.(new Error(`env git snapshot degraded — ${reason}`), { phase: "degraded", sessionId, classification: "env-git-snapshot" }),
|
|
143
145
|
});
|
|
144
|
-
return { provider, featureFlags, userSystemPrompt, userAppendSystemPrompt, mcpInstructionsBlock, envFacts, tzValid, userTz, gitStatusRef };
|
|
146
|
+
return { provider, featureFlags, userSystemPrompt, userAppendSystemPrompt, mcpInstructionsBlock, envFacts, tzValid, userTz, dateAnchor, gitStatusRef };
|
|
145
147
|
}
|
|
@@ -283,7 +283,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
283
283
|
let shellGatedTools = new Set();
|
|
284
284
|
refuseRequireExistingWithoutSession(spec);
|
|
285
285
|
refuseRegistryScopeMismatch(spec, internals);
|
|
286
|
-
const { acquired, session, conflictRef, wakeRecovered
|
|
286
|
+
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 } : {}; })() });
|
|
287
287
|
const sessionId = acquired.sessionId;
|
|
288
288
|
const onceLedger = await loadAnnounceOnceLedger(session, resume?.seed.announcedListings, deps.onError);
|
|
289
289
|
const hostTaskId = spec.taskId ?? sessionId;
|
|
@@ -382,7 +382,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
382
382
|
const ownedEnv = ownedEnvSeat.current;
|
|
383
383
|
const { taskRootFinal, rebaseRestoredPath } = await prepareWorkspaceRestore({ ownedEnv, deps, spec, internals, resume, taskRootInitial, abortController, sessionId });
|
|
384
384
|
const { canonical: taskRootCanonical } = await resolveTaskRootCanonical({ env: executionEnv, given: taskRootFinal, onNotice: deps.onNotice, sessionId, runId });
|
|
385
|
-
const { trackFileEdit, fileHistoryBoundary, restoredFilePaths, rewindNotes, fileHistoryEnabled, historyScope, historyRoot, historyFs } = await prepareFileHistory({ deps, spec, internals, executionEnv, taskRootFinal, handsEnabled, sessionId, session,
|
|
385
|
+
const { trackFileEdit, fileHistoryBoundary, restoredFilePaths, rewindNotes, fileHistoryEnabled, fileHistoryFact, historyScope, historyRoot, historyFs } = await prepareFileHistory({ deps, spec, internals, executionEnv, taskRootFinal, handsEnabled, sessionId, session, abortController });
|
|
386
386
|
const { noteFileEdited, editedFilesSnapshot, harnessRef, toolProgressRef, skillScope, forwardEvent, reviewRequestRef, requestReview, stopRequestedRef, requestStopAfterTurn, planModeRef, enterPlanMode, subagentRetain, worktreeIsolation } = prepareRunRefs({ spec, internals, executionEnv, taskRootFinal });
|
|
387
387
|
const legContextOverlay = () => runnerSelf?.contextOverlayOf?.(harnessRef.current?.getModelRef() ?? resolvedRole.modelRef);
|
|
388
388
|
let resolvedReadFace;
|
|
@@ -521,6 +521,8 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
521
521
|
governedProvenance: orgGovernedProvenance,
|
|
522
522
|
},
|
|
523
523
|
});
|
|
524
|
+
if (memoryEngineSession !== undefined)
|
|
525
|
+
rollback.push(() => memoryEngineSession.release());
|
|
524
526
|
memoryAdmittedOrgScopesRef.current = memoryAdmittedOrgScopes;
|
|
525
527
|
ownOrgVerdictRef.current = memoryOwnOrgVerdict ?? priorOwnOrgVerdict;
|
|
526
528
|
if (internals?.ownOrgAdmissionRef !== undefined && ownOrgVerdictRef.current !== undefined) {
|
|
@@ -594,7 +596,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
594
596
|
}
|
|
595
597
|
const projectContext = await prepareProjectContext({ deps, spec, internals, session, sessionId, hostTaskId, taskRootFinal, handsEnabled, delegation, seedContextFiles, memoryBlockFromEngine, skillScope, roster, toolFaceSnapshot, onceLedger, memoryTools, memoryEngineSession, memorySearchToolsPlanned, memoryPairExcludedName, memoryPairOccupiedName, resume, skillListingBudget: doors.skillListingBudget });
|
|
596
598
|
const { memoryBlock: memoryBlockWithProject, instructionSources, projectInstructionContent, hasSkillManifest, skillsListing, sharedMemoryPairMounted, memoryEnginePairMounted } = projectContext;
|
|
597
|
-
const { provider, featureFlags, userSystemPrompt, userAppendSystemPrompt, mcpInstructionsBlock, envFacts, tzValid, userTz, gitStatusRef } = await preparePromptInputs({ spec, deps, contextOverlay: legContextOverlay(), failClosedReason: selfOrchestrationFailClosedReason(spec, deps), lockedPreflight, selfOrchestrationActive, executionEnv, reminderMark, resolvedReadFace, resolvedWriteFace, toolFaceSnapshot, promptProfile, fableMitigations, internals, thinking, ownedEnv, delegation, resolvedRole, mcp, model, externalContentTargetActive, resume, handsEnabled, taskRootFinal, additionalRootsCanonical, additionalReadRootsCanonical, sessionId, ...(advertisedWritableDirs !== undefined ? { advertisedWritableDirs } : {}) });
|
|
599
|
+
const { provider, featureFlags, userSystemPrompt, userAppendSystemPrompt, mcpInstructionsBlock, envFacts, tzValid, userTz, dateAnchor, gitStatusRef } = await preparePromptInputs({ spec, deps, contextOverlay: legContextOverlay(), failClosedReason: selfOrchestrationFailClosedReason(spec, deps), lockedPreflight, selfOrchestrationActive, executionEnv, reminderMark, resolvedReadFace, resolvedWriteFace, toolFaceSnapshot, promptProfile, fableMitigations, internals, thinking, ownedEnv, delegation, resolvedRole, mcp, model, externalContentTargetActive, resume, handsEnabled, taskRootFinal, additionalRootsCanonical, additionalReadRootsCanonical, sessionId, session, ...(advertisedWritableDirs !== undefined ? { advertisedWritableDirs } : {}) });
|
|
598
600
|
const { deferred, memoryBlock, toolSearch: toolSearchPolicy } = prepareDeferClassify({ spec, deps, roster, toolFaceSnapshot, handsEnabled, fullShellReachable, promptProfile, model, mcp, a2a, sharedMemoryPairMounted, memoryEnginePairMounted, memoryBlock: memoryBlockWithProject, memoryRecallSegment, onceLedger, sessionId });
|
|
599
601
|
prepareMemoryEngineSession({ memoryEngineSession, internals, memoryDelegationEvidence, externalContentTargetActive, lockedPreflight, mcp, sessionId, runId, deps, provenanceForChildrenRef, delegationSettlementRef, spec, envHandToolNames, roster, contentOriginWrapRef });
|
|
600
602
|
const { systemPromptSeat, renderWithDate, systemBlocks, promptManifest, epochDeclaredSections, epochArtifactDigestForSnapshot, buildAssembleInputs, centerAdoptionRef } = await preparePromptAssembly({ session, deps, internals, resume, provider, userSystemPrompt, userAppendSystemPrompt, featureFlags, mcpInstructionsBlock, memoryBlock, envFacts, promptProfile, fableMitigations, tools, model, sessionId, reminderMark, onceLedger });
|
|
@@ -608,7 +610,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
608
610
|
declaredCards: toolRoster.entries.flatMap((e) => e.renderHints?.resultCards ?? []),
|
|
609
611
|
onUndeclared: (type) => deliverEngineNotice(deps.onNotice, { code: "config.tool_card_undeclared", message: `a tool minted a \`details.type\` card ${JSON.stringify(type)} its definition never declared — dropped from tool_end.structured (declare it on the definition's catalog row or the caller's renderHints.resultCards)`, detail: { type, sessionId, runId } }),
|
|
610
612
|
});
|
|
611
|
-
const { agentListing, announcedListingsRef, dateChange } = prepareListings({ spec, tools, onceLedger, sessionId, toolFaceSnapshot, activeTools, resume, skillsListing, listingBudget: doors.skillListingBudget, listingRideRef, renderWithDate, envFacts, tzValid, userTz });
|
|
613
|
+
const { agentListing, announcedListingsRef, dateChange } = prepareListings({ spec, tools, onceLedger, sessionId, toolFaceSnapshot, activeTools, resume, skillsListing, listingBudget: doors.skillListingBudget, listingRideRef, renderWithDate, envFacts, tzValid, userTz, dateAnchor });
|
|
612
614
|
const lastBrainContextRef = {};
|
|
613
615
|
const requestLossyRef = { current: false };
|
|
614
616
|
const staleOffloadWrittenRefs = new Set();
|
|
@@ -707,7 +709,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
707
709
|
}
|
|
708
710
|
}
|
|
709
711
|
const { hooks, hookTimeoutMs, preToolUseObservational, ownGatePreToolUse, basePolicyForResumeEdit, denyNarrowingPolicy, policyLayers, effectivePolicy, inheritedUnavailableAsks, inheritedAskGrants, askSourceIdentity, riskAxesOf, ruleOffersOf, permissionRuleLane, permissionRuleOrgLane, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, foldAskClasses, ancestorSandboxAdmissions } = await preparePolicyChain({ spec, deps, internals, sessionId, runId, hostTaskId, taskRootFinal, executionEnv, lockedPreflight, tools, harnessTools, toolEffects, egressTools, irreversibilityTier, axisExplicitNegatives, shellGatedTools, envHandToolNames, handsCwdRef, readDenyMatcher, questionToolMounted, runtimeCaps, inheritedAncestorRules, ancestorSessionRulesRef, inheritedParentConstraints, seedInheritedGate, hasSkillManifest, skillScope, frozenOnAsk, hookEnvSource, notifyOwnHookCrash, autoModeDecider, stopForDenialLimit, delegation, abortController, now, ownSessionRulesRef });
|
|
710
|
-
const { onAsk, preToolContexts, blockedToolCalls, gateOutcomes, batchHaltRef, blockedTracked, incompleteSuspendAdapter, durableSuspendInfraReady, resourceSuspendEligible, usageGovernance, durableApproval, wiringManifest, writeProtectionCheck, parkLaneArmed, gateMachineryActive, hookIdentity, hookEnvFace, sessionBoxBound } = prepareWiringManifest({ spec, deps, internals, resume, sessionId, runId, hostTaskId, taskScope, hooks, preToolUseObservational, policyLayers, effectivePolicy, handsEnabled, taskRootFinal, mcp, irreversibleTools, egressTools, shellReadStationArmed: shellReadCheck !== undefined, toolEffects, ownedEnv, executionEnv, offloadStore, onceLedger, usageWindows, envLifetimeSuspendAt, runtimeCaps, resolvedInteractionPosture, durableQuestionFace, liveQuestionFace, checkpointStore, sessions, modelGateManifest, autoModeArmReason, lockedPreflight, peerLaneRefs, frameSettlement, harness, pausedRef, frozenOnAsk, liveInheritedGate, delegation, toolRoster, readDenyBuiltinTiersActive: handsReadFace.readDenyBuiltinTiersActive, lspManagerWired, lspDiagnosticsLive: lspDiagnostics !== undefined, sessionBox });
|
|
712
|
+
const { onAsk, preToolContexts, blockedToolCalls, gateOutcomes, batchHaltRef, blockedTracked, incompleteSuspendAdapter, durableSuspendInfraReady, resourceSuspendEligible, usageGovernance, durableApproval, wiringManifest, writeProtectionCheck, parkLaneArmed, gateMachineryActive, hookIdentity, hookEnvFace, sessionBoxBound } = prepareWiringManifest({ spec, deps, internals, resume, sessionId, runId, hostTaskId, taskScope, hooks, preToolUseObservational, policyLayers, effectivePolicy, handsEnabled, taskRootFinal, mcp, irreversibleTools, egressTools, shellReadStationArmed: shellReadCheck !== undefined, toolEffects, ownedEnv, executionEnv, offloadStore, onceLedger, usageWindows, envLifetimeSuspendAt, runtimeCaps, resolvedInteractionPosture, durableQuestionFace, liveQuestionFace, checkpointStore, sessions, modelGateManifest, autoModeArmReason, lockedPreflight, peerLaneRefs, frameSettlement, harness, pausedRef, frozenOnAsk, liveInheritedGate, delegation, toolRoster, readDenyBuiltinTiersActive: handsReadFace.readDenyBuiltinTiersActive, lspManagerWired, lspDiagnosticsLive: lspDiagnostics !== undefined, fileHistoryFact, sessionBox });
|
|
711
713
|
if (fileHistoryBoundary !== undefined) {
|
|
712
714
|
harness.on("tool_call", async () => {
|
|
713
715
|
await fileHistoryBoundary.settle();
|
|
@@ -118,6 +118,7 @@ export interface PrepareWiringManifestInput {
|
|
|
118
118
|
readDenyBuiltinTiersActive: readonly string[];
|
|
119
119
|
/** borrowed-readonly — from the LSP phase's manager fold: gates the manifest's LSP section (absent ⇒ byte-identical manifest). */ lspManagerWired: boolean;
|
|
120
120
|
/** borrowed-readonly — from the LSP phase: is the diagnostics lane live? The `lane` word's only input. */ lspDiagnosticsLive: boolean;
|
|
121
|
+
/** borrowed-readonly — from the file-history phase's one fold of the two off switches: the manifest's word, relayed. */ fileHistoryFact: NonNullable<WiringManifest["fileHistory"]>;
|
|
121
122
|
/** borrowed-readonly — the arming outcome the caps phase minted (the manifest's auto-mode face). */
|
|
122
123
|
autoModeArmReason: AutoModeArmFact;
|
|
123
124
|
/** borrowed-readonly — the frozen preflight; only `mcp` (the declared servers the manifest face joins). */
|
|
@@ -116,7 +116,7 @@ function announceDurableGateUnavailable(args) {
|
|
|
116
116
|
});
|
|
117
117
|
}
|
|
118
118
|
export function prepareWiringManifest(input) {
|
|
119
|
-
const { spec, deps, internals, resume, sessionId, runId, hostTaskId, taskScope, hooks, preToolUseObservational, policyLayers, effectivePolicy, handsEnabled, taskRootFinal, mcp, irreversibleTools, egressTools, toolEffects, ownedEnv, executionEnv, offloadStore, onceLedger, usageWindows, envLifetimeSuspendAt, runtimeCaps, resolvedInteractionPosture, durableQuestionFace, liveQuestionFace, checkpointStore, sessions, modelGateManifest, autoModeArmReason, lockedPreflight, peerLaneRefs, frameSettlement, sessionBox, harness, pausedRef, frozenOnAsk, liveInheritedGate, delegation, toolRoster, readDenyBuiltinTiersActive, lspManagerWired, shellReadStationArmed, lspDiagnosticsLive } = input;
|
|
119
|
+
const { spec, deps, internals, resume, sessionId, runId, hostTaskId, taskScope, hooks, preToolUseObservational, policyLayers, effectivePolicy, handsEnabled, taskRootFinal, mcp, irreversibleTools, egressTools, toolEffects, ownedEnv, executionEnv, offloadStore, onceLedger, usageWindows, envLifetimeSuspendAt, runtimeCaps, resolvedInteractionPosture, durableQuestionFace, liveQuestionFace, checkpointStore, sessions, modelGateManifest, autoModeArmReason, lockedPreflight, peerLaneRefs, frameSettlement, sessionBox, harness, pausedRef, frozenOnAsk, liveInheritedGate, delegation, toolRoster, readDenyBuiltinTiersActive, lspManagerWired, shellReadStationArmed, lspDiagnosticsLive, fileHistoryFact } = input;
|
|
120
120
|
const onAsk = spec.onAsk ?? deps.onAsk;
|
|
121
121
|
const handWriteTools = toolRoster.entries.filter((e) => e.mountedBy === "hands" && (e.effect === "write" || e.effect === "idempotent")).map((e) => e.name);
|
|
122
122
|
const hasEffectAwareGate = Boolean(policyLayers.length > 0 || (hooks?.preToolUse !== undefined && !preToolUseObservational));
|
|
@@ -218,6 +218,7 @@ export function prepareWiringManifest(input) {
|
|
|
218
218
|
tools: toolRoster,
|
|
219
219
|
hooks: wiredHookEntries(hooks, spec.hooks !== undefined ? "spec" : "deps", preToolUseObservational),
|
|
220
220
|
...(lspManagerWired ? { lsp: deriveLspSeam(toolRoster.entries.some((e) => e.contract.contractId === LSP_CONTRACT_ID), lspDiagnosticsLive) } : {}),
|
|
221
|
+
fileHistory: fileHistoryFact,
|
|
221
222
|
});
|
|
222
223
|
peerLaneRefs.askEffective = wiringManifest.ask.effective;
|
|
223
224
|
const sessionBoxBound = sessionBox !== undefined && internals?.onTaskNotification !== undefined ? sessionBox : undefined;
|
|
@@ -14,7 +14,7 @@ export async function runAttachmentSeats(input) {
|
|
|
14
14
|
const listingsLive = (rs.attach.agentListingOn && prepared.agentListing !== undefined) || (rs.attach.skillsListingOn && prepared.skillsListing !== undefined);
|
|
15
15
|
const backgroundTasksLive = (rs.attach.attachmentsCfg?.backgroundTasks ?? eventDefaultOn("background_tasks")) === true;
|
|
16
16
|
rs.attach.attachState = rs.attach.attachmentsCfg !== undefined || listingsLive || backgroundTasksLive ? createAttachmentState() : undefined;
|
|
17
|
-
rs.attach.dateState = prepared.dateChange !== undefined ? { announcedDate: prepared.dateChange.legDate } : undefined;
|
|
17
|
+
rs.attach.dateState = prepared.dateChange !== undefined ? { announcedDate: prepared.dateChange.anchor?.current?.announcedDate ?? prepared.dateChange.legDate } : undefined;
|
|
18
18
|
rs.attach.instrProbe = runner.deps.probeInstructionSources;
|
|
19
19
|
rs.attach.instrState =
|
|
20
20
|
rs.attach.instrProbe !== undefined && prepared.instructionSources !== undefined && prepared.instructionSources.length > 0
|