@sema-agent/server 7.141.0 → 7.143.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 (341) hide show
  1. package/MIGRATION.md +657 -0
  2. package/USAGE.md +102 -30
  3. package/dist/adoption/plan.js +22 -0
  4. package/dist/approval-ask-audit-store.d.ts +61 -43
  5. package/dist/approval-ask-audit-store.js +69 -44
  6. package/dist/approval-ask-machine.d.ts +15 -7
  7. package/dist/approval-ask-machine.js +10 -4
  8. package/dist/approval-card.d.ts +126 -27
  9. package/dist/approval-card.js +103 -23
  10. package/dist/approval-crash-convergence.d.ts +17 -7
  11. package/dist/approval-crash-convergence.js +94 -22
  12. package/dist/approval-deny-reasons.d.ts +34 -30
  13. package/dist/approval-deny-reasons.js +21 -6
  14. package/dist/approval-policy-settlement.d.ts +1 -1
  15. package/dist/approval-queue-kind.d.ts +27 -0
  16. package/dist/approval-queue-kind.js +6 -0
  17. package/dist/approval-reconciler.d.ts +41 -9
  18. package/dist/approval-reconciler.js +45 -42
  19. package/dist/audit.js +4 -2
  20. package/dist/auth-bridge.d.ts +9 -6
  21. package/dist/auth-bridge.js +9 -3
  22. package/dist/boot/adoption.js +2 -1
  23. package/dist/boot/budget-tracing.d.ts +17 -1
  24. package/dist/boot/budget-tracing.js +10 -6
  25. package/dist/boot/device-lane.d.ts +1 -1
  26. package/dist/boot/execution-env.d.ts +24 -4
  27. package/dist/boot/execution-env.js +26 -23
  28. package/dist/boot/execution-lane.js +2 -1
  29. package/dist/boot/exit-boundary.js +5 -4
  30. package/dist/boot/governance-seams.d.ts +26 -41
  31. package/dist/boot/governance-seams.js +61 -28
  32. package/dist/boot/late-binds.d.ts +7 -4
  33. package/dist/boot/late-binds.js +3 -1
  34. package/dist/boot/leader.js +2 -4
  35. package/dist/boot/memory-consolidation.d.ts +0 -8
  36. package/dist/boot/memory-consolidation.js +5 -4
  37. package/dist/boot/parked-revive-gate.js +2 -1
  38. package/dist/boot/permission-rules-audit.d.ts +0 -28
  39. package/dist/boot/permission-rules-audit.js +2 -1
  40. package/dist/boot/read-deny-anchor-audit.js +2 -1
  41. package/dist/boot/reapers.js +9 -7
  42. package/dist/boot/resolve-spec.d.ts +1 -1
  43. package/dist/boot/resolve-spec.js +19 -10
  44. package/dist/boot/retention-lane.js +5 -3
  45. package/dist/boot/runner-deps.d.ts +10 -7
  46. package/dist/boot/runner-deps.js +20 -29
  47. package/dist/boot/runtime-caps.js +3 -2
  48. package/dist/boot/session-faces.js +4 -3
  49. package/dist/boot/shutdown.d.ts +9 -0
  50. package/dist/boot/shutdown.js +19 -4
  51. package/dist/boot/stage-02-web-admin-pull.js +3 -0
  52. package/dist/boot/stage-03-store-backend.d.ts +4 -1
  53. package/dist/boot/stage-03-store-backend.js +1 -2
  54. package/dist/boot/stage-04-stores.d.ts +5 -2
  55. package/dist/boot/stage-04-stores.js +6 -7
  56. package/dist/boot/stage-05-execution-env.d.ts +6 -3
  57. package/dist/boot/stage-05-execution-env.js +8 -6
  58. package/dist/boot/stage-06-runners.d.ts +6 -3
  59. package/dist/boot/stage-06-runners.js +3 -4
  60. package/dist/boot/stage-07-capability-layer.d.ts +6 -3
  61. package/dist/boot/stage-07-capability-layer.js +7 -2
  62. package/dist/boot/stage-08-reapers.d.ts +6 -3
  63. package/dist/boot/stage-08-reapers.js +3 -2
  64. package/dist/boot/stage-09-leader.d.ts +6 -3
  65. package/dist/boot/stage-10-http-server.d.ts +6 -3
  66. package/dist/boot/stage-10-http-server.js +14 -5
  67. package/dist/boot/stores.d.ts +5 -2
  68. package/dist/boot/stores.js +10 -9
  69. package/dist/boot/web-admin.d.ts +5 -1
  70. package/dist/boot/web-admin.js +48 -36
  71. package/dist/boot/webfetch-summarize-lane.js +2 -1
  72. package/dist/boot/workflow-orchestration.js +3 -2
  73. package/dist/capabilities/builtin-tools.d.ts +2 -1
  74. package/dist/capabilities/builtin-tools.js +2 -4
  75. package/dist/capabilities/composite-members.d.ts +2 -1
  76. package/dist/capabilities/composite-members.js +2 -1
  77. package/dist/capabilities/hands-lane.d.ts +9 -39
  78. package/dist/capabilities/hands-lane.js +8 -13
  79. package/dist/capabilities/mcp-probe.d.ts +3 -2
  80. package/dist/capabilities/scenarios.d.ts +11 -1
  81. package/dist/capabilities/scenarios.js +1 -0
  82. package/dist/capabilities/skills.d.ts +1 -17
  83. package/dist/capabilities/skills.js +0 -8
  84. package/dist/capability-facts.d.ts +31 -7
  85. package/dist/capability-facts.js +27 -4
  86. package/dist/card-void.d.ts +6 -9
  87. package/dist/config-catalog.js +2 -1
  88. package/dist/config-dir-trust.js +58 -29
  89. package/dist/config-invariants.d.ts +7 -1
  90. package/dist/config-invariants.js +7 -0
  91. package/dist/config-provider.d.ts +10 -0
  92. package/dist/config-provider.js +15 -4
  93. package/dist/config-root-migration.d.ts +13 -0
  94. package/dist/config-root-migration.js +99 -0
  95. package/dist/config-types.d.ts +19 -8
  96. package/dist/config.d.ts +10 -3
  97. package/dist/config.js +18 -4
  98. package/dist/delegated-session-owner.d.ts +5 -3
  99. package/dist/delegated-session-owner.js +1 -1
  100. package/dist/device-ws-protocol.d.ts +1 -0
  101. package/dist/device-ws-protocol.js +2 -1
  102. package/dist/env-model-table-gate.d.ts +53 -0
  103. package/dist/env-model-table-gate.js +53 -0
  104. package/dist/execution-lane-caps.d.ts +2 -1
  105. package/dist/fleet/fleet-bus.d.ts +34 -55
  106. package/dist/fleet/fleet-bus.js +35 -100
  107. package/dist/fleet/fleet-reconciler.d.ts +4 -4
  108. package/dist/fleet/fleet-reconciler.js +1 -1
  109. package/dist/fleet/subagent-tail-bus.d.ts +14 -11
  110. package/dist/fleet/subagent-tail-bus.js +15 -28
  111. package/dist/hooks/hook-runner.d.ts +6 -0
  112. package/dist/hooks/hook-runner.js +58 -8
  113. package/dist/host-decision.d.ts +54 -20
  114. package/dist/host-decision.js +42 -14
  115. package/dist/http/admission.d.ts +1 -1
  116. package/dist/http/admission.js +7 -3
  117. package/dist/http/approval-sweeps.js +11 -8
  118. package/dist/http/caller-trust.d.ts +1 -1
  119. package/dist/http/dispatch.js +4 -2
  120. package/dist/http/durable-run-leg.js +2 -2
  121. package/dist/http/engine-refusal.d.ts +16 -0
  122. package/dist/http/engine-refusal.js +17 -0
  123. package/dist/http/execution-context.d.ts +2 -2
  124. package/dist/http/idempotency.d.ts +1 -1
  125. package/dist/http/memory-compliance-failure-reply.d.ts +1 -3
  126. package/dist/http/memory-compliance-failure-reply.js +4 -6
  127. package/dist/http/owner-access.d.ts +11 -0
  128. package/dist/http/owner-access.js +13 -0
  129. package/dist/http/principal-gate.d.ts +3 -1
  130. package/dist/http/principal-gate.js +17 -8
  131. package/dist/http/resume-legs.d.ts +21 -7
  132. package/dist/http/resume-legs.js +76 -58
  133. package/dist/http/resume-restatement.d.ts +39 -0
  134. package/dist/http/resume-restatement.js +25 -0
  135. package/dist/http/route-ctx.d.ts +35 -10
  136. package/dist/http/route-ctx.js +1 -1
  137. package/dist/http/route-table.js +2 -0
  138. package/dist/http/routes/approvals-assistant.d.ts +9 -1
  139. package/dist/http/routes/approvals-assistant.js +142 -31
  140. package/dist/http/routes/attachments.js +18 -0
  141. package/dist/http/routes/capabilities.js +16 -4
  142. package/dist/http/routes/memory-policy.d.ts +2 -2
  143. package/dist/http/routes/memory-policy.js +27 -7
  144. package/dist/http/routes/notify-wake.js +23 -25
  145. package/dist/http/routes/rules.js +48 -13
  146. package/dist/http/routes/runs.js +12 -11
  147. package/dist/http/routes/session-memory-sync.d.ts +91 -0
  148. package/dist/http/routes/session-memory-sync.js +174 -0
  149. package/dist/http/routes/session-sync.js +13 -20
  150. package/dist/http/routes/sessions-list.d.ts +2 -1
  151. package/dist/http/routes/sessions.d.ts +2 -2
  152. package/dist/http/routes/sessions.js +22 -23
  153. package/dist/http/routes/tasks.js +34 -54
  154. package/dist/http/run-read-face.d.ts +7 -0
  155. package/dist/http/run-read-face.js +9 -3
  156. package/dist/http/send.d.ts +5 -0
  157. package/dist/http/send.js +9 -2
  158. package/dist/http/server.d.ts +27 -15
  159. package/dist/http/server.js +4 -6
  160. package/dist/http/stored-body-replay.js +15 -4
  161. package/dist/http/submit-replay.d.ts +4 -3
  162. package/dist/http/submit-replay.js +2 -2
  163. package/dist/http/sync-submit-body.d.ts +21 -4
  164. package/dist/http/sync-submit-body.js +13 -0
  165. package/dist/http/wire-types.d.ts +17 -7
  166. package/dist/identity-source.d.ts +21 -2
  167. package/dist/identity-source.js +6 -0
  168. package/dist/leader/leader.js +5 -2
  169. package/dist/leader/wire.d.ts +7 -1
  170. package/dist/leader/wire.js +6 -5
  171. package/dist/leg-facts.d.ts +37 -0
  172. package/dist/leg-facts.js +15 -0
  173. package/dist/memory-bundle-engine.d.ts +1 -4
  174. package/dist/memory-bundle-engine.js +2 -2
  175. package/dist/memory-incident-sink.d.ts +19 -6
  176. package/dist/memory-incident-sink.js +8 -4
  177. package/dist/memory-operator-faces.d.ts +30 -66
  178. package/dist/memory-operator-faces.js +17 -88
  179. package/dist/memory-scope-stores.d.ts +38 -40
  180. package/dist/memory-scope-stores.js +51 -36
  181. package/dist/memory-scope.d.ts +0 -9
  182. package/dist/memory-scope.js +0 -9
  183. package/dist/memory-sync-client.d.ts +21 -21
  184. package/dist/memory-sync-client.js +62 -43
  185. package/dist/memory-sync-identity.d.ts +24 -0
  186. package/dist/memory-sync-identity.js +57 -0
  187. package/dist/memory-sync.d.ts +27 -5
  188. package/dist/memory-sync.js +29 -7
  189. package/dist/model-plane-face.d.ts +13 -7
  190. package/dist/model-plane-face.js +2 -1
  191. package/dist/observability/fail-open.d.ts +47 -14
  192. package/dist/observability/fail-open.js +37 -11
  193. package/dist/observability/run-terminal.d.ts +92 -34
  194. package/dist/observability/run-terminal.js +171 -162
  195. package/dist/orchestration/workflow-completion-inbox.d.ts +5 -19
  196. package/dist/orchestration/workflow-completion-inbox.js +0 -12
  197. package/dist/orchestration/workflow-notify-journal.d.ts +3 -2
  198. package/dist/orchestration/workflow-park-decision.d.ts +8 -3
  199. package/dist/orchestration/workflow-park-decision.js +5 -3
  200. package/dist/org-delivery-gate.d.ts +11 -0
  201. package/dist/org-delivery-gate.js +19 -1
  202. package/dist/parked-decide.d.ts +13 -9
  203. package/dist/parked-decide.js +7 -7
  204. package/dist/parked-revive-surface.js +1 -1
  205. package/dist/peer-inbound-face.d.ts +127 -0
  206. package/dist/peer-inbound-face.js +158 -0
  207. package/dist/permission-rule-list.d.ts +13 -9
  208. package/dist/permission-rule-list.js +7 -3
  209. package/dist/plugins/approval-ask-store-file.d.ts +14 -4
  210. package/dist/plugins/approval-ask-store-file.js +64 -11
  211. package/dist/plugins/approval-ask-store-memory.d.ts +2 -1
  212. package/dist/plugins/approval-ask-store-memory.js +17 -14
  213. package/dist/plugins/approval-ask-store-sql.d.ts +70 -23
  214. package/dist/plugins/approval-ask-store-sql.js +79 -30
  215. package/dist/plugins/checkpoint-store-sql.d.ts +4 -4
  216. package/dist/plugins/checkpoint-store-sql.js +9 -7
  217. package/dist/plugins/file-history-store-sql.d.ts +24 -18
  218. package/dist/plugins/file-history-store-sql.js +24 -19
  219. package/dist/plugins/file-run-store.d.ts +35 -1
  220. package/dist/plugins/file-run-store.js +108 -9
  221. package/dist/plugins/imported-layer-root-retirement.d.ts +82 -0
  222. package/dist/plugins/imported-layer-root-retirement.js +96 -0
  223. package/dist/plugins/local-checkpoint-store.d.ts +1 -1
  224. package/dist/plugins/local-checkpoint-store.js +2 -2
  225. package/dist/plugins/local-session-store.d.ts +42 -9
  226. package/dist/plugins/local-session-store.js +83 -33
  227. package/dist/plugins/local-task-attachment-store.d.ts +12 -2
  228. package/dist/plugins/local-task-attachment-store.js +67 -43
  229. package/dist/plugins/mailbox-recipient-lifecycle.d.ts +9 -31
  230. package/dist/plugins/mailbox-recipient-lifecycle.js +4 -0
  231. package/dist/plugins/mailbox-store-sql.d.ts +12 -8
  232. package/dist/plugins/mailbox-store-sql.js +76 -7
  233. package/dist/plugins/memory-key-guards.d.ts +3 -3
  234. package/dist/plugins/memory-run-store.d.ts +6 -1
  235. package/dist/plugins/memory-run-store.js +11 -1
  236. package/dist/plugins/memory-sync-store-pg.d.ts +15 -0
  237. package/dist/plugins/memory-sync-store-pg.js +21 -0
  238. package/dist/plugins/memory-sync-store-tidb.d.ts +2 -0
  239. package/dist/plugins/memory-sync-store-tidb.js +13 -1
  240. package/dist/plugins/one-time-migrations.d.ts +58 -2
  241. package/dist/plugins/one-time-migrations.js +161 -4
  242. package/dist/plugins/org-delivery-quota-store.d.ts +1 -1
  243. package/dist/plugins/org-delivery-quota-store.js +2 -12
  244. package/dist/plugins/park-commit-watch.d.ts +1 -1
  245. package/dist/plugins/permission-rule-store-file.d.ts +10 -1
  246. package/dist/plugins/permission-rule-store-file.js +15 -2
  247. package/dist/plugins/permission-rule-store-sql.d.ts +31 -1
  248. package/dist/plugins/permission-rule-store-sql.js +35 -2
  249. package/dist/plugins/remote-env-device.d.ts +8 -11
  250. package/dist/plugins/remote-env-device.js +6 -3
  251. package/dist/plugins/remote-env-e2b.d.ts +23 -4
  252. package/dist/plugins/remote-env-e2b.js +111 -28
  253. package/dist/plugins/remote-env-k8s.d.ts +61 -22
  254. package/dist/plugins/remote-env-k8s.js +133 -33
  255. package/dist/plugins/remote-env-local-docker.d.ts +15 -3
  256. package/dist/plugins/remote-env-local-docker.js +40 -12
  257. package/dist/plugins/retention-store-sql.d.ts +2 -2
  258. package/dist/plugins/run-store-sql.d.ts +9 -1
  259. package/dist/plugins/run-store-sql.js +9 -1
  260. package/dist/plugins/sandbox-read-floor.d.ts +5 -7
  261. package/dist/plugins/sandbox-read-floor.js +2 -7
  262. package/dist/plugins/sql-errors.d.ts +10 -1
  263. package/dist/plugins/sql-errors.js +13 -0
  264. package/dist/plugins/store-backend.d.ts +33 -35
  265. package/dist/plugins/store-backend.js +10 -1
  266. package/dist/plugins/store-contracts.d.ts +50 -1
  267. package/dist/plugins/store-contracts.js +6 -0
  268. package/dist/plugins/task-attachment-store.d.ts +112 -14
  269. package/dist/plugins/task-attachment-store.js +207 -29
  270. package/dist/plugins/tool-result-store-sql.d.ts +9 -8
  271. package/dist/plugins/tool-result-store-sql.js +23 -2
  272. package/dist/plugins/wiring-section-codec.d.ts +32 -0
  273. package/dist/plugins/wiring-section-codec.js +55 -0
  274. package/dist/plugins/workspace-fill.d.ts +60 -0
  275. package/dist/plugins/workspace-fill.js +106 -0
  276. package/dist/project-bundle.d.ts +38 -0
  277. package/dist/project-bundle.js +609 -0
  278. package/dist/rule-entry-list.d.ts +3 -2
  279. package/dist/rule-entry-list.js +5 -1
  280. package/dist/rules-consent.d.ts +28 -5
  281. package/dist/rules-consent.js +40 -28
  282. package/dist/run-local.js +11 -13
  283. package/dist/runs.d.ts +12 -8
  284. package/dist/runs.js +6 -8
  285. package/dist/runtime-governance.d.ts +1 -1
  286. package/dist/sandbox-egress-policy.d.ts +4 -1
  287. package/dist/sandbox-egress-policy.js +3 -1
  288. package/dist/sandbox-git-plane.d.ts +31 -12
  289. package/dist/sandbox-git-plane.js +24 -4
  290. package/dist/security.d.ts +9 -0
  291. package/dist/security.js +8 -0
  292. package/dist/server-secret-env.d.ts +4 -0
  293. package/dist/session-error-wire.d.ts +36 -0
  294. package/dist/session-error-wire.js +13 -0
  295. package/dist/session-incarnation.d.ts +1 -1
  296. package/dist/session-notify-door.d.ts +106 -0
  297. package/dist/session-notify-door.js +93 -0
  298. package/dist/session-sync.d.ts +9 -14
  299. package/dist/session-sync.js +5 -5
  300. package/dist/session-workspace.d.ts +3 -13
  301. package/dist/session-workspace.js +0 -9
  302. package/dist/standing-answer-grant.d.ts +5 -0
  303. package/dist/standing-answer-grant.js +10 -0
  304. package/dist/stores-sql/session-policy-store-sql.d.ts +4 -2
  305. package/dist/stores-sql/session-policy-store-sql.js +3 -13
  306. package/dist/task-mcp.d.ts +1 -1
  307. package/dist/task-settings.d.ts +21 -10
  308. package/dist/task-settings.js +46 -13
  309. package/dist/terminal.d.ts +39 -19
  310. package/dist/terminal.js +65 -22
  311. package/dist/tool-approval.d.ts +56 -37
  312. package/dist/tool-approval.js +78 -71
  313. package/dist/trace/core-keyset-guard.d.ts +134 -14
  314. package/dist/trace/engine-notice-wire.d.ts +9 -3
  315. package/dist/trace/engine-notice-wire.js +7 -3
  316. package/dist/trace/exit-seat.d.ts +9 -2
  317. package/dist/trace/exit-seat.js +1 -0
  318. package/dist/trace/ledger-sink.d.ts +10 -6
  319. package/dist/trace/ledger-sink.js +2 -2
  320. package/dist/trace/model-segment.d.ts +55 -25
  321. package/dist/trace/model-segment.js +101 -33
  322. package/dist/trace/project.d.ts +25 -5
  323. package/dist/trace/project.js +22 -0
  324. package/dist/trace/redact.d.ts +61 -9
  325. package/dist/trace/redact.js +1490 -468
  326. package/dist/trace/self-minted-wire.d.ts +745 -24
  327. package/dist/trace/self-minted-wire.js +239 -9
  328. package/dist/trace/wire-projection-faces.d.ts +2 -2
  329. package/dist/trace/wire-projection-faces.js +2 -2
  330. package/dist/verifier-pause-card.d.ts +33 -5
  331. package/dist/verifier-pause-card.js +15 -10
  332. package/dist/web-admin-client/apply-effective.d.ts +12 -16
  333. package/dist/web-admin-client/apply-effective.js +109 -9
  334. package/dist/web-admin-client/effective-keys.js +2 -0
  335. package/dist/web-admin-client/types.d.ts +4 -0
  336. package/dist/workspace-space.d.ts +19 -3
  337. package/dist/workspace-space.js +8 -4
  338. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +3 -1
  339. package/package.json +3 -2
  340. package/wire-changes/server@7.142.0.json +639 -0
  341. package/wire-changes/server@7.143.0.json +1167 -0
@@ -1,13 +1,19 @@
1
1
  import { persistedPlaneOf } from "../terminal.js";
2
- import { memoRedactedRead, memoRedactTerminalResult, redactErrorMessage, sealRunRowResult } from "../observability/run-terminal.js";
2
+ import { memoRedactedRead, memoRedactTerminalResult, redactErrorMessage, sealStoredRunRowResult } from "../observability/run-terminal.js";
3
3
  import { RUN_HOLDER_DEATH_CODES, isTerminalRunStatus } from "../plugins/store-contracts.js";
4
4
  import { composeSupervisorCost, infraCost, infraUsageFromEvents, hasInfraPricing } from "../observability/cost-taxonomy.js";
5
5
  import { recordFailOpen } from "../observability/fail-open.js";
6
6
  import { readTurnActivityMs } from "../turn-activity.js";
7
7
  import { buildCrossSliceUsage, readResourceWindow } from "../resource-window.js";
8
+ export function runRowStale(deps, run) {
9
+ return run.status === "running" && Date.now() - new Date(run.updatedAt).getTime() > deps.config.runStaleSec * 1000;
10
+ }
11
+ export function runRowExitResult(run) {
12
+ return isTerminalRunStatus(run.status) ? memoRedactTerminalResult("run.result", run.result ?? undefined) : (sealStoredRunRowResult(run.result ?? null, "run.result") ?? undefined);
13
+ }
8
14
  export async function readRunFace(deps, runStore, run) {
9
15
  const taskId = run.taskId;
10
- const stale = run.status === "running" && Date.now() - new Date(run.updatedAt).getTime() > deps.config.runStaleSec * 1000;
16
+ const stale = runRowStale(deps, run);
11
17
  const infraRates = deps.config.infraCostRates;
12
18
  const needCost = Boolean(run.result?.stats && !stale && infraRates && hasInfraPricing(infraRates));
13
19
  const needSuggestions = !stale && run.status === "completed";
@@ -53,7 +59,7 @@ export async function readRunFace(deps, runStore, run) {
53
59
  status: stale ? "failed" : run.status,
54
60
  ...(lastActivityAt !== undefined ? { msSinceLastActivity: Math.max(0, Date.now() - lastActivityAt) } : {}),
55
61
  ...(crossSliceUsage !== undefined ? { crossSliceUsage } : {}),
56
- result: isTerminalRunStatus(run.status) ? memoRedactTerminalResult("run.result", run.result ?? undefined) : (sealRunRowResult(run.result ?? null, "run.result") ?? undefined),
62
+ result: runRowExitResult(run),
57
63
  supervisorCost,
58
64
  suggestions,
59
65
  errorCode: stale ? RUN_HOLDER_DEATH_CODES.stalled : (persistedPlaneOf(run.result).errorCode ?? run.errorCode ?? undefined),
@@ -123,6 +123,11 @@ export declare function sendSessionPolicyError(res: ServerResponse, e: unknown,
123
123
  * (路径只进运维面:`server.session-repo.corrupt-record-skipped` 的探针行,[ref];SQL 两店走各自的拒绝句)。
124
124
  */
125
125
  export declare function sendSessionError(res: ServerResponse, e: unknown, face: SessionErrorFace): boolean;
126
+ /**
127
+ * 全局兜底的 open 面一臂(`http/server.ts`:路由里逃出来的、不是 `HttpError` 的故障)—— 码经 {@link openFaceFaultWire}(会话列表行的 `unreadable` 同读这一只:
128
+ * 列表说的码就是读口答的码,`session-error-wire.ts` 头注「一张表、两个读者」)。有臂的 `SessionError` 同 {@link sendSessionError};其余落通用 500,固定句。
129
+ */
130
+ export declare function sendOpenFaceFault(res: ServerResponse, e: unknown): void;
126
131
  export declare function msg(e: unknown): string;
127
132
  /**
128
133
  * 路由抛出的未归类错误的运维行 `request_error` —— **唯一写者**。外层兜底(`server.ts`)与「就地经映射下发」的站点(会话同步的暂存提交 catch)同调它:
package/dist/http/send.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { SessionError, SessionPolicyError } from "@sema-agent/core";
2
2
  import { sessionPolicyErrorFacts, sessionPolicyErrorHttp, sessionPolicyErrorSentence } from "../session-policy-wire.js";
3
- import { sessionErrorWireOf } from "../session-error-wire.js";
3
+ import { openFaceFaultWire, sessionErrorWireOf } from "../session-error-wire.js";
4
4
  import { redactErrorMessage, redactHead } from "../observability/run-terminal.js";
5
5
  import { createCodedHttpError } from "../security.js";
6
6
  import { refusalBody } from "./refusal-body.js";
@@ -82,9 +82,16 @@ export function sendSessionError(res, e, face) {
82
82
  const wire = sessionErrorWireOf(e, face);
83
83
  if (wire === undefined)
84
84
  return false;
85
- sendError(res, wire.status, wire.errorCode, wire.sentence ?? redactErrorMessage(e.message) ?? "session store error", wire.detail === undefined ? undefined : { detail: wire.detail });
85
+ sendSessionWire(res, e, wire);
86
86
  return true;
87
87
  }
88
+ export function sendOpenFaceFault(res, e) {
89
+ sendSessionWire(res, e, openFaceFaultWire(e));
90
+ }
91
+ function sendSessionWire(res, e, wire) {
92
+ const sentence = wire.sentence ?? (e instanceof SessionError ? redactErrorMessage(e.message) : undefined) ?? "session store error";
93
+ sendError(res, wire.status, wire.errorCode, sentence, wire.detail === undefined ? undefined : { detail: wire.detail });
94
+ }
88
95
  export function msg(e) {
89
96
  return e instanceof Error ? e.message : String(e);
90
97
  }
@@ -12,7 +12,7 @@ import type { PeerDesk, PeerLease } from "../peer-seat.js";
12
12
  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
- import { type MemorySyncRequest, type MemorySyncResponse } from "../memory-sync.js";
15
+ import { type MemorySyncAnswer, type MemorySyncRequest } from "../memory-sync.js";
16
16
  import type { MemorySyncRunner } from "../memory-sync-client.js";
17
17
  import type { TaskAttachmentStore } from "../plugins/task-attachment-store.js";
18
18
  import type { LeaderEndpoint } from "../leader/endpoint.js";
@@ -38,6 +38,7 @@ import { cascadeConfig } from "./run-meta.js";
38
38
  export { cascadeConfig };
39
39
  import { coarseStatusForState, errorCodeForExit } from "./routes/images.js";
40
40
  export { coarseStatusForState, errorCodeForExit };
41
+ import type { SessionNotifyDoor } from "../session-notify-door.js";
41
42
  import { MAX_SKILL_CONTENT_CHARS, MAX_SYSTEM_PROMPT_CHARS, MAX_OUTPUT_SCHEMA_CHARS, validateUserSkills } from "./admission.js";
42
43
  import { routeLabel, isBillableSubmitPath, isCredentialGatedRewrite, isMethodDispatchedSubmitPath } from "./route-table.js";
43
44
  export { routeLabel, isBillableSubmitPath, isCredentialGatedRewrite, isMethodDispatchedSubmitPath, hasServiceAuth };
@@ -139,11 +140,11 @@ export interface ServiceCoreDeps {
139
140
  execution: ExecutionRoot;
140
141
  }) => ResolvedTaskSpec | Promise<ResolvedTaskSpec>;
141
142
  /**
142
- * [ref] 场景 hands lane 选路:按 `resolveSpec` 刚产出的 TaskSpec 取本任务的执行 Runner。
143
- * 装配点(`boot/stage-10-http-server.ts`)传的是 `createHandsRunnerSelector` —— 选路规则只有那一份实现,
144
- * 本层不解释场景,只取用。
143
+ * [ref] 场景 hands lane 选路:按 `resolveSpec` 刚产出的那一只对象取本任务的执行 Runner —— 两只漏斗(受理 / 续跑)在盖根复制
144
+ * (`stampSpecRoot`)之前以装配输出调它,不交复制品。装配点(`boot/stage-10-http-server.ts`)传的是 `createHandsRunnerSelector`
145
+ * (读这条腿的部署事实里的车道,`leg-facts.ts`)—— 选路规则只有那一份实现,本层不解释场景,只取用。
145
146
  * 🔴 **必填**([ref],7.105.0):修前这一席可选,缺席 ⇒ 静默落 {@link ServiceDeps.runner} —— 最宽的那只
146
- * (带全量手的主 Runner)。而同一轴上「车道**字段**缺席」早已是拒([ref],`handsLaneOf` 抛
147
+ * (带全量手的主 Runner)。而同一轴上「车道读不到」早已是拒(选路器抛
147
148
  * `HandsLaneUnstampedError`),席缺席回落最宽 = 同一件事两条律。现在缺席是**编译错**;绕过类型
148
149
  * (JS 嵌入方 / `as` 硬转)造的 deps 在 {@link createHttpServer} 入口**拒启**。单 Runner 的嵌入方显式传
149
150
  * `runnerFor: () => runner` —— 那是一句表态,不是一个回落。
@@ -464,7 +465,8 @@ export interface ServiceSeamDeps {
464
465
  }>;
465
466
  /** 142-S5 §1.4: per-scope memory export reader (main.ts wires `exportMemoryScope` over the DB memory
466
467
  * backend). Enables GET /v1/memory/export — present ONLY on a DB memory plane (MEMORY_ENGINE_BACKEND=
467
- * pg|mysql); absent / file posture ⇒ 501 (single-user file memory exports by copying the memory dir). */
468
+ * pg|mysql); absent ⇒ 501 (single-user file memory exports by copying the memory dir). The gate and the capability bit
469
+ * `memoryExport` read ONE fact (`capability-facts.ts` `memoryExport`) — whether this face is wired, never the backend name. */
468
470
  memoryExport?: (scope: string) => Promise<MemoryEntry[]>;
469
471
  /**
470
472
  * [ref](core 5.57.0 `routePairingStatus`)—— **key↔URL 配对读面**:`GET /v1/models` 每行的
@@ -479,10 +481,12 @@ export interface ServiceSeamDeps {
479
481
  routeJudgeBrain?: Pick<Brain, "adjudicateRoute">;
480
482
  /** 142-S2.5(设计 §2.5;裁定 plan 随数据走,core 零运行时半场):one full sync round for one
481
483
  * (scope, peer) — main.ts wires `performMemorySync` over the DB memory backend + the sync-cursor
482
- * store. Enables POST /v1/memory/sync/:scope — present ONLY on a DB memory plane
483
- * (MEMORY_ENGINE_BACKEND=pg|mysql); absent / file posture ⇒ 501 honestly (a single-user file plane
484
- * IS the TOC side of a sync — it has no central-authority half to serve). */
485
- memorySync?: (scope: string, syncReq: MemorySyncRequest) => Promise<MemorySyncResponse>;
484
+ * store. Enables POST /v2/memory/sync/:scope — present ONLY on a DB memory plane
485
+ * (MEMORY_ENGINE_BACKEND=pg|mysql); absent ⇒ 501 honestly (a single-user file plane
486
+ * IS the TOC side of a sync — it has no central-authority half to serve). [ref]: the face also needs the center's
487
+ * declared sync identity (`config.memorySyncServeIdentity`) — the gate and the capability bit `memorySyncServe` read ONE
488
+ * fact (`capability-facts.ts` `memorySyncServe`). */
489
+ memorySync?: (scope: string, syncReq: MemorySyncRequest) => Promise<MemorySyncAnswer>;
486
490
  /** [ref] v2-c(core 5.40.0 `MemoryEngine.exportMemoryScopes`):治理完备包的**携出**面。main.ts 把它接到
487
491
  * 装配好的 memory engine 上。启用 `POST /v1/memory/export`(operator-only)。
488
492
  * 🔴 缺席 = 这个部署**没有记忆引擎**(`MEMORY_ENGINE=off` / 多租 file 底座等暗态)⇒ 501
@@ -538,8 +542,10 @@ export interface ServiceSeamDeps {
538
542
  * [ref] —— 本**部署**的记忆同步腿(客户端半场):`MEMORY_SYNC_URL` 设了且 file 记忆引擎亮着、执行器起了才在场(`boot/stores.ts`)。
539
543
  * `GET /v1/sessions/:id/memory-status` 的 `memorySync` 格只读它的 `parked()` —— 停驻事实的唯一读口(写者 = 执行器的轮,运维行 `memory_sync_layer_parked` 读同一份);
540
544
  * 缺席 ⇒ 那一格缺席(没有同步腿)。与 `memoryAutoConsolidationArmed` 同类:部署事实,不随会话、不随层座。
545
+ * [ref]:会话记忆同步触发口(`POST /v1/sessions/:id/memory/sync`)读它的 `peer`(目标比对)与 `syncOnce`(一轮,交回每层每次调用;从不 reject)——
546
+ * 能力事实 `sessionMemorySync` 的第一格就是它在不在。
541
547
  */
542
- memorySyncLeg?: Pick<MemorySyncRunner, "parked">;
548
+ memorySyncLeg?: Pick<MemorySyncRunner, "parked" | "peer" | "syncOnce">;
543
549
  /**
544
550
  * [ref] / [ref] + 车PI 修复轮 ④ —— 记忆整理阀门的**生效判决**(boot 第 4 段 `createConsolidationValve`:显式词,或出厂缺省按
545
551
  * 装配结果派生)。配置目录那一行(`GET /v1/config/catalog` 的 `MEMORY_CONSOLIDATION_DRIVER` `effectiveValue`)读它 —— 那一列的契约是
@@ -698,10 +704,11 @@ export interface ServiceDeploymentDeps {
698
704
  /** [ref] ②:caps `centerWiring` 的读面(`capabilities/center-wiring.ts` `createCenterWiringReader`;入参 = 请求的已验 principal)。
699
705
  * 缺席 = 没接中心(或测试夹具)⇒ 键整个缺席。 */
700
706
  centerWiring?: (principal: string | undefined) => import("../capabilities/center-wiring.js").CenterWiring;
701
- /** The member git-credential plane's one reading (`sandbox-git-plane.ts`; stage 5 computes it once — config premises + the boot's secret
702
- * seat answer + the static patch judge). Caps `credentialPlane.sandboxGit` projects it as is. Absent = not built by the composition root
703
- * (a fixture) ⇒ the same judge on config alone, the seat counted as not asked. */
704
- sandboxGitPlane?: import("../sandbox-git-plane.js").SandboxGitPlane;
707
+ /** The member git-credential plane's read function (`sandbox-git-plane.ts` `createSandboxGitPlaneSeat`'s `now`: the judge over the boot readings — the
708
+ * secret seat answer stage 5 settles, the static patch judge — and the live config, whose `sandboxGit` block hot-swaps with each effective-config commit).
709
+ * Caps `credentialPlane.sandboxGit` calls it on every read and projects the answer as is. Absent = not built by the composition root (a fixture) ⇒
710
+ * the same judge on config alone, the seat counted as not asked. */
711
+ sandboxGitPlane?: () => import("../sandbox-git-plane.js").SandboxGitPlane;
705
712
  /**
706
713
  * 本进程起服装上的**运维声明** mod 包数(部署座装配口 `assembleDeploymentMods` 的 `loaded.length`;本服务自铸的注册不算)。一个事实两个出口,同读这一格:
707
714
  * `/health` 的 `mods: { deploymentPackages }` 与 `/v1/capabilities` 的 `modsDeploymentPackages: true` —— 都只在 > 0 时在场;0 / 缺席(没声明,或不是由
@@ -761,6 +768,9 @@ export interface ServiceDeploymentDeps {
761
768
  * `candidateRejectionState: () => webAdmin.candidateRejectionState()`;座 = web-admin 的 `candidateRejection`,`config_candidate_rejected` 日志行的去重键读同一份)。
762
769
  * present-iff 当前生效配置是因候选被拒而回落的那一份;缺席 / 返回 undefined = 没有被拒的候选或没有配置管道 ⇒ `GET /v1/models` 不出该键(additive)。 */
763
770
  candidateRejectionState?: () => import("../web-admin-client/candidate-gate.js").CandidateRejection | undefined;
771
+ /** `GET /v1/models.modelPlane.planeRefusalCode` 与 `catalog` 模型面那一半的取值口(`boot/stage-10-http-server.ts` → `latestPlaneRefusalState: () => webAdmin.latestPlaneRefusalState()`):
772
+ * 最新到达的目录候选被模型面组拒的码。缺席 / 返回 undefined = 最新到达的候选没有被模型面组拒,或没有配置管道 ⇒ 读面不出该键。 */
773
+ latestPlaneRefusalState?: () => import("@sema-agent/settings-schema").ModelPlaneRefusalCode | undefined;
764
774
  /** `/health.configHandoff`(只上 `/health`):在场 ⇔ 部署声明了耐久接力 ∧ 应用着的那一代没被确认(web-admin 接力账的 `configHandoffState()`;合成律
765
775
  * `fleet/engine-signal.ts` 的 `buildConfigHandoff`)。缺席 / 返回 undefined = 有接力、没有中心或本地腿 ⇒ 键缺席。 */
766
776
  configHandoffState?: () => import("../fleet/engine-signal.js").ConfigHandoff | undefined;
@@ -911,6 +921,8 @@ export declare function createHttpServer(rawDeps: ServiceDeps): http.Server & {
911
921
  isRunLiveOnThisReplica: (taskId: string) => boolean;
912
922
  /** [ref]:live 回决腿的 PARKED 赎回席(装配层把它接进协调器的晚绑座,见 {@link redeemParkedAsk})。 */
913
923
  redeemParkedAsk: ParkedAskRedeem;
924
+ /** 会话通知门(装配层把它接进场景层后台完成 sink 的晚绑座;门与律见 `session-notify-door.ts`)。 */
925
+ sessionNotifyDoor: SessionNotifyDoor;
914
926
  };
915
927
  /** SSE: replay durable events after Last-Event-ID, then tail until the run is terminal (or stale). */
916
928
  /**
@@ -18,7 +18,7 @@ import { cascadeConfig } from "./run-meta.js";
18
18
  export { cascadeConfig };
19
19
  import { coarseStatusForState, errorCodeForExit } from "./routes/images.js";
20
20
  export { coarseStatusForState, errorCodeForExit };
21
- import { sendError, sendHttpError, sendSessionError, logRequestError } from "./send.js";
21
+ import { sendError, sendHttpError, sendOpenFaceFault, logRequestError } from "./send.js";
22
22
  import { createRequestGuards } from "./request-guards.js";
23
23
  import { sqlEngineSeatIssue } from "../sql-engine-posture.js";
24
24
  import { parkDecisionStoreRefusal } from "../orchestration/workflow-park-decision.js";
@@ -152,7 +152,7 @@ export function createHttpServer(rawDeps) {
152
152
  }
153
153
  const { quotaExceeded, ownerCostQuotaDenied, ownerFleetLeaseDenied, ownerLeaseDenied, ownerQuotaDenied, leaseDenied, usageWindowDenialFor, usageWindowDenied, rateLimited, safeDecode, runOwnerOk, sessionOwnerOk, runSessionAcceptOk, readJson, readRawBody } = createRequestGuards({ deps });
154
154
  const { prepareSpec } = createAdmission({ deps, readJson, runnerFor });
155
- const { routeCtxBase, resumeCheckpoint, driveResumeIntoRunLog, driveResumeLeg, mayDiscloseRowError, resumePreempted, startFreshHostTurn, resumeWake } = createResumeLegs({ deps, runnerFor, idemCache, inflightRuns, preemptableRuns, steerableRuns, wakeParkMints, counters, readJson, readRawBody, rateLimited, quotaExceeded, ownerQuotaDenied, leaseDenied, ownerLeaseDenied, usageWindowDenied, safeDecode, runOwnerOk, sessionOwnerOk, runSessionAcceptOk, prepareSpec, finalizeTaskResult, ownerCostQuotaDenied, ownerFleetLeaseDenied, usageWindowDenialFor });
155
+ const { routeCtxBase, resumeCheckpoint, driveResumeIntoRunLog, driveResumeLeg, mayDiscloseRowError, resumePreempted, startFreshHostTurn, resumeWake, sessionNotifyDoor } = createResumeLegs({ deps, runnerFor, idemCache, inflightRuns, preemptableRuns, steerableRuns, wakeParkMints, counters, readJson, readRawBody, rateLimited, quotaExceeded, ownerQuotaDenied, leaseDenied, ownerLeaseDenied, usageWindowDenied, safeDecode, runOwnerOk, sessionOwnerOk, runSessionAcceptOk, prepareSpec, finalizeTaskResult, ownerCostQuotaDenied, ownerFleetLeaseDenied, usageWindowDenialFor });
156
156
  const { denyExpiredApprovals, redeemParkedAsk } = createApprovalSweeps({ deps, resumeCheckpoint, mayDiscloseRowError });
157
157
  const { handle } = createDispatch({ deps, noteActivity, routeCtxBase, counters });
158
158
  const server = http.createServer((req, res) => {
@@ -169,13 +169,11 @@ export function createHttpServer(rawDeps) {
169
169
  res.end();
170
170
  return;
171
171
  }
172
- if (sendSessionError(res, err, "open"))
173
- return;
174
172
  if (err instanceof SessionForkInProgressError) {
175
173
  sendError(res, 409, err.code, err.message);
176
174
  return;
177
175
  }
178
- sendError(res, 500, "internal.error", "internal error");
176
+ sendOpenFaceFault(res, err);
179
177
  });
180
178
  });
181
179
  const deviceLane = facts.deviceLane(deps);
@@ -208,6 +206,6 @@ export function createHttpServer(rawDeps) {
208
206
  deps.planCacheProbe?.record(principal, objective, result.terminal.kind === "completed");
209
207
  }
210
208
  const isRunLiveOnThisReplica = (taskId) => inflightRuns.has(taskId) || steerableRuns.has(taskId);
211
- return Object.assign(server, { denyExpiredApprovals, isRunLiveOnThisReplica, redeemParkedAsk });
209
+ return Object.assign(server, { denyExpiredApprovals, isRunLiveOnThisReplica, redeemParkedAsk, sessionNotifyDoor });
212
210
  }
213
211
  //# sourceMappingURL=server.js.map
@@ -1,4 +1,4 @@
1
- import { REQUEST_SETTINGS_REFUSAL_PREFIX, SETTINGS_RULE_REFUSAL_CODE, neverAutoNamesRefusal, rulePolicyBucketsRefusal, settingsPermissionBucketIssue, storedBodyPermissionMode } from "../task-settings.js";
1
+ import { REQUEST_SETTINGS_REFUSAL_PREFIX, SETTINGS_PERMISSION_BUCKETS, SETTINGS_RULE_REFUSAL_CODE, neverAutoNamesRefusal, rulePolicyBucketsRefusal, settingsPermissionBucketIssue, storedBodyPermissionMode } from "../task-settings.js";
2
2
  import { readTightenOnlySeats, tightenOnlySeatField, tightenOnlySeatIssue } from "../tighten-only-seats.js";
3
3
  import { entryProblemsFacts } from "../entry-problems.js";
4
4
  import { autonomyModeFloor, entryPermissionMode } from "../runtime-governance.js";
@@ -15,6 +15,11 @@ export function permissionModeReadingUnstated(ctx, floor) {
15
15
  }
16
16
  const RETIRED_KEY_REWRITE_MIGRATION = { promptProfile: "M30" };
17
17
  const BUCKET_GATE_CODE = "request.field_invalid";
18
+ const BUCKET_SIDE = {
19
+ "settings.permissions.allow": "allow",
20
+ "settings.permissions.deny": "deny",
21
+ "settings.permissions.ask": "deny",
22
+ };
18
23
  function storedPermissions(body) {
19
24
  const permissions = body?.settings?.permissions;
20
25
  return permissions !== null && typeof permissions === "object" && !Array.isArray(permissions) ? permissions : undefined;
@@ -23,7 +28,7 @@ function storedPermissionBucketRefusal(body) {
23
28
  const issue = settingsPermissionBucketIssue(storedPermissions(body));
24
29
  if (issue === null)
25
30
  return undefined;
26
- return replayInertEntry(issue.fields.field, issue.fields.field === "settings.permissions.allow" ? "allow" : "deny", BUCKET_GATE_CODE, issue.message, { ...issue.fields });
31
+ return replayInertEntry(issue.fields.field, BUCKET_SIDE[issue.fields.field], BUCKET_GATE_CODE, issue.message, { ...issue.fields });
27
32
  }
28
33
  function storedTightenOnlySeatRefusal(body) {
29
34
  const issue = tightenOnlySeatIssue(body?.settings);
@@ -37,9 +42,15 @@ function storedRulePolicyRefusal(body, deployment) {
37
42
  return undefined;
38
43
  const home = executionLaneHomeDir(deployment);
39
44
  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 } : {}) });
45
+ const buckets = {};
46
+ for (const bucket of SETTINGS_PERMISSION_BUCKETS) {
47
+ const entries = permissions[bucket];
48
+ if (Array.isArray(entries))
49
+ buckets[bucket] = entries;
50
+ }
51
+ const refused = rulePolicyBucketsRefusal(buckets, { ...(home !== undefined ? { home } : {}), ...(configRoot !== undefined ? { configRoot } : {}) });
41
52
  if (refused !== undefined)
42
- return replayInertEntry(`settings.permissions.${refused.bucket}`, "deny", SETTINGS_RULE_REFUSAL_CODE, `${REQUEST_SETTINGS_REFUSAL_PREFIX}${refused.message}`, { ...entryProblemsFacts(refused.problems) });
53
+ return replayInertEntry(`settings.permissions.${refused.bucket}`, BUCKET_SIDE[`settings.permissions.${refused.bucket}`], SETTINGS_RULE_REFUSAL_CODE, `${REQUEST_SETTINGS_REFUSAL_PREFIX}${refused.message}`, { ...entryProblemsFacts(refused.problems) });
43
54
  const neverAuto = readTightenOnlySeats({ permissions }).values.neverAuto;
44
55
  if (neverAuto === undefined)
45
56
  return undefined;
@@ -18,9 +18,10 @@
18
18
  *
19
19
  * ## 回执两形(按提交腿)
20
20
  * · `durable`(`POST /v1/runs`、A2A `message/send`)—— `202 { taskId, sessionId, status }`(这条腿首答的既有形);
21
- * · `sync`(`POST /v1/tasks`;`/v1/tasks/stream` 把同一份体放进 `done.result`)—— `200 { …run 行读面, replay: true }`
22
- * (读面 = `GET /v1/runs/:id` 的 200 体,同一只投影口 `readRunFace`)。同步腿的首答是引擎结果,而重放时手里只有行;
23
- * `replay: true` 是这一形的判别位。
21
+ * · `sync`(`POST /v1/tasks`;`/v1/tasks/stream` 把同一份体放进 `done.result`)—— `200 { …首答的信封, replay: true }`:
22
+ * 首答的信封由 `http/sync-submit-body.ts` 铸(`buildSyncSubmitBody`),重放经同文件的 `syncSubmitBodyOfRow` 读行 ——
23
+ * 终局 / 停驻行上有结果 ⇒ 与首答同形(结果的键在顶层,`result` 是串);行上没有结果可交(首投还在跑)⇒ 轮询回执 `{ taskId, sessionId, status }`。
24
+ * `replay: true` 是重放的判别位(本函数叠上,不在信封里)。
24
25
  */
25
26
  import type { RunIdemBinding, RunRecord } from "../plugins/store-contracts.js";
26
27
  import type { RunStore } from "../plugins/store-backend.js";
@@ -1,5 +1,5 @@
1
1
  import { runRowReadable } from "./owner-access.js";
2
- import { readRunFace } from "./run-read-face.js";
2
+ import { syncSubmitBodyOfRow } from "./sync-submit-body.js";
3
3
  import { refusalBody } from "./refusal-body.js";
4
4
  export function isRunExistsConflictBody(body) {
5
5
  return typeof body === "object" && body !== null && body.errorCode === "conflict.run_exists";
@@ -19,7 +19,7 @@ export async function replayOfExistingRun(row, caller, face, deps, runStore) {
19
19
  case "durable":
20
20
  return { status: 202, body: { taskId: row.taskId, sessionId: row.sessionId, status: row.status } };
21
21
  case "sync":
22
- return { status: 200, body: { ...(await readRunFace(deps, runStore, row)), replay: true } };
22
+ return { status: 200, body: { ...syncSubmitBodyOfRow(deps, row), replay: true } };
23
23
  default: {
24
24
  const unknown = face;
25
25
  throw new Error(`replayOfExistingRun: unknown submit face ${String(unknown)}`);
@@ -25,14 +25,19 @@
25
25
  * (`observability/run-terminal.ts`),调用方铸一次交进来;本函数只负责「体长什么样」。凭据(`paused.token` /
26
26
  * `failed.nestedPause.token`)因此在进本函数之前就已摘掉,幂等缓存存的正是本函数的产物,重放体同体同脱。
27
27
  */
28
- import type { ParkedRunStatus, PersistedTaskResult } from "../plugins/store-contracts.js";
29
- /** park 中的 run 在同步 200 体上带的 poll 回执三键(修前 park 体的全部内容,值逐字不变)。 */
30
- export interface SyncParkReceipt {
28
+ import { type ParkedRunStatus, type PersistedTaskResult, type RunRecord } from "../plugins/store-contracts.js";
29
+ import { type RunFaceDeps } from "./run-read-face.js";
30
+ /** 同步 200 体上的 poll 回执三键:一条 run 的 poll 键、会话、对外词。park 体叠在结果之上带它({@link SyncParkReceipt});重放命中一条还没有结果可交的行时,它**就是**整个体({@link syncSubmitBodyOfRow})。 */
31
+ export interface SyncRunReceipt {
31
32
  /** 同步腿提交时铸的 durable run id —— `GET /v1/runs/:taskId` 的 poll 键。 */
32
33
  taskId: string;
33
34
  /** 提交的会话。 */
34
35
  sessionId: string;
35
- /** 对外词 = `GET /v1/runs/:id` 行上的 `status`(park 两词之一,闭集从 `RUN_STATUS_CLASS` 派生)。 */
36
+ /** 对外词 = `GET /v1/runs/:id` 行上的 `status`。 */
37
+ status: RunRecord["status"];
38
+ }
39
+ /** park 中的 run 在同步 200 体上带的 poll 回执三键(修前 park 体的全部内容,值逐字不变);`status` 是 park 两词之一(闭集从 `RUN_STATUS_CLASS` 派生)。 */
40
+ export interface SyncParkReceipt extends SyncRunReceipt {
36
41
  status: ParkedRunStatus;
37
42
  }
38
43
  /**
@@ -40,4 +45,16 @@ export interface SyncParkReceipt {
40
45
  * 返回的是纯数据(无方法、无闭包)⇒ `build*`。
41
46
  */
42
47
  export declare function buildSyncSubmitBody<R extends PersistedTaskResult>(exitResult: R, parkReceipt?: SyncParkReceipt): R | (R & SyncParkReceipt);
48
+ /**
49
+ * **同键重放读行的出口** —— 同一条 run 的同步 200 体,首答与重放读**同一只信封**:终局行 / 停驻行上有结果 ⇒ 经 {@link buildSyncSubmitBody} 铸
50
+ * (终局 = 结果本身;停驻 = 结果 + 回执三键),与首答的三个 200 出口逐字同形 —— 首答恒 = 「出口封口 + 脱敏后的引擎结果」,那份对象就是落在行上的那一份
51
+ * (调用方铸一次、既落行又进体),重放读到的是它被读入口(同一只 {@link runRowExitResult},`GET /v1/runs/:id` 的 `result` 读的也是它)再封再脱的样子。
52
+ * 行上没有结果可交(首投还在跑、在别的副本上没落定;或终局行的结果已被收割清空)⇒ 首答在这一刻**不存在**,体只剩 {@link SyncRunReceipt} 三键 —— 去 `GET /v1/runs/:taskId` 轮询,
53
+ * 不把「读面」塞进同步体里充首答(失联折叠与读面同一只判据 {@link runRowStale}:折成 `failed`)。
54
+ *
55
+ * 首答体上另有两类**本次请求**的附注(`notice` / `warnings`,见 `routes/tasks.ts` 的 `withSyncSubmitKeys`):重放在 `prepareSpec` 之前就答了,
56
+ * 结构上不知道本次请求带没带 verify / cascade、放行侧选择器里有没有空条目 ⇒ 重放体没有它们。判别位 `replay: true` 由重放出口(`submit-replay.ts`)叠上,不在信封里。
57
+ * 纯数据 ⇒ `build*` 的近亲;名字取 `…OfRow`(行 → 体的读法),与 `buildSyncSubmitBody` 同文件同铸点。
58
+ */
59
+ export declare function syncSubmitBodyOfRow(deps: RunFaceDeps, row: RunRecord): ReturnType<typeof buildSyncSubmitBody> | SyncRunReceipt;
43
60
  //# sourceMappingURL=sync-submit-body.d.ts.map
@@ -1,4 +1,17 @@
1
+ import { isParkedRunStatus, isTerminalRunStatus } from "../plugins/store-contracts.js";
2
+ import { runRowExitResult, runRowStale } from "./run-read-face.js";
1
3
  export function buildSyncSubmitBody(exitResult, parkReceipt) {
2
4
  return parkReceipt === undefined ? exitResult : { ...exitResult, ...parkReceipt };
3
5
  }
6
+ export function syncSubmitBodyOfRow(deps, row) {
7
+ const stale = runRowStale(deps, row);
8
+ const exit = stale ? undefined : runRowExitResult(row);
9
+ if (exit !== undefined) {
10
+ if (isTerminalRunStatus(row.status))
11
+ return buildSyncSubmitBody(exit);
12
+ if (isParkedRunStatus(row.status))
13
+ return buildSyncSubmitBody(exit, { taskId: row.taskId, sessionId: row.sessionId, status: row.status });
14
+ }
15
+ return { taskId: row.taskId, sessionId: row.sessionId, status: stale ? "failed" : row.status };
16
+ }
4
17
  //# sourceMappingURL=sync-submit-body.js.map
@@ -587,18 +587,28 @@ export interface TaskRequestBody {
587
587
  enableFork?: boolean;
588
588
  [k: string]: unknown;
589
589
  }
590
- /** [ref] D-1: the operator-echoed decision-action binding carried on POST /v1/approvals/:sessionId/decide([ref]C-4:裸 :id 臂已删).
591
- * All optional for back-compat — a legacy BFF caller omitting them resumes on the current-pending values
592
- * exactly as before (the pre-D-1 path), tracked by a deprecation counter.
590
+ /** [ref] D-1 —— **一个答案只属于它被展示的那一个动作**:决断方在队列行上看到的那一对(`GET /v1/approvals` 行的 `boundCallId` /
591
+ * `boundInputHash`),原样回显、从不重算,引擎在认领前逐字比对。本服务从不拿当前停驻行替决断方补任何一位 —— 补上的是此刻停在门上的动作,
592
+ * 不是决断方看到的那一个。判官 = `http/resume-legs.ts` 的 `decidedActionOf`。 */
593
+ export type DecidedAction = {
594
+ /** The pendingAction.toolCallId the decider saw — echoed into ResumeOutcome.boundCallId. */
595
+ readonly boundCallId: string;
596
+ /** The engine-minted opaque boundInputHash the decider saw — echoed VERBATIM (never recomputed here). */
597
+ readonly boundInputHash: string;
598
+ };
599
+ /** [ref] D-1: the decision-action binding as read off POST /v1/approvals/:sessionId/decide([ref]C-4:裸 :id 臂已删).
600
+ * The body's value-shape gate only checks "a string when present"; the pair {@link DecidedAction} is REQUIRED and judged by the
601
+ * resume leg after its gate-kind guard (a wrong gate kind gets its 409 pointer first): either half missing ⇒ 400
602
+ * `decide_requires_binding` naming `missingKeys`. 7.142.x and earlier filled a missing half from the current pending row.
593
603
  * [ref] A9: hoisted VERBATIM out of `createHttpServer`'s closure so the approvals/assistant route domain
594
604
  * and the resume leg can name the SAME shape without a routes/* → server.ts value edge. */
595
605
  export type DecideBinding = {
596
- /** The capability token the operator actually SAW (from listPending). A mismatch with the current pending
597
- * ⇒ approval_stale (they decided a superseded/resolved view). */
606
+ /** The capability token the decider saw (never surfaced on the queue row; the server-internal seats hold it). A mismatch
607
+ * with the current pending ⇒ approval_stale (they decided a superseded/resolved view). Optional, and never a substitute for the pair. */
598
608
  checkpointToken?: string;
599
- /** The pendingAction.toolCallId the operator saw — echoed into ResumeOutcome.boundCallId. */
609
+ /** {@link DecidedAction.boundCallId} as echoed (required for a decision; see the type note). */
600
610
  boundCallId?: string;
601
- /** The server-minted opaque boundInputHash the operator saw — echoed VERBATIM (never recomputed here). */
611
+ /** {@link DecidedAction.boundInputHash} as echoed (required for a decision; see the type note). */
602
612
  boundInputHash?: string;
603
613
  /** [ref] edit: operator-corrected tool args, applied by core AFTER the binding check, on approve only. */
604
614
  updatedInput?: unknown;
@@ -12,9 +12,13 @@
12
12
  * 3. **缺席一种读法**:`null` = 这一行**没有「属主在受理时验过的凭据」的记录** —— 三列存在之前写下的行、没有任何验过凭据的受理(无鉴权写面
13
13
  * `ALLOW_UNAUTHED_WRITES`)、以及别人替属主按下的那一跑(受理请求验过的主体不是这一行的属主:唤醒 / 决定投递铸的新一跑)。读者一律按「不合格」处置
14
14
  * (fail-closed),不分辨三种成因;存量行不回填(没有事实可回填)。
15
+ * 4. **令牌声明装不进它的列就不记**(不截断:截断 = 两个不同的值折成一个):`sso` 臂从验过的令牌铸元组时,某一格装不进它的列宽({@link RUN_IDENTITY_CLAIM_COLUMNS})
16
+ * ⇒ 那一格「未记录」—— 可空的格(化身号)记 `null`;必填的格(scope)装不下就铸不出合形元组 ⇒ 无元组。两格结果不同来自元组的型,不是两条规则:
17
+ * 同一只判({@link runIdentityClaimOverflow})、同一行告警 `run_identity_claim_unrecorded { claim, chars, max }`(凭据门的铸点发;只名与长度,不带值)。
15
18
  *
16
- * 化身号 `principalInc`:令牌 `sub_inc` 声明原样,经契约包 `VerifiedIdentity.principalInc` 读(settings-schema 14.7.0 加的可选字段,已提货:验证腿随身份带出);本版接线未做 ⇒ 恒 `null`,
17
- * 接线点在 `admitRunIdentity` 的 `sso` 臂(不在本仓另定一份读法)。
19
+ * 化身号 `principalInc`:令牌 `sub_inc` 声明原样(契约包 `VerifiedIdentity.principalInc`)。来源链只有一条 —— 验证器读出 → 注入边界再判形(`auth-bridge.ts` 的
20
+ * `admitBridgeIdentity`)→ 入口预认证挂 request-local(`security.ts` 的 `setSsoPrincipalInc`)→ 凭据门 `admitRunIdentity` 的 `sso` 臂铸进元组(律 4)→ 建行原样写入。
21
+ * `null` 化身号只有一种读法:**未记录**(契约 §12.8「缺 ⇒ 化身号未记录」)—— 存量行、令牌没带、装不下,三种成因同一读法。
18
22
  */
19
23
  /** 验过的身份来源的**闭集**(序 = 判定次序 = `/health.auth.kinds` 的出现序;加一个来源 = 加一个词,读它的各只穷举 `switch` 不接就编译红)。 */
20
24
  export declare const IDENTITY_SOURCES: readonly ["service_token", "sso", "direct_door_jwt"];
@@ -36,6 +40,21 @@ export type RunIdentity = {
36
40
  export declare const RUN_IDENTITY_SCOPE_MAX_CHARS = 190;
37
41
  /** `identity_principal_inc` 的列宽(字符):化身号是签发方插入时铸的不透明随机串(与会话化身同宽)。 */
38
42
  export declare const RUN_IDENTITY_PRINCIPAL_INC_MAX_CHARS = 64;
43
+ /** 令牌声明 → 它落的那一列的列宽(字符;律 4 的判读这一张)。 */
44
+ export declare const RUN_IDENTITY_CLAIM_COLUMNS: {
45
+ readonly scope: 190;
46
+ readonly principalInc: 64;
47
+ };
48
+ export type RunIdentityClaim = keyof typeof RUN_IDENTITY_CLAIM_COLUMNS;
49
+ /**
50
+ * 律 4 的判:这一格令牌声明装不装得进它的列(按码点数,与两方言 VARCHAR 同口径)。装得下 ⇒ `undefined`;装不下 ⇒ 告警行 `run_identity_claim_unrecorded` 的载荷
51
+ * (`claim` 名 + 码点数 + 列宽,不带值)。调用方按格的型处置:可空格记 `null`,必填格无元组。
52
+ */
53
+ export declare function runIdentityClaimOverflow(claim: RunIdentityClaim, value: string): {
54
+ readonly claim: RunIdentityClaim;
55
+ readonly chars: number;
56
+ readonly max: number;
57
+ } | undefined;
39
58
  /**
40
59
  * `task_run` 三列的列定义 —— 两方言各一段,**唯一属主**:中央建表语句(`tidb-pool.ts` / `pg-pool.ts` 的 `CREATE TABLE task_run`)内插这同一段;
41
60
  * 存量库缺列时起服列册对账(`schema-consistency.ts`)拒启,拒句里的 `ALTER TABLE task_run ADD COLUMN …` 由同一份建表语句解析生成 ⇒
@@ -1,6 +1,12 @@
1
1
  export const IDENTITY_SOURCES = ["service_token", "sso", "direct_door_jwt"];
2
2
  export const RUN_IDENTITY_SCOPE_MAX_CHARS = 190;
3
3
  export const RUN_IDENTITY_PRINCIPAL_INC_MAX_CHARS = 64;
4
+ export const RUN_IDENTITY_CLAIM_COLUMNS = { scope: RUN_IDENTITY_SCOPE_MAX_CHARS, principalInc: RUN_IDENTITY_PRINCIPAL_INC_MAX_CHARS };
5
+ export function runIdentityClaimOverflow(claim, value) {
6
+ const chars = [...value].length;
7
+ const max = RUN_IDENTITY_CLAIM_COLUMNS[claim];
8
+ return chars > max ? { claim, chars, max } : undefined;
9
+ }
4
10
  export const RUN_IDENTITY_COLUMNS = {
5
11
  mysql: [
6
12
  "identity_source VARCHAR(32) NULL",
@@ -4,6 +4,7 @@ import { pullDiff } from "./diffout.js";
4
4
  import { mergeBranches } from "./merge.js";
5
5
  import { Runner, runWithVerification, resumeWithVerification } from "@sema-agent/core";
6
6
  import { pausedCauseOf, outwardPlane } from "../terminal.js";
7
+ import { voidVerifierPauseCard } from "../verifier-pause-card.js";
7
8
  import { entryPermissionMode } from "../runtime-governance.js";
8
9
  import { withUnattendedLeg } from "../unattended-permission-mode.js";
9
10
  const MAX_RESUME_SLICES = 200;
@@ -93,11 +94,13 @@ export async function runLeaderTask(task, durableBaseSha, deps) {
93
94
  const w = bySession.get(st.sessionId);
94
95
  const base = { workerId: w.workerId, sessionId: w.sessionId, branch: w.branch, baseSha: w.baseSha };
95
96
  const cfg = w.verifierTools ? { ...verify, verifierTools: w.verifierTools } : verify;
96
- let vr = await runWithVerification(w.runner, { ...w.spec, sessionId: w.sessionId, signal }, cfg);
97
+ const workerRunner = w.runner;
98
+ let vr = await runWithVerification(workerRunner, { ...w.spec, sessionId: w.sessionId, signal }, cfg);
97
99
  vr = await autoResumeOnResource(vr, signal, async (token, slice) => {
98
100
  deps.logger?.info?.("worker_resource_resume", { workerId: w.workerId, slice });
99
- return resumeWithVerification(w.runner, token, { gate: "resource_limit", decision: "continue" }, { ...w.spec, sessionId: w.sessionId, signal }, w.spec.objective ?? "", cfg);
101
+ return resumeWithVerification(workerRunner, token, { gate: "resource_limit", decision: "continue" }, { ...w.spec, sessionId: w.sessionId, signal }, w.spec.objective ?? "", cfg);
100
102
  });
103
+ await voidVerifierPauseCard(vr, workerRunner);
101
104
  const vrPlane = outwardPlane(vr.terminal);
102
105
  deps.logger?.info?.("verify_outcome", { workerId: w.workerId, status: vrPlane.status, verdict: vr.verification.verdict, rounds: vr.verification.rounds, finding: redactHead(vr.verification.findings[0] ?? "", 220) });
103
106
  const pass = vr.terminal.kind === "completed" && vr.verification.verdict === "PASS";
@@ -138,6 +138,10 @@ export interface LeaderWireConfig {
138
138
  brain: Brain;
139
139
  models: Record<string, Model>;
140
140
  roles: ModelRoles;
141
+ /** The active tier table of the served catalog (boot hands the same object as `config.tiers`, mutated in place on a hot apply).
142
+ * Every leader Runner gets it with `models` / `roles` (one seat, `servedTableSeat`): a role resolves in the tier-expanded view,
143
+ * exactly as the main runner resolves it — absent ⇒ no tiers (the env table has none). */
144
+ tiers?: NonNullable<RunnerDeps["tiers"]>;
141
145
  pricing: Record<string, ModelPricing>;
142
146
  /** Workspace root inside each E2B VM. Default /home/user. */
143
147
  workspace?: string;
@@ -152,7 +156,9 @@ export interface LeaderWireConfig {
152
156
  * classification; running it on a heavy reasoning model (deepseek-v4-pro + reasoning) returns an EMPTY
153
157
  * completion ~2/3 of the time — the budget is spent on reasoning with no answer text → "not valid JSON" →
154
158
  * collapse-to-single, silently defeating fan-out (search 2026-06-14, reproduced 3×). A cheap non-reasoning
155
- * model (deepseek-v4-flash) routes correctly 51/51 in probes. Unset → the route runs on the default model. */
159
+ * model (deepseek-v4-flash) routes correctly 51/51 in probes. Unset → the route resolves the `classifier` role
160
+ * in the served table (the same `models` / `roles` every task of this leader resolves against; core's fallback
161
+ * chain classifier → summarize → default: the env cheap slot binds `summarize`, an adopted catalog binds its own). */
156
162
  routerModel?: string;
157
163
  /** Max bounded integration-repair rounds on a clean-merge-but-failing-build (see merge.ts IntegrationRepair).
158
164
  * 0 / unset = OFF (a failing integration test is terminal, the pre-2026-06-14 behavior). Env override:
@@ -168,6 +168,7 @@ export function createLeaderRunner(cfg) {
168
168
  const deploymentPostureSeat = () => cfg.deploymentPosture?.() ?? {};
169
169
  const tracerSeat = cfg.tracer ? { tracer: cfg.tracer } : {};
170
170
  const modsSeat = cfg.mods ? { mods: cfg.mods } : {};
171
+ const servedTableSeat = { models: cfg.models, roles: cfg.roles, ...(cfg.tiers ? { tiers: cfg.tiers } : {}) };
171
172
  const usageWindowSeat = cfg.usageWindows && cfg.usageWindowStore ? { usageWindows: cfg.usageWindows, usageWindowStore: cfg.usageWindowStore } : {};
172
173
  const promptSourceSeat = cfg.promptSource ? { promptSource: cfg.promptSource } : {};
173
174
  const onErrorSeat = cfg.onError ? { onError: cfg.onError } : {};
@@ -188,7 +189,7 @@ export function createLeaderRunner(cfg) {
188
189
  throw new Error(`oracle still present after remove (${f.path}) — refusing repair (measurement integrity)`);
189
190
  }
190
191
  try {
191
- const runner = new Runner({ brain: cfg.brain, models: cfg.models, roles: cfg.roles, pricing: cfg.pricing, ...onNoticeSeat, ...governanceSeat, ...deploymentPostureSeat(), ...tracerSeat, ...usageWindowSeat, ...promptSourceSeat, ...onErrorSeat, ...modsSeat, executionEnv: rawEnv, rootPath: repoDir });
192
+ const runner = new Runner({ brain: cfg.brain, ...servedTableSeat, pricing: cfg.pricing, ...onNoticeSeat, ...governanceSeat, ...deploymentPostureSeat(), ...tracerSeat, ...usageWindowSeat, ...promptSourceSeat, ...onErrorSeat, ...modsSeat, executionEnv: rawEnv, rootPath: repoDir });
192
193
  const objective = [
193
194
  `The integrated project at ${repoDir} fails its build/test. Make the MINIMAL change to the working tree so this command exits 0 (cd into the repo and run it yourself to confirm):`,
194
195
  ` ${testCmd}`,
@@ -255,13 +256,13 @@ export function createLeaderRunner(cfg) {
255
256
  if (Array.isArray(body.subtasks) && body.subtasks.length > 0) {
256
257
  return validateSubtasks(body.subtasks);
257
258
  }
258
- const planRunner = new Runner({ brain: cfg.brain, models: cfg.models, roles: cfg.roles, pricing: cfg.pricing, ...onNoticeSeat, ...governanceSeat, ...deploymentPostureSeat(), ...tracerSeat, ...usageWindowSeat, ...promptSourceSeat, ...onErrorSeat, ...modsSeat });
259
+ const planRunner = new Runner({ brain: cfg.brain, ...servedTableSeat, pricing: cfg.pricing, ...onNoticeSeat, ...governanceSeat, ...deploymentPostureSeat(), ...tracerSeat, ...usageWindowSeat, ...promptSourceSeat, ...onErrorSeat, ...modsSeat });
259
260
  const runRoute = async (prompt) => {
260
261
  const res = await planRunner.runTaskStream({
261
262
  objective: prompt,
262
263
  ...principalSpec(),
263
264
  sessionId: `leader-route-${Date.now()}`,
264
- ...(cfg.routerModel ? { model: cfg.routerModel } : {}),
265
+ ...(cfg.routerModel ? { model: cfg.routerModel } : { modelRole: "classifier" }),
265
266
  }).result();
266
267
  return res.result ?? "";
267
268
  };
@@ -349,7 +350,7 @@ export function createLeaderRunner(cfg) {
349
350
  workerId: sub.workerId, sessionId, branch: sub.branch,
350
351
  baseSha,
351
352
  runner: keepCtxWarm(new Runner({
352
- brain: cfg.brain, models: cfg.models, roles: cfg.roles, pricing: cfg.pricing, ...onNoticeSeat, ...governanceSeat, ...deploymentPostureSeat(), ...tracerSeat, ...usageWindowSeat, ...promptSourceSeat, ...onErrorSeat, ...modsSeat,
353
+ brain: cfg.brain, ...servedTableSeat, pricing: cfg.pricing, ...onNoticeSeat, ...governanceSeat, ...deploymentPostureSeat(), ...tracerSeat, ...usageWindowSeat, ...promptSourceSeat, ...onErrorSeat, ...modsSeat,
353
354
  ...(cfg.toolResultStore ? { toolResultStore: cfg.toolResultStore } : {}),
354
355
  ...(cfg.sessionStore ? { sessionStore: cfg.sessionStore } : {}),
355
356
  executionEnvFactory: async (ctx) => {
@@ -374,7 +375,7 @@ export function createLeaderRunner(cfg) {
374
375
  const baseSha = await sh(env)(`cd ${repo} && git rev-parse HEAD`);
375
376
  return {
376
377
  workerId: sub.workerId, sessionId, branch: sub.branch, baseSha,
377
- runner: keepCtxWarm(new Runner({ brain: cfg.brain, models: cfg.models, roles: cfg.roles, pricing: cfg.pricing, ...onNoticeSeat, ...governanceSeat, ...deploymentPostureSeat(), ...tracerSeat, ...usageWindowSeat, ...promptSourceSeat, ...onErrorSeat, ...modsSeat, ...(cfg.toolResultStore ? { toolResultStore: cfg.toolResultStore } : {}), ...(cfg.sessionStore ? { sessionStore: cfg.sessionStore } : {}), executionEnv: env })),
378
+ runner: keepCtxWarm(new Runner({ brain: cfg.brain, ...servedTableSeat, pricing: cfg.pricing, ...onNoticeSeat, ...governanceSeat, ...deploymentPostureSeat(), ...tracerSeat, ...usageWindowSeat, ...promptSourceSeat, ...onErrorSeat, ...modsSeat, ...(cfg.toolResultStore ? { toolResultStore: cfg.toolResultStore } : {}), ...(cfg.sessionStore ? { sessionStore: cfg.sessionStore } : {}), executionEnv: env })),
378
379
  diffEnv: env,
379
380
  destroy: () => env.destroy().then(() => { }),
380
381
  spec: withLeaderLeg({ ...workerLimits, ...sub.spec, ...durableSpec, ...resourceSpec, ...principalSpec() }, resumeBody),
@@ -0,0 +1,37 @@
1
+ /**
2
+ * 一条腿的**部署事实**(执行车道 · run 技能名册 · 受理见证)—— server 自有的载体,**不搭引擎 spec 的车**。
3
+ *
4
+ * 规则:`TaskSpec` 是引擎的类型面,上面只放引擎读的成员。本仓装配器(`boot/resolve-spec.ts` 的 `createResolveSpec`)同时还判出三件
5
+ * 只有 server 自己读的事实 —— 它们以装配器**自己的输出对象**为键登记在这一张表里(单一铸点 {@link mintLegFacts}),由两只漏斗
6
+ * (受理 `http/admission.ts` 的 `prepareSpec` · 续跑 `http/resume-legs.ts` 的 `resolveResumeSpec`)在拿到装配输出的**同一只对象**时
7
+ * 读一次(唯一读口 {@link legFactsOf},读在 `stampSpecRoot` 复制之前),此后作普通值随 `PreparedTaskSubmission.legFacts` /
8
+ * `DriveResumeArgs.legFacts` 走到各读者。生产选路器(`capabilities/hands-lane.ts` 的 `createHandsRunnerSelector`)经公共缝
9
+ * `runnerFor(spec)` 被同两只漏斗以同一只装配输出调用,读同一只读口。
10
+ *
11
+ * 为什么是「以输出对象为键的表 + 漏斗处一读」而不是 spec 上的字段:引擎的 TaskSpec 一读门按 `Reflect.ownKeys` 判自有成员,
12
+ * 任何不是它声明的键(含 symbol 键)都拒(fresh `config.spec_unknown_key` / 续跑 `checkpoint.config_refused`)。表的键身份只需在
13
+ * 「装配器返回 → 漏斗读」这一步成立,两步相邻、按构造成立;复制出来的对象(`{...spec}` / rest 解构)读不到 —— 读晚了是响亮拒,不是静默放宽。
14
+ *
15
+ * 嵌入方自带的 `resolveSpec` 不铸事实 ⇒ 读口得 `undefined`:选路响亮拒(`HandsLaneUnstampedError`),名册与见证缺席(腿的
16
+ * `wiring_manifest` 不带技能段 / 会话行记录座不写住客)。
17
+ */
18
+ import type { ScenarioHands } from "./capabilities/hands-lane.js";
19
+ import type { RunSkillEntry } from "./capabilities/skills.js";
20
+ import type { DelegationRootWitness } from "./delegated-session-owner.js";
21
+ /** 一条腿的部署事实(冻结记录)。 */
22
+ export interface LegFacts {
23
+ /** 执行车道:`none` ⇒ 无手孪生 Runner。读者 = 生产选路器。 */
24
+ readonly hands: ScenarioHands;
25
+ /** 这条 run 交给引擎的技能名册(`{ name, description, source }[]`)。读者 = 每条投 `wiring_manifest` 的腿。 */
26
+ readonly skills: readonly RunSkillEntry[];
27
+ /** 受理时读根会话行的那一读(会话 id + 住客)。读者 = 腿的会话行记录座(`session-workspace.ts`)。 */
28
+ readonly sessionWitness: DelegationRootWitness;
29
+ }
30
+ /**
31
+ * 铸事实(**单一属主**:只允许 `createResolveSpec` 的出口调用)。同一只对象被第二次铸 ⇒ 当场抛 —— 两个写者是漂移的成因,
32
+ * 响亮好过后到者悄悄赢。值冻结(名册条目与见证各自冻结)。
33
+ */
34
+ export declare function mintLegFacts<T extends object>(resolved: T, facts: LegFacts): T;
35
+ /** 唯一读口:交装配器输出的**那一只**对象。复制品 / 嵌入方装配器的输出 ⇒ `undefined`。 */
36
+ export declare function legFactsOf(resolved: object): LegFacts | undefined;
37
+ //# sourceMappingURL=leg-facts.d.ts.map