@sema-agent/server 7.139.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 (328) hide show
  1. package/MIGRATION.md +471 -0
  2. package/README.md +1 -1
  3. package/README.zh-CN.md +1 -1
  4. package/USAGE.md +94 -26
  5. package/dist/adoption/runner.js +1 -1
  6. package/dist/adoption/sql.js +1 -1
  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 +37 -22
  10. package/dist/approval-card.js +6 -3
  11. package/dist/approval.d.ts +15 -0
  12. package/dist/approval.js +10 -0
  13. package/dist/audit.d.ts +4 -2
  14. package/dist/audit.js +2 -2
  15. package/dist/bench/s1/live-deps.js +3 -2
  16. package/dist/bench/s1/row.d.ts +5 -2
  17. package/dist/bench/s1/row.js +2 -22
  18. package/dist/boot/adoption.js +1 -1
  19. package/dist/boot/device-lane.d.ts +11 -0
  20. package/dist/boot/device-lane.js +16 -0
  21. package/dist/boot/engine-lease.d.ts +24 -3
  22. package/dist/boot/engine-lease.js +9 -2
  23. package/dist/boot/execution-env.js +18 -12
  24. package/dist/boot/execution-lane.d.ts +8 -0
  25. package/dist/boot/execution-lane.js +6 -1
  26. package/dist/boot/memory-boundary.d.ts +16 -53
  27. package/dist/boot/memory-boundary.js +10 -20
  28. package/dist/boot/memory-consolidation.d.ts +16 -12
  29. package/dist/boot/memory-consolidation.js +24 -13
  30. package/dist/boot/reapers.d.ts +2 -2
  31. package/dist/boot/resolve-spec.d.ts +3 -5
  32. package/dist/boot/resolve-spec.js +9 -8
  33. package/dist/boot/runner-deps.d.ts +3 -3
  34. package/dist/boot/runner-deps.js +1 -0
  35. package/dist/boot/session-faces.d.ts +1 -1
  36. package/dist/boot/session-faces.js +4 -3
  37. package/dist/boot/shutdown.js +5 -0
  38. package/dist/boot/stage-03-store-backend.d.ts +2 -6
  39. package/dist/boot/stage-03-store-backend.js +2 -3
  40. package/dist/boot/stage-04-stores.d.ts +2 -6
  41. package/dist/boot/stage-04-stores.js +5 -5
  42. package/dist/boot/stage-05-execution-env.d.ts +2 -6
  43. package/dist/boot/stage-05-execution-env.js +3 -1
  44. package/dist/boot/stage-06-runners.d.ts +2 -8
  45. package/dist/boot/stage-06-runners.js +3 -3
  46. package/dist/boot/stage-07-capability-layer.d.ts +2 -7
  47. package/dist/boot/stage-07-capability-layer.js +8 -10
  48. package/dist/boot/stage-08-reapers.d.ts +2 -7
  49. package/dist/boot/stage-09-leader.d.ts +2 -7
  50. package/dist/boot/stage-10-http-server.d.ts +2 -7
  51. package/dist/boot/stage-10-http-server.js +6 -4
  52. package/dist/boot/stores.d.ts +3 -6
  53. package/dist/boot/stores.js +37 -44
  54. package/dist/boot/task-list-lane.d.ts +1 -1
  55. package/dist/boot/task-list-lane.js +1 -1
  56. package/dist/boot/web-admin.js +36 -9
  57. package/dist/capabilities/execution-lane.d.ts +2 -2
  58. package/dist/capabilities/scenarios.d.ts +1 -1
  59. package/dist/capability-facts.d.ts +9 -0
  60. package/dist/capability-facts.js +9 -0
  61. package/dist/card-void.d.ts +38 -0
  62. package/dist/card-void.js +23 -0
  63. package/dist/config-catalog.js +12 -8
  64. package/dist/config-provider.d.ts +18 -17
  65. package/dist/config-provider.js +28 -36
  66. package/dist/config-types.d.ts +36 -9
  67. package/dist/config.js +56 -46
  68. package/dist/delegated-session-owner.d.ts +23 -20
  69. package/dist/delegated-session-owner.js +2 -2
  70. package/dist/deployment-shape.d.ts +9 -8
  71. package/dist/deployment-shape.js +4 -4
  72. package/dist/device-store.d.ts +7 -0
  73. package/dist/device-store.js +3 -0
  74. package/dist/execution-config-root.d.ts +22 -0
  75. package/dist/execution-config-root.js +35 -0
  76. package/dist/execution-lane-caps.d.ts +145 -107
  77. package/dist/execution-lane-caps.js +144 -83
  78. package/dist/execution-placement.d.ts +3 -0
  79. package/dist/execution-placement.js +7 -0
  80. package/dist/fleet/drain-entry.d.ts +3 -0
  81. package/dist/hosted-posture.d.ts +8 -0
  82. package/dist/hosted-posture.js +4 -0
  83. package/dist/http/admission.js +3 -3
  84. package/dist/http/caller-trust.d.ts +3 -2
  85. package/dist/http/caller-trust.js +2 -1
  86. package/dist/http/dispatch.js +4 -0
  87. package/dist/http/live-frame.d.ts +24 -0
  88. package/dist/http/live-frame.js +16 -0
  89. package/dist/http/memory-compliance-failure-reply.d.ts +3 -1
  90. package/dist/http/memory-compliance-failure-reply.js +5 -0
  91. package/dist/http/memory-layer-reply.d.ts +30 -0
  92. package/dist/http/memory-layer-reply.js +24 -0
  93. package/dist/http/resume-legs.js +49 -35
  94. package/dist/http/retired-service-deps.d.ts +1 -1
  95. package/dist/http/retired-service-deps.js +1 -1
  96. package/dist/http/route-table.js +2 -0
  97. package/dist/http/routes/adoption.js +1 -1
  98. package/dist/http/routes/approvals-assistant.js +1 -0
  99. package/dist/http/routes/capabilities.js +5 -4
  100. package/dist/http/routes/diagnostics.d.ts +0 -19
  101. package/dist/http/routes/diagnostics.js +16 -2
  102. package/dist/http/routes/memory-bundle.d.ts +2 -2
  103. package/dist/http/routes/memory-bundle.js +4 -1
  104. package/dist/http/routes/memory-compliance.js +9 -2
  105. package/dist/http/routes/memory-consolidation.js +12 -1
  106. package/dist/http/routes/memory-origin.js +14 -2
  107. package/dist/http/routes/memory-policy.js +7 -2
  108. package/dist/http/routes/run-permission-mode.d.ts +75 -0
  109. package/dist/http/routes/run-permission-mode.js +170 -0
  110. package/dist/http/routes/session-sync.d.ts +3 -6
  111. package/dist/http/routes/session-sync.js +7 -2
  112. package/dist/http/routes/sessions.js +33 -15
  113. package/dist/http/routes/tasks.js +67 -68
  114. package/dist/http/run-read-face.js +3 -3
  115. package/dist/http/send.d.ts +1 -1
  116. package/dist/http/send.js +2 -2
  117. package/dist/http/server.d.ts +14 -27
  118. package/dist/http/server.js +2 -2
  119. package/dist/http/sse-log.d.ts +3 -8
  120. package/dist/http/stored-body-replay.d.ts +3 -3
  121. package/dist/http/stored-body-replay.js +3 -1
  122. package/dist/identity-source.d.ts +1 -1
  123. package/dist/identity-source.js +1 -1
  124. package/dist/instruction-source-notice.d.ts +7 -0
  125. package/dist/instruction-source-notice.js +6 -6
  126. package/dist/lane-home-probe.d.ts +68 -42
  127. package/dist/lane-home-probe.js +53 -30
  128. package/dist/leader/wire.js +5 -4
  129. package/dist/mcp-assertion-header.d.ts +4 -0
  130. package/dist/mcp-assertion-header.js +5 -0
  131. package/dist/memory-bundle-engine.d.ts +16 -9
  132. package/dist/memory-bundle-engine.js +29 -6
  133. package/dist/memory-operator-faces.d.ts +85 -30
  134. package/dist/memory-operator-faces.js +136 -30
  135. package/dist/memory-posture.d.ts +1 -1
  136. package/dist/memory-project-layer.d.ts +3 -21
  137. package/dist/memory-project-layer.js +11 -8
  138. package/dist/memory-scope-stores.d.ts +73 -0
  139. package/dist/memory-scope-stores.js +86 -0
  140. package/dist/memory-scope.d.ts +33 -9
  141. package/dist/memory-scope.js +17 -5
  142. package/dist/memory-sync-client.d.ts +34 -9
  143. package/dist/memory-sync-client.js +108 -28
  144. package/dist/observability/fail-open.d.ts +30 -2
  145. package/dist/observability/fail-open.js +30 -2
  146. package/dist/observability/metrics.js +0 -1
  147. package/dist/observability/run-terminal.d.ts +6 -2
  148. package/dist/observability/run-terminal.js +25 -26
  149. package/dist/observability/secret-env-scrub.d.ts +20 -1
  150. package/dist/observability/secret-env-scrub.js +14 -0
  151. package/dist/orchestration/workflow-completion-inbox.d.ts +5 -2
  152. package/dist/orchestration/workflow-completion-inbox.js +13 -5
  153. package/dist/orchestration/workflow-notify-journal.d.ts +5 -3
  154. package/dist/orchestration/workflow-notify-journal.js +2 -1
  155. package/dist/permission-mode-admission.d.ts +68 -0
  156. package/dist/permission-mode-admission.js +23 -0
  157. package/dist/permission-rule-list.d.ts +55 -6
  158. package/dist/permission-rule-list.js +52 -5
  159. package/dist/plugins/adoption-log-sql.js +4 -4
  160. package/dist/plugins/approval-ask-store-sql.js +14 -14
  161. package/dist/plugins/approval-nonce-store.js +4 -4
  162. package/dist/plugins/blob-backend.d.ts +4 -4
  163. package/dist/plugins/blob-backend.js +7 -7
  164. package/dist/plugins/breaker-state-sql.js +2 -2
  165. package/dist/plugins/caching-session-store.d.ts +6 -0
  166. package/dist/plugins/caching-session-store.js +3 -0
  167. package/dist/plugins/checkpoint-index-columns.js +2 -2
  168. package/dist/plugins/checkpoint-store-sql.d.ts +65 -17
  169. package/dist/plugins/checkpoint-store-sql.js +90 -19
  170. package/dist/plugins/device-store-sql.d.ts +5 -2
  171. package/dist/plugins/device-store-sql.js +23 -20
  172. package/dist/plugins/ensure-index.d.ts +1 -2
  173. package/dist/plugins/execution-placement-sql.d.ts +19 -9
  174. package/dist/plugins/execution-placement-sql.js +20 -9
  175. package/dist/plugins/file-history-store-sql.d.ts +2 -2
  176. package/dist/plugins/file-history-store-sql.js +4 -4
  177. package/dist/plugins/file-run-store.d.ts +2 -2
  178. package/dist/plugins/file-run-store.js +1 -1
  179. package/dist/plugins/fork-routing-session-store.d.ts +10 -32
  180. package/dist/plugins/fork-routing-session-store.js +2 -61
  181. package/dist/plugins/image-bake-store-sql.js +9 -9
  182. package/dist/plugins/image-index-sql.js +11 -11
  183. package/dist/plugins/k8s-exec-protocol.d.ts +4 -1
  184. package/dist/plugins/k8s-exec-protocol.js +6 -1
  185. package/dist/plugins/leader-run-store-sql.js +4 -4
  186. package/dist/plugins/local-checkpoint-store.d.ts +10 -1
  187. package/dist/plugins/local-checkpoint-store.js +22 -0
  188. package/dist/plugins/local-session-store.d.ts +227 -35
  189. package/dist/plugins/local-session-store.js +518 -37
  190. package/dist/plugins/local-session-window.d.ts +17 -3
  191. package/dist/plugins/local-session-window.js +7 -13
  192. package/dist/plugins/mailbox-store-sql.d.ts +2 -1
  193. package/dist/plugins/mailbox-store-sql.js +4 -4
  194. package/dist/plugins/memory-engine-tidb.js +5 -5
  195. package/dist/plugins/memory-optout-grant-store-sql.js +1 -1
  196. package/dist/plugins/memory-run-store.d.ts +2 -2
  197. package/dist/plugins/memory-run-store.js +1 -1
  198. package/dist/plugins/memory-sync-store-tidb.js +3 -3
  199. package/dist/plugins/one-time-migrations.d.ts +52 -11
  200. package/dist/plugins/one-time-migrations.js +101 -39
  201. package/dist/plugins/org-delivery-quota-store.js +2 -2
  202. package/dist/plugins/outcome-ledger-sql.js +2 -2
  203. package/dist/plugins/permission-rule-store-sql.d.ts +4 -4
  204. package/dist/plugins/permission-rule-store-sql.js +16 -16
  205. package/dist/plugins/pg-pool.js +3 -2
  206. package/dist/plugins/pg-session-storage.d.ts +2 -0
  207. package/dist/plugins/pg-session-storage.js +3 -2
  208. package/dist/plugins/remote-env-adb.d.ts +7 -24
  209. package/dist/plugins/remote-env-adb.js +22 -5
  210. package/dist/plugins/remote-env-device.d.ts +2 -28
  211. package/dist/plugins/remote-env-device.js +2 -1
  212. package/dist/plugins/remote-env-e2b.d.ts +40 -27
  213. package/dist/plugins/remote-env-e2b.js +180 -20
  214. package/dist/plugins/remote-env-file-error.d.ts +1 -1
  215. package/dist/plugins/remote-env-file-error.js +8 -2
  216. package/dist/plugins/remote-env-host.d.ts +19 -35
  217. package/dist/plugins/remote-env-host.js +26 -3
  218. package/dist/plugins/remote-env-k8s.d.ts +22 -14
  219. package/dist/plugins/remote-env-k8s.js +150 -26
  220. package/dist/plugins/remote-env-local-docker.d.ts +27 -24
  221. package/dist/plugins/remote-env-local-docker.js +91 -24
  222. package/dist/plugins/remote-env-ssh.d.ts +4 -24
  223. package/dist/plugins/remote-env-ssh.js +4 -3
  224. package/dist/plugins/resume-anchor-store-sql.js +2 -2
  225. package/dist/plugins/retention-lane-store-sql.d.ts +1 -1
  226. package/dist/plugins/retention-lane-store-sql.js +2 -2
  227. package/dist/plugins/retention-store-sql.d.ts +1 -1
  228. package/dist/plugins/retention-store-sql.js +6 -6
  229. package/dist/plugins/run-store-sql.d.ts +3 -3
  230. package/dist/plugins/run-store-sql.js +19 -18
  231. package/dist/plugins/sandbox-read-floor.d.ts +273 -0
  232. package/dist/plugins/sandbox-read-floor.js +608 -0
  233. package/dist/plugins/schema-consistency.d.ts +6 -6
  234. package/dist/plugins/schema-consistency.js +1 -1
  235. package/dist/plugins/schema-ensure-legs.d.ts +2 -3
  236. package/dist/plugins/schema-ensure-legs.js +2 -2
  237. package/dist/plugins/schema-live-columns.d.ts +1 -1
  238. package/dist/plugins/session-capture-record-store-sql.js +1 -1
  239. package/dist/plugins/session-ownership.d.ts +2 -1
  240. package/dist/plugins/session-placement.d.ts +17 -4
  241. package/dist/plugins/session-placement.js +2 -1
  242. package/dist/plugins/session-rules-column.d.ts +1 -1
  243. package/dist/plugins/session-rules-column.js +1 -1
  244. package/dist/plugins/session-store.d.ts +18 -20
  245. package/dist/plugins/session-store.js +4 -12
  246. package/dist/plugins/session-workspace-cell.d.ts +1 -1
  247. package/dist/plugins/session-workspace-cell.js +1 -1
  248. package/dist/plugins/shared-memory-store-sql.js +2 -2
  249. package/dist/plugins/sql-driver.d.ts +10 -5
  250. package/dist/plugins/sql-driver.js +6 -6
  251. package/dist/plugins/sql-errors.js +1 -1
  252. package/dist/plugins/store-backend.d.ts +35 -6
  253. package/dist/plugins/store-backend.js +27 -10
  254. package/dist/plugins/store-contracts.d.ts +9 -2
  255. package/dist/plugins/task-list-store-sql.js +11 -11
  256. package/dist/plugins/tidb-pool.js +7 -6
  257. package/dist/plugins/tidb-session-storage.js +4 -4
  258. package/dist/plugins/tidb-session-store.d.ts +4 -1
  259. package/dist/plugins/tidb-session-store.js +16 -15
  260. package/dist/plugins/tool-result-store-sql.d.ts +2 -2
  261. package/dist/plugins/tool-result-store-sql.js +3 -3
  262. package/dist/plugins/user-input-ledger-sql.js +2 -2
  263. package/dist/plugins/workflow-journal-store-sql.js +5 -5
  264. package/dist/plugins/workflow-run-store-sql.js +19 -19
  265. package/dist/plugins/write-behind-counter.d.ts +2 -3
  266. package/dist/plugins/write-behind-counter.js +5 -5
  267. package/dist/resource-suspend.d.ts +14 -12
  268. package/dist/resource-suspend.js +1 -1
  269. package/dist/resource-window.d.ts +4 -3
  270. package/dist/run-cancel-context.d.ts +34 -0
  271. package/dist/run-cancel-context.js +7 -0
  272. package/dist/run-local.js +14 -19
  273. package/dist/runs.d.ts +47 -16
  274. package/dist/runs.js +112 -113
  275. package/dist/security.d.ts +2 -2
  276. package/dist/server-secret-env.d.ts +2 -1
  277. package/dist/server-secret-env.js +2 -4
  278. package/dist/session-error-wire.d.ts +22 -4
  279. package/dist/session-error-wire.js +16 -0
  280. package/dist/session-incarnation.d.ts +10 -4
  281. package/dist/session-incarnation.js +1 -1
  282. package/dist/session-policy-wire.d.ts +1 -1
  283. package/dist/session-sync-kernel.d.ts +42 -1
  284. package/dist/session-sync-kernel.js +17 -0
  285. package/dist/session-sync.js +16 -4
  286. package/dist/sql-engine-coordinates.d.ts +49 -0
  287. package/dist/sql-engine-coordinates.js +27 -0
  288. package/dist/sql-engine-posture.d.ts +1 -1
  289. package/dist/sql-engine-posture.js +1 -1
  290. package/dist/standing-answer-grant.d.ts +31 -2
  291. package/dist/standing-answer-grant.js +14 -2
  292. package/dist/store-posture.d.ts +1 -1
  293. package/dist/{plugins → stores-sql}/background-agent-store-sql.d.ts +2 -2
  294. package/dist/{plugins → stores-sql}/background-agent-store-sql.js +8 -8
  295. package/dist/{plugins → stores-sql}/session-policy-store-sql.d.ts +7 -5
  296. package/dist/{plugins → stores-sql}/session-policy-store-sql.js +12 -12
  297. package/dist/{plugins → stores-sql}/usage-window-store-sql.d.ts +1 -1
  298. package/dist/{plugins → stores-sql}/usage-window-store-sql.js +3 -3
  299. package/dist/task-a2a.d.ts +1 -1
  300. package/dist/task-a2a.js +5 -6
  301. package/dist/task-mcp.d.ts +21 -8
  302. package/dist/task-mcp.js +17 -9
  303. package/dist/task-settings.d.ts +52 -25
  304. package/dist/task-settings.js +91 -28
  305. package/dist/terminal.d.ts +103 -19
  306. package/dist/terminal.js +72 -20
  307. package/dist/trace/core-keyset-guard.d.ts +79 -2
  308. package/dist/trace/exit-seat.d.ts +7 -0
  309. package/dist/trace/exit-seat.js +1 -0
  310. package/dist/trace/model-segment.d.ts +2 -2
  311. package/dist/trace/redact.d.ts +3 -1
  312. package/dist/trace/redact.js +395 -110
  313. package/dist/trace/self-minted-wire.d.ts +226 -2
  314. package/dist/trace/self-minted-wire.js +79 -0
  315. package/dist/verifier-pause-card.d.ts +8 -0
  316. package/dist/verifier-pause-card.js +19 -0
  317. package/dist/web-admin-client/apply-effective.d.ts +5 -7
  318. package/dist/web-admin-client/apply-effective.js +2 -2
  319. package/dist/web-admin-client/candidate-gate.d.ts +11 -7
  320. package/dist/web-admin-client/candidate-gate.js +1 -1
  321. package/dist/web-admin-client/http-client.d.ts +5 -4
  322. package/dist/web-admin-client/http-client.js +2 -2
  323. package/dist/web-admin-client/read-warnings.d.ts +7 -17
  324. package/dist/web-admin-client/read-warnings.js +5 -9
  325. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +3 -2
  326. package/package.json +2 -2
  327. package/wire-changes/server@7.140.0.json +184 -0
  328. package/wire-changes/server@7.141.0.json +367 -0
@@ -1,15 +1,16 @@
1
1
  import { redactErrorMessage, redactHead } from "../observability/run-terminal.js";
2
2
  import { createHash } from "node:crypto";
3
- import { uuidv7, resumeWithVerification, CheckpointError, defaultTaskRegistry, taskNotificationDedupKey, validatePendingSteer, GLOBAL_USAGE_KEY, PAUSE_REGISTRY } from "@sema-agent/core";
3
+ import { uuidv7, resumeWithVerification, CheckpointError, defaultTaskRegistry, taskNotificationDedupKey, validatePendingSteer, GLOBAL_USAGE_KEY } from "@sema-agent/core";
4
4
  import { decideParkedAgent, denyWorkflowParkForked, denyWorkflowParksUnreadable, findParkOrigin, heldWorkflowParkDecisions, planWorkflowParkedDecide } from "../parked-decide.js";
5
5
  import { parkDecisionFingerprint } from "../orchestration/workflow-park-decision.js";
6
6
  import { headReadOf } from "../session-incarnation.js";
7
7
  import { createSessionWorkspaceRecorder, legSessionWitnessOf, sessionWorkspaceStoreOf } from "../session-workspace.js";
8
8
  const DELIVERY_NOT_RECORDED = "workflow park decide: this delivery no longer holds the host session (its claim was released) — the decision was not recorded and this delivery was not started";
9
9
  import { HttpError, decodeCheckpointScope, CHECKPOINT_PUBLIC_SCOPE } from "../security.js";
10
- import { graftParkToolCallId, parkToolCallId, TurnAnchorCapture, HEARTBEAT_MS, markChildrenStoppedByUserOnAbort } from "../runs.js";
11
- import { failureCodeOf, nestedPauseOf, sealResultForExit, outwardPlane } from "../terminal.js";
12
- import { buildCancelledLedgerRow, createRunAbort, mintCancelledResult } from "../run-cancel-context.js";
10
+ import { graftParkToolCallId, parkToolCallId, TurnAnchorCapture, HEARTBEAT_MS, markChildrenStoppedByUserOnAbort, voidHeldParkCard } from "../runs.js";
11
+ import { atHostBoundary, failureCodeOf, nestedPauseOf, sealResultForExit, outwardPlane } from "../terminal.js";
12
+ import { voidVerifierPauseCard } from "../verifier-pause-card.js";
13
+ import { buildCancelledLedgerRow, CARD_SETTLED_BY_CANCEL_MESSAGE, createRunAbort, mintCancelledResult, withCardSettledByCancelMessage } from "../run-cancel-context.js";
13
14
  import { isTerminalRunStatus } from "../plugins/store-contracts.js";
14
15
  import { readTurnActivityMs, recordTurnActivity } from "../turn-activity.js";
15
16
  import { recordResumeResourceWindow } from "../resource-window.js";
@@ -51,6 +52,7 @@ import { commitExecutionContext, isRootSessionGoneError, resolveExecutionContext
51
52
  import { commitSessionInheritEnv } from "./session-inherit-env.js";
52
53
  import { ASK_USER_QUESTION_TOOL_NAME, isApprovalGateKind, isEngineQuestionRow } from "../approval-content-kind.js";
53
54
  import { deploymentListAsks } from "../approval.js";
55
+ import { isParkLedgerEventType } from "../trace/ledger-events.js";
54
56
  import { readResumeCtx, resumeCtxCorruptAnswer, resumeCtxUnsealableAnswer } from "./resume-ctx-read.js";
55
57
  import { buildCheckpointVersionKeys, resumeBlockedByPolicyAnswer, resumeRefusalWithCard, sealCheckpointCtx, storedBodyReplayAnswer, storedBodyReplayLogFields, withPermissionModeRewritten } from "./checkpoint-ctx.js";
56
58
  import { refusalBody, resumeRefusalFacts } from "./refusal-body.js";
@@ -61,12 +63,6 @@ import { fieldConflictFacts } from "../field-conflict.js";
61
63
  function legMayHaveReopenedCheckpoint(r) {
62
64
  return r.terminal.kind === "failed" && nestedPauseOf(r.terminal) === undefined;
63
65
  }
64
- function nestedParkStatusOf(r) {
65
- const paused = nestedPauseOf(r.terminal);
66
- if (paused === undefined)
67
- return undefined;
68
- return PAUSE_REGISTRY[paused.gate.kind].taskStatus;
69
- }
70
66
  const WORKER_SWAP_REDEEMABLE = {
71
67
  version_newer: true,
72
68
  env_factory_missing: true,
@@ -684,6 +680,7 @@ export function createResumeLegs(ctx) {
684
680
  fleetPub?.onTerminal(status, residuals);
685
681
  };
686
682
  let result;
683
+ let heldPark;
687
684
  let reopenConfirmedPark = false;
688
685
  const confirmCheckpointReopened = async () => {
689
686
  const store = deps.checkpointStore;
@@ -700,28 +697,32 @@ export function createResumeLegs(ctx) {
700
697
  const settleCardForCancel = async () => {
701
698
  const cs2 = deps.checkpointStore;
702
699
  if (!cs2)
703
- return;
700
+ return false;
704
701
  try {
705
702
  const live = await cs2.get(token);
706
- if (live?.status === "pending" && !(await cs2.expire(token, live.scope))) {
707
- deps.logger?.warn?.("resume_cancel_checkpoint_settle_lost", { taskId, sessionId });
708
- }
703
+ if (live?.status !== "pending")
704
+ return false;
705
+ if (await cs2.expire(token, live.scope))
706
+ return true;
707
+ deps.logger?.warn?.("resume_cancel_checkpoint_settle_lost", { taskId, sessionId });
708
+ return false;
709
709
  }
710
710
  catch (cancelSettleErr) {
711
711
  deps.logger?.warn?.("resume_cancel_checkpoint_settle_failed", {
712
712
  taskId, sessionId, err: cancelSettleErr instanceof Error ? cancelSettleErr.message : String(cancelSettleErr),
713
713
  });
714
+ return false;
714
715
  }
715
716
  };
716
717
  const reopenedAfterLeg = async (leg, cancelledAtDone) => {
717
718
  if (freshRunClaimed || !legMayHaveReopenedCheckpoint(leg))
718
- return false;
719
+ return { reopened: false, leg };
719
720
  const pending = cancelledAtDone ? false : await confirmCheckpointReopened();
720
721
  if (cancelledAtDone || cancelCtrl.cause() !== undefined) {
721
- await settleCardForCancel();
722
- return false;
722
+ const expired = await settleCardForCancel();
723
+ return { reopened: false, leg: expired ? withCardSettledByCancelMessage(leg) : leg };
723
724
  }
724
- return pending;
725
+ return { reopened: pending, leg };
725
726
  };
726
727
  let resumeHeartbeat;
727
728
  let resumeManifestLease = 0;
@@ -855,13 +856,18 @@ export function createResumeLegs(ctx) {
855
856
  resumeLegLive = true;
856
857
  const vrEngine = await resumeWithVerification(legRunner, token, outcome, { ...resumeTaskConfig, signal: cancelCtrl.signal, preemptSignal: preemptCtrl.signal }, resumeObjective, verifyRounds, verifyInternals);
857
858
  const vrCause = cancelCtrl.cause();
858
- const vr = vrCause !== undefined && taskId !== undefined ? mintCancelledResult({ taskId, sessionId, startedAtMs: resumeLegStartedAt, message: "cancelled by user", engineResult: vrEngine, cause: vrCause }) : vrEngine;
859
+ await voidVerifierPauseCard(vrEngine, deps.checkpointStore);
860
+ const vrJudged = atHostBoundary(vrEngine, sessionId);
861
+ if (vrJudged.terminal.kind === "paused")
862
+ heldPark = vrJudged;
863
+ const vrMinted = vrCause !== undefined && taskId !== undefined ? mintCancelledResult({ taskId, sessionId, startedAtMs: resumeLegStartedAt, message: "cancelled by user", engineResult: vrJudged, cause: vrCause }) : vrJudged;
859
864
  await commitResumeCtx();
865
+ const { reopened: vrReopened, leg: vr } = await reopenedAfterLeg(vrMinted, vrCause !== undefined);
860
866
  let safe = sealResultForExit(vr);
861
- const vrNested = nestedPauseOf(vr.terminal);
862
- const reParkStatus = nestedParkStatusOf(vr);
863
- const reSuspended = vrNested !== undefined;
864
- const vrReopened = await reopenedAfterLeg(vr, vrCause !== undefined);
867
+ const vrPaused = vr.terminal.kind === "paused" ? vr.terminal : undefined;
868
+ const vrParkWord = vrPaused !== undefined ? outwardPlane(vrPaused).status : undefined;
869
+ const reParkEvent = vrParkWord !== undefined && isParkLedgerEventType(vrParkWord) ? vrParkWord : undefined;
870
+ const reSuspended = reParkEvent !== undefined;
865
871
  if (vrReopened)
866
872
  reopenConfirmedPark = true;
867
873
  if (taskId && deps.runStore) {
@@ -871,8 +877,8 @@ export function createResumeLegs(ctx) {
871
877
  await appendPromptManifest(ap, deps.promptManifests, taskId);
872
878
  if (reSuspended || vrReopened) {
873
879
  await appendModelUsageDelta(ap, deps.modelUsage, taskId);
874
- const vrParkCallId = vrNested !== undefined ? await parkToolCallId({ terminal: vrNested }, deps.checkpointStore) : undefined;
875
- await ap(reParkStatus ?? reparkStatus, parkEventData({ terminal: vrNested, ...(vrParkCallId !== undefined ? { toolCallId: vrParkCallId } : {}) }, vrReopened ? (failureCodeOf(vr.terminal) ?? null) : undefined));
880
+ const vrParkCallId = reSuspended ? await parkToolCallId(vr, deps.checkpointStore) : undefined;
881
+ await ap(reParkEvent ?? reparkStatus, parkEventData({ terminal: vrPaused, ...(vrParkCallId !== undefined ? { toolCallId: vrParkCallId } : {}) }, vrReopened ? (failureCodeOf(vr.terminal) ?? null) : undefined));
876
882
  }
877
883
  else {
878
884
  safe = await attachModelUsage(safe, { append: ap, getEvents: (id, a) => rs2.getEvents(id, a), modelUsage: deps.modelUsage, taskId });
@@ -884,8 +890,8 @@ export function createResumeLegs(ctx) {
884
890
  throw e;
885
891
  }
886
892
  }
887
- if (vrNested !== undefined)
888
- return { ...safe, terminal: vrNested };
893
+ if (reSuspended)
894
+ return safe;
889
895
  if (vr.verification?.verdict)
890
896
  deps.metrics?.inc("verifications_total", { verdict: vr.verification.verdict });
891
897
  return safe;
@@ -919,7 +925,7 @@ export function createResumeLegs(ctx) {
919
925
  const captureUserMessageAnchor = deps.resumeAnchorStore && taskId
920
926
  ? async (entryId) => { await deps.resumeAnchorStore.put(sessionId, taskId, entryId, anchorOwner); }
921
927
  : undefined;
922
- const anchor = new TurnAnchorCapture(captureTurnAnchor, () => deps.metrics?.inc("resume_anchor_capture_failed"), captureUserMessageAnchor);
928
+ const anchor = new TurnAnchorCapture(captureTurnAnchor, "resume", captureUserMessageAnchor);
923
929
  const flush = async () => {
924
930
  if (reasoning) {
925
931
  await append("reasoning", modelTextEventData({ text: reasoning, eventId: reasoningEventId }));
@@ -1000,15 +1006,18 @@ export function createResumeLegs(ctx) {
1000
1006
  for await (const ev of stream)
1001
1007
  await resumeWorkspace.observe(ev);
1002
1008
  const rNoRow = await stream.result();
1003
- if (await reopenedAfterLeg(rNoRow, cancelCtrl.cause() !== undefined))
1009
+ const noRowLeg = await reopenedAfterLeg(rNoRow, cancelCtrl.cause() !== undefined);
1010
+ if (noRowLeg.reopened)
1004
1011
  reopenConfirmedPark = true;
1005
- return sealResultForExit(rNoRow);
1012
+ return sealResultForExit(noRowLeg.leg);
1006
1013
  }
1007
1014
  onAccepted?.(acceptedResumingReceipt(taskId, sessionId, buildSettlementEvidence({ at: "engine_accepted", commitment: args.commitment })));
1008
1015
  let causeAtDone;
1009
1016
  for await (const ev of stream) {
1010
1017
  if (ev.type === "done")
1011
1018
  causeAtDone = cancelCtrl.cause();
1019
+ if (ev.type === "done" && ev.result.terminal.kind === "paused")
1020
+ heldPark = ev.result;
1012
1021
  recordTurnActivity(taskId);
1013
1022
  fleetPub?.onEvent(ev);
1014
1023
  await deps.userInputLedger?.observeLegEvent(stream, ev);
@@ -1128,6 +1137,8 @@ export function createResumeLegs(ctx) {
1128
1137
  await flush();
1129
1138
  const rEngine = await stream.result();
1130
1139
  const r = causeAtDone !== undefined ? mintCancelledResult({ taskId, sessionId, startedAtMs: resumeLegStartedAt, message: "cancelled by user", engineResult: rEngine, cause: causeAtDone }) : rEngine;
1140
+ if (r.terminal.kind === "paused")
1141
+ heldPark = r;
1131
1142
  const rPark = r.terminal.kind === "paused" ? outwardPlane(r.terminal).status : undefined;
1132
1143
  if (rPark === "suspended") {
1133
1144
  await append("suspended", parkEventData(await graftParkToolCallId(r, deps.checkpointStore)));
@@ -1139,7 +1150,8 @@ export function createResumeLegs(ctx) {
1139
1150
  await appendModelUsageDelta(append, deps.modelUsage, taskId);
1140
1151
  return r;
1141
1152
  }
1142
- if (await reopenedAfterLeg(r, causeAtDone !== undefined)) {
1153
+ const settledLeg = await reopenedAfterLeg(r, causeAtDone !== undefined);
1154
+ if (settledLeg.reopened) {
1143
1155
  reopenConfirmedPark = true;
1144
1156
  try {
1145
1157
  await append(reparkStatus, parkEventData(r, failureCodeOf(r.terminal) ?? null));
@@ -1149,7 +1161,7 @@ export function createResumeLegs(ctx) {
1149
1161
  }
1150
1162
  return r;
1151
1163
  }
1152
- const safe = await attachModelUsage(sealResultForExit(r), { append, getEvents: (id, a) => rs.getEvents(id, a), modelUsage: deps.modelUsage, taskId });
1164
+ const safe = await attachModelUsage(sealResultForExit(settledLeg.leg), { append, getEvents: (id, a) => rs.getEvents(id, a), modelUsage: deps.modelUsage, taskId });
1153
1165
  await append("done", { result: safe });
1154
1166
  if (taskConfig.suggestNextPrompts && safe.terminal.kind === "completed") {
1155
1167
  const suggestions = await stream.suggestions().catch(() => []);
@@ -1187,14 +1199,14 @@ export function createResumeLegs(ctx) {
1187
1199
  if (e instanceof CheckpointError) {
1188
1200
  const disposition = resumeRefusalDisposition(e);
1189
1201
  if (disposition === "cancelled") {
1190
- await settleCardForCancel();
1202
+ const abortedText = (await settleCardForCancel()) ? CARD_SETTLED_BY_CANCEL_MESSAGE : e.message;
1191
1203
  if (claimedRow && taskId && deps.runStore) {
1192
1204
  const handleCause = cancelCtrl.cause();
1193
1205
  if (handleCause === undefined)
1194
1206
  recordFailOpen("server.runs.abort-cause-missing", `task=${taskId} arm=resume-aborted`);
1195
- const c = mintCancelledResult({ taskId, sessionId, startedAtMs: resumeLegStartedAt, message: e.message, cause: handleCause ?? "cancel_verb" });
1207
+ const c = mintCancelledResult({ taskId, sessionId, startedAtMs: resumeLegStartedAt, message: abortedText, cause: handleCause ?? "cancel_verb" });
1196
1208
  await cancelLedgerAppend?.("failed", buildCancelledLedgerRow(c)).catch((err) => recordFailOpen("server.runs.terminal-ledger-write-failed", `arm=resume-append-resume-aborted ${errorText(err)}`));
1197
- await deps.runStore.setTerminal(taskId, "failed", c, e.message).catch(() => undefined);
1209
+ await deps.runStore.setTerminal(taskId, "failed", c, abortedText).catch(() => undefined);
1198
1210
  }
1199
1211
  settleFleet("failed");
1200
1212
  return { status: 200, body: { taskId, sessionId, status: "failed", errorCode: "cancelled" } };
@@ -1222,6 +1234,7 @@ export function createResumeLegs(ctx) {
1222
1234
  const thrownCause = cancelCtrl.cause();
1223
1235
  if (thrownCause !== undefined) {
1224
1236
  if (taskId && deps.runStore) {
1237
+ await voidHeldParkCard(heldPark, sessionId, deps.checkpointStore, "resume");
1225
1238
  const c = mintCancelledResult({ taskId, sessionId, startedAtMs: resumeLegStartedAt, message: "cancelled by user", cause: thrownCause });
1226
1239
  await cancelLedgerAppend?.("failed", buildCancelledLedgerRow(c)).catch((err) => recordFailOpen("server.runs.terminal-ledger-write-failed", `arm=resume-append-thrown-cancel ${errorText(err)}`));
1227
1240
  await deps.runStore.setTerminal(taskId, "failed", c, "cancelled by user").catch(() => undefined);
@@ -1230,6 +1243,7 @@ export function createResumeLegs(ctx) {
1230
1243
  return { status: 200, body: { taskId, sessionId, status: "failed", errorCode: "cancelled" } };
1231
1244
  }
1232
1245
  if (claimedRow && taskId && deps.runStore) {
1246
+ await voidHeldParkCard(heldPark, sessionId, deps.checkpointStore, "resume");
1233
1247
  await deps.runStore.setTerminal(taskId, "failed", null, errorText(e)).catch(() => undefined);
1234
1248
  }
1235
1249
  settleFleet("failed");
@@ -22,7 +22,7 @@ export interface RetiredServiceDep {
22
22
  export declare const RETIRED_SERVICE_DEPS: {
23
23
  readonly sqlEngineFacts: {
24
24
  readonly retiredIn: "7.132.0";
25
- readonly wayOut: "replaced by sqlEngine — pass the SQL pool's engine reading as sqlEngine: `{ dialect: \"tidb\" | \"pg\", facts }` where `facts` is read live (a getter) and is null while the pool's connection setup has not succeeded, or leave both unset when there is no SQL store";
25
+ readonly wayOut: "replaced by sqlEngine — pass the SQL pool's engine reading as sqlEngine: `{ dialect: \"mysql\" | \"pg\", facts }` where `facts` is read live (a getter) and is null while the pool's connection setup has not succeeded, or leave both unset when there is no SQL store";
26
26
  };
27
27
  readonly snapshotBlobSqlCapBytes: {
28
28
  readonly retiredIn: "7.132.0";
@@ -2,7 +2,7 @@ const BLOB_CAP_WAY_OUT = "the HTTP surface no longer holds a blob cap of its own
2
2
  export const RETIRED_SERVICE_DEPS = {
3
3
  sqlEngineFacts: {
4
4
  retiredIn: "7.132.0",
5
- wayOut: "replaced by sqlEngine — pass the SQL pool's engine reading as sqlEngine: `{ dialect: \"tidb\" | \"pg\", facts }` where `facts` is read live (a getter) and is null while the pool's connection setup has not succeeded, or leave both unset when there is no SQL store",
5
+ wayOut: "replaced by sqlEngine — pass the SQL pool's engine reading as sqlEngine: `{ dialect: \"mysql\" | \"pg\", facts }` where `facts` is read live (a getter) and is null while the pool's connection setup has not succeeded, or leave both unset when there is no SQL store",
6
6
  },
7
7
  snapshotBlobSqlCapBytes: { retiredIn: "7.132.0", wayOut: BLOB_CAP_WAY_OUT },
8
8
  snapshotBlobSqlCap: { retiredIn: "7.133.0", wayOut: BLOB_CAP_WAY_OUT },
@@ -29,6 +29,7 @@ import { handleNotifyWake, NOTIFY_WAKE_ROUTES } from "./routes/notify-wake.js";
29
29
  import { handleApprovalsAssistant, APPROVALS_ASSISTANT_ROUTES } from "./routes/approvals-assistant.js";
30
30
  import { handleRuns, handleRunVerbs, RUNS_ROUTES, RUN_VERBS_ROUTES } from "./routes/runs.js";
31
31
  import { handleRunMemoryCapture, RUN_MEMORY_CAPTURE_ROUTES } from "./routes/run-memory-capture.js";
32
+ import { handlePermissionMode, RUN_PERMISSION_MODE_ROUTES } from "./routes/run-permission-mode.js";
32
33
  import { handleMcpReconnect, MCP_RECONNECT_ROUTES } from "./routes/mcp-reconnect.js";
33
34
  import { handleBackground, BACKGROUND_ROUTES } from "./routes/background.js";
34
35
  import { handleSideQuery, SIDE_QUERY_ROUTES } from "./routes/side-query.js";
@@ -51,6 +52,7 @@ export const ROUTES = [
51
52
  row({ handler: handleWorkflowAgentSteer, decls: WORKFLOW_AGENT_STEER_ROUTES, position: "post-credential", label: "workflow-agent-steer" }),
52
53
  row({ handler: handleRunVerbs, decls: RUN_VERBS_ROUTES, position: "post-credential", label: "run-verbs" }),
53
54
  row({ handler: handleRunMemoryCapture, decls: RUN_MEMORY_CAPTURE_ROUTES, position: "post-credential", label: "run-memory-capture" }),
55
+ row({ handler: handlePermissionMode, decls: RUN_PERMISSION_MODE_ROUTES, position: "post-credential", label: "permission-mode" }),
54
56
  row({ handler: handleMcpReconnect, decls: MCP_RECONNECT_ROUTES, position: "post-credential", label: "mcp-reconnect" }),
55
57
  row({ handler: handleBackground, decls: BACKGROUND_ROUTES, position: "post-credential", label: "background" }),
56
58
  row({ handler: handleLeader, decls: LEADER_ROUTES, position: "post-credential", label: "leader" }),
@@ -69,7 +69,7 @@ export async function handleAdoption(req, res, match, ctx) {
69
69
  }
70
70
  }
71
71
  const store = fact.backend.adoptionLog();
72
- const runner = createAdoptionRunner({ store, dialect: deps.backend?.kind === "pg" ? "pg" : "tidb", now: Date.now, logger: deps.logger });
72
+ const runner = createAdoptionRunner({ store, dialect: deps.backend?.kind === "pg" ? "pg" : "mysql", now: Date.now, logger: deps.logger });
73
73
  switch (match.decl.id) {
74
74
  case "adoption-detail": {
75
75
  const id = ctx.helpers.safeDecode(match.params.id);
@@ -408,6 +408,7 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
408
408
  ...(s.mandate !== undefined ? { mandate: s.mandate } : {}),
409
409
  ...(s.denialLimitFallback !== undefined ? { denialLimitFallback: s.denialLimitFallback } : {}),
410
410
  ...(s.origin !== undefined ? { origin: s.origin } : {}),
411
+ ...(s.boundGrantDigest !== undefined ? { boundGrantDigest: s.boundGrantDigest } : {}),
411
412
  ...skillCardFacts(s),
412
413
  ...(s.boundGrantAbsence !== undefined ? { boundGrantAbsence: s.boundGrantAbsence } : {}),
413
414
  objective,
@@ -24,7 +24,7 @@ import { projectStoreCapability } from "../../store-posture.js";
24
24
  import { projectWebSearchCapability } from "../../plugins/web-search.js";
25
25
  import { projectExecutionLaneCapability } from "../../capabilities/execution-lane.js";
26
26
  import { judgeSandboxGitPlane, sandboxGitPlanePremisesOf } from "../../sandbox-git-plane.js";
27
- import { MCP_ASSERTION_HEADER_SENT } from "../../mcp-assertion-header.js";
27
+ import { MCP_ASSERTION_HEADER_SENT, MCP_REQUEST_TRANSPORT_KINDS } from "../../mcp-assertion-header.js";
28
28
  import { gateCompositeMembers } from "../../capabilities/composite-members.js";
29
29
  import { projectApprovalsStreamLiveCapability } from "../../capabilities/approvals-push.js";
30
30
  import { workflowModelAllowlistFor } from "../../task-workflow.js";
@@ -96,7 +96,7 @@ export async function handleCapabilities(req, res, match, ctx) {
96
96
  maxInflightPerDevice: deps.config.remoteExec?.provider === "device" ? (deps.config.remoteExec.maxInflightPerDevice ?? 4) : 4,
97
97
  wsPath: DEVICE_WS_PATH,
98
98
  management: facts.deviceManagement(deps).available,
99
- ...(deps.config.remoteExec?.provider === "device" && deps.config.remoteExec.relayUrl !== undefined ? { relayUrl: deps.config.remoteExec.relayUrl } : {}),
99
+ ...(deps.config.remoteExec?.provider === "device" && deps.config.remoteExec.relay.kind === "url" ? { relayUrl: deps.config.remoteExec.relay.url } : {}),
100
100
  }
101
101
  : false,
102
102
  sessionEvents: facts.sessionEventStream(deps).available,
@@ -133,7 +133,7 @@ export async function handleCapabilities(req, res, match, ctx) {
133
133
  oneShot: true,
134
134
  policy: true,
135
135
  usage: Boolean(deps.costQuota),
136
- permissionModeWrite: false,
136
+ permissionModeWrite: facts.permissionModeWrite(deps).available,
137
137
  modelSelection: true,
138
138
  effortSelection: true,
139
139
  toolOutput: true,
@@ -143,7 +143,7 @@ export async function handleCapabilities(req, res, match, ctx) {
143
143
  subagentSteer: facts.subagentSteer(deps).available,
144
144
  subagentResume: facts.subagentSteer(deps).available,
145
145
  taskSettings: { permissions: true, permissionMode: true, model: true, outputStyle: true, env: DEPLOYMENT_SHAPE_PREDICATES.callerCwd.holds(deps.config), hooks: taskHooksHonored(deps.config), pluginHooks: taskHooksHonored(deps.config), managedHookGroups: taskHooksHonored(deps.config), tightenOnlySeats: true, approvalFrameFamilies: true },
146
- settings: { permissions: { allowGrant: true, allowLayer: true, callerTrust: callerTrust(req, deps.config).trust } },
146
+ settings: { permissions: { allowGrant: true, allowLayer: true, layers: true, callerTrust: callerTrust(req, deps.config).trust } },
147
147
  permissionModeAuto: {
148
148
  accepted: true,
149
149
  classifierSeat: deps.autoModeFace?.seatMounted === true,
@@ -181,6 +181,7 @@ export async function handleCapabilities(req, res, match, ctx) {
181
181
  mcp: true,
182
182
  mcpProbe: true,
183
183
  mcpAssertionHeaderSent: MCP_ASSERTION_HEADER_SENT,
184
+ mcpTransportKinds: [...MCP_REQUEST_TRANSPORT_KINDS],
184
185
  mcpElicitation: facts.elicitation(deps).available,
185
186
  askUserQuestion: facts.askUserQuestion(deps).available,
186
187
  toolApproval: facts.toolApproval(deps).available,
@@ -73,25 +73,6 @@ export interface StaticWiringFacts {
73
73
  /** store backend 的种类;`undefined` = env-only worker(无 backend)。 */
74
74
  backendKind: "mysql" | "pg" | "local" | undefined;
75
75
  }
76
- /**
77
- * 三项对表(设计稿件二)。判据全是**两个独立谓词对同一件事的答案**,矛盾即装配谎言 —— 装配谎言不是
78
- * 「配置不理想」,是「服务端对自己接了什么线的两套说法互斥」,继续启动只会把矛盾带进运行期的每一条腿。
79
- *
80
- * ① park 设施:core 从 `spec.checkpointStore ?? deps.checkpointStore` 判 `parkLane.capable`,我方从
81
- * `backend.checkpoint ∧ DURABLE_APPROVAL` 判 `parkFacility` 并据此决定流内审批协议上不上场。两者
82
- * 不等 ⇒ 协议按「窗到期能 park」上场而引擎侧根本不 park(结局是 core fail-closed deny),或反之
83
- * 白白关掉一个可用的协议。`capable` 真而 `effective` 不真同样致命:能力在、这条部署形上却不会真的
84
- * park,窗到期依旧无降级目的地。
85
- * ② 会话店持久性:manifest 声明 `declared_durable` 而后端是 local / 根本没有后端 ⇒ 「重启存活」的声明
86
- * 没有介质兑现。这条与 memory+durable 两条既有拒启同族(声明与介质必须对得上)。
87
- * ③ interaction posture 声明 `interactive` 却没有任何 question 投递面 ⇒ 只 **warn**:core 在 prepare 时
88
- * 会按腿拒,boot 先一步把话说成人话。不拒启,因为部署形本身可能只是暂时没接活体面,而 core 侧已有
89
- * 兜底门 —— 拒启会把一个可运行的部署挡在门外。
90
- * ④ park 车道的持久性读数不可信时 ⇒ **warn**(理由与这条判据为什么不是拒启,见其行内注)。
91
- *
92
- * 判决分两级是有判据的:**拒启**留给「两个谓词对同一件事互斥」(其中一个必错,继续跑就是带着谎言服务);
93
- * **警告**留给「读数不可信/声明不完整」(信号本身还不足以断定谁错,据此拒启会挡住正常部署)。
94
- */
95
76
  export declare function buildStaticWiringAudit(facts: StaticWiringFacts): StaticWiringAudit;
96
77
  /**
97
78
  * boot 消费口:`refusals` 非空即抛(拒启,与 memory+durable 两条既有拒启同族的 fail-loud 形),
@@ -43,6 +43,20 @@ export function buildServerWiringGates(input) {
43
43
  approvalGrant: [...input.approvalGrant],
44
44
  };
45
45
  }
46
+ function durableSessionMedium(kind) {
47
+ switch (kind) {
48
+ case "mysql":
49
+ case "pg":
50
+ case "local":
51
+ return true;
52
+ case undefined:
53
+ return false;
54
+ default: {
55
+ const unknownKind = kind;
56
+ throw new Error(`durableSessionMedium: no ruling for store backend kind ${JSON.stringify(unknownKind)}`);
57
+ }
58
+ }
59
+ }
46
60
  export function buildStaticWiringAudit(facts) {
47
61
  const refusals = [];
48
62
  const warnings = [];
@@ -56,9 +70,9 @@ export function buildStaticWiringAudit(facts) {
56
70
  refusals.push(`park facility contradiction: this server assembled its approval gates with parkFacility=true, but the engine's static wiring resolves parkLane.effective=${JSON.stringify(park.effective)} (reasons: ${park.reasons.join(", ") || "none"}). ` +
57
71
  `A window expiry would then have no degradation target and adjudicate as a fail-closed deny — refusing to start.`);
58
72
  }
59
- if (facts.manifest.session.store === "declared_durable" && facts.backendKind !== "mysql" && facts.backendKind !== "pg") {
73
+ if (facts.manifest.session.store === "declared_durable" && !durableSessionMedium(facts.backendKind)) {
60
74
  refusals.push(`session store durability contradiction: the engine's static wiring reports session.store="declared_durable" while the store backend is ${facts.backendKind === undefined ? "absent (env-only worker)" : `"${facts.backendKind}"`}. ` +
61
- `A durable declaration with no durable medium is a claim nothing can honor — refusing to start. Wire DB_BACKEND=mysql|pg, or fix the store's durability declaration.`);
75
+ `A durable declaration with no durable medium is a claim nothing can honor — refusing to start. Wire DB_BACKEND=mysql|pg|local, or fix the store's durability declaration.`);
62
76
  }
63
77
  if (facts.parkFacility && facts.manifest.parkLane.checkpointDurability !== "declared_durable") {
64
78
  warnings.push(`park facility is enabled but the checkpoint store does not declare durable storage ` +
@@ -20,12 +20,12 @@
20
20
  * 不该从「这个部署有没有记忆引擎」上读出部署形态。
21
21
  *
22
22
  * ── 能力面的诚实形(与 GET 面**方向相反**,这不是笔误)──────────────────────────────────────
23
- * `GET /v1/memory/export` 要的是 **DB 记忆平面**(pg|tidb),file 形态 501。本面要的是 core 的
23
+ * `GET /v1/memory/export` 要的是 **DB 记忆平面**(pg|mysql),file 形态 501。本面要的是 core 的
24
24
  * **bundle 复合面**(`exportSnapshotOf` / `importBundleCommit`),而它今天只在 core 自带的 **File**
25
25
  * 后端上实装:本仓的两只 SQL 记忆孪生(plugins/memory-engine-{pg,tidb}.ts)没有实现这两个可选面。
26
26
  * 因此**两个成因同落 501** `capability.memory_engine_required`(都是「换部署形态才行」,消费端分支相同):
27
27
  * · 记忆引擎整个没接线(`MEMORY_ENGINE=off` / 多租 file 底座等暗态);
28
- * · 引擎接了但后端没有 bundle 复合面(pg/tidb 孪生)—— 这一支在**挂载期**就判掉了
28
+ * · 引擎接了但后端没有 bundle 复合面(pg/mysql 孪生)—— 这一支在**挂载期**就判掉了
29
29
  * (`createMemoryBundleFaces` 返回 undefined ⇒ 两口整个不挂),能力位 `memoryBundle` 因此与「路由真能用」
30
30
  * 严格同真。🔴 首版把它当运行期事实(照常挂载、让 core 每次抛 409/422),被 codex 交叉复审驳倒并改此形:
31
31
  * 面在不在是一次**属性检查**、boot 期判得出、且是**永久**缺席 ⇒ 照常挂着就是一个恒假的 yes,
@@ -4,6 +4,7 @@ import { sentMemoryStoreRefusal } from "../memory-store-refusal-reply.js";
4
4
  import { buildOriginFencedBundle, readOriginAware } from "../../memory-origin-fence.js";
5
5
  import { gatedPrincipal, explicitOperatorOk, sendOperatorPrincipalsRequired, sendPrincipalRefusal } from "../principal-gate.js";
6
6
  import { assertNever } from "../route-ctx.js";
7
+ import { sentMemoryLayerRefusal } from "../memory-layer-reply.js";
7
8
  import * as facts from "../../capability-facts.js";
8
9
  export const MEMORY_BUNDLE_EXPORT_PATH = "/v1/memory/export";
9
10
  export const MEMORY_BUNDLE_IMPORT_PATH = "/v1/memory/import";
@@ -34,6 +35,8 @@ function codeOf(err) {
34
35
  return typeof code === "string" ? code : undefined;
35
36
  }
36
37
  function sentClassifiedFailure(res, ctx, face, err) {
38
+ if (sentMemoryLayerRefusal(res, err, { kind: "operator" }))
39
+ return true;
37
40
  const code = codeOf(err);
38
41
  if (code !== undefined && sentCoreCode(res, code, err instanceof Error ? err.message : String(err)))
39
42
  return true;
@@ -80,7 +83,7 @@ export async function handleMemoryBundle(req, res, match, ctx) {
80
83
  if (!fact.available) {
81
84
  switch (fact.why) {
82
85
  case "memory_bundle_faces_absent":
83
- sendError(res, 501, "capability.memory_engine_required", "memory governance bundles are not available on this deployment — they require a wired memory engine (MEMORY_ENGINE=on) whose backend implements the v2-c bundle composite (exportSnapshotOf / importBundleCommit); the file memory backend does, the pg/tidb memory backends do not");
86
+ sendError(res, 501, "capability.memory_engine_required", "memory governance bundles are not available on this deployment — they require a wired memory engine (MEMORY_ENGINE=on) whose backend implements the v2-c bundle composite (exportSnapshotOf / importBundleCommit); the file memory backend does, the pg/mysql memory backends do not");
84
87
  return;
85
88
  case "operator_principals_empty":
86
89
  sendOperatorPrincipalsRequired(res);
@@ -1,6 +1,7 @@
1
1
  import { z } from "zod";
2
2
  import { erasureInputSmugglesPrototypeKey } from "../../memory-operator-faces.js";
3
3
  import { sentMemoryComplianceFailure } from "../memory-compliance-failure-reply.js";
4
+ import { readLayerSeat, sentMemoryLayerRefusal } from "../memory-layer-reply.js";
4
5
  import { sendJson, sendError } from "../send.js";
5
6
  import { gatedPrincipal, explicitOperatorOk, sendOperatorPrincipalsRequired, sendPrincipalRefusal } from "../principal-gate.js";
6
7
  import { assertNever } from "../route-ctx.js";
@@ -12,6 +13,8 @@ const EraseRequestSchema = z.object({
12
13
  allowUnevidenced: z.boolean().optional(),
13
14
  });
14
15
  function sentClassifiedFailure(res, ctx, face, err) {
16
+ if (sentMemoryLayerRefusal(res, err, { kind: "operator" }))
17
+ return true;
15
18
  if (sentMemoryComplianceFailure(res, err, { kind: "operator" }, ctx.deps.logger))
16
19
  return true;
17
20
  ctx.deps.logger?.warn?.(`memory_compliance_${face}_failed`, { err: String(err) });
@@ -36,7 +39,7 @@ export async function handleMemoryCompliance(req, res, match, ctx) {
36
39
  if (!fact.available) {
37
40
  switch (fact.why) {
38
41
  case "memory_compliance_faces_absent":
39
- sendError(res, 501, "capability.memory_engine_required", "memory provenance and erasure are not available on this deployment — they require a wired memory engine (MEMORY_ENGINE=on) whose backend owns the engine control plane (controlPlaneRoot); the file memory backend does, the pg/tidb memory backends do not (their control plane would land on a replica's local disk)");
42
+ sendError(res, 501, "capability.memory_engine_required", "memory provenance and erasure are not available on this deployment — they require a wired memory engine (MEMORY_ENGINE=on) whose backend owns the engine control plane (controlPlaneRoot); the file memory backend does, the pg/mysql memory backends do not (their control plane would land on a replica's local disk)");
40
43
  return;
41
44
  case "operator_principals_empty":
42
45
  sendOperatorPrincipalsRequired(res);
@@ -53,8 +56,12 @@ export async function handleMemoryCompliance(req, res, match, ctx) {
53
56
  sendError(res, 400, "request.id_invalid", "invalid memory entry id");
54
57
  return;
55
58
  }
59
+ const query = new URLSearchParams(match.search);
60
+ const at = readLayerSeat(res, query.has("scope"), query.get("scope"));
61
+ if (at === null)
62
+ return;
56
63
  try {
57
- sendJson(res, 200, await faces.provenanceOf(entryId));
64
+ sendJson(res, 200, await (at !== undefined ? faces.provenanceOf(entryId, at) : faces.provenanceOf(entryId)));
58
65
  }
59
66
  catch (err) {
60
67
  if (!sentClassifiedFailure(res, ctx, "provenance", err))
@@ -1,6 +1,7 @@
1
1
  import { z } from "zod";
2
2
  import { ControlPlaneCorruptError } from "@sema-agent/core";
3
3
  import { sendJson, sendError } from "../send.js";
4
+ import { sentMemoryLayerRefusal } from "../memory-layer-reply.js";
4
5
  import { gatedPrincipal, explicitOperatorOk, sendPrincipalRefusal, sendOperatorPrincipalsRequired } from "../principal-gate.js";
5
6
  import { assertNever } from "../route-ctx.js";
6
7
  import * as facts from "../../capability-facts.js";
@@ -101,7 +102,15 @@ export async function handleMemoryConsolidation(req, res, match, ctx) {
101
102
  const q = new URLSearchParams(match.search).get("scope") ?? undefined;
102
103
  const decided = decideScope(q, faces.scopes);
103
104
  const scope = "scope" in decided ? decided.scope : undefined;
104
- const row = scope !== undefined ? faces.lastRun(scope) : undefined;
105
+ let row;
106
+ try {
107
+ row = scope !== undefined ? faces.lastRun(scope) : undefined;
108
+ }
109
+ catch (err) {
110
+ if (sentMemoryLayerRefusal(res, err, { kind: "operator" }))
111
+ return;
112
+ throw err;
113
+ }
105
114
  sendJson(res, 200, {
106
115
  enabled: true,
107
116
  seat: faces.seat,
@@ -144,6 +153,8 @@ export async function handleMemoryConsolidation(req, res, match, ctx) {
144
153
  sendJson(res, 200, buildRunSummary(r));
145
154
  }
146
155
  catch (err) {
156
+ if (sentMemoryLayerRefusal(res, err, { kind: "operator" }))
157
+ return;
147
158
  const coreCode = codeOf(err);
148
159
  if (coreCode !== undefined) {
149
160
  sendError(res, 409, "memory.consolidation_refused", `memory consolidation refused (${coreCode}): ${err instanceof Error ? err.message : String(err)}`);
@@ -3,6 +3,7 @@ import { ControlPlaneCorruptError } from "@sema-agent/core";
3
3
  import { sendJson, sendError } from "../send.js";
4
4
  import { sentMemoryStoreRefusal } from "../memory-store-refusal-reply.js";
5
5
  import { buildOriginFence, readOriginAware } from "../../memory-origin-fence.js";
6
+ import { readLayerSeat, sentMemoryLayerRefusal } from "../memory-layer-reply.js";
6
7
  import { gatedPrincipal, explicitOperatorOk, sendOperatorPrincipalsRequired, sendPrincipalRefusal } from "../principal-gate.js";
7
8
  import { assertNever } from "../route-ctx.js";
8
9
  import * as facts from "../../capability-facts.js";
@@ -49,6 +50,8 @@ function codeOf(err) {
49
50
  return typeof code === "string" ? code : undefined;
50
51
  }
51
52
  function sentClassifiedFailure(res, ctx, face, err) {
53
+ if (sentMemoryLayerRefusal(res, err, { kind: "operator" }))
54
+ return true;
52
55
  if (face === "clear") {
53
56
  const coreCode = codeOf(err);
54
57
  if (coreCode !== undefined && sentClearCode(res, coreCode, err instanceof Error ? err.message : String(err)))
@@ -157,8 +160,12 @@ export async function handleMemoryOrigin(req, res, match, ctx) {
157
160
  return;
158
161
  }
159
162
  case "memory-origin-clearances": {
163
+ const query = new URLSearchParams(match.search);
164
+ const at = readLayerSeat(res, query.has("scope"), query.get("scope"));
165
+ if (at === null)
166
+ return;
160
167
  try {
161
- sendJson(res, 200, { clearances: faces.listClearances().map(buildClearanceRowWire) });
168
+ sendJson(res, 200, { clearances: (at !== undefined ? faces.listClearances(at) : faces.listClearances()).map(buildClearanceRowWire) });
162
169
  }
163
170
  catch (err) {
164
171
  if (!sentClassifiedFailure(res, ctx, "clearances", err))
@@ -182,8 +189,13 @@ export async function handleMemoryOrigin(req, res, match, ctx) {
182
189
  sendError(res, 400, "request.body_shape", "invalid memory origin clearance request — expected an object with a non-empty `requestId` and a `reason` string (whether an EMPTY reason is acceptable is the engine's judgment, not this layer's)");
183
190
  return;
184
191
  }
192
+ const body = raw;
193
+ const at = readLayerSeat(res, Object.prototype.hasOwnProperty.call(body, "scope"), body.scope);
194
+ if (at === null)
195
+ return;
185
196
  try {
186
- const receipt = await faces.clear(entryId, { requestId: parsed.data.requestId, reason: parsed.data.reason });
197
+ const input = { requestId: parsed.data.requestId, reason: parsed.data.reason };
198
+ const receipt = await (at !== undefined ? faces.clear(entryId, input, at) : faces.clear(entryId, input));
187
199
  ctx.deps.logger?.info?.("memory_origin_cleared", {
188
200
  principal: principal ?? null,
189
201
  entryId,
@@ -5,6 +5,7 @@ import { buildOriginFence, readOriginAware } from "../../memory-origin-fence.js"
5
5
  import { parseProjectLayerKey } from "../../project-layer-key.js";
6
6
  import { gatedPrincipal, explicitOperatorOk, sendPrincipalRefusal, sendUnauthorized } from "../principal-gate.js";
7
7
  import { assertNever } from "../route-ctx.js";
8
+ import { sentMemoryLayerRefusal } from "../memory-layer-reply.js";
8
9
  const ORG_PREFIX = "org:";
9
10
  export const MEMORY_EXPORT_MAX_LIMIT = 500;
10
11
  function encodeExportCursor(c) {
@@ -73,7 +74,7 @@ export async function handleMemoryPolicy(req, res, match, ctx) {
73
74
  return;
74
75
  }
75
76
  if (deps.config.memoryEngineBackend === "file" || !deps.memoryExport) {
76
- sendError(res, 501, "capability.memory_store_required", "memory export requires a DB memory backend (MEMORY_ENGINE_BACKEND=pg|tidb)");
77
+ sendError(res, 501, "capability.memory_store_required", "memory export requires a DB memory backend (MEMORY_ENGINE_BACKEND=pg|mysql)");
77
78
  return;
78
79
  }
79
80
  const q = new URLSearchParams(match.search);
@@ -121,6 +122,8 @@ export async function handleMemoryPolicy(req, res, match, ctx) {
121
122
  });
122
123
  }
123
124
  catch (err) {
125
+ if (sentMemoryLayerRefusal(res, err, { kind: "operator" }))
126
+ return;
124
127
  deps.logger?.warn?.("memory_export_failed", { scope, err: String(err) });
125
128
  sendError(res, 500, "internal.error", "memory export failed");
126
129
  }
@@ -133,7 +136,7 @@ export async function handleMemoryPolicy(req, res, match, ctx) {
133
136
  return;
134
137
  }
135
138
  if (deps.config.memoryEngineBackend === "file" || !deps.memorySync) {
136
- sendError(res, 501, "capability.memory_store_required", "memory sync requires a DB memory backend (MEMORY_ENGINE_BACKEND=pg|tidb)");
139
+ sendError(res, 501, "capability.memory_store_required", "memory sync requires a DB memory backend (MEMORY_ENGINE_BACKEND=pg|mysql)");
137
140
  return;
138
141
  }
139
142
  const scope = safeDecode(match.params.scope);
@@ -158,6 +161,8 @@ export async function handleMemoryPolicy(req, res, match, ctx) {
158
161
  sendJson(res, 200, out);
159
162
  }
160
163
  catch (err) {
164
+ if (sentMemoryLayerRefusal(res, err, { kind: "operator" }))
165
+ return;
161
166
  deps.logger?.warn?.("memory_sync_failed", { scope, peer: parsed.value.peer, err: String(err) });
162
167
  sendError(res, 500, "internal.error", "memory sync failed");
163
168
  }