@sema-agent/core 7.14.0 → 7.16.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 +59 -0
- package/dist/core/ask-origin.d.ts +2 -2
- package/dist/core/checkpoint-store.d.ts +14 -15
- package/dist/core/governance-codes.js +2 -0
- package/dist/core/hooks.d.ts +4 -3
- package/dist/core/memory-engine/delegation-settlement.d.ts +37 -12
- package/dist/core/memory-engine/delegation-settlement.js +128 -39
- package/dist/core/memory-engine/engine.d.ts +9 -8
- package/dist/core/memory-engine/engine.js +115 -120
- package/dist/core/memory-engine/file-backend.d.ts +17 -5
- package/dist/core/memory-engine/file-backend.js +78 -34
- package/dist/core/memory-engine/index.d.ts +2 -2
- package/dist/core/memory-engine/index.js +2 -2
- package/dist/core/memory-engine/layout.d.ts +152 -54
- package/dist/core/memory-engine/layout.js +441 -104
- package/dist/core/memory-engine/types.d.ts +8 -3
- package/dist/core/memory-engine/types.js +5 -0
- package/dist/core/runner/abort-race.d.ts +3 -3
- package/dist/core/runner/active-skill-scope.d.ts +2 -2
- package/dist/core/runner/assemble-result.d.ts +29 -29
- package/dist/core/runner/checkpoint-scope.d.ts +4 -4
- package/dist/core/runner/clock-and-limits.d.ts +3 -3
- package/dist/core/runner/compaction-call-options.d.ts +11 -11
- package/dist/core/runner/compaction-knobs.d.ts +4 -4
- package/dist/core/runner/compaction-seams.d.ts +5 -5
- package/dist/core/runner/contracts.d.ts +224 -226
- package/dist/core/runner/decide-continuation.d.ts +6 -6
- package/dist/core/runner/denial-limit-arms.d.ts +8 -8
- package/dist/core/runner/derived-route-fallback.d.ts +2 -2
- package/dist/core/runner/gate-exit.d.ts +6 -6
- package/dist/core/runner/git-status-frame.d.ts +7 -7
- package/dist/core/runner/inherited-ask-grants.d.ts +6 -6
- package/dist/core/runner/memory-capture-optout.d.ts +1 -1
- package/dist/core/runner/memory-consolidation-driver.d.ts +4 -4
- package/dist/core/runner/memory-consolidation.d.ts +6 -6
- package/dist/core/runner/park-commit.d.ts +6 -6
- package/dist/core/runner/permission-rule-lanes.d.ts +22 -20
- package/dist/core/runner/permission-rule-lanes.js +1 -1
- package/dist/core/runner/prepare-acquire-reconcile.d.ts +4 -4
- package/dist/core/runner/prepare-ask-lane.d.ts +3 -3
- package/dist/core/runner/prepare-boundary-parks.d.ts +3 -3
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +5 -5
- package/dist/core/runner/prepare-config-doors.d.ts +21 -21
- package/dist/core/runner/prepare-context-lane.d.ts +6 -6
- package/dist/core/runner/prepare-defer-classify.d.ts +3 -3
- package/dist/core/runner/prepare-defer-classify.js +12 -10
- package/dist/core/runner/prepare-delegation-surface.d.ts +1 -1
- package/dist/core/runner/prepare-file-history.d.ts +2 -2
- package/dist/core/runner/prepare-gate-stations.d.ts +8 -9
- package/dist/core/runner/prepare-gate-stations.js +2 -2
- package/dist/core/runner/prepare-hands-readface.d.ts +41 -41
- package/dist/core/runner/prepare-hands-readface.js +27 -29
- package/dist/core/runner/prepare-inherited-gate.d.ts +6 -6
- package/dist/core/runner/prepare-listings.d.ts +3 -3
- package/dist/core/runner/prepare-lsp.d.ts +3 -3
- package/dist/core/runner/prepare-memory-engine-session.d.ts +5 -5
- package/dist/core/runner/prepare-memory.js +6 -7
- package/dist/core/runner/prepare-offload-wrappers.d.ts +2 -2
- package/dist/core/runner/prepare-park-ask.d.ts +11 -12
- package/dist/core/runner/prepare-park-ask.js +3 -3
- package/dist/core/runner/prepare-policy-chain.d.ts +6 -6
- package/dist/core/runner/prepare-policy-chain.js +2 -2
- package/dist/core/runner/prepare-prompt-inputs.d.ts +5 -5
- package/dist/core/runner/prepare-protocol-tools.d.ts +1 -1
- package/dist/core/runner/prepare-question-face.d.ts +4 -4
- package/dist/core/runner/prepare-run-refs.d.ts +11 -11
- package/dist/core/runner/prepare-safety-scan.d.ts +1 -1
- package/dist/core/runner/prepare-suspend-saga.d.ts +4 -4
- package/dist/core/runner/prepare-task.d.ts +12 -12
- package/dist/core/runner/prepare-task.js +5 -7
- package/dist/core/runner/prepare-tool-disclosure-mount.d.ts +2 -3
- package/dist/core/runner/prepare-wiring-manifest.d.ts +4 -4
- package/dist/core/runner/prepare-workspace-restore.d.ts +1 -1
- package/dist/core/runner/remote-env-retry.d.ts +3 -3
- package/dist/core/runner/resume-admission.d.ts +1 -1
- package/dist/core/runner/resume-claim.d.ts +1 -1
- package/dist/core/runner/resume-internals-and-config.d.ts +1 -1
- package/dist/core/runner/resume-policy-outcome.d.ts +1 -1
- package/dist/core/runner/resume-preflight.d.ts +1 -1
- package/dist/core/runner/resume-review-outcome.d.ts +1 -1
- package/dist/core/runner/run-brain-sinks.d.ts +1 -1
- package/dist/core/runner/run-clock-and-content.d.ts +4 -4
- package/dist/core/runner/run-compaction-machinery.d.ts +3 -3
- package/dist/core/runner/run-git-lane.d.ts +1 -1
- package/dist/core/runner/run-harness-handlers.d.ts +2 -2
- package/dist/core/runner/run-identity-wiring.d.ts +4 -4
- package/dist/core/runner/run-leg.d.ts +3 -3
- package/dist/core/runner/run-notification-lane.d.ts +2 -2
- package/dist/core/runner/run-reasoning-seat.d.ts +2 -2
- package/dist/core/runner/run-settle-and-teardown.d.ts +4 -4
- package/dist/core/runner/run-telemetry-and-budget-seats.d.ts +2 -2
- package/dist/core/runner/run-terminal-adoption.d.ts +5 -5
- package/dist/core/runner/runtask.d.ts +14 -14
- package/dist/core/runner/session-file-state-replay.d.ts +3 -3
- package/dist/core/runner/session-rule-policy.d.ts +2 -2
- package/dist/core/runner/steer-admission.d.ts +2 -2
- package/dist/core/runner/stream-halt-verbs.d.ts +1 -1
- package/dist/core/runner/stream-reap.d.ts +1 -1
- package/dist/core/runner/synthetic-tools.d.ts +8 -8
- package/dist/core/runner/teardown-bounded.d.ts +2 -2
- package/dist/core/runner/tool-defer-gate.d.ts +86 -0
- package/dist/core/runner/tool-defer-gate.js +57 -0
- package/dist/core/runner/tool-disclosure.d.ts +33 -69
- package/dist/core/runner/tool-disclosure.js +0 -43
- package/dist/core/runner/tool-end-body.d.ts +3 -3
- package/dist/core/runner/tool-face-overlay.d.ts +2 -2
- package/dist/core/runner/tool-output-projection.d.ts +2 -2
- package/dist/core/runner/turn-attachments.d.ts +53 -53
- package/dist/core/runner/usage-accounting.d.ts +4 -4
- package/dist/core/runner/workspace-path.d.ts +1 -1
- package/dist/core/runner-deps.d.ts +16 -9
- package/dist/core/task-spec.d.ts +8 -2
- package/dist/core/tool-spec.d.ts +7 -4
- package/dist/core/types.d.ts +1 -1
- package/dist/engine/llm/types.d.ts +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +3 -3
- package/dist/tools/fs/bash-readonly-classifier.d.ts +40 -40
- package/dist/tools/fs/encoding.d.ts +31 -40
- package/dist/tools/fs/fs-bash.d.ts +76 -35
- package/dist/tools/fs/fs-bash.js +86 -29
- package/dist/tools/fs/fs-pdf.d.ts +8 -8
- package/dist/tools/fs/fs-search-tools.d.ts +4 -4
- package/dist/tools/fs/fs-shared.d.ts +144 -158
- package/dist/tools/fs/fs-write.d.ts +8 -8
- package/dist/tools/fs/gh-rate-limit.d.ts +13 -14
- package/dist/tools/fs/index.d.ts +74 -78
- package/dist/tools/fs/notebook.d.ts +24 -25
- package/dist/tools/fs/pdf.d.ts +3 -3
- package/dist/tools/fs/read-deny.d.ts +22 -22
- package/dist/tools/fs/read-face.d.ts +21 -24
- package/dist/tools/fs/repo-map.d.ts +8 -8
- package/dist/tools/fs/safety.d.ts +116 -129
- package/dist/tools/fs/search.d.ts +63 -71
- package/package.json +5 -2
- package/test/export-surface.snapshot.json +9 -1
|
@@ -43,7 +43,7 @@ import type { SystemInjectionPriority, TaskNotificationPayload } from "../task-n
|
|
|
43
43
|
import type { OnAsk, PermissionResult, ResolvedAsk, ToolCallRequest, ToolPolicy } from "../tool-policy.js";
|
|
44
44
|
import type { RemoteExecutionEnv, SnapshotId, WorkspaceHandle } from "../remote-env.js";
|
|
45
45
|
import type { ToolDisclosureManifest } from "../trace.js";
|
|
46
|
-
import type { AgentDefinition, Brain, CompactOutcome, ModelRoles, NestedUsageAccum, RunnerDeps, TaskEvent, TaskResult, TaskSpec, TaskStream, ToolActivity, ToolEffect } from "../types.js";
|
|
46
|
+
import type { AgentDefinition, Brain, CompactOutcome, ModelRoles, NestedUsageAccum, RunnerDeps, ShellGateDoctrine, TaskEvent, TaskResult, TaskSpec, TaskStream, ToolActivity, ToolEffect } from "../types.js";
|
|
47
47
|
import type { WiringManifest } from "../wiring-manifest.js";
|
|
48
48
|
import type { ActiveSkillFrame } from "./active-skill-scope.js";
|
|
49
49
|
import type { BudgetAxis } from "./assemble-result.js";
|
|
@@ -62,7 +62,7 @@ export interface ToolFaceSnapshot {
|
|
|
62
62
|
exclude: readonly string[] | undefined;
|
|
63
63
|
defer: readonly string[] | undefined;
|
|
64
64
|
alwaysLoad: readonly string[] | undefined;
|
|
65
|
-
/**
|
|
65
|
+
/** The model-gate restore selector ({@link TaskSpec.restoreGatedTools}), fourth
|
|
66
66
|
* seat of the same frozen task-start snapshot: the gate decision and the delegation carrier
|
|
67
67
|
* read THIS, never the live spec. */
|
|
68
68
|
restoreGated: readonly string[] | true | undefined;
|
|
@@ -94,8 +94,7 @@ export type ReversibilityProbes = Map<string, NonNullable<TaskSpec["tools"]>[num
|
|
|
94
94
|
* each exactly once, none of them able to stop another — a bounded settle, the same posture the
|
|
95
95
|
* teardown leg already uses. NEVER call unwind on the success path.
|
|
96
96
|
*
|
|
97
|
-
* The detach guard for an owned execution env and the worktree-isolation check stay with the DRIVER
|
|
98
|
-
* (design/238 D-8 case ①): a phase pushes, it does not destroy, because the driver's reference is
|
|
97
|
+
* The detach guard for an owned execution env and the worktree-isolation check stay with the DRIVER: a phase pushes, it does not destroy, because the driver's reference is
|
|
99
98
|
* the authoritative one and a phase-local rebind could never reach it.
|
|
100
99
|
*/
|
|
101
100
|
export interface RollbackStack {
|
|
@@ -107,7 +106,7 @@ export interface RollbackStack {
|
|
|
107
106
|
unwindAll(): Promise<void>;
|
|
108
107
|
}
|
|
109
108
|
/**
|
|
110
|
-
*
|
|
109
|
+
* The run's view of deployment usage governance, built once at prepare when
|
|
111
110
|
* `RunnerDeps.usageWindows` + `usageWindowStore` are both wired (absent otherwise, so every consumer is
|
|
112
111
|
* an explicit `!== undefined` test and an ungoverned deployment executes not one extra line).
|
|
113
112
|
*
|
|
@@ -131,14 +130,14 @@ export interface UsageGovernance {
|
|
|
131
130
|
* a boundary loses nothing.
|
|
132
131
|
*
|
|
133
132
|
* `cumulativeCostMicroUsd` is the MONEY half (integer micro-USD, `stats.costMicroUsd`). Pass `undefined`
|
|
134
|
-
* when the run's spend has no cost figure at all
|
|
133
|
+
* when the run's spend has no cost figure at all — a deployment governing a
|
|
135
134
|
* `maxCostUsd` window then REFUSES here rather than charging the fabricated 0 that would let the ceiling
|
|
136
135
|
* silently stop applying. A token-only deployment ignores the argument entirely.
|
|
137
136
|
*/
|
|
138
137
|
commit(cumulativeTokens: number, cumulativeCostMicroUsd: number | undefined, now: number): Promise<void>;
|
|
139
138
|
}
|
|
140
139
|
/**
|
|
141
|
-
*
|
|
140
|
+
* The run's turn-start file-history BOUNDARY seat. `begin(entryId)` starts the capture
|
|
142
141
|
* for the turn's own initial entry (first-wins: exactly one boundary per turn incarnation, DV-4);
|
|
143
142
|
* `settle()` awaits the in-flight capture's settle and is the caller's LEASE CLOSE (awaited before
|
|
144
143
|
* the first tool executes) as well as the finish-tail durability await. The capture is bounded by a
|
|
@@ -171,7 +170,7 @@ export interface Prepared {
|
|
|
171
170
|
session: StoredSession;
|
|
172
171
|
sessionId: string;
|
|
173
172
|
/**
|
|
174
|
-
*
|
|
173
|
+
* THIS INVOCATION's own identity, minted once at the top of {@link prepareTask} and never
|
|
175
174
|
* rewritten. The third id of the trio, and the only one the engine owns outright:
|
|
176
175
|
* - `spec.taskId` — the HOST's task identity (absent whenever the host names nothing);
|
|
177
176
|
* - `sessionId` — the CONVERSATION's identity (shared by every run that continues it);
|
|
@@ -190,12 +189,12 @@ export interface Prepared {
|
|
|
190
189
|
* prepare emits run-scoped disclosures of its own and each must have a terminal that names it.
|
|
191
190
|
*/
|
|
192
191
|
runId: string;
|
|
193
|
-
/**
|
|
192
|
+
/** The session's reminder provenance mark this run mints under (adopted
|
|
194
193
|
* through the prepare adoption ladder: checkpoint seed → trusted fork channel → session entry →
|
|
195
194
|
* fresh mint). Every engine-authored `<system-reminder>` open tag in the run carries it, and the
|
|
196
195
|
* system prompt's Harness declaration names it. Always present on a completed prepare. */
|
|
197
196
|
reminderMark: string;
|
|
198
|
-
/**
|
|
197
|
+
/** The leg's reminder-disclosure trigger counters (mutated by the
|
|
199
198
|
* disclosure outlets at tool-execute time; read once at result assembly into
|
|
200
199
|
* `stats.mechanisms.reminderDisclosures` when any key is non-zero). Always present. */
|
|
201
200
|
reminderDisclosureCounts: import("../reminder-disclosure.js").ReminderDisclosureCounts;
|
|
@@ -223,13 +222,13 @@ export interface Prepared {
|
|
|
223
222
|
conflictRef: {
|
|
224
223
|
hit: boolean;
|
|
225
224
|
};
|
|
226
|
-
/**
|
|
225
|
+
/** Tool-call ids the gate blocked (policy/hook/plan-mode deny) or suspended —
|
|
227
226
|
* populated only while a consumer is wired (per-tool post hooks or postToolBatch). The runner's
|
|
228
227
|
* batch collector DELETES on match (its tool_execution_end is the only end-event a blocked call
|
|
229
228
|
* emits; the tool_result-side delete in prepare-task never fires for immediate results). */
|
|
230
229
|
blockedToolCalls: Set<string>;
|
|
231
230
|
/**
|
|
232
|
-
* WHAT ended the approval a gated call was waiting on and
|
|
231
|
+
* WHAT ended the approval a gated call was waiting on and WHOSE settlement it
|
|
233
232
|
* was, keyed by tool-call id: written ONLY by the tool gate, at the one exit where an ask resolved,
|
|
234
233
|
* and read once when that call's `tool_end` frame is minted (the reader deletes on read; a call the
|
|
235
234
|
* gate never settled has no entry, and an entry never names neither fact).
|
|
@@ -262,7 +261,7 @@ export interface Prepared {
|
|
|
262
261
|
};
|
|
263
262
|
/** Summed usage of nested sub-runs (sub-agents) spawned by this task's tools. */
|
|
264
263
|
nestedStats: NestedUsageAccum;
|
|
265
|
-
/**
|
|
264
|
+
/** Prepare-time rewind disclosures (conversation-only branch / no snapshot backend / no file
|
|
266
265
|
* env), echoed verbatim onto `TaskResult.rewindNotes`. Present only when there is something to say. */
|
|
267
266
|
rewindNotes?: NonNullable<TaskResult["rewindNotes"]>;
|
|
268
267
|
/** The run's edited-file ledger read face — what its OWN hands landed, as `TaskResult.editedFiles`
|
|
@@ -270,34 +269,34 @@ export interface Prepared {
|
|
|
270
269
|
* than a snapshot, so the throw-path backstop terminal reports the same ledger the ordinary
|
|
271
270
|
* assembly would. Always present on Prepared; independent of whether a fileHistoryStore is wired. */
|
|
272
271
|
editedFilesSnapshot: () => TaskResult["editedFiles"];
|
|
273
|
-
/**
|
|
272
|
+
/** The run's turn-start boundary seat (present iff a fileHistoryStore is wired and
|
|
274
273
|
* the run mounts a real fs env). runtask calls begin() at the first committed user entry and
|
|
275
274
|
* awaits settle() at the lease close + the finish tail. */
|
|
276
275
|
fileHistoryBoundary?: FileHistoryBoundarySeat;
|
|
277
|
-
/**
|
|
276
|
+
/** The run's RESOLVED read face for the result observation seat
|
|
278
277
|
* (`TaskResult.effectiveReadFace`): `carrierReadFace()`'s value at prepare completion — the hands
|
|
279
278
|
* block's single resolution, or the hands-less legs' resolver run (live spec-time facts, with the
|
|
280
279
|
* checkpoint seed folded stricter-wins where one exists). Every leg that completes prepare has a
|
|
281
280
|
* read posture now — this is what its delegation subtree is clamped by even where no faces mount. */
|
|
282
281
|
effectiveReadFace?: ReadFace;
|
|
283
|
-
/**
|
|
282
|
+
/** The normalized deny ADDITIONS in force (deployment ∪ task ∪ checkpoint seed; built-ins
|
|
284
283
|
* excluded), echoed on `TaskResult.effectiveReadDenyPatterns`. Present iff non-empty; a defensive
|
|
285
284
|
* copy (the wide-scope working array stays the engine's own). */
|
|
286
285
|
effectiveReadDenyPatterns?: readonly import("../../tools/fs/read-deny.js").NormalizedReadDenyEntry[];
|
|
287
|
-
/**
|
|
286
|
+
/** The memory-visibility observation prepareMemory minted (echoed on
|
|
288
287
|
* `TaskResult.effectiveMemoryScopes`). Always present on a completed prepare (the memory-less
|
|
289
288
|
* states are their own values); the seat is optional only so a Prepared shape without the phase
|
|
290
289
|
* cannot fabricate one. */
|
|
291
290
|
effectiveMemoryScopes?: import("../types.js").EffectiveMemoryScopes;
|
|
292
|
-
/**
|
|
291
|
+
/** The per-task logical cwd ref when a real shell is mounted (else undefined). The Runner
|
|
293
292
|
* reads `cwdRef.current` after each tool to detect a `cd` move and emit `workspace_changed`. */
|
|
294
293
|
cwdRef?: CwdRef;
|
|
295
|
-
/**
|
|
294
|
+
/** The ACTIVE EnterWorktree session ref (mounted with the worktree tools; undefined without
|
|
296
295
|
* real write hands). runtask's settle write reads `current` for the workspace-state entry. */
|
|
297
296
|
worktreeSessionRef?: {
|
|
298
297
|
current?: ActiveWorktreeSession;
|
|
299
298
|
};
|
|
300
|
-
/**
|
|
299
|
+
/** The settle-write base — the canonical root + what the cwd/worktree were RESTORED to at
|
|
301
300
|
* prepare. runtask diffs the live refs against this at settle and appends a `workspace_state` entry
|
|
302
301
|
* when the state changed (skipped on a durable suspend — the checkpoint lane owns that state). */
|
|
303
302
|
workspaceStateSettle?: {
|
|
@@ -306,16 +305,16 @@ export interface Prepared {
|
|
|
306
305
|
restoredWorktreeDir?: string;
|
|
307
306
|
baselineUnknown?: boolean;
|
|
308
307
|
};
|
|
309
|
-
/**
|
|
308
|
+
/** The settle-time session-seat SEAL (see prepare-hands-readface): re-anchors
|
|
310
309
|
* the per-session read-state seat to the entry id THIS run last committed (its own
|
|
311
310
|
* message_committed tail — provenance, never a shared-leaf re-read). The driver calls it once at
|
|
312
311
|
* the run's settle, every terminal (suspend included), under the session lock; undefined argument
|
|
313
312
|
* (no commits) is a no-op. Synchronous, never throws. Absent ⇔ hands-less / no seat channel. */
|
|
314
313
|
sealReadStateSeat?: (ownCommittedTailEntryId: string | undefined) => void;
|
|
315
|
-
/**
|
|
314
|
+
/** The DENY-NARROWING layers (session rules + skill scope, deny-only). Re-checked on RESUME
|
|
316
315
|
* before an approved pending tool executes, so a rule tightened during the suspend still applies. */
|
|
317
316
|
denyNarrowingPolicy?: ToolPolicy;
|
|
318
|
-
/**
|
|
317
|
+
/** The person's own persisted-rule lane (deny/ask rows), re-adjudicated on RESUME at the same
|
|
319
318
|
* station as the deny-narrowing layers: a deny row added while the call was parked vetoes the execution
|
|
320
319
|
* (`deniedBy: "persisted_rule"`); an ask row or an unreadable store fails closed the same way (the approval
|
|
321
320
|
* answered a question the person has since asked to be asked again — re-issue and re-approve). Absent when
|
|
@@ -323,10 +322,10 @@ export interface Prepared {
|
|
|
323
322
|
persistedRuleLane?: {
|
|
324
323
|
adjudicate: (req: ToolCallRequest) => Promise<import("../hooks.js").PersistedRuleAnswer>;
|
|
325
324
|
};
|
|
326
|
-
/**
|
|
325
|
+
/** The deployment's own caller policy, re-checked on a durable resume ONLY when the approver
|
|
327
326
|
* rewrote the pending call's args (see the composition site for why the edit case is special). */
|
|
328
327
|
basePolicyForResumeEdit?: ToolPolicy;
|
|
329
|
-
/**
|
|
328
|
+
/** The ORG adjudication face, re-resolved on a durable RESUME before an approved
|
|
330
329
|
* pending call executes. The resume path bypasses the harness gate by design (a human already
|
|
331
330
|
* adjudicated the checkpointed call), which is exactly where org policy skew is most likely: the
|
|
332
331
|
* suspend may have outlived the snapshot revision that was current when it was minted. Present only
|
|
@@ -337,7 +336,7 @@ export interface Prepared {
|
|
|
337
336
|
/** Removes the `spec.signal` abort listener on task end (else a long-lived signal leaks listeners). */
|
|
338
337
|
releaseSignal: () => void;
|
|
339
338
|
/**
|
|
340
|
-
*
|
|
339
|
+
* End-of-leg sweep for questions this leg's gate routed to a person. Called once by the
|
|
341
340
|
* run loop at task end, on every exit path. A binding that is still present means a person ANSWERED and
|
|
342
341
|
* the call never executed to collect it (aborted, batch torn down, loop threw): that answer is disclosed
|
|
343
342
|
* through the deployment's error sink rather than dropped, because "a human answered and it vanished" is
|
|
@@ -348,11 +347,11 @@ export interface Prepared {
|
|
|
348
347
|
deliveryId: string;
|
|
349
348
|
toolCallId: string;
|
|
350
349
|
}>;
|
|
351
|
-
/** Per-task prefix-cache-break detector
|
|
352
|
-
|
|
350
|
+
/** Per-task prefix-cache-break detector. The fingerprint is mutated when deferred tools
|
|
351
|
+
* materialize — see `cacheFingerprint`. */
|
|
353
352
|
cacheBreakDetector?: CacheBreakDetector;
|
|
354
353
|
/** The fingerprinted prefix. `systemPrompt` is stable; `tools` is REFRESHED in place when a deferred
|
|
355
|
-
* tool is materialized (placeholder→full schema), so the
|
|
354
|
+
* tool is materialized (placeholder→full schema), so the cache-break detector sees the real tool set. */
|
|
356
355
|
cacheFingerprint?: {
|
|
357
356
|
systemPrompt: string;
|
|
358
357
|
tools: ToolFingerprintInput[];
|
|
@@ -366,14 +365,14 @@ export interface Prepared {
|
|
|
366
365
|
* prompt" a runtime fact instead of archaeology.
|
|
367
366
|
*/
|
|
368
367
|
/**
|
|
369
|
-
*
|
|
368
|
+
* This leg's EFFECTIVE wiring manifest (built once in prepare from resolved
|
|
370
369
|
* facts through the same derivation as the static half). runtask emits it as the
|
|
371
370
|
* `wiring_manifest` TaskEvent after the prepare consume point and before the leg's first
|
|
372
371
|
* model/tool interaction. Host/operator plane — never enters model context.
|
|
373
372
|
*/
|
|
374
373
|
wiringManifest: WiringManifest;
|
|
375
374
|
/**
|
|
376
|
-
*
|
|
375
|
+
* This leg's frozen identity envelope, minted ONCE in prepare beside the wiring
|
|
377
376
|
* manifest (same leg derivation, one mint — {@link mintHookInvocationIdentity}). Every hook
|
|
378
377
|
* station runtask drives (stop/stopFailure/userPromptSubmit/postToolBatch, the compaction
|
|
379
378
|
* wrapper) and the 件B delegation-lifecycle observer read THIS object; prepare's own stations
|
|
@@ -416,17 +415,17 @@ export interface Prepared {
|
|
|
416
415
|
/** S2 (additive): the mounted tools plane — contract identity, durable-replay aliases,
|
|
417
416
|
* presentation-invariant shape digest and full wire digest per tool (initial mount face). */
|
|
418
417
|
tools?: ToolManifestRow[];
|
|
419
|
-
/**
|
|
418
|
+
/** The nine-element cache identity — digests only, no prompt
|
|
420
419
|
* text; backfilled once the final wire tool list exists. Live post-refresh truth rides
|
|
421
420
|
* `prepared.turnSnapshot`. */
|
|
422
421
|
snapshot?: {
|
|
423
422
|
cacheIdentity: string;
|
|
424
423
|
elements: import("../../prompt-assembly/turn-snapshot.js").CacheIdentityElements;
|
|
425
424
|
};
|
|
426
|
-
/**
|
|
425
|
+
/** The run's lowering record (version/wire form/known
|
|
427
426
|
* intentional divergences — run-static v1, one brain serves every call). */
|
|
428
427
|
lowering?: import("../../prompt-assembly/turn-snapshot.js").LoweringRecord;
|
|
429
|
-
/**
|
|
428
|
+
/** The RESOLVED deferred-tool disclosure strategy for this leg and which
|
|
430
429
|
* seat chose it. Absent when nothing is deferred (there is no disclosure to describe). */
|
|
431
430
|
toolDisclosure?: ToolDisclosureManifest;
|
|
432
431
|
};
|
|
@@ -434,10 +433,10 @@ export interface Prepared {
|
|
|
434
433
|
* threaded to every compaction-boundary epoch selection so boundary re-pins hash the same
|
|
435
434
|
* artifact identity as the prepare-time pin. Empty on declaration-free runs. */
|
|
436
435
|
epochDeclaredSections: import("../../prompt-assembly/epoch.js").EpochDeclaredSections;
|
|
437
|
-
/**
|
|
438
|
-
* the
|
|
436
|
+
/** The LIVE nine-element identity face (refreshed by deferred materialization and
|
|
437
|
+
* the deferred-materialization adoption swap); the manifest holds the prepare-time initial copy. */
|
|
439
438
|
turnSnapshot?: import("../../prompt-assembly/turn-snapshot.js").TurnPromptSnapshot;
|
|
440
|
-
/**
|
|
439
|
+
/** The compaction-boundary center-adoption seam (undefined = no source
|
|
441
440
|
* wired or session not center-pinned). Returns the maybeCompact `centerAdoption` fragment or
|
|
442
441
|
* undefined; `apply` runs post-CAS only (auto-compaction owns the ordering). Both
|
|
443
442
|
* `epochDeclaredSections` and `promptOverheadTokens` on THIS object are mutated by a successful
|
|
@@ -450,38 +449,38 @@ export interface Prepared {
|
|
|
450
449
|
overheadTokensAfter: number;
|
|
451
450
|
apply: (committedArtifactDigest?: string) => void;
|
|
452
451
|
} | undefined;
|
|
453
|
-
/** Deferred-tool disclosure
|
|
452
|
+
/** Deferred-tool disclosure: the monotonic set of activated deferred-tool names. Empty
|
|
454
453
|
* (and no `tool_search` injected) when nothing is deferred. Mutated by BOTH disclosure lanes across
|
|
455
|
-
* the run — the injected `tool_search` and the
|
|
454
|
+
* the run — the injected `tool_search` and the direct-call placeholder lane (default ON) —
|
|
456
455
|
* under ONE shared activation critical section, plus resume seeding at prepare. A leg on which the
|
|
457
456
|
* model never calls `tool_search` is therefore NOT quiescent. */
|
|
458
457
|
activeTools: Set<string>;
|
|
459
|
-
/**
|
|
458
|
+
/** The DECLARED deferred set (populated by `classifyDeferred`, ghost names already pruned).
|
|
460
459
|
* Present iff the task has deferred tools at all; `deferredToolNames − activeTools` is the
|
|
461
460
|
* "undiscovered" census the tool_search_usage_reminder lane enumerates. Frozen at prepare time: a
|
|
462
461
|
* name never leaves the deferred set, it only moves into `activeTools`. */
|
|
463
462
|
deferredToolNames?: ReadonlySet<string>;
|
|
464
|
-
/**
|
|
463
|
+
/** The RESOLVED materialization strategy this run runs under (`true` = "static":
|
|
465
464
|
* activation never swaps the placeholder; the real schema's only in-context carrier is the
|
|
466
465
|
* ToolSearch result text). Consumed by the tools_delta boundary renderer, whose "full schemas are
|
|
467
466
|
* loaded" wording is a statement about the tools block and is only true under swap. `false` when
|
|
468
467
|
* nothing is deferred (the knob is inert then). */
|
|
469
468
|
toolMaterializeStatic: boolean;
|
|
470
|
-
/**
|
|
469
|
+
/** Is the direct-call lane mounted on this run's placeholders (`TaskSpec.deferSelfResolve`
|
|
471
470
|
* not disabled; default ON)? The SAME fact `createToolSearchTool` receives as `directCallEnabled`,
|
|
472
471
|
* surfaced here so every model-facing face that describes what happens to a call on a
|
|
473
472
|
* still-deferred tool reads ONE value — under the direct lane a schema-valid call executes rather
|
|
474
473
|
* than failing, so an absolute failure claim is only true for the opt-out posture. `false` when
|
|
475
474
|
* nothing is deferred (no placeholders, so the fact is inert). */
|
|
476
475
|
deferDirectCall: boolean;
|
|
477
|
-
/**
|
|
476
|
+
/** Is THIS deferred name on the static face? False under `"swap"`, and false under
|
|
478
477
|
* `"static"` for a tool whose declaration the result-text carrier cannot hold (the per-tool
|
|
479
478
|
* exemption: it materializes into the tools block instead). Read at call time — the roster is
|
|
480
479
|
* mutated in place by MCP refresh, so renderability is a live fact. Absent when nothing is
|
|
481
480
|
* deferred; a caller with no accessor has no deferred family to describe. */
|
|
482
481
|
staticFaceFor?: (name: string) => boolean;
|
|
483
482
|
/**
|
|
484
|
-
*
|
|
483
|
+
* The MemoryEngine session. Present when `deps.memoryBackend` + `spec.memory.enabled`
|
|
485
484
|
* hold AND the engine mount succeeded: a materialize failure without a `config.memory_*` code is
|
|
486
485
|
* fail-open (reported via `deps.onError`, the task runs memory-less), leaving this absent even though
|
|
487
486
|
* both flags hold.
|
|
@@ -496,7 +495,7 @@ export interface Prepared {
|
|
|
496
495
|
* runtask call site passes nothing); the checkpoint-mint call site passes "checkpoint".
|
|
497
496
|
*/
|
|
498
497
|
memoryEngineSession?: {
|
|
499
|
-
/** The WRITE-plane pair (
|
|
498
|
+
/** The WRITE-plane pair (dual roots collapse to one session face; these are the
|
|
500
499
|
* plane that owns the write gate — the read-only plane is internal to `inject`/`harvest`). */
|
|
501
500
|
engine: MemoryEngine;
|
|
502
501
|
handle: MemorySessionHandle;
|
|
@@ -504,15 +503,15 @@ export interface Prepared {
|
|
|
504
503
|
inject: () => import("../memory-engine/engine.js").MemoryInjection;
|
|
505
504
|
harvest: (phase?: "checkpoint" | "terminal") => Promise<HarvestReport | undefined>;
|
|
506
505
|
/**
|
|
507
|
-
*
|
|
506
|
+
* The session's capture opt-out face (the `TaskStream.optOutMemoryCapture`
|
|
508
507
|
* verb's target; host-API only — no tool face reads it, §2.6). `flip` re-adjudicates the
|
|
509
508
|
* entitlement at call time (fresh caps resolve), mints the one-way record, runs the §2.3
|
|
510
509
|
* boundary sweep, and delivers the effectiveness notice; its typed refusals are the
|
|
511
510
|
* `memory.capture_optout_*` family. `optedOut` is the live state read (declared / standing /
|
|
512
511
|
* flipped) — a GENUINE-record read: a store fault answers false here and TRUE on
|
|
513
|
-
* `indeterminate` instead
|
|
512
|
+
* `indeterminate` instead: the fault must reach the delegation floor
|
|
514
513
|
* as its own third state, never as either boolean; an irreversible record is never minted off
|
|
515
|
-
* an unreadable state, and an outage must not spawn un-floored children
|
|
514
|
+
* an unreadable state, and an outage must not spawn un-floored children. Present whenever
|
|
516
515
|
* the memory session mounted.
|
|
517
516
|
*/
|
|
518
517
|
captureOptOut?: {
|
|
@@ -524,7 +523,7 @@ export interface Prepared {
|
|
|
524
523
|
}>;
|
|
525
524
|
};
|
|
526
525
|
/**
|
|
527
|
-
*
|
|
526
|
+
* The session's ONE-WAY pollution face. `markPolluted` fires when an
|
|
528
527
|
* external-content-class tool is invoked (the prepare-time tool wrap below is the caller);
|
|
529
528
|
* durable + in-process, no unmark exists at any layer. `polluted` is what the harvest legs read
|
|
530
529
|
* (they consult it at harvest time themselves — this accessor serves observers/tests).
|
|
@@ -535,20 +534,20 @@ export interface Prepared {
|
|
|
535
534
|
reason: string;
|
|
536
535
|
cause?: import("../memory-engine/types.js").MemoryOriginCause;
|
|
537
536
|
} | undefined;
|
|
538
|
-
/**
|
|
537
|
+
/** `cause` is the structured mechanical fact the mark records (and the
|
|
539
538
|
* origin marker minted off it carries): `"observed"` for a witnessed external event,
|
|
540
539
|
* `"static"` for the capability over-approximation, `"derived"` for recall-taint. Absent
|
|
541
540
|
* folds to `"observed"` at mint time (the honest floor). */
|
|
542
541
|
markPolluted: (reason: string, cause?: import("../memory-engine/types.js").MemoryOriginCause) => void;
|
|
543
542
|
};
|
|
544
|
-
/**
|
|
543
|
+
/** The task's content-safety config (normalized memory spec): the allowlist for
|
|
545
544
|
* UNDECLARED tools and the strict execution-class upgrade. Consumed by the tool wrap only. */
|
|
546
545
|
contentSafety: {
|
|
547
546
|
trustedTools: ReadonlySet<string>;
|
|
548
547
|
execIsExternalContent: boolean;
|
|
549
548
|
};
|
|
550
549
|
/**
|
|
551
|
-
*
|
|
550
|
+
* The delegation-settlement handle: the control-plane coordinates a
|
|
552
551
|
* settlement writer needs, as PURE DATA. Consumers (the subagent background leg's write-ahead
|
|
553
552
|
* + terminal observation, the tool wrap's sync unattestable row) can outlive this prepared
|
|
554
553
|
* leg, so they rebuild their write handle from these fields alone — never from the live
|
|
@@ -562,7 +561,7 @@ export interface Prepared {
|
|
|
562
561
|
provenance: "carry";
|
|
563
562
|
};
|
|
564
563
|
/**
|
|
565
|
-
*
|
|
564
|
+
* The Read-tool recall-taint judgment, present only under
|
|
566
565
|
* `memoryProvenance: "carry"`. True ⇔ the delivered ABSOLUTE path sits inside a mounted memory
|
|
567
566
|
* plane and its head bytes carry a committed external-origin marker; the tool wrap then marks
|
|
568
567
|
* the session derived (same seat and cause as the memory_get propagation). Never throws;
|
|
@@ -572,7 +571,7 @@ export interface Prepared {
|
|
|
572
571
|
judgeDeliveredPath: (absPath: string) => boolean;
|
|
573
572
|
};
|
|
574
573
|
};
|
|
575
|
-
/** A per-task env minted by `RunnerDeps.executionEnvFactory` (
|
|
574
|
+
/** A per-task env minted by `RunnerDeps.executionEnvFactory` (the remote seam) that THIS task owns
|
|
576
575
|
* and the Runner must tear down on task end. Undefined when the env came from a (caller-owned) static
|
|
577
576
|
* `deps.executionEnv` or the stub — those outlive the task and must NOT be destroyed here. */
|
|
578
577
|
ownedEnv?: ExecutionEnv;
|
|
@@ -592,7 +591,7 @@ export interface Prepared {
|
|
|
592
591
|
suspendProgressRef: {
|
|
593
592
|
executedApproved: boolean;
|
|
594
593
|
};
|
|
595
|
-
/**
|
|
594
|
+
/** The remote-workspace lifecycle failures this run hit, appended in call order and echoed
|
|
596
595
|
* verbatim on `TaskResult.remoteEnvFailures`. A shared array (not a per-call return) because a suspend
|
|
597
596
|
* refusal is reported through the deployment's `onError` side channel and the run then continues or
|
|
598
597
|
* stops by its own rules — without this collector the caller's result kept no trace that a durable
|
|
@@ -600,13 +599,13 @@ export interface Prepared {
|
|
|
600
599
|
* failed. Resume-leg failures do NOT land here (that leg throws out of prepare before a `Prepared`
|
|
601
600
|
* exists) — they ride the thrown error's `remoteEnvFailure` carrier instead. */
|
|
602
601
|
remoteEnvFailures: NonNullable<TaskResult["remoteEnvFailures"]>;
|
|
603
|
-
/**
|
|
602
|
+
/** Set when a suspend was REFUSED because the task already suspended `maxSuspends`
|
|
604
603
|
* times (a resume/restart loop) — the run is aborted and assembles as `failed`/`suspend.loop` instead
|
|
605
604
|
* of minting yet another checkpoint. */
|
|
606
605
|
suspendLoopRef: {
|
|
607
606
|
hit: boolean;
|
|
608
607
|
};
|
|
609
|
-
/**
|
|
608
|
+
/** Opt-in resource-slice suspend. Present (≠ undefined) ONLY when the task opted in
|
|
610
609
|
* (`spec.resourceSuspend`) AND it is eligible to suspend durably (a checkpoint store, durable tool
|
|
611
610
|
* results, and a remote — or static caller-owned, never per-task-stub — env). The run loop calls it at a
|
|
612
611
|
* CLEAN turn boundary when a resource limit (turns/budget/walltime) was hit: it mints a `resource_limit`
|
|
@@ -619,7 +618,7 @@ export interface Prepared {
|
|
|
619
618
|
turns: number;
|
|
620
619
|
walltimeMs: number;
|
|
621
620
|
}) => Promise<boolean>;
|
|
622
|
-
/**
|
|
621
|
+
/** The PLATFORM-cause suspend — the same commit saga as {@link suspendForResource},
|
|
623
622
|
* exposed on the INFRASTRUCTURE alone (checkpoint store + durable tool results + remote/no owned env),
|
|
624
623
|
* WITHOUT the `spec.resourceSuspend` opt-in. The run loop calls it at a clean turn boundary when the
|
|
625
624
|
* execution environment is about to be reclaimed (`env_lifetime`) or a deployment usage window is
|
|
@@ -635,15 +634,15 @@ export interface Prepared {
|
|
|
635
634
|
}, hint?: {
|
|
636
635
|
resumeAfterMs: number;
|
|
637
636
|
}) => Promise<boolean>;
|
|
638
|
-
/**
|
|
637
|
+
/** Epoch ms at which this run must stop and checkpoint because the EXECUTION
|
|
639
638
|
* ENVIRONMENT's declared lifetime is about to expire (`ExecutionEnv.lifetimeMs` minus
|
|
640
639
|
* {@link ENV_LIFETIME_SUSPEND_MARGIN_MS}). Undefined ⇒ the env declared no lifetime (every local env,
|
|
641
640
|
* and any adapter on an unbounded host) or declared one the engine could not anchor — in both cases the
|
|
642
|
-
* boundary check is dead code
|
|
641
|
+
* boundary check is dead code. Epoch, not monotonic: the anchor
|
|
643
642
|
* comes from the PLATFORM (an env can be older than this process), which is a wall-clock fact and the
|
|
644
643
|
* one domain both sides can name. */
|
|
645
644
|
envLifetimeSuspendAt?: number;
|
|
646
|
-
/**
|
|
645
|
+
/** Deployment usage governance for this run, or undefined when the deployment wired
|
|
647
646
|
* none (or wired windows without a ledger, which is reported and not enforced). */
|
|
648
647
|
usageGovernance?: UsageGovernance;
|
|
649
648
|
/** 1.296 件2b — epoch ms at which the loop ISSUED the current provider call (stamped by the
|
|
@@ -652,7 +651,7 @@ export interface Prepared {
|
|
|
652
651
|
callIssuedAtRef: {
|
|
653
652
|
current?: number;
|
|
654
653
|
};
|
|
655
|
-
/**
|
|
654
|
+
/** Was the run's WORK cut by a stop? Two observation points, one record, read by the answer-settled
|
|
656
655
|
* verdict (`answerSettled`) beside the harness's own undrained-input account:
|
|
657
656
|
* - `continuation` — the loop decided to CONTINUE past its last assistant turn and the abort caught it
|
|
658
657
|
* before that continuation dispatched. Written by the loop-trace sink from the loop's own steps: a
|
|
@@ -670,14 +669,14 @@ export interface Prepared {
|
|
|
670
669
|
continuation: boolean;
|
|
671
670
|
abortedBeforeTurnEnd: boolean;
|
|
672
671
|
};
|
|
673
|
-
/**
|
|
672
|
+
/** Records the FIRST brain call this run's outer guardrail gave up on (see
|
|
674
673
|
* {@link import("../../brain/timeout.js").withBrainCallGuardrail}). Always present; `timedOut`
|
|
675
674
|
* stays absent unless the guardrail fired. The run loop reads it AFTER the loop settles and gives
|
|
676
675
|
* the task the typed terminal — the harness turns a loop throw into an error assistant message, so
|
|
677
676
|
* without this the cause would reach the caller only as the generic `provider.error`. */
|
|
678
677
|
brainCallGuardrailRef: BrainCallGuardrailRef;
|
|
679
678
|
/**
|
|
680
|
-
*
|
|
679
|
+
* The tool gate's own TYPED STOP: set (once) when the classifier denial limit was reached with
|
|
681
680
|
* no approver to fall back to (headless), together with the run abort. The run loop adopts it as the
|
|
682
681
|
* terminal `threw` (`TaskResult.errorCode` = the error's `code`, `errorMessage` = its sentence) the
|
|
683
682
|
* same way it adopts the brain-call guardrail's — a loop that ended because THIS lane aborted it must
|
|
@@ -689,7 +688,7 @@ export interface Prepared {
|
|
|
689
688
|
code: string;
|
|
690
689
|
};
|
|
691
690
|
};
|
|
692
|
-
/**
|
|
691
|
+
/** Set by a tool calling `ctx.requestReview()` (the first-party `present_plan` tool, CC
|
|
693
692
|
* ExitPlanMode parity): the run loop honors it at the next CLEAN turn boundary by minting a `plan_review`
|
|
694
693
|
* checkpoint. `{ pending }` is set (with an optional reason) the moment a tool requests review; the boundary
|
|
695
694
|
* reads + clears it. First request in a batch wins (idempotent). */
|
|
@@ -698,17 +697,17 @@ export interface Prepared {
|
|
|
698
697
|
reason?: string;
|
|
699
698
|
};
|
|
700
699
|
};
|
|
701
|
-
/**
|
|
700
|
+
/** Present (≠ undefined) ONLY when a `checkpointStore` is wired (the deployment can pause). The
|
|
702
701
|
* run loop calls it at a CLEAN turn boundary when `reviewRequestRef.pending` is set: it mints a `plan_review`
|
|
703
702
|
* checkpoint (`status:"needs_review"` by its registry row) + pauses the workspace + aborts the loop, reusing
|
|
704
703
|
* the SAME commit saga as the human/resource suspends. Returns true iff it committed a resumable checkpoint;
|
|
705
704
|
* false ⇒ the request could not be honored (caller drops it and continues). */
|
|
706
705
|
suspendForReview?: (reason?: string) => Promise<boolean>;
|
|
707
|
-
/**
|
|
706
|
+
/** The prior cross-slice {@link ResourceLedger} (from the resumed checkpoint), so the run
|
|
708
707
|
* loop can size this slice's effective budget = `min(maxCostUsd, remaining)`. Undefined on the first slice
|
|
709
708
|
* (or a non-resource task). */
|
|
710
709
|
resourceLedger?: ResourceLedger;
|
|
711
|
-
/**
|
|
710
|
+
/** A mutable holder the run loop populates (right after `stats` exists) so the
|
|
712
711
|
* human/irreversible_ask suspend can debit THIS leg's live cumulative spend onto the durable approval
|
|
713
712
|
* ledger it attaches (the resource-slice path passes `sliceSpend` explicitly; this event-driven gate has
|
|
714
713
|
* no such arg, so it reads the live spend here). Read at suspend time; absent ⇒ this leg's spend is not
|
|
@@ -721,10 +720,10 @@ export interface Prepared {
|
|
|
721
720
|
walltimeMs: number;
|
|
722
721
|
};
|
|
723
722
|
};
|
|
724
|
-
/**
|
|
723
|
+
/** The per-task human-review accumulator (synchronous `resolveAsk` waits this leg + the carried
|
|
725
724
|
* prior-leg burden seeded from the resumed checkpoint). The run loop ADDS the durable-resume latency
|
|
726
725
|
* (`now() − cp.suspendedAt`) on a resume, then surfaces it as `stats.humanReview` at assembly (omitted when
|
|
727
|
-
|
|
726
|
+
* empty). **Budget-EXCLUDED** — never folded into cost/the budget gate. */
|
|
728
727
|
humanReviewRef: {
|
|
729
728
|
count: number;
|
|
730
729
|
totalWaitMs: number;
|
|
@@ -736,17 +735,17 @@ export interface Prepared {
|
|
|
736
735
|
toolArg?: string;
|
|
737
736
|
}>;
|
|
738
737
|
};
|
|
739
|
-
/**
|
|
738
|
+
/** The injectable wall-clock the run loop uses for the durable-resume human-review latency
|
|
740
739
|
* (`humanLatencyMs = now() − cp.suspendedAt`), so it reads the SAME clock as the suspend-side `suspendedAt`. */
|
|
741
740
|
now: () => number;
|
|
742
|
-
/**
|
|
741
|
+
/** The FULL resolved tool list (real tools, never deferred placeholders) so the
|
|
743
742
|
* resume engine can execute a previously-suspended pending tool call directly (it bypasses the gate —
|
|
744
743
|
* the human already adjudicated it). Same wrapping (offload + ctx) the harness runs with.
|
|
745
744
|
*
|
|
746
745
|
* ONE array, mutated in place; identity is the contract (every closure that resolves a name at run time
|
|
747
|
-
* reads this exact array).
|
|
746
|
+
* reads this exact array). The array is PRIVATE to the `RosterBuilder` (tool-roster.ts) —
|
|
748
747
|
* every station below writes through its verbs (`mount` / `mountAll` / `unmountWhere` / `replaceAt` /
|
|
749
|
-
* `replaceDomain`) and this field is the builder's read face. WRITER TABLE
|
|
748
|
+
* `replaceDomain`) and this field is the builder's read face. WRITER TABLE — the only
|
|
750
749
|
* stations that write it, in prepare order:
|
|
751
750
|
* · caps-and-workflow — MINTS it (`spec.tools` through the ctx wrap + the large-result wrapper), then pushes
|
|
752
751
|
* ReportBlocked (enableBlockedReport ≠ false), ReportFindings (no caller tool of that name/alias),
|
|
@@ -771,28 +770,28 @@ export interface Prepared {
|
|
|
771
770
|
* tool-disclosure and listings only READ it (`harnessTools` is a derived list; placeholders never enter here). */
|
|
772
771
|
tools: readonly AgentTool[];
|
|
773
772
|
/**
|
|
774
|
-
*
|
|
773
|
+
* This leg's minted TOOL ROSTER (the same object `wiringManifest.tools` carries):
|
|
775
774
|
* one row per mounted instance in wire order. Minted ONCE at the prompt-assembly station (the same
|
|
776
775
|
* pass that projects the prompt manifest's tool rows, so the two agree by construction); the park
|
|
777
776
|
* station reads the gated call's identity off it, the exemption probe hands it to the host.
|
|
778
777
|
*/
|
|
779
778
|
toolRoster: import("../tool-roster.js").ToolRoster;
|
|
780
779
|
/**
|
|
781
|
-
*
|
|
780
|
+
* The run-time delta seat: every roster change after prepare (the RefreshMcpTools
|
|
782
781
|
* seam) re-mints the roster here and publishes a `ToolRosterDelta`. The run loop subscribes at the
|
|
783
782
|
* point it emits `wiring_manifest` and forwards each delta as a `tool_roster_delta` event; until it
|
|
784
783
|
* does, deltas are buffered in order.
|
|
785
784
|
*/
|
|
786
785
|
toolRosterDeltas: import("../tool-roster.js").ToolRosterDeltaSeat;
|
|
787
786
|
/**
|
|
788
|
-
*
|
|
787
|
+
* The leg's `tool_end.structured` projector: the engine card set ∪ the caller rows' declared
|
|
789
788
|
* `renderHints.resultCards`; an undeclared `details.type` is dropped and announced ONCE per leg
|
|
790
789
|
* (`config.tool_card_undeclared`). The ONE card port: every tool_end body projection (the live loop, the resumed
|
|
791
790
|
* batch, the reconcile-recovered orphan) takes it as a parameter; no module-level card set exists to fall back to.
|
|
792
791
|
*/
|
|
793
792
|
structuredProjector: (result: unknown) => unknown;
|
|
794
|
-
/** Name→effect map for every tool this task can call
|
|
795
|
-
|
|
793
|
+
/** Name→effect map for every tool this task can call. Used by the abort-path orphan
|
|
794
|
+
* reconcile to make interrupted tool_results effect-aware (read/idempotent = safe to
|
|
796
795
|
* repeat; write/unknown = outcome unknown). Unknown names default to `write` (conservative). */
|
|
797
796
|
toolEffects: Map<string, ToolEffect>;
|
|
798
797
|
/** scan-1/A5 — the orphans the WAKE/CRASH reconcile closed while preparing this run (empty on a fresh or
|
|
@@ -803,9 +802,9 @@ export interface Prepared {
|
|
|
803
802
|
wakeRecovered: RecoveredOrphan[];
|
|
804
803
|
/** Fixed per-request prompt overhead (system prompt + tool schemas, ≈chars/4 tokens). Fed to
|
|
805
804
|
* `maybeCompact.overheadTokens` so the compaction trigger stays accurate in the anchor-less
|
|
806
|
-
* regime (custom Brains that don't report usage
|
|
805
|
+
* regime (custom Brains that don't report usage). */
|
|
807
806
|
promptOverheadTokens: number;
|
|
808
|
-
/**
|
|
807
|
+
/** Accessor for the MAIN lane's latest real brain request (systemPrompt/messages/
|
|
809
808
|
* tools snapshot, recorded at the harness's provider seam just before each main-loop call). Fed
|
|
810
809
|
* to `maybeCompact.forkContext` on all three compaction lanes so the summary request can FORK the
|
|
811
810
|
* already-paid main prefix (CC form). `undefined` until the run's first main-loop call. Summary
|
|
@@ -816,7 +815,7 @@ export interface Prepared {
|
|
|
816
815
|
* via the SAME env the hands ran against (so remote/k8s/E2B tasks read the container's tree, not
|
|
817
816
|
* the control plane's). Present only when the hands are enabled — without an env there is no
|
|
818
817
|
* workspace to re-read. null = unreadable (deleted/binary/transport error); callers skip it.
|
|
819
|
-
*
|
|
818
|
+
* `{ withheld }` = the target matches the sensitive-path read deny list — the
|
|
820
819
|
* attachment is deliberately withheld and the consumer must SAY so (an annotation, never a silent
|
|
821
820
|
* skip: a silently missing attachment reads as "file gone", which is a different fact). */
|
|
822
821
|
readTaskFile?: (path: string) => Promise<string | null | {
|
|
@@ -828,10 +827,10 @@ export interface Prepared {
|
|
|
828
827
|
* first (from the hands' readFileState `lastReadAt` stamps). The compaction working-file
|
|
829
828
|
* attachment prefers this over the modified set — CC restores what the model RECENTLY READ,
|
|
830
829
|
* including untouched reference files. Present only with hands (same gate as readTaskFile).
|
|
831
|
-
*
|
|
830
|
+
* Seeded entries are excluded — their content lives in the system-prompt lane, which
|
|
832
831
|
* compaction never touches, so re-attaching them into the summary would be a duplicate. */
|
|
833
832
|
recentlyReadFiles?: () => string[];
|
|
834
|
-
/**
|
|
833
|
+
/** Canonicalizes a raw (often relative, model-typed) path the
|
|
835
834
|
* SAME way the hands toolkit does (`resolveKey` against the same containment root `readTaskFile`
|
|
836
835
|
* uses), so `maybeCompact`'s kept-tail/instruction-source exclusions compare paths in the SAME
|
|
837
836
|
* coordinate `recentlyReadFiles()` already uses — without this a plain string match silently never
|
|
@@ -839,23 +838,23 @@ export interface Prepared {
|
|
|
839
838
|
* readTaskFile); absent there is no containment root to resolve against, and every path source is
|
|
840
839
|
* already in the same raw coordinate anyway. */
|
|
841
840
|
normalizeAttachmentPath?: (raw: string) => Promise<string>;
|
|
842
|
-
/**
|
|
841
|
+
/** Recognizes the hands Read tool's own dedup-stub markers
|
|
843
842
|
* ({@link isReadDedupStubResult}), so `maybeCompact`'s kept-tail scan can tell a SUBSTANTIVE Read
|
|
844
843
|
* result from a stub hit whose original full transmission may already be summarized away. Present
|
|
845
844
|
* only with hands (same gate as readTaskFile). */
|
|
846
845
|
isDedupStubResult?: (resultText: string) => boolean;
|
|
847
|
-
/**
|
|
848
|
-
*
|
|
846
|
+
/** Wired to `MaybeCompactOptions.onApplied` by every compaction lane (CC 220 clears readFileState at its
|
|
847
|
+
* compaction landing site, @388663). Drops the non-seeded read-state entries
|
|
849
848
|
* (the summary just replaced the Read results the dedup stubs point at) and re-registers the files
|
|
850
849
|
* that were re-attached WHOLE. Present only with hands (same gate as readTaskFile).
|
|
851
|
-
*
|
|
850
|
+
* `preserveReadState` carries the kept-tail-visible files that were
|
|
852
851
|
* deliberately skipped for re-attachment — their existing entry must survive the clear too (same
|
|
853
852
|
* reasoning as a seeded entry: the model's view of the file did not change). */
|
|
854
853
|
onCompactionApplied?: (attachedComplete: ReadonlyArray<{
|
|
855
854
|
path: string;
|
|
856
855
|
content: string;
|
|
857
856
|
}>, preserveReadState?: ReadonlyArray<string>) => void;
|
|
858
|
-
/**
|
|
857
|
+
/** The live diagnostics lane (present only when the gate passed — manager w/ registry +
|
|
859
858
|
* write hands + not opted out). `registry` is drained by runtask at turn boundaries; `nudge` is
|
|
860
859
|
* called (fire-and-forget) after each successful edit/write so the language server re-analyzes. */
|
|
861
860
|
lspDiagnostics?: {
|
|
@@ -866,7 +865,7 @@ export interface Prepared {
|
|
|
866
865
|
* `drain` and calls `releaseRun` with it at the run's terminal. */
|
|
867
866
|
runIdent: string;
|
|
868
867
|
};
|
|
869
|
-
/**
|
|
868
|
+
/** The live plan-mode flag (`enter_plan_mode` flips it, run-local one-way). Exposed
|
|
870
869
|
* so the run loop's plan-mode attachment producer reads the SAME flag the write-deny enforces —
|
|
871
870
|
* never a second source of truth. Always present (`active:false` when plan mode is unused). */
|
|
872
871
|
planModeRef: {
|
|
@@ -885,7 +884,7 @@ export interface Prepared {
|
|
|
885
884
|
* as a whole-snapshot append on this leg (it would replace the branch's record with a partial
|
|
886
885
|
* one); the leg's announcements then simply repeat next run. */
|
|
887
886
|
announcedSnapshotRecovered: boolean;
|
|
888
|
-
/**
|
|
887
|
+
/** The date-flip detector seam: `legDate` = the date frozen
|
|
889
888
|
* into this leg's system prefix; `today()` = the boundary-time LOCAL date (user-zone-bound closure).
|
|
890
889
|
* The run loop feeds both to the `date_change` attachment producer; the prefix itself never
|
|
891
890
|
* re-renders mid-leg (cache preservation, CC parity). Present only when the prompt carries a date. */
|
|
@@ -902,7 +901,7 @@ export interface Prepared {
|
|
|
902
901
|
path: string;
|
|
903
902
|
contentHash: string | null;
|
|
904
903
|
}>;
|
|
905
|
-
/**
|
|
904
|
+
/** The RAW instruction-file text this leg's `loadProjectMemory` returned
|
|
906
905
|
* (`ProjectMemoryLoad.content`), for the compaction lanes' `contextInstructionFiles` seat.
|
|
907
906
|
*
|
|
908
907
|
* Which bytes, exactly: the string prepare-task hands `composeMemoryBlock(projectMem, "project")`
|
|
@@ -930,7 +929,7 @@ export interface Prepared {
|
|
|
930
929
|
legGuideline: WorkflowSizeGuideline;
|
|
931
930
|
current: () => WorkflowSizeGuideline;
|
|
932
931
|
};
|
|
933
|
-
/**
|
|
932
|
+
/** Boundary-time external-change scan over the ≤`maxFiles` most-recently-READ
|
|
934
933
|
* files. Stats each via `env.fileInfo` and reports paths whose `mtimeMs` moved past the recorded
|
|
935
934
|
* `lastReadAt` + 2s epsilon (CC getChangedFiles shape: readFileState needs NO new field; the agent's
|
|
936
935
|
* own write-backs refresh `lastReadAt`, so self-edits are immune). ENOENT evicts the readFileState
|
|
@@ -944,14 +943,14 @@ export interface Prepared {
|
|
|
944
943
|
}>;
|
|
945
944
|
evicted: string[];
|
|
946
945
|
}>;
|
|
947
|
-
/** G1 通告层 — deferred tools MATERIALIZED (
|
|
946
|
+
/** G1 通告层 — deferred tools MATERIALIZED (rematerialized) but not yet announced at a
|
|
948
947
|
* turn boundary. Appended by the rematerialize diff (newly-activated names only — the announced set
|
|
949
948
|
* is seeded with prepare-time actives INCLUDING resume-reseeded ones, so a resume never replays);
|
|
950
949
|
* DRAINED by the run loop only when the `tools_delta` attachment actually survived the byte cap.
|
|
951
|
-
|
|
950
|
+
* Present when the task has deferred tools at all — OR when a declared MCP server failed
|
|
952
951
|
* to connect, so the failure is announceable even on a task whose every MCP tool went missing with it.
|
|
953
952
|
*
|
|
954
|
-
*
|
|
953
|
+
* The same frame's MCP arms, filled by the SAME rematerialize seam / materialize-time
|
|
955
954
|
* projection and drained by the same intact-survival predicate:
|
|
956
955
|
* - `pendingRemoved`: previously-ANNOUNCED tool names that left the live roster (a RefreshMcpTools
|
|
957
956
|
* re-splice whose server withdrew them). CC `removedNames`.
|
|
@@ -1008,7 +1007,7 @@ export interface Prepared {
|
|
|
1008
1007
|
* announce-once-ledger.ts): seeded at prepare from the branch's record, advanced by the run loop
|
|
1009
1008
|
* on intact delivery of the tools_delta `failedServers` arm / the mcp_dropped_tools frame. */
|
|
1010
1009
|
announcedListingsRef: AnnouncedListingSnapshotInput;
|
|
1011
|
-
/** env-tail migration
|
|
1010
|
+
/** env-tail migration — the git-status frame lane's run-local state: this leg's
|
|
1012
1011
|
* resolved frame (probe outcome rendered + hashed at prepare), the announced `(kind, hash)`
|
|
1013
1012
|
* mirror the checkpoint serializer reads, the trim-protection slot the request-build context
|
|
1014
1013
|
* handler matches on, and the re-assert closure the compaction landing + boundary retry call.
|
|
@@ -1023,20 +1022,20 @@ export interface Prepared {
|
|
|
1023
1022
|
description?: string;
|
|
1024
1023
|
status: string;
|
|
1025
1024
|
}>;
|
|
1026
|
-
/**
|
|
1025
|
+
/** The parent-run subagent-retain ledger (present ONLY when `spec.retainSubagentSessions`
|
|
1027
1026
|
* is enabled). The Runner disposes it (abort in-flight resumes + unpin + release every retained child
|
|
1028
1027
|
* session) in the task's terminal `finally` — same UNCONDITIONAL posture as the background-agent reap:
|
|
1029
1028
|
* retain is NOT durable (a suspend leg's in-memory ledger cannot survive a re-prepare), so releasing on
|
|
1030
1029
|
* every exit path is hygiene, never a loss. */
|
|
1031
1030
|
subagentRetain?: SubagentRetainLedger;
|
|
1032
|
-
/**
|
|
1031
|
+
/** Run-scoped consecutive-`summaryProvider`-reuse counter, OWNED by the Runner and
|
|
1033
1032
|
* SHARED across both compaction call sites (within-task turn boundary + `finish()`), so the
|
|
1034
1033
|
* `maxConsecutiveProviderReuse` drift guard is enforced over the whole task — incremented when a
|
|
1035
1034
|
* compaction reused the provider's summary, reset to 0 on a real (LLM) summary. */
|
|
1036
1035
|
compactionReuseRef: {
|
|
1037
1036
|
consecutive: number;
|
|
1038
1037
|
};
|
|
1039
|
-
/**
|
|
1038
|
+
/** Trim→compaction pressure propagation (16k live sawtooth root cause): set by the
|
|
1040
1039
|
* context hook when `trimToBudget` actually DROPPED messages from a request view (request-only trim
|
|
1041
1040
|
* + usage-anchor mismatch deflates the next boundary's estimate → the trigger and floor are both
|
|
1042
1041
|
* deceived → full-size request spikes alternate with trimmed troughs). The next turn boundary's
|
|
@@ -1047,7 +1046,7 @@ export interface Prepared {
|
|
|
1047
1046
|
trimPressureRef: {
|
|
1048
1047
|
droppedMessages: boolean;
|
|
1049
1048
|
};
|
|
1050
|
-
/**
|
|
1049
|
+
/** The microCompact machine state this run: the selected clearing
|
|
1051
1050
|
* machine, the cleared-projection ledger (request-view application, durable decisions — see
|
|
1052
1051
|
* `context-edit.ts`'s ledger note; per-run in-memory, so durable resume / `resumeAt` rebuilds
|
|
1053
1052
|
* start EMPTY by construction), the last request's projection seat (what the provider actually
|
|
@@ -1062,10 +1061,10 @@ export interface PreparedMicroCompact {
|
|
|
1062
1061
|
/** The frontier-machine selection — `"off"` = no proactive frontier clearing (the unified
|
|
1063
1062
|
* machine instead gets its one blocking-point shot, slice-3 arm A). */
|
|
1064
1063
|
machine: "off" | ContextEditMachine;
|
|
1065
|
-
/** MC-R
|
|
1064
|
+
/** MC-R: one-shot clear-and-retry on a provider input-too-long rejection.
|
|
1066
1065
|
* Default true since the slice-3 flip. */
|
|
1067
1066
|
clearOnRejection: boolean;
|
|
1068
|
-
/**
|
|
1067
|
+
/** The in-turn forced-compaction seat: runtask wires a closure
|
|
1069
1068
|
* that runs the SAME forced-compaction pass the prompt-too-long recovery uses (gates included)
|
|
1070
1069
|
* and answers whether a compaction landed in the session. The context hook calls it when the
|
|
1071
1070
|
* pre-send estimate breaks the guard budget and then returns `adoptSessionRebuild` so the
|
|
@@ -1093,7 +1092,7 @@ export interface PreparedMicroCompact {
|
|
|
1093
1092
|
offloadPersist?: (toolCallId: string, fullText: string) => string;
|
|
1094
1093
|
}
|
|
1095
1094
|
/**
|
|
1096
|
-
*
|
|
1095
|
+
* Resume inputs threaded into {@link prepareTask} to continue a suspended task. The Runner
|
|
1097
1096
|
* builds it from the persisted {@link Checkpoint}: rewind the branch to the suspension leaf, skip the
|
|
1098
1097
|
* suspended batch during wake-reconcile, and re-seed the §4.bis per-task correctness state so the
|
|
1099
1098
|
* resumed run is in the **same state space** it suspended in.
|
|
@@ -1108,15 +1107,15 @@ export interface PrepareResume {
|
|
|
1108
1107
|
/** The §4.bis correctness-state snapshot to re-seed (activeTools / outputRef / nestedStats /
|
|
1109
1108
|
* consolidationNotes / readFileState). */
|
|
1110
1109
|
seed: CheckpointState;
|
|
1111
|
-
/**
|
|
1110
|
+
/** How many times this task already suspended (the resumed checkpoint's
|
|
1112
1111
|
* `suspendCount`). The next suspend mints `priorSuspendCount + 1`; past `maxSuspends` it fails
|
|
1113
1112
|
* (`suspend.loop`) instead of re-suspending. Absent/0 ⇒ no prior suspends. */
|
|
1114
1113
|
priorSuspendCount?: number;
|
|
1115
|
-
/**
|
|
1114
|
+
/** The cross-slice {@link ResourceLedger} carried by the resumed `resource_limit`
|
|
1116
1115
|
* checkpoint (cumulative spend + the frozen human totals). The next slice's effective budget is
|
|
1117
1116
|
* `min(maxCostUsd, totalBudget − spent)`, and its own suspend debits onto this. Absent ⇒ the first slice. */
|
|
1118
1117
|
priorLedger?: ResourceLedger;
|
|
1119
|
-
/**
|
|
1118
|
+
/** The accumulated human-review burden carried by the resumed checkpoint
|
|
1120
1119
|
* ({@link import("../checkpoint-store.js").Checkpoint.humanReview}) — the gates resolved up to and including
|
|
1121
1120
|
* the suspend BEFORE this one. Seeds the per-task accumulator so the resumed leg ADDS this suspend's own
|
|
1122
1121
|
* latency (`now() − cp.suspendedAt`) on top, reporting the WHOLE chain's burden. Absent ⇒ no prior human time. */
|
|
@@ -1131,15 +1130,15 @@ export interface PrepareResume {
|
|
|
1131
1130
|
toolArg?: string;
|
|
1132
1131
|
}>;
|
|
1133
1132
|
};
|
|
1134
|
-
/**
|
|
1133
|
+
/** When the suspend ran with a remote workspace, the {@link CheckpointState.workspaceHandle}
|
|
1135
1134
|
* to restore — prepare rebuilds the per-task env via `deps.executionEnvFactory` then `resumeVM(snapshotId)`
|
|
1136
1135
|
* + `postResumeInit()` (instead of running on a fresh, empty env). Threaded HERE (not via `ResumeTaskConfig`)
|
|
1137
1136
|
* so the factory stays a deployment-level `RunnerDeps` capability and never pollutes `TaskSpec` — preserving
|
|
1138
1137
|
* the "untrusted caller can't inject an env" red line ({@link import("../remote-env.js").ExecutionEnvFactory}'s
|
|
1139
|
-
* own contract states it: "Lives on `RunnerDeps` (deployment-level) — NOT on `TaskSpec`"
|
|
1138
|
+
* own contract states it: "Lives on `RunnerDeps` (deployment-level) — NOT on `TaskSpec`"). */
|
|
1140
1139
|
workspaceHandle?: import("../remote-env.js").WorkspaceHandle;
|
|
1141
1140
|
/**
|
|
1142
|
-
*
|
|
1141
|
+
* The call id of the CONTENT ask whose answer an operator's approval was spent on, when
|
|
1143
1142
|
* that is what this leg redeems. Scoped as an id, not a leg-wide flag: an `unavailable` outcome on
|
|
1144
1143
|
* THAT call must become a coded failure (the approval bought a question nobody answered), while a NEW
|
|
1145
1144
|
* question raised later on the same leg had no approval spent on it and keeps the ordinary
|
|
@@ -1189,7 +1188,7 @@ export interface InheritedGate {
|
|
|
1189
1188
|
rules: SessionPermissionRules;
|
|
1190
1189
|
}>;
|
|
1191
1190
|
/** The chain's effective shell-gate doctrine — the child folds it by max-rank with its own spec. */
|
|
1192
|
-
shellGate?:
|
|
1191
|
+
shellGate?: ShellGateDoctrine;
|
|
1193
1192
|
/**
|
|
1194
1193
|
* The chain's AUTO-MODE INTENT (`TaskSpec.autoModeRequested`, session-wide like a permission mode):
|
|
1195
1194
|
* emitted when the spawning task carried the intent itself or inherited it, so an engine-spawned
|
|
@@ -1215,7 +1214,7 @@ export interface InheritedGate {
|
|
|
1215
1214
|
*/
|
|
1216
1215
|
admittedOrgScopes?: readonly string[];
|
|
1217
1216
|
/**
|
|
1218
|
-
* The MONOTONIC org-governance provenance bit
|
|
1217
|
+
* The MONOTONIC org-governance provenance bit: `true` when any leg of this
|
|
1219
1218
|
* tree ran with an org-admission surface configured (resolver / deployment scope list) or
|
|
1220
1219
|
* inherited the bit. It never clears once set (a governed tree stays governed), and it counts as
|
|
1221
1220
|
* governance evidence at the admission door EVEN when every admitted set en route is empty — a
|
|
@@ -1263,7 +1262,7 @@ export interface InheritedGate {
|
|
|
1263
1262
|
* permission ask does under `durableMandate`. */
|
|
1264
1263
|
contentMandate?: boolean;
|
|
1265
1264
|
/**
|
|
1266
|
-
|
|
1265
|
+
* F-012 — the ancestor's FROZEN auto-mode classifier: the same decider instance the
|
|
1267
1266
|
* ancestor's own gate consults for a surviving ask (`ToolGateInput.autoMode`). Without it the
|
|
1268
1267
|
* ancestor's ask DECISION CHAIN did not travel — the wrappers resolved an inherited ask straight
|
|
1269
1268
|
* at the frozen approver, so an ask the ancestor's classifier would have BLOCKED executed in the
|
|
@@ -1276,14 +1275,14 @@ export interface InheritedGate {
|
|
|
1276
1275
|
autoMode?: {
|
|
1277
1276
|
decider: AutoModeDecider;
|
|
1278
1277
|
/**
|
|
1279
|
-
*
|
|
1278
|
+
* The ancestor's per-run DENIAL-LIMIT tracker, frozen beside its decider (same owner). The
|
|
1280
1279
|
* wrapper arms count the frozen classifier's blocks on it and, at a bound, resolve the fallback
|
|
1281
1280
|
* ask at the frozen approver instead of denying (`requiresRealApproval` set, sandbox admission
|
|
1282
1281
|
* excluded). Live-only, like the decider: a cross-process redemption starts a fresh count.
|
|
1283
1282
|
*/
|
|
1284
1283
|
denialTracking?: AutoModeDenialTracker;
|
|
1285
1284
|
/**
|
|
1286
|
-
*
|
|
1285
|
+
* The SERIALIZABLE criteria half of this classifier (assembly inputs + knobs + the
|
|
1287
1286
|
* deployment's settings epoch), present when the arming deployment opted in
|
|
1288
1287
|
* (`RunnerDeps.autoMode.persistArming`). A durable park records it on the chain entry so a
|
|
1289
1288
|
* CROSS-PROCESS redemption can rebuild an equivalent decider over its own model leg instead of
|
|
@@ -1338,7 +1337,7 @@ export interface InheritedGate {
|
|
|
1338
1337
|
}>;
|
|
1339
1338
|
}
|
|
1340
1339
|
/** The runtime feature flags the stable prompt's harness-context block gates its sections on
|
|
1341
|
-
* (
|
|
1340
|
+
* (claim only what the task has). Spread into the assembly's StablePromptContext
|
|
1342
1341
|
* by the prompt-assembly phase, which re-derives the two orchestration flags against the post-exclusion roster. */
|
|
1343
1342
|
export interface PromptFeatureFlags {
|
|
1344
1343
|
policyEnabled: boolean;
|
|
@@ -1357,9 +1356,9 @@ export interface PromptFeatureFlags {
|
|
|
1357
1356
|
isSubagent: boolean;
|
|
1358
1357
|
}
|
|
1359
1358
|
/**
|
|
1360
|
-
*
|
|
1359
|
+
* A TRUSTED, run-scoped internal channel into {@link prepareTask}, set
|
|
1361
1360
|
* ONLY by a trusted CORE caller (`runRepairLoop` via the Runner's internal `runTaskStream` arg) — NEVER from
|
|
1362
|
-
* a {@link TaskSpec} field (the untrusted-caller surface
|
|
1361
|
+
* a {@link TaskSpec} field (the untrusted-caller surface). It is the live-state counterpart
|
|
1363
1362
|
* of {@link PrepareResume.seed}: where `resume.seed` re-seeds correctness state RESTORED from a checkpoint,
|
|
1364
1363
|
* this carries the LIVE per-task state the Runner cannot otherwise see (it lives in the caller's closure).
|
|
1365
1364
|
*
|
|
@@ -1368,7 +1367,7 @@ export interface PromptFeatureFlags {
|
|
|
1368
1367
|
* the bundle (failureTrace/diagnostics/attemptCount/oracleTier) sits in the loop's closure and was being lost
|
|
1369
1368
|
* — the minted checkpoint serialized `repairBundle: undefined`. Threading it here lets
|
|
1370
1369
|
* {@link prepareTask}'s `serializeCheckpointState` source the LIVE bundle so a resume re-seeds `attemptCount`
|
|
1371
|
-
* MONOTONICALLY
|
|
1370
|
+
* MONOTONICALLY. Mirrors how `nestedStats`/`resume.seed` thread trusted
|
|
1372
1371
|
* run-scoped internals through the Runner without touching `TaskSpec`.
|
|
1373
1372
|
*
|
|
1374
1373
|
* @contract prepare.deps-read-stable — the `RunnerDeps`, `RunInternals` and `ExecutionEnv` handles a host
|
|
@@ -1385,7 +1384,7 @@ export interface RunInternals {
|
|
|
1385
1384
|
* checkpoint minted MID-attempt so a resume re-seeds it; undefined for any non-repair run. */
|
|
1386
1385
|
repairBundle?: RepairBundle;
|
|
1387
1386
|
/**
|
|
1388
|
-
*
|
|
1387
|
+
* The ENGINE deliberately stripped the spawn turn's per-request `onQuestion`
|
|
1389
1388
|
* face from this leg's spec (a long-lived background/retained/revived child must not hold a
|
|
1390
1389
|
* callback torn down with the turn that spawned it). Minted ONLY by the subagent lanes'
|
|
1391
1390
|
* `stripSpawnTurnQuestionFace` helper, PAIR-PRODUCED with the strip itself — never inferred from
|
|
@@ -1398,7 +1397,7 @@ export interface RunInternals {
|
|
|
1398
1397
|
*/
|
|
1399
1398
|
questionFaceStripped?: true;
|
|
1400
1399
|
/**
|
|
1401
|
-
*
|
|
1400
|
+
* The SPAWNING run's resolved interaction posture, carried
|
|
1402
1401
|
* into engine-built children over the trusted internals channel (never copied onto the child
|
|
1403
1402
|
* SPEC — the §8.3 rule). The child's door resolves `spec ?? THIS ?? deps`, so a root's per-run
|
|
1404
1403
|
* posture override governs its whole engine-built tree instead of every child falling back to
|
|
@@ -1407,7 +1406,7 @@ export interface RunInternals {
|
|
|
1407
1406
|
*/
|
|
1408
1407
|
parentInteractionPosture?: "interactive" | "headless";
|
|
1409
1408
|
/**
|
|
1410
|
-
*
|
|
1409
|
+
* The trusted post-consume hook for the PARKED-RESUME drive:
|
|
1411
1410
|
* called by `resumeStream` after its resolve CAS WON (the token is consumed — the master
|
|
1412
1411
|
* arbitration is decided) and BEFORE the resumed leg starts. The parked-resume caller uses it to
|
|
1413
1412
|
* flip the reserved row `parked→running` (guarded CAS) + adopt the live handle/lane — the ONLY
|
|
@@ -1430,12 +1429,12 @@ export interface RunInternals {
|
|
|
1430
1429
|
*/
|
|
1431
1430
|
inheritedGate?: InheritedGate;
|
|
1432
1431
|
/**
|
|
1433
|
-
*
|
|
1432
|
+
* The delegation RUNTIME-PROVENANCE channel. Minted by the spawning delegation
|
|
1434
1433
|
* tool when the parent chain is armed (the parent mounts a memory session, or is itself recording
|
|
1435
1434
|
* for ITS parent): `ref` is the child's monotonic aggregate — the child's recorder writes into it
|
|
1436
1435
|
* as the run progresses (live faces read the current bits; the terminal attestation reduces from
|
|
1437
1436
|
* it); `contentSafety` is the chain's FROZEN classification snapshot — the child may narrow it
|
|
1438
|
-
* with its own config, never widen
|
|
1437
|
+
* with its own config, never widen. Trusted internals chain only, same posture as
|
|
1439
1438
|
* {@link inheritedGate}. Absent ⇒ the child records nothing (its deliveries then read `unknown`,
|
|
1440
1439
|
* and every judgment falls back to the static floor — fail-closed by construction; whether the
|
|
1441
1440
|
* floor's verdict MARKS the judging session follows that run's deployment evidence standard,
|
|
@@ -1448,7 +1447,7 @@ export interface RunInternals {
|
|
|
1448
1447
|
contentSafety: import("../memory-engine/delegation-provenance.js").DelegationContentSafety;
|
|
1449
1448
|
};
|
|
1450
1449
|
/**
|
|
1451
|
-
*
|
|
1450
|
+
* The SESSION-scoped org-admission freeze for a SAME-SESSION continuation
|
|
1452
1451
|
* that is NOT a checkpoint resume: a retained background child revived through the in-process resume
|
|
1453
1452
|
* leg. The checkpoint plane already freezes the session's own verdict
|
|
1454
1453
|
* ({@link InheritedGate.ownAdmittedOrgScopes}); this leg has no checkpoint, so without a carrier it
|
|
@@ -1468,7 +1467,7 @@ export interface RunInternals {
|
|
|
1468
1467
|
current: import("../memory-admission.js").OwnOrgAdmissionVerdict | undefined;
|
|
1469
1468
|
};
|
|
1470
1469
|
/**
|
|
1471
|
-
*
|
|
1470
|
+
* This run's LATE-BOUND peer-identity carrier (a REF, same family and reason as
|
|
1472
1471
|
* {@link ownOrgAdmissionRef}: revival replays a spread copy of spawn-time internals, and the axes
|
|
1473
1472
|
* a run wears are born at different points — a* handle at registration, session/task at prepare's
|
|
1474
1473
|
* session acquisition). Created at internals assembly (delegation lanes; runtask normalizes one
|
|
@@ -1478,7 +1477,7 @@ export interface RunInternals {
|
|
|
1478
1477
|
*/
|
|
1479
1478
|
peerSelfRef?: import("../../agents/peer-admission.js").PeerSelfRef;
|
|
1480
1479
|
/**
|
|
1481
|
-
*
|
|
1480
|
+
* This run's INBOUND peer-chain ref: overwritten at the harness consumption boundary
|
|
1482
1481
|
* with the chain of the peer message the model just consumed (enqueue-time writes would leak a
|
|
1483
1482
|
* not-yet-seen message's chain into outbound sends); seeded by the L3/L4 wake legs; empty
|
|
1484
1483
|
* otherwise. Not checkpointed in v1 (recorded honest boundary: a cross-process resume forwards
|
|
@@ -1486,7 +1485,7 @@ export interface RunInternals {
|
|
|
1486
1485
|
*/
|
|
1487
1486
|
peerInboundChainRef?: import("../../agents/peer-admission.js").PeerInboundChainRef;
|
|
1488
1487
|
/**
|
|
1489
|
-
*
|
|
1488
|
+
* The PARENT run's peer-identity ref, PAIR-MINTED with {@link parentNotify} at every
|
|
1490
1489
|
* trust point that binds the uplink callback (spawn assembly, the resume face's replacement): the
|
|
1491
1490
|
* callback is opaque and the parent AXES deliberately keep the original spawner on the revive arm
|
|
1492
1491
|
* while the callback points at the WAKER — so the uplink's admission identity can only travel
|
|
@@ -1494,7 +1493,7 @@ export interface RunInternals {
|
|
|
1494
1493
|
*/
|
|
1495
1494
|
parentPeerRef?: import("../../agents/peer-admission.js").PeerSelfRef;
|
|
1496
1495
|
/**
|
|
1497
|
-
* 🔴
|
|
1496
|
+
* 🔴 The workflow **nesting depth** for this run, a TRUSTED
|
|
1498
1497
|
* cross-process channel (worker/script can NEVER set it — it is not a {@link TaskSpec} field nor a
|
|
1499
1498
|
* `run_workflow` tool param). When a deployment initiates a workflow on behalf of a parent run that is
|
|
1500
1499
|
* itself inside a workflow (e.g. service's `/v1/workflows`), it threads `workflowDepth = parentDepth + 1`
|
|
@@ -1505,7 +1504,7 @@ export interface RunInternals {
|
|
|
1505
1504
|
*/
|
|
1506
1505
|
workflowDepth?: number;
|
|
1507
1506
|
/**
|
|
1508
|
-
*
|
|
1507
|
+
* The host's DECISIONS for parked workflow-agent rows (`wa*` rows with `status:"parked"`), a TRUSTED
|
|
1509
1508
|
* run channel like `workflowDepth` (never a `TaskSpec` field, never a tool argument — a model cannot decide
|
|
1510
1509
|
* an approval). A host that decided a workflow child's parked checkpoint launches the run that re-invokes
|
|
1511
1510
|
* `Workflow({resumeFromRunId})` with the decision here; the Workflow tool applies the entries naming the
|
|
@@ -1521,7 +1520,7 @@ export interface RunInternals {
|
|
|
1521
1520
|
inheritedGate?: InheritedGate;
|
|
1522
1521
|
}>;
|
|
1523
1522
|
/**
|
|
1524
|
-
*
|
|
1523
|
+
* Set ONLY by the Agent tool's fork route (`Agent(subagent_type:"fork")`, a core caller) on the
|
|
1525
1524
|
* child it spawns: this run IS a forked child. `prepareTask` threads it to tool ctx as `insideFork` so the
|
|
1526
1525
|
* child's own Agent tool refuses a nested fork (nesting guard — mirrors CC's "fork is not available inside a
|
|
1527
1526
|
* forked worker"; a fork can still delegate via `Agent`, just not fork again). TRUSTED internal (NOT a
|
|
@@ -1529,7 +1528,7 @@ export interface RunInternals {
|
|
|
1529
1528
|
*/
|
|
1530
1529
|
insideFork?: boolean;
|
|
1531
1530
|
/**
|
|
1532
|
-
*
|
|
1531
|
+
* The PARENT's reminder provenance mark, set ONLY by the Agent tool's
|
|
1533
1532
|
* fork route on the child it spawns ("one declaration, one mark": a fork runs under the parent's
|
|
1534
1533
|
* byte-identical system-prompt declaration, so its own engine mints must carry the PARENT's mark;
|
|
1535
1534
|
* a spawn/clone context mints its own). Verified through the mint home's verify port at adoption
|
|
@@ -1540,7 +1539,7 @@ export interface RunInternals {
|
|
|
1540
1539
|
*/
|
|
1541
1540
|
reminderMark?: string;
|
|
1542
1541
|
/**
|
|
1543
|
-
*
|
|
1542
|
+
* Set UNCONDITIONALLY by every core spawn path (`createSubagentTool`'s
|
|
1544
1543
|
* `childInternals` — shared by all four spawn legs sync/steer/background/fork, its persisted
|
|
1545
1544
|
* `internalsSnapshot` for revive, and the workflow orchestrator's `spawnAttribution`), regardless
|
|
1546
1545
|
* of whether a NAMEABLE `parentTaskId`/`parentToolCallId` exists. A directly-started workflow (no
|
|
@@ -1563,7 +1562,7 @@ export interface RunInternals {
|
|
|
1563
1562
|
*/
|
|
1564
1563
|
sessionPlacement?: import("../session.js").SessionPlacement;
|
|
1565
1564
|
/**
|
|
1566
|
-
*
|
|
1565
|
+
* The DEFAULT role-base persona for a DELEGATED child, threaded by
|
|
1567
1566
|
* `createSubagentTool`'s execute (a core caller) when neither an agent-definition `systemPrompt` nor the
|
|
1568
1567
|
* delegation tool's `opts.systemPrompt` names one. It sits at the BOTTOM of the role-base chain —
|
|
1569
1568
|
* `spec.systemPrompt ?? resolvedRole.systemPrompt ?? internals.defaultSystemPrompt` — so a deployment's
|
|
@@ -1575,7 +1574,7 @@ export interface RunInternals {
|
|
|
1575
1574
|
*/
|
|
1576
1575
|
defaultSystemPrompt?: string;
|
|
1577
1576
|
/**
|
|
1578
|
-
*
|
|
1577
|
+
* GOAL MODE flag, a TRUSTED internal channel set ONLY by `runGoal` (a core caller),
|
|
1579
1578
|
* NEVER a {@link TaskSpec} field. It drives `featureFlags.goalEnabled` → injects `GOAL_COMPLETION_GUIDANCE`.
|
|
1580
1579
|
* Why internal (not a public `TaskSpec.goalMode`): the guidance promises "declaring done STOPS iteration and
|
|
1581
1580
|
* surfaces" — a promise only `runGoal`'s loop makes real. A public field would let a caller inject that
|
|
@@ -1584,7 +1583,7 @@ export interface RunInternals {
|
|
|
1584
1583
|
*/
|
|
1585
1584
|
goalMode?: boolean;
|
|
1586
1585
|
/**
|
|
1587
|
-
* 🔴
|
|
1586
|
+
* 🔴 Skill→subagent manifest-scope PROPAGATION (must close before ON). The parent task's
|
|
1588
1587
|
* ACTIVE skill-manifest frames, snapshotted at the moment a subagent was spawned WHILE a manifest scope
|
|
1589
1588
|
* was live on the parent. The child's {@link prepareTask} seeds its own {@link ActiveSkillScope} from
|
|
1590
1589
|
* these so the child inherits the parent skill's deny-narrowing — fail-closed and MONOTONIC: a child of
|
|
@@ -1592,7 +1591,7 @@ export interface RunInternals {
|
|
|
1592
1591
|
* never re-grant a tool/path the parent removed).
|
|
1593
1592
|
*
|
|
1594
1593
|
* This is a TRUSTED, run-scoped channel filled ONLY by `createSubagentTool`'s `execute` (a core caller),
|
|
1595
|
-
* NEVER a {@link TaskSpec} field (TaskSpec is the untrusted-caller surface
|
|
1594
|
+
* NEVER a {@link TaskSpec} field (TaskSpec is the untrusted-caller surface). It mirrors
|
|
1596
1595
|
* how `repairBundle`/`resume.seed` thread live per-task state the Runner cannot see from `spec`.
|
|
1597
1596
|
*
|
|
1598
1597
|
* Fail-closed: when the parent HAD an active manifest at spawn but the precise frames cannot be
|
|
@@ -1602,7 +1601,7 @@ export interface RunInternals {
|
|
|
1602
1601
|
*/
|
|
1603
1602
|
inheritedManifestScope?: readonly ActiveSkillFrame[];
|
|
1604
1603
|
/**
|
|
1605
|
-
*
|
|
1604
|
+
* When this task runs as a SUB-AGENT spawned under a parent task's
|
|
1606
1605
|
* tool call, the spawning tool's `ToolExecuteContext.toolCallId`. The Runner stamps it onto this task's
|
|
1607
1606
|
* stream content events as {@link TaskEvent.parentToolCallId} so a consumer can attribute the child's live
|
|
1608
1607
|
* content to the delegation subtree WITHOUT core merging the child stream into the parent (lightweight
|
|
@@ -1612,18 +1611,18 @@ export interface RunInternals {
|
|
|
1612
1611
|
*/
|
|
1613
1612
|
parentToolCallId?: string;
|
|
1614
1613
|
/**
|
|
1615
|
-
*
|
|
1614
|
+
* A SUBAGENT's human display NAME, threaded at spawn so the
|
|
1616
1615
|
* child's `task_progress` ticks carry a readable label (a Fleet child row otherwise shows the raw `taskId`).
|
|
1617
1616
|
* Filled by `createSubagentTool`'s `execute` = the explicit `taskName`, else the selected agent-type
|
|
1618
1617
|
* (`AgentDefinition.name`). TRUSTED run-scoped channel (NOT a {@link TaskSpec} field), mirroring
|
|
1619
1618
|
* `parentToolCallId`. Absent for a top-level run / a bare delegation with neither label — the child's
|
|
1620
1619
|
* `task_progress` then carries NO `name` (it keeps its taskId; it deliberately does NOT fall back to the raw
|
|
1621
|
-
* objective, which could leak a delegated secret
|
|
1620
|
+
* objective, which could leak a delegated secret). Untrusted (`taskName` is model-chosen) →
|
|
1622
1621
|
* the consumer sanitizes via `inlineUntrusted` at emit.
|
|
1623
1622
|
*/
|
|
1624
1623
|
agentName?: string;
|
|
1625
1624
|
/**
|
|
1626
|
-
*
|
|
1625
|
+
* The EXPLICIT `Agent({name})` spawn identity — set
|
|
1627
1626
|
* ONLY when the spawn carried a `name` parameter, unlike {@link agentName} (a DISPLAY label:
|
|
1628
1627
|
* description or agent-type, present on nearly every spawn). Teammate semantics (hierarchy clamp,
|
|
1629
1628
|
* teammate addendum, uplink attribution) key on THIS field; keying on the display label made
|
|
@@ -1631,17 +1630,17 @@ export interface RunInternals {
|
|
|
1631
1630
|
*/
|
|
1632
1631
|
explicitAgentName?: string;
|
|
1633
1632
|
/**
|
|
1634
|
-
*
|
|
1633
|
+
* The SPAWNING run's taskId, threaded at spawn (from the parent's
|
|
1635
1634
|
* `ToolExecuteContext.taskId`) so this child's `task_progress` ticks carry `parentTaskId`. Lets a UI build the
|
|
1636
1635
|
* live nested-agent tree directly (child.parentTaskId === parent.taskId) at any depth. TRUSTED run-scoped
|
|
1637
1636
|
* channel (NOT a {@link TaskSpec} field), mirroring `parentToolCallId`. Absent for a top-level run.
|
|
1638
1637
|
*/
|
|
1639
1638
|
parentTaskId?: string;
|
|
1640
|
-
/**
|
|
1639
|
+
/** The spawning run's sessionId (paired with parentTaskId; see
|
|
1641
1640
|
* ToolExecuteContext.parentSessionId). */
|
|
1642
1641
|
parentSessionId?: string;
|
|
1643
1642
|
/**
|
|
1644
|
-
*
|
|
1643
|
+
* The memory-capture opt-out FLOOR: TRUE ⇔ the spawning session was under an
|
|
1645
1644
|
* opt-out when this child spawned. The child then runs opted-out itself (its prepare mints its
|
|
1646
1645
|
* own one-way record, reason naming the floor) — NOT re-adjudicated against the child's
|
|
1647
1646
|
* entitlement (the floor is the parent's already-granted opt-out tightening the tree; a
|
|
@@ -1653,7 +1652,7 @@ export interface RunInternals {
|
|
|
1653
1652
|
*/
|
|
1654
1653
|
memoryCaptureFloor?: true;
|
|
1655
1654
|
/**
|
|
1656
|
-
*
|
|
1655
|
+
* The floor's THIRD state: the spawning session's
|
|
1657
1656
|
* capture state was INDETERMINATE at spawn (its record store faulted at the getter read).
|
|
1658
1657
|
* Neither boolean is honest there — no floor runs a possibly-recorded lineage captured, a coined
|
|
1659
1658
|
* floor mints an IRREVERSIBLE record off an unreadable state — so the lane carries the fault
|
|
@@ -1663,11 +1662,11 @@ export interface RunInternals {
|
|
|
1663
1662
|
* exclusive with it at the spawn site (the floor wins when the state IS known).
|
|
1664
1663
|
*/
|
|
1665
1664
|
memoryCaptureFloorIndeterminate?: true;
|
|
1666
|
-
/**
|
|
1665
|
+
/** The spawning session's write-plane control dir (the coordinate its capture
|
|
1667
1666
|
* opt-out record is keyed under), so a child on a DIFFERENT memory plane can still run the
|
|
1668
1667
|
* record-query leg against the parent's own carrier. Trusted chain, rides internalsSnapshot. */
|
|
1669
1668
|
memoryCaptureQueryDir?: string;
|
|
1670
|
-
/**
|
|
1669
|
+
/** The ancestor chain's capture coordinates (root first, one
|
|
1671
1670
|
* row per generation, appended by each spawner's ctx seat). The child's harvest closures walk
|
|
1672
1671
|
* every row, so a mid-run flip ANYWHERE up the tree suppresses every in-flight descendant.
|
|
1673
1672
|
* Trusted chain; rides internalsSnapshot. */
|
|
@@ -1690,7 +1689,7 @@ export interface RunInternals {
|
|
|
1690
1689
|
*/
|
|
1691
1690
|
delegationTaskType?: import("../types.js").DelegationTaskType;
|
|
1692
1691
|
/**
|
|
1693
|
-
*
|
|
1692
|
+
* The registry row's stop-cycle generation this run executes as (fresh spawn = 1, a
|
|
1694
1693
|
* revival's bumped counter), threaded by the BACKGROUND delegation lanes from the registry's own
|
|
1695
1694
|
* `cycleSeq` so every `task_progress` tick the run mints carries it as `seq` (same axis as
|
|
1696
1695
|
* `TaskNotificationPayload.seq` / `BackgroundChildEvent.seq`). Absent for runs with no `a*` row
|
|
@@ -1705,7 +1704,7 @@ export interface RunInternals {
|
|
|
1705
1704
|
* "everything under this host session" needs the root anchor, not an alias walk. */
|
|
1706
1705
|
rootSessionId?: string;
|
|
1707
1706
|
/**
|
|
1708
|
-
*
|
|
1707
|
+
* The run tree's PLACEMENT root: the fixed point a target-bound env factory keys
|
|
1709
1708
|
* its placement lookup on ({@link import("../remote-env.js").ExecutionEnvFactoryContext.placementRootSessionId}).
|
|
1710
1709
|
* A SEPARATE axis from {@link rootSessionId} deliberately: that field means "member of this host
|
|
1711
1710
|
* session's DELEGATION tree" and is consumed by the registry access/recovery faces — cascade rungs
|
|
@@ -1718,15 +1717,14 @@ export interface RunInternals {
|
|
|
1718
1717
|
* workflow deps → shared internals base), so every descendant of a placed leg keeps the fixed
|
|
1719
1718
|
* point; prepare's mint reads it first (`placementRoot ?? rootSessionId ?? sessionId`). Absent
|
|
1720
1719
|
* everywhere else — the delegation lanes' `rootSessionId` fixed point then becomes the placement
|
|
1721
|
-
* root through the middle segment, unchanged. DURABLE
|
|
1722
|
-
* residual, fulfilled): the suspend mint stamps the resolved fixed point as
|
|
1720
|
+
* root through the middle segment, unchanged. DURABLE: the suspend mint stamps the resolved fixed point as
|
|
1723
1721
|
* `CheckpointState.placementRootSessionId`, and a bare durable resume restores it into this
|
|
1724
1722
|
* member (live internals win when re-supplied; a CONTRADICTING re-supply refuses pre-CAS,
|
|
1725
1723
|
* `resume.placement_mismatch`). TRUSTED run-scoped channel (never a {@link TaskSpec} field).
|
|
1726
1724
|
*/
|
|
1727
1725
|
placementRoot?: string;
|
|
1728
1726
|
/**
|
|
1729
|
-
*
|
|
1727
|
+
* The REGISTRY SCOPE this run's own background row lives in: the domain its registry-facing
|
|
1730
1728
|
* tools (TaskOutput / TaskStop / SendMessage / AgentTranscript / Monitor, and the announce listing)
|
|
1731
1729
|
* must mount in to see it. Filled by the delegation tool at spawn, which is the party that CHOSE the
|
|
1732
1730
|
* domain when it registered the row — `ctx.principal` when the spawning run has one, else the
|
|
@@ -1737,17 +1735,17 @@ export interface RunInternals {
|
|
|
1737
1735
|
* with no principal at all, and `principal ?? "default"` sends every one of its registry-facing tools
|
|
1738
1736
|
* to a domain the row is not in — scope is fail-closed on both access predicates, so such a child
|
|
1739
1737
|
* cannot see its own row, its siblings, or the children it spawns. Carrying the domain as its own
|
|
1740
|
-
* trusted axis keeps `principal` the
|
|
1738
|
+
* trusted axis keeps `principal` the IDENTITY it is: the identity also keys the durable
|
|
1741
1739
|
* approval / checkpoint namespace (`checkpointScopeOf`), the runtime-capability lookup and the MCP
|
|
1742
1740
|
* principal header, and a mount's registry scope has no business moving any of those (an unattended
|
|
1743
|
-
* safety park must not migrate into the caller's opt-in approval bucket
|
|
1741
|
+
* safety park must not migrate into the caller's opt-in approval bucket).
|
|
1744
1742
|
*
|
|
1745
1743
|
* TRUSTED channel (never a {@link TaskSpec} field, never a model argument), like the parentage axes
|
|
1746
1744
|
* above. When a deployment sets both, they agree by construction: with a principal present the
|
|
1747
1745
|
* delegation tool resolves this axis TO that principal.
|
|
1748
1746
|
*/
|
|
1749
1747
|
registryScope?: string;
|
|
1750
|
-
/**
|
|
1748
|
+
/** The spawning run's ADOPTED center artifact, threaded down the
|
|
1751
1749
|
* trusted internals chain so every child in the tree composes the SAME closure (a child must
|
|
1752
1750
|
* never spontaneously adopt the live candidate while its parent runs an older pin — that is the
|
|
1753
1751
|
* exact mixed-version state the epoch exists to prevent). Resolved by-digest through the
|
|
@@ -1758,38 +1756,38 @@ export interface RunInternals {
|
|
|
1758
1756
|
/** R2 双形轴 — parent's resolved prompt profile, inherited unless the child spec overrides. */
|
|
1759
1757
|
promptProfile?: "simple" | "classic";
|
|
1760
1758
|
/**
|
|
1761
|
-
*
|
|
1759
|
+
* An OPT-IN, DISPLAY-ONLY event sink a deployment sets on the TOP run to
|
|
1762
1760
|
* receive a subagent's live `task_progress` ticks (which otherwise stay in the child's ISOLATED stream). Threaded
|
|
1763
1761
|
* recursively down the delegation tree (via `ctx.forwardEvent`), so every nested subagent's ticks bubble to the
|
|
1764
1762
|
* SAME sink. The Runner's ctx wrapper forwards `task_progress` always; when the run's spec sets
|
|
1765
|
-
|
|
1763
|
+
* `forwardSubagentEvents: true` it ALSO forwards the child's content events (`text_delta` / `text_end` /
|
|
1766
1764
|
* `reasoning_delta` / `tool_start` / `tool_end` — the subagent viewing pane, carrying the same UNTRUSTED-RAW/consumer-must-redact
|
|
1767
1765
|
* contract as the main stream's tool events). Either way the child stream is NEVER merged into the parent's
|
|
1768
1766
|
* MODEL context (this is purely a render channel). Absent unless the deployment opted in.
|
|
1769
1767
|
*/
|
|
1770
1768
|
onForwardEvent?: (event: TaskEvent) => void;
|
|
1771
1769
|
/**
|
|
1772
|
-
*
|
|
1770
|
+
* The run's OWN top-level `status` TaskEvent stream (brain liveness: rate-limit/retry/
|
|
1773
1771
|
* reconnect/circuit-open), offered to the internals holder beside the queue. The queue alone was
|
|
1774
1772
|
* enough for a direct `runTask` caller (the TaskStream carries these frames), but a COMPOSITION
|
|
1775
1773
|
* entry (verify/cascade) drains its inner legs' queues itself — without this seat, an inner leg's
|
|
1776
1774
|
* retry disclosure died inside the gate and the wire showed a silent stall. Fed the SAME frame
|
|
1777
|
-
* object the queue receives, at the same moment; contained by the run's safe notifier (
|
|
1778
|
-
*
|
|
1775
|
+
* object the queue receives, at the same moment; contained by the run's safe notifier (a throwing
|
|
1776
|
+
* sink is swallowed, first failure per site disclosed, never faults the leg). Subagent
|
|
1779
1777
|
* frames still ride {@link onForwardEvent} — this seat is ONLY the run's own status type.
|
|
1780
1778
|
*/
|
|
1781
1779
|
onStatusEvent?: (event: Extract<TaskEvent, {
|
|
1782
1780
|
type: "status";
|
|
1783
1781
|
}>) => void;
|
|
1784
1782
|
/**
|
|
1785
|
-
*
|
|
1783
|
+
* Trusted run-local system-injection sink. `Runner.runLocked` wires this to the
|
|
1786
1784
|
* live TaskStream queue plus the current harness follow-up lane; it is not a public TaskSpec field.
|
|
1787
1785
|
*/
|
|
1788
|
-
/**
|
|
1786
|
+
/** The run-local per-tool-call detach hub. runtask creates it and exposes
|
|
1789
1787
|
* `TaskStream.detach(toolCallId)`; the hands Bash tool threads `signalFor(toolCallId)` into env.exec. */
|
|
1790
1788
|
detachHub?: import("../tool-detach.js").ToolDetachHub;
|
|
1791
1789
|
/**
|
|
1792
|
-
*
|
|
1790
|
+
* The Runner's per-session read-file-state seats (CC parity: readFileState is
|
|
1793
1791
|
* session-scoped). Always set by the Runner's own prepare call (overriding any caller value, like
|
|
1794
1792
|
* the peer refs beside it); absent on a standalone prepareTask, where the transcript-replay rung
|
|
1795
1793
|
* covers alone. A CACHE, never an authority — see {@link SessionReadFileStates}. Trusted internals
|
|
@@ -1797,7 +1795,7 @@ export interface RunInternals {
|
|
|
1797
1795
|
*/
|
|
1798
1796
|
sessionReadStates?: SessionReadFileStates;
|
|
1799
1797
|
onTaskNotification?: (notification: TaskNotificationPayload,
|
|
1800
|
-
/** Injection tier (
|
|
1798
|
+
/** Injection tier (the ladder is LIVE): "next" = the running turn's next boundary
|
|
1801
1799
|
* (arrival order, consecutive frames batch); "later" = the run's would-otherwise-stop seat
|
|
1802
1800
|
* (never folded into work in progress); "now" = class-head + earliest natural boundary on this
|
|
1803
1801
|
* lane (interrupt authority belongs to the steer face, never to notifications). Internal
|
|
@@ -1807,7 +1805,7 @@ export interface RunInternals {
|
|
|
1807
1805
|
priority?: import("../task-notification.js").SystemInjectionPriority;
|
|
1808
1806
|
}) => void;
|
|
1809
1807
|
/**
|
|
1810
|
-
*
|
|
1808
|
+
* The PARENT run's notification injector (its runtask-wrapped
|
|
1811
1809
|
* `injectTaskNotification`), threaded into a CHILD's internals at spawn time so the child's
|
|
1812
1810
|
* SendMessage("main") uplink lands in the parent's queue at a turn boundary (the CC
|
|
1813
1811
|
* "delivered automatically" parent half). DELIBERATELY a separate field from
|
|
@@ -1819,14 +1817,14 @@ export interface RunInternals {
|
|
|
1819
1817
|
priority?: import("../task-notification.js").SystemInjectionPriority;
|
|
1820
1818
|
}) => void;
|
|
1821
1819
|
/**
|
|
1822
|
-
*
|
|
1820
|
+
* The PARENT run's subagent-retain ledger, threaded to a CHILD so its
|
|
1823
1821
|
* SendMessage can continue a RETAINED SIBLING (the sibling's retain entry lives on the parent's
|
|
1824
1822
|
* ledger — without this, sibling resolution succeeds but delivery always reads not-retained).
|
|
1825
1823
|
* TRUSTED chain; read-only use (the sibling leg resumes through the same fenced resume face).
|
|
1826
1824
|
*/
|
|
1827
1825
|
parentRetainLedger?: import("../../agents/retain-ledger.js").SubagentRetainLedger;
|
|
1828
1826
|
/**
|
|
1829
|
-
*
|
|
1827
|
+
* Hands THIS run's notification injector back to the SPAWNER once the lane is
|
|
1830
1828
|
* live (runtask calls it with its wrapped `injectTaskNotification`). The spawner stores it on the
|
|
1831
1829
|
* child's registry handle so a parent/sibling SendMessage can deliver TO the RUNNING child at its
|
|
1832
1830
|
* next turn boundary (CC's in-memory `pendingMessages` pedestal, anchors/2.1.212
|
|
@@ -1839,9 +1837,9 @@ export interface RunInternals {
|
|
|
1839
1837
|
priority?: import("../task-notification.js").SystemInjectionPriority;
|
|
1840
1838
|
}) => Promise<"queued" | "parked" | "dropped_duplicate">) => void;
|
|
1841
1839
|
/**
|
|
1842
|
-
*
|
|
1840
|
+
* Per-task ISOLATION hint, a TRUSTED run-scoped channel filled ONLY by a core caller
|
|
1843
1841
|
* (the workflow's `ctx.agent` when the SCRIPT passed `{ isolation: "worktree" }` as an OPTION) — NEVER a
|
|
1844
|
-
* {@link TaskSpec} field (the untrusted-caller surface
|
|
1842
|
+
* {@link TaskSpec} field (the untrusted-caller surface). Forwarded to
|
|
1845
1843
|
* {@link ExecutionEnvFactory} via {@link ExecutionEnvFactoryContext.isolation} so the trusted control-plane
|
|
1846
1844
|
* factory mints a git-worktree-rooted env for this agent; and it makes root resolution use the worktree
|
|
1847
1845
|
* env's own cwd (the worktree dir), bypassing `deps.rootPath`. Isolate-ONLY: the runtime never merges
|
|
@@ -1894,26 +1892,26 @@ export interface RunInternals {
|
|
|
1894
1892
|
* into the running child (fenced-marker semantics matching the workflow agent handle). Threaded to
|
|
1895
1893
|
* the tool ctx as {@link ToolExecuteContext.onSubagentSpawn} and recursively down the delegation
|
|
1896
1894
|
* tree. Absent ⇒ children run non-steerable (prior behavior, zero overhead).
|
|
1897
|
-
* SCOPE
|
|
1895
|
+
* SCOPE: only SYNC delegations emit a handle — a
|
|
1898
1896
|
* `run_in_background` child does not (poll/stop it via TaskOutput/TaskStop); wiring the background
|
|
1899
1897
|
* lane is a recorded follow-up, not an oversight a deployment should discover at runtime.
|
|
1900
1898
|
*/
|
|
1901
1899
|
onSubagentSpawn?: (handle: import("../../agents/subagent.js").SubagentSteerHandle) => void;
|
|
1902
1900
|
/**
|
|
1903
|
-
*
|
|
1901
|
+
* A TRUSTED run-scoped tool-ACTIVITY sink, filled ONLY by a core caller (the workflow's
|
|
1904
1902
|
* `ctx.agent`, to render a per-agent "last N tool calls" drill-down). Called synchronously at each tool start +
|
|
1905
1903
|
* end with structural data (name/phase/ids) — NEVER args/output (those carry untrusted/host data). NEVER a
|
|
1906
1904
|
* {@link TaskSpec} field. Absent ⇒ no activity capture (default).
|
|
1907
1905
|
*
|
|
1908
1906
|
* Reaches activity on FRESH and RESUMED runs alike — the durable-resume entry (`resumeStream`) threads
|
|
1909
1907
|
* `internals` too (see its parent-constraint re-supply snapshot), so a resumed leg's SUBSEQUENT tool calls
|
|
1910
|
-
|
|
1908
|
+
* hit this sink. One real boundary remains: the resume's already-approved pending call itself is
|
|
1911
1909
|
* executed by `applyResumeDecision`'s own callback, outside the frame-minting harness, so THAT one call
|
|
1912
1910
|
* emits no activity.
|
|
1913
1911
|
*/
|
|
1914
1912
|
onActivity?: (activity: ToolActivity) => void;
|
|
1915
1913
|
/**
|
|
1916
|
-
*
|
|
1914
|
+
* A TRUSTED run-scoped WORKSPACE-observation sink, filled ONLY by a core caller
|
|
1917
1915
|
* (the workflow's `ctx.agent` / `ctx.agentStream`, to record an isolated agent's worktree directory on the
|
|
1918
1916
|
* persisted run record). NEVER a {@link TaskSpec} field — same posture as {@link onActivity}.
|
|
1919
1917
|
*
|
|
@@ -1934,7 +1932,7 @@ export interface RunInternals {
|
|
|
1934
1932
|
onWorkspaceResolved?: (workspace: ResolvedWorkspace) => void;
|
|
1935
1933
|
}
|
|
1936
1934
|
/**
|
|
1937
|
-
*
|
|
1935
|
+
* The payload of {@link RunInternals.onWorkspaceResolved}: the working root this task actually
|
|
1938
1936
|
* runs on, plus whether that root is the task's OWN isolated workspace.
|
|
1939
1937
|
*
|
|
1940
1938
|
* `isolated: true` means "`cwd` is this agent's own git worktree": it is reported only when
|
|
@@ -1948,14 +1946,14 @@ export interface ResolvedWorkspace {
|
|
|
1948
1946
|
cwd: string;
|
|
1949
1947
|
/** True only for an accepted `isolation: "worktree"` request (⇒ `cwd` is this agent's own worktree). */
|
|
1950
1948
|
isolated: boolean;
|
|
1951
|
-
/** True when the task's execution env is REMOTE
|
|
1949
|
+
/** True when the task's execution env is REMOTE: `cwd` then names a path INSIDE the remote
|
|
1952
1950
|
* target (a per-task sandbox on the shape-(d) exemption leg, e.g. `/workspace`), which does not exist —
|
|
1953
1951
|
* or names an unrelated directory — on the host. `isolated && !remote` is the only combination under
|
|
1954
1952
|
* which `cwd` is a host path a consumer may diff / merge / remove. */
|
|
1955
1953
|
remote: boolean;
|
|
1956
1954
|
}
|
|
1957
1955
|
/**
|
|
1958
|
-
*
|
|
1956
|
+
* The resolver's answer, with the WITHHELD cause beside the value.
|
|
1959
1957
|
*
|
|
1960
1958
|
* The old signature returned a bare `unknown`, which collapsed three different worlds into one
|
|
1961
1959
|
* `undefined`: "this tool declares no preview at all", "the projection threw / could not be
|
|
@@ -2037,23 +2035,23 @@ export interface SuspendSaga {
|
|
|
2037
2035
|
* "the park lane's closures exist" is one fact; `suspendAsk` stays optional INSIDE it because the park predicate (a store,
|
|
2038
2036
|
* and something to park for) is a narrower condition than the gate machinery's activation. */
|
|
2039
2037
|
export interface ParkAsk {
|
|
2040
|
-
/**
|
|
2038
|
+
/** The gate's content-ask routing closure (total by construction; answers `unavailable` with no live face). */
|
|
2041
2039
|
resolveContentAsk: NonNullable<ToolGateInput["resolveContentAsk"]>;
|
|
2042
|
-
/**
|
|
2040
|
+
/** The durable park closure (twelve positional seats then the structural carry), or undefined when the park
|
|
2043
2041
|
* lane is not armed (the gate then keeps the synchronous onAsk path). */
|
|
2044
2042
|
suspendAsk: ToolGateInput["suspendAsk"];
|
|
2045
2043
|
}
|
|
2046
2044
|
/**
|
|
2047
|
-
*
|
|
2045
|
+
* `runLocked`'s per-run mutable state, EXPLICIT. These fields started as loose
|
|
2048
2046
|
* `let`/`const` bindings in the R2 declaration hub; the extraction kept every assignment at its
|
|
2049
2047
|
* original site and order (binding-form-only rewrite — the event-snapshot pin held the run
|
|
2050
2048
|
* byte-identical), and later work has since added fields directly here (see the per-field notes).
|
|
2051
2049
|
* Grouped by lifecycle semantics per the B15 pre-recon partition. Function members start as inert
|
|
2052
2050
|
* placeholders and are assigned at their ORIGINAL declaration sites (the original code could not
|
|
2053
2051
|
* call them earlier either — TDZ proved it). Not on the npm face; this extraction is what enabled
|
|
2054
|
-
* createTurnBoundary / createHarnessHandlers (
|
|
2052
|
+
* createTurnBoundary / createHarnessHandlers (both are run lanes of their own).
|
|
2055
2053
|
*
|
|
2056
|
-
* WRITERS, by group (
|
|
2054
|
+
* WRITERS, by group (the driver mints the zero value, initial-run-state.ts, and hands it to every
|
|
2057
2055
|
* lane as a borrowed-mutable seat): `telemetry` / `degrade` / `limits` / `budget` initial values and function
|
|
2058
2056
|
* members — the telemetry-and-budget-seats lane; `counters` / `attach` initial values — the attachment-seats lane
|
|
2059
2057
|
* (the clock lane zeroes `counters.walltimeSyncBackstopFired`; the tool-mount facts only read); the per-turn writes — the harness-handlers lane
|
|
@@ -2064,20 +2062,20 @@ export interface RunState {
|
|
|
2064
2062
|
telemetry: {
|
|
2065
2063
|
cacheFamily: ReturnType<typeof cacheFamilyOf>;
|
|
2066
2064
|
pricing: ModelPricing;
|
|
2067
|
-
/**
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2065
|
+
/** Whether the CURRENT serving model has a configured price table (a
|
|
2066
|
+
* `RunnerDeps.pricing` entry or a `Model.cost` declaration). When neither exists,
|
|
2067
|
+
* `modelCostToPricing(undefined)` yields an all-zero table and every computed cost is a
|
|
2068
|
+
* fabricated 0 — indistinguishable from "declared free". This flag keeps the two apart so
|
|
2069
|
+
* the DISCLOSURE faces (trace frames, public stats) can go absent instead of lying; the
|
|
2070
|
+
* internal budget coordinate (`stats.costMicroUsd`) stays numeric either way. */
|
|
2073
2071
|
pricingConfigured: boolean;
|
|
2074
|
-
/**
|
|
2072
|
+
/** Sticky — some spend was ACCOUNTED while `pricingConfigured` was false (a mid-task
|
|
2075
2073
|
* model switch can flip pricedness, so per-call state isn't enough for the task total). Once
|
|
2076
2074
|
* true, the task-level cost total is an undercount and its faces are omitted. */
|
|
2077
2075
|
unpricedSpend: boolean;
|
|
2078
2076
|
tracer: TaskSpec["tracer"];
|
|
2079
2077
|
taskId: string;
|
|
2080
|
-
/**
|
|
2078
|
+
/** The run's engine-minted identity, so the task.start/task.end pair carries it from ONE
|
|
2081
2079
|
* seat (the same place taskId is published). Empty only before the run body assigns it. */
|
|
2082
2080
|
runId: string;
|
|
2083
2081
|
taskStart: number;
|
|
@@ -2094,11 +2092,11 @@ export interface RunState {
|
|
|
2094
2092
|
limits: {
|
|
2095
2093
|
turnsExceeded: boolean;
|
|
2096
2094
|
budgetHit: "exceeded" | "precall" | undefined;
|
|
2097
|
-
/**
|
|
2095
|
+
/** WHICH budget axis tripped, set at the same instant as {@link budgetHit} so the
|
|
2098
2096
|
* terminal can name it (`limits.max_tokens_exceeded` vs `limits.max_cost_exceeded`). Tokens
|
|
2099
2097
|
* outrank cost when both are over at the same boundary (the documented attribution order). */
|
|
2100
2098
|
budgetAxis: BudgetAxis | undefined;
|
|
2101
|
-
/**
|
|
2099
|
+
/** The TYPED terminal an EXTERNAL cause (a dying execution environment, an
|
|
2102
2100
|
* exhausted governance window) recorded when it could not suspend the run durably. Set together with
|
|
2103
2101
|
* the abort it triggers, and adopted as the run's `threw` once the loop settles, so the caller gets
|
|
2104
2102
|
* `env.lifetime_expired` / `usage.window_exhausted` instead of the anonymous error an abort produces.
|
|
@@ -2114,7 +2112,7 @@ export interface RunState {
|
|
|
2114
2112
|
budget: {
|
|
2115
2113
|
remainingMicroUsd: number | undefined;
|
|
2116
2114
|
maxCostMicroUsd: number | undefined;
|
|
2117
|
-
/**
|
|
2115
|
+
/** Tokens still available on the cross-slice allocation (`resourceSuspend.totalTokens`
|
|
2118
2116
|
* minus everything earlier slices spent), or `undefined` when no total is set. */
|
|
2119
2117
|
remainingTokens: number | undefined;
|
|
2120
2118
|
/** This slice's EFFECTIVE token ceiling = `min(limits.maxTokens, remainingTokens)`. The exact mirror
|
|
@@ -2142,11 +2140,11 @@ export interface RunState {
|
|
|
2142
2140
|
turnUsageMissing: boolean;
|
|
2143
2141
|
turnStopReason: string | undefined;
|
|
2144
2142
|
lastTurnHadToolCalls: boolean;
|
|
2145
|
-
/** B15 三期使能:
|
|
2143
|
+
/** B15 三期使能:postToolBatch 的本回合聚集批(每回合边界消费并重置 — 回合语义,故归 turn)。 */
|
|
2146
2144
|
toolBatch: PostToolBatchCall[];
|
|
2147
2145
|
};
|
|
2148
2146
|
counters: {
|
|
2149
|
-
/**
|
|
2147
|
+
/** How many LIMIT-APPROACH frames have been injected this run (0..2). Also the
|
|
2150
2148
|
* one-shot latch itself: each frame fires when the count is still below its index. */
|
|
2151
2149
|
approachNoticesSent: number;
|
|
2152
2150
|
/** B15 三期使能:R9 引用的 R3/压缩区 latch(walltime 收尾 latch — preemptIgnoredReported 同族)。 */
|
|
@@ -2184,7 +2182,7 @@ export interface RunState {
|
|
|
2184
2182
|
instrState: {
|
|
2185
2183
|
lastAnnouncedHash: Map<string, string | null>;
|
|
2186
2184
|
} | undefined;
|
|
2187
|
-
/**
|
|
2185
|
+
/** The Workflow tool card's advisory size guideline as last ANNOUNCED to the model,
|
|
2188
2186
|
* plus the live boundary-time read (Prepared.workflowSizeGuideline). Same deliberate posture as
|
|
2189
2187
|
* `dateState`/`instrState`: NOT an AttachmentState member, one field, zero reducers. */
|
|
2190
2188
|
sizeGuidelineState: {
|
|
@@ -2195,7 +2193,7 @@ export interface RunState {
|
|
|
2195
2193
|
attachmentsInjected: number;
|
|
2196
2194
|
};
|
|
2197
2195
|
}
|
|
2198
|
-
/**
|
|
2196
|
+
/** One accepted live steer's REPLAY identity, the twin of the parked
|
|
2199
2197
|
* queue's `samePendingSteerPayload`. `payload` is the exact string handed to the harness, so the text,
|
|
2200
2198
|
* the speaker envelope and the trust framing all fold into it; `trusted` is kept SEPARATELY from those
|
|
2201
2199
|
* framed bytes so a text that spells its own `<system-reminder>` wrapper can never read as the trusted
|
|
@@ -2203,7 +2201,7 @@ export interface RunState {
|
|
|
2203
2201
|
export interface AcceptedSteerInput {
|
|
2204
2202
|
payload: string;
|
|
2205
2203
|
trusted: boolean;
|
|
2206
|
-
/**
|
|
2204
|
+
/** The NORMALIZED priority the call delivered under (absent input ⇒ "next"),
|
|
2207
2205
|
* the replay identity's sixth axis: same id + same text at a DIFFERENT tier is not a replay —
|
|
2208
2206
|
* a `next` input re-sent as `now` answering "idempotent success" without the interrupt would be
|
|
2209
2207
|
* a disposition lie, so it refuses `duplicate_input_id` like any other identity mismatch. */
|
|
@@ -2211,18 +2209,18 @@ export interface AcceptedSteerInput {
|
|
|
2211
2209
|
actor?: ActorAssertion;
|
|
2212
2210
|
}
|
|
2213
2211
|
/**
|
|
2214
|
-
* Config re-supplied to {@link Runner.resume}
|
|
2212
|
+
* Config re-supplied to {@link Runner.resume}. A suspended task's tools / model / policy /
|
|
2215
2213
|
* hooks cannot be reconstructed from a checkpoint token (the session stores neither tool implementations
|
|
2216
2214
|
* nor the hand band), so the caller's trusted control plane re-supplies the same {@link TaskSpec} it ran
|
|
2217
2215
|
* with — minus the conversation bits: `sessionId` comes from the checkpoint and `objective` is replaced by
|
|
2218
2216
|
* an internally-generated continuation, so both are omitted.
|
|
2219
2217
|
*/
|
|
2220
2218
|
export type ResumeTaskConfig = Omit<TaskSpec, "objective" | "sessionId">;
|
|
2221
|
-
/**
|
|
2219
|
+
/** Resume plan threaded from {@link Runner.resume} into the shared run loop. */
|
|
2222
2220
|
export interface ResumeRun {
|
|
2223
2221
|
cp: Checkpoint;
|
|
2224
2222
|
/**
|
|
2225
|
-
*
|
|
2223
|
+
* Did the APPROVED ACTION actually begin executing?
|
|
2226
2224
|
*
|
|
2227
2225
|
* The reopen compensation used to key on an error-code whitelist (`resume.env_failed` /
|
|
2228
2226
|
* `resume.session_not_found` / `resume.tool_unavailable`). That is a proxy for the thing that actually
|
|
@@ -2230,7 +2228,7 @@ export interface ResumeRun {
|
|
|
2230
2228
|
* know about it: a caller's abort landing anywhere between the CAS and `tool.execute` — across
|
|
2231
2229
|
* `SessionStore.acquire` (pluggable, cross-network on a durable backend), the MCP reconnect, the env
|
|
2232
2230
|
* rebuild, `resumeVM`, tool materialization — produced a `failed` result with NO errorCode, no reopen,
|
|
2233
|
-
|
|
2231
|
+
* and a human approval consumed for work that never happened. Two rounds of fixes each
|
|
2234
2232
|
* moved that window rather than closing it, because both extended the whitelist.
|
|
2235
2233
|
*
|
|
2236
2234
|
* This binds the compensation to the FACT instead: set the instant before `tool.execute` for the gated
|
|
@@ -2239,33 +2237,33 @@ export interface ResumeRun {
|
|
|
2239
2237
|
*/
|
|
2240
2238
|
pendingActionStarted?: boolean;
|
|
2241
2239
|
/** Validated against `cp.gate.kind` at the resume entry: human/irreversible_ask→`policy_ask`,
|
|
2242
|
-
|
|
2243
|
-
* plan_review→`plan_review
|
|
2244
|
-
* correlation.
|
|
2240
|
+
* resource_limit→`resource_limit`, needs_review→`dry_run_review`,
|
|
2241
|
+
* plan_review→`plan_review`. The gate-match guard in `resumeStream` enforces the
|
|
2242
|
+
* correlation. `wake` is the NON-GATE arm — only a checkpoint awaiting NO gate
|
|
2245
2243
|
* decision passes the resume entry with it (gate purity, `wake.gate_pending`); the run loop skips
|
|
2246
2244
|
* `applyResumeDecision` for it (no pending action to resolve) and re-enters via the continuation +
|
|
2247
2245
|
* pendingSteer tail alone. */
|
|
2248
2246
|
outcome: Extract<ResumeOutcome, {
|
|
2249
2247
|
gate: "policy_ask" | "resource_limit" | "dry_run_review" | "plan_review" | "wake";
|
|
2250
2248
|
}>;
|
|
2251
|
-
/**
|
|
2249
|
+
/** The wake's own operator message, validated (`validatePendingSteer`) at the
|
|
2252
2250
|
* resume entry and carried SEPARATELY from the checkpoint's parked `pendingSteer`: a message-bearing
|
|
2253
2251
|
* wake of a checkpoint that ALSO holds a parked steer must deliver BOTH (park order: parked first,
|
|
2254
2252
|
* wake message second), each under its own trusted framing — the old merge-into-the-slot shape
|
|
2255
2253
|
* silently DISPLACED the parked (undelivered) supervisor steer. Wake outcomes only. */
|
|
2256
2254
|
wakeMessage?: Omit<PendingSteerEntry, "seq">;
|
|
2257
|
-
/**
|
|
2255
|
+
/** The userPromptSubmit screen's `additionalContext` for {@link wakeMessage},
|
|
2258
2256
|
* captured at the resume ENTRY (the message is screened once, pre-CAS, on the resuming process's
|
|
2259
2257
|
* hook) and delivered by the drain as the engine's own reminder AHEAD of the wake frame — carrying
|
|
2260
2258
|
* it forward is what keeps the hook single-run (re-screening at the drain would be the double-run
|
|
2261
2259
|
* §4.3-3 reserves for the cross-process parked leg). Present only when a wake message passed a
|
|
2262
2260
|
* screen that supplied context. */
|
|
2263
2261
|
wakeMessageHookContext?: string;
|
|
2264
|
-
/** Compensation hook
|
|
2262
|
+
/** Compensation hook: called iff the resumed run fails with `resume.env_failed` (post-CAS
|
|
2265
2263
|
* workspace `resumeVM` failed) OR `resume.tool_unavailable` (P-7: the approved tool vanished) — in both
|
|
2266
2264
|
* the CAS already consumed the checkpoint but the pending action never ran. `resumeStream` supplies a
|
|
2267
2265
|
* closure that reopens the checkpoint (`resolved → pending`) so a retry re-resumes the SAME suspended work
|
|
2268
|
-
* instead of losing it to a forced "re-initiate"
|
|
2266
|
+
* instead of losing it to a forced "re-initiate" (reopen-by-reason): the `reason` is
|
|
2269
2267
|
* recorded on the reopened row so the next re-resume validates per reason — an `env_failed` reopen must
|
|
2270
2268
|
* replay the persisted winner (a system retry of the approved action), while a `tool_unavailable` reopen
|
|
2271
2269
|
* lets a human re-decide with the tool present (a fresh decision is allowed — preserves P-7). */
|
|
@@ -2279,16 +2277,16 @@ export interface ResumeRun {
|
|
|
2279
2277
|
* allowed). The word it answers is read through `EXECUTION_RECORD_LEAVES_ROW_UNRECORDED`; a
|
|
2280
2278
|
* conflict throw propagates (an engine defect, not a store condition). */
|
|
2281
2279
|
recordExecutionOutcome: (gate: import("../gate-outcome.js").GateOutcome) => Promise<ExecutionOutcomeRecordWord>;
|
|
2282
|
-
/**
|
|
2280
|
+
/** Set in the run body right after `applyResumeDecision` completes: the negative-
|
|
2283
2281
|
* decision twin of `pendingActionStarted`. A reject/deny consumes its gate BY BEING DELIVERED, and
|
|
2284
2282
|
* this bit is the delivery fact — every throw-arm cause (prepare failure, `session_not_found`, a
|
|
2285
2283
|
* pre-delivery abort) and the walltime-exhausted settle fire BEFORE it is set, so an undelivered
|
|
2286
2284
|
* negative decision still reopens as `env_failed` (the retry replays the persisted decision; it
|
|
2287
|
-
* never re-asks
|
|
2285
|
+
* never re-asks), closing the loss class the first cut reopened. */
|
|
2288
2286
|
decisionDelivered?: boolean;
|
|
2289
2287
|
}
|
|
2290
2288
|
/**
|
|
2291
|
-
* What {@link TaskStream.destroy} needs to reap a SUSPENDED task
|
|
2289
|
+
* What {@link TaskStream.destroy} needs to reap a SUSPENDED task. Captured (stashed) onto
|
|
2292
2290
|
* the stream handle the moment a run assembles `status:"suspended"` — `finish()` deliberately left the
|
|
2293
2291
|
* paused env + committed checkpoint alive for resume, so without this stash they'd be unreachable (the
|
|
2294
2292
|
* `Prepared`, and its `ownedEnv`, are GC'd once the run promise settles). `env` is `undefined` for a
|
|
@@ -2305,7 +2303,7 @@ export interface SuspendReap {
|
|
|
2305
2303
|
}
|
|
2306
2304
|
/** B15 三期终件 — R9(回合边界全域:压缩/attachments 注入/提醒节律/预算判决)工厂。
|
|
2307
2305
|
* 正文自 runLocked 逐字搬迁(this 面经 runnerHooks 闭包打包,B13 #coreView 同款);模块级符号
|
|
2308
|
-
* 同文件直见不经 deps;可变运行态全在 rs(B15
|
|
2306
|
+
* 同文件直见不经 deps;可变运行态全在 rs(B15 二期),deps 全部为 const 稳定引用。 */
|
|
2309
2307
|
export interface TurnBoundaryDeps {
|
|
2310
2308
|
spec: TaskSpec;
|
|
2311
2309
|
queue: PushQueue<TaskEvent>;
|
|
@@ -2353,10 +2351,10 @@ export interface TurnBoundaryDeps {
|
|
|
2353
2351
|
};
|
|
2354
2352
|
/** The Runner's deployment deps, read LIVE ({@link RunnerDepsSeat}): the compaction seams (compaction-seams.ts) the
|
|
2355
2353
|
* boundary's compaction pass reaches down for read the summary provider, the hooks slot and the error sink through it
|
|
2356
|
-
|
|
2354
|
+
* on every pass — the three Runner methods that used to sit on `runnerHooks` as delegates. */
|
|
2357
2355
|
runner: RunnerDepsSeat;
|
|
2358
2356
|
}
|
|
2359
|
-
/**
|
|
2357
|
+
/** R5(harness 事件处理器族)的依赖包。全部为 runLocked 内声明顺序早于
|
|
2360
2358
|
* 工厂调用点的 const 稳定引用 + 三个 runLocked 形参;this 面(deps.onError)经 runnerHooks 打包
|
|
2361
2359
|
* (B13 #coreView / R9 TurnBoundaryDeps 同款)。*/
|
|
2362
2360
|
export interface HarnessHandlersDeps {
|
|
@@ -2440,7 +2438,7 @@ export interface RunnerSelfSeat {
|
|
|
2440
2438
|
resumeStream(token: CheckpointToken, outcome: ResumeOutcome, taskConfig: ResumeTaskConfig, internals?: RunInternals): Promise<TaskStream>;
|
|
2441
2439
|
}
|
|
2442
2440
|
/**
|
|
2443
|
-
*
|
|
2441
|
+
* The orchestrator's entry (`prepareTask`, prepare-task.ts) as ONE contract: the notification lane's
|
|
2444
2442
|
* `prepareTask` seat names it, and the orchestrator pins its own declaration against it (`PrepareTaskIsTheContract`), so a
|
|
2445
2443
|
* signature change reds at the declaration — not at the driver's hand-in, and not as a seat spelled a second time. It lives
|
|
2446
2444
|
* on the floor because a lane may not name the orchestrator (docs/LAYERING.json: layer 4 sits above the lanes). Positional,
|
|
@@ -2450,10 +2448,10 @@ export type PrepareTaskFn = (spec: TaskSpec, deps: RunnerDeps, sessions: Session
|
|
|
2450
2448
|
runId?: string;
|
|
2451
2449
|
}) => Promise<Prepared>;
|
|
2452
2450
|
/**
|
|
2453
|
-
*
|
|
2451
|
+
* The Result of an INSTALLING phase: a lane whose every product is installed on a seat it borrowed
|
|
2454
2452
|
* (the harness's stop gate and recovery chain, the run state's counter groups, the stream's result setter, the claimed
|
|
2455
2453
|
* row's registries) hands nothing back, and says so by extending this marker. The marker is machine-read by gate:phase-api
|
|
2456
|
-
*
|
|
2454
|
+
* a Result with no members MUST extend it, a Result with members MAY NOT, and no Result
|
|
2457
2455
|
* inherits anything else — so an empty Result is a stated fact about the phase, never an interface someone forgot to
|
|
2458
2456
|
* fill, and a phase that starts handing a product back must drop the declaration in the same edit. Six lanes carry it:
|
|
2459
2457
|
* the attachment seats, the stop gate, the recovery lanes, the settle and teardown (run-), the preflight and the claim
|
|
@@ -2461,7 +2459,7 @@ export type PrepareTaskFn = (spec: TaskSpec, deps: RunnerDeps, sessions: Session
|
|
|
2461
2459
|
*/
|
|
2462
2460
|
export interface InstallingPhaseResult {
|
|
2463
2461
|
}
|
|
2464
|
-
/** The live-task handle `runLocked` publishes once the harness exists
|
|
2462
|
+
/** The live-task handle `runLocked` publishes once the harness exists: the harness + abort
|
|
2465
2463
|
* controller, the loop-liveness latch (`ended` flips when the single `harness.prompt` settles; `userInterrupted`
|
|
2466
2464
|
* / `userHalted` are the interrupt and halt verbs' attribution seats), the run's reminder mark, its session and
|
|
2467
2465
|
* engine-minted run id, and the hook bound + identity envelope the steer entrance screen runs under. */
|
|
@@ -2475,12 +2473,12 @@ export interface LiveHandle {
|
|
|
2475
2473
|
};
|
|
2476
2474
|
reminderMark: string;
|
|
2477
2475
|
sessionId: string;
|
|
2478
|
-
/**
|
|
2476
|
+
/** The run body's engine-minted run id, so the stream-layer verbs can name the run their disclosures are about. */
|
|
2479
2477
|
runId: string;
|
|
2480
2478
|
hookTimeoutMs: number;
|
|
2481
2479
|
hookIdentity: HookInvocationIdentity;
|
|
2482
2480
|
}
|
|
2483
|
-
/** The run body's backstop CARRIER
|
|
2481
|
+
/** The run body's backstop CARRIER: the effective ids and the post-prepare
|
|
2484
2482
|
* observations the run body publishes as they are minted, so the stream layer's failure backstop names the
|
|
2485
2483
|
* same run, session and observations the frames the run body already emitted did. */
|
|
2486
2484
|
export interface TaskIdRef {
|
|
@@ -2492,7 +2490,7 @@ export interface TaskIdRef {
|
|
|
2492
2490
|
delegationTerminalOwed?: HookInvocationIdentity;
|
|
2493
2491
|
editedFiles?: () => TaskResult["editedFiles"];
|
|
2494
2492
|
}
|
|
2495
|
-
/**
|
|
2493
|
+
/** The manual `/compact` request seat: the `requested` flag, the parked waiters (each with its
|
|
2496
2494
|
* caller's cancel signal and per-call instructions), the run body's mooted-frame channel and the registration
|
|
2497
2495
|
* gate the run-end backstop closes before its final drain. */
|
|
2498
2496
|
export interface ManualCompactRef {
|
|
@@ -2506,7 +2504,7 @@ export interface ManualCompactRef {
|
|
|
2506
2504
|
closed?: boolean;
|
|
2507
2505
|
}
|
|
2508
2506
|
/**
|
|
2509
|
-
*
|
|
2507
|
+
* The end-of-task compaction pass's outcome (`Runner.finish`'s return): what the terminal-adoption lane
|
|
2510
2508
|
* hands the settle lane, which reads it for the `compacted` frame, the phase-timings frame and the detector reset. Named
|
|
2511
2509
|
* once here so the two lanes and the method spell one type.
|
|
2512
2510
|
*/
|
|
@@ -2529,7 +2527,7 @@ export type EndOfTaskCompaction = {
|
|
|
2529
2527
|
clampReason?: "budget" | "tolerance";
|
|
2530
2528
|
} | undefined;
|
|
2531
2529
|
/**
|
|
2532
|
-
*
|
|
2530
|
+
* The notification lane's BINDINGS: the run-notification-lane's own four `let`s as ONE seat (getters
|
|
2533
2531
|
* and setters over the lane's variables, never a copy). The identity-wiring lane binds `harness` / `sessionId` /
|
|
2534
2532
|
* `ident` the moment `prepared` exists (the lane's closures read them by variable — the routing listener, the park
|
|
2535
2533
|
* destination, the injection entry); the leg lane flips `live` in its finally, from which point every notification
|
|
@@ -2545,13 +2543,13 @@ export interface NotificationLaneBindings {
|
|
|
2545
2543
|
};
|
|
2546
2544
|
live: boolean;
|
|
2547
2545
|
}
|
|
2548
|
-
/**
|
|
2546
|
+
/** The `notify()` bridge: `runLocked` binds `inject` the moment the task-notification lane exists. */
|
|
2549
2547
|
export interface NotifyRef {
|
|
2550
2548
|
inject?: (n: TaskNotificationPayload, opts?: {
|
|
2551
2549
|
priority?: SystemInjectionPriority;
|
|
2552
2550
|
}) => void;
|
|
2553
2551
|
}
|
|
2554
|
-
/**
|
|
2552
|
+
/** The capture opt-out flip verb's binding; bound only when the run mounted a memory session. */
|
|
2555
2553
|
export interface CaptureOptOutRef {
|
|
2556
2554
|
flip?: (reason?: string) => Promise<{
|
|
2557
2555
|
outcome: "created" | "existed";
|
|
@@ -2568,6 +2566,6 @@ export interface TaskStreamLiveSeat {
|
|
|
2568
2566
|
resultValue: TaskResult | undefined;
|
|
2569
2567
|
/** The live-task handle once `runLocked` published it; `undefined` before, and forever when prepare threw. */
|
|
2570
2568
|
readonly handle: LiveHandle | undefined;
|
|
2571
|
-
/**
|
|
2569
|
+
/** What `destroy()` reaps when the run SUSPENDED; unset for every other terminal state. */
|
|
2572
2570
|
readonly reapHandle: SuspendReap | undefined;
|
|
2573
2571
|
}
|