@sema-agent/server 7.151.0 → 7.152.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 (286) hide show
  1. package/MIGRATION.md +266 -0
  2. package/README.md +15 -3
  3. package/README.zh-CN.md +10 -2
  4. package/USAGE.md +93 -64
  5. package/deploy/sema-up/README.md +5 -4
  6. package/deploy/sema-up/cluster-up.sh +6 -6
  7. package/deploy/sema-up/kube-up.sh +5 -5
  8. package/deploy/sema-up/lib/flagshape.sh +36 -8
  9. package/deploy/sema-up/machines.example.yaml +3 -1
  10. package/deploy/sema-up/sema-up.sh +22 -16
  11. package/dist/approval-ask-audit-store.d.ts +1 -1
  12. package/dist/approval-ask-machine.d.ts +4 -10
  13. package/dist/approval-ask-retention.d.ts +1 -1
  14. package/dist/approval-card.d.ts +10 -12
  15. package/dist/approval-gate-currency.d.ts +8 -8
  16. package/dist/approval-gate-currency.js +3 -4
  17. package/dist/approval-hmac.d.ts +17 -1
  18. package/dist/approval-hmac.js +7 -1
  19. package/dist/approval-queue-kind.d.ts +1 -1
  20. package/dist/approval.d.ts +2 -2
  21. package/dist/approval.js +2 -2
  22. package/dist/bind-host.d.ts +1 -3
  23. package/dist/bind-host.js +2 -3
  24. package/dist/boot/coordinators.d.ts +1 -1
  25. package/dist/boot/coordinators.js +9 -10
  26. package/dist/boot/device-lane.js +2 -0
  27. package/dist/boot/execution-env.d.ts +1 -0
  28. package/dist/boot/execution-env.js +31 -5
  29. package/dist/boot/leader.d.ts +31 -30
  30. package/dist/boot/leader.js +38 -28
  31. package/dist/boot/leg-path-adjudication.d.ts +40 -0
  32. package/dist/boot/leg-path-adjudication.js +18 -0
  33. package/dist/boot/parked-revive-gate.js +3 -15
  34. package/dist/boot/reapers.d.ts +1 -1
  35. package/dist/boot/reapers.js +1 -1
  36. package/dist/boot/resolve-spec.js +12 -26
  37. package/dist/boot/runner-deps.d.ts +39 -35
  38. package/dist/boot/runner-deps.js +92 -89
  39. package/dist/boot/shutdown.d.ts +6 -0
  40. package/dist/boot/shutdown.js +10 -4
  41. package/dist/boot/stage-02-web-admin-pull.js +4 -5
  42. package/dist/boot/stage-05-execution-env.js +2 -1
  43. package/dist/boot/stage-06-runners.d.ts +2 -0
  44. package/dist/boot/stage-06-runners.js +10 -4
  45. package/dist/boot/stage-07-capability-layer.d.ts +1 -0
  46. package/dist/boot/stage-07-capability-layer.js +1 -1
  47. package/dist/boot/stage-08-reapers.d.ts +1 -0
  48. package/dist/boot/stage-09-leader.d.ts +1 -0
  49. package/dist/boot/stage-09-leader.js +2 -2
  50. package/dist/boot/stage-10-http-server.d.ts +8 -0
  51. package/dist/boot/stage-10-http-server.js +11 -15
  52. package/dist/boot/stores.js +7 -4
  53. package/dist/boot/web-admin.js +2 -7
  54. package/dist/capabilities/approvals-push.d.ts +3 -3
  55. package/dist/capabilities/scenarios.d.ts +28 -13
  56. package/dist/capabilities/scenarios.js +2 -2
  57. package/dist/capability-facts.d.ts +22 -20
  58. package/dist/capability-facts.js +18 -34
  59. package/dist/card-rule-offers.d.ts +32 -0
  60. package/dist/card-rule-offers.js +130 -0
  61. package/dist/config-catalog.js +12 -11
  62. package/dist/config-dir-trust.js +4 -2
  63. package/dist/config-invariants.d.ts +18 -7
  64. package/dist/config-invariants.js +51 -8
  65. package/dist/config-lkg.d.ts +5 -19
  66. package/dist/config-lkg.js +8 -62
  67. package/dist/config-provider.d.ts +1 -1
  68. package/dist/config-root-migration.d.ts +2 -2
  69. package/dist/config-types.d.ts +28 -38
  70. package/dist/config.d.ts +7 -5
  71. package/dist/config.js +55 -16
  72. package/dist/control-socket.d.ts +51 -0
  73. package/dist/control-socket.js +115 -0
  74. package/dist/deployment-governance.d.ts +2 -1
  75. package/dist/device-ws-hub.d.ts +7 -0
  76. package/dist/device-ws-hub.js +7 -1
  77. package/dist/elicitation.js +2 -2
  78. package/dist/entry-problems.d.ts +40 -3
  79. package/dist/entry-problems.js +3 -1
  80. package/dist/execution-env-refusal.d.ts +8 -2
  81. package/dist/execution-env-refusal.js +3 -0
  82. package/dist/fleet/engine-signal.d.ts +12 -29
  83. package/dist/fleet/engine-signal.js +1 -7
  84. package/dist/fleet-client.js +2 -5
  85. package/dist/gate-settlement.d.ts +1 -8
  86. package/dist/gate-settlement.js +0 -4
  87. package/dist/history-anchor.js +1 -1
  88. package/dist/hitl-delivery.d.ts +2 -3
  89. package/dist/hitl-delivery.js +0 -2
  90. package/dist/hooks/hook-llm.js +4 -2
  91. package/dist/hooks/hook-runner.d.ts +3 -2
  92. package/dist/hooks/hook-runner.js +16 -1
  93. package/dist/host-decision.d.ts +11 -11
  94. package/dist/http/active-run-conflict.d.ts +35 -2
  95. package/dist/http/active-run-conflict.js +48 -19
  96. package/dist/http/approval-sweeps.d.ts +1 -1
  97. package/dist/http/approval-sweeps.js +5 -2
  98. package/dist/http/checkpoint-ctx.d.ts +2 -0
  99. package/dist/http/checkpoint-ctx.js +1 -0
  100. package/dist/http/dispatch.d.ts +6 -2
  101. package/dist/http/dispatch.js +25 -5
  102. package/dist/http/durable-run-leg.js +0 -1
  103. package/dist/http/health-reader.d.ts +16 -9
  104. package/dist/http/health-reader.js +2 -1
  105. package/dist/http/health-self-report.js +1 -1
  106. package/dist/http/owner-access.d.ts +2 -3
  107. package/dist/http/owner-access.js +3 -4
  108. package/dist/http/principal-gate.d.ts +49 -21
  109. package/dist/http/principal-gate.js +61 -11
  110. package/dist/http/request-channel.d.ts +23 -0
  111. package/dist/http/request-channel.js +9 -0
  112. package/dist/http/request-guards.js +17 -2
  113. package/dist/http/resume-ctx-read.js +20 -3
  114. package/dist/http/resume-legs.d.ts +2 -2
  115. package/dist/http/resume-legs.js +111 -41
  116. package/dist/http/route-ctx.d.ts +73 -7
  117. package/dist/http/route-ctx.js +17 -0
  118. package/dist/http/route-table.d.ts +4 -0
  119. package/dist/http/route-table.js +4 -0
  120. package/dist/http/routes/admin-config-refresh.js +3 -3
  121. package/dist/http/routes/admin-drain.d.ts +3 -0
  122. package/dist/http/routes/admin-drain.js +7 -7
  123. package/dist/http/routes/admin-memory-optout.js +3 -3
  124. package/dist/http/routes/adoption.js +3 -5
  125. package/dist/http/routes/approvals-assistant.d.ts +2 -1
  126. package/dist/http/routes/approvals-assistant.js +95 -48
  127. package/dist/http/routes/capabilities.d.ts +4 -0
  128. package/dist/http/routes/capabilities.js +30 -5
  129. package/dist/http/routes/config-catalog.js +2 -2
  130. package/dist/http/routes/devices.js +1 -1
  131. package/dist/http/routes/diagnostics.d.ts +3 -3
  132. package/dist/http/routes/diagnostics.js +19 -7
  133. package/dist/http/routes/images.js +10 -10
  134. package/dist/http/routes/memory-bundle.js +3 -3
  135. package/dist/http/routes/memory-compliance.js +3 -3
  136. package/dist/http/routes/memory-consolidation.js +2 -2
  137. package/dist/http/routes/memory-origin.js +3 -3
  138. package/dist/http/routes/memory-policy.js +2 -2
  139. package/dist/http/routes/observability.js +3 -3
  140. package/dist/http/routes/retention-ops.js +3 -3
  141. package/dist/http/routes/rules.js +5 -5
  142. package/dist/http/routes/run-permission-mode.d.ts +2 -1
  143. package/dist/http/routes/run-permission-mode.js +2 -2
  144. package/dist/http/routes/runs.d.ts +4 -9
  145. package/dist/http/routes/runs.js +73 -33
  146. package/dist/http/routes/session-sync.d.ts +18 -6
  147. package/dist/http/routes/session-sync.js +38 -36
  148. package/dist/http/routes/sessions.js +20 -9
  149. package/dist/http/routes/tasks.js +28 -37
  150. package/dist/http/routes/workflows.js +1 -1
  151. package/dist/http/server.d.ts +9 -3
  152. package/dist/http/server.js +15 -3
  153. package/dist/http/submit-ctx.d.ts +1 -1
  154. package/dist/http/submit-ctx.js +2 -0
  155. package/dist/human-facing-args.d.ts +33 -0
  156. package/dist/human-facing-args.js +33 -0
  157. package/dist/index.d.ts +1 -1
  158. package/dist/k8s-api-credentials.d.ts +29 -0
  159. package/dist/k8s-api-credentials.js +25 -0
  160. package/dist/lane-home-probe.d.ts +1 -1
  161. package/dist/lane-home-probe.js +2 -1
  162. package/dist/leader/diffup.d.ts +19 -0
  163. package/dist/leader/diffup.js +7 -0
  164. package/dist/leader/leader.d.ts +114 -10
  165. package/dist/leader/leader.js +69 -5
  166. package/dist/leader/repair-wire.js +2 -2
  167. package/dist/leader/run-entry.d.ts +2 -1
  168. package/dist/leader/run-entry.js +1 -1
  169. package/dist/leader/wire.d.ts +42 -132
  170. package/dist/leader/wire.js +81 -67
  171. package/dist/memory-scope.d.ts +20 -9
  172. package/dist/memory-scope.js +15 -3
  173. package/dist/model-entry-headers.d.ts +9 -10
  174. package/dist/model-entry-headers.js +0 -4
  175. package/dist/model-entry-refusal.d.ts +7 -4
  176. package/dist/model-entry-refusal.js +11 -5
  177. package/dist/model-plane-face.d.ts +1 -1
  178. package/dist/model-plane-face.js +3 -1
  179. package/dist/model-route-endpoint.d.ts +13 -7
  180. package/dist/model-route-endpoint.js +14 -11
  181. package/dist/model-select.d.ts +22 -0
  182. package/dist/model-select.js +9 -0
  183. package/dist/model-unreachable-notice.d.ts +11 -0
  184. package/dist/model-unreachable-notice.js +4 -4
  185. package/dist/object-store-buckets.d.ts +640 -6
  186. package/dist/object-store-buckets.js +166 -0
  187. package/dist/observability/fail-open.d.ts +20 -16
  188. package/dist/observability/fail-open.js +20 -16
  189. package/dist/observability/logger.js +3 -1
  190. package/dist/operator-roster.d.ts +68 -0
  191. package/dist/operator-roster.js +32 -0
  192. package/dist/orchestration/workflow-park-decision.d.ts +1 -1
  193. package/dist/outbound-dispatcher.d.ts +71 -8
  194. package/dist/outbound-dispatcher.js +48 -7
  195. package/dist/owner-faces.d.ts +1 -1
  196. package/dist/parked-decide.d.ts +2 -2
  197. package/dist/permission-mode-admission.d.ts +59 -26
  198. package/dist/permission-mode-admission.js +37 -10
  199. package/dist/plugins/approval-ask-store-file.d.ts +4 -0
  200. package/dist/plugins/approval-ask-store-file.js +3 -0
  201. package/dist/plugins/approval-ask-store-memory.d.ts +4 -0
  202. package/dist/plugins/approval-ask-store-memory.js +7 -1
  203. package/dist/plugins/approval-ask-store-sql.d.ts +26 -2
  204. package/dist/plugins/approval-ask-store-sql.js +12 -1
  205. package/dist/plugins/blob-backend.d.ts +83 -7
  206. package/dist/plugins/blob-backend.js +57 -6
  207. package/dist/plugins/checkpoint-index-columns.d.ts +20 -16
  208. package/dist/plugins/checkpoint-index-columns.js +3 -6
  209. package/dist/plugins/checkpoint-store-face.d.ts +119 -61
  210. package/dist/plugins/checkpoint-store-face.js +134 -55
  211. package/dist/plugins/landed-attendants.d.ts +2 -2
  212. package/dist/plugins/local-checkpoint-store.d.ts +13 -3
  213. package/dist/plugins/local-checkpoint-store.js +38 -49
  214. package/dist/plugins/one-time-migrations.d.ts +51 -21
  215. package/dist/plugins/one-time-migrations.js +67 -45
  216. package/dist/plugins/pg-pool.js +11 -9
  217. package/dist/plugins/remote-env-host.d.ts +29 -10
  218. package/dist/plugins/remote-env-host.js +99 -19
  219. package/dist/plugins/remote-env-k8s.d.ts +68 -2
  220. package/dist/plugins/remote-env-k8s.js +107 -24
  221. package/dist/plugins/replica-registration.d.ts +1 -1
  222. package/dist/plugins/replica-registration.js +1 -1
  223. package/dist/plugins/s3-presign.d.ts +23 -0
  224. package/dist/plugins/s3-presign.js +37 -3
  225. package/dist/plugins/scheduler-support.d.ts +2 -2
  226. package/dist/plugins/scheduler-support.js +0 -3
  227. package/dist/plugins/schema-indexes.js +2 -0
  228. package/dist/plugins/send-file-ledger.d.ts +2 -2
  229. package/dist/plugins/send-file-ledger.js +2 -2
  230. package/dist/plugins/send-user-file.d.ts +3 -4
  231. package/dist/plugins/send-user-file.js +56 -52
  232. package/dist/plugins/session-blob-claim-token.d.ts +15 -0
  233. package/dist/plugins/session-blob-claim-token.js +20 -0
  234. package/dist/plugins/session-blob-namespace.d.ts +46 -0
  235. package/dist/plugins/session-blob-namespace.js +116 -0
  236. package/dist/plugins/snapshot-bucket-presence.d.ts +25 -2
  237. package/dist/plugins/snapshot-bucket-presence.js +8 -2
  238. package/dist/plugins/sql-json-column.d.ts +1 -1
  239. package/dist/plugins/store-backend.d.ts +44 -2
  240. package/dist/plugins/store-backend.js +75 -53
  241. package/dist/plugins/task-attachment-store.d.ts +2 -1
  242. package/dist/plugins/task-attachment-store.js +5 -1
  243. package/dist/plugins/tidb-pool.js +19 -24
  244. package/dist/plugins/workspace-custody.d.ts +4 -3
  245. package/dist/question.d.ts +2 -1
  246. package/dist/question.js +5 -13
  247. package/dist/request-form.d.ts +6 -1
  248. package/dist/request-form.js +4 -1
  249. package/dist/rule-issue-reading.d.ts +1 -1
  250. package/dist/rules-consent.d.ts +1 -1
  251. package/dist/run-local.js +8 -9
  252. package/dist/runs.d.ts +17 -8
  253. package/dist/runs.js +15 -2
  254. package/dist/runtime-governance.d.ts +2 -2
  255. package/dist/sema-config-dir.d.ts +2 -1
  256. package/dist/session-sync.d.ts +27 -11
  257. package/dist/session-sync.js +15 -7
  258. package/dist/stores-sql/blob-index-sql.d.ts +30 -9
  259. package/dist/stores-sql/blob-index-sql.js +40 -21
  260. package/dist/stores-sql/checkpoint-store-sql.d.ts +54 -27
  261. package/dist/stores-sql/checkpoint-store-sql.js +70 -146
  262. package/dist/stores-sql/file-history-store-sql.d.ts +64 -16
  263. package/dist/stores-sql/file-history-store-sql.js +100 -28
  264. package/dist/stores-sql/retention-store-sql.js +3 -9
  265. package/dist/task-settings.d.ts +6 -5
  266. package/dist/task-settings.js +3 -3
  267. package/dist/tool-approval.d.ts +342 -518
  268. package/dist/tool-approval.js +498 -1207
  269. package/dist/trace/core-keyset-guard.d.ts +1 -1
  270. package/dist/trace/ledger-events.d.ts +3 -3
  271. package/dist/trace/project.d.ts +2 -3
  272. package/dist/trace/redact.js +3 -2
  273. package/dist/trace/self-minted-wire.d.ts +287 -157
  274. package/dist/trace/self-minted-wire.js +93 -48
  275. package/dist/web-admin-client/apply-effective.js +2 -2
  276. package/dist/web-admin-client/read-warnings.d.ts +2 -2
  277. package/dist/web-admin-client/read-warnings.js +1 -1
  278. package/dist/web-admin-client/types.d.ts +1 -1
  279. package/dist/workspace-space.d.ts +10 -4
  280. package/dist/workspace-space.js +4 -1
  281. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +1 -1
  282. package/package.json +6 -2
  283. package/scripts/embed-minimal.mjs +3 -3
  284. package/wire-changes/server@7.152.0.json +900 -0
  285. package/dist/config-d-migration.d.ts +0 -37
  286. package/dist/config-d-migration.js +0 -60
@@ -65,10 +65,6 @@ export function createEngineNoticeForwarder(logger, router = defaultEngineNotice
65
65
  export function installDefaultEngineNoticeSeat(logger, metrics) {
66
66
  setDefaultEngineNoticeSeat(createEngineNoticeForwarder(logger, defaultEngineNoticeRouter, metrics));
67
67
  }
68
- export function createEngineNoticeSeat(logger, router = defaultEngineNoticeRouter) {
69
- const warn = logger?.warn?.bind(logger);
70
- return warn ? { onNotice: createEngineNoticeForwarder({ warn }, router) } : {};
71
- }
72
68
  export const CROSS_BOUNDARY_POSTURE_REQUIRES_PRINCIPAL = { multi_tenant: true, single_user: false };
73
69
  export function crossBoundaryPostureOf(requirePrincipal) {
74
70
  for (const w of Object.keys(CROSS_BOUNDARY_POSTURE_REQUIRES_PRINCIPAL)) {
@@ -111,9 +107,8 @@ export function announceReadDenyRows(config, logger) {
111
107
  announcedReadDenyRows.set(config, key);
112
108
  auditReadDenyAnchoring({ rows: config.readDenyPatterns, logger });
113
109
  }
114
- export function createSharedRunnerDeps(ctx) {
115
- announceReadDenyRows(ctx.config, ctx.logger);
116
- const shared = {
110
+ export function createDeploymentPlaneDeps(ctx, lane) {
111
+ const plane = {
117
112
  brain: ctx.brain,
118
113
  onNotice: createEngineNoticeForwarder(ctx.logger, defaultEngineNoticeRouter, ctx.metrics),
119
114
  tiers: ctx.config.tiers,
@@ -123,13 +118,29 @@ export function createSharedRunnerDeps(ctx) {
123
118
  tracer: ctx.tracer,
124
119
  promptSource: ctx.promptSource,
125
120
  ...buildDeploymentPostureSeats(ctx.config),
121
+ mods: ctx.deploymentMods,
122
+ hands: buildHandsBand(ctx.config, lane.commitCoAuthor),
123
+ usageWindows: ctx.config.usageWindows ? ctx.config.usageWindows : undefined,
124
+ usageWindowStore: ctx.usageWindowStore ? ctx.usageWindowStore : undefined,
125
+ memoryEngineDir: ctx.engineDataRoot,
126
+ compliancePostureResolver: ctx.governanceSeams.compliancePostureResolver,
127
+ lockedConfig: ctx.governanceSeams.lockedConfig,
128
+ retentionPolicy: ctx.governanceSeams.retentionPolicy,
129
+ mcpRevocations: ctx.mcpRevocations ? ctx.mcpRevocations : undefined,
130
+ runtimeCapsResolver: ctx.runtimeCapsResolver ? ctx.runtimeCapsResolver : undefined,
131
+ onError: ctx.onError,
132
+ };
133
+ return plane;
134
+ }
135
+ export function createSharedRunnerDeps(ctx) {
136
+ announceReadDenyRows(ctx.config, ctx.logger);
137
+ const shared = {
138
+ ...createDeploymentPlaneDeps(ctx, { commitCoAuthor: ctx.commitCoAuthor }),
126
139
  executionEnvFactory: ctx.executionEnvFactory ? ctx.executionEnvFactory : undefined,
127
140
  lspManager: ctx.lspManager ? ctx.lspManager : undefined,
128
141
  backgroundAgentStore: ctx.backgroundAgentStore ? ctx.backgroundAgentStore : undefined,
129
142
  mailboxStore: ctx.mailboxStore ? ctx.mailboxStore : undefined,
130
143
  rosterStore: ctx.rosterStore ? ctx.rosterStore : undefined,
131
- mods: ctx.deploymentMods,
132
- hands: buildHandsBand(ctx.config, ctx.commitCoAuthor),
133
144
  toolResultStore: ctx.toolResultStore,
134
145
  checkpointStore: ctx.checkpointStore ? ctx.checkpointStore : undefined,
135
146
  fileHistoryStore: ctx.fileHistoryStore ? ctx.fileHistoryStore : undefined,
@@ -137,16 +148,8 @@ export function createSharedRunnerDeps(ctx) {
137
148
  sessionPolicyStore: ctx.sessionPolicyStore ? ctx.sessionPolicyStore : undefined,
138
149
  memoryScopeAdmission: ctx.orgMemoryAdmission.memoryScopeAdmission ? ctx.orgMemoryAdmission.memoryScopeAdmission : undefined,
139
150
  deploymentMemoryScopes: ctx.orgMemoryAdmission.deploymentMemoryScopes && ctx.orgMemoryAdmission.deploymentMemoryScopes.length > 0 ? ctx.orgMemoryAdmission.deploymentMemoryScopes : undefined,
140
- usageWindows: ctx.config.usageWindows ? ctx.config.usageWindows : undefined,
141
- usageWindowStore: ctx.usageWindowStore ? ctx.usageWindowStore : undefined,
142
151
  sharedMemoryStores: ctx.sharedMemoryStores ? ctx.sharedMemoryStores : undefined,
143
- memoryEngineDir: ctx.engineDataRoot,
144
- compliancePostureResolver: ctx.governanceSeams.compliancePostureResolver,
145
- lockedConfig: ctx.governanceSeams.lockedConfig,
146
- retentionPolicy: ctx.governanceSeams.retentionPolicy,
147
- mcpRevocations: ctx.mcpRevocations ? ctx.mcpRevocations : undefined,
148
152
  peerSeat: ctx.peerDesk.seat,
149
- runtimeCapsResolver: ctx.runtimeCapsResolver ? ctx.runtimeCapsResolver : undefined,
150
153
  };
151
154
  return shared;
152
155
  }
@@ -157,7 +160,78 @@ export function createRunnerDeps(ctx) {
157
160
  const { config, logger, metrics, localRoot, outcomeSink, elicitation, question, toolApproval, sessionStore, memoryEngine, sessionCaptureRecords, memorySyncRunner, permissionRuleStore, fleetBus, workflowRunStore, workflowJournalStore, workflowAgentRegistry, workflowNotifyGate, deliverWorkflowCompletion, } = ctx;
158
161
  const peerSessionLister = sessionStore.listSessionRows?.bind(sessionStore);
159
162
  const memoryEngineIncident = createMemoryEngineIncidentSink({ logger, metrics });
160
- const sharedRunnerDeps = createSharedRunnerDeps(ctx);
163
+ const onError = (err, ctx) => {
164
+ const codeField = codeFieldOf(err);
165
+ if (ctx.phase === "degraded") {
166
+ logger.warn("task_degraded", { sessionId: ctx.sessionId, ...codeField, info: seatText("operator-log-text", String(err)) });
167
+ return;
168
+ }
169
+ if (ctx.phase === "prompt-constitution") {
170
+ logger.warn("prompt_composition_warning", { sessionId: ctx.sessionId, ...codeField, info: seatText("operator-log-text", String(err)) });
171
+ return;
172
+ }
173
+ if (ctx.phase === "rewind") {
174
+ const code = rewindFailureCode(err);
175
+ logger.warn("rewind_snapshot_failed", { sessionId: ctx.sessionId, code, info: seatText("operator-log-text", String(err)) });
176
+ metrics.inc("rewind_snapshot_failed_total", { code });
177
+ return;
178
+ }
179
+ if (ctx.phase === "memory") {
180
+ memoryEngineIncident(err, ctx.sessionId !== undefined ? { sessionId: ctx.sessionId } : undefined);
181
+ return;
182
+ }
183
+ if (ctx.phase === "mcp") {
184
+ logger.warn("mcp_server_unavailable", { sessionId: ctx.sessionId, kind: errorKindOf(err), ...codeField, info: seatText("operator-log-text", buildShownUrlsInText(String(err))) });
185
+ metrics.inc("mcp_server_unavailable_total");
186
+ return;
187
+ }
188
+ if (ctx.phase === "a2a") {
189
+ logger.warn("a2a_peer_unavailable", { sessionId: ctx.sessionId, kind: errorKindOf(err), ...codeField, info: seatText("operator-log-text", buildShownUrlsInText(String(err))) });
190
+ metrics.inc("a2a_peer_unavailable_total");
191
+ return;
192
+ }
193
+ if (ctx.phase === "prompt-cache") {
194
+ const classification = ctx.classification;
195
+ const causeLevel = classification === undefined ? undefined : PROMPT_CACHE_BREAK_LEVELS.get(classification);
196
+ const level = classification === undefined ? "warn" : (causeLevel ?? "error");
197
+ const fields = {
198
+ sessionId: ctx.sessionId,
199
+ confirmed: classification !== undefined,
200
+ ...(classification !== undefined ? { classification, classificationKnown: causeLevel !== undefined } : {}),
201
+ ...codeField,
202
+ err: seatText("operator-log-text", String(err)),
203
+ };
204
+ metrics.inc("prompt_cache_low_hit_total", {
205
+ ...(classification !== undefined ? { classification: causeLevel !== undefined ? classification : "unknown" } : {}),
206
+ level,
207
+ });
208
+ if (level === "warn")
209
+ logger.warn("prompt_cache_break", fields);
210
+ else
211
+ logger.error("prompt_cache_break", fields);
212
+ return;
213
+ }
214
+ if (ctx.phase === "config") {
215
+ const classification = ctx.classification;
216
+ const classificationKnown = classification === undefined ? undefined : CONFIG_ADVISORY_CLASSIFICATIONS.has(classification);
217
+ const fields = {
218
+ sessionId: ctx.sessionId,
219
+ ...codeField,
220
+ ...(classification !== undefined ? { classification, classificationKnown } : {}),
221
+ info: seatText("operator-log-text", String(err)),
222
+ };
223
+ logger.warn("runner_config_advisory", fields);
224
+ metrics.inc("runner_config_advisory_total", {
225
+ ...codeField,
226
+ ...(classification !== undefined ? { classification: classificationKnown ? classification : "unknown" } : {}),
227
+ level: "warn",
228
+ });
229
+ return;
230
+ }
231
+ metrics.inc("runner_error_total", { phase: ctx.phase });
232
+ logger.error("runner_error", { phase: ctx.phase, sessionId: ctx.sessionId, ...codeField, err: seatText("operator-log-text", String(err)) });
233
+ };
234
+ const sharedRunnerDeps = createSharedRunnerDeps({ ...ctx, onError });
161
235
  const workflowModelAllowlist = workflowModelAllowlistFor(config);
162
236
  const selfOrchestrationDeps = config.selfOrchestrationEnabled
163
237
  ? {
@@ -248,77 +322,6 @@ export function createRunnerDeps(ctx) {
248
322
  ? makeProbeInstructionSources()
249
323
  : undefined,
250
324
  ...selfOrchestrationDeps,
251
- onError: (err, ctx) => {
252
- const codeField = codeFieldOf(err);
253
- if (ctx.phase === "degraded") {
254
- logger.warn("task_degraded", { sessionId: ctx.sessionId, ...codeField, info: seatText("operator-log-text", String(err)) });
255
- return;
256
- }
257
- if (ctx.phase === "prompt-constitution") {
258
- logger.warn("prompt_composition_warning", { sessionId: ctx.sessionId, ...codeField, info: seatText("operator-log-text", String(err)) });
259
- return;
260
- }
261
- if (ctx.phase === "rewind") {
262
- const code = rewindFailureCode(err);
263
- logger.warn("rewind_snapshot_failed", { sessionId: ctx.sessionId, code, info: seatText("operator-log-text", String(err)) });
264
- metrics.inc("rewind_snapshot_failed_total", { code });
265
- return;
266
- }
267
- if (ctx.phase === "memory") {
268
- memoryEngineIncident(err, ctx.sessionId !== undefined ? { sessionId: ctx.sessionId } : undefined);
269
- return;
270
- }
271
- if (ctx.phase === "mcp") {
272
- logger.warn("mcp_server_unavailable", { sessionId: ctx.sessionId, kind: errorKindOf(err), ...codeField, info: seatText("operator-log-text", buildShownUrlsInText(String(err))) });
273
- metrics.inc("mcp_server_unavailable_total");
274
- return;
275
- }
276
- if (ctx.phase === "a2a") {
277
- logger.warn("a2a_peer_unavailable", { sessionId: ctx.sessionId, kind: errorKindOf(err), ...codeField, info: seatText("operator-log-text", buildShownUrlsInText(String(err))) });
278
- metrics.inc("a2a_peer_unavailable_total");
279
- return;
280
- }
281
- if (ctx.phase === "prompt-cache") {
282
- const classification = ctx.classification;
283
- const causeLevel = classification === undefined ? undefined : PROMPT_CACHE_BREAK_LEVELS.get(classification);
284
- const level = classification === undefined ? "warn" : (causeLevel ?? "error");
285
- const fields = {
286
- sessionId: ctx.sessionId,
287
- confirmed: classification !== undefined,
288
- ...(classification !== undefined ? { classification, classificationKnown: causeLevel !== undefined } : {}),
289
- ...codeField,
290
- err: seatText("operator-log-text", String(err)),
291
- };
292
- metrics.inc("prompt_cache_low_hit_total", {
293
- ...(classification !== undefined ? { classification: causeLevel !== undefined ? classification : "unknown" } : {}),
294
- level,
295
- });
296
- if (level === "warn")
297
- logger.warn("prompt_cache_break", fields);
298
- else
299
- logger.error("prompt_cache_break", fields);
300
- return;
301
- }
302
- if (ctx.phase === "config") {
303
- const classification = ctx.classification;
304
- const classificationKnown = classification === undefined ? undefined : CONFIG_ADVISORY_CLASSIFICATIONS.has(classification);
305
- const fields = {
306
- sessionId: ctx.sessionId,
307
- ...codeField,
308
- ...(classification !== undefined ? { classification, classificationKnown } : {}),
309
- info: seatText("operator-log-text", String(err)),
310
- };
311
- logger.warn("runner_config_advisory", fields);
312
- metrics.inc("runner_config_advisory_total", {
313
- ...codeField,
314
- ...(classification !== undefined ? { classification: classificationKnown ? classification : "unknown" } : {}),
315
- level: "warn",
316
- });
317
- return;
318
- }
319
- metrics.inc("runner_error_total", { phase: ctx.phase });
320
- logger.error("runner_error", { phase: ctx.phase, sessionId: ctx.sessionId, ...codeField, err: seatText("operator-log-text", String(err)) });
321
- },
322
325
  ...(ctx.consolidationSeat !== undefined
323
326
  ? {
324
327
  memoryConsolidation: {},
@@ -39,6 +39,12 @@ export interface ShutdownCtx {
39
39
  version: string;
40
40
  logger: Logger;
41
41
  server: ReturnType<typeof createHttpServer>;
42
+ /**
43
+ * 本机控制 socket 那只 `http.Server`(`server.controlSocketServer`)—— present-iff 它在听(起服第 10 段 `openControlSocket` 的结局)。
44
+ * 🔴 收尾序承重:两只 server **都**关完(close 回调落地)才 `backend.close()`(数据根锁在那条链里放)。运行时关 unix socket 监听口时按路径名 unlink;
45
+ * 锁若先放、控制口还在听,接班的引擎可在此刻替换路径,随后这边关口就删掉接班者的 socket(`control-socket.ts` 头注前提律)。
46
+ */
47
+ controlSocket?: import("node:http").Server | undefined;
42
48
  reaper: NodeJS.Timeout;
43
49
  /** [ref]:fleet 存活对账腿(60s 定时器 + 总线订阅)。与 `reaper` 同列文件头契约 3 —— 收尾期不该再有
44
50
  * 对账 tick 打向正在关闭的池,订阅也要摘(否则 bus 的扇出还在往一个已停的观察者写)。 */
@@ -19,7 +19,8 @@ export function backgroundGraceRemainingMs(a) {
19
19
  return Math.max(0, Math.min(a.softStoppedAt + a.graceMs, a.deadlineMs) - a.now);
20
20
  }
21
21
  export function installShutdownHandlers(ctx) {
22
- const { config, logger, server, reaper, fleetReconcile, retentionLane, releaseRetentionLease, otelExporter, breakerState, costQuota, rateLimiter, runner, subRunner, lspManager, workflowNotifyJournal, fleetClient, backend, drainState, storeLiveProbe, webAdmin, version, deviceHub, toolApproval, parkCommits, servingLease, peerInbound, } = ctx;
22
+ const { config, logger, server, controlSocket, reaper, fleetReconcile, retentionLane, releaseRetentionLease, otelExporter, breakerState, costQuota, rateLimiter, runner, subRunner, lspManager, workflowNotifyJournal, fleetClient, backend, drainState, storeLiveProbe, webAdmin, version, deviceHub, toolApproval, parkCommits, servingLease, peerInbound, } = ctx;
23
+ const httpListeners = controlSocket === undefined ? [server] : [server, controlSocket];
23
24
  const dataRoot = config.localDataRoot;
24
25
  if (dataRoot) {
25
26
  const prior = readCrashLast(dataRoot);
@@ -161,7 +162,8 @@ export function installShutdownHandlers(ctx) {
161
162
  rateLimiter.stop();
162
163
  await fleetClient?.flushFinalUsage();
163
164
  });
164
- server.close(() => {
165
+ const listenersClosed = Promise.all(httpListeners.map((s) => new Promise((resolve) => s.close(() => resolve())))).then(() => undefined);
166
+ void listenersClosed.then(() => {
165
167
  void Promise.all([retentionTeardown, ledgerStopped])
166
168
  .then(() => (backend ? backend.close() : Promise.resolve()))
167
169
  .then(() => routingStopped)
@@ -172,8 +174,12 @@ export function installShutdownHandlers(ctx) {
172
174
  const finalExit = setTimeout(() => { logger.warn("hard_shutdown_final_deadline", { afterMs: FINAL_EXIT_MS }); process.exit(0); }, FINAL_EXIT_MS);
173
175
  finalExit.unref?.();
174
176
  drainState.endSubscriptions?.();
175
- server.closeIdleConnections?.();
176
- const forceClose = setTimeout(() => server.closeAllConnections?.(), HARD_STOP_GRACE_MS);
177
+ for (const s of httpListeners)
178
+ s.closeIdleConnections?.();
179
+ const forceClose = setTimeout(() => {
180
+ for (const s of httpListeners)
181
+ s.closeAllConnections?.();
182
+ }, HARD_STOP_GRACE_MS);
177
183
  forceClose.unref?.();
178
184
  };
179
185
  let draining = false;
@@ -5,13 +5,12 @@ import { configSourceKind } from "../config-provider.js";
5
5
  import { announceConfigRootEnclosingWorkspace } from "../sema-config-dir.js";
6
6
  import { launchWorkspaceOf } from "../task-cwd.js";
7
7
  import { buildCandidateRejectionNotes } from "../web-admin-client/candidate-gate.js";
8
- import { logConfigDirMigration, migrateLocalConfigDirectory } from "../config-d-migration.js";
9
8
  import { logEnvModelsMigration, runEnvModelsMigration } from "../config-root-migration.js";
10
9
  import { assertLocalConfigDirTrusted } from "../config-dir-trust.js";
11
10
  import { defaultModelRefusal, refusedNameMintedRefusal } from "../model-entry-refusal.js";
12
11
  import { isRosterGateArmed } from "../config.js";
13
12
  import { judgeServedModelRoute } from "../model-route-endpoint.js";
14
- import { servedModelTableLeg } from "../model-select.js";
13
+ import { modelRefusalLegOf, servedModelTableLeg } from "../model-select.js";
15
14
  import { warnAssumedContextWindows } from "../context-window-notice.js";
16
15
  import { captureBootStoreEvidence } from "./store-evidence.js";
17
16
  import { admitStoreDurability } from "../store-admission.js";
@@ -22,7 +21,6 @@ export async function runStage02(ctx) {
22
21
  const configSource = configSourceKind(loaded);
23
22
  if (configSource === "local") {
24
23
  await assertLocalConfigDirTrusted({ root: localRoot, declaredOwnerUid: loaded.configLocalOwnerUid });
25
- logConfigDirMigration(logger, await migrateLocalConfigDirectory(localRoot));
26
24
  }
27
25
  const config = await composeExecutionLane(loaded, { configSource, localRoot, logger, entry: HTTP_SERVICE_LANE_ENTRY });
28
26
  admitStoreDurability(config, storeEvidence);
@@ -35,11 +33,12 @@ export async function runStage02(ctx) {
35
33
  const webAdmin = await createWebAdminRuntime({ config, logger, metrics, localRoot });
36
34
  const servedLeg = servedModelTableLeg(config);
37
35
  const rejection = webAdmin.candidateRejectionState();
38
- const noDefaultModel = defaultModelRefusal({ models: config.models, modelRefusals: config.modelRefusals, candidateRejectionNotes: rejection === undefined ? undefined : buildCandidateRejectionNotes(rejection) }, servedLeg);
36
+ const webAdminIsConfigSource = configSource === "remote";
37
+ const noDefaultModel = defaultModelRefusal({ models: config.models, modelRefusals: config.modelRefusals, candidateRejectionNotes: rejection === undefined ? undefined : buildCandidateRejectionNotes(rejection) }, modelRefusalLegOf(servedLeg, webAdminIsConfigSource));
39
38
  if (noDefaultModel !== undefined) {
40
39
  throw new Error(noDefaultModel);
41
40
  }
42
- const routeVerdict = judgeServedModelRoute(config, { envTableIsPlaceholder: isRosterGateArmed(config.webAdmin) });
41
+ const routeVerdict = judgeServedModelRoute(config, { envTableIsPlaceholder: isRosterGateArmed(config.webAdmin), webAdminIsConfigSource });
43
42
  if (routeVerdict !== undefined) {
44
43
  throw new Error(routeVerdict.reason);
45
44
  }
@@ -13,11 +13,12 @@ export async function runStage05(ctx) {
13
13
  const deviceLane = config.remoteExec.provider === "device" ? createDeviceLane({ config, logger, metrics, backend, seat: sessionStore.executionPlacement, replicaId: instanceId }) : undefined;
14
14
  const headOf = headReadOf(sessionStore);
15
15
  const spaceCommits = backend !== undefined ? () => runStore : undefined;
16
- const { perTaskImage, sessionEnvSelection, perSessionCwd, sessionBindings, fenceSessionOwner, dropSessionScoped, sessionResidentBackground, dropSessionScopedOf, executionEnvFactory, worktreeReap, sendUserFileTaskEnvs, lspManager, spaceReclaimer, sandboxSecretSeatGate, sandboxReaper, sandboxGitPlane: sandboxGitPlaneSeat, sandboxCapacity, } = createExecutionEnv({ config, logger, metrics, taskAttachmentStore, ...(deviceLane ? { deviceLane } : {}), ...(spaceCommits !== undefined ? { spaceCommits } : {}), ...(headOf !== undefined ? { headOf } : {}), ...(backend !== undefined ? { runRows: () => runStore } : {}) });
16
+ const { perTaskImage, sessionEnvSelection, perSessionCwd, sessionBindings, fenceSessionOwner, dropSessionScoped, sessionResidentBackground, dropSessionScopedOf, executionEnvFactory, worktreeReap, sendUserFileTaskEnvs, lspManager, spaceReclaimer, sandboxApiCredentialsGate, sandboxSecretSeatGate, sandboxReaper, sandboxGitPlane: sandboxGitPlaneSeat, sandboxCapacity, } = createExecutionEnv({ config, logger, metrics, taskAttachmentStore, ...(deviceLane ? { deviceLane } : {}), ...(spaceCommits !== undefined ? { spaceCommits } : {}), ...(headOf !== undefined ? { headOf } : {}), ...(backend !== undefined ? { runRows: () => runStore } : {}) });
17
17
  assertDeviceLaneWired(config.remoteExec.provider === "device", deviceLane, executionEnvFactory !== undefined);
18
18
  if (deviceLane !== undefined && config.remoteExec.provider === "device")
19
19
  await noteDeviceRelayBindings(config.remoteExec.relay, deviceLane.store, logger);
20
20
  assertWorkspaceSpaceReadable(facts.workspaceSpace(config), { headOf, spaceCommits }, facts.workspaceCache(config), sessionStoreLabelOf(config.sessionBackend, backend?.kind));
21
+ sandboxApiCredentialsGate?.();
21
22
  if (sandboxSecretSeatGate !== undefined)
22
23
  await sandboxSecretSeatGate();
23
24
  await sandboxGitPlaneSeat.settle();
@@ -1,6 +1,8 @@
1
1
  import { Runner } from "@sema-agent/core";
2
+ import { type DeploymentPlaneDeps, type DeploymentPlaneLane } from "./runner-deps.js";
2
3
  import type { runStage05 } from "./stage-05-execution-env.js";
3
4
  export declare function runStage06(ctx: Awaited<ReturnType<typeof runStage05>>): Promise<{
5
+ deploymentPlane: (lane: DeploymentPlaneLane) => DeploymentPlaneDeps;
4
6
  sessionEraser: import("../session-erase.js").SessionEraser | undefined;
5
7
  settleErasedSessions: import("../session-erase.js").SessionEraseSettler;
6
8
  approvalAskAudit: import("../approval-ask-audit-store.js").FileApprovalAskAuditStore | undefined;
@@ -3,6 +3,7 @@ import { Runner, InMemoryToolResultStore, TtlSessionStore, uuidv7, createAllowDe
3
3
  import { createEngineSessionRulesSeat } from "../session-rules-seat.js";
4
4
  import { outwardPlane } from "../terminal.js";
5
5
  import { createSessionTitler } from "../session-titler.js";
6
+ import { createPerModelAuthSeat } from "./side-query-lane.js";
6
7
  import { sessionOccupantReadOf } from "../http/owner-access.js";
7
8
  import { cardRuleScopeRoot } from "../task-cwd.js";
8
9
  import { ForkRoutingSessionStore } from "../plugins/fork-routing-session-store.js";
@@ -21,7 +22,7 @@ import { CHECKPOINT_CTX_SEALING_REQUIRED } from "../http/checkpoint-ctx.js";
21
22
  import { sealCheckpointCtxCredentialsM28 } from "../checkpoint-ctx-seal-m28.js";
22
23
  import { retirePromptProfileM30 } from "../stored-request-prompt-profile-m30.js";
23
24
  import { createRuntimeCaps } from "./runtime-caps.js";
24
- import { createEngineNoticeForwarder, createRunnerDeps, createSharedRunnerDeps, localOwnerRulesDeclared } from "./runner-deps.js";
25
+ import { createDeploymentPlaneDeps, createEngineNoticeForwarder, createRunnerDeps, createSharedRunnerDeps, localOwnerRulesDeclared } from "./runner-deps.js";
25
26
  import { defaultEngineNoticeRouter } from "../trace/engine-notice-wire.js";
26
27
  import { createOrgMemoryAdmissionWiring } from "./org-memory.js";
27
28
  import { createGovernanceSeams } from "./governance-seams.js";
@@ -36,6 +37,8 @@ export async function runStage06(ctx) {
36
37
  const { backend, backgroundAgentStore, brain, engineDataRoot, peerDesk, config, webAdmin, consolidationValve, deploymentMods, executionEnvFactory, fileHistoryStore, localRoot, logger, lspManager, mailboxRecipientLifecycle, mailboxStore, memoryEngine, memorySyncRunner, metrics, perSessionCwd, permissionRuleProvider, pricing, rosterStore, ruleConsent, sendUserFileTaskEnvs, sessionCaptureRecords, sessionPolicyStore, sessionStore, spaceReclaimer, taskAttachmentStore, taskListLane, toolResultStore, tracer, usageWindowStore } = ctx;
37
38
  const { sqlWorkflowRunStore, workflowNotifyJournal, workflowCompletionInbox, deliverWorkflowCompletion, workflowNotifyGate, fleetBus, workflowRunStore, workflowJournalStore, outcomeSink, workflowRecoverOpts, workflowAgentRegistry, subagentSteerRegistry, workflowAgentSessionIndex, workflowParkDecisions, heldParksHere, } = createWorkflowOrchestration({ config, logger, metrics, localRoot, backend, getRunStore: () => runStore, getRunEndedHandoff: () => runEndedHandoff });
38
39
  backend?.bindWorkflowRunReader?.(workflowRunStore ?? "none");
40
+ const cardScopeRootOf = (sessionId) => cardRuleScopeRoot(sessionId !== undefined ? perSessionCwd.get(sessionId) : undefined, config);
41
+ backend?.bindCardScopeRoot?.(cardScopeRootOf);
39
42
  const parkCommitted = backend?.checkpoint && config.durableApproval ? createParkCommitWatch(backend.checkpoint(logger)) : undefined;
40
43
  const checkpointStore = parkCommitted?.store;
41
44
  const parkCommits = parkCommitted?.watch;
@@ -56,7 +59,7 @@ export async function runStage06(ctx) {
56
59
  config, logger, backend, sendUserFileTaskEnvs, ruleConsent, parkCommits,
57
60
  ...(checkpointStore !== undefined ? { checkpointStore } : {}),
58
61
  getParkedRedeem: () => parkedAskRedeem,
59
- ruleScopeRootFor: (sessionId) => cardRuleScopeRoot(sessionId !== undefined ? perSessionCwd.get(sessionId) : undefined, config),
62
+ ruleScopeRootFor: cardScopeRootOf,
60
63
  });
61
64
  if (streamApprovalGate.active)
62
65
  await assertApprovalAskRuleMaterialOnBackend(backend);
@@ -164,11 +167,13 @@ export async function runStage06(ctx) {
164
167
  const pick = hookModelFor(model);
165
168
  if (!pick.ok)
166
169
  return pick;
170
+ const resolver = webAdmin.getKeyResolver();
167
171
  try {
168
172
  const result = await hookAgentRunner.runTask({
169
173
  objective: prompt,
170
174
  sessionId: uuidv7(),
171
175
  model: pick.catalogRef,
176
+ getApiKeyAndHeaders: createPerModelAuthSeat(() => resolver),
172
177
  ...(system !== undefined ? { systemPrompt: system } : {}),
173
178
  handsReadOnly: true,
174
179
  enableFork: false,
@@ -235,15 +240,16 @@ export async function runStage06(ctx) {
235
240
  engineDataRoot,
236
241
  peerDesk,
237
242
  runtimeCapsResolver,
243
+ onError: runnerDeps.onError,
238
244
  }),
239
245
  sessionStore: subRunnerSessions,
240
246
  onBackgroundChildEvent: runnerDeps.onBackgroundChildEvent ? runnerDeps.onBackgroundChildEvent : undefined,
241
247
  loadProjectMemory: runnerDeps.loadProjectMemory ? runnerDeps.loadProjectMemory : undefined,
242
248
  probeInstructionSources: runnerDeps.probeInstructionSources ? runnerDeps.probeInstructionSources : undefined,
243
- onError: runnerDeps.onError ? runnerDeps.onError : undefined,
244
249
  };
245
250
  const subRunner = new Runner(subRunnerDeps);
251
+ const deploymentPlane = (lane) => createDeploymentPlaneDeps({ config, logger, metrics, brain, pricing, tracer, promptSource: webAdmin.promptSource, deploymentMods, usageWindowStore, governanceSeams, mcpRevocations, engineDataRoot, runtimeCapsResolver, onError: runnerDeps.onError }, lane);
246
252
  const settleErasedSessions = createSessionEraseSettler({ attachments: taskAttachmentStore, spaceReclaimer, logger });
247
- return { ...ctx, sessionEraser, settleErasedSessions, approvalAskAudit, approvalExemptionStore, centerRuntimeCapsResolver, checkpointStore, checkpointCtxSealing, parkCommits, durableEnabled, elicitation, fleetBus, governanceSeams, handslessRunner, hookAgent, hookAgentRunner, hookLlm, mcpRevocations, memoryConsolidationFaces, memoryOptOutGrantStore, orgMemoryAdmission, outcomeSink, principalCaps, question, retentionExecutor, retentionLaneStore, runner, runnerDeps, runtimeCapsPeekReading, sendFileLedger, sendUserFileEmitter, sendUserFileToolSpec, sessionTitler, sharedMemoryStore, sqlWorkflowRunStore, streamApprovalGate, subRunner, subagentSteerRegistry, toolApproval, workflowAgentRegistry, workflowAgentSessionIndex, workflowCompletionInbox, workflowJournalStore, workflowModelAllowlistSnapshot, workflowParkDecisions, workflowParkHolderPull, workflowNotifyGate, workflowNotifyJournal, workflowRecoverOpts, workflowRunStore, workflowsCapable, orgDeliveryGate };
253
+ return { ...ctx, deploymentPlane, sessionEraser, settleErasedSessions, approvalAskAudit, approvalExemptionStore, centerRuntimeCapsResolver, checkpointStore, checkpointCtxSealing, parkCommits, durableEnabled, elicitation, fleetBus, governanceSeams, handslessRunner, hookAgent, hookAgentRunner, hookLlm, mcpRevocations, memoryConsolidationFaces, memoryOptOutGrantStore, orgMemoryAdmission, outcomeSink, principalCaps, question, retentionExecutor, retentionLaneStore, runner, runnerDeps, runtimeCapsPeekReading, sendFileLedger, sendUserFileEmitter, sendUserFileToolSpec, sessionTitler, sharedMemoryStore, sqlWorkflowRunStore, streamApprovalGate, subRunner, subagentSteerRegistry, toolApproval, workflowAgentRegistry, workflowAgentSessionIndex, workflowCompletionInbox, workflowJournalStore, workflowModelAllowlistSnapshot, workflowParkDecisions, workflowParkHolderPull, workflowNotifyGate, workflowNotifyJournal, workflowRecoverOpts, workflowRunStore, workflowsCapable, orgDeliveryGate };
248
254
  }
249
255
  //# sourceMappingURL=stage-06-runners.js.map
@@ -24,6 +24,7 @@ export declare function runStage07(ctx: Awaited<ReturnType<typeof runStage06>>):
24
24
  userInputLedger: import("../user-input-ledger.js").UserInputLedger | undefined;
25
25
  userInputLedgerStore: import("../user-input-ledger.js").UserInputLedgerStore | undefined;
26
26
  webSearchProvider: "brave" | "tavily" | "searxng" | undefined;
27
+ deploymentPlane: (lane: import("./runner-deps.js").DeploymentPlaneLane) => import("./runner-deps.js").DeploymentPlaneDeps;
27
28
  sessionEraser: import("../session-erase.js").SessionEraser | undefined;
28
29
  settleErasedSessions: import("../session-erase.js").SessionEraseSettler;
29
30
  approvalAskAudit: import("../approval-ask-audit-store.js").FileApprovalAskAuditStore | undefined;
@@ -94,7 +94,7 @@ export async function runStage07(ctx) {
94
94
  ? selectEnvironmentTool({
95
95
  catalog: imageIndex,
96
96
  selection: sessionEnvSelection,
97
- viewerFor: (principal) => ({ operator: explicitOperatorOk(principal === undefined ? undefined : personOf(recoveredSubject(principal)), config), tenantId: principal ?? null }),
97
+ viewerFor: (principal) => ({ operator: explicitOperatorOk(principal === undefined ? undefined : personOf(recoveredSubject(principal)), config, "operate"), tenantId: principal ?? null }),
98
98
  })
99
99
  : undefined;
100
100
  const imageBakes = backend?.imageBake && config.imageBakes.enabled ? backend.imageBake() : undefined;
@@ -37,6 +37,7 @@ export declare function runStage08(ctx: Awaited<ReturnType<typeof runStage07>>):
37
37
  userInputLedger: import("../user-input-ledger.js").UserInputLedger | undefined;
38
38
  userInputLedgerStore: import("../user-input-ledger.js").UserInputLedgerStore | undefined;
39
39
  webSearchProvider: "brave" | "tavily" | "searxng" | undefined;
40
+ deploymentPlane: (lane: import("./runner-deps.js").DeploymentPlaneLane) => import("./runner-deps.js").DeploymentPlaneDeps;
40
41
  sessionEraser: import("../session-erase.js").SessionEraser | undefined;
41
42
  settleErasedSessions: import("../session-erase.js").SessionEraseSettler;
42
43
  approvalAskAudit: import("../approval-ask-audit-store.js").FileApprovalAskAuditStore | undefined;
@@ -59,6 +59,7 @@ export declare function runStage09(ctx: Awaited<ReturnType<typeof runStage08>>):
59
59
  userInputLedger: import("../user-input-ledger.js").UserInputLedger | undefined;
60
60
  userInputLedgerStore: import("../user-input-ledger.js").UserInputLedgerStore | undefined;
61
61
  webSearchProvider: "brave" | "tavily" | "searxng" | undefined;
62
+ deploymentPlane: (lane: import("./runner-deps.js").DeploymentPlaneLane) => import("./runner-deps.js").DeploymentPlaneDeps;
62
63
  sessionEraser: import("../session-erase.js").SessionEraser | undefined;
63
64
  settleErasedSessions: import("../session-erase.js").SessionEraseSettler;
64
65
  approvalAskAudit: import("../approval-ask-audit-store.js").FileApprovalAskAuditStore | undefined;
@@ -11,7 +11,7 @@ import { assertStaticWiringConsistent } from "../http/routes/diagnostics.js";
11
11
  import { seatText } from "../trace/exit-seat.js";
12
12
  import { buildDisplaySafeUrl } from "../trace/redact.js";
13
13
  export function runStage09(ctx) {
14
- const { approvalExemptionStore, backend, backgroundAgentStore, brain, checkpointStore, checkpointCtxSealing, config, webAdmin, deploymentMods, dropSessionScoped, durableEnabled, executionEnvFactory, fileHistoryErasure, governanceSeams, localRoot, logger, mailboxRecipientLifecycle, mailboxStore, metrics, pricing, resumeAnchorStore, runStore, runnerDeps, sessionEraser, sessionPolicyStore, sessionStore, settleErasedSessions, storePosture, streamApprovalGate, taskAttachmentStore, spaceReclaimer, taskListLane, toolResultStore, tracer, usageWindowStore, userInputLedgerStore, workflowCompletionInbox } = ctx;
14
+ const { approvalExemptionStore, deploymentPlane, backend, backgroundAgentStore, checkpointStore, checkpointCtxSealing, config, dropSessionScoped, durableEnabled, executionEnvFactory, fileHistoryErasure, localRoot, logger, mailboxRecipientLifecycle, mailboxStore, metrics, resumeAnchorStore, runStore, runnerDeps, sessionEraser, sessionPolicyStore, sessionStore, settleErasedSessions, storePosture, streamApprovalGate, taskAttachmentStore, spaceReclaimer, taskListLane, toolResultStore, userInputLedgerStore, webAdmin, workflowCompletionInbox } = ctx;
15
15
  const { ownerAware, sessionAudit, sessionWatchRegistry, purgeSession, recoverPendingDeletions, instrumentDegenerate, planCacheProbe } = createSessionFaces({
16
16
  dropSessionScoped,
17
17
  config, logger, metrics, localRoot, backend, sessionStore, runStore, checkpointStore, toolResultStore,
@@ -31,7 +31,7 @@ export function runStage09(ctx) {
31
31
  bindSessionAgeOut(purgeSession !== undefined && ageOutStore !== undefined && facts.sessionKinds({ sessionStorage: ownerAware, purgeSession }).available
32
32
  ? createSessionAgeOut({ store: ageOutStore, purge: purgeSession, retentionMs: () => config.backgroundAgentRetentionMs, logger, metrics })
33
33
  : undefined);
34
- const leaderEndpoint = createLeaderFace({ config, logger, brain, pricing, executionEnvFactory, toolResultStore, sessionStore, checkpointStore, checkpointCtxSealing, governanceSeams, backend, tracer, usageWindowStore, promptSource: webAdmin.promptSource, onError: runnerDeps.onError, deploymentMods });
34
+ const leaderEndpoint = createLeaderFace({ config, logger, localRoot, executionEnvFactory, toolResultStore, sessionStore, checkpointStore, checkpointCtxSealing, backend, deploymentPlane, getKeyResolver: () => webAdmin.getKeyResolver() });
35
35
  const drainState = { draining: false };
36
36
  const authBridgeIssuer = authBridgeIssuerOf(config)?.issuer;
37
37
  const webAdminJwtVerifier = authBridgeIssuer
@@ -1,11 +1,14 @@
1
1
  import { brainSummary } from "../brain.js";
2
2
  import { type ServiceConfig } from "../config.js";
3
3
  import type { runStage09 } from "./stage-09-leader.js";
4
+ import { type ControlSocketUnavailableReason } from "../control-socket.js";
4
5
  /**
5
6
  * 启动协议行 `listening` 的字段(行本身是 `observability/logger.ts` 的 {@link import("../observability/logger.js").STARTUP_PROTOCOL_EVENTS} 一员:不随 `LOG_LEVEL`)。
6
7
  * 铸点 = 本文件 listen 之后那一行(全仓唯一,`test/source-hygiene-gate.test.ts` M7),字面量过 {@link exactListeningLine}(键集恰等于本型,可选键与条件展开同算);
7
8
  * 键集登记在自铸登记表 `listeningLineKey`(`satisfies Record<keyof ListeningLine, …>`:键加一个而登记表没跟 / 多一个 ⇒ tsc 红)。只登顶层键;`brain` 段里的键随 `brainSummary` 走,不在本型。
8
9
  *
10
+ * 本机控制 socket 两格(`controlSocket` / `controlSocketUnavailable`)恰一只在场:同一次开口结局(`control-socket.ts` 的 `openControlSocket`)的投影 —— 绑定的事实由绑定者报,与 `boundAddress` 同一条。
11
+ *
9
12
  * 绑址两格,一格一个事实:`bindHost` = 本进程**请求**绑的地址(`resolveBindHost` 的答案 —— `BIND_HOST` 经无鉴权自收窄之后的那一只;答案缺席 = 全接口时是说明串);`boundAddress` = 内核**实际**绑上的地址
10
13
  * (`server.address().address` 原样:`::` / `0.0.0.0` / `127.0.0.1` / `::1` …;配置写 `localhost` 时它是解析出的那一只)。口同理:`port` 读的也是绑定者自己的答案。
11
14
  */
@@ -14,6 +17,10 @@ export interface ListeningLine {
14
17
  readonly bindHost: string;
15
18
  readonly bindHostNote?: string;
16
19
  readonly boundAddress: string;
20
+ /** 本机控制 socket 的绝对路径 —— present-iff 它在听(与下一键恰一只在场;同一次开口结局的投影 `controlSocketLineKeysOf`)。 */
21
+ readonly controlSocket?: string;
22
+ /** 本机控制 socket 没开的原因词(闭集 `CONTROL_SOCKET_UNAVAILABLE_REASONS`)—— present-iff 它没在听。 */
23
+ readonly controlSocketUnavailable?: ControlSocketUnavailableReason;
17
24
  readonly model: ServiceConfig["model"]["id"];
18
25
  readonly brain: ReturnType<typeof brainSummary>;
19
26
  readonly breakerState: string;
@@ -90,6 +97,7 @@ export declare function runStage10(ctx: Awaited<ReturnType<typeof runStage09>>):
90
97
  userInputLedger: import("../user-input-ledger.js").UserInputLedger | undefined;
91
98
  userInputLedgerStore: import("../user-input-ledger.js").UserInputLedgerStore | undefined;
92
99
  webSearchProvider: "brave" | "tavily" | "searxng" | undefined;
100
+ deploymentPlane: (lane: import("./runner-deps.js").DeploymentPlaneLane) => import("./runner-deps.js").DeploymentPlaneDeps;
93
101
  sessionEraser: import("../session-erase.js").SessionEraser | undefined;
94
102
  settleErasedSessions: import("../session-erase.js").SessionEraseSettler;
95
103
  approvalAskAudit: import("../approval-ask-audit-store.js").FileApprovalAskAuditStore | undefined;
@@ -29,6 +29,7 @@ import { createRunnerDepsOnAsk } from "./runner-deps.js";
29
29
  import { installShutdownHandlers } from "./shutdown.js";
30
30
  import { bindServerLateSeats } from "./late-binds.js";
31
31
  import { serviceVersion } from "../service-version.js";
32
+ import { controlSocketLineKeysOf, openControlSocket } from "../control-socket.js";
32
33
  import { buildDisplaySafeUrl } from "../trace/redact.js";
33
34
  import { seatText } from "../trace/exit-seat.js";
34
35
  function exactListeningLine(line) {
@@ -238,19 +239,6 @@ export async function runStage10(ctx) {
238
239
  metrics,
239
240
  });
240
241
  const bindHost = resolveBindHost(config);
241
- if (config.bindHostSource === "HOST" && bindHost !== config.bindHost) {
242
- logger.warn("bind_host_from_HOST_env_overridden", {
243
- bindHost,
244
- ignoredHostEnv: config.bindHost,
245
- note: "HOST was inherited from the shell (zsh commonly sets it to the machine name) and would have bound the write face to a non-loopback address — but this deployment has ALLOW_UNAUTHED_WRITES with no service token, so the bind address was narrowed to loopback instead. Two ways out if you meant to expose it: set BIND_HOST explicitly, or configure a service token.",
246
- });
247
- }
248
- else if (config.bindHostSource === "HOST") {
249
- logger.warn("bind_host_from_HOST_env", {
250
- bindHost,
251
- note: "the bind address came from the HOST env var (not BIND_HOST). Shells like zsh commonly set HOST to the machine name — if you did not set it yourself, this may be an inherited shell variable silently configuring the bind face. Set BIND_HOST explicitly to silence this warning.",
252
- });
253
- }
254
242
  let onListenError;
255
243
  try {
256
244
  await new Promise((resolve, reject) => {
@@ -263,8 +251,6 @@ export async function runStage10(ctx) {
263
251
  logger.error("listen_failed", {
264
252
  port: config.port,
265
253
  bindHost: bindHost ?? "0.0.0.0/::(all interfaces)",
266
- ...(config.bindHostSource ? { bindHostSource: config.bindHostSource } : {}),
267
- ...(config.bindHostSource === "HOST" ? { note: "bind failed for a host inherited from the HOST env var — set BIND_HOST explicitly (e.g. BIND_HOST=127.0.0.1)." } : {}),
268
254
  error: seatText("operator-log-text", e instanceof Error ? e.message : String(e)),
269
255
  });
270
256
  throw e;
@@ -279,6 +265,14 @@ export async function runStage10(ctx) {
279
265
  ...("code" in e ? { code: String(e.code) } : {}),
280
266
  });
281
267
  });
268
+ const controlSocketServer = server.controlSocketServer;
269
+ controlSocketServer.on("error", (e) => {
270
+ logger.error("control_socket_error", {
271
+ error: seatText("operator-log-text", e.message),
272
+ ...("code" in e ? { code: String(e.code) } : {}),
273
+ });
274
+ });
275
+ const controlSocket = await openControlSocket(controlSocketServer, { exclusiveDataRoot: backend?.exclusiveDataRoot?.() });
282
276
  const fleetClient = startFleetClientFromConfig(config, {
283
277
  instanceId,
284
278
  version: serviceVersion(),
@@ -307,6 +301,7 @@ export async function runStage10(ctx) {
307
301
  ? { bindHostNote: "auto-narrowed to loopback: write face is unauthenticated (ALLOW_UNAUTHED_WRITES with no service token). Set BIND_HOST explicitly to override." }
308
302
  : {}),
309
303
  boundAddress: bound.address,
304
+ ...controlSocketLineKeysOf(controlSocket),
310
305
  model: config.model.id,
311
306
  brain: brainSummary(config),
312
307
  breakerState: config.resilience.circuitBreaker ? (breakerState ? `shared(${backend.kind})` : "in-process") : "off",
@@ -342,6 +337,7 @@ export async function runStage10(ctx) {
342
337
  }
343
338
  void installShutdownHandlers({
344
339
  config, logger, server, reaper, fleetReconcile, otelExporter, breakerState, costQuota, rateLimiter,
340
+ controlSocket: controlSocket.listening ? controlSocketServer : undefined,
345
341
  version: serviceVersion(),
346
342
  runner, subRunner, lspManager, workflowNotifyJournal, fleetClient, backend, drainState,
347
343
  storeLiveProbe, webAdmin,
@@ -9,7 +9,7 @@ import { PgMemoryEngineBackend, ensurePgMemoryEngineSchema } from "../plugins/me
9
9
  import { TiDBMemoryEngineBackend, ensureTiDBMemoryEngineSchema } from "../plugins/memory-engine-tidb.js";
10
10
  import { PgMemoryHistoryStore, PgMemorySyncStore, ensurePgMemoryHistorySchema, ensurePgMemorySyncSchema } from "../plugins/memory-sync-store-pg.js";
11
11
  import { TiDBMemoryHistoryStore, TiDBMemorySyncStore, ensureTiDBMemoryHistorySchema, ensureTiDBMemorySyncSchema } from "../plugins/memory-sync-store-tidb.js";
12
- import { MinioBlobBackend } from "../plugins/blob-backend.js";
12
+ import { createSessionBlobBackend } from "../plugins/blob-backend.js";
13
13
  import { ensureSnapshotBuckets } from "../plugins/snapshot-bucket-presence.js";
14
14
  import { PgBackgroundAgentStore, TiDBBackgroundAgentStore, ensurePgBackgroundAgentSchema, ensureTiDBBackgroundAgentSchema } from "../stores-sql/background-agent-store-sql.js";
15
15
  import { recordFailOpen } from "../observability/fail-open.js";
@@ -304,14 +304,17 @@ export async function openStores(ctx) {
304
304
  const mysqlPool = backend?.mysqlPool?.();
305
305
  const pgPool = backend?.pgPool?.();
306
306
  if (pgPool || mysqlPool) {
307
- const minio = config.snapshotBlobStore;
308
- if (!minio) {
307
+ const namespace = backend?.sessionBlobNamespace?.();
308
+ if (!config.snapshotBlobStore) {
309
309
  logger.error("attachments_disabled_object_store_required", {
310
310
  hint: "cloud deployments must configure object storage (MINIO_ENDPOINT/MINIO_ACCESS_KEY/MINIO_SECRET_KEY) — attachment routes will 501 until it is set",
311
311
  });
312
312
  }
313
+ else if (!namespace) {
314
+ throw new Error("object storage is configured but the store backend holds no session blob namespace — the attachment store's bytes have no namespace proven to be this database's (a store backend that does not implement sessionBlobNamespace())");
315
+ }
313
316
  else {
314
- const bytes = new MinioBlobBackend({ ...minio, keyPrefix: `${minio.keyPrefix ?? ""}attachments/` });
317
+ const bytes = createSessionBlobBackend(namespace, "attachments");
315
318
  if (pgPool) {
316
319
  const q = async (text, params) => { const r = await pgPool.query(text, params); return { rows: r.rows }; };
317
320
  await ensurePgTaskAttachmentSchema(q);