@sema-agent/core 5.60.1 → 5.61.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.
Files changed (32) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/dist/agents/subagent.d.ts +4 -2
  3. package/dist/agents/subagent.js +9 -9
  4. package/dist/core/governance-codes.d.ts +1 -1
  5. package/dist/core/governance-codes.js +2 -2
  6. package/dist/core/memory-engine/consolidation-driver.d.ts +19 -1
  7. package/dist/core/memory-engine/consolidation-driver.js +75 -3
  8. package/dist/core/memory-engine/consolidation.d.ts +52 -5
  9. package/dist/core/memory-engine/consolidation.js +3 -1
  10. package/dist/core/memory-engine/distiller.d.ts +89 -1
  11. package/dist/core/memory-engine/distiller.js +94 -5
  12. package/dist/core/memory-engine/engine.d.ts +8 -0
  13. package/dist/core/memory-engine/engine.js +51 -8
  14. package/dist/core/memory-engine/index.d.ts +1 -1
  15. package/dist/core/memory-engine/index.js +1 -1
  16. package/dist/core/runner/prepare-task.d.ts +6 -3
  17. package/dist/core/runner/runtask.js +57 -26
  18. package/dist/core/task-notification.d.ts +50 -23
  19. package/dist/core/task-notification.js +20 -4
  20. package/dist/core/types.d.ts +76 -19
  21. package/dist/engine/harness/agent-harness.d.ts +58 -2
  22. package/dist/engine/harness/agent-harness.js +115 -5
  23. package/dist/engine/loop/agent-loop.js +153 -15
  24. package/dist/engine/loop/types.d.ts +32 -0
  25. package/dist/index.d.ts +2 -2
  26. package/dist/index.js +2 -2
  27. package/dist/orchestration/run-workflow-tool.d.ts +7 -2
  28. package/dist/orchestration/run-workflow-tool.js +1 -1
  29. package/dist/tools/monitor.d.ts +3 -3
  30. package/dist/tools/monitor.js +1 -1
  31. package/package.json +1 -1
  32. package/test/export-surface.snapshot.json +7 -1
@@ -1,5 +1,6 @@
1
1
  import { findToolByName, validateToolArguments } from "../llm/index.js";
2
2
  import { truncateError } from "../../core/tool-errors.js";
3
+ import { INTERRUPTED_BY_USER_FOR_TOOL_USE_MARKER, INTERRUPTED_BY_USER_MARKER, } from "../../core/session-reconcile.js";
3
4
  import { resolveAgentCoreStreamFn } from "./runtime-deps.js";
4
5
  function appendTextDeltaToAssistantMessage(message, contentIndex, delta) {
5
6
  const content = [...message.content];
@@ -158,6 +159,13 @@ async function runLoop(initialContext, newMessages, initialConfig, signal, emit,
158
159
  if (!state.hasMoreToolCalls && state.pendingMessages.length === 0) {
159
160
  const followUpMessages = (await state.config.getFollowUpMessages?.()) || [];
160
161
  if (followUpMessages.length === 0) {
162
+ if ((state.config.pendingInjectionCount?.() ?? 0) > 0) {
163
+ state.pendingMessages = (await state.config.getSteeringMessages?.()) || [];
164
+ if (state.pendingMessages.length > 0) {
165
+ trace?.({ kind: "continue", reason: "steer_injected" });
166
+ }
167
+ continue;
168
+ }
161
169
  trace?.({ kind: "terminal", reason: "completed" });
162
170
  break;
163
171
  }
@@ -193,6 +201,38 @@ async function runSingleTurn(state, signal, emit, streamFn, runtime, trace) {
193
201
  else {
194
202
  state.firstTurn = false;
195
203
  }
204
+ const turnController = new AbortController();
205
+ const onRunAbort = () => turnController.abort();
206
+ if (signal !== undefined) {
207
+ if (signal.aborted)
208
+ turnController.abort();
209
+ else
210
+ signal.addEventListener("abort", onRunAbort, { once: true });
211
+ }
212
+ let seatLive = false;
213
+ const publishSeat = () => {
214
+ seatLive = true;
215
+ state.config.publishTurnInterruptSeat?.(turnController);
216
+ };
217
+ const retractSeat = () => {
218
+ if (!seatLive)
219
+ return;
220
+ seatLive = false;
221
+ state.config.publishTurnInterruptSeat?.(undefined);
222
+ };
223
+ try {
224
+ return await runTurnPhases(state, signal, turnController, publishSeat, retractSeat, emit, streamFn, runtime, trace);
225
+ }
226
+ finally {
227
+ retractSeat();
228
+ signal?.removeEventListener("abort", onRunAbort);
229
+ }
230
+ }
231
+ async function runTurnPhases(state, signal, turnController, publishSeat, retractSeat, emit, streamFn, runtime, trace) {
232
+ publishSeat();
233
+ if (state.config.recheckImmediateInjections) {
234
+ state.pendingMessages = await state.config.recheckImmediateInjections(state.pendingMessages);
235
+ }
196
236
  if (state.pendingMessages.length > 0) {
197
237
  for (const message of state.pendingMessages) {
198
238
  await emit({ type: "message_start", message });
@@ -201,7 +241,7 @@ async function runSingleTurn(state, signal, emit, streamFn, runtime, trace) {
201
241
  state.newMessages.push(message);
202
242
  }
203
243
  }
204
- let executor = new StreamToolExecutor(state.context, state.config, signal, emit);
244
+ let executor = new StreamToolExecutor(state.context, state.config, turnController.signal, emit);
205
245
  const staticReasoningCutDowngrade = state.config.recovery?.truncatedOutput !== undefined &&
206
246
  state.staticReasoningCutRecoveries < MAX_STATIC_REASONING_CUT_RECOVERIES;
207
247
  const ptl = state.config.recovery?.promptTooLong;
@@ -210,7 +250,7 @@ async function runSingleTurn(state, signal, emit, streamFn, runtime, trace) {
210
250
  let withhold = withholdEnabled ? createPtlWithholdBuffer(emit, ptlDetect) : undefined;
211
251
  let message;
212
252
  try {
213
- message = await streamAssistantResponse(state.context, state.config, signal, withhold?.sink ?? emit, streamFn, runtime, executor, staticReasoningCutDowngrade);
253
+ message = await streamAssistantResponse(state.context, state.config, turnController.signal, withhold?.sink ?? emit, streamFn, runtime, executor, staticReasoningCutDowngrade);
214
254
  }
215
255
  finally {
216
256
  await executor.settle();
@@ -246,9 +286,9 @@ async function runSingleTurn(state, signal, emit, streamFn, runtime, trace) {
246
286
  withhold = withholdEnabled ? createPtlWithholdBuffer(emit, ptlDetect) : undefined;
247
287
  state.context.messages = replaced;
248
288
  trace?.({ kind: "continue", reason: "reactive_compact_retry" });
249
- executor = new StreamToolExecutor(state.context, state.config, signal, emit);
289
+ executor = new StreamToolExecutor(state.context, state.config, turnController.signal, emit);
250
290
  try {
251
- message = await streamAssistantResponse(state.context, state.config, signal, withhold?.sink ?? emit, streamFn, runtime, executor, staticReasoningCutDowngrade);
291
+ message = await streamAssistantResponse(state.context, state.config, turnController.signal, withhold?.sink ?? emit, streamFn, runtime, executor, staticReasoningCutDowngrade);
252
292
  }
253
293
  finally {
254
294
  await executor.settle();
@@ -261,6 +301,10 @@ async function runSingleTurn(state, signal, emit, streamFn, runtime, trace) {
261
301
  state.newMessages.push(message);
262
302
  if (message.staticReasoningCut === true)
263
303
  state.staticReasoningCutRecoveries++;
304
+ if (message.stopReason === "aborted" && turnController.signal.aborted && !signal?.aborted) {
305
+ retractSeat();
306
+ return await settleInterruptedTurn(state, message, executor, [], signal, emit);
307
+ }
264
308
  {
265
309
  const degen = state.config.recovery?.degenerateOutput;
266
310
  if (degen &&
@@ -270,6 +314,7 @@ async function runSingleTurn(state, signal, emit, streamFn, runtime, trace) {
270
314
  executor.admittedCount === 0 &&
271
315
  message.content.every((b) => b.type !== "toolCall") &&
272
316
  state.degenerateContinues < (degen.maxContinues ?? 2)) {
317
+ retractSeat();
273
318
  state.degenerateContinues++;
274
319
  await emit({ type: "turn_end", message, toolResults: [] });
275
320
  const drained = (await state.config.getSteeringMessages?.()) || [];
@@ -280,7 +325,8 @@ async function runSingleTurn(state, signal, emit, streamFn, runtime, trace) {
280
325
  state.degenerateContinues = 0;
281
326
  }
282
327
  if (message.stopReason === "error" || message.stopReason === "aborted") {
283
- const errorFinalResults = await harvestExecutorOnErrorFinal(executor, state, message, signal, emit);
328
+ retractSeat();
329
+ const errorFinalResults = await harvestExecutorOnErrorFinal(executor, state, message, turnController.signal, emit);
284
330
  await emit({ type: "turn_end", message, toolResults: errorFinalResults });
285
331
  await emit({ type: "agent_end", messages: state.newMessages });
286
332
  return { kind: "terminal", reason: "assistant_error" };
@@ -289,7 +335,7 @@ async function runSingleTurn(state, signal, emit, streamFn, runtime, trace) {
289
335
  const toolResults = [];
290
336
  state.hasMoreToolCalls = false;
291
337
  if (toolCalls.length > 0) {
292
- const executedToolBatch = await executeToolCalls(state.context, message, state.config, signal, emit, executor);
338
+ const executedToolBatch = await executeToolCalls(state.context, message, state.config, turnController.signal, emit, executor);
293
339
  toolResults.push(...executedToolBatch.messages);
294
340
  state.hasMoreToolCalls = !executedToolBatch.terminate;
295
341
  for (const result of toolResults) {
@@ -303,6 +349,10 @@ async function runSingleTurn(state, signal, emit, streamFn, runtime, trace) {
303
349
  await closeOrphanedStreamEntry(orphan, emit);
304
350
  }
305
351
  }
352
+ retractSeat();
353
+ if (toolCalls.length > 0 && turnController.signal.aborted && !signal?.aborted) {
354
+ return await settleInterruptedTurn(state, message, executor, toolResults, signal, emit);
355
+ }
306
356
  await emit({ type: "turn_end", message, toolResults });
307
357
  const nextTurnContext = {
308
358
  message,
@@ -311,15 +361,7 @@ async function runSingleTurn(state, signal, emit, streamFn, runtime, trace) {
311
361
  newMessages: state.newMessages,
312
362
  };
313
363
  const nextTurnSnapshot = await state.config.prepareNextTurn?.(nextTurnContext);
314
- if (nextTurnSnapshot) {
315
- state.context = nextTurnSnapshot.context ?? state.context;
316
- state.config = Object.assign({}, state.config, {
317
- model: nextTurnSnapshot.model ?? state.config.model,
318
- reasoning: nextTurnSnapshot.thinkingLevel === undefined
319
- ? state.config.reasoning
320
- : nextTurnSnapshot.thinkingLevel,
321
- });
322
- }
364
+ adoptNextTurnSnapshot(state, nextTurnSnapshot);
323
365
  if (await state.config.shouldStopAfterTurn?.({
324
366
  message,
325
367
  toolResults,
@@ -383,6 +425,102 @@ async function runSingleTurn(state, signal, emit, streamFn, runtime, trace) {
383
425
  }
384
426
  return { kind: "ran" };
385
427
  }
428
+ function adoptNextTurnSnapshot(state, nextTurnSnapshot) {
429
+ if (!nextTurnSnapshot)
430
+ return;
431
+ state.context = nextTurnSnapshot.context ?? state.context;
432
+ state.config = Object.assign({}, state.config, {
433
+ model: nextTurnSnapshot.model ?? state.config.model,
434
+ reasoning: nextTurnSnapshot.thinkingLevel === undefined
435
+ ? state.config.reasoning
436
+ : nextTurnSnapshot.thinkingLevel,
437
+ });
438
+ }
439
+ const TURN_INTERRUPTED_TOOL_TEXT = "[INTERRUPTED] The user interrupted this turn before this tool call started. It was never executed and " +
440
+ "had no side effects. Address the user's interjection first; re-issue the call afterwards if it is still needed.";
441
+ async function settleInterruptedTurn(state, message, executor, committedResults, signal, emit) {
442
+ const toolResults = [...committedResults];
443
+ toolResults.push(...(await harvestExecutorOnErrorFinal(executor, state, message, signal, emit)));
444
+ const turnCalls = message.content.filter((c) => c.type === "toolCall");
445
+ const answered = new Set(toolResults.map((r) => r.toolCallId));
446
+ for (const call of turnCalls) {
447
+ if (answered.has(call.id))
448
+ continue;
449
+ await emit({
450
+ type: "tool_execution_start",
451
+ toolCallId: call.id,
452
+ toolName: call.name,
453
+ args: call.arguments,
454
+ });
455
+ const finalized = {
456
+ toolCall: call,
457
+ result: {
458
+ content: [{ type: "text", text: TURN_INTERRUPTED_TOOL_TEXT }],
459
+ details: { errorKind: "interrupted_never_started" },
460
+ },
461
+ isError: true,
462
+ };
463
+ await emit({
464
+ type: "tool_execution_end",
465
+ toolCallId: call.id,
466
+ toolName: call.name,
467
+ result: finalized.result,
468
+ isError: true,
469
+ notExecuted: true,
470
+ });
471
+ const toolResultMessage = createToolResultMessage(finalized);
472
+ await emitToolResultMessage(toolResultMessage, emit);
473
+ state.context.messages.push(toolResultMessage);
474
+ state.newMessages.push(toolResultMessage);
475
+ toolResults.push(toolResultMessage);
476
+ }
477
+ if (turnCalls.length === 0 &&
478
+ isBlankFailureContent(message) &&
479
+ state.context.messages[state.context.messages.length - 1] === message) {
480
+ state.context.messages.pop();
481
+ if (state.newMessages[state.newMessages.length - 1] === message)
482
+ state.newMessages.pop();
483
+ }
484
+ const marker = {
485
+ role: "user",
486
+ content: [
487
+ {
488
+ type: "text",
489
+ text: turnCalls.length > 0 ? INTERRUPTED_BY_USER_FOR_TOOL_USE_MARKER : INTERRUPTED_BY_USER_MARKER,
490
+ },
491
+ ],
492
+ provenance: "engine-note",
493
+ timestamp: Date.now(),
494
+ };
495
+ await emit({ type: "message_start", message: marker });
496
+ await emit({ type: "message_end", message: marker });
497
+ state.context.messages.push(marker);
498
+ state.newMessages.push(marker);
499
+ state.hasMoreToolCalls = false;
500
+ await emit({ type: "turn_end", message, toolResults });
501
+ if (signal?.aborted) {
502
+ await emit({ type: "agent_end", messages: state.newMessages });
503
+ return { kind: "terminal", reason: "aborted_before_stream" };
504
+ }
505
+ const nextTurnSnapshot = await state.config.prepareNextTurn?.({
506
+ message,
507
+ toolResults,
508
+ context: state.context,
509
+ newMessages: state.newMessages,
510
+ });
511
+ adoptNextTurnSnapshot(state, nextTurnSnapshot);
512
+ if (await state.config.shouldStopAfterTurn?.({
513
+ message,
514
+ toolResults,
515
+ context: state.context,
516
+ newMessages: state.newMessages,
517
+ })) {
518
+ await emit({ type: "agent_end", messages: state.newMessages });
519
+ return { kind: "terminal", reason: "stop_requested" };
520
+ }
521
+ state.pendingMessages = (await state.config.getSteeringMessages?.()) || [];
522
+ return { kind: "ran" };
523
+ }
386
524
  async function streamAssistantResponse(context, config, signal, emit, streamFn, runtime, executor, staticReasoningCutDowngrade) {
387
525
  let messages = context.messages;
388
526
  if (config.transformContext) {
@@ -380,6 +380,38 @@ export interface AgentLoopConfig extends SimpleStreamOptions {
380
380
  * Contract: must not throw or reject. Return [] when no follow-up messages are available.
381
381
  */
382
382
  getFollowUpMessages?: () => Promise<AgentMessage[]>;
383
+ /**
384
+ * design/373 S1 — the TURN-scoped interrupt seat. The loop publishes each main turn's own
385
+ * AbortController here BEFORE its pre-request injection re-check (the linearization the
386
+ * immediate-class contract depends on: an interrupt request that missed the re-check must find the
387
+ * seat already live), and retracts it (`undefined`) the moment the turn's provider stream + tool
388
+ * batch have settled — an interrupt landing in the between-turns window is a no-op whose frame
389
+ * simply rides the next boundary drain, mirroring the upstream form (only an in-flight request is
390
+ * ever aborted). Aborting the published controller cancels THIS turn only: the loop reconciles
391
+ * (real results for work that finished, paired never-started results for calls that never began,
392
+ * the interruption marker) and the run CONTINUES at the next boundary. The run-level signal always
393
+ * wins: when both fire, the loop takes the run-terminal path.
394
+ */
395
+ publishTurnInterruptSeat?: (seat: AbortController | undefined) => void;
396
+ /**
397
+ * design/373 S1 — the pre-request re-check (the level half of the immediate-class contract):
398
+ * called once per turn, after the interrupt seat above is published and before the provider
399
+ * request, with the turn's pending injection batch. The host drains any queued immediate-class
400
+ * ("now") frames and returns the batch to inject — merged at their class position (after
401
+ * immediate frames already pending, ahead of everything else), so an immediate frame that arrived
402
+ * after the boundary drain still rides THIS request instead of waiting a whole turn.
403
+ */
404
+ recheckImmediateInjections?: (pending: AgentMessage[]) => Promise<AgentMessage[]>;
405
+ /**
406
+ * design/373 S1 — the FINAL COMMIT POINT's synchronous double-check: how many queued injection
407
+ * frames a boundary drain could deliver right now (steer + follow-up, excluding frames a live
408
+ * hold or an unwinding run would refuse to drain). Consulted SYNCHRONOUSLY after the follow-up
409
+ * drain (and stop gate) answered empty, with zero awaits between the check and the terminal
410
+ * commit — a frame that arrived during the stop gate's await window is therefore served by this
411
+ * run instead of being stranded behind an already-decided terminal. Absent ⇒ the pre-373 commit
412
+ * behavior (the follow-up drain's answer is final).
413
+ */
414
+ pendingInjectionCount?: () => number;
383
415
  /**
384
416
  * Tool execution mode.
385
417
  * - "sequential": execute tool calls one by one
package/dist/index.d.ts CHANGED
@@ -110,7 +110,7 @@ export { createSensitivePathPolicy, RECOMMENDED_SENSITIVE_PATTERNS } from "./cor
110
110
  export { createFsWriteGatePolicy, type FsWriteGatePolicyOptions } from "./core/fs-write-gate-policy.js";
111
111
  export { RETIRED_TOOL_NAMES } from "./core/tool-name-aliases.js";
112
112
  export { DEFAULT_SUBAGENT_TOOL_NAME } from "./agents/subagent.js";
113
- export { renderTaskNotificationXml, taskNotificationDedupKey, isDelegatedAgentTerminal, SystemInjectionQueue, type TaskNotificationPayload, type TaskNotificationStatus, type ExternalNotificationInput, type SystemInjection, type SystemInjectionPriority, } from "./core/task-notification.js";
113
+ export { renderTaskNotificationXml, taskNotificationDedupKey, isDelegatedAgentTerminal, isTerminalTaskNotification, SystemInjectionQueue, type TaskNotificationPayload, type TaskNotificationStatus, type ExternalNotificationInput, type SystemInjection, type SystemInjectionPriority, } from "./core/task-notification.js";
114
114
  export { describeStaticWiring, deriveWiringManifest, deriveAskEffective, resolveDeclaredDurability, resolveSubagentTranscriptTier, type SubagentTranscriptTier, resolveAskSeamForm, resolveQuestionSeam, countElicitOptIns, type WiringManifest, type WiringFacts, type WiringLegKind, type AskSeamForm, type AskEffective, type QuestionChannelState, type SeamProvenance, type ParkLaneReason, type ManifestDurability, type StaticWiringDeps, type StaticWiringSpec, } from "./core/wiring-manifest.js";
115
115
  export { probeParkRoundTrip, durableParkGapOf, durableParkGapFor, PARK_SELFCHECK_SCOPE_PREFIX, type ParkSelfCheckResult, type ParkProbeFinding, type ParkProbeFindingCode, } from "./core/park-selfcheck.js";
116
116
  export { type StoreDurability } from "./core/checkpoint-store.js";
@@ -168,7 +168,7 @@ export { AdoptionError, assertAdoptionBootGate, readRootAdoptionFile, writeRootA
168
168
  export { adoptLocalDataRoot, ackAdoptionConfig, witnessAdoptionConfig, listAdoptionQuarantine, readAdoptionStatus, type AdoptionStatus, type AdoptLocalDataRootOptions, type AdoptLocalDataRootResult, type AdoptionCarriageLeg, type AdoptionCarriageLegContext, type AdoptionConfigWitnessReceipt, } from "./stores/file/adoption/adopt.js";
169
169
  export { formatHookFeedback, runToolGate, createHookEnvCapabilities, createPreToolUseConstraintPolicy, type PersistedRuleHit, type PersistedRuleHitRule, type PersistedRuleUnreadable, type PersistedRuleCoverage, type PersistedRuleAnswer, normalizePersistedRuleHit, type Hooks, type HookToolContext, type HookInvocationIdentity, type UserPromptSubmitContext, type PostToolBatchContext, type HookEnvCapabilities, type HookToolOutput, type PreToolUseResult, type PostToolUseResult, type UserPromptSubmitResult, type HookToolFailure, type PostToolUseFailureResult, type PostToolBatchCall, type PostToolBatchResult, type PreCompactContext, type PreCompactResult, type PostCompactContext, type StopFailureContext, type PermissionDeniedPayload, type PermissionDeniedSource, } from "./core/hooks.js";
170
170
  export { InMemoryMemoryStore, composeMemoryBlock, composeLayeredMemoryBlock, normalizeMemorySpec, type NormalizedMemorySpec, type MemorySpecInput, supportsConsolidation, supportsPeriodicConsolidation, firstSentence, expandLexicalTerms, lexicalSearchMatch, type Embedder, classifyPromotable, enforcePromotableWriteGate, guardedMemoryStore, MemoryGateError, detectSecret, enforceSecretWriteGate, enforceStructuredNoteSecretGate, type UtilityGate, type MemoryStore, type MemoryVectorMode, type ScoredMemory, type MemoryNoteHeader, type MemoryNoteRecord, type MemoryNoteType, type StructuredNoteInput, } from "./core/memory.js";
171
- export { MemoryEngine, FileMemoryEngineBackend, memoryBackendContract, assertMemoryBackendSearchEquivalence, type MemoryBackendContractHooks, buildMemoryInstruction, truncateIndex, scanEntryFiles, deriveRepoKey, deriveRepoMemoryDir, deriveControlPlaneDir, deriveRepoControlPlaneDir, resolveMemoryEngineRoot, scopeDirName, ControlPlaneCorruptError, parseEntryFile, serializeEntryFile, computeEntryRev, entryFromFile, MEMORY_ORIGIN_CAUSES, committedOriginOf, originEquals, ambiguousOriginRepresentation, type OriginClearanceRow, type OriginClearanceEvent, committedDistilledOf, distilledEquals, type MemoryEntryDistilled, type MemoryEntryDistilledInput, CONSOLIDATION_DEFAULTS, ConsolidationRefusedError, MEMORY_SEARCH_SUPERSEDED_TAG, consolidationTypeEligible, deriveSupersededSet, memorySupersededNote, readIntentCredentials, supersessionFuseCeiling, memoryConsolidationRecommendedNotice, memoryConsolidationCommittedNotice, memoryConsolidationConflictNotice, memoryConsolidationIncompleteNotice, memoryConsolidationRefusedNotice, type ConsolidationGateRead, type ConsolidationGateRow, type ConsolidationIntent, type ConsolidationIntentCredentialRow, type ConsolidationLeaseSeat, type ConsolidationProductProposal, type ConsolidationProposal, type MemoryConsolidationOptions, type ConsolidationCommitReceipt, type ConsolidationReconcileReport, type ConsolidationResolveReceipt, type ConsolidationPlanSummary, type ConsolidationPlanFoldEvidence, DISTILLER_DEFAULT_MAX_INPUTS_PER_PRODUCT, LLM_DISTILLER_CONTRACT, LLM_DISTILLER_CONTRACT_DL2, LLM_DISTILLER_CONTRACT_DL3, LLM_DISTILLER_CONTRACTS, MEMORY_DISTILLER_CONTRACT_V1, contractGroupingDiff, driveConsolidationToFixpoint, isAliasModelId, llmPlanDistiller, mintLlmConsolidationPlan, openAiCompatChatSeat, parseJsonAnswer, planParseRepairs, sanitizeLlmGroups, scheduleUnderFuse, type ConsolidationDistillFn, type ConsolidationDriveCycleRow, type ConsolidationDriveEngine, type ConsolidationDriveResult, type ConsolidationFoldState, type DistillerCandidate, type DistillerChatAnswer, type DistillerChatFn, type DistillerChatRequest, type FuseSchedule, type LlmConsolidationPlan, type LlmConsolidationPlanProduct, type LlmDistillerContract, type MintLlmConsolidationPlanResult, type PlanParseRepairs, type SanitizedLlmGroups, CONSOLIDATION_DRIVER_PLANS_DIR, CONSOLIDATION_DRIVER_RUNS_FILE, CONSOLIDATION_RUN_STOP_REASONS, archiveDistillerPlan, readConsolidationDriverRun, runMemoryConsolidationDriver, type ConsolidationDriverEngine, type ConsolidationDriverRunRow, type ConsolidationRunReceipt, type ConsolidationRunStopReason, type RunMemoryConsolidationOptions, isInstructionEntry, type MemoryEntryOrigin, type MemoryOriginCause, MEMORY_INSTRUCTION_TEMPLATE, MEMORY_RECALL_DISCIPLINE, MEMORY_PREFERENCE_DISCIPLINE, MEMORY_READONLY_NOTICE, readV2HeaderHints, type V2HeaderHints, LINEAGE_FILE, CHALLENGES_FILE, CHALLENGED_HISTORY_FILE, CHALLENGE_LEDGER_MAX_EVENTS, rebuildStrictControlPlaneLedger, type ControlPlaneRebuildReceipt, type StrictControlPlaneLedger, type ChallengeAssignment, type ChallengeEvent, type ChallengedHistoryRow, type LineagePendingTxn, type LineagePromotion, MEMORY_INDEX_FILENAME, MEMORY_INDEX_MAX_LINES, MEMORY_INDEX_MAX_BYTES, MEMORY_SEARCH_TOOL_NAME, MEMORY_GET_TOOL_NAME, MEMORY_ENGINE_TOOL_NAMES, type MemorySearchDetails, type MemorySearchHit, type CleanMemorySearchHit, type ExposedMemorySearchHit, MEMORY_EXPOSURE_BANNER, MEMORY_EXPOSURE_HANDLE_TAG, memoryExposureIndexRow, type MemoryGetDetails, STUB_ARCHIVED_LINE, DEFAULT_MAX_MEMORY_FILES, DEFAULT_MAX_ENTRY_DEPTH, DEFAULT_HARVEST_DEADLINE_MS, DEFAULT_HARVEST_FILE_BUDGET, MASS_DELETION_FUSE_RATIO, scanMemoryWrite, scanMemoryFileName, scanRemediation, MEMORY_FILENAME_SEGMENT_RE, renderAnnouncements, enqueueMemoryAnnouncement, drainMemoryAnnouncements, peekMemoryAnnouncements, bumpScanFuse, scanFuseCount, clearScanFuse, ANNOUNCEMENTS_FILE, MEMORY_ANNOUNCEMENTS_MAX, SCAN_FUSE_FILE, SCAN_FUSE_THRESHOLD, type MemoryAnnouncement, type ScanFinding, type MemoryEngineOptions, type MemoryInjection, type EntryProvenanceAccount, type TransferEvidence, type CommittedBinding, type CommittedEntrySnapshot, type CommittedScopeSnapshots, type EntryCustodyReport, erasureSelectHash, type EraseMemoryEntriesInput, type ErasureSelect, type ErasedBinding, type MemoryErasureAttestation, computeMemoryBundleHash, type MemoryExportBundle, type MemoryImportReport, type MemoryExportSnapshot, type MemoryBundleImportPlan, type BundleChallengeRow, type BundleLineageRow, type BundlePollutedSession, type MemoryBackend, type MemoryEntry, type MemoryEntryFrontmatter, type MemoryEntryHeader, type MemoryScopeEnumeration, type ScoredMemoryEntry, type NotePatch, type PatchReport, type MaterializedFile, type MemorySessionHandle, type HarvestReport, type HarvestRejection, type HarvestRejectionCode, type ParsedEntryFile, type ScannedEntryFile, SCOPE_SEGMENT_MAX_ENCODED, PROJECT_MARKER_PATH, encodeScopeSegment, decodeScopeSegment, parseScopeKey, formatUserScope, formatOrgScope, formatProjScope, formatUserProjScope, isPersonalScope, assertScopeContractPlacement, formatProjectMarker, parseProjectMarker, resolveProjectId, PROJECT_ID_REGEX, type ParsedScopeKey, migrateScope, type MigrateScopeReport, materializeEntriesToFiles, harvestFilesToPatches, projectionsToWriteBack, screenInboundEntries, REMOTE_HARVEST_PER_FILE_BYTES, REMOTE_MASS_DELETION_FUSE_RATIO, type RemoteMemoryFile, type RemoteMemoryBaseline, type RemoteMaterialization, type RemoteHarvestResult, type InboundEntryFinding, deriveProjectMemoryDir, deriveProjectControlDir, recordProjectIdHint, lookupProjectIdHint, PROJECT_ID_HINTS_FILE, reconcileMemoryEntries, nextSyncBaseline, mergeRecallHits, type MemorySyncCursor, type MemorySyncConflict, type MemorySyncPlan, type RecallSource, syncMemoryScope, type MemorySyncTransport, type MemorySyncRequestBody, type MemorySyncResponseBody, type MemorySyncClientConflict, type SyncMemoryScopeOptions, type MemorySyncClientResult, } from "./core/memory-engine/index.js";
171
+ export { MemoryEngine, FileMemoryEngineBackend, memoryBackendContract, assertMemoryBackendSearchEquivalence, type MemoryBackendContractHooks, buildMemoryInstruction, truncateIndex, scanEntryFiles, deriveRepoKey, deriveRepoMemoryDir, deriveControlPlaneDir, deriveRepoControlPlaneDir, resolveMemoryEngineRoot, scopeDirName, ControlPlaneCorruptError, parseEntryFile, serializeEntryFile, computeEntryRev, entryFromFile, MEMORY_ORIGIN_CAUSES, committedOriginOf, originEquals, ambiguousOriginRepresentation, type OriginClearanceRow, type OriginClearanceEvent, committedDistilledOf, distilledEquals, type MemoryEntryDistilled, type MemoryEntryDistilledInput, CONSOLIDATION_DEFAULTS, ConsolidationRefusedError, MEMORY_SEARCH_SUPERSEDED_TAG, consolidationTypeEligible, deriveSupersededSet, memorySupersededNote, readIntentCredentials, supersessionFuseCeiling, memoryConsolidationRecommendedNotice, memoryConsolidationCommittedNotice, memoryConsolidationConflictNotice, memoryConsolidationIncompleteNotice, memoryConsolidationRefusedNotice, type ConsolidationGateRead, type ConsolidationGateRow, type ConsolidationIntent, type ConsolidationIntentCredentialRow, type ConsolidationLeaseSeat, type ConsolidationProductProposal, type ConsolidationProposal, type MemoryConsolidationOptions, type ConsolidationCommitReceipt, type ConsolidationReconcileReport, type ConsolidationResolveReceipt, type ConsolidationPlanSummary, type ConsolidationPlanFoldEvidence, DISTILLER_DEFAULT_MAX_INPUTS_PER_PRODUCT, LLM_DISTILLER_CONTRACT, LLM_DISTILLER_CONTRACT_DL2, LLM_DISTILLER_CONTRACT_DL3, LLM_DISTILLER_CONTRACTS, MEMORY_DISTILLER_CONTRACT_V1, contractGroupingDiff, driveConsolidationToFixpoint, isAliasModelId, llmPlanDistiller, mintExposurePartitionedPlan, mintLlmConsolidationPlan, openAiCompatChatSeat, parseJsonAnswer, planParseRepairs, sanitizeLlmGroups, scheduleUnderFuse, type ConsolidationDistillFn, type ConsolidationDriveCycleRow, type ConsolidationDriveEngine, type ConsolidationDriveResult, type ConsolidationFoldState, type DistillerCandidate, type DistillerChatAnswer, type DistillerChatFn, type DistillerChatRequest, type FuseSchedule, type LlmConsolidationPlan, type LlmConsolidationPlanArm, type LlmConsolidationPlanProduct, type LlmDistillerContract, type MintLlmConsolidationPlanResult, type PlanParseRepairs, type SanitizedLlmGroups, CONSOLIDATION_DRIVER_PLANS_DIR, CONSOLIDATION_DRIVER_RUNS_FILE, CONSOLIDATION_RUN_STOP_REASONS, archiveDistillerPlan, readConsolidationDriverRun, runMemoryConsolidationDriver, type ConsolidationDriverEngine, type ConsolidationDriverRunRow, type ConsolidationRunReceipt, type ConsolidationRunStopReason, type RunMemoryConsolidationOptions, isInstructionEntry, type MemoryEntryOrigin, type MemoryOriginCause, MEMORY_INSTRUCTION_TEMPLATE, MEMORY_RECALL_DISCIPLINE, MEMORY_PREFERENCE_DISCIPLINE, MEMORY_READONLY_NOTICE, readV2HeaderHints, type V2HeaderHints, LINEAGE_FILE, CHALLENGES_FILE, CHALLENGED_HISTORY_FILE, CHALLENGE_LEDGER_MAX_EVENTS, rebuildStrictControlPlaneLedger, type ControlPlaneRebuildReceipt, type StrictControlPlaneLedger, type ChallengeAssignment, type ChallengeEvent, type ChallengedHistoryRow, type LineagePendingTxn, type LineagePromotion, MEMORY_INDEX_FILENAME, MEMORY_INDEX_MAX_LINES, MEMORY_INDEX_MAX_BYTES, MEMORY_SEARCH_TOOL_NAME, MEMORY_GET_TOOL_NAME, MEMORY_ENGINE_TOOL_NAMES, type MemorySearchDetails, type MemorySearchHit, type CleanMemorySearchHit, type ExposedMemorySearchHit, MEMORY_EXPOSURE_BANNER, MEMORY_EXPOSURE_HANDLE_TAG, memoryExposureIndexRow, type MemoryGetDetails, STUB_ARCHIVED_LINE, DEFAULT_MAX_MEMORY_FILES, DEFAULT_MAX_ENTRY_DEPTH, DEFAULT_HARVEST_DEADLINE_MS, DEFAULT_HARVEST_FILE_BUDGET, MASS_DELETION_FUSE_RATIO, scanMemoryWrite, scanMemoryFileName, scanRemediation, MEMORY_FILENAME_SEGMENT_RE, renderAnnouncements, enqueueMemoryAnnouncement, drainMemoryAnnouncements, peekMemoryAnnouncements, bumpScanFuse, scanFuseCount, clearScanFuse, ANNOUNCEMENTS_FILE, MEMORY_ANNOUNCEMENTS_MAX, SCAN_FUSE_FILE, SCAN_FUSE_THRESHOLD, type MemoryAnnouncement, type ScanFinding, type MemoryEngineOptions, type MemoryInjection, type EntryProvenanceAccount, type TransferEvidence, type CommittedBinding, type CommittedEntrySnapshot, type CommittedScopeSnapshots, type EntryCustodyReport, erasureSelectHash, type EraseMemoryEntriesInput, type ErasureSelect, type ErasedBinding, type MemoryErasureAttestation, computeMemoryBundleHash, type MemoryExportBundle, type MemoryImportReport, type MemoryExportSnapshot, type MemoryBundleImportPlan, type BundleChallengeRow, type BundleLineageRow, type BundlePollutedSession, type MemoryBackend, type MemoryEntry, type MemoryEntryFrontmatter, type MemoryEntryHeader, type MemoryScopeEnumeration, type ScoredMemoryEntry, type NotePatch, type PatchReport, type MaterializedFile, type MemorySessionHandle, type HarvestReport, type HarvestRejection, type HarvestRejectionCode, type ParsedEntryFile, type ScannedEntryFile, SCOPE_SEGMENT_MAX_ENCODED, PROJECT_MARKER_PATH, encodeScopeSegment, decodeScopeSegment, parseScopeKey, formatUserScope, formatOrgScope, formatProjScope, formatUserProjScope, isPersonalScope, assertScopeContractPlacement, formatProjectMarker, parseProjectMarker, resolveProjectId, PROJECT_ID_REGEX, type ParsedScopeKey, migrateScope, type MigrateScopeReport, materializeEntriesToFiles, harvestFilesToPatches, projectionsToWriteBack, screenInboundEntries, REMOTE_HARVEST_PER_FILE_BYTES, REMOTE_MASS_DELETION_FUSE_RATIO, type RemoteMemoryFile, type RemoteMemoryBaseline, type RemoteMaterialization, type RemoteHarvestResult, type InboundEntryFinding, deriveProjectMemoryDir, deriveProjectControlDir, recordProjectIdHint, lookupProjectIdHint, PROJECT_ID_HINTS_FILE, reconcileMemoryEntries, nextSyncBaseline, mergeRecallHits, type MemorySyncCursor, type MemorySyncConflict, type MemorySyncPlan, type RecallSource, syncMemoryScope, type MemorySyncTransport, type MemorySyncRequestBody, type MemorySyncResponseBody, type MemorySyncClientConflict, type SyncMemoryScopeOptions, type MemorySyncClientResult, } from "./core/memory-engine/index.js";
172
172
  export { SHARED_MEMORY_READ_CAP_BYTES, SHARED_MEMORY_LIST_PAGE_SIZE, SharedMemoryStoreError, type SharedMemoryStoreProvider, type SharedMemoryStoreReader, type SharedMemoryPagedList, type SharedMemoryStoreInfo, type SharedMemoryDocumentEntry, type SharedMemorySnapshot, type SharedMemoryRequestContext, type MemoryListDetails, type MemoryReadDetails, } from "./core/shared-memory/types.js";
173
173
  export { sharedMemoryStoreContract, type SharedMemoryFixture, type SharedMemoryStoreContractHooks, } from "./core/shared-memory/contract.js";
174
174
  export { termSet, jaccardDistance, cosineDistance } from "./core/memory-vector.js";
package/dist/index.js CHANGED
@@ -89,7 +89,7 @@ export { createSensitivePathPolicy, RECOMMENDED_SENSITIVE_PATTERNS } from "./cor
89
89
  export { createFsWriteGatePolicy } from "./core/fs-write-gate-policy.js";
90
90
  export { RETIRED_TOOL_NAMES } from "./core/tool-name-aliases.js";
91
91
  export { DEFAULT_SUBAGENT_TOOL_NAME } from "./agents/subagent.js";
92
- export { renderTaskNotificationXml, taskNotificationDedupKey, isDelegatedAgentTerminal, SystemInjectionQueue, } from "./core/task-notification.js";
92
+ export { renderTaskNotificationXml, taskNotificationDedupKey, isDelegatedAgentTerminal, isTerminalTaskNotification, SystemInjectionQueue, } from "./core/task-notification.js";
93
93
  export { describeStaticWiring, deriveWiringManifest, deriveAskEffective, resolveDeclaredDurability, resolveSubagentTranscriptTier, resolveAskSeamForm, resolveQuestionSeam, countElicitOptIns, } from "./core/wiring-manifest.js";
94
94
  export { probeParkRoundTrip, durableParkGapOf, durableParkGapFor, PARK_SELFCHECK_SCOPE_PREFIX, } from "./core/park-selfcheck.js";
95
95
  export {} from "./core/checkpoint-store.js";
@@ -130,7 +130,7 @@ export { AdoptionError, assertAdoptionBootGate, readRootAdoptionFile, writeRootA
130
130
  export { adoptLocalDataRoot, ackAdoptionConfig, witnessAdoptionConfig, listAdoptionQuarantine, readAdoptionStatus, } from "./stores/file/adoption/adopt.js";
131
131
  export { formatHookFeedback, runToolGate, createHookEnvCapabilities, createPreToolUseConstraintPolicy, normalizePersistedRuleHit, } from "./core/hooks.js";
132
132
  export { InMemoryMemoryStore, composeMemoryBlock, composeLayeredMemoryBlock, normalizeMemorySpec, supportsConsolidation, supportsPeriodicConsolidation, firstSentence, expandLexicalTerms, lexicalSearchMatch, classifyPromotable, enforcePromotableWriteGate, guardedMemoryStore, MemoryGateError, detectSecret, enforceSecretWriteGate, enforceStructuredNoteSecretGate, } from "./core/memory.js";
133
- export { MemoryEngine, FileMemoryEngineBackend, memoryBackendContract, assertMemoryBackendSearchEquivalence, buildMemoryInstruction, truncateIndex, scanEntryFiles, deriveRepoKey, deriveRepoMemoryDir, deriveControlPlaneDir, deriveRepoControlPlaneDir, resolveMemoryEngineRoot, scopeDirName, ControlPlaneCorruptError, parseEntryFile, serializeEntryFile, computeEntryRev, entryFromFile, MEMORY_ORIGIN_CAUSES, committedOriginOf, originEquals, ambiguousOriginRepresentation, committedDistilledOf, distilledEquals, CONSOLIDATION_DEFAULTS, ConsolidationRefusedError, MEMORY_SEARCH_SUPERSEDED_TAG, consolidationTypeEligible, deriveSupersededSet, memorySupersededNote, readIntentCredentials, supersessionFuseCeiling, memoryConsolidationRecommendedNotice, memoryConsolidationCommittedNotice, memoryConsolidationConflictNotice, memoryConsolidationIncompleteNotice, memoryConsolidationRefusedNotice, DISTILLER_DEFAULT_MAX_INPUTS_PER_PRODUCT, LLM_DISTILLER_CONTRACT, LLM_DISTILLER_CONTRACT_DL2, LLM_DISTILLER_CONTRACT_DL3, LLM_DISTILLER_CONTRACTS, MEMORY_DISTILLER_CONTRACT_V1, contractGroupingDiff, driveConsolidationToFixpoint, isAliasModelId, llmPlanDistiller, mintLlmConsolidationPlan, openAiCompatChatSeat, parseJsonAnswer, planParseRepairs, sanitizeLlmGroups, scheduleUnderFuse, CONSOLIDATION_DRIVER_PLANS_DIR, CONSOLIDATION_DRIVER_RUNS_FILE, CONSOLIDATION_RUN_STOP_REASONS, archiveDistillerPlan, readConsolidationDriverRun, runMemoryConsolidationDriver, isInstructionEntry, MEMORY_INSTRUCTION_TEMPLATE, MEMORY_RECALL_DISCIPLINE, MEMORY_PREFERENCE_DISCIPLINE, MEMORY_READONLY_NOTICE, readV2HeaderHints, LINEAGE_FILE, CHALLENGES_FILE, CHALLENGED_HISTORY_FILE, CHALLENGE_LEDGER_MAX_EVENTS, rebuildStrictControlPlaneLedger, MEMORY_INDEX_FILENAME, MEMORY_INDEX_MAX_LINES, MEMORY_INDEX_MAX_BYTES, MEMORY_SEARCH_TOOL_NAME, MEMORY_GET_TOOL_NAME, MEMORY_ENGINE_TOOL_NAMES, MEMORY_EXPOSURE_BANNER, MEMORY_EXPOSURE_HANDLE_TAG, memoryExposureIndexRow, STUB_ARCHIVED_LINE, DEFAULT_MAX_MEMORY_FILES, DEFAULT_MAX_ENTRY_DEPTH, DEFAULT_HARVEST_DEADLINE_MS, DEFAULT_HARVEST_FILE_BUDGET, MASS_DELETION_FUSE_RATIO, scanMemoryWrite, scanMemoryFileName, scanRemediation, MEMORY_FILENAME_SEGMENT_RE, renderAnnouncements, enqueueMemoryAnnouncement, drainMemoryAnnouncements, peekMemoryAnnouncements, bumpScanFuse, scanFuseCount, clearScanFuse, ANNOUNCEMENTS_FILE, MEMORY_ANNOUNCEMENTS_MAX, SCAN_FUSE_FILE, SCAN_FUSE_THRESHOLD, erasureSelectHash, computeMemoryBundleHash, SCOPE_SEGMENT_MAX_ENCODED, PROJECT_MARKER_PATH, encodeScopeSegment, decodeScopeSegment, parseScopeKey, formatUserScope, formatOrgScope, formatProjScope, formatUserProjScope, isPersonalScope, assertScopeContractPlacement, formatProjectMarker, parseProjectMarker, resolveProjectId, PROJECT_ID_REGEX, migrateScope, materializeEntriesToFiles, harvestFilesToPatches, projectionsToWriteBack, screenInboundEntries, REMOTE_HARVEST_PER_FILE_BYTES, REMOTE_MASS_DELETION_FUSE_RATIO, deriveProjectMemoryDir, deriveProjectControlDir, recordProjectIdHint, lookupProjectIdHint, PROJECT_ID_HINTS_FILE, reconcileMemoryEntries, nextSyncBaseline, mergeRecallHits, syncMemoryScope, } from "./core/memory-engine/index.js";
133
+ export { MemoryEngine, FileMemoryEngineBackend, memoryBackendContract, assertMemoryBackendSearchEquivalence, buildMemoryInstruction, truncateIndex, scanEntryFiles, deriveRepoKey, deriveRepoMemoryDir, deriveControlPlaneDir, deriveRepoControlPlaneDir, resolveMemoryEngineRoot, scopeDirName, ControlPlaneCorruptError, parseEntryFile, serializeEntryFile, computeEntryRev, entryFromFile, MEMORY_ORIGIN_CAUSES, committedOriginOf, originEquals, ambiguousOriginRepresentation, committedDistilledOf, distilledEquals, CONSOLIDATION_DEFAULTS, ConsolidationRefusedError, MEMORY_SEARCH_SUPERSEDED_TAG, consolidationTypeEligible, deriveSupersededSet, memorySupersededNote, readIntentCredentials, supersessionFuseCeiling, memoryConsolidationRecommendedNotice, memoryConsolidationCommittedNotice, memoryConsolidationConflictNotice, memoryConsolidationIncompleteNotice, memoryConsolidationRefusedNotice, DISTILLER_DEFAULT_MAX_INPUTS_PER_PRODUCT, LLM_DISTILLER_CONTRACT, LLM_DISTILLER_CONTRACT_DL2, LLM_DISTILLER_CONTRACT_DL3, LLM_DISTILLER_CONTRACTS, MEMORY_DISTILLER_CONTRACT_V1, contractGroupingDiff, driveConsolidationToFixpoint, isAliasModelId, llmPlanDistiller, mintExposurePartitionedPlan, mintLlmConsolidationPlan, openAiCompatChatSeat, parseJsonAnswer, planParseRepairs, sanitizeLlmGroups, scheduleUnderFuse, CONSOLIDATION_DRIVER_PLANS_DIR, CONSOLIDATION_DRIVER_RUNS_FILE, CONSOLIDATION_RUN_STOP_REASONS, archiveDistillerPlan, readConsolidationDriverRun, runMemoryConsolidationDriver, isInstructionEntry, MEMORY_INSTRUCTION_TEMPLATE, MEMORY_RECALL_DISCIPLINE, MEMORY_PREFERENCE_DISCIPLINE, MEMORY_READONLY_NOTICE, readV2HeaderHints, LINEAGE_FILE, CHALLENGES_FILE, CHALLENGED_HISTORY_FILE, CHALLENGE_LEDGER_MAX_EVENTS, rebuildStrictControlPlaneLedger, MEMORY_INDEX_FILENAME, MEMORY_INDEX_MAX_LINES, MEMORY_INDEX_MAX_BYTES, MEMORY_SEARCH_TOOL_NAME, MEMORY_GET_TOOL_NAME, MEMORY_ENGINE_TOOL_NAMES, MEMORY_EXPOSURE_BANNER, MEMORY_EXPOSURE_HANDLE_TAG, memoryExposureIndexRow, STUB_ARCHIVED_LINE, DEFAULT_MAX_MEMORY_FILES, DEFAULT_MAX_ENTRY_DEPTH, DEFAULT_HARVEST_DEADLINE_MS, DEFAULT_HARVEST_FILE_BUDGET, MASS_DELETION_FUSE_RATIO, scanMemoryWrite, scanMemoryFileName, scanRemediation, MEMORY_FILENAME_SEGMENT_RE, renderAnnouncements, enqueueMemoryAnnouncement, drainMemoryAnnouncements, peekMemoryAnnouncements, bumpScanFuse, scanFuseCount, clearScanFuse, ANNOUNCEMENTS_FILE, MEMORY_ANNOUNCEMENTS_MAX, SCAN_FUSE_FILE, SCAN_FUSE_THRESHOLD, erasureSelectHash, computeMemoryBundleHash, SCOPE_SEGMENT_MAX_ENCODED, PROJECT_MARKER_PATH, encodeScopeSegment, decodeScopeSegment, parseScopeKey, formatUserScope, formatOrgScope, formatProjScope, formatUserProjScope, isPersonalScope, assertScopeContractPlacement, formatProjectMarker, parseProjectMarker, resolveProjectId, PROJECT_ID_REGEX, migrateScope, materializeEntriesToFiles, harvestFilesToPatches, projectionsToWriteBack, screenInboundEntries, REMOTE_HARVEST_PER_FILE_BYTES, REMOTE_MASS_DELETION_FUSE_RATIO, deriveProjectMemoryDir, deriveProjectControlDir, recordProjectIdHint, lookupProjectIdHint, PROJECT_ID_HINTS_FILE, reconcileMemoryEntries, nextSyncBaseline, mergeRecallHits, syncMemoryScope, } from "./core/memory-engine/index.js";
134
134
  export { SHARED_MEMORY_READ_CAP_BYTES, SHARED_MEMORY_LIST_PAGE_SIZE, SharedMemoryStoreError, } from "./core/shared-memory/types.js";
135
135
  export { sharedMemoryStoreContract, } from "./core/shared-memory/contract.js";
136
136
  export { termSet, jaccardDistance, cosineDistance } from "./core/memory-vector.js";
@@ -188,8 +188,13 @@ export interface RunWorkflowToolDeps {
188
188
  rootSessionId?: string;
189
189
  /** Process-local unified task registry. When present, RunWorkflow returns `task_id === runId` with a `w*` id. */
190
190
  taskRegistry?: TaskRegistry;
191
- /** design/115 P2 core slice: run-local task-notification sink for SDK event + live model XML injection. */
192
- taskNotification?: (notification: TaskNotificationPayload) => void;
191
+ /** design/115 P2 core slice: run-local task-notification sink for SDK event + live model XML injection.
192
+ * design/373 §3.7: the sink accepts the injection tier — workflow terminals declare `"next"`
193
+ * explicitly (a completion must reach a busy model at the boundary; the parameterless funnel
194
+ * default is the EXTERNAL lane's `"later"` and no internal lane may lean on it). */
195
+ taskNotification?: (notification: TaskNotificationPayload, opts?: {
196
+ priority?: "now" | "next" | "later";
197
+ }) => void;
193
198
  /** Runner-owned owner fallback for registry access when the execute context is unavailable. */
194
199
  taskOwner?: string;
195
200
  /** Hard ceilings. */
@@ -559,7 +559,7 @@ export async function createRunWorkflowTool(d) {
559
559
  return;
560
560
  notified = true;
561
561
  try {
562
- d.taskNotification?.(notification);
562
+ d.taskNotification?.(notification, { priority: "next" });
563
563
  }
564
564
  catch {
565
565
  }
@@ -14,9 +14,9 @@
14
14
  * Wiring: the process runs through the SAME ExecutionEnv background seam as Bash(run_in_background)
15
15
  * (`spawnBackground` — remote envs included); the watcher/batching/timeout machinery lives in
16
16
  * {@link TaskRegistry.registerMonitor} (background_bash G2b watcher's near kin); events ride the
17
- * TaskNotificationPayload lane at "later" priority (delivered at the next turn boundary like every
18
- * notificationruled 2026-08-05; consecutive frames drain as one boundary batch, and a backlog past
19
- * the engine-note cap parks per session, so a chatty watcher cannot monopolize the run's boundaries).
17
+ * TaskNotificationPayload lane at "next" priority (design/373 #445 ALIGNED re-seat: the running turn's
18
+ * next boundary — consecutive frames drain as one boundary batch, the rate limiter + engine-note cap
19
+ * with terminal preference keep a chatty watcher from monopolizing the run's boundaries).
20
20
  * (1.257): events born BETWEEN turns (run torn down / harness idle — the long-watch main case)
21
21
  * are no longer lost: the Runner parks them per session (bounded, drop-disclosing) and the session's next
22
22
  * run redelivers them through the same notification lane at its first turn boundary.
@@ -89,7 +89,7 @@ export function createMonitorTool(env, opts) {
89
89
  persistent: isPersistent,
90
90
  ...(sessionScoped ? { sessionScoped: true } : {}),
91
91
  ...(isPersistent ? {} : { timeoutMs }),
92
- ...(onNotify !== undefined ? { onEvent: (n) => onNotify(n, { priority: "later" }) } : {}),
92
+ ...(onNotify !== undefined ? { onEvent: (n) => onNotify(n, { priority: "next" }) } : {}),
93
93
  ...(opts.timers !== undefined ? { timers: opts.timers } : {}),
94
94
  ...(opts.batchWindowMs !== undefined ? { batchWindowMs: opts.batchWindowMs } : {}),
95
95
  ...(opts.maxBatchesPerMinute !== undefined ? { maxBatchesPerMinute: opts.maxBatchesPerMinute } : {}),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sema-agent/core",
3
- "version": "5.60.1",
3
+ "version": "5.61.0",
4
4
  "description": "Stateless, task-oriented AI agent core",
5
5
  "type": "module",
6
6
  "license": "BUSL-1.1",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "_comment": "design/87 L3 — frozen public export surface of src/index.ts (name -> kind). DO NOT edit by hand to silence a red test. A removed/changed entry = a SemVer-BREAKING change; bump MAJOR and update this fixture in the SAME commit (design/87 §4.2 / §5.2). Regenerate via REGEN in test/export-surface.test.ts.",
3
3
  "_tierComment": "#435 v1 — machine-readable layering of the public surface: stable = demonstrated by README.md / src/examples; internal = an `Internal`-marked name or a runner/engine deep-subtree declaration (the model seam src/engine/llm is excluded — it is the BYOM contract, not an engine internal); advanced = a supported export the front door does not walk you through. THIS IS AN INITIAL HEURISTIC, derived mechanically and expected to be refined ticket by ticket: no human reviewed these 1700+ entries one by one, and nothing here claims otherwise. Known bias: a short or English-word export name (ok, err, Result, Usage) can match ordinary prose in README.md and land `stable` on a coincidence. Every export MUST carry a tier — a new export with no row fails the gate in export-surface.test.ts.",
4
- "count": 1760,
4
+ "count": 1763,
5
5
  "exports": {
6
6
  "A2ATaskState": "type",
7
7
  "A2ATaskStateReversal": "type",
@@ -442,6 +442,7 @@
442
442
  "LineagePendingTxn": "interface",
443
443
  "LineagePromotion": "interface",
444
444
  "LlmConsolidationPlan": "interface",
445
+ "LlmConsolidationPlanArm": "interface",
445
446
  "LlmConsolidationPlanProduct": "interface",
446
447
  "LlmDistillerContract": "interface",
447
448
  "LockedConfig": "interface",
@@ -1473,6 +1474,7 @@
1473
1474
  "isSelfOrchestrationActive": "function",
1474
1475
  "isSessionConflict": "function",
1475
1476
  "isSuspendable": "function",
1477
+ "isTerminalTaskNotification": "function",
1476
1478
  "isTerminalWorkflowStatus": "function",
1477
1479
  "isThinkingLevel": "function",
1478
1480
  "isValidCronExpr": "function",
@@ -1519,6 +1521,7 @@
1519
1521
  "migrateScope": "function",
1520
1522
  "mintCheckpointId": "function",
1521
1523
  "mintCheckpointToken": "function",
1524
+ "mintExposurePartitionedPlan": "function",
1522
1525
  "mintLlmConsolidationPlan": "function",
1523
1526
  "mintReminderMark": "function",
1524
1527
  "mintRuleTicket": "function",
@@ -2204,6 +2207,7 @@
2204
2207
  "LineagePendingTxn": "advanced",
2205
2208
  "LineagePromotion": "advanced",
2206
2209
  "LlmConsolidationPlan": "advanced",
2210
+ "LlmConsolidationPlanArm": "advanced",
2207
2211
  "LlmConsolidationPlanProduct": "advanced",
2208
2212
  "LlmDistillerContract": "advanced",
2209
2213
  "LockedConfig": "advanced",
@@ -3235,6 +3239,7 @@
3235
3239
  "isSelfOrchestrationActive": "advanced",
3236
3240
  "isSessionConflict": "stable",
3237
3241
  "isSuspendable": "advanced",
3242
+ "isTerminalTaskNotification": "advanced",
3238
3243
  "isTerminalWorkflowStatus": "advanced",
3239
3244
  "isThinkingLevel": "advanced",
3240
3245
  "isValidCronExpr": "advanced",
@@ -3281,6 +3286,7 @@
3281
3286
  "migrateScope": "advanced",
3282
3287
  "mintCheckpointId": "advanced",
3283
3288
  "mintCheckpointToken": "advanced",
3289
+ "mintExposurePartitionedPlan": "advanced",
3284
3290
  "mintLlmConsolidationPlan": "advanced",
3285
3291
  "mintReminderMark": "advanced",
3286
3292
  "mintRuleTicket": "advanced",