@sema-agent/server 7.140.0 → 7.141.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 (200) hide show
  1. package/MIGRATION.md +290 -0
  2. package/README.md +1 -1
  3. package/README.zh-CN.md +1 -1
  4. package/USAGE.md +75 -13
  5. package/dist/approval-batch-census.d.ts +27 -0
  6. package/dist/approval-batch-census.js +27 -0
  7. package/dist/approval-card.d.ts +31 -16
  8. package/dist/approval-card.js +6 -3
  9. package/dist/approval.d.ts +15 -0
  10. package/dist/approval.js +10 -0
  11. package/dist/audit.d.ts +4 -2
  12. package/dist/audit.js +2 -2
  13. package/dist/boot/device-lane.d.ts +11 -0
  14. package/dist/boot/device-lane.js +16 -0
  15. package/dist/boot/engine-lease.d.ts +24 -3
  16. package/dist/boot/engine-lease.js +9 -2
  17. package/dist/boot/execution-env.js +8 -4
  18. package/dist/boot/memory-boundary.d.ts +2 -2
  19. package/dist/boot/memory-consolidation.d.ts +1 -1
  20. package/dist/boot/memory-consolidation.js +1 -1
  21. package/dist/boot/reapers.d.ts +2 -2
  22. package/dist/boot/resolve-spec.js +7 -4
  23. package/dist/boot/session-faces.d.ts +1 -1
  24. package/dist/boot/session-faces.js +4 -3
  25. package/dist/boot/shutdown.js +5 -0
  26. package/dist/boot/stage-05-execution-env.js +3 -1
  27. package/dist/boot/stage-06-runners.d.ts +0 -2
  28. package/dist/boot/stage-06-runners.js +1 -1
  29. package/dist/boot/stage-07-capability-layer.d.ts +0 -1
  30. package/dist/boot/stage-07-capability-layer.js +8 -10
  31. package/dist/boot/stage-08-reapers.d.ts +0 -1
  32. package/dist/boot/stage-09-leader.d.ts +0 -1
  33. package/dist/boot/stage-10-http-server.d.ts +0 -1
  34. package/dist/boot/stage-10-http-server.js +1 -0
  35. package/dist/boot/stores.js +10 -4
  36. package/dist/boot/web-admin.js +1 -0
  37. package/dist/capabilities/scenarios.d.ts +1 -1
  38. package/dist/capability-facts.d.ts +9 -0
  39. package/dist/capability-facts.js +9 -0
  40. package/dist/card-void.d.ts +38 -0
  41. package/dist/card-void.js +23 -0
  42. package/dist/config-catalog.js +11 -8
  43. package/dist/config-provider.d.ts +13 -13
  44. package/dist/config-provider.js +19 -33
  45. package/dist/config-types.d.ts +26 -8
  46. package/dist/config.js +55 -46
  47. package/dist/delegated-session-owner.d.ts +21 -19
  48. package/dist/delegated-session-owner.js +1 -1
  49. package/dist/device-store.d.ts +7 -0
  50. package/dist/device-store.js +3 -0
  51. package/dist/execution-config-root.d.ts +22 -0
  52. package/dist/execution-config-root.js +35 -0
  53. package/dist/execution-lane-caps.d.ts +49 -2
  54. package/dist/execution-lane-caps.js +90 -13
  55. package/dist/execution-placement.d.ts +3 -0
  56. package/dist/execution-placement.js +7 -0
  57. package/dist/fleet/drain-entry.d.ts +3 -0
  58. package/dist/hosted-posture.d.ts +8 -0
  59. package/dist/hosted-posture.js +4 -0
  60. package/dist/http/admission.js +3 -3
  61. package/dist/http/caller-trust.d.ts +3 -2
  62. package/dist/http/caller-trust.js +2 -1
  63. package/dist/http/dispatch.js +4 -0
  64. package/dist/http/live-frame.d.ts +24 -0
  65. package/dist/http/live-frame.js +16 -0
  66. package/dist/http/resume-legs.js +37 -20
  67. package/dist/http/route-table.js +2 -0
  68. package/dist/http/routes/approvals-assistant.js +1 -0
  69. package/dist/http/routes/capabilities.js +5 -4
  70. package/dist/http/routes/diagnostics.d.ts +0 -19
  71. package/dist/http/routes/diagnostics.js +16 -2
  72. package/dist/http/routes/memory-bundle.d.ts +2 -2
  73. package/dist/http/routes/memory-bundle.js +1 -1
  74. package/dist/http/routes/memory-compliance.js +1 -1
  75. package/dist/http/routes/memory-policy.js +2 -2
  76. package/dist/http/routes/run-permission-mode.d.ts +75 -0
  77. package/dist/http/routes/run-permission-mode.js +170 -0
  78. package/dist/http/routes/session-sync.d.ts +3 -6
  79. package/dist/http/routes/session-sync.js +7 -2
  80. package/dist/http/routes/sessions.js +5 -4
  81. package/dist/http/routes/tasks.js +63 -66
  82. package/dist/http/run-read-face.js +3 -3
  83. package/dist/http/send.d.ts +1 -1
  84. package/dist/http/send.js +2 -2
  85. package/dist/http/server.d.ts +9 -2
  86. package/dist/http/sse-log.d.ts +3 -8
  87. package/dist/http/stored-body-replay.d.ts +3 -3
  88. package/dist/http/stored-body-replay.js +3 -1
  89. package/dist/instruction-source-notice.d.ts +7 -0
  90. package/dist/instruction-source-notice.js +6 -6
  91. package/dist/mcp-assertion-header.d.ts +4 -0
  92. package/dist/mcp-assertion-header.js +5 -0
  93. package/dist/memory-posture.d.ts +1 -1
  94. package/dist/memory-scope.d.ts +4 -4
  95. package/dist/memory-scope.js +1 -1
  96. package/dist/memory-sync-client.d.ts +14 -2
  97. package/dist/memory-sync-client.js +80 -18
  98. package/dist/observability/fail-open.d.ts +30 -2
  99. package/dist/observability/fail-open.js +30 -2
  100. package/dist/observability/metrics.js +0 -1
  101. package/dist/observability/run-terminal.d.ts +6 -2
  102. package/dist/observability/run-terminal.js +25 -26
  103. package/dist/observability/secret-env-scrub.d.ts +20 -1
  104. package/dist/observability/secret-env-scrub.js +14 -0
  105. package/dist/orchestration/workflow-completion-inbox.d.ts +5 -2
  106. package/dist/orchestration/workflow-completion-inbox.js +13 -5
  107. package/dist/orchestration/workflow-notify-journal.d.ts +5 -3
  108. package/dist/orchestration/workflow-notify-journal.js +2 -1
  109. package/dist/permission-mode-admission.d.ts +68 -0
  110. package/dist/permission-mode-admission.js +23 -0
  111. package/dist/permission-rule-list.d.ts +55 -6
  112. package/dist/permission-rule-list.js +52 -5
  113. package/dist/plugins/caching-session-store.d.ts +6 -0
  114. package/dist/plugins/caching-session-store.js +3 -0
  115. package/dist/plugins/checkpoint-store-sql.d.ts +65 -17
  116. package/dist/plugins/checkpoint-store-sql.js +74 -3
  117. package/dist/plugins/device-store-sql.d.ts +5 -2
  118. package/dist/plugins/device-store-sql.js +4 -1
  119. package/dist/plugins/execution-placement-sql.d.ts +11 -1
  120. package/dist/plugins/execution-placement-sql.js +12 -1
  121. package/dist/plugins/file-run-store.d.ts +2 -2
  122. package/dist/plugins/file-run-store.js +1 -1
  123. package/dist/plugins/fork-routing-session-store.d.ts +10 -32
  124. package/dist/plugins/fork-routing-session-store.js +2 -61
  125. package/dist/plugins/k8s-exec-protocol.d.ts +4 -1
  126. package/dist/plugins/k8s-exec-protocol.js +6 -1
  127. package/dist/plugins/local-checkpoint-store.d.ts +10 -1
  128. package/dist/plugins/local-checkpoint-store.js +22 -0
  129. package/dist/plugins/local-session-store.d.ts +227 -35
  130. package/dist/plugins/local-session-store.js +518 -37
  131. package/dist/plugins/local-session-window.d.ts +17 -3
  132. package/dist/plugins/local-session-window.js +7 -13
  133. package/dist/plugins/memory-run-store.d.ts +2 -2
  134. package/dist/plugins/memory-run-store.js +1 -1
  135. package/dist/plugins/one-time-migrations.d.ts +42 -2
  136. package/dist/plugins/one-time-migrations.js +65 -3
  137. package/dist/plugins/pg-pool.js +3 -2
  138. package/dist/plugins/pg-session-storage.d.ts +2 -0
  139. package/dist/plugins/pg-session-storage.js +3 -2
  140. package/dist/plugins/remote-env-e2b.d.ts +24 -3
  141. package/dist/plugins/remote-env-e2b.js +131 -18
  142. package/dist/plugins/remote-env-k8s.d.ts +20 -1
  143. package/dist/plugins/remote-env-k8s.js +148 -25
  144. package/dist/plugins/remote-env-local-docker.d.ts +25 -11
  145. package/dist/plugins/remote-env-local-docker.js +87 -21
  146. package/dist/plugins/run-store-sql.d.ts +3 -3
  147. package/dist/plugins/run-store-sql.js +4 -3
  148. package/dist/plugins/sandbox-read-floor.d.ts +273 -0
  149. package/dist/plugins/sandbox-read-floor.js +608 -0
  150. package/dist/plugins/session-ownership.d.ts +2 -1
  151. package/dist/plugins/session-placement.d.ts +17 -4
  152. package/dist/plugins/session-placement.js +2 -1
  153. package/dist/plugins/session-store.d.ts +18 -20
  154. package/dist/plugins/session-store.js +4 -12
  155. package/dist/plugins/store-backend.d.ts +31 -0
  156. package/dist/plugins/store-backend.js +21 -4
  157. package/dist/plugins/store-contracts.d.ts +9 -2
  158. package/dist/plugins/tidb-pool.js +2 -1
  159. package/dist/plugins/tidb-session-store.d.ts +4 -1
  160. package/dist/plugins/tidb-session-store.js +3 -2
  161. package/dist/run-cancel-context.d.ts +34 -0
  162. package/dist/run-cancel-context.js +7 -0
  163. package/dist/runs.d.ts +39 -12
  164. package/dist/runs.js +68 -53
  165. package/dist/security.d.ts +2 -2
  166. package/dist/server-secret-env.d.ts +2 -1
  167. package/dist/server-secret-env.js +2 -4
  168. package/dist/session-error-wire.d.ts +22 -4
  169. package/dist/session-error-wire.js +16 -0
  170. package/dist/session-incarnation.d.ts +9 -3
  171. package/dist/session-sync-kernel.d.ts +42 -1
  172. package/dist/session-sync-kernel.js +17 -0
  173. package/dist/session-sync.js +16 -4
  174. package/dist/sql-engine-coordinates.d.ts +49 -0
  175. package/dist/sql-engine-coordinates.js +27 -0
  176. package/dist/standing-answer-grant.d.ts +31 -2
  177. package/dist/standing-answer-grant.js +14 -2
  178. package/dist/store-posture.d.ts +1 -1
  179. package/dist/task-a2a.d.ts +1 -1
  180. package/dist/task-mcp.d.ts +1 -1
  181. package/dist/task-settings.d.ts +52 -25
  182. package/dist/task-settings.js +91 -28
  183. package/dist/terminal.d.ts +77 -20
  184. package/dist/terminal.js +66 -20
  185. package/dist/trace/core-keyset-guard.d.ts +79 -2
  186. package/dist/trace/exit-seat.d.ts +7 -0
  187. package/dist/trace/exit-seat.js +1 -0
  188. package/dist/trace/model-segment.d.ts +2 -2
  189. package/dist/trace/redact.js +323 -90
  190. package/dist/trace/self-minted-wire.d.ts +168 -2
  191. package/dist/trace/self-minted-wire.js +63 -0
  192. package/dist/verifier-pause-card.d.ts +8 -0
  193. package/dist/verifier-pause-card.js +19 -0
  194. package/dist/web-admin-client/apply-effective.d.ts +5 -7
  195. package/dist/web-admin-client/apply-effective.js +2 -2
  196. package/dist/web-admin-client/candidate-gate.d.ts +1 -1
  197. package/dist/web-admin-client/read-warnings.d.ts +2 -2
  198. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +3 -2
  199. package/package.json +2 -2
  200. package/wire-changes/server@7.141.0.json +367 -0
@@ -1,8 +1,9 @@
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";
@@ -14,14 +15,14 @@ import { clearTurnActivity, readTurnActivityMs, recordTurnActivity } from "../..
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
  }
@@ -407,7 +403,7 @@ export async function handleTasks(req, res, match, ctx) {
407
403
  recordFailOpen(failOpenTagForDroppedFrame("engine_notice"), "frame=engine_notice");
408
404
  return;
409
405
  }
410
- sseData(res, { type: "engine_notice", ...row });
406
+ writeLiveFrame(res, { type: "engine_notice", ...row });
411
407
  },
412
408
  ...(noticeLedger
413
409
  ? {
@@ -437,34 +433,34 @@ export async function handleTasks(req, res, match, ctx) {
437
433
  if (res.writableEnded)
438
434
  return;
439
435
  for (const end of childReasoning.onEvent(e))
440
- sseData(res, end);
436
+ writeLiveFrame(res, end);
441
437
  const t = e.type;
442
438
  if (t === "task_progress") {
443
- sseData(res, { type: "task_progress", ...taskProgressEventData(e) });
439
+ writeLiveFrame(res, { type: "task_progress", ...taskProgressEventData(e) });
444
440
  }
445
441
  else if (t === "task_started") {
446
- sseData(res, { type: "task_started", ...taskStartedEventData(e) });
442
+ writeLiveFrame(res, { type: "task_started", ...taskStartedEventData(e) });
447
443
  }
448
444
  else if (t === "tool_start") {
449
445
  const tsv = e;
450
- sseData(res, { type: "tool_start", ...toolStartEventData(tsv) });
446
+ writeLiveFrame(res, { type: "tool_start", ...toolStartEventData(tsv) });
451
447
  }
452
448
  else if (t === "tool_end") {
453
449
  const te = e;
454
- sseData(res, { type: "tool_end", ...toolEndEventData(te) });
450
+ writeLiveFrame(res, { type: "tool_end", ...toolEndEventData(te) });
455
451
  }
456
452
  else if (t === "text_delta") {
457
453
  const td = e;
458
- sseData(res, { type: "text_delta", delta: td.delta, ...(td.eventId ? { eventId: td.eventId } : {}), ...(td.parentToolCallId ? { parentToolCallId: td.parentToolCallId } : {}) });
454
+ writeLiveFrame(res, { type: "text_delta", delta: td.delta, ...(td.eventId ? { eventId: td.eventId } : {}), ...(td.parentToolCallId ? { parentToolCallId: td.parentToolCallId } : {}) });
459
455
  }
460
456
  else if (t === "text_end") {
461
457
  const tend = textEndEventData(e);
462
458
  if (tend !== null)
463
- sseData(res, { type: "text_end", ...tend });
459
+ writeLiveFrame(res, { type: "text_end", ...tend });
464
460
  }
465
461
  else if (t === "reasoning_delta") {
466
462
  const rd = e;
467
- sseData(res, { type: "reasoning_delta", delta: redactSecrets(rd.delta), ...(rd.eventId ? { eventId: rd.eventId } : {}), ...(rd.parentToolCallId ? { parentToolCallId: rd.parentToolCallId } : {}) });
463
+ writeLiveFrame(res, { type: "reasoning_delta", delta: redactSecrets(rd.delta), ...(rd.eventId ? { eventId: rd.eventId } : {}), ...(rd.parentToolCallId ? { parentToolCallId: rd.parentToolCallId } : {}) });
468
464
  }
469
465
  },
470
466
  onTaskNotification: (n, opts) => {
@@ -472,7 +468,7 @@ export async function handleTasks(req, res, match, ctx) {
472
468
  return;
473
469
  if (!res.writableEnded)
474
470
  for (const end of childReasoning.cut(reasoningStreamOfTask(n.task_id, n.sessionId)))
475
- sseData(res, end);
471
+ writeLiveFrame(res, end);
476
472
  defaultSubagentTailBus.forgetHandle(n.task_id);
477
473
  if (defaultSubagentTailBus.hasSubscribers(n.task_id)) {
478
474
  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 +484,7 @@ export async function handleTasks(req, res, match, ctx) {
488
484
  const key = taskNotificationDedupKey(n);
489
485
  if (syncNotifiedKeys.get(key) === undefined) {
490
486
  syncNotifiedKeys.set(key, Promise.resolve(true));
491
- sseData(res, { type: "task_notification", ...taskNotificationEventData({ notification: n, ...(opts?.priority !== undefined ? { priority: opts.priority } : {}) }) });
487
+ writeLiveFrame(res, { type: "task_notification", ...taskNotificationEventData({ notification: n, ...(opts?.priority !== undefined ? { priority: opts.priority } : {}) }) });
492
488
  }
493
489
  }
494
490
  },
@@ -505,13 +501,13 @@ export async function handleTasks(req, res, match, ctx) {
505
501
  void heldFor(prepared.peerLease, () => Promise.allSettled([Promise.resolve().then(() => liveStream.result())]));
506
502
  if (durableTaskId)
507
503
  steerableRuns.set(durableTaskId, liveStream);
508
- prepared.acceptance.attachStream({ reachable: () => !closed && !res.writableEnded && !res.destroyed, write: (frame) => sseData(res, { ...frame }) });
504
+ prepared.acceptance.attachStream({ reachable: () => !closed && !res.writableEnded && !res.destroyed, write: (frame) => writeLiveFrame(res, { ...frame }) });
509
505
  const liveWorkspace = createSessionWorkspaceRecorder(sessionWorkspaceStoreOf(deps.sessionStorage), legSessionWitnessOf(prepared.spec));
510
506
  for await (const ev of liveStream) {
511
507
  if (closed)
512
508
  break;
513
509
  for (const end of ev.type === "done" ? [...childReasoning.cut(), ...topReasoning.cut()] : topReasoning.onEvent(ev))
514
- sseData(res, end);
510
+ writeLiveFrame(res, end);
515
511
  const promptEntryId = promptCommit(ev);
516
512
  if (promptEntryId !== undefined)
517
513
  userMsgEntryId = promptEntryId;
@@ -528,7 +524,7 @@ export async function handleTasks(req, res, match, ctx) {
528
524
  }
529
525
  finalizeTaskResult(ev.result, principal, prepared.spec.objective);
530
526
  noteRunOutcome(finalResult);
531
- putRewindAnchor();
527
+ await putRewindAnchor();
532
528
  settleFleet(outwardPlane(finalResult.terminal).status, fleetRunResiduals(finalResult));
533
529
  if (ledgerSink && finalResult) {
534
530
  if (usageKey && deps.modelUsage && deps.runStore && durableTaskId) {
@@ -540,7 +536,7 @@ export async function handleTasks(req, res, match, ctx) {
540
536
  await ledgerSink.onDone(finalResult);
541
537
  ledgerTerminal = true;
542
538
  }
543
- sseData(res, { ...ev, result: finalResult });
539
+ writeLiveFrame(res, { ...ev, result: finalResult });
544
540
  continue;
545
541
  }
546
542
  if (ledgerSink) {
@@ -552,15 +548,15 @@ export async function handleTasks(req, res, match, ctx) {
552
548
  if (ev.type === "status")
553
549
  deps.metrics?.inc("brain_retry_total", { phase: String(ev.phase) });
554
550
  if (ev.type === "status") {
555
- sseData(res, { type: "status", ...brainStatusEventData(ev) });
551
+ writeLiveFrame(res, { type: "status", ...brainStatusEventData(ev) });
556
552
  }
557
553
  else if (ev.type === "tool_end") {
558
554
  const te = ev;
559
- sseData(res, { type: "tool_end", ...toolEndEventData(te) });
555
+ writeLiveFrame(res, { type: "tool_end", ...toolEndEventData(te) });
560
556
  }
561
557
  else if (ev.type === "tool_start") {
562
558
  const tsv = ev;
563
- sseData(res, { type: "tool_start", ...toolStartEventData(tsv) });
559
+ writeLiveFrame(res, { type: "tool_start", ...toolStartEventData(tsv) });
564
560
  }
565
561
  else if (ev.type === "task_notification") {
566
562
  const tnv = ev.notification;
@@ -569,58 +565,58 @@ export async function handleTasks(req, res, match, ctx) {
569
565
  if (tnvPrior === undefined || !(await tnvPrior)) {
570
566
  if (tnvKey !== undefined)
571
567
  syncNotifiedKeys.set(tnvKey, Promise.resolve(true));
572
- sseData(res, { type: "task_notification", ...taskNotificationEventData(ev) });
568
+ writeLiveFrame(res, { type: "task_notification", ...taskNotificationEventData(ev) });
573
569
  }
574
570
  }
575
571
  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 } : {}) });
572
+ writeLiveFrame(res, { type: "reasoning_delta", delta: redactSecrets(ev.delta), ...(ev.eventId ? { eventId: ev.eventId } : {}), ...(ev.parentToolCallId ? { parentToolCallId: ev.parentToolCallId } : {}) });
577
573
  }
578
574
  else if (ev.type === "task_progress") {
579
- sseData(res, { type: "task_progress", ...taskProgressEventData(ev) });
575
+ writeLiveFrame(res, { type: "task_progress", ...taskProgressEventData(ev) });
580
576
  }
581
577
  else if (ev.type === "task_started") {
582
- sseData(res, { type: "task_started", ...taskStartedEventData(ev) });
578
+ writeLiveFrame(res, { type: "task_started", ...taskStartedEventData(ev) });
583
579
  }
584
580
  else if (ev.type === "compacted") {
585
- sseData(res, { type: "compacted", ...compactedEventData(ev) });
581
+ writeLiveFrame(res, { type: "compacted", ...compactedEventData(ev) });
586
582
  }
587
583
  else if (ev.type === "diagnostics") {
588
- sseData(res, { type: "diagnostics", ...diagnosticsEventData(ev) });
584
+ writeLiveFrame(res, { type: "diagnostics", ...diagnosticsEventData(ev) });
589
585
  }
590
586
  else if (ev.type === "steering_injected") {
591
- sseData(res, { type: "steering_injected", ...steeringInjectedEventData(ev) });
587
+ writeLiveFrame(res, { type: "steering_injected", ...steeringInjectedEventData(ev) });
592
588
  }
593
589
  else if (ev.type === "workspace_changed") {
594
- sseData(res, { type: "workspace_changed", ...workspaceChangedEventData(ev) });
590
+ writeLiveFrame(res, { type: "workspace_changed", ...workspaceChangedEventData(ev) });
595
591
  }
596
592
  else if (ev.type === "compaction_outcome") {
597
- sseData(res, { type: "compaction_outcome", ...compactionOutcomeEventData(ev) });
593
+ writeLiveFrame(res, { type: "compaction_outcome", ...compactionOutcomeEventData(ev) });
598
594
  }
599
595
  else if (ev.type === "compaction_started") {
600
- sseData(res, { type: "compaction_started", ...compactionStartedEventData(ev) });
596
+ writeLiveFrame(res, { type: "compaction_started", ...compactionStartedEventData(ev) });
601
597
  }
602
598
  else if (ev.type === "wiring_manifest") {
603
599
  const wiringFace = wiringManifestFaceEventData(ev, wiringOperatorFace, legWiringSections());
604
600
  wiringReceipt ??= wiringFace;
605
- sseData(res, { type: "wiring_manifest", ...wiringFace });
601
+ writeLiveFrame(res, { type: "wiring_manifest", ...wiringFace });
606
602
  }
607
603
  else if (ev.type === "tool_roster_delta") {
608
604
  const rosterDelta = toolRosterDeltaEventData(ev);
609
605
  if (rosterDelta !== undefined)
610
- sseData(res, { type: "tool_roster_delta", ...rosterDelta });
606
+ writeLiveFrame(res, { type: "tool_roster_delta", ...rosterDelta });
611
607
  }
612
608
  else if (ev.type === "tool_progress") {
613
609
  const progress = toolProgressEventData(ev);
614
610
  if (progress !== undefined)
615
- sseData(res, { type: "tool_progress", ...progress });
611
+ writeLiveFrame(res, { type: "tool_progress", ...progress });
616
612
  }
617
613
  else if (ev.type === "tool_disclosure") {
618
614
  const disclosure = toolDisclosureEventData(ev);
619
615
  if (disclosure !== undefined)
620
- sseData(res, { type: "tool_disclosure", ...disclosure });
616
+ writeLiveFrame(res, { type: "tool_disclosure", ...disclosure });
621
617
  }
622
618
  else if (ev.type === "human_input") {
623
- sseData(res, { type: "human_input", ...humanInputEventData(ev) });
619
+ writeLiveFrame(res, { type: "human_input", ...humanInputEventData(ev) });
624
620
  }
625
621
  else if (ev.type === "text_delta" || ev.type === "text_end" || ev.type === "turn_end" || ev.type === "message_committed" || ev.type === "context_usage") {
626
622
  const e = ev;
@@ -637,10 +633,10 @@ export async function handleTasks(req, res, match, ctx) {
637
633
  ? { type: "message_committed", entryId: e.entryId, role: e.role, ...(e.toolCallId !== undefined ? { toolCallId: e.toolCallId } : {}), ...ident }
638
634
  : { type: "context_usage", ...contextUsageEventData(ev), ...ident };
639
635
  if (arm !== null)
640
- sseData(res, arm);
636
+ writeLiveFrame(res, arm);
641
637
  }
642
638
  else {
643
- sseData(res, { ...ev });
639
+ writeLiveFrame(res, { ...ev });
644
640
  }
645
641
  }
646
642
  });
@@ -652,7 +648,7 @@ export async function handleTasks(req, res, match, ctx) {
652
648
  recordFailOpen(failOpenTagForDroppedFrame(frame.type), `frame=${frame.type}`);
653
649
  return;
654
650
  }
655
- res.write(`event: ${frame.type}\ndata: ${JSON.stringify(frame)}\n\n`);
651
+ writeLiveFrame(res, { ...frame });
656
652
  };
657
653
  const faceAlive = () => !res.writableEnded && !res.destroyed;
658
654
  const emitElicitation = createLedgerTwinEmit({ sink: ledgerSink, writeLive: emitAsk, liveReachable: faceAlive });
@@ -669,7 +665,7 @@ export async function handleTasks(req, res, match, ctx) {
669
665
  const fKey = f.type === "task_notification" ? taskNotificationStreamKeyOf(f) : undefined;
670
666
  if (fKey !== undefined)
671
667
  syncNotifiedKeys.set(fKey, Promise.resolve(true));
672
- sseData(res, frame);
668
+ writeLiveFrame(res, frame);
673
669
  }, { route: "sync-stream-open", connection: "live-sse", log: (m, x) => deps.logger?.info?.(m, x) });
674
670
  const withElicit = deps.elicitation
675
671
  ? () => deps.elicitation.runWithContext({ taskId: askTaskId, owner: askOwner, emit: emitElicitation, abortSignal: ac.signal }, streamBody)
@@ -765,7 +761,7 @@ export async function handleTasks(req, res, match, ctx) {
765
761
  await releaseKeyIfZeroWorkRefusal(deps.runStore, durableTaskId, finalResult);
766
762
  }
767
763
  else {
768
- putRewindAnchor();
764
+ await putRewindAnchor();
769
765
  const pending = await deps.checkpointStore?.findPendingTokenBySession(prepared.spec.sessionId);
770
766
  const dcCause = ac.cause();
771
767
  if (pending) {
@@ -885,7 +881,7 @@ export async function handleTasks(req, res, match, ctx) {
885
881
  deps.modelUsage?.clear(usageKey);
886
882
  }
887
883
  if (!ranLive && resp && !res.writableEnded) {
888
- sseData(res, { type: "done", result: doneResultOfOutcome(resp), replay: true });
884
+ writeLiveFrame(res, { type: "done", result: doneResultOfOutcome(resp), replay: true });
889
885
  }
890
886
  res.end();
891
887
  }
@@ -979,6 +975,7 @@ export async function handleTasks(req, res, match, ctx) {
979
975
  inflightRuns.delete(durableTaskId);
980
976
  }
981
977
  const syncAbortCause = syncCancelCtrl.cause();
978
+ await voidVerifierPauseCard(result, deps.checkpointStore);
982
979
  if (syncAbortCause !== undefined) {
983
980
  result = mintCancelledResult({
984
981
  taskId: durableTaskId ?? "",
@@ -1,5 +1,5 @@
1
1
  import { persistedPlaneOf } from "../terminal.js";
2
- import { memoRedactedRead, memoRedactTerminalResult, redactErrorMessage, redactTerminalResult } from "../observability/run-terminal.js";
2
+ import { memoRedactedRead, memoRedactTerminalResult, redactErrorMessage, sealRunRowResult } 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";
@@ -53,14 +53,14 @@ export async function readRunFace(deps, runStore, run) {
53
53
  status: stale ? "failed" : run.status,
54
54
  ...(lastActivityAt !== undefined ? { msSinceLastActivity: Math.max(0, Date.now() - lastActivityAt) } : {}),
55
55
  ...(crossSliceUsage !== undefined ? { crossSliceUsage } : {}),
56
- result: isTerminalRunStatus(run.status) ? memoRedactTerminalResult("run.result", run.result ?? undefined) : redactTerminalResult(run.result ?? undefined),
56
+ result: isTerminalRunStatus(run.status) ? memoRedactTerminalResult("run.result", run.result ?? undefined) : (sealRunRowResult(run.result ?? null, "run.result") ?? undefined),
57
57
  supervisorCost,
58
58
  suggestions,
59
59
  errorCode: stale ? RUN_HOLDER_DEATH_CODES.stalled : (persistedPlaneOf(run.result).errorCode ?? run.errorCode ?? undefined),
60
60
  error: stale ? "run stalled (instance lost?)" : isTerminalRunStatus(run.status) ? memoRedactedRead("run.error", run.error ?? undefined, redactErrorMessage) : redactErrorMessage(run.error ?? undefined),
61
61
  jobId: run.jobId ?? undefined,
62
62
  source: run.source ?? undefined,
63
- heldBy: run.instanceId ?? null,
63
+ heldBy: isTerminalRunStatus(run.status) ? null : (run.instanceId ?? null),
64
64
  cancelRequested: run.cancelRequested,
65
65
  };
66
66
  }
@@ -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
  *
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 { 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,7 +79,7 @@ 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
85
  sendError(res, wire.status, wire.errorCode, wire.sentence ?? redactErrorMessage(e.message) ?? "session store error", wire.detail === undefined ? undefined : { detail: wire.detail });
@@ -13,6 +13,7 @@ import type { ExecutionRoot, ResolvedTaskSpec } from "./execution-context.js";
13
13
  import type { RunStore, ImageIndex, ImageBake, CheckpointStoreFull, ResumeAnchorStore, ApprovalExemptionStore, ApprovalNonceStore, ServiceSessionPolicyStore, ServiceFileHistoryStore, ToolResultStoreFull, StoreBackend } from "../plugins/store-backend.js";
14
14
  import type { RuleConsentLane } from "../rules-consent.js";
15
15
  import { type MemorySyncRequest, type MemorySyncResponse } from "../memory-sync.js";
16
+ import type { MemorySyncRunner } from "../memory-sync-client.js";
16
17
  import type { TaskAttachmentStore } from "../plugins/task-attachment-store.js";
17
18
  import type { LeaderEndpoint } from "../leader/endpoint.js";
18
19
  import { type WorkflowAgentRegistry } from "../orchestration/workflow-agent-steer.js";
@@ -463,7 +464,7 @@ export interface ServiceSeamDeps {
463
464
  }>;
464
465
  /** 142-S5 §1.4: per-scope memory export reader (main.ts wires `exportMemoryScope` over the DB memory
465
466
  * backend). Enables GET /v1/memory/export — present ONLY on a DB memory plane (MEMORY_ENGINE_BACKEND=
466
- * pg|tidb); absent / file posture ⇒ 501 (single-user file memory exports by copying the memory dir). */
467
+ * pg|mysql); absent / file posture ⇒ 501 (single-user file memory exports by copying the memory dir). */
467
468
  memoryExport?: (scope: string) => Promise<MemoryEntry[]>;
468
469
  /**
469
470
  * [ref](core 5.57.0 `routePairingStatus`)—— **key↔URL 配对读面**:`GET /v1/models` 每行的
@@ -479,7 +480,7 @@ export interface ServiceSeamDeps {
479
480
  /** 142-S2.5(设计 §2.5;裁定 plan 随数据走,core 零运行时半场):one full sync round for one
480
481
  * (scope, peer) — main.ts wires `performMemorySync` over the DB memory backend + the sync-cursor
481
482
  * store. Enables POST /v1/memory/sync/:scope — present ONLY on a DB memory plane
482
- * (MEMORY_ENGINE_BACKEND=pg|tidb); absent / file posture ⇒ 501 honestly (a single-user file plane
483
+ * (MEMORY_ENGINE_BACKEND=pg|mysql); absent / file posture ⇒ 501 honestly (a single-user file plane
483
484
  * IS the TOC side of a sync — it has no central-authority half to serve). */
484
485
  memorySync?: (scope: string, syncReq: MemorySyncRequest) => Promise<MemorySyncResponse>;
485
486
  /** [ref] v2-c(core 5.40.0 `MemoryEngine.exportMemoryScopes`):治理完备包的**携出**面。main.ts 把它接到
@@ -533,6 +534,12 @@ export interface ServiceSeamDeps {
533
534
  * 装配漏接 ⇒ tsc 红(本行就是通知);测试桩在 `test/helpers/boot.ts` 显式给 false。
534
535
  */
535
536
  memoryAutoConsolidationArmed: boolean;
537
+ /**
538
+ * [ref] —— 本**部署**的记忆同步腿(客户端半场):`MEMORY_SYNC_URL` 设了且 file 记忆引擎亮着、执行器起了才在场(`boot/stores.ts`)。
539
+ * `GET /v1/sessions/:id/memory-status` 的 `memorySync` 格只读它的 `parked()` —— 停驻事实的唯一读口(写者 = 执行器的轮,运维行 `memory_sync_layer_parked` 读同一份);
540
+ * 缺席 ⇒ 那一格缺席(没有同步腿)。与 `memoryAutoConsolidationArmed` 同类:部署事实,不随会话、不随层座。
541
+ */
542
+ memorySyncLeg?: Pick<MemorySyncRunner, "parked">;
536
543
  /**
537
544
  * [ref] / [ref] + 车PI 修复轮 ④ —— 记忆整理阀门的**生效判决**(boot 第 4 段 `createConsolidationValve`:显式词,或出厂缺省按
538
545
  * 装配结果派生)。配置目录那一行(`GET /v1/config/catalog` 的 `MEMORY_CONSOLIDATION_DRIVER` `effectiveValue`)读它 —— 那一列的契约是
@@ -70,15 +70,10 @@ export declare const SSE_PREAMBLE_TIMEOUT_MS = 2000;
70
70
  * `ApprovalAskStore.listPendingBySession` 的注)。丢结果这条语义不变:preamble 只读,丢弃零副作用。
71
71
  *
72
72
  * 导出给 `routes/tasks.ts` 的 sync 腿直接用 —— 那条腿不走 `streamSseLog`(它不是账本 tail),但
73
- * 「有界 + fail-open」这条判据必须是**同一份实现**,不能各腿各写一遍。
73
+ * 「有界 + fail-open」这条判据必须是**同一份实现**,不能各腿各写一遍。帧型是调用方的(本泵写 `{ event, data }`,
74
+ * sync 腿把卡帧原样交给它自己的写口 `http/live-frame.ts`),所以按帧型泛化。
74
75
  */
75
- export declare function collectSsePreamble(preamble: (signal: AbortSignal) => Promise<Array<{
76
- event: string;
77
- data: unknown;
78
- }>>, onFailure?: (reason: "timeout" | "error", err?: unknown) => void, timeoutMs?: number): Promise<Array<{
79
- event: string;
80
- data: unknown;
81
- }>>;
76
+ export declare function collectSsePreamble<F>(preamble: (signal: AbortSignal) => Promise<F[]>, onFailure?: (reason: "timeout" | "error", err?: unknown) => void, timeoutMs?: number): Promise<F[]>;
82
77
  /** The shared resumable SSE pump (P2.8) — provider supplies the log-specific differences; the liveness/
83
78
  * heartbeat/terminal-re-fetch/15-min-cap logic is identical for task_run + image_bake.
84
79
  *
@@ -9,7 +9,7 @@
9
9
  */
10
10
  import type { PermissionMode } from "@sema-agent/core";
11
11
  import { type Autonomy } from "../runtime-governance.js";
12
- import { type LaneHomeDeployment } from "../execution-lane-caps.js";
12
+ import { type ExecutionConfigRootDeployment } from "../execution-config-root.js";
13
13
  import { type StoredBodyReplayRefusal } from "./checkpoint-ctx.js";
14
14
  import type { CheckpointCtx } from "./route-ctx.js";
15
15
  /**
@@ -22,9 +22,9 @@ export declare function permissionModeReadingUnstated(ctx: CheckpointCtx, floor:
22
22
  floor: PermissionMode;
23
23
  } | undefined;
24
24
  /**
25
- * 预判读的部署配置:`autonomy`(第三问的模式词地板)与执行车道的 home 两位(`~/` 形规则那一问)。`ServiceConfig` 结构上满足,四个问点传 `deps.config` 整份。
25
+ * 预判读的部署配置:`autonomy`(第三问的模式词地板)、执行车道的 home 两位(`~/` 形规则那一问)与配置根的几位(user 设置层 `/` 规则那一问)。`ServiceConfig` 结构上满足,四个问点传 `deps.config` 整份。
26
26
  */
27
- export type StoredReplayDeployment = LaneHomeDeployment & {
27
+ export type StoredReplayDeployment = ExecutionConfigRootDeployment & {
28
28
  readonly autonomy?: Autonomy | undefined;
29
29
  };
30
30
  /**
@@ -4,6 +4,7 @@ import { entryProblemsFacts } from "../entry-problems.js";
4
4
  import { autonomyModeFloor, entryPermissionMode } from "../runtime-governance.js";
5
5
  import { inertToolListEntryOf, replayInertEntry } from "../rule-entry-list.js";
6
6
  import { executionLaneHomeDir } from "../execution-lane-caps.js";
7
+ import { executionConfigRootOf } from "../execution-config-root.js";
7
8
  import { migrationWindowEnd } from "../plugins/one-time-migrations.js";
8
9
  import { allowListReadingEraOf, allowListReadingUnstated, permissionModeReadingStated, retiredRequestKeyOf } from "./checkpoint-ctx.js";
9
10
  export function permissionModeReadingUnstated(ctx, floor) {
@@ -35,7 +36,8 @@ function storedRulePolicyRefusal(body, deployment) {
35
36
  if (permissions === undefined)
36
37
  return undefined;
37
38
  const home = executionLaneHomeDir(deployment);
38
- const refused = rulePolicyBucketsRefusal({ ...(Array.isArray(permissions["ask"]) ? { ask: permissions["ask"] } : {}), ...(Array.isArray(permissions["deny"]) ? { deny: permissions["deny"] } : {}) }, home !== undefined ? { home } : {});
39
+ const configRoot = executionConfigRootOf(deployment);
40
+ const refused = rulePolicyBucketsRefusal({ ...(Array.isArray(permissions["ask"]) ? { ask: permissions["ask"] } : {}), ...(Array.isArray(permissions["deny"]) ? { deny: permissions["deny"] } : {}) }, { ...(home !== undefined ? { home } : {}), ...(configRoot !== undefined ? { configRoot } : {}) });
39
41
  if (refused !== undefined)
40
42
  return replayInertEntry(`settings.permissions.${refused.bucket}`, "deny", SETTINGS_RULE_REFUSAL_CODE, `${REQUEST_SETTINGS_REFUSAL_PREFIX}${refused.message}`, { ...entryProblemsFacts(refused.problems) });
41
43
  const neverAuto = readTightenOnlySeats({ permissions }).values.neverAuto;
@@ -79,8 +79,15 @@ export declare function createInstructionSourceSeat(sessionStore: unknown, emit:
79
79
  * 超时**(codex che-NM r2 [high];S-9 `write-behind-counter.ts` 先例:mysql2 `{sql, timeout}` / pg `query_timeout`,pg-pool
80
80
  * 超时即销毁那条连接)—— 只放手不截断,卡住的查询会一直占着池里的连接。超期后仍在飞的写由 CAS 挡住,不会盖掉更新的基线。
81
81
  * 数值与 core 给 `probeInstructionSources` 的 2s 天花板同量级:一行 PK 读写在健康库上是毫秒级。
82
+ * 第二个读者:回退锚写入(`runs.ts` 的 `settleResumeAnchor`)—— 同为单行 PK 写、同在腿的关键路径上(流式腿的终帧等它),
83
+ * 同为披露类(F)放手,所以读同一只数、同一只 {@link withinIoDeadline}。
82
84
  */
83
85
  export declare const BASELINE_IO_DEADLINE_MS = 2000;
86
+ /** {@link withinIoDeadline} 到点放手。**具名型**:调用方据它分诊「超期」与「店报错」,不比对文案。 */
87
+ export declare class IoDeadlineExceeded extends Error {
88
+ }
89
+ /** 单行店操作的有界等待:`op` 在 {@link BASELINE_IO_DEADLINE_MS} 内落定就原样交出,否则 reject {@link IoDeadlineExceeded}。只放手不取消 —— 超期后仍在飞的那次操作照常落定(迟到的 reject 被吞,不成未处理拒绝)。 */
90
+ export declare function withinIoDeadline<T>(op: () => Promise<T>): Promise<T>;
84
91
  /**
85
92
  * **唯一铸点**:本次 prepare 选中的来源 `current`(链成员相对路径;没有 = `null`)与基线比。
86
93
  * · 没有基线 ⇒ 只写不发(新会话首 run);