@sema-agent/core 5.45.0 → 5.47.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 (80) hide show
  1. package/CHANGELOG.md +97 -0
  2. package/dist/agents/subagent.js +130 -3
  3. package/dist/core/checkpoint-store.d.ts +12 -0
  4. package/dist/core/governance-codes.d.ts +13 -0
  5. package/dist/core/governance-codes.js +33 -0
  6. package/dist/core/hooks.d.ts +9 -2
  7. package/dist/core/hooks.js +6 -5
  8. package/dist/core/memory-engine/content-origin.d.ts +3 -1
  9. package/dist/core/memory-engine/delegation-settlement.d.ts +318 -0
  10. package/dist/core/memory-engine/delegation-settlement.js +661 -0
  11. package/dist/core/memory-engine/engine.d.ts +209 -4
  12. package/dist/core/memory-engine/engine.js +885 -39
  13. package/dist/core/memory-engine/export-bundle.d.ts +10 -1
  14. package/dist/core/memory-engine/export-bundle.js +21 -0
  15. package/dist/core/memory-engine/file-backend.d.ts +34 -4
  16. package/dist/core/memory-engine/file-backend.js +168 -40
  17. package/dist/core/memory-engine/frontmatter.d.ts +69 -1
  18. package/dist/core/memory-engine/frontmatter.js +156 -2
  19. package/dist/core/memory-engine/header-hints.d.ts +17 -0
  20. package/dist/core/memory-engine/header-hints.js +6 -0
  21. package/dist/core/memory-engine/index.d.ts +7 -5
  22. package/dist/core/memory-engine/index.js +5 -3
  23. package/dist/core/memory-engine/layout.d.ts +39 -2
  24. package/dist/core/memory-engine/layout.js +27 -14
  25. package/dist/core/memory-engine/memory-backend-contract.js +108 -0
  26. package/dist/core/memory-engine/origin-clearance.d.ts +66 -0
  27. package/dist/core/memory-engine/origin-clearance.js +84 -0
  28. package/dist/core/memory-engine/provenance-wording.d.ts +50 -0
  29. package/dist/core/memory-engine/provenance-wording.js +15 -0
  30. package/dist/core/memory-engine/sync-client.d.ts +1 -1
  31. package/dist/core/memory-engine/sync-client.js +33 -1
  32. package/dist/core/memory-engine/tools.d.ts +64 -3
  33. package/dist/core/memory-engine/tools.js +37 -9
  34. package/dist/core/memory-engine/types.d.ts +145 -3
  35. package/dist/core/memory-engine/types.js +1 -1
  36. package/dist/core/reminder-mint.d.ts +70 -0
  37. package/dist/core/reminder-mint.js +25 -0
  38. package/dist/core/runner/git-status-frame.d.ts +3 -14
  39. package/dist/core/runner/git-status-frame.js +39 -14
  40. package/dist/core/runner/prepare-config-doors.d.ts +4 -0
  41. package/dist/core/runner/prepare-config-doors.js +15 -0
  42. package/dist/core/runner/prepare-hands-readface.d.ts +5 -11
  43. package/dist/core/runner/prepare-hands-readface.js +26 -0
  44. package/dist/core/runner/prepare-memory.d.ts +11 -0
  45. package/dist/core/runner/prepare-memory.js +61 -24
  46. package/dist/core/runner/prepare-task.d.ts +46 -1
  47. package/dist/core/runner/prepare-task.js +128 -23
  48. package/dist/core/runner/runtask.js +62 -55
  49. package/dist/core/session-reconcile.js +3 -2
  50. package/dist/core/side-query.d.ts +11 -1
  51. package/dist/core/side-query.js +3 -0
  52. package/dist/core/types.d.ts +85 -10
  53. package/dist/core/types.js +3 -0
  54. package/dist/engine/harness/types.d.ts +46 -1
  55. package/dist/engine/harness/types.js +11 -0
  56. package/dist/engine/session/import-validate.js +6 -1
  57. package/dist/engine/session/session.d.ts +20 -0
  58. package/dist/engine/session/session.js +26 -1
  59. package/dist/index.d.ts +3 -1
  60. package/dist/index.js +3 -1
  61. package/dist/orchestration/run-workflow-tool.d.ts +16 -0
  62. package/dist/orchestration/run-workflow-tool.js +23 -3
  63. package/dist/orchestration/workflow-governance.d.ts +8 -1
  64. package/dist/prompt-assembly/epoch.js +2 -0
  65. package/dist/prompt-assembly/types.d.ts +6 -0
  66. package/dist/prompts/default.d.ts +13 -1
  67. package/dist/prompts/default.js +5 -1
  68. package/dist/tools/fs/fs-bash.d.ts +4 -0
  69. package/dist/tools/fs/fs-bash.js +1 -1
  70. package/dist/tools/fs/fs-read.d.ts +1 -1
  71. package/dist/tools/fs/fs-read.js +8 -7
  72. package/dist/tools/fs/fs-shared.d.ts +10 -4
  73. package/dist/tools/fs/fs-shared.js +6 -3
  74. package/dist/tools/fs/gh-rate-limit.d.ts +4 -1
  75. package/dist/tools/fs/gh-rate-limit.js +3 -2
  76. package/dist/tools/fs/index.d.ts +10 -2
  77. package/dist/tools/fs/index.js +2 -1
  78. package/dist/tools/task-list.d.ts +5 -1
  79. package/package.json +1 -1
  80. package/test/export-surface.snapshot.json +21 -2
@@ -26,6 +26,7 @@ import { findAdmittingRule, suggestRulesForCommand } from "../permission-rule-mo
26
26
  import { ActiveSkillScope, createActiveSkillScopePolicy } from "./active-skill-scope.js";
27
27
  import { CHANGED_FILES_MTIME_EPS_MS, fenceMcpServerInstructions, renderAgentListingDelta } from "./turn-attachments.js";
28
28
  import { inlineUntrusted } from "../untrusted-text.js";
29
+ import { isValidReminderMark, mintReminderMark, reminderMarkDeclaration } from "../reminder-mint.js";
29
30
  import { policyAskClassOf } from "../ask-class.js";
30
31
  import { emitTrace } from "../trace.js";
31
32
  import { createSessionRulePolicy, PATH_CONFINABLE_WRITE_TOOLS } from "./session-rule-policy.js";
@@ -46,9 +47,10 @@ import { TOOL_SEARCH_NAME, buildDeferredRegistry, classifyDeferred, extractDisco
46
47
  import { createSharedMemoryTools } from "../shared-memory/tools.js";
47
48
  import { SHARED_MEMORY_TOOL_NAMES } from "../shared-memory/types.js";
48
49
  import { MEMORY_ENGINE_TOOL_NAMES } from "../memory-engine/tools.js";
49
- import { MEMORY_RECALL_DISCIPLINE } from "../memory-engine/engine.js";
50
+ import { memoryRecallDisciplineSegment } from "../memory-engine/engine.js";
50
51
  import { classifyToolContentOrigin, contentOriginPollutes, delegationCallIsExternal } from "../memory-engine/content-origin.js";
51
52
  import { narrowContentSafety, readCardAttestation } from "../memory-engine/delegation-provenance.js";
53
+ import { recordSyncUnattestable, sessionSettlements } from "../memory-engine/delegation-settlement.js";
52
54
  import { composeMemoryBlock } from "../memory.js";
53
55
  import { COMPLIANCE_CAPABILITIES, WEB_FETCH_TOOL_NAME, complianceCallDenial, resolveComplianceDenies } from "../compliance.js";
54
56
  import { foldAdmissionFreeze } from "../memory-admission.js";
@@ -333,7 +335,7 @@ function cwdConflictsRestoreError(requestedCwd) {
333
335
  export async function prepareTask(spec, deps, sessions, resume, internals, runnerSelf) {
334
336
  const doors = prepareConfigDoors({ spec, deps, sessions, resume, internals });
335
337
  spec = doors.spec;
336
- const { toolFaceSnapshot, promptProfile, lockedPreflight, resolvedInteractionPosture, resolvedRole, model, thinking, compModel, fableMitigations, memoryDelegationEvidence, usageWindows, brainCallGuardrailRef, brainCallGuardrailMs } = doors;
338
+ const { toolFaceSnapshot, promptProfile, lockedPreflight, resolvedInteractionPosture, resolvedRole, model, thinking, compModel, fableMitigations, memoryDelegationEvidence, memoryProvenance, usageWindows, brainCallGuardrailRef, brainCallGuardrailMs } = doors;
337
339
  announceToolModelGate(deps.onNotice, model.id, doors.modelGate);
338
340
  const { toolEffects, egressTools, irreversibleTools, irreversibilityTier, axisExplicitNegatives, reversibilityProbes, ownToolNames } = prepareSafetyScan({ spec, deps });
339
341
  let shellGatedBash = false;
@@ -351,6 +353,30 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
351
353
  const taskScope = internals?.registryScope ?? spec.principal ?? "default";
352
354
  internals?.peerSelfRef?.addAxis("s", sessionId);
353
355
  internals?.peerSelfRef?.addAxis("t", hostTaskId);
356
+ const sessionReminderMark = await (async () => {
357
+ try {
358
+ return await session.getReminderMark();
359
+ }
360
+ catch (err) {
361
+ deps.onError?.(err instanceof Error ? err : new Error(String(err)), { phase: "config", sessionId });
362
+ return undefined;
363
+ }
364
+ })();
365
+ const reminderMark = isValidReminderMark(resume?.seed.reminderMark)
366
+ ? resume.seed.reminderMark
367
+ : isValidReminderMark(internals?.reminderMark)
368
+ ? internals.reminderMark
369
+ : isValidReminderMark(sessionReminderMark)
370
+ ? sessionReminderMark
371
+ : mintReminderMark();
372
+ if (reminderMark !== sessionReminderMark) {
373
+ try {
374
+ await session.appendReminderMark(reminderMark);
375
+ }
376
+ catch (err) {
377
+ deps.onError?.(err instanceof Error ? err : new Error(String(err)), { phase: "config", sessionId });
378
+ }
379
+ }
354
380
  const offloadScope = spec.principal ?? "default";
355
381
  if (internals?.registryScope !== undefined && internals.registryScope !== offloadScope) {
356
382
  deps.onError?.(new Error(`offload/tool-result namespace note: this run mounts in registry domain "${internals.registryScope}" but its offloaded tool results live under the TRUST identity "${offloadScope}" (principal${spec.principal === undefined ? " absent → default" : ""}). Before 2.13.0 the registry domain named this namespace too; if a deployment used registryScope as its ref-tenancy boundary, that boundary is now the principal — pass one, or read refs under "${offloadScope}".`), { phase: "config", sessionId });
@@ -708,6 +734,8 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
708
734
  const frozenOnQuestion = spec.onQuestion ?? deps.onQuestion;
709
735
  const provenanceForChildrenRef = {};
710
736
  const delegationProvenanceForChildren = () => provenanceForChildrenRef.current;
737
+ const delegationSettlementRef = {};
738
+ const delegationSettlementForChildren = () => delegationSettlementRef.current;
711
739
  const inheritedGateForChildren = () => {
712
740
  const ancestorRules = [
713
741
  ...(inheritedAncestorRules ?? []),
@@ -797,11 +825,13 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
797
825
  ...(spec.memoryPersistenceCapable !== undefined ? { memoryPersistenceCapable: spec.memoryPersistenceCapable } : {}),
798
826
  getApiKeyAndHeaders: spec.getApiKeyAndHeaders,
799
827
  parentCwd: taskRootFinal,
828
+ reminderMark,
800
829
  ...(centerAdoption !== undefined ? { centerArtifactDigest: centerAdoption.artifact.artifactDigest } : {}),
801
830
  ...(centerAdoption?.sourceRevision !== undefined ? { centerSourceRevision: centerAdoption.sourceRevision } : {}),
802
831
  activeSkillScope: () => skillScope.active(),
803
832
  inheritedGateForChildren,
804
833
  delegationProvenanceForChildren,
834
+ delegationSettlement: delegationSettlementForChildren,
805
835
  ...(autoModeDecider ? { autoModeReview: { decider: autoModeDecider } } : {}),
806
836
  ...(spec.durableApproval !== undefined ? { durableApprovalForChildren: { ...spec.durableApproval } } : {}),
807
837
  ...(spec.checkpointStore === null ? { checkpointStoreDisabledForChildren: true } : {}),
@@ -983,6 +1013,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
983
1013
  sourceTaskId: hostTaskId,
984
1014
  parentModel: () => harnessRef.current?.getModel(),
985
1015
  ...(spec.getApiKeyAndHeaders !== undefined ? { parentGetApiKeyAndHeaders: spec.getApiKeyAndHeaders } : {}),
1016
+ ...(frozenOnAsk !== undefined ? { parentOnAsk: frozenOnAsk } : {}),
986
1017
  principal: spec.principal,
987
1018
  oneShot: spec.oneShot,
988
1019
  ...(resolvedInteractionPosture !== undefined ? { parentInteractionPosture: resolvedInteractionPosture } : {}),
@@ -1198,7 +1229,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
1198
1229
  foldProtocolAxes(a2a.toolAxes, "A2A");
1199
1230
  const callIssuedAtRef = {};
1200
1231
  const memoryWriteGateRef = {};
1201
- const handsReadFaceInput = { handsEnabled, executionEnv, taskRootFinal, rebaseRestoredPath, resume, session, sessionId, hostTaskId, taskScope, fullShellReachable, effectiveShellGate, toolFaceSnapshot, model, spec, deps, internals, memoryWriteGateRef, firstPartyOffload, tools, egressTools, irreversibilityTier, irreversibleTools, reversibilityProbes };
1232
+ const handsReadFaceInput = { handsEnabled, executionEnv, taskRootFinal, rebaseRestoredPath, resume, session, sessionId, hostTaskId, taskScope, fullShellReachable, effectiveShellGate, toolFaceSnapshot, model, spec, deps, internals, memoryWriteGateRef, firstPartyOffload, tools, egressTools, irreversibilityTier, irreversibleTools, reversibilityProbes, reminderMark };
1202
1233
  const handsReadFace = handsEnabled ? await prepareHandsMount(handsReadFaceInput) : resolveHandsLessReadFace(handsReadFaceInput);
1203
1234
  const { readFileStateForCheckpoint, seedContextFiles, handsCwdRef, workspaceStateSettle, wsSnapshot, rebaseWsPath, backgroundTaskToolsActive, additionalRootsCanonical, additionalReadRootsCanonical, attachmentRootCanonical, readDenyMatcher } = handsReadFace;
1204
1235
  resolvedReadFace = handsReadFace.resolvedReadFace;
@@ -1439,9 +1470,11 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
1439
1470
  sessionId,
1440
1471
  taskRootPath: taskRootFinal,
1441
1472
  memoryWriteGateRef,
1473
+ reminderMark,
1442
1474
  writeToolsMounted: tools.some((t) => t.name === "Write") &&
1443
1475
  !(toolFaceSnapshot.exclude?.includes("Write") ?? false) &&
1444
1476
  !(handsEnabled && isRemoteExecutionEnv(executionEnv) && spec.memoryPersistenceCapable !== true),
1477
+ memoryProvenance,
1445
1478
  memoryPersistenceDeclared: spec.memoryPersistenceCapable,
1446
1479
  rosterCanPersist: spec.memoryPersistenceCapable ??
1447
1480
  tools.some((t) => {
@@ -1644,6 +1677,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
1644
1677
  policyEnabled: promptPolicyEnabled,
1645
1678
  hooksEnabled: promptHooksEnabled,
1646
1679
  isolationEnabled: isIsolated(executionEnv),
1680
+ reminderMark,
1647
1681
  readFaceOpen: resolvedReadFace === "open",
1648
1682
  orchestrationEnabled: selfOrchestrationActive,
1649
1683
  orchestrationDeferred: selfOrchestrationActive && (toolFaceSnapshot.defer?.includes("Workflow") ?? false),
@@ -1833,12 +1867,13 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
1833
1867
  if (memoryEnginePair.length > 0) {
1834
1868
  memoryEnginePairMounted = false;
1835
1869
  if (memoryBlock !== undefined) {
1836
- if (memoryBlock === MEMORY_RECALL_DISCIPLINE)
1870
+ const segment = memoryRecallDisciplineSegment(memoryProvenance);
1871
+ if (memoryBlock === segment)
1837
1872
  memoryBlock = undefined;
1838
- else if (memoryBlock.includes(`\n\n${MEMORY_RECALL_DISCIPLINE}`))
1839
- memoryBlock = memoryBlock.replace(`\n\n${MEMORY_RECALL_DISCIPLINE}`, "");
1840
- else if (memoryBlock.startsWith(`${MEMORY_RECALL_DISCIPLINE}\n\n`))
1841
- memoryBlock = memoryBlock.slice(MEMORY_RECALL_DISCIPLINE.length + 2);
1873
+ else if (memoryBlock.includes(`\n\n${segment}`))
1874
+ memoryBlock = memoryBlock.replace(`\n\n${segment}`, "");
1875
+ else if (memoryBlock.startsWith(`${segment}\n\n`))
1876
+ memoryBlock = memoryBlock.slice(segment.length + 2);
1842
1877
  }
1843
1878
  deps.onError?.(new Error(`Memory tools ${MEMORY_ENGINE_TOOL_NAMES.join("/")} were NOT mounted: mounting them would inject ` +
1844
1879
  `the "${TOOL_SEARCH_NAME}" tool, whose name this task already declares — the pair mounts together or not at all.`), { phase: "config", sessionId, classification: "memory-tools-not-mounted" });
@@ -1861,6 +1896,9 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
1861
1896
  const trustedTools = effectiveSafety.trustedTools;
1862
1897
  const execIsExternalContent = effectiveSafety.execIsExternalContent;
1863
1898
  provenanceForChildrenRef.current = { trustedTools: [...trustedTools], execIsExternalContent };
1899
+ if (memoryEngineSession?.settlement !== undefined) {
1900
+ delegationSettlementRef.current = { controlDir: memoryEngineSession.settlement.controlDir, sessionId: memoryEngineSession.settlement.sessionId };
1901
+ }
1864
1902
  const recordExternal = () => {
1865
1903
  if (delegationProvenanceChannel !== undefined)
1866
1904
  delegationProvenanceChannel.ref.current.sawExternal = true;
@@ -1890,6 +1928,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
1890
1928
  isCallerTool: true,
1891
1929
  trusted: trustedTools.has(t.name),
1892
1930
  }), execIsExternalContent);
1931
+ const recallTaintJudge = memoryEngineSession?.recallTaint?.judgeDeliveredPath;
1893
1932
  contentOriginWrapRef.current = () => {
1894
1933
  for (let i = 0; i < tools.length; i++) {
1895
1934
  const t = tools[i];
@@ -1899,14 +1938,15 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
1899
1938
  const delegation = delegationByName.get(t.name);
1900
1939
  const isDelegation = delegation !== undefined;
1901
1940
  const pollutes = contentOriginPollutes(origin, execIsExternalContent);
1902
- if (!pollutes && !isDelegation) {
1941
+ const readsMemoryPlane = recallTaintJudge !== undefined && t.name === "Read";
1942
+ if (!pollutes && !isDelegation && !readsMemoryPlane) {
1903
1943
  contentOriginWrapped.add(t);
1904
1944
  continue;
1905
1945
  }
1906
1946
  const inner = t.execute.bind(t);
1907
- const mark = (reason) => {
1947
+ const mark = (reason, cause) => {
1908
1948
  try {
1909
- pollution?.markPolluted(reason);
1949
+ pollution?.markPolluted(reason, cause);
1910
1950
  }
1911
1951
  catch {
1912
1952
  }
@@ -1915,11 +1955,42 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
1915
1955
  ...t,
1916
1956
  execute: async (toolCallId, params, signal, onUpdate) => {
1917
1957
  if (pollutes) {
1918
- mark(`tool "${t.name}" (${origin} content class) was invoked in this session`);
1958
+ mark(`tool "${t.name}" (${origin} content class) was invoked in this session`, "observed");
1919
1959
  recordExternal();
1920
1960
  }
1921
- if (!isDelegation)
1922
- return inner(toolCallId, params, signal, onUpdate);
1961
+ if (!isDelegation) {
1962
+ if (!readsMemoryPlane)
1963
+ return inner(toolCallId, params, signal, onUpdate);
1964
+ const result = await inner(toolCallId, params, signal, onUpdate);
1965
+ const raw = result;
1966
+ const contentField = typeof raw === "object" && raw !== null ? raw.content : undefined;
1967
+ const headText = typeof raw === "string"
1968
+ ? raw
1969
+ : typeof contentField === "string"
1970
+ ? contentField
1971
+ : Array.isArray(contentField) && typeof contentField[0]?.text === "string"
1972
+ ? contentField[0].text
1973
+ : "";
1974
+ const delivered = result?.isError !== true &&
1975
+ result?.details?.type !== "file_unchanged" &&
1976
+ !headText.startsWith("<system-reminder");
1977
+ const fp = params?.file_path;
1978
+ if (delivered && typeof fp === "string" && recallTaintJudge(fp)) {
1979
+ mark(`the "${t.name}" tool delivered the content of an external-origin memory entry file`, "derived");
1980
+ }
1981
+ return result;
1982
+ }
1983
+ let preCallLaunchRows;
1984
+ if (delegationEvidenceAttestedOnly && memoryEngineSession?.settlement !== undefined) {
1985
+ try {
1986
+ preCallLaunchRows = new Set(sessionSettlements(memoryEngineSession.settlement.controlDir, memoryEngineSession.settlement.sessionId)
1987
+ .filter((r) => r.row.lane === "background" && r.row.toolUseId === toolCallId)
1988
+ .map((r) => r.row.settleId));
1989
+ }
1990
+ catch {
1991
+ preCallLaunchRows = undefined;
1992
+ }
1993
+ }
1923
1994
  const requested = params?.subagent_type;
1924
1995
  const external = delegationCallIsExternal({
1925
1996
  requestedType: typeof requested === "string" ? requested : undefined,
@@ -1931,7 +2002,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
1931
2002
  const att = readCardAttestation(result?.details);
1932
2003
  if (att === "external") {
1933
2004
  mark(`tool "${t.name}" returned the output of a delegated agent that invoked an external-content-class tool at runtime` +
1934
- (typeof requested === "string" ? ` (subagent_type "${requested}")` : ""));
2005
+ (typeof requested === "string" ? ` (subagent_type "${requested}")` : ""), "observed");
1935
2006
  recordExternal();
1936
2007
  }
1937
2008
  else if (att !== "clean") {
@@ -1939,9 +2010,38 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
1939
2010
  const staticFaceReason = `tool "${t.name}" returned the output of a delegated agent whose tool face can reach external content` +
1940
2011
  (typeof requested === "string" ? ` (subagent_type "${requested}")` : " (no subagent_type named — classified fail-closed)");
1941
2012
  if (!delegationEvidenceAttestedOnly) {
1942
- mark(staticFaceReason);
2013
+ mark(staticFaceReason, "static");
1943
2014
  }
1944
- else if (pollution !== undefined && !staticMarkWaiverAnnounced) {
2015
+ else {
2016
+ const receiptDetails = result?.details;
2017
+ const claimsLaunchReceipt = receiptDetails !== undefined && receiptDetails !== null && receiptDetails.status === "async_launched";
2018
+ const claimedSettleId = claimsLaunchReceipt && typeof receiptDetails.settle_id === "string" ? receiptDetails.settle_id : undefined;
2019
+ const settlementSeat = memoryEngineSession?.settlement;
2020
+ let isLaunchReceipt = false;
2021
+ if (claimsLaunchReceipt && settlementSeat !== undefined) {
2022
+ try {
2023
+ isLaunchReceipt =
2024
+ preCallLaunchRows !== undefined &&
2025
+ claimedSettleId !== undefined &&
2026
+ !preCallLaunchRows.has(claimedSettleId) &&
2027
+ sessionSettlements(settlementSeat.controlDir, settlementSeat.sessionId).some((r) => r.row.lane === "background" && r.row.settleId === claimedSettleId && r.row.toolUseId === toolCallId);
2028
+ }
2029
+ catch {
2030
+ isLaunchReceipt = false;
2031
+ }
2032
+ }
2033
+ if (!isLaunchReceipt && settlementSeat !== undefined) {
2034
+ try {
2035
+ recordSyncUnattestable(settlementSeat.controlDir, { sessionId: settlementSeat.sessionId, toolCallId, now: Date.now });
2036
+ }
2037
+ catch (err) {
2038
+ const e = new Error(`delegated output withheld (fail-closed): the delegation delivered without a provable attestation and the settlement account could not record the fact (${err instanceof Error ? err.message : String(err)}) — repair the memory control plane or retry`);
2039
+ e.code = "memory.settlement_record_failed";
2040
+ throw e;
2041
+ }
2042
+ }
2043
+ }
2044
+ if (delegationEvidenceAttestedOnly && pollution !== undefined && !staticMarkWaiverAnnounced) {
1945
2045
  staticMarkWaiverAnnounced = true;
1946
2046
  const waivedReason = inlineUntrusted(staticFaceReason, 200);
1947
2047
  deliverEngineNotice(deps.onNotice, {
@@ -2043,6 +2143,9 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
2043
2143
  centerAdoption = undefined;
2044
2144
  }
2045
2145
  let systemPrompt = assembled.systemPrompt;
2146
+ if (!systemPrompt.includes(reminderMarkDeclaration(reminderMark))) {
2147
+ deps.onError?.(new Error("reminder-mark declaration missing from the assembled system prompt: this run's PromptProvider owns the prompt and did not render the mark declaration, so engine <system-reminder> tags carry a mark the model is never told about (the impersonation defense is inactive for this deployment). Render `reminderMarkDeclaration(ctx.reminderMark)` (exported; the value rides StablePromptContext.reminderMark) in the provider, or accept the disclosure."), { phase: "config", sessionId });
2148
+ }
2046
2149
  const renderWithDate = assembled.renderWithDate
2047
2150
  ? (date) => {
2048
2151
  systemPrompt = assembled.renderWithDate(date);
@@ -3406,6 +3509,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
3406
3509
  consolidationNotes: undefined,
3407
3510
  readFileState: readFileStateForCheckpoint ? [...readFileStateForCheckpoint.entries()] : undefined,
3408
3511
  readFace: faceCheckpointSection(),
3512
+ reminderMark,
3409
3513
  repairBundle: repairBundleForCheckpoint(parkedSpendMicroUsd),
3410
3514
  workspaceHandle,
3411
3515
  handsCwd: handsCwdRef?.current,
@@ -4069,7 +4173,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
4069
4173
  if (notifyPermissionDenied) {
4070
4174
  await notifyPermissionDenied({ toolName: e.toolName, input: cloneObserverInput(e.input), toolCallId: e.toolCallId, reason: complianceDeny, source: "safety", identity: hookIdentity });
4071
4175
  }
4072
- return { block: true, reason: formatHookFeedback(complianceDeny), preToolContext: [] };
4176
+ return { block: true, reason: formatHookFeedback(complianceDeny, reminderMark), preToolContext: [] };
4073
4177
  }
4074
4178
  }
4075
4179
  if (planModeRef.active && (toolEffects.get(e.toolName) ?? "write") !== "read") {
@@ -4082,7 +4186,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
4082
4186
  }
4083
4187
  return {
4084
4188
  block: true,
4085
- reason: formatHookFeedback(planDenyReason),
4189
+ reason: formatHookFeedback(planDenyReason, reminderMark),
4086
4190
  preToolContext: [],
4087
4191
  };
4088
4192
  }
@@ -4092,6 +4196,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
4092
4196
  onNotifyError: (f) => emitTrace(deps.tracer, () => ({ kind: "observer.notify_failed", version: 1, taskId: spec.taskId ?? sessionId, site: f.site, message: f.error.message, ts: Date.now() })),
4093
4197
  event: e,
4094
4198
  identity: hookIdentity,
4199
+ reminderMark,
4095
4200
  preToolUse: ownGatePreToolUse,
4096
4201
  ...(hookEnvFace !== undefined ? { hookEnv: hookEnvFace } : {}),
4097
4202
  adjudicate,
@@ -4208,7 +4313,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
4208
4313
  details: clonedDetails,
4209
4314
  }, { toolCallId: e.toolCallId, toolName: e.toolName, ...(hookEnvFace !== undefined ? { env: hookEnvFace } : {}), identity: hookIdentity });
4210
4315
  if (patch?.additionalContext) {
4211
- content = [...content, { type: "text", text: formatHookFeedback(patch.additionalContext) }];
4316
+ content = [...content, { type: "text", text: formatHookFeedback(patch.additionalContext, reminderMark) }];
4212
4317
  changed = true;
4213
4318
  }
4214
4319
  }
@@ -4220,14 +4325,14 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
4220
4325
  changed = true;
4221
4326
  }
4222
4327
  if (patch?.additionalContext) {
4223
- content = [...content, { type: "text", text: formatHookFeedback(patch.additionalContext) }];
4328
+ content = [...content, { type: "text", text: formatHookFeedback(patch.additionalContext, reminderMark) }];
4224
4329
  changed = true;
4225
4330
  }
4226
4331
  }
4227
4332
  const pre = preToolContexts.get(e.toolCallId);
4228
4333
  if (pre) {
4229
4334
  preToolContexts.delete(e.toolCallId);
4230
- content = [...content, ...pre.map((t) => ({ type: "text", text: formatHookFeedback(t) }))];
4335
+ content = [...content, ...pre.map((t) => ({ type: "text", text: formatHookFeedback(t, reminderMark) }))];
4231
4336
  changed = true;
4232
4337
  }
4233
4338
  return changed ? { content } : undefined;
@@ -4501,7 +4606,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
4501
4606
  const effectiveReadFaceObserved = carrierReadFace();
4502
4607
  const effectiveReadDenyObserved = readDenyAdditionsNormalized.length > 0 ? readDenyAdditionsNormalized.map((e) => ({ ...e })) : undefined;
4503
4608
  const preparedHolder = {};
4504
- const buildPrepared = () => ({ harness, session, sessionId, taskRootPath: taskRootFinal, model, thinking, compModel, mcp: mcp, ...(a2a !== undefined && a2a.tools.length > 0 ? { a2a } : {}), blockedRef, outputRef, abortController, conflictRef, blockedToolCalls, approvalSettlement, nestedStats, ...(rewindNotes.length > 0 ? { rewindNotes } : {}), ...(effectiveReadFaceObserved !== undefined ? { effectiveReadFace: effectiveReadFaceObserved } : {}), ...(effectiveReadDenyObserved !== undefined ? { effectiveReadDenyPatterns: effectiveReadDenyObserved } : {}), effectiveMemoryScopes: memoryEffectiveScopes, cwdRef: handsCwdRef, ...(worktreeSessionRef !== undefined ? { worktreeSessionRef } : {}), ...(workspaceStateSettle !== undefined ? { workspaceStateSettle } : {}), denyNarrowingPolicy, ...(basePolicyForResumeEdit !== undefined ? { basePolicyForResumeEdit } : {}), ...(permissionRuleOrgLane !== undefined ? { permissionRuleOrg: permissionRuleOrgLane } : {}), releaseSignal, settleContentAskBindings, cacheBreakDetector, cacheFingerprint, wiringManifest, promptManifest, epochDeclaredSections, activeTools, ...(deferred.size > 0 ? { deferredToolNames: deferred } : {}), toolMaterializeStatic, deferDirectCall, ...(staticFaceForRef.current !== undefined ? { staticFaceFor: staticFaceForRef.current } : {}), ownedEnv, suspendRef, suspendProgressRef, reviewRef, remoteEnvFailures, reviewRequestRef, suspendLoopRef, suspendForResource, ...(suspendForPlatformLimit !== undefined ? { suspendForPlatformLimit } : {}), ...(envLifetimeSuspendAt !== undefined ? { envLifetimeSuspendAt } : {}), ...(usageGovernance !== undefined ? { usageGovernance } : {}), callIssuedAtRef, brainCallGuardrailRef, suspendForReview, resourceLedger: priorLedger, liveSpendRef, humanReviewRef, now, tools, toolEffects, wakeRecovered, promptOverheadTokens, lastBrainContext, readTaskFile, recentlyReadFiles, normalizeAttachmentPath, isDedupStubResult, ...(onCompactionApplied ? { onCompactionApplied } : {}), compactionReuseRef, trimPressureRef, ...(memoryEngineSession ? { memoryEngineSession } : {}), ...(subagentRetain ? { subagentRetain } : {}), ...(lspDiagnostics && nudgeLspOnEdit ? { lspDiagnostics: { registry: lspDiagnostics, nudge: nudgeLspOnEdit, runIdent: lspRunIdent } } : {}), planModeRef, ...(dateChange ? { dateChange } : {}), ...(instructionSources ? { instructionSources } : {}), ...(workflowSizeGuideline ? { workflowSizeGuideline } : {}), ...(detectExternalChanges ? { detectExternalChanges } : {}), ...(toolsDeltaRef ? { toolsDeltaRef } : {}), ...(agentListing ? { agentListing } : {}), ...(skillsListing ? { skillsListing } : {}), announcedListingsRef, gitStatusRef, listBackgroundTasks, hookIdentity, ...(turnSnapshotRef.current !== undefined ? { turnSnapshot: turnSnapshotRef.current } : {}), ...(centerCompactionCandidate !== undefined ? { centerCompactionCandidate } : {}) });
4609
+ const buildPrepared = () => ({ harness, session, sessionId, reminderMark, taskRootPath: taskRootFinal, model, thinking, compModel, mcp: mcp, ...(a2a !== undefined && a2a.tools.length > 0 ? { a2a } : {}), blockedRef, outputRef, abortController, conflictRef, blockedToolCalls, approvalSettlement, nestedStats, ...(rewindNotes.length > 0 ? { rewindNotes } : {}), ...(effectiveReadFaceObserved !== undefined ? { effectiveReadFace: effectiveReadFaceObserved } : {}), ...(effectiveReadDenyObserved !== undefined ? { effectiveReadDenyPatterns: effectiveReadDenyObserved } : {}), effectiveMemoryScopes: memoryEffectiveScopes, cwdRef: handsCwdRef, ...(worktreeSessionRef !== undefined ? { worktreeSessionRef } : {}), ...(workspaceStateSettle !== undefined ? { workspaceStateSettle } : {}), denyNarrowingPolicy, ...(basePolicyForResumeEdit !== undefined ? { basePolicyForResumeEdit } : {}), ...(permissionRuleOrgLane !== undefined ? { permissionRuleOrg: permissionRuleOrgLane } : {}), releaseSignal, settleContentAskBindings, cacheBreakDetector, cacheFingerprint, wiringManifest, promptManifest, epochDeclaredSections, activeTools, ...(deferred.size > 0 ? { deferredToolNames: deferred } : {}), toolMaterializeStatic, deferDirectCall, ...(staticFaceForRef.current !== undefined ? { staticFaceFor: staticFaceForRef.current } : {}), ownedEnv, suspendRef, suspendProgressRef, reviewRef, remoteEnvFailures, reviewRequestRef, suspendLoopRef, suspendForResource, ...(suspendForPlatformLimit !== undefined ? { suspendForPlatformLimit } : {}), ...(envLifetimeSuspendAt !== undefined ? { envLifetimeSuspendAt } : {}), ...(usageGovernance !== undefined ? { usageGovernance } : {}), callIssuedAtRef, brainCallGuardrailRef, suspendForReview, resourceLedger: priorLedger, liveSpendRef, humanReviewRef, now, tools, toolEffects, wakeRecovered, promptOverheadTokens, lastBrainContext, readTaskFile, recentlyReadFiles, normalizeAttachmentPath, isDedupStubResult, ...(onCompactionApplied ? { onCompactionApplied } : {}), compactionReuseRef, trimPressureRef, ...(memoryEngineSession ? { memoryEngineSession } : {}), ...(subagentRetain ? { subagentRetain } : {}), ...(lspDiagnostics && nudgeLspOnEdit ? { lspDiagnostics: { registry: lspDiagnostics, nudge: nudgeLspOnEdit, runIdent: lspRunIdent } } : {}), planModeRef, ...(dateChange ? { dateChange } : {}), ...(instructionSources ? { instructionSources } : {}), ...(workflowSizeGuideline ? { workflowSizeGuideline } : {}), ...(detectExternalChanges ? { detectExternalChanges } : {}), ...(toolsDeltaRef ? { toolsDeltaRef } : {}), ...(agentListing ? { agentListing } : {}), ...(skillsListing ? { skillsListing } : {}), announcedListingsRef, gitStatusRef, listBackgroundTasks, hookIdentity, ...(turnSnapshotRef.current !== undefined ? { turnSnapshot: turnSnapshotRef.current } : {}), ...(centerCompactionCandidate !== undefined ? { centerCompactionCandidate } : {}) });
4505
4610
  const prepared = buildPrepared();
4506
4611
  preparedHolder.current = prepared;
4507
4612
  return prepared;