@sema-agent/core 5.41.0 → 5.43.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 +95 -0
- package/dist/core/checkpoint-store.d.ts +15 -0
- package/dist/core/checkpoint-store.js +5 -1
- package/dist/core/memory-engine/file-backend.js +2 -2
- package/dist/core/memory-engine/layout.d.ts +5 -0
- package/dist/core/memory-engine/layout.js +6 -3
- package/dist/core/park-selfcheck.js +3 -1
- package/dist/core/runner/assemble-result.d.ts +3 -0
- package/dist/core/runner/assemble-result.js +4 -1
- package/dist/core/runner/prepare-hands-readface.d.ts +192 -0
- package/dist/core/runner/prepare-hands-readface.js +283 -0
- package/dist/core/runner/prepare-task.d.ts +3 -5
- package/dist/core/runner/prepare-task.js +22 -233
- package/dist/core/runner/runtask.js +6 -7
- package/dist/core/types.d.ts +23 -6
- package/dist/core/types.js +20 -0
- package/dist/engine/execution-env/node-execution-env.d.ts +8 -0
- package/dist/engine/execution-env/node-execution-env.js +41 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/tools/fs/fs-search-tools.d.ts +8 -0
- package/dist/tools/fs/fs-search-tools.js +70 -58
- package/dist/tools/fs/search.d.ts +42 -9
- package/dist/tools/fs/search.js +125 -77
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +2 -1
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
import { emitTrace } from "../trace.js";
|
|
2
|
+
import { StubExecutionEnv } from "../stub-env.js";
|
|
3
|
+
import { hasBackgroundShell } from "../background-shell.js";
|
|
4
|
+
import { defaultTaskRegistry } from "../task-registry.js";
|
|
5
|
+
import { bashReversibilityProbe, compileReadDeny, createHandsToolkit, deploymentReadFaceClampNotice, pdfModelCapabilitiesOf, resolveReadDenyBuiltins, resolveReadFace, seedReadFileStateFromContext, seedReadFileStateFromTranscript, } from "../../tools/fs/index.js";
|
|
6
|
+
import { resolveKey } from "../../tools/fs/safety.js";
|
|
7
|
+
import { wholeFileRecordsFromTranscript } from "./session-file-state-replay.js";
|
|
8
|
+
import { deliverEngineNotice } from "../types.js";
|
|
9
|
+
import { rebaseWorkspacePath } from "./prepare-workspace-restore.js";
|
|
10
|
+
const readFaceClampAnnouncedSinks = new WeakSet();
|
|
11
|
+
let readFaceClampConsoleAnnounced = false;
|
|
12
|
+
export function __resetReadFaceClampAnnouncement() {
|
|
13
|
+
readFaceClampConsoleAnnounced = false;
|
|
14
|
+
}
|
|
15
|
+
export function resolveHandsLessReadFace(input) {
|
|
16
|
+
const { resume, fullShellReachable, spec, deps } = input;
|
|
17
|
+
let handsLessResolvedFace;
|
|
18
|
+
let readDenyAdditionsNormalized = [];
|
|
19
|
+
{
|
|
20
|
+
const liveFace = resolveReadFace({
|
|
21
|
+
specReadFace: spec.readFace,
|
|
22
|
+
depsReadFace: deps.readFace,
|
|
23
|
+
readOnlyMount: spec.handsReadOnly === true,
|
|
24
|
+
orgGoverned: deps.permissionRuleOrg !== undefined,
|
|
25
|
+
fullShellReachable,
|
|
26
|
+
});
|
|
27
|
+
const seed = resume?.seed.readFace;
|
|
28
|
+
handsLessResolvedFace = resume !== undefined && (seed === undefined || seed.face === "roots") ? "roots" : liveFace;
|
|
29
|
+
const denyAdditions = [...(deps.readDenyPatterns ?? []), ...(spec.readDenyPatterns ?? []), ...(seed?.denyEntries ?? [])];
|
|
30
|
+
resolveReadDenyBuiltins({
|
|
31
|
+
...(deps.readDenyBuiltinTiers !== undefined ? { tiers: deps.readDenyBuiltinTiers } : {}),
|
|
32
|
+
...(deps.readDenyBuiltinExclude !== undefined ? { exclude: deps.readDenyBuiltinExclude } : {}),
|
|
33
|
+
});
|
|
34
|
+
if (denyAdditions.length > 0) {
|
|
35
|
+
readDenyAdditionsNormalized = compileReadDeny(denyAdditions, "readDenyPatterns", { tiers: [] }).entries;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
readFileStateForCheckpoint: undefined,
|
|
40
|
+
seedContextFiles: undefined,
|
|
41
|
+
handsCwdRef: undefined,
|
|
42
|
+
workspaceStateSettle: undefined,
|
|
43
|
+
wsSnapshot: undefined,
|
|
44
|
+
rebaseWsPath: (p) => p,
|
|
45
|
+
backgroundTaskToolsActive: false,
|
|
46
|
+
resolvedReadFace: undefined,
|
|
47
|
+
readDenyAdditionsNormalized,
|
|
48
|
+
handsLessResolvedFace,
|
|
49
|
+
additionalRootsCanonical: [],
|
|
50
|
+
additionalReadRootsCanonical: [],
|
|
51
|
+
attachmentRootCanonical: undefined,
|
|
52
|
+
readDenyMatcher: undefined,
|
|
53
|
+
shellGatedBash: false,
|
|
54
|
+
shellGatedMonitor: false,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
export async function prepareHandsMount(input) {
|
|
58
|
+
const { handsEnabled, executionEnv, taskRootFinal, rebaseRestoredPath, resume, session, sessionId, hostTaskId, taskScope, fullShellReachable, effectiveShellGate, toolFaceSnapshot, model, spec, deps, internals, memoryWriteGateRef, firstPartyOffload, tools, egressTools, irreversibilityTier, irreversibleTools, reversibilityProbes } = input;
|
|
59
|
+
let readFileStateForCheckpoint;
|
|
60
|
+
let seedContextFiles;
|
|
61
|
+
let handsCwdRef;
|
|
62
|
+
let workspaceStateSettle;
|
|
63
|
+
let wsSnapshot;
|
|
64
|
+
let rebaseWsPath = (p) => p;
|
|
65
|
+
let backgroundTaskToolsActive = false;
|
|
66
|
+
let resolvedReadFace;
|
|
67
|
+
let readDenyAdditionsNormalized = [];
|
|
68
|
+
let handsLessResolvedFace;
|
|
69
|
+
let shellGatedBash = false;
|
|
70
|
+
let shellGatedMonitor = false;
|
|
71
|
+
const additionalRootsCanonical = [];
|
|
72
|
+
const additionalReadRootsCanonical = [];
|
|
73
|
+
let attachmentRootCanonical;
|
|
74
|
+
let readDenyMatcher;
|
|
75
|
+
if (handsEnabled) {
|
|
76
|
+
const rootRaw = taskRootFinal;
|
|
77
|
+
const canon = await executionEnv.canonicalPath(rootRaw);
|
|
78
|
+
const rootCanonical = canon.ok ? canon.value : rootRaw;
|
|
79
|
+
attachmentRootCanonical = rootCanonical;
|
|
80
|
+
const canonicalizeExtraDirs = async (dirs, field, sink) => {
|
|
81
|
+
for (const dir of dirs ?? []) {
|
|
82
|
+
if (!dir || !dir.trim())
|
|
83
|
+
continue;
|
|
84
|
+
const c = await executionEnv.canonicalPath(dir);
|
|
85
|
+
if (c.ok) {
|
|
86
|
+
sink.push(c.value);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
deps.onError?.(new Error(`${field} entry skipped (cannot canonicalize): ${dir}`), {
|
|
90
|
+
phase: "config",
|
|
91
|
+
sessionId,
|
|
92
|
+
});
|
|
93
|
+
emitTrace(deps.tracer, () => ({
|
|
94
|
+
kind: "config.additional_directory_skipped",
|
|
95
|
+
version: 1,
|
|
96
|
+
taskId: hostTaskId,
|
|
97
|
+
entry: dir,
|
|
98
|
+
...(field !== "additionalDirectories" ? { field } : {}),
|
|
99
|
+
reason: `${c.error.code}: ${c.error.message}`,
|
|
100
|
+
ts: Date.now(),
|
|
101
|
+
}));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
await canonicalizeExtraDirs(spec.additionalDirectories, "additionalDirectories", additionalRootsCanonical);
|
|
106
|
+
await canonicalizeExtraDirs(spec.additionalReadDirectories, "additionalReadDirectories", additionalReadRootsCanonical);
|
|
107
|
+
if (spec.envFacts?.scratchpadDir) {
|
|
108
|
+
let c = await executionEnv.canonicalPath(spec.envFacts.scratchpadDir);
|
|
109
|
+
if (!c.ok && c.error.code === "not_found") {
|
|
110
|
+
const marker = await executionEnv.joinPath([spec.envFacts.scratchpadDir, ".sema-scratchpad"]);
|
|
111
|
+
const exclusiveCreate = executionEnv.writeFileExclusive?.bind(executionEnv);
|
|
112
|
+
if (marker.ok && exclusiveCreate) {
|
|
113
|
+
const w = await exclusiveCreate(marker.value, "");
|
|
114
|
+
if (w.ok || w.error.code === "already_exists")
|
|
115
|
+
c = await executionEnv.canonicalPath(spec.envFacts.scratchpadDir);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (c.ok)
|
|
119
|
+
additionalRootsCanonical.push(c.value);
|
|
120
|
+
}
|
|
121
|
+
for (const a of [additionalRootsCanonical, additionalReadRootsCanonical])
|
|
122
|
+
a.splice(0, a.length, ...new Set(a));
|
|
123
|
+
const readFileState = new Map((resume?.seed.readFileState ?? []).map(([k, v]) => [rebaseRestoredPath(k), v]));
|
|
124
|
+
readFileStateForCheckpoint = readFileState;
|
|
125
|
+
seedContextFiles = async (files) => {
|
|
126
|
+
for (const f of files) {
|
|
127
|
+
const rk = await resolveKey(executionEnv, rootCanonical, f.path, undefined, undefined, [...additionalRootsCanonical, ...additionalReadRootsCanonical], undefined, undefined, resolvedReadFace);
|
|
128
|
+
if (rk.ok)
|
|
129
|
+
seedReadFileStateFromContext(readFileState, rk.key, f.content);
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
const handsIncludeShell = !(executionEnv instanceof StubExecutionEnv);
|
|
133
|
+
const handsReadOnly = spec.handsReadOnly === true;
|
|
134
|
+
backgroundTaskToolsActive = handsIncludeShell && !handsReadOnly && hasBackgroundShell(executionEnv);
|
|
135
|
+
wsSnapshot = resume !== undefined || !(handsIncludeShell && !handsReadOnly) ? undefined : await session.getWorkspaceState().catch(() => undefined);
|
|
136
|
+
rebaseWsPath = (p) => (wsSnapshot === undefined || wsSnapshot.taskRoot === rootCanonical ? p : rebaseWorkspacePath(p, wsSnapshot.taskRoot, rootCanonical));
|
|
137
|
+
if (handsIncludeShell && !handsReadOnly) {
|
|
138
|
+
handsCwdRef = { current: rootCanonical };
|
|
139
|
+
if (resume?.seed.handsCwd !== undefined)
|
|
140
|
+
handsCwdRef.current = rebaseRestoredPath(resume.seed.handsCwd);
|
|
141
|
+
else if (wsSnapshot?.handsCwd !== undefined)
|
|
142
|
+
handsCwdRef.current = rebaseWsPath(wsSnapshot.handsCwd);
|
|
143
|
+
workspaceStateSettle = {
|
|
144
|
+
rootCanonical,
|
|
145
|
+
restoredHandsCwd: handsCwdRef.current !== rootCanonical ? handsCwdRef.current : undefined,
|
|
146
|
+
...(resume !== undefined ? { baselineUnknown: true } : {}),
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
const seedReadFaceSection = resume?.seed.readFace;
|
|
150
|
+
const readDenyAdditions = [...(deps.readDenyPatterns ?? []), ...(spec.readDenyPatterns ?? []), ...(seedReadFaceSection?.denyEntries ?? [])];
|
|
151
|
+
const readDenyBuiltinCfg = {
|
|
152
|
+
...(deps.readDenyBuiltinTiers !== undefined ? { tiers: [...deps.readDenyBuiltinTiers] } : {}),
|
|
153
|
+
...(deps.readDenyBuiltinExclude !== undefined ? { exclude: [...deps.readDenyBuiltinExclude] } : {}),
|
|
154
|
+
};
|
|
155
|
+
readDenyMatcher = compileReadDeny(readDenyAdditions, "readDenyPatterns", readDenyBuiltinCfg);
|
|
156
|
+
readDenyAdditionsNormalized = compileReadDeny(readDenyAdditions, "readDenyPatterns", { tiers: [] }).entries;
|
|
157
|
+
let liveReadFace = resolveReadFace({
|
|
158
|
+
specReadFace: spec.readFace,
|
|
159
|
+
depsReadFace: deps.readFace,
|
|
160
|
+
readOnlyMount: handsReadOnly,
|
|
161
|
+
orgGoverned: deps.permissionRuleOrg !== undefined,
|
|
162
|
+
fullShellReachable,
|
|
163
|
+
onDeploymentClamp: () => {
|
|
164
|
+
const sink = deps.onNotice;
|
|
165
|
+
if (typeof sink === "function") {
|
|
166
|
+
if (readFaceClampAnnouncedSinks.has(sink))
|
|
167
|
+
return;
|
|
168
|
+
readFaceClampAnnouncedSinks.add(sink);
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
if (readFaceClampConsoleAnnounced)
|
|
172
|
+
return;
|
|
173
|
+
readFaceClampConsoleAnnounced = true;
|
|
174
|
+
}
|
|
175
|
+
deliverEngineNotice(sink, deploymentReadFaceClampNotice());
|
|
176
|
+
},
|
|
177
|
+
});
|
|
178
|
+
if (resume !== undefined && (seedReadFaceSection === undefined || seedReadFaceSection.face === "roots"))
|
|
179
|
+
liveReadFace = "roots";
|
|
180
|
+
resolvedReadFace = liveReadFace;
|
|
181
|
+
if (resume === undefined && spec.sessionId !== undefined) {
|
|
182
|
+
const prior = await session.buildContext().catch(() => undefined);
|
|
183
|
+
for (const rec of wholeFileRecordsFromTranscript(prior?.messages ?? [])) {
|
|
184
|
+
const rk = await resolveKey(executionEnv, rootCanonical, rec.path, undefined, undefined, [...additionalRootsCanonical, ...additionalReadRootsCanonical], undefined, undefined, liveReadFace);
|
|
185
|
+
if (rk.ok)
|
|
186
|
+
seedReadFileStateFromTranscript(readFileState, rk.key, rec.content, rec.at);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
const band = createHandsToolkit(executionEnv, readFileState, rootCanonical, {
|
|
190
|
+
...(additionalRootsCanonical.length > 0 ? { additionalRoots: additionalRootsCanonical } : {}),
|
|
191
|
+
...(additionalReadRootsCanonical.length > 0 ? { additionalReadRoots: additionalReadRootsCanonical } : {}),
|
|
192
|
+
...(readDenyAdditions.length > 0 ? { readDenyPatterns: readDenyAdditions } : {}),
|
|
193
|
+
...(readDenyBuiltinCfg.tiers !== undefined ? { readDenyBuiltinTiers: readDenyBuiltinCfg.tiers } : {}),
|
|
194
|
+
...(readDenyBuiltinCfg.exclude !== undefined ? { readDenyBuiltinExclude: readDenyBuiltinCfg.exclude } : {}),
|
|
195
|
+
readFace: liveReadFace,
|
|
196
|
+
includeShell: handsIncludeShell,
|
|
197
|
+
readOnly: handsReadOnly,
|
|
198
|
+
...(handsCwdRef ? { cwdRef: handsCwdRef } : {}),
|
|
199
|
+
taskRegistry: defaultTaskRegistry,
|
|
200
|
+
taskOwner: hostTaskId,
|
|
201
|
+
taskScope,
|
|
202
|
+
oneShot: spec.oneShot,
|
|
203
|
+
...(sessionId !== undefined ? { sessionId } : {}),
|
|
204
|
+
...(internals?.onTaskNotification !== undefined ? { taskNotification: internals.onTaskNotification } : {}),
|
|
205
|
+
...(internals?.detachHub !== undefined ? { detachHub: internals.detachHub } : {}),
|
|
206
|
+
...(deps.onNotice !== undefined ? { onNotice: deps.onNotice } : {}),
|
|
207
|
+
pdfModelCapabilities: pdfModelCapabilitiesOf(model),
|
|
208
|
+
...(deps.hands?.bashReadonlyAllow !== undefined ? { bashReadonlyAllow: deps.hands.bashReadonlyAllow } : {}),
|
|
209
|
+
...(deps.hands?.commitCoAuthor !== undefined ? { commitCoAuthor: deps.hands.commitCoAuthor } : {}),
|
|
210
|
+
...(deps.hands?.readImageDownsampler !== undefined ? { readImageDownsampler: deps.hands.readImageDownsampler } : {}),
|
|
211
|
+
...(deps.hands?.autoBackgroundOnTimeout !== undefined ? { autoBackgroundOnTimeout: deps.hands.autoBackgroundOnTimeout } : {}),
|
|
212
|
+
...(deps.hands?.readCyberReminder !== undefined ? { readCyberReminder: deps.hands.readCyberReminder } : {}),
|
|
213
|
+
beforeWrite: async (w) => {
|
|
214
|
+
const deploymentGate = deps.hands?.beforeWrite;
|
|
215
|
+
if (deploymentGate) {
|
|
216
|
+
const verdict = await deploymentGate(w);
|
|
217
|
+
if (verdict !== undefined && verdict.ok === false)
|
|
218
|
+
return verdict;
|
|
219
|
+
}
|
|
220
|
+
return memoryWriteGateRef.current?.(w);
|
|
221
|
+
},
|
|
222
|
+
mountBackgroundTaskTools: false,
|
|
223
|
+
monitorToolActive: backgroundTaskToolsActive && !(toolFaceSnapshot.exclude?.includes("Monitor") ?? false),
|
|
224
|
+
});
|
|
225
|
+
{
|
|
226
|
+
const bandNames = new Set(band.flatMap((t) => [t.name, ...(t.aliases ?? [])]));
|
|
227
|
+
const shadowed = (spec.tools ?? []).filter((t) => [t.name, ...(t.aliases ?? [])].some((n) => bandNames.has(n)));
|
|
228
|
+
if (shadowed.length > 0) {
|
|
229
|
+
const names = shadowed.map((t) => `"${t.name}"`).join(", ");
|
|
230
|
+
deps.onError?.(new Error(`spec.tools ${shadowed.length > 1 ? "entries" : "entry"} ${names} collide${shadowed.length > 1 ? "" : "s"} with the built-in hands tool band — the built-in wins (registered later; the harness tool Map is last-write-wins) and the caller tool never dispatches this task. Rename the caller tool, or don't inject executionEnv if you intend to replace the band.`), { phase: "config", sessionId });
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
tools.push(...band.map((t) => firstPartyOffload(t)));
|
|
234
|
+
const shellGate = effectiveShellGate;
|
|
235
|
+
if (shellGate === "off" && !(executionEnv instanceof StubExecutionEnv) && spec.handsReadOnly !== true) {
|
|
236
|
+
deps.onError?.(new Error(`shell gate doctrine is "off" while a real writable shell (Bash) is mounted — no shell safety-axis ` +
|
|
237
|
+
`fold applies to this run (commands are adjudicated by the ordinary policy/hook chain only). ` +
|
|
238
|
+
`Set spec.shellGate to "classify" or "always" if this deployment expects doctrine-gated shell behavior.`), { phase: "config", sessionId, classification: "shell-gate-off" });
|
|
239
|
+
}
|
|
240
|
+
if (shellGate !== "off" && !(executionEnv instanceof StubExecutionEnv) && spec.handsReadOnly !== true) {
|
|
241
|
+
const bashTierBefore = irreversibilityTier.get("Bash");
|
|
242
|
+
shellGatedBash = !egressTools.has("Bash") && bashTierBefore !== "always" && bashTierBefore !== "maybe";
|
|
243
|
+
const bashEffectiveTier = shellGate === "always" || bashTierBefore === "always" ? "always" : "maybe";
|
|
244
|
+
irreversibilityTier.set("Bash", bashEffectiveTier);
|
|
245
|
+
irreversibleTools.add("Bash");
|
|
246
|
+
const shellReadBoundary = () => ({
|
|
247
|
+
roots: [rootCanonical, ...additionalRootsCanonical, ...additionalReadRootsCanonical],
|
|
248
|
+
...(handsCwdRef?.current !== undefined ? { cwd: handsCwdRef.current } : {}),
|
|
249
|
+
denyMatch: (p) => readDenyMatcher?.matchPath(p)?.pattern ?? null,
|
|
250
|
+
...(resolvedReadFace !== undefined ? { face: resolvedReadFace } : {}),
|
|
251
|
+
});
|
|
252
|
+
if (shellGate === "classify" && shellGatedBash)
|
|
253
|
+
reversibilityProbes.set("Bash", bashReversibilityProbe(undefined, shellReadBoundary));
|
|
254
|
+
if (backgroundTaskToolsActive) {
|
|
255
|
+
const monitorTierBefore = irreversibilityTier.get("Monitor");
|
|
256
|
+
shellGatedMonitor = !egressTools.has("Monitor") && monitorTierBefore !== "always" && monitorTierBefore !== "maybe";
|
|
257
|
+
const monitorEffectiveTier = shellGate === "always" || monitorTierBefore === "always" ? "always" : "maybe";
|
|
258
|
+
irreversibilityTier.set("Monitor", monitorEffectiveTier);
|
|
259
|
+
irreversibleTools.add("Monitor");
|
|
260
|
+
if (shellGate === "classify" && shellGatedMonitor)
|
|
261
|
+
reversibilityProbes.set("Monitor", bashReversibilityProbe(undefined, shellReadBoundary));
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
return {
|
|
266
|
+
readFileStateForCheckpoint,
|
|
267
|
+
seedContextFiles,
|
|
268
|
+
handsCwdRef,
|
|
269
|
+
workspaceStateSettle,
|
|
270
|
+
wsSnapshot,
|
|
271
|
+
rebaseWsPath,
|
|
272
|
+
backgroundTaskToolsActive,
|
|
273
|
+
resolvedReadFace,
|
|
274
|
+
readDenyAdditionsNormalized,
|
|
275
|
+
handsLessResolvedFace,
|
|
276
|
+
additionalRootsCanonical,
|
|
277
|
+
additionalReadRootsCanonical,
|
|
278
|
+
attachmentRootCanonical,
|
|
279
|
+
readDenyMatcher,
|
|
280
|
+
shellGatedBash,
|
|
281
|
+
shellGatedMonitor,
|
|
282
|
+
};
|
|
283
|
+
}
|
|
@@ -37,11 +37,7 @@ export declare function __resetMaterializeEnvAnnouncements(): void;
|
|
|
37
37
|
* seam below (console latch only): tests here legitimately reuse ONE sink across prepares to pin
|
|
38
38
|
* the per-sink dedup itself, so the seam must be able to re-arm a still-referenced sink. */
|
|
39
39
|
export declare function __resetToolModelGateAnnouncements(): void;
|
|
40
|
-
|
|
41
|
-
* Deliberately asymmetric — it resets only the console latch: the WeakSet arm needs no seam
|
|
42
|
-
* because a test resets it by minting a fresh sink function (identity IS the ledger key), while
|
|
43
|
-
* the console arm's key is the process itself, which only this seam can refresh. */
|
|
44
|
-
export declare function __resetReadFaceClampAnnouncement(): void;
|
|
40
|
+
export { __resetReadFaceClampAnnouncement } from "./prepare-hands-readface.js";
|
|
45
41
|
/**
|
|
46
42
|
* design/164 件四 — how long before an execution environment's declared `lifetimeMs` expires the engine
|
|
47
43
|
* stops the run and checkpoints it. The margin has to cover ONE suspend: pausing/snapshotting the
|
|
@@ -437,6 +433,7 @@ export interface Prepared {
|
|
|
437
433
|
* fired this run. */
|
|
438
434
|
suspendRef: {
|
|
439
435
|
token?: CheckpointToken;
|
|
436
|
+
checkpointId?: string;
|
|
440
437
|
gate?: CheckpointGate;
|
|
441
438
|
scope?: string;
|
|
442
439
|
restoreMode?: "snapshot" | "park_only";
|
|
@@ -457,6 +454,7 @@ export interface Prepared {
|
|
|
457
454
|
* `status:"needs_review"`. Empty unless a review pause fired this run. */
|
|
458
455
|
reviewRef: {
|
|
459
456
|
token?: CheckpointToken;
|
|
457
|
+
checkpointId?: string;
|
|
460
458
|
gate?: CheckpointGate;
|
|
461
459
|
scope?: string;
|
|
462
460
|
restoreMode?: "snapshot" | "park_only";
|