@sema-agent/server 7.140.0 → 7.142.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 (296) hide show
  1. package/MIGRATION.md +505 -0
  2. package/README.md +1 -1
  3. package/README.zh-CN.md +1 -1
  4. package/USAGE.md +142 -25
  5. package/dist/approval-ask-audit-store.d.ts +54 -38
  6. package/dist/approval-ask-audit-store.js +58 -39
  7. package/dist/approval-batch-census.d.ts +27 -0
  8. package/dist/approval-batch-census.js +27 -0
  9. package/dist/approval-card.d.ts +39 -24
  10. package/dist/approval-card.js +6 -3
  11. package/dist/approval-crash-convergence.d.ts +17 -7
  12. package/dist/approval-crash-convergence.js +94 -22
  13. package/dist/approval-deny-reasons.d.ts +34 -30
  14. package/dist/approval-deny-reasons.js +21 -6
  15. package/dist/approval-policy-settlement.d.ts +1 -1
  16. package/dist/approval-reconciler.d.ts +33 -1
  17. package/dist/approval-reconciler.js +43 -40
  18. package/dist/approval.d.ts +15 -0
  19. package/dist/approval.js +10 -0
  20. package/dist/audit.d.ts +4 -2
  21. package/dist/audit.js +2 -2
  22. package/dist/auth-bridge.d.ts +9 -6
  23. package/dist/auth-bridge.js +9 -3
  24. package/dist/boot/adoption.js +2 -1
  25. package/dist/boot/budget-tracing.d.ts +16 -0
  26. package/dist/boot/budget-tracing.js +10 -6
  27. package/dist/boot/device-lane.d.ts +11 -0
  28. package/dist/boot/device-lane.js +16 -0
  29. package/dist/boot/engine-lease.d.ts +24 -3
  30. package/dist/boot/engine-lease.js +9 -2
  31. package/dist/boot/execution-env.d.ts +24 -4
  32. package/dist/boot/execution-env.js +34 -27
  33. package/dist/boot/execution-lane.js +2 -1
  34. package/dist/boot/exit-boundary.js +5 -4
  35. package/dist/boot/memory-boundary.d.ts +2 -2
  36. package/dist/boot/memory-consolidation.d.ts +1 -1
  37. package/dist/boot/memory-consolidation.js +3 -2
  38. package/dist/boot/parked-revive-gate.js +2 -1
  39. package/dist/boot/permission-rules-audit.d.ts +0 -28
  40. package/dist/boot/permission-rules-audit.js +2 -1
  41. package/dist/boot/read-deny-anchor-audit.js +2 -1
  42. package/dist/boot/reapers.d.ts +2 -2
  43. package/dist/boot/reapers.js +4 -3
  44. package/dist/boot/resolve-spec.js +18 -6
  45. package/dist/boot/retention-lane.js +5 -3
  46. package/dist/boot/runner-deps.js +16 -13
  47. package/dist/boot/runtime-caps.js +3 -2
  48. package/dist/boot/session-faces.d.ts +1 -1
  49. package/dist/boot/session-faces.js +8 -6
  50. package/dist/boot/shutdown.js +8 -2
  51. package/dist/boot/stage-04-stores.js +3 -2
  52. package/dist/boot/stage-05-execution-env.d.ts +1 -1
  53. package/dist/boot/stage-05-execution-env.js +11 -7
  54. package/dist/boot/stage-06-runners.d.ts +1 -3
  55. package/dist/boot/stage-06-runners.js +3 -2
  56. package/dist/boot/stage-07-capability-layer.d.ts +1 -2
  57. package/dist/boot/stage-07-capability-layer.js +10 -11
  58. package/dist/boot/stage-08-reapers.d.ts +1 -2
  59. package/dist/boot/stage-08-reapers.js +3 -2
  60. package/dist/boot/stage-09-leader.d.ts +1 -2
  61. package/dist/boot/stage-10-http-server.d.ts +1 -2
  62. package/dist/boot/stage-10-http-server.js +6 -4
  63. package/dist/boot/stores.js +13 -6
  64. package/dist/boot/web-admin.js +18 -17
  65. package/dist/boot/webfetch-summarize-lane.js +2 -1
  66. package/dist/boot/workflow-orchestration.js +3 -2
  67. package/dist/capabilities/builtin-tools.d.ts +2 -1
  68. package/dist/capabilities/builtin-tools.js +2 -4
  69. package/dist/capabilities/composite-members.d.ts +2 -1
  70. package/dist/capabilities/composite-members.js +2 -1
  71. package/dist/capabilities/scenarios.d.ts +1 -1
  72. package/dist/capability-facts.d.ts +33 -0
  73. package/dist/capability-facts.js +32 -0
  74. package/dist/card-void.d.ts +38 -0
  75. package/dist/card-void.js +23 -0
  76. package/dist/config-catalog.js +12 -8
  77. package/dist/config-provider.d.ts +13 -13
  78. package/dist/config-provider.js +19 -33
  79. package/dist/config-types.d.ts +39 -10
  80. package/dist/config.d.ts +6 -0
  81. package/dist/config.js +72 -49
  82. package/dist/delegated-session-owner.d.ts +21 -19
  83. package/dist/delegated-session-owner.js +1 -1
  84. package/dist/device-store.d.ts +7 -0
  85. package/dist/device-store.js +3 -0
  86. package/dist/execution-config-root.d.ts +22 -0
  87. package/dist/execution-config-root.js +35 -0
  88. package/dist/execution-lane-caps.d.ts +50 -2
  89. package/dist/execution-lane-caps.js +90 -13
  90. package/dist/execution-placement.d.ts +3 -0
  91. package/dist/execution-placement.js +7 -0
  92. package/dist/fleet/drain-entry.d.ts +3 -0
  93. package/dist/fleet/fleet-bus.d.ts +6 -3
  94. package/dist/hooks/hook-runner.d.ts +6 -0
  95. package/dist/hooks/hook-runner.js +30 -1
  96. package/dist/hosted-posture.d.ts +8 -0
  97. package/dist/hosted-posture.js +4 -0
  98. package/dist/http/admission.js +3 -3
  99. package/dist/http/caller-trust.d.ts +3 -2
  100. package/dist/http/caller-trust.js +2 -1
  101. package/dist/http/dispatch.js +8 -2
  102. package/dist/http/execution-context.d.ts +2 -2
  103. package/dist/http/idempotency.d.ts +1 -1
  104. package/dist/http/live-frame.d.ts +24 -0
  105. package/dist/http/live-frame.js +16 -0
  106. package/dist/http/principal-gate.d.ts +3 -1
  107. package/dist/http/principal-gate.js +17 -8
  108. package/dist/http/resume-legs.js +42 -29
  109. package/dist/http/route-table.js +4 -0
  110. package/dist/http/routes/approvals-assistant.js +1 -0
  111. package/dist/http/routes/attachments.js +18 -0
  112. package/dist/http/routes/capabilities.js +10 -6
  113. package/dist/http/routes/diagnostics.d.ts +0 -19
  114. package/dist/http/routes/diagnostics.js +16 -2
  115. package/dist/http/routes/memory-bundle.d.ts +2 -2
  116. package/dist/http/routes/memory-bundle.js +1 -1
  117. package/dist/http/routes/memory-compliance.js +1 -1
  118. package/dist/http/routes/memory-policy.js +27 -7
  119. package/dist/http/routes/run-permission-mode.d.ts +75 -0
  120. package/dist/http/routes/run-permission-mode.js +170 -0
  121. package/dist/http/routes/runs.js +3 -3
  122. package/dist/http/routes/session-memory-sync.d.ts +63 -0
  123. package/dist/http/routes/session-memory-sync.js +157 -0
  124. package/dist/http/routes/session-sync.d.ts +3 -6
  125. package/dist/http/routes/session-sync.js +7 -2
  126. package/dist/http/routes/sessions-list.d.ts +2 -1
  127. package/dist/http/routes/sessions.js +5 -4
  128. package/dist/http/routes/tasks.js +70 -71
  129. package/dist/http/run-read-face.d.ts +7 -0
  130. package/dist/http/run-read-face.js +10 -4
  131. package/dist/http/send.d.ts +6 -1
  132. package/dist/http/send.js +10 -3
  133. package/dist/http/server.d.ts +20 -7
  134. package/dist/http/server.js +2 -4
  135. package/dist/http/sse-log.d.ts +3 -8
  136. package/dist/http/stored-body-replay.d.ts +3 -3
  137. package/dist/http/stored-body-replay.js +3 -1
  138. package/dist/http/submit-replay.d.ts +4 -3
  139. package/dist/http/submit-replay.js +2 -2
  140. package/dist/http/sync-submit-body.d.ts +21 -4
  141. package/dist/http/sync-submit-body.js +13 -0
  142. package/dist/identity-source.d.ts +21 -2
  143. package/dist/identity-source.js +6 -0
  144. package/dist/instruction-source-notice.d.ts +7 -0
  145. package/dist/instruction-source-notice.js +6 -6
  146. package/dist/mcp-assertion-header.d.ts +4 -0
  147. package/dist/mcp-assertion-header.js +5 -0
  148. package/dist/memory-incident-sink.d.ts +19 -6
  149. package/dist/memory-incident-sink.js +8 -4
  150. package/dist/memory-posture.d.ts +1 -1
  151. package/dist/memory-scope.d.ts +4 -4
  152. package/dist/memory-scope.js +1 -1
  153. package/dist/memory-sync-client.d.ts +35 -23
  154. package/dist/memory-sync-client.js +122 -52
  155. package/dist/memory-sync-identity.d.ts +24 -0
  156. package/dist/memory-sync-identity.js +57 -0
  157. package/dist/memory-sync.d.ts +7 -1
  158. package/dist/memory-sync.js +6 -3
  159. package/dist/observability/fail-open.d.ts +57 -12
  160. package/dist/observability/fail-open.js +50 -9
  161. package/dist/observability/metrics.js +0 -1
  162. package/dist/observability/run-terminal.d.ts +93 -31
  163. package/dist/observability/run-terminal.js +175 -171
  164. package/dist/observability/secret-env-scrub.d.ts +20 -1
  165. package/dist/observability/secret-env-scrub.js +14 -0
  166. package/dist/orchestration/workflow-completion-inbox.d.ts +5 -2
  167. package/dist/orchestration/workflow-completion-inbox.js +13 -5
  168. package/dist/orchestration/workflow-notify-journal.d.ts +5 -3
  169. package/dist/orchestration/workflow-notify-journal.js +2 -1
  170. package/dist/permission-mode-admission.d.ts +68 -0
  171. package/dist/permission-mode-admission.js +23 -0
  172. package/dist/permission-rule-list.d.ts +55 -6
  173. package/dist/permission-rule-list.js +52 -5
  174. package/dist/plugins/approval-ask-store-file.d.ts +14 -4
  175. package/dist/plugins/approval-ask-store-file.js +48 -7
  176. package/dist/plugins/approval-ask-store-memory.d.ts +2 -1
  177. package/dist/plugins/approval-ask-store-memory.js +9 -8
  178. package/dist/plugins/approval-ask-store-sql.d.ts +42 -10
  179. package/dist/plugins/approval-ask-store-sql.js +49 -19
  180. package/dist/plugins/caching-session-store.d.ts +6 -0
  181. package/dist/plugins/caching-session-store.js +3 -0
  182. package/dist/plugins/checkpoint-store-sql.d.ts +65 -17
  183. package/dist/plugins/checkpoint-store-sql.js +74 -3
  184. package/dist/plugins/device-store-sql.d.ts +5 -2
  185. package/dist/plugins/device-store-sql.js +4 -1
  186. package/dist/plugins/execution-placement-sql.d.ts +11 -1
  187. package/dist/plugins/execution-placement-sql.js +12 -1
  188. package/dist/plugins/file-run-store.d.ts +7 -2
  189. package/dist/plugins/file-run-store.js +12 -2
  190. package/dist/plugins/fork-routing-session-store.d.ts +10 -32
  191. package/dist/plugins/fork-routing-session-store.js +2 -61
  192. package/dist/plugins/k8s-exec-protocol.d.ts +4 -1
  193. package/dist/plugins/k8s-exec-protocol.js +6 -1
  194. package/dist/plugins/local-checkpoint-store.d.ts +10 -1
  195. package/dist/plugins/local-checkpoint-store.js +22 -0
  196. package/dist/plugins/local-session-store.d.ts +260 -39
  197. package/dist/plugins/local-session-store.js +582 -57
  198. package/dist/plugins/local-session-window.d.ts +17 -3
  199. package/dist/plugins/local-session-window.js +7 -13
  200. package/dist/plugins/local-task-attachment-store.d.ts +12 -2
  201. package/dist/plugins/local-task-attachment-store.js +67 -43
  202. package/dist/plugins/memory-key-guards.d.ts +3 -3
  203. package/dist/plugins/memory-run-store.d.ts +7 -2
  204. package/dist/plugins/memory-run-store.js +12 -2
  205. package/dist/plugins/one-time-migrations.d.ts +68 -2
  206. package/dist/plugins/one-time-migrations.js +120 -4
  207. package/dist/plugins/pg-pool.js +3 -2
  208. package/dist/plugins/pg-session-storage.d.ts +2 -0
  209. package/dist/plugins/pg-session-storage.js +3 -2
  210. package/dist/plugins/remote-env-e2b.d.ts +47 -7
  211. package/dist/plugins/remote-env-e2b.js +242 -46
  212. package/dist/plugins/remote-env-k8s.d.ts +51 -6
  213. package/dist/plugins/remote-env-k8s.js +234 -44
  214. package/dist/plugins/remote-env-local-docker.d.ts +40 -14
  215. package/dist/plugins/remote-env-local-docker.js +127 -33
  216. package/dist/plugins/run-store-sql.d.ts +11 -3
  217. package/dist/plugins/run-store-sql.js +13 -4
  218. package/dist/plugins/sandbox-read-floor.d.ts +273 -0
  219. package/dist/plugins/sandbox-read-floor.js +608 -0
  220. package/dist/plugins/session-ownership.d.ts +2 -1
  221. package/dist/plugins/session-placement.d.ts +17 -4
  222. package/dist/plugins/session-placement.js +2 -1
  223. package/dist/plugins/session-store.d.ts +18 -20
  224. package/dist/plugins/session-store.js +4 -12
  225. package/dist/plugins/store-backend.d.ts +41 -7
  226. package/dist/plugins/store-backend.js +22 -4
  227. package/dist/plugins/store-contracts.d.ts +35 -3
  228. package/dist/plugins/store-contracts.js +3 -0
  229. package/dist/plugins/task-attachment-store.d.ts +112 -14
  230. package/dist/plugins/task-attachment-store.js +221 -28
  231. package/dist/plugins/tidb-pool.js +2 -1
  232. package/dist/plugins/tidb-session-store.d.ts +4 -1
  233. package/dist/plugins/tidb-session-store.js +3 -2
  234. package/dist/plugins/workspace-fill.d.ts +60 -0
  235. package/dist/plugins/workspace-fill.js +106 -0
  236. package/dist/project-bundle.d.ts +38 -0
  237. package/dist/project-bundle.js +609 -0
  238. package/dist/run-cancel-context.d.ts +34 -0
  239. package/dist/run-cancel-context.js +7 -0
  240. package/dist/run-local.js +2 -8
  241. package/dist/runs.d.ts +39 -12
  242. package/dist/runs.js +69 -55
  243. package/dist/sandbox-egress-policy.d.ts +4 -1
  244. package/dist/sandbox-egress-policy.js +3 -1
  245. package/dist/sandbox-git-plane.d.ts +31 -12
  246. package/dist/sandbox-git-plane.js +24 -4
  247. package/dist/security.d.ts +11 -2
  248. package/dist/security.js +8 -0
  249. package/dist/server-secret-env.d.ts +2 -1
  250. package/dist/server-secret-env.js +2 -4
  251. package/dist/session-error-wire.d.ts +46 -4
  252. package/dist/session-error-wire.js +23 -0
  253. package/dist/session-incarnation.d.ts +9 -3
  254. package/dist/session-sync-kernel.d.ts +42 -1
  255. package/dist/session-sync-kernel.js +17 -0
  256. package/dist/session-sync.js +16 -4
  257. package/dist/sql-engine-coordinates.d.ts +49 -0
  258. package/dist/sql-engine-coordinates.js +27 -0
  259. package/dist/standing-answer-grant.d.ts +31 -2
  260. package/dist/standing-answer-grant.js +14 -2
  261. package/dist/store-posture.d.ts +1 -1
  262. package/dist/task-a2a.d.ts +1 -1
  263. package/dist/task-mcp.d.ts +1 -1
  264. package/dist/task-settings.d.ts +62 -27
  265. package/dist/task-settings.js +105 -29
  266. package/dist/terminal.d.ts +97 -20
  267. package/dist/terminal.js +107 -18
  268. package/dist/tool-approval.d.ts +4 -3
  269. package/dist/tool-approval.js +12 -14
  270. package/dist/trace/core-keyset-guard.d.ts +196 -2
  271. package/dist/trace/engine-notice-wire.d.ts +8 -2
  272. package/dist/trace/engine-notice-wire.js +4 -2
  273. package/dist/trace/exit-seat.d.ts +9 -1
  274. package/dist/trace/exit-seat.js +1 -0
  275. package/dist/trace/ledger-sink.d.ts +8 -4
  276. package/dist/trace/ledger-sink.js +2 -2
  277. package/dist/trace/model-segment.d.ts +2 -2
  278. package/dist/trace/project.d.ts +18 -1
  279. package/dist/trace/project.js +16 -0
  280. package/dist/trace/redact.js +323 -90
  281. package/dist/trace/self-minted-wire.d.ts +419 -4
  282. package/dist/trace/self-minted-wire.js +145 -0
  283. package/dist/trace/wire-projection-faces.d.ts +1 -1
  284. package/dist/trace/wire-projection-faces.js +1 -1
  285. package/dist/verifier-pause-card.d.ts +8 -0
  286. package/dist/verifier-pause-card.js +19 -0
  287. package/dist/web-admin-client/apply-effective.d.ts +5 -7
  288. package/dist/web-admin-client/apply-effective.js +22 -2
  289. package/dist/web-admin-client/candidate-gate.d.ts +1 -1
  290. package/dist/web-admin-client/effective-keys.js +2 -0
  291. package/dist/web-admin-client/read-warnings.d.ts +2 -2
  292. package/dist/web-admin-client/types.d.ts +4 -0
  293. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +3 -2
  294. package/package.json +2 -2
  295. package/wire-changes/server@7.141.0.json +367 -0
  296. package/wire-changes/server@7.142.0.json +639 -0
@@ -1,27 +1,28 @@
1
1
  import { redactErrorMessage, redactHead, redactTerminalResult } from "../../observability/run-terminal.js";
2
2
  import { runWithVerification, runCascade, taskNotificationDedupKey, uuidv7 } from "@sema-agent/core";
3
3
  import { heldFor } from "../../peer-seat.js";
4
- import { graftParkToolCallId, markChildrenStoppedByUserOnAbort, syncRefusalHttpStatus, zeroWorkRefusalFacts, releaseKeyIfZeroWorkRefusal, createPromptCommitReader, HEARTBEAT_MS } from "../../runs.js";
4
+ import { graftParkToolCallId, markChildrenStoppedByUserOnAbort, syncRefusalHttpStatus, zeroWorkRefusalFacts, releaseKeyIfZeroWorkRefusal, createPromptCommitReader, settleResumeAnchor, HEARTBEAT_MS } from "../../runs.js";
5
5
  import { atHostBoundary, sealResultForExit, outwardPlane } from "../../terminal.js";
6
+ import { voidVerifierPauseCard } from "../../verifier-pause-card.js";
6
7
  import { withPrincipal } from "../../observability/principal-context.js";
7
8
  import { fleetRunPublisher, fleetRunLabels, fleetRunResiduals, isFleetAgentTerminalNotification } from "../../fleet/fleet-bus.js";
8
9
  import { defaultSubagentTailBus } from "../../fleet/subagent-tail-bus.js";
9
10
  import { createReasoningSegments, reasoningStreamOfTask } from "../../trace/model-segment.js";
10
11
  import { emitPendingWorkflowCompletions, taskNotificationInboxEntry, taskNotificationStreamKeyOf, NotifiedKeys } from "../../orchestration/workflow-completion-inbox.js";
11
- import { createLedgerSink, createLedgerTwinEmit } from "../../trace/ledger-sink.js";
12
+ import { createForwardAppendFailedNote, createLedgerSink, createLedgerTwinEmit } from "../../trace/ledger-sink.js";
12
13
  import { registerEngineNoticeLeg } from "../../trace/engine-notice-wire.js";
13
14
  import { clearTurnActivity, readTurnActivityMs, recordTurnActivity } from "../../turn-activity.js";
14
15
  import { buildCancelledLedgerRow, createRunAbort, mintCancelledResult } from "../../run-cancel-context.js";
15
16
  import { recordResourceWindow } from "../../resource-window.js";
16
17
  import { redactSecrets } from "../../trace/redact.js";
17
- import { liveToolEndForBacklog } from "../../trace/tool-output-media.js";
18
+ import { writeLiveFrame, writeLiveHeartbeat } from "../live-frame.js";
18
19
  import { contextUsageEventData, turnEndEventData, toolStartEventData, toolEndEventData, taskProgressEventData, taskStartedEventData, taskNotificationEventData, compactedEventData, diagnosticsEventData, brainStatusEventData, steeringInjectedEventData, compactionOutcomeEventData, compactionStartedEventData, workspaceChangedEventData, wiringManifestFaceEventData, toolRosterDeltaEventData, toolProgressEventData, toolDisclosureEventData, humanInputEventData, appendModelUsageDelta, attachModelUsage, textEndEventData, liveIdentityFields } from "../../trace/project.js";
19
20
  import { cascadeConfig, runMeta } from "../run-meta.js";
20
21
  import { idemCallerOf, inflightKeyOf, submissionIdemOf } from "../idempotency.js";
21
22
  import { replayOfExistingRun } from "../submit-replay.js";
22
23
  import { httpErrorCode, sendJson, sendError, sseHeaders } from "../send.js";
23
24
  import { collectSsePreamble } from "../sse-log.js";
24
- import { buildApprovalPreamble, buildApprovalPreambleSseFrames } from "../../approval-card.js";
25
+ import { buildApprovalPreamble } from "../../approval-card.js";
25
26
  import { approvalPreambleReplays, createApprovalCardEmitter, declaredApprovalFrameFamilies, resolveApprovalLeg, resolveStreamApprovalGate } from "../../tool-approval.js";
26
27
  import { buildActiveRunConflict, isActiveRunConflictBody, toDoneFrameResult } from "../active-run-conflict.js";
27
28
  import { commitExecutionContext } from "../execution-context.js";
@@ -42,12 +43,6 @@ import { refusalBody } from "../refusal-body.js";
42
43
  import { heldWorkflowParkDecisions } from "../../parked-decide.js";
43
44
  import { createSessionWorkspaceRecorder, legSessionWitnessOf, sessionWorkspaceStoreOf } from "../../session-workspace.js";
44
45
  const DISCONNECT_PARK_GRACE_MS = 10_000;
45
- function sseData(res, payload) {
46
- const anchor = payload.eventId;
47
- const idLine = typeof anchor === "string" && anchor.length > 0 ? `id: ${anchor}\n` : "";
48
- const frame = payload.type === "tool_end" ? liveToolEndForBacklog(payload, res.writableLength) : payload;
49
- res.write(`${idLine}data: ${JSON.stringify(frame)}\n\n`);
50
- }
51
46
  async function mintSubmitExitResult(result, checkpoints) {
52
47
  return redactTerminalResult(sealResultForExit(await graftParkToolCallId(result, checkpoints)));
53
48
  }
@@ -68,7 +63,7 @@ function sendSubmitResult(res, resp) {
68
63
  sendJson(res, 200, body);
69
64
  }
70
65
  function writeMetaFrame(res, taskId, sessionId, warnings) {
71
- res.write(`event: meta\ndata: ${JSON.stringify({ type: "meta", taskId, ...(sessionId ? { sessionId } : {}), ...(warnings !== undefined ? { warnings } : {}) })}\n\n`);
66
+ writeLiveFrame(res, { type: "meta", taskId, ...(sessionId ? { sessionId } : {}), ...(warnings !== undefined ? { warnings } : {}) });
72
67
  }
73
68
  function refusalDoneResult(body) {
74
69
  if (isActiveRunConflictBody(body))
@@ -116,7 +111,7 @@ export async function handleTasks(req, res, match, ctx) {
116
111
  if (liveStream && replay.status === 200) {
117
112
  sseHeaders(res, { "x-task-id": keyedRow.taskId });
118
113
  writeMetaFrame(res, keyedRow.taskId, keyedRow.sessionId);
119
- sseData(res, { type: "done", result: replay.body, replay: true });
114
+ writeLiveFrame(res, { type: "done", result: replay.body, replay: true });
120
115
  res.end();
121
116
  }
122
117
  else {
@@ -129,14 +124,14 @@ export async function handleTasks(req, res, match, ctx) {
129
124
  sseHeaders(res);
130
125
  const hb = setInterval(() => {
131
126
  if (!res.writableEnded)
132
- res.write(`event: heartbeat\ndata: {}\n\n`);
127
+ writeLiveHeartbeat(res);
133
128
  }, 15_000);
134
129
  hb.unref?.();
135
130
  res.on("close", () => clearInterval(hb));
136
131
  try {
137
132
  const resp = await cached;
138
133
  if (!res.writableEnded)
139
- sseData(res, { type: "done", result: doneResultOfOutcome(resp), replay: true });
134
+ writeLiveFrame(res, { type: "done", result: doneResultOfOutcome(resp), replay: true });
140
135
  }
141
136
  finally {
142
137
  clearInterval(hb);
@@ -260,18 +255,18 @@ export async function handleTasks(req, res, match, ctx) {
260
255
  deps.logger?.warn?.("approval_preamble_row_skipped", { sessionId: replaySessionId, skipped, face: "tasks.stream" });
261
256
  if (dropped > 0)
262
257
  deps.logger?.warn?.("approval_preamble_capped", { sessionId: replaySessionId, dropped, replayMax: deps.config.streamApproval.replayMax, face: "tasks.stream" });
263
- return buildApprovalPreambleSseFrames(frames);
258
+ return frames;
264
259
  }, (reason, err) => deps.logger?.warn?.("approval_preamble_failed", { sessionId: replaySessionId, reason, face: "tasks.stream", error: err instanceof Error ? err.message : String(err ?? "") }));
265
260
  if (!res.writableEnded && !res.destroyed) {
266
261
  for (const f of preambleFrames)
267
- res.write(`event: ${f.event}\ndata: ${JSON.stringify(f.data)}\n\n`);
262
+ writeLiveFrame(res, { ...f });
268
263
  if (deps.toolApproval && preambleFrames.length > 0) {
269
264
  for (const askId of presentedAskIds)
270
265
  presentedOnConnection.add(askId);
271
266
  const unwatch = deps.toolApproval.watchPresentedCards(presentedAskIds, (frame) => {
272
267
  if (res.writableEnded || res.destroyed || !admitPresentedComplete(frame.askId))
273
268
  return;
274
- res.write(`event: ${frame.type}\ndata: ${JSON.stringify(frame)}\n\n`);
269
+ writeLiveFrame(res, { ...frame });
275
270
  });
276
271
  res.once("close", unwatch);
277
272
  }
@@ -279,7 +274,7 @@ export async function handleTasks(req, res, match, ctx) {
279
274
  }
280
275
  const hb = setInterval(() => {
281
276
  if (!res.writableEnded && !res.destroyed)
282
- res.write(`event: heartbeat\ndata: {}\n\n`);
277
+ writeLiveHeartbeat(res);
283
278
  }, 15_000);
284
279
  hb.unref?.();
285
280
  let ranLive = false;
@@ -294,13 +289,14 @@ export async function handleTasks(req, res, match, ctx) {
294
289
  let userMsgEntryId;
295
290
  const promptCommit = createPromptCommitReader();
296
291
  let anchorPut = false;
297
- const putRewindAnchor = () => {
298
- if (anchorPut || !userMsgEntryId || !durableTaskId || !deps.resumeAnchorStore)
292
+ const putRewindAnchor = async () => {
293
+ const store = deps.resumeAnchorStore;
294
+ const key = durableTaskId;
295
+ const entryId = userMsgEntryId;
296
+ if (anchorPut || !entryId || !key || !store)
299
297
  return;
300
298
  anchorPut = true;
301
- void deps.resumeAnchorStore
302
- .put(prepared.spec.sessionId, durableTaskId, userMsgEntryId, principal ?? null)
303
- .catch(() => deps.metrics?.inc("resume_anchor_capture_failed"));
299
+ await settleResumeAnchor(() => store.put(prepared.spec.sessionId, key, entryId, principal ?? null), { leg: "stream", kind: "prompt" });
304
300
  };
305
301
  if (deps.runStore) {
306
302
  const tid = earlyDurableTid ?? uuidv7();
@@ -311,23 +307,23 @@ export async function handleTasks(req, res, match, ctx) {
311
307
  recordResourceWindow(tid, prepared.spec.resourceSuspend);
312
308
  if (created.existing) {
313
309
  const replay = await replayOfExistingRun(created.existing, { principal: submitter, idem }, "sync", deps, deps.runStore);
314
- sseData(res, { type: "done", result: doneResultOfOutcome(replay), replay: true });
310
+ writeLiveFrame(res, { type: "done", result: doneResultOfOutcome(replay), replay: true });
315
311
  return replay;
316
312
  }
317
313
  if (created.sessionAbsent) {
318
314
  const refused = rootSessionAbsentAnswer();
319
- sseData(res, { type: "done", result: doneResultOfOutcome(refused) });
315
+ writeLiveFrame(res, { type: "done", result: doneResultOfOutcome(refused) });
320
316
  return refused;
321
317
  }
322
318
  if (!created.ok) {
323
319
  const conflict = await buildActiveRunConflict({ runStore: deps.runStore, checkpointStore: deps.checkpointStore, governance: deps.config, runStaleSec: deps.config.runStaleSec, turnActivity: readTurnActivityMs }, prepared.spec.sessionId, created.activeTaskId);
324
320
  const refused = { status: 409, body: conflict };
325
- sseData(res, { type: "done", result: doneResultOfOutcome(refused) });
321
+ writeLiveFrame(res, { type: "done", result: doneResultOfOutcome(refused) });
326
322
  return refused;
327
323
  }
328
324
  const placementReject = await commitExecutionContext(deps, { kind: "run", runStore: deps.runStore, taskId: tid }, prepared.execution);
329
325
  if (placementReject) {
330
- sseData(res, { type: "done", result: doneResultOfOutcome(placementReject) });
326
+ writeLiveFrame(res, { type: "done", result: doneResultOfOutcome(placementReject) });
331
327
  return placementReject;
332
328
  }
333
329
  durableTaskId = tid;
@@ -335,7 +331,7 @@ export async function handleTasks(req, res, match, ctx) {
335
331
  if (deps.checkpointStore) {
336
332
  const ctxRefusal = await persistSubmitCtx(deps.checkpointStore, deps, durableTaskId !== undefined && deps.runStore ? { runStore: deps.runStore, taskId: durableTaskId } : undefined, prepared.spec.sessionId, { body: prepared.body, memoryScope: prepared.auth?.memoryScope, writerVersion: serviceVersion() });
337
333
  if (ctxRefusal) {
338
- sseData(res, { type: "done", result: doneResultOfOutcome(ctxRefusal) });
334
+ writeLiveFrame(res, { type: "done", result: doneResultOfOutcome(ctxRefusal) });
339
335
  return ctxRefusal;
340
336
  }
341
337
  }
@@ -346,7 +342,7 @@ export async function handleTasks(req, res, match, ctx) {
346
342
  if (durableTaskId && deps.runStore) {
347
343
  const rs = deps.runStore;
348
344
  const tid = durableTaskId;
349
- ledgerSink = createLedgerSink({ appendEvent: (seq, type, data) => rs.appendEvent(tid, seq, type, data), persistThinking: deps.config.traceThinking, onActivity: (kind, statusData) => recordTurnActivity(tid, kind, statusData), legSections: legWiringSections });
345
+ ledgerSink = createLedgerSink({ appendEvent: (seq, type, data) => rs.appendEvent(tid, seq, type, data), persistThinking: deps.config.traceThinking, onActivity: (kind, statusData) => recordTurnActivity(tid, kind, statusData), legSections: legWiringSections, usage: { modelUsage: deps.modelUsage, taskId: tid } });
350
346
  usageKey = tid;
351
347
  deps.modelUsage?.register(tid);
352
348
  const owner = principal ?? null;
@@ -404,10 +400,11 @@ export async function handleTasks(req, res, match, ctx) {
404
400
  ...(prepared.engineNotices !== undefined ? { pending: prepared.engineNotices } : {}),
405
401
  live: (row) => {
406
402
  if (res.writableEnded || res.destroyed) {
407
- recordFailOpen(failOpenTagForDroppedFrame("engine_notice"), "frame=engine_notice");
403
+ if (noticeLedger === undefined)
404
+ recordFailOpen(failOpenTagForDroppedFrame("engine_notice"), "frame=engine_notice");
408
405
  return;
409
406
  }
410
- sseData(res, { type: "engine_notice", ...row });
407
+ writeLiveFrame(res, { type: "engine_notice", ...row });
411
408
  },
412
409
  ...(noticeLedger
413
410
  ? {
@@ -437,34 +434,34 @@ export async function handleTasks(req, res, match, ctx) {
437
434
  if (res.writableEnded)
438
435
  return;
439
436
  for (const end of childReasoning.onEvent(e))
440
- sseData(res, end);
437
+ writeLiveFrame(res, end);
441
438
  const t = e.type;
442
439
  if (t === "task_progress") {
443
- sseData(res, { type: "task_progress", ...taskProgressEventData(e) });
440
+ writeLiveFrame(res, { type: "task_progress", ...taskProgressEventData(e) });
444
441
  }
445
442
  else if (t === "task_started") {
446
- sseData(res, { type: "task_started", ...taskStartedEventData(e) });
443
+ writeLiveFrame(res, { type: "task_started", ...taskStartedEventData(e) });
447
444
  }
448
445
  else if (t === "tool_start") {
449
446
  const tsv = e;
450
- sseData(res, { type: "tool_start", ...toolStartEventData(tsv) });
447
+ writeLiveFrame(res, { type: "tool_start", ...toolStartEventData(tsv) });
451
448
  }
452
449
  else if (t === "tool_end") {
453
450
  const te = e;
454
- sseData(res, { type: "tool_end", ...toolEndEventData(te) });
451
+ writeLiveFrame(res, { type: "tool_end", ...toolEndEventData(te) });
455
452
  }
456
453
  else if (t === "text_delta") {
457
454
  const td = e;
458
- sseData(res, { type: "text_delta", delta: td.delta, ...(td.eventId ? { eventId: td.eventId } : {}), ...(td.parentToolCallId ? { parentToolCallId: td.parentToolCallId } : {}) });
455
+ writeLiveFrame(res, { type: "text_delta", delta: td.delta, ...(td.eventId ? { eventId: td.eventId } : {}), ...(td.parentToolCallId ? { parentToolCallId: td.parentToolCallId } : {}) });
459
456
  }
460
457
  else if (t === "text_end") {
461
458
  const tend = textEndEventData(e);
462
459
  if (tend !== null)
463
- sseData(res, { type: "text_end", ...tend });
460
+ writeLiveFrame(res, { type: "text_end", ...tend });
464
461
  }
465
462
  else if (t === "reasoning_delta") {
466
463
  const rd = e;
467
- sseData(res, { type: "reasoning_delta", delta: redactSecrets(rd.delta), ...(rd.eventId ? { eventId: rd.eventId } : {}), ...(rd.parentToolCallId ? { parentToolCallId: rd.parentToolCallId } : {}) });
464
+ writeLiveFrame(res, { type: "reasoning_delta", delta: redactSecrets(rd.delta), ...(rd.eventId ? { eventId: rd.eventId } : {}), ...(rd.parentToolCallId ? { parentToolCallId: rd.parentToolCallId } : {}) });
468
465
  }
469
466
  },
470
467
  onTaskNotification: (n, opts) => {
@@ -472,7 +469,7 @@ export async function handleTasks(req, res, match, ctx) {
472
469
  return;
473
470
  if (!res.writableEnded)
474
471
  for (const end of childReasoning.cut(reasoningStreamOfTask(n.task_id, n.sessionId)))
475
- sseData(res, end);
472
+ writeLiveFrame(res, end);
476
473
  defaultSubagentTailBus.forgetHandle(n.task_id);
477
474
  if (defaultSubagentTailBus.hasSubscribers(n.task_id)) {
478
475
  defaultSubagentTailBus.publish(n.task_id, { type: "task_settled", taskId: n.task_id, status: n.status, ...(typeof n.seq === "number" ? { seq: n.seq } : {}), ...(n.summary ? { summary: redactSecrets(n.summary) } : {}) });
@@ -488,7 +485,7 @@ export async function handleTasks(req, res, match, ctx) {
488
485
  const key = taskNotificationDedupKey(n);
489
486
  if (syncNotifiedKeys.get(key) === undefined) {
490
487
  syncNotifiedKeys.set(key, Promise.resolve(true));
491
- sseData(res, { type: "task_notification", ...taskNotificationEventData({ notification: n, ...(opts?.priority !== undefined ? { priority: opts.priority } : {}) }) });
488
+ writeLiveFrame(res, { type: "task_notification", ...taskNotificationEventData({ notification: n, ...(opts?.priority !== undefined ? { priority: opts.priority } : {}) }) });
492
489
  }
493
490
  }
494
491
  },
@@ -505,13 +502,13 @@ export async function handleTasks(req, res, match, ctx) {
505
502
  void heldFor(prepared.peerLease, () => Promise.allSettled([Promise.resolve().then(() => liveStream.result())]));
506
503
  if (durableTaskId)
507
504
  steerableRuns.set(durableTaskId, liveStream);
508
- prepared.acceptance.attachStream({ reachable: () => !closed && !res.writableEnded && !res.destroyed, write: (frame) => sseData(res, { ...frame }) });
505
+ prepared.acceptance.attachStream({ reachable: () => !closed && !res.writableEnded && !res.destroyed, write: (frame) => writeLiveFrame(res, { ...frame }) });
509
506
  const liveWorkspace = createSessionWorkspaceRecorder(sessionWorkspaceStoreOf(deps.sessionStorage), legSessionWitnessOf(prepared.spec));
510
507
  for await (const ev of liveStream) {
511
508
  if (closed)
512
509
  break;
513
510
  for (const end of ev.type === "done" ? [...childReasoning.cut(), ...topReasoning.cut()] : topReasoning.onEvent(ev))
514
- sseData(res, end);
511
+ writeLiveFrame(res, end);
515
512
  const promptEntryId = promptCommit(ev);
516
513
  if (promptEntryId !== undefined)
517
514
  userMsgEntryId = promptEntryId;
@@ -528,7 +525,7 @@ export async function handleTasks(req, res, match, ctx) {
528
525
  }
529
526
  finalizeTaskResult(ev.result, principal, prepared.spec.objective);
530
527
  noteRunOutcome(finalResult);
531
- putRewindAnchor();
528
+ await putRewindAnchor();
532
529
  settleFleet(outwardPlane(finalResult.terminal).status, fleetRunResiduals(finalResult));
533
530
  if (ledgerSink && finalResult) {
534
531
  if (usageKey && deps.modelUsage && deps.runStore && durableTaskId) {
@@ -540,7 +537,7 @@ export async function handleTasks(req, res, match, ctx) {
540
537
  await ledgerSink.onDone(finalResult);
541
538
  ledgerTerminal = true;
542
539
  }
543
- sseData(res, { ...ev, result: finalResult });
540
+ writeLiveFrame(res, { ...ev, result: finalResult });
544
541
  continue;
545
542
  }
546
543
  if (ledgerSink) {
@@ -552,15 +549,15 @@ export async function handleTasks(req, res, match, ctx) {
552
549
  if (ev.type === "status")
553
550
  deps.metrics?.inc("brain_retry_total", { phase: String(ev.phase) });
554
551
  if (ev.type === "status") {
555
- sseData(res, { type: "status", ...brainStatusEventData(ev) });
552
+ writeLiveFrame(res, { type: "status", ...brainStatusEventData(ev) });
556
553
  }
557
554
  else if (ev.type === "tool_end") {
558
555
  const te = ev;
559
- sseData(res, { type: "tool_end", ...toolEndEventData(te) });
556
+ writeLiveFrame(res, { type: "tool_end", ...toolEndEventData(te) });
560
557
  }
561
558
  else if (ev.type === "tool_start") {
562
559
  const tsv = ev;
563
- sseData(res, { type: "tool_start", ...toolStartEventData(tsv) });
560
+ writeLiveFrame(res, { type: "tool_start", ...toolStartEventData(tsv) });
564
561
  }
565
562
  else if (ev.type === "task_notification") {
566
563
  const tnv = ev.notification;
@@ -569,58 +566,58 @@ export async function handleTasks(req, res, match, ctx) {
569
566
  if (tnvPrior === undefined || !(await tnvPrior)) {
570
567
  if (tnvKey !== undefined)
571
568
  syncNotifiedKeys.set(tnvKey, Promise.resolve(true));
572
- sseData(res, { type: "task_notification", ...taskNotificationEventData(ev) });
569
+ writeLiveFrame(res, { type: "task_notification", ...taskNotificationEventData(ev) });
573
570
  }
574
571
  }
575
572
  else if (ev.type === "reasoning_delta" && typeof ev.delta === "string") {
576
- sseData(res, { type: "reasoning_delta", delta: redactSecrets(ev.delta), ...(ev.eventId ? { eventId: ev.eventId } : {}), ...(ev.parentToolCallId ? { parentToolCallId: ev.parentToolCallId } : {}) });
573
+ writeLiveFrame(res, { type: "reasoning_delta", delta: redactSecrets(ev.delta), ...(ev.eventId ? { eventId: ev.eventId } : {}), ...(ev.parentToolCallId ? { parentToolCallId: ev.parentToolCallId } : {}) });
577
574
  }
578
575
  else if (ev.type === "task_progress") {
579
- sseData(res, { type: "task_progress", ...taskProgressEventData(ev) });
576
+ writeLiveFrame(res, { type: "task_progress", ...taskProgressEventData(ev) });
580
577
  }
581
578
  else if (ev.type === "task_started") {
582
- sseData(res, { type: "task_started", ...taskStartedEventData(ev) });
579
+ writeLiveFrame(res, { type: "task_started", ...taskStartedEventData(ev) });
583
580
  }
584
581
  else if (ev.type === "compacted") {
585
- sseData(res, { type: "compacted", ...compactedEventData(ev) });
582
+ writeLiveFrame(res, { type: "compacted", ...compactedEventData(ev) });
586
583
  }
587
584
  else if (ev.type === "diagnostics") {
588
- sseData(res, { type: "diagnostics", ...diagnosticsEventData(ev) });
585
+ writeLiveFrame(res, { type: "diagnostics", ...diagnosticsEventData(ev) });
589
586
  }
590
587
  else if (ev.type === "steering_injected") {
591
- sseData(res, { type: "steering_injected", ...steeringInjectedEventData(ev) });
588
+ writeLiveFrame(res, { type: "steering_injected", ...steeringInjectedEventData(ev) });
592
589
  }
593
590
  else if (ev.type === "workspace_changed") {
594
- sseData(res, { type: "workspace_changed", ...workspaceChangedEventData(ev) });
591
+ writeLiveFrame(res, { type: "workspace_changed", ...workspaceChangedEventData(ev) });
595
592
  }
596
593
  else if (ev.type === "compaction_outcome") {
597
- sseData(res, { type: "compaction_outcome", ...compactionOutcomeEventData(ev) });
594
+ writeLiveFrame(res, { type: "compaction_outcome", ...compactionOutcomeEventData(ev) });
598
595
  }
599
596
  else if (ev.type === "compaction_started") {
600
- sseData(res, { type: "compaction_started", ...compactionStartedEventData(ev) });
597
+ writeLiveFrame(res, { type: "compaction_started", ...compactionStartedEventData(ev) });
601
598
  }
602
599
  else if (ev.type === "wiring_manifest") {
603
600
  const wiringFace = wiringManifestFaceEventData(ev, wiringOperatorFace, legWiringSections());
604
601
  wiringReceipt ??= wiringFace;
605
- sseData(res, { type: "wiring_manifest", ...wiringFace });
602
+ writeLiveFrame(res, { type: "wiring_manifest", ...wiringFace });
606
603
  }
607
604
  else if (ev.type === "tool_roster_delta") {
608
605
  const rosterDelta = toolRosterDeltaEventData(ev);
609
606
  if (rosterDelta !== undefined)
610
- sseData(res, { type: "tool_roster_delta", ...rosterDelta });
607
+ writeLiveFrame(res, { type: "tool_roster_delta", ...rosterDelta });
611
608
  }
612
609
  else if (ev.type === "tool_progress") {
613
610
  const progress = toolProgressEventData(ev);
614
611
  if (progress !== undefined)
615
- sseData(res, { type: "tool_progress", ...progress });
612
+ writeLiveFrame(res, { type: "tool_progress", ...progress });
616
613
  }
617
614
  else if (ev.type === "tool_disclosure") {
618
615
  const disclosure = toolDisclosureEventData(ev);
619
616
  if (disclosure !== undefined)
620
- sseData(res, { type: "tool_disclosure", ...disclosure });
617
+ writeLiveFrame(res, { type: "tool_disclosure", ...disclosure });
621
618
  }
622
619
  else if (ev.type === "human_input") {
623
- sseData(res, { type: "human_input", ...humanInputEventData(ev) });
620
+ writeLiveFrame(res, { type: "human_input", ...humanInputEventData(ev) });
624
621
  }
625
622
  else if (ev.type === "text_delta" || ev.type === "text_end" || ev.type === "turn_end" || ev.type === "message_committed" || ev.type === "context_usage") {
626
623
  const e = ev;
@@ -637,10 +634,10 @@ export async function handleTasks(req, res, match, ctx) {
637
634
  ? { type: "message_committed", entryId: e.entryId, role: e.role, ...(e.toolCallId !== undefined ? { toolCallId: e.toolCallId } : {}), ...ident }
638
635
  : { type: "context_usage", ...contextUsageEventData(ev), ...ident };
639
636
  if (arm !== null)
640
- sseData(res, arm);
637
+ writeLiveFrame(res, arm);
641
638
  }
642
639
  else {
643
- sseData(res, { ...ev });
640
+ writeLiveFrame(res, { ...ev });
644
641
  }
645
642
  }
646
643
  });
@@ -652,7 +649,7 @@ export async function handleTasks(req, res, match, ctx) {
652
649
  recordFailOpen(failOpenTagForDroppedFrame(frame.type), `frame=${frame.type}`);
653
650
  return;
654
651
  }
655
- res.write(`event: ${frame.type}\ndata: ${JSON.stringify(frame)}\n\n`);
652
+ writeLiveFrame(res, { ...frame });
656
653
  };
657
654
  const faceAlive = () => !res.writableEnded && !res.destroyed;
658
655
  const emitElicitation = createLedgerTwinEmit({ sink: ledgerSink, writeLive: emitAsk, liveReachable: faceAlive });
@@ -669,7 +666,7 @@ export async function handleTasks(req, res, match, ctx) {
669
666
  const fKey = f.type === "task_notification" ? taskNotificationStreamKeyOf(f) : undefined;
670
667
  if (fKey !== undefined)
671
668
  syncNotifiedKeys.set(fKey, Promise.resolve(true));
672
- sseData(res, frame);
669
+ writeLiveFrame(res, frame);
673
670
  }, { route: "sync-stream-open", connection: "live-sse", log: (m, x) => deps.logger?.info?.(m, x) });
674
671
  const withElicit = deps.elicitation
675
672
  ? () => deps.elicitation.runWithContext({ taskId: askTaskId, owner: askOwner, emit: emitElicitation, abortSignal: ac.signal }, streamBody)
@@ -746,10 +743,11 @@ export async function handleTasks(req, res, match, ctx) {
746
743
  ? deps.sendUserFile.runWithContext({
747
744
  taskId: askTaskId,
748
745
  emit: async (f) => {
749
- void (await emitAsk(f));
746
+ if (ledgerSink === undefined || faceAlive())
747
+ void (await emitAsk(f));
750
748
  if (ledgerSink) {
751
749
  const { type, ...rest } = f;
752
- await ledgerSink.append(type, rest).catch(() => undefined);
750
+ await ledgerSink.append(type, rest).catch(createForwardAppendFailedNote(type));
753
751
  }
754
752
  },
755
753
  }, withApproval)
@@ -765,7 +763,7 @@ export async function handleTasks(req, res, match, ctx) {
765
763
  await releaseKeyIfZeroWorkRefusal(deps.runStore, durableTaskId, finalResult);
766
764
  }
767
765
  else {
768
- putRewindAnchor();
766
+ await putRewindAnchor();
769
767
  const pending = await deps.checkpointStore?.findPendingTokenBySession(prepared.spec.sessionId);
770
768
  const dcCause = ac.cause();
771
769
  if (pending) {
@@ -885,7 +883,7 @@ export async function handleTasks(req, res, match, ctx) {
885
883
  deps.modelUsage?.clear(usageKey);
886
884
  }
887
885
  if (!ranLive && resp && !res.writableEnded) {
888
- sseData(res, { type: "done", result: doneResultOfOutcome(resp), replay: true });
886
+ writeLiveFrame(res, { type: "done", result: doneResultOfOutcome(resp), replay: true });
889
887
  }
890
888
  res.end();
891
889
  }
@@ -979,6 +977,7 @@ export async function handleTasks(req, res, match, ctx) {
979
977
  inflightRuns.delete(durableTaskId);
980
978
  }
981
979
  const syncAbortCause = syncCancelCtrl.cause();
980
+ await voidVerifierPauseCard(result, deps.checkpointStore);
982
981
  if (syncAbortCause !== undefined) {
983
982
  result = mintCancelledResult({
984
983
  taskId: durableTaskId ?? "",
@@ -5,6 +5,13 @@ import type { ServiceConfig } from "../config-types.js";
5
5
  export interface RunFaceDeps {
6
6
  config: Pick<ServiceConfig, "runStaleSec" | "infraCostRates">;
7
7
  }
8
+ /** 一条行是不是「看起来失联」:盘上 `running`、而最后一次心跳早于 `runStaleSec` —— 读面把它折成 `failed`(`run.stalled`)。读它的人只此一只判据(读面与同步重放回执同读)。 */
9
+ export declare function runRowStale(deps: RunFaceDeps, run: RunRecord): boolean;
10
+ /**
11
+ * 一条行上的结果**当作出口结果读**(封口 + 脱敏的读入口)—— 读面的 `result` 与同步提交的重放体读的是同一只:
12
+ * 终局行按 taskId+updatedAt 记忆的读入口,非终局行(停驻 / 在跑)走店入口那一套封口的读入口;行上没有结果 ⇒ `undefined`。
13
+ */
14
+ export declare function runRowExitResult(run: RunRecord): import("../plugins/store-contracts.js").PersistedTaskResult | undefined;
8
15
  export declare function readRunFace(deps: RunFaceDeps, runStore: RunStore, run: RunRecord): Promise<{
9
16
  result: import("../plugins/store-contracts.js").PersistedTaskResult | undefined;
10
17
  supervisorCost: import("../observability/cost-taxonomy.js").SupervisorCostBreakdown | undefined;
@@ -1,13 +1,19 @@
1
1
  import { persistedPlaneOf } from "../terminal.js";
2
- import { memoRedactedRead, memoRedactTerminalResult, redactErrorMessage, redactTerminalResult } from "../observability/run-terminal.js";
2
+ import { memoRedactedRead, memoRedactTerminalResult, redactErrorMessage, sealStoredRunRowResult } from "../observability/run-terminal.js";
3
3
  import { RUN_HOLDER_DEATH_CODES, isTerminalRunStatus } from "../plugins/store-contracts.js";
4
4
  import { composeSupervisorCost, infraCost, infraUsageFromEvents, hasInfraPricing } from "../observability/cost-taxonomy.js";
5
5
  import { recordFailOpen } from "../observability/fail-open.js";
6
6
  import { readTurnActivityMs } from "../turn-activity.js";
7
7
  import { buildCrossSliceUsage, readResourceWindow } from "../resource-window.js";
8
+ export function runRowStale(deps, run) {
9
+ return run.status === "running" && Date.now() - new Date(run.updatedAt).getTime() > deps.config.runStaleSec * 1000;
10
+ }
11
+ export function runRowExitResult(run) {
12
+ return isTerminalRunStatus(run.status) ? memoRedactTerminalResult("run.result", run.result ?? undefined) : (sealStoredRunRowResult(run.result ?? null, "run.result") ?? undefined);
13
+ }
8
14
  export async function readRunFace(deps, runStore, run) {
9
15
  const taskId = run.taskId;
10
- const stale = run.status === "running" && Date.now() - new Date(run.updatedAt).getTime() > deps.config.runStaleSec * 1000;
16
+ const stale = runRowStale(deps, run);
11
17
  const infraRates = deps.config.infraCostRates;
12
18
  const needCost = Boolean(run.result?.stats && !stale && infraRates && hasInfraPricing(infraRates));
13
19
  const needSuggestions = !stale && run.status === "completed";
@@ -53,14 +59,14 @@ export async function readRunFace(deps, runStore, run) {
53
59
  status: stale ? "failed" : run.status,
54
60
  ...(lastActivityAt !== undefined ? { msSinceLastActivity: Math.max(0, Date.now() - lastActivityAt) } : {}),
55
61
  ...(crossSliceUsage !== undefined ? { crossSliceUsage } : {}),
56
- result: isTerminalRunStatus(run.status) ? memoRedactTerminalResult("run.result", run.result ?? undefined) : redactTerminalResult(run.result ?? undefined),
62
+ result: runRowExitResult(run),
57
63
  supervisorCost,
58
64
  suggestions,
59
65
  errorCode: stale ? RUN_HOLDER_DEATH_CODES.stalled : (persistedPlaneOf(run.result).errorCode ?? run.errorCode ?? undefined),
60
66
  error: stale ? "run stalled (instance lost?)" : isTerminalRunStatus(run.status) ? memoRedactedRead("run.error", run.error ?? undefined, redactErrorMessage) : redactErrorMessage(run.error ?? undefined),
61
67
  jobId: run.jobId ?? undefined,
62
68
  source: run.source ?? undefined,
63
- heldBy: run.instanceId ?? null,
69
+ heldBy: isTerminalRunStatus(run.status) ? null : (run.instanceId ?? null),
64
70
  cancelRequested: run.cancelRequested,
65
71
  };
66
72
  }
@@ -113,7 +113,7 @@ export declare function sendHttpError(res: ServerResponse, e: HttpError): void;
113
113
  */
114
114
  export declare function sendSessionPolicyError(res: ServerResponse, e: unknown, sentencePrefix?: string): boolean;
115
115
  /**
116
- * [ref] —— core `SessionError` → 应答,经 {@link sessionErrorHttp} 那**一只**映射(`src/session-error-wire.ts`)。
116
+ * [ref] —— core `SessionError` → 应答,经 {@link sessionErrorWireOf} 那**一只**映射(`src/session-error-wire.ts`;本服务自铸的同码具名拒按型先认,其余按码)。
117
117
  * 回 `true` = 已应答,调用点 `return`;`false` = 不是 `SessionError`,或这个词在这一面上是登记过的留白(站点的既有
118
118
  * 处置照旧 —— 通常是继续上抛到全局兜底)。
119
119
  *
@@ -123,6 +123,11 @@ export declare function sendSessionPolicyError(res: ServerResponse, e: unknown,
123
123
  * (路径只进运维面:`server.session-repo.corrupt-record-skipped` 的探针行,[ref];SQL 两店走各自的拒绝句)。
124
124
  */
125
125
  export declare function sendSessionError(res: ServerResponse, e: unknown, face: SessionErrorFace): boolean;
126
+ /**
127
+ * 全局兜底的 open 面一臂(`http/server.ts`:路由里逃出来的、不是 `HttpError` 的故障)—— 码经 {@link openFaceFaultWire}(会话列表行的 `unreadable` 同读这一只:
128
+ * 列表说的码就是读口答的码,`session-error-wire.ts` 头注「一张表、两个读者」)。有臂的 `SessionError` 同 {@link sendSessionError};其余落通用 500,固定句。
129
+ */
130
+ export declare function sendOpenFaceFault(res: ServerResponse, e: unknown): void;
126
131
  export declare function msg(e: unknown): string;
127
132
  /**
128
133
  * 路由抛出的未归类错误的运维行 `request_error` —— **唯一写者**。外层兜底(`server.ts`)与「就地经映射下发」的站点(会话同步的暂存提交 catch)同调它:
package/dist/http/send.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { SessionError, SessionPolicyError } from "@sema-agent/core";
2
2
  import { sessionPolicyErrorFacts, sessionPolicyErrorHttp, sessionPolicyErrorSentence } from "../session-policy-wire.js";
3
- import { sessionErrorHttp } from "../session-error-wire.js";
3
+ import { openFaceFaultWire, sessionErrorWireOf } from "../session-error-wire.js";
4
4
  import { redactErrorMessage, redactHead } from "../observability/run-terminal.js";
5
5
  import { createCodedHttpError } from "../security.js";
6
6
  import { refusalBody } from "./refusal-body.js";
@@ -79,12 +79,19 @@ export function sendSessionPolicyError(res, e, sentencePrefix = "") {
79
79
  export function sendSessionError(res, e, face) {
80
80
  if (!(e instanceof SessionError))
81
81
  return false;
82
- const wire = sessionErrorHttp(e.code, face);
82
+ const wire = sessionErrorWireOf(e, face);
83
83
  if (wire === undefined)
84
84
  return false;
85
- sendError(res, wire.status, wire.errorCode, wire.sentence ?? redactErrorMessage(e.message) ?? "session store error", wire.detail === undefined ? undefined : { detail: wire.detail });
85
+ sendSessionWire(res, e, wire);
86
86
  return true;
87
87
  }
88
+ export function sendOpenFaceFault(res, e) {
89
+ sendSessionWire(res, e, openFaceFaultWire(e));
90
+ }
91
+ function sendSessionWire(res, e, wire) {
92
+ const sentence = wire.sentence ?? (e instanceof SessionError ? redactErrorMessage(e.message) : undefined) ?? "session store error";
93
+ sendError(res, wire.status, wire.errorCode, sentence, wire.detail === undefined ? undefined : { detail: wire.detail });
94
+ }
88
95
  export function msg(e) {
89
96
  return e instanceof Error ? e.message : String(e);
90
97
  }