@sema-agent/server 1.323.0 → 2.0.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 (539) hide show
  1. package/dist/approval-hmac.d.ts +40 -0
  2. package/dist/approval-hmac.js +67 -0
  3. package/dist/approval.d.ts +31 -0
  4. package/dist/approval.js +72 -4
  5. package/dist/audit.d.ts +26 -0
  6. package/dist/audit.js +40 -1
  7. package/dist/auth-bridge.d.ts +10 -0
  8. package/dist/auth-bridge.js +47 -4
  9. package/dist/auth-keys.d.ts +19 -0
  10. package/dist/auth-keys.js +13 -0
  11. package/dist/bake-runner/main.d.ts +5 -0
  12. package/dist/bake-runner/main.js +43 -4
  13. package/dist/bake-runner/protocol.d.ts +57 -0
  14. package/dist/bake-runner/protocol.js +58 -3
  15. package/dist/bake-runner/runner.d.ts +54 -0
  16. package/dist/bake-runner/runner.js +87 -5
  17. package/dist/bench/l8/artifact.d.ts +63 -0
  18. package/dist/bench/l8/artifact.js +61 -2
  19. package/dist/bench/l8/escape.d.ts +36 -0
  20. package/dist/bench/l8/escape.js +25 -0
  21. package/dist/bench/l8/index.d.ts +14 -0
  22. package/dist/bench/l8/index.js +14 -0
  23. package/dist/bench/l8/probes.d.ts +74 -0
  24. package/dist/bench/l8/probes.js +60 -0
  25. package/dist/bench/l8/run-probes.d.ts +43 -0
  26. package/dist/bench/l8/run-probes.js +45 -2
  27. package/dist/bench/s1/arms.d.ts +126 -0
  28. package/dist/bench/s1/arms.js +188 -13
  29. package/dist/bench/s1/live-deps.d.ts +66 -0
  30. package/dist/bench/s1/live-deps.js +249 -11
  31. package/dist/bench/s1/oracle.d.ts +49 -0
  32. package/dist/bench/s1/oracle.js +36 -1
  33. package/dist/bench/s1/repair-oracle-adapter.d.ts +33 -0
  34. package/dist/bench/s1/repair-oracle-adapter.js +30 -0
  35. package/dist/bench/s1/reviewer.d.ts +38 -0
  36. package/dist/bench/s1/reviewer.js +34 -0
  37. package/dist/bench/s1/row.d.ts +77 -0
  38. package/dist/bench/s1/row.js +62 -0
  39. package/dist/bench/s1/run-firm.d.ts +47 -0
  40. package/dist/bench/s1/run-firm.js +70 -4
  41. package/dist/bench/s1/runner-ctx.d.ts +71 -0
  42. package/dist/bench/s1/runner-ctx.js +36 -0
  43. package/dist/bench/s1/tasks.d.ts +108 -0
  44. package/dist/bench/s1/tasks.js +115 -0
  45. package/dist/boot-reclaim.d.ts +19 -0
  46. package/dist/boot-reclaim.js +20 -0
  47. package/dist/brain.d.ts +25 -0
  48. package/dist/brain.js +61 -1
  49. package/dist/budget.d.ts +66 -0
  50. package/dist/budget.js +128 -4
  51. package/dist/capabilities/builtin-tools.d.ts +3 -0
  52. package/dist/capabilities/builtin-tools.js +3 -0
  53. package/dist/capabilities/center-plugins.d.ts +17 -1
  54. package/dist/capabilities/center-plugins.js +45 -4
  55. package/dist/capabilities/center-prompts.d.ts +46 -0
  56. package/dist/capabilities/center-prompts.js +57 -3
  57. package/dist/capabilities/code-review-council.d.ts +28 -0
  58. package/dist/capabilities/code-review-council.js +40 -7
  59. package/dist/capabilities/collab-wire.d.ts +2 -0
  60. package/dist/capabilities/collab-workflows.d.ts +7 -0
  61. package/dist/capabilities/collab-workflows.js +44 -1
  62. package/dist/capabilities/oa-tools.d.ts +6 -0
  63. package/dist/capabilities/oa-tools.js +10 -0
  64. package/dist/capabilities/prompt.d.ts +14 -0
  65. package/dist/capabilities/prompt.js +14 -0
  66. package/dist/capabilities/prompts/code-review.d.ts +14 -0
  67. package/dist/capabilities/prompts/code-review.js +14 -0
  68. package/dist/capabilities/prompts/identity.d.ts +6 -0
  69. package/dist/capabilities/prompts/identity.js +6 -0
  70. package/dist/capabilities/prompts/team.d.ts +4 -0
  71. package/dist/capabilities/prompts/team.js +4 -0
  72. package/dist/capabilities/repo-tools.d.ts +11 -0
  73. package/dist/capabilities/repo-tools.js +8 -0
  74. package/dist/capabilities/sandbox-file-send.d.ts +95 -0
  75. package/dist/capabilities/sandbox-file-send.js +91 -3
  76. package/dist/capabilities/scenarios.d.ts +130 -0
  77. package/dist/capabilities/scenarios.js +180 -7
  78. package/dist/capabilities/select-environment-tool.d.ts +7 -0
  79. package/dist/capabilities/select-environment-tool.js +30 -0
  80. package/dist/capabilities/send-user-file-tool.d.ts +33 -0
  81. package/dist/capabilities/send-user-file-tool.js +65 -1
  82. package/dist/capabilities/skills.d.ts +29 -0
  83. package/dist/capabilities/skills.js +13 -2
  84. package/dist/capabilities/team.d.ts +22 -0
  85. package/dist/capabilities/team.js +22 -2
  86. package/dist/capabilities/tool-defer.d.ts +26 -0
  87. package/dist/capabilities/tool-defer.js +3 -0
  88. package/dist/config-center/apply-effective.d.ts +65 -0
  89. package/dist/config-center/apply-effective.js +204 -12
  90. package/dist/config-center/http-client.d.ts +34 -0
  91. package/dist/config-center/http-client.js +68 -0
  92. package/dist/config-center/restart-signal.d.ts +22 -0
  93. package/dist/config-center/restart-signal.js +39 -0
  94. package/dist/config-center/skills-mcp.d.ts +20 -1
  95. package/dist/config-center/skills-mcp.js +42 -7
  96. package/dist/config-center/types.d.ts +92 -1
  97. package/dist/config-lkg.d.ts +12 -0
  98. package/dist/config-lkg.js +41 -0
  99. package/dist/config-provider.d.ts +78 -0
  100. package/dist/config-provider.js +165 -2
  101. package/dist/config-types.d.ts +546 -0
  102. package/dist/config.d.ts +64 -0
  103. package/dist/config.js +455 -60
  104. package/dist/degenerate-instrument.d.ts +38 -0
  105. package/dist/degenerate-instrument.js +55 -3
  106. package/dist/elicitation.d.ts +39 -0
  107. package/dist/elicitation.js +87 -3
  108. package/dist/env-facts.d.ts +61 -0
  109. package/dist/env-facts.js +73 -7
  110. package/dist/fleet/fleet-bus.d.ts +185 -0
  111. package/dist/fleet/fleet-bus.js +333 -27
  112. package/dist/fleet/subagent-tail-bus.d.ts +11 -0
  113. package/dist/fleet/subagent-tail-bus.js +33 -2
  114. package/dist/fleet-client.d.ts +38 -0
  115. package/dist/fleet-client.js +44 -9
  116. package/dist/fleet-lease.d.ts +46 -0
  117. package/dist/fleet-lease.js +73 -5
  118. package/dist/hooks/branch-transcript.d.ts +8 -0
  119. package/dist/hooks/branch-transcript.js +33 -0
  120. package/dist/hooks/cc-stop-prompt.d.ts +42 -0
  121. package/dist/hooks/cc-stop-prompt.js +43 -1
  122. package/dist/hooks/hook-llm.d.ts +15 -0
  123. package/dist/hooks/hook-llm.js +47 -0
  124. package/dist/hooks/hook-runner.d.ts +89 -0
  125. package/dist/hooks/hook-runner.js +327 -18
  126. package/dist/http/idempotency.d.ts +31 -0
  127. package/dist/http/idempotency.js +34 -0
  128. package/dist/http/principal-gate.d.ts +17 -0
  129. package/dist/http/principal-gate.js +35 -3
  130. package/dist/http/route-ctx.d.ts +36 -0
  131. package/dist/http/routes/approvals-assistant.d.ts +25 -0
  132. package/dist/http/routes/approvals-assistant.js +253 -23
  133. package/dist/http/routes/attachments.js +22 -4
  134. package/dist/http/routes/capabilities.d.ts +7 -0
  135. package/dist/http/routes/capabilities.js +202 -1
  136. package/dist/http/routes/fleet.d.ts +6 -0
  137. package/dist/http/routes/fleet.js +94 -5
  138. package/dist/http/routes/images.d.ts +17 -0
  139. package/dist/http/routes/images.js +222 -14
  140. package/dist/http/routes/leader.d.ts +7 -0
  141. package/dist/http/routes/leader.js +10 -0
  142. package/dist/http/routes/memory-policy.d.ts +6 -0
  143. package/dist/http/routes/memory-policy.js +38 -6
  144. package/dist/http/routes/notify-wake.d.ts +10 -0
  145. package/dist/http/routes/notify-wake.js +19 -3
  146. package/dist/http/routes/observability.d.ts +6 -0
  147. package/dist/http/routes/observability.js +19 -2
  148. package/dist/http/routes/runs.d.ts +15 -0
  149. package/dist/http/routes/runs.js +464 -41
  150. package/dist/http/routes/session-sync.d.ts +15 -0
  151. package/dist/http/routes/session-sync.js +229 -19
  152. package/dist/http/routes/sessions-list.d.ts +6 -0
  153. package/dist/http/routes/sessions-list.js +35 -4
  154. package/dist/http/routes/sessions.d.ts +14 -0
  155. package/dist/http/routes/sessions.js +176 -31
  156. package/dist/http/routes/side-query.d.ts +8 -0
  157. package/dist/http/routes/side-query.js +26 -1
  158. package/dist/http/routes/tasks.d.ts +18 -0
  159. package/dist/http/routes/tasks.js +501 -38
  160. package/dist/http/routes/trace-usage.d.ts +10 -0
  161. package/dist/http/routes/trace-usage.js +66 -14
  162. package/dist/http/routes/workflows.d.ts +12 -0
  163. package/dist/http/routes/workflows.js +180 -19
  164. package/dist/http/run-meta.d.ts +11 -0
  165. package/dist/http/run-meta.js +6 -0
  166. package/dist/http/send.d.ts +19 -0
  167. package/dist/http/send.js +11 -0
  168. package/dist/http/server.d.ts +255 -0
  169. package/dist/http/server.js +921 -75
  170. package/dist/http/sse-log.d.ts +15 -0
  171. package/dist/http/sse-log.js +16 -0
  172. package/dist/http/tar.d.ts +9 -0
  173. package/dist/http/tar.js +21 -5
  174. package/dist/http/wire-gate.d.ts +9 -0
  175. package/dist/http/wire-gate.js +9 -0
  176. package/dist/http/wire-types.d.ts +187 -0
  177. package/dist/http/workspace-content.d.ts +8 -0
  178. package/dist/http/workspace-content.js +10 -0
  179. package/dist/images/bake-validate.d.ts +63 -0
  180. package/dist/images/bake-validate.js +71 -1
  181. package/dist/images/manifest.d.ts +19 -0
  182. package/dist/images/manifest.js +6 -1
  183. package/dist/index.d.ts +1 -5
  184. package/dist/index.js +10 -5
  185. package/dist/key-resolver.d.ts +23 -0
  186. package/dist/key-resolver.js +27 -2
  187. package/dist/leader/diffout.d.ts +23 -0
  188. package/dist/leader/diffout.js +8 -1
  189. package/dist/leader/diffup.d.ts +32 -0
  190. package/dist/leader/diffup.js +43 -0
  191. package/dist/leader/endpoint.d.ts +20 -0
  192. package/dist/leader/endpoint.js +25 -2
  193. package/dist/leader/fanout.d.ts +60 -0
  194. package/dist/leader/fanout.js +29 -3
  195. package/dist/leader/grader-env-factory.d.ts +74 -0
  196. package/dist/leader/grader-env-factory.js +62 -3
  197. package/dist/leader/leader.d.ts +97 -0
  198. package/dist/leader/leader.js +151 -4
  199. package/dist/leader/merge.d.ts +94 -0
  200. package/dist/leader/merge.js +112 -9
  201. package/dist/leader/planner.d.ts +52 -0
  202. package/dist/leader/planner.js +47 -3
  203. package/dist/leader/repair-oracle.d.ts +61 -0
  204. package/dist/leader/repair-oracle.js +59 -1
  205. package/dist/leader/repair-wire.d.ts +78 -0
  206. package/dist/leader/repair-wire.js +79 -2
  207. package/dist/leader/wire.d.ts +79 -0
  208. package/dist/leader/wire.js +255 -8
  209. package/dist/lsp/e2b-bridge.d.ts +16 -0
  210. package/dist/lsp/e2b-bridge.js +32 -4
  211. package/dist/lsp/e2b-manager.d.ts +10 -0
  212. package/dist/lsp/e2b-manager.js +18 -2
  213. package/dist/lsp/lsp-frames.d.ts +12 -0
  214. package/dist/lsp/lsp-frames.js +12 -0
  215. package/dist/lsp/manager.d.ts +12 -0
  216. package/dist/lsp/manager.js +35 -2
  217. package/dist/lsp/types.d.ts +10 -0
  218. package/dist/lsp/ws-transport.d.ts +12 -0
  219. package/dist/lsp/ws-transport.js +53 -5
  220. package/dist/lsp-evict.d.ts +14 -0
  221. package/dist/lsp-evict.js +15 -1
  222. package/dist/main.js +2132 -96
  223. package/dist/memory-export.d.ts +1 -0
  224. package/dist/memory-export.js +4 -0
  225. package/dist/memory-scope.d.ts +49 -0
  226. package/dist/memory-scope.js +87 -4
  227. package/dist/memory-sync-client.d.ts +24 -0
  228. package/dist/memory-sync-client.js +41 -2
  229. package/dist/memory-sync.d.ts +23 -0
  230. package/dist/memory-sync.js +70 -1
  231. package/dist/model-select.d.ts +39 -0
  232. package/dist/model-select.js +42 -1
  233. package/dist/observability/cost-quota.d.ts +20 -0
  234. package/dist/observability/cost-quota.js +4 -0
  235. package/dist/observability/cost-taxonomy.d.ts +45 -0
  236. package/dist/observability/cost-taxonomy.js +34 -0
  237. package/dist/observability/logger.d.ts +1 -0
  238. package/dist/observability/logger.js +6 -0
  239. package/dist/observability/metrics.d.ts +13 -0
  240. package/dist/observability/metrics.js +63 -0
  241. package/dist/observability/otel-exporter.d.ts +9 -0
  242. package/dist/observability/otel-exporter.js +11 -3
  243. package/dist/observability/principal-context.d.ts +9 -0
  244. package/dist/observability/principal-context.js +9 -0
  245. package/dist/observability/prompt-manifest.d.ts +37 -0
  246. package/dist/observability/prompt-manifest.js +35 -1
  247. package/dist/observability/rate-limit.d.ts +10 -0
  248. package/dist/observability/rate-limit.js +1 -0
  249. package/dist/observability/tool-trace.d.ts +24 -0
  250. package/dist/observability/tool-trace.js +41 -1
  251. package/dist/orchestration/hardened-vm-runner.d.ts +107 -0
  252. package/dist/orchestration/hardened-vm-runner.js +119 -4
  253. package/dist/orchestration/hardened-vm-worker-runner.d.ts +14 -0
  254. package/dist/orchestration/hardened-vm-worker-runner.js +26 -1
  255. package/dist/orchestration/hardened-vm-worker.js +27 -0
  256. package/dist/orchestration/subagent-steer.d.ts +44 -0
  257. package/dist/orchestration/subagent-steer.js +45 -1
  258. package/dist/orchestration/workflow-agent-steer.d.ts +54 -0
  259. package/dist/orchestration/workflow-agent-steer.js +80 -1
  260. package/dist/orchestration/workflow-completion-inbox.d.ts +189 -2
  261. package/dist/orchestration/workflow-completion-inbox.js +283 -32
  262. package/dist/orchestration/workflow-notify-journal.d.ts +132 -1
  263. package/dist/orchestration/workflow-notify-journal.js +187 -13
  264. package/dist/parked-decide.d.ts +61 -0
  265. package/dist/parked-decide.js +58 -1
  266. package/dist/per-task-image.d.ts +54 -0
  267. package/dist/per-task-image.js +41 -0
  268. package/dist/plan-cache-probe.d.ts +35 -0
  269. package/dist/plan-cache-probe.js +18 -3
  270. package/dist/plugins/approval-exemption-store.d.ts +7 -0
  271. package/dist/plugins/approval-exemption-store.js +28 -2
  272. package/dist/plugins/approval-store-sql.d.ts +64 -0
  273. package/dist/plugins/approval-store-sql.js +32 -0
  274. package/dist/plugins/background-agent-store-sql.d.ts +55 -0
  275. package/dist/plugins/background-agent-store-sql.js +91 -4
  276. package/dist/plugins/background-shell-support.d.ts +98 -0
  277. package/dist/plugins/background-shell-support.js +117 -13
  278. package/dist/plugins/blob-backend.d.ts +104 -0
  279. package/dist/plugins/blob-backend.js +163 -6
  280. package/dist/plugins/breaker-state-sql.d.ts +65 -1
  281. package/dist/plugins/breaker-state-sql.js +46 -8
  282. package/dist/plugins/caching-session-store.d.ts +42 -0
  283. package/dist/plugins/caching-session-store.js +63 -3
  284. package/dist/plugins/checkpoint-store-sql.d.ts +179 -0
  285. package/dist/plugins/checkpoint-store-sql.js +239 -11
  286. package/dist/plugins/file-outcome-sink.d.ts +4 -0
  287. package/dist/plugins/file-outcome-sink.js +9 -0
  288. package/dist/plugins/file-resume-anchor-store.d.ts +20 -0
  289. package/dist/plugins/file-resume-anchor-store.js +43 -4
  290. package/dist/plugins/file-run-store.d.ts +90 -0
  291. package/dist/plugins/file-run-store.js +145 -13
  292. package/dist/plugins/file-snapshot-store-sql.d.ts +133 -1
  293. package/dist/plugins/file-snapshot-store-sql.js +178 -10
  294. package/dist/plugins/file-workflow-journal-store.d.ts +10 -0
  295. package/dist/plugins/file-workflow-journal-store.js +10 -0
  296. package/dist/plugins/fork-routing-session-store.d.ts +47 -0
  297. package/dist/plugins/fork-routing-session-store.js +51 -3
  298. package/dist/plugins/host-platform.d.ts +69 -0
  299. package/dist/plugins/host-platform.js +81 -2
  300. package/dist/plugins/image-bake-store-sql.d.ts +136 -1
  301. package/dist/plugins/image-bake-store-sql.js +241 -7
  302. package/dist/plugins/image-index-sql.d.ts +46 -0
  303. package/dist/plugins/image-index-sql.js +113 -4
  304. package/dist/plugins/k8s-bg-scripts.d.ts +34 -0
  305. package/dist/plugins/k8s-bg-scripts.js +88 -4
  306. package/dist/plugins/k8s-exec-protocol.d.ts +33 -0
  307. package/dist/plugins/k8s-exec-protocol.js +41 -0
  308. package/dist/plugins/local-checkpoint-store.d.ts +40 -0
  309. package/dist/plugins/local-checkpoint-store.js +86 -7
  310. package/dist/plugins/local-session-store.d.ts +157 -0
  311. package/dist/plugins/local-session-store.js +289 -34
  312. package/dist/plugins/local-task-attachment-store.js +14 -2
  313. package/dist/plugins/mailbox-store-sql.d.ts +38 -0
  314. package/dist/plugins/mailbox-store-sql.js +39 -6
  315. package/dist/plugins/memory-engine-pg.d.ts +30 -0
  316. package/dist/plugins/memory-engine-pg.js +122 -4
  317. package/dist/plugins/memory-engine-tidb.d.ts +26 -0
  318. package/dist/plugins/memory-engine-tidb.js +115 -5
  319. package/dist/plugins/memory-engine-vector-util.d.ts +5 -0
  320. package/dist/plugins/memory-engine-vector-util.js +5 -0
  321. package/dist/plugins/memory-resume-anchor-store.d.ts +8 -0
  322. package/dist/plugins/memory-resume-anchor-store.js +17 -0
  323. package/dist/plugins/memory-run-store.d.ts +63 -0
  324. package/dist/plugins/memory-run-store.js +73 -8
  325. package/dist/plugins/memory-session-policy-store.d.ts +17 -0
  326. package/dist/plugins/memory-session-policy-store.js +17 -0
  327. package/dist/plugins/memory-sync-store-pg.d.ts +42 -0
  328. package/dist/plugins/memory-sync-store-pg.js +45 -2
  329. package/dist/plugins/memory-sync-store-tidb.d.ts +9 -0
  330. package/dist/plugins/memory-sync-store-tidb.js +31 -1
  331. package/dist/plugins/outcome-ledger-sql.d.ts +63 -0
  332. package/dist/plugins/outcome-ledger-sql.js +97 -3
  333. package/dist/plugins/pg-approval-store.d.ts +7 -0
  334. package/dist/plugins/pg-approval-store.js +7 -0
  335. package/dist/plugins/pg-breaker-state.d.ts +6 -0
  336. package/dist/plugins/pg-breaker-state.js +6 -0
  337. package/dist/plugins/pg-checkpoint-store.d.ts +8 -0
  338. package/dist/plugins/pg-checkpoint-store.js +8 -0
  339. package/dist/plugins/pg-cost-quota.d.ts +17 -0
  340. package/dist/plugins/pg-cost-quota.js +6 -0
  341. package/dist/plugins/pg-file-snapshot-store.d.ts +6 -0
  342. package/dist/plugins/pg-file-snapshot-store.js +6 -0
  343. package/dist/plugins/pg-image-bake.d.ts +9 -0
  344. package/dist/plugins/pg-image-bake.js +9 -0
  345. package/dist/plugins/pg-image-index.d.ts +9 -0
  346. package/dist/plugins/pg-image-index.js +9 -0
  347. package/dist/plugins/pg-outcome-ledger.d.ts +9 -0
  348. package/dist/plugins/pg-outcome-ledger.js +9 -0
  349. package/dist/plugins/pg-pool.d.ts +50 -0
  350. package/dist/plugins/pg-pool.js +78 -0
  351. package/dist/plugins/pg-query.d.ts +11 -0
  352. package/dist/plugins/pg-rate-limiter.d.ts +23 -0
  353. package/dist/plugins/pg-rate-limiter.js +12 -2
  354. package/dist/plugins/pg-resume-anchor-store.d.ts +5 -0
  355. package/dist/plugins/pg-resume-anchor-store.js +5 -0
  356. package/dist/plugins/pg-run-store.d.ts +7 -0
  357. package/dist/plugins/pg-run-store.js +7 -0
  358. package/dist/plugins/pg-safe-json.d.ts +13 -0
  359. package/dist/plugins/pg-safe-json.js +40 -4
  360. package/dist/plugins/pg-session-policy-store.d.ts +5 -0
  361. package/dist/plugins/pg-session-policy-store.js +5 -0
  362. package/dist/plugins/pg-session-storage.d.ts +72 -0
  363. package/dist/plugins/pg-session-storage.js +152 -20
  364. package/dist/plugins/pg-session-store.d.ts +10 -0
  365. package/dist/plugins/pg-session-store.js +10 -0
  366. package/dist/plugins/pg-tool-result-store.d.ts +7 -0
  367. package/dist/plugins/pg-tool-result-store.js +7 -0
  368. package/dist/plugins/pg-workflow-journal-store.d.ts +7 -0
  369. package/dist/plugins/pg-workflow-journal-store.js +7 -0
  370. package/dist/plugins/pg-workflow-run-store.d.ts +7 -0
  371. package/dist/plugins/pg-workflow-run-store.js +7 -0
  372. package/dist/plugins/posix-shell-fs.d.ts +3 -0
  373. package/dist/plugins/posix-shell-fs.js +31 -1
  374. package/dist/plugins/remote-env-adb.d.ts +25 -0
  375. package/dist/plugins/remote-env-adb.js +95 -12
  376. package/dist/plugins/remote-env-e2b.d.ts +146 -0
  377. package/dist/plugins/remote-env-e2b.js +371 -40
  378. package/dist/plugins/remote-env-file-error.d.ts +34 -0
  379. package/dist/plugins/remote-env-file-error.js +37 -0
  380. package/dist/plugins/remote-env-host.d.ts +151 -0
  381. package/dist/plugins/remote-env-host.js +468 -70
  382. package/dist/plugins/remote-env-k8s.d.ts +135 -0
  383. package/dist/plugins/remote-env-k8s.js +318 -32
  384. package/dist/plugins/remote-env-local-docker.d.ts +65 -0
  385. package/dist/plugins/remote-env-local-docker.js +149 -24
  386. package/dist/plugins/remote-env-ssh.d.ts +35 -0
  387. package/dist/plugins/remote-env-ssh.js +117 -20
  388. package/dist/plugins/remote-scratchpad.d.ts +38 -0
  389. package/dist/plugins/remote-scratchpad.js +32 -2
  390. package/dist/plugins/remote-shell.d.ts +22 -0
  391. package/dist/plugins/remote-shell.js +27 -1
  392. package/dist/plugins/resume-anchor-store-sql.d.ts +28 -0
  393. package/dist/plugins/resume-anchor-store-sql.js +11 -0
  394. package/dist/plugins/roster-store-sql.d.ts +27 -0
  395. package/dist/plugins/roster-store-sql.js +54 -0
  396. package/dist/plugins/run-store-sql.d.ts +194 -0
  397. package/dist/plugins/run-store-sql.js +210 -9
  398. package/dist/plugins/s3-presign.d.ts +20 -0
  399. package/dist/plugins/s3-presign.js +49 -2
  400. package/dist/plugins/scheduler-support.d.ts +12 -0
  401. package/dist/plugins/scheduler-support.js +75 -3
  402. package/dist/plugins/send-file-ledger.d.ts +15 -0
  403. package/dist/plugins/send-file-ledger.js +53 -4
  404. package/dist/plugins/send-user-file.d.ts +77 -0
  405. package/dist/plugins/send-user-file.js +92 -4
  406. package/dist/plugins/session-policy-store-sql.d.ts +15 -0
  407. package/dist/plugins/session-policy-store-sql.js +75 -3
  408. package/dist/plugins/session-store.d.ts +45 -0
  409. package/dist/plugins/session-store.js +51 -0
  410. package/dist/plugins/sql-driver.d.ts +77 -0
  411. package/dist/plugins/sql-driver.js +4 -0
  412. package/dist/plugins/sql-escape.d.ts +8 -0
  413. package/dist/plugins/sql-escape.js +8 -0
  414. package/dist/plugins/sql-row-helpers.d.ts +25 -0
  415. package/dist/plugins/sql-row-helpers.js +25 -0
  416. package/dist/plugins/store-backend.d.ts +103 -0
  417. package/dist/plugins/store-backend.js +120 -27
  418. package/dist/plugins/store-contracts.d.ts +62 -0
  419. package/dist/plugins/store-contracts.js +3 -0
  420. package/dist/plugins/task-attachment-store.d.ts +60 -0
  421. package/dist/plugins/task-attachment-store.js +49 -3
  422. package/dist/plugins/task-list-store-sql.d.ts +25 -0
  423. package/dist/plugins/task-list-store-sql.js +21 -0
  424. package/dist/plugins/tidb-approval-store.d.ts +6 -0
  425. package/dist/plugins/tidb-approval-store.js +6 -0
  426. package/dist/plugins/tidb-breaker-state.d.ts +5 -0
  427. package/dist/plugins/tidb-breaker-state.js +5 -0
  428. package/dist/plugins/tidb-checkpoint-store.d.ts +7 -0
  429. package/dist/plugins/tidb-checkpoint-store.js +7 -0
  430. package/dist/plugins/tidb-cost-quota.d.ts +6 -0
  431. package/dist/plugins/tidb-cost-quota.js +1 -0
  432. package/dist/plugins/tidb-file-snapshot-store.d.ts +6 -0
  433. package/dist/plugins/tidb-file-snapshot-store.js +6 -0
  434. package/dist/plugins/tidb-image-bake.d.ts +8 -0
  435. package/dist/plugins/tidb-image-bake.js +8 -0
  436. package/dist/plugins/tidb-image-index.d.ts +8 -0
  437. package/dist/plugins/tidb-image-index.js +8 -0
  438. package/dist/plugins/tidb-outcome-ledger.d.ts +10 -0
  439. package/dist/plugins/tidb-outcome-ledger.js +10 -0
  440. package/dist/plugins/tidb-pool.d.ts +56 -0
  441. package/dist/plugins/tidb-pool.js +181 -1
  442. package/dist/plugins/tidb-rate-limiter.d.ts +11 -0
  443. package/dist/plugins/tidb-rate-limiter.js +5 -2
  444. package/dist/plugins/tidb-resume-anchor-store.d.ts +5 -0
  445. package/dist/plugins/tidb-resume-anchor-store.js +5 -0
  446. package/dist/plugins/tidb-run-store.d.ts +7 -0
  447. package/dist/plugins/tidb-run-store.js +7 -0
  448. package/dist/plugins/tidb-session-policy-store.d.ts +5 -0
  449. package/dist/plugins/tidb-session-policy-store.js +5 -0
  450. package/dist/plugins/tidb-session-storage.d.ts +43 -0
  451. package/dist/plugins/tidb-session-storage.js +62 -3
  452. package/dist/plugins/tidb-session-store.d.ts +142 -0
  453. package/dist/plugins/tidb-session-store.js +264 -16
  454. package/dist/plugins/tidb-tool-result-store.d.ts +5 -0
  455. package/dist/plugins/tidb-tool-result-store.js +7 -0
  456. package/dist/plugins/tidb-workflow-journal-store.d.ts +7 -0
  457. package/dist/plugins/tidb-workflow-journal-store.js +7 -0
  458. package/dist/plugins/tidb-workflow-run-store.d.ts +8 -0
  459. package/dist/plugins/tidb-workflow-run-store.js +8 -0
  460. package/dist/plugins/tool-result-store-sql.d.ts +58 -0
  461. package/dist/plugins/tool-result-store-sql.js +38 -2
  462. package/dist/plugins/web-search.d.ts +35 -0
  463. package/dist/plugins/web-search.js +45 -9
  464. package/dist/plugins/workflow-journal-limits.d.ts +10 -0
  465. package/dist/plugins/workflow-journal-limits.js +10 -0
  466. package/dist/plugins/workflow-journal-store-sql.d.ts +78 -0
  467. package/dist/plugins/workflow-journal-store-sql.js +58 -2
  468. package/dist/plugins/workflow-run-store-sql.d.ts +84 -0
  469. package/dist/plugins/workflow-run-store-sql.js +84 -6
  470. package/dist/plugins/worktree-isolation.d.ts +45 -0
  471. package/dist/plugins/worktree-isolation.js +105 -6
  472. package/dist/plugins/write-behind-counter.d.ts +56 -1
  473. package/dist/plugins/write-behind-counter.js +53 -14
  474. package/dist/principal-jwt.d.ts +24 -0
  475. package/dist/principal-jwt.js +60 -5
  476. package/dist/project-memory.d.ts +22 -0
  477. package/dist/project-memory.js +144 -15
  478. package/dist/prompts-domain-validate.d.ts +28 -0
  479. package/dist/prompts-domain-validate.js +42 -1
  480. package/dist/question.d.ts +33 -0
  481. package/dist/question.js +69 -2
  482. package/dist/resource-suspend.d.ts +21 -0
  483. package/dist/resource-suspend.js +16 -0
  484. package/dist/router/route-orchestration.d.ts +78 -0
  485. package/dist/router/route-orchestration.js +77 -0
  486. package/dist/run-local.d.ts +32 -0
  487. package/dist/run-local.js +172 -8
  488. package/dist/runs.d.ts +189 -4
  489. package/dist/runs.js +465 -24
  490. package/dist/runtime-caps-resolver.d.ts +106 -0
  491. package/dist/runtime-caps-resolver.js +89 -4
  492. package/dist/runtime-governance.d.ts +84 -0
  493. package/dist/runtime-governance.js +127 -1
  494. package/dist/sandbox-pkg-source.d.ts +23 -0
  495. package/dist/sandbox-pkg-source.js +37 -0
  496. package/dist/sealed-key.d.ts +54 -0
  497. package/dist/sealed-key.js +68 -3
  498. package/dist/security.d.ts +108 -0
  499. package/dist/security.js +145 -6
  500. package/dist/sema-registry.d.ts +21 -0
  501. package/dist/sema-registry.js +21 -0
  502. package/dist/session-leaf-bus.d.ts +31 -0
  503. package/dist/session-leaf-bus.js +32 -0
  504. package/dist/session-sync-content.d.ts +46 -0
  505. package/dist/session-sync-content.js +47 -1
  506. package/dist/session-sync-kernel.d.ts +89 -0
  507. package/dist/session-sync-kernel.js +48 -3
  508. package/dist/session-sync.d.ts +125 -0
  509. package/dist/session-sync.js +181 -8
  510. package/dist/session-titler.d.ts +26 -0
  511. package/dist/session-titler.js +41 -7
  512. package/dist/session-watch.d.ts +53 -1
  513. package/dist/session-watch.js +73 -9
  514. package/dist/sighup-idle.d.ts +30 -0
  515. package/dist/sighup-idle.js +12 -1
  516. package/dist/spec-fields.d.ts +91 -3
  517. package/dist/spec-fields.js +116 -4
  518. package/dist/task-cwd.d.ts +50 -0
  519. package/dist/task-cwd.js +68 -1
  520. package/dist/task-mcp.d.ts +47 -0
  521. package/dist/task-mcp.js +29 -0
  522. package/dist/task-settings.d.ts +175 -0
  523. package/dist/task-settings.js +226 -11
  524. package/dist/task-workflow.d.ts +67 -0
  525. package/dist/task-workflow.js +75 -8
  526. package/dist/tool-approval.d.ts +91 -0
  527. package/dist/tool-approval.js +215 -0
  528. package/dist/trace/artifacts.d.ts +9 -0
  529. package/dist/trace/artifacts.js +30 -5
  530. package/dist/trace/core-keyset-guard.d.ts +18 -0
  531. package/dist/trace/ledger-sink.d.ts +43 -0
  532. package/dist/trace/ledger-sink.js +64 -5
  533. package/dist/trace/project.d.ts +133 -0
  534. package/dist/trace/project.js +189 -2
  535. package/dist/trace/redact.d.ts +19 -0
  536. package/dist/trace/redact.js +66 -9
  537. package/dist/usage-analytics.d.ts +26 -0
  538. package/dist/usage-analytics.js +26 -3
  539. package/package.json +1 -1
@@ -1,3 +1,9 @@
1
+ /**
2
+ * design/158 A9 域模块 —— D-1 通用文件附件面(`/v1/attachments`:上传/取回/删除三动词)。
3
+ *
4
+ * owner 门无 oracle(未知与他人同答 404,与 notify 门同姿);上限=server 权威(reject-not-OOM);
5
+ * mime 白名单是部署策略旋钮不是安全开关。本域零可变状态。
6
+ */
1
7
  import { createHash } from "node:crypto";
2
8
  import { uuidv7, sanitizePathComponent } from "@sema-agent/core";
3
9
  import { HttpError } from "../../security.js";
@@ -8,11 +14,19 @@ export async function handleAttachments(req, res, url, ctx) {
8
14
  await handleAttachmentsBody(req, res, url, ctx, miss);
9
15
  return !miss.fell;
10
16
  }
17
+ /** 路由体 = 从 `server.ts` 的 `handle()` 里**整段剪切**过来的原文(唯一改动:统一去缩进两格)。裸 `return;`
18
+ * 的语义原样 =「本域已应答」;走到函数尾才是「没匹配上」,置 `miss.fell` 交回装配器继续下一个域。
19
+ * 跨域的东西(deps / 助手 / 单域状态 / 每请求量)一律在首行解构出来,于是下面每一行都逐字不变。 */
11
20
  async function handleAttachmentsBody(req, res, url, ctx, miss) {
12
21
  const { deps } = ctx;
13
22
  const { rateLimited, quotaExceeded, safeDecode, readRawBody } = ctx.helpers;
23
+ // D-1 通用文件上传(clay 拍 2026-07-27:独立附件 store)——上传/取回/删除三动词。
24
+ // 语义:上传先行拿句柄 → TaskRequest.attachments 引用绑定(main.ts resolveSpec 半场)→ env 建立
25
+ // 时物化到执行环境(远程 lane factory 包装 / host lane 提交时直写)。owner 门无 oracle(未知与
26
+ // 他人同答 404,notify 门同姿);上限=server 权威(reject-not-OOM,sync-blob 同姿);
27
+ // mime 白名单是部署策略旋钮非安全开关(声明 mime 不可验证;真防线=尺寸上限+沙箱内消费)。
14
28
  {
15
- const am = /^\/v1\/attachments(?:\/([^/?]+))?$/.exec(url);
29
+ const am = /^\/v1\/attachments(?:\/([^/?]+))?$/.exec(url); // NB: `url` 已剥 query(:1017),参数读 req.url
16
30
  if (am) {
17
31
  if (rateLimited(req, res) || quotaExceeded(req, res))
18
32
  return;
@@ -29,14 +43,17 @@ async function handleAttachmentsBody(req, res, url, ctx, miss) {
29
43
  const owner = principal ?? "default";
30
44
  const attId = am[1] !== undefined ? safeDecode(am[1]) : undefined;
31
45
  if (attId === undefined && req.method === "POST") {
32
- const q = new URL(req.url ?? "", "http://x").searchParams;
46
+ // ── 上传:POST /v1/attachments?name=<urlencoded>,raw body,content-type=声明 mime ──
47
+ const q = new URL(req.url ?? "", "http://x").searchParams; // `url` 已剥 query
33
48
  const rawName = q.get("name");
49
+ // 消毒:剥路径段(两种分隔符)取 basename,截长,再过 core 的组件验证器(throw 形——不合法
50
+ // 即拒;此处先自检同一规则把「用户给了个烂名」按 400 答而不是 500)。
34
51
  const base = ((rawName ?? "").split(/[/\\]/).filter(Boolean).pop() ?? "").slice(0, 128);
35
52
  if (!rawName || base === "" || base === "." || base === ".." || !/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(base)) {
36
53
  sendError(res, 400, "request.query_invalid", "query param `name` is required and must reduce to a safe basename ([A-Za-z0-9._-], not starting with a dot)");
37
54
  return;
38
55
  }
39
- const name = sanitizePathComponent(base);
56
+ const name = sanitizePathComponent(base); // 双保险:与 core 文件店同一验证器(不合法=上面已 400,这里恒过)
40
57
  const mime = String(req.headers["content-type"] ?? "").split(";")[0].trim().toLowerCase();
41
58
  if (!/^[a-z0-9!#$&^_.+-]+\/[a-z0-9!#$&^_.+-]+$/.test(mime) || mime.length > 128) {
42
59
  sendError(res, 400, "request.query_invalid", "content-type must be a well-formed mime type (type/subtype)");
@@ -50,7 +67,7 @@ async function handleAttachmentsBody(req, res, url, ctx, miss) {
50
67
  const max = deps.config.attachmentMaxBytes ?? 32 * 1024 * 1024;
51
68
  let body;
52
69
  try {
53
- body = await readRawBody(req, max);
70
+ body = await readRawBody(req, max); // 413s mid-stream(reject-not-OOM)
54
71
  }
55
72
  catch (err) {
56
73
  if (err instanceof HttpError && err.status === 413) {
@@ -83,6 +100,7 @@ async function handleAttachmentsBody(req, res, url, ctx, miss) {
83
100
  res.writeHead(200, {
84
101
  "content-type": meta.mime,
85
102
  "content-length": String(bytes.byteLength),
103
+ // RFC 5987 编码名(name 已消毒为安全 basename,URL 编码后恒 header-safe)
86
104
  "content-disposition": `attachment; filename*=UTF-8''${encodeURIComponent(meta.name)}`,
87
105
  });
88
106
  res.end(Buffer.from(bytes));
@@ -1,3 +1,10 @@
1
+ /**
2
+ * design/158 A9 域模块 —— 能力/场景/模型目录只读面。
3
+ *
4
+ * 路由:`GET /v1/capabilities/scenarios/:name`、`GET /v1/capabilities`、`GET /v1/models`。
5
+ * 三条都在全局 service-credential 门**之后**(config 面非密只读),装配表里的位置必须保住这一点。
6
+ * 本域零可变状态;deps 面宽(能力布尔逐条对应各路由的 501 门,单源不许漂移)但全是存在性只读。
7
+ */
1
8
  import type { IncomingMessage, ServerResponse } from "node:http";
2
9
  import type { RouteCtx } from "../route-ctx.js";
3
10
  export declare function handleCapabilities(req: IncomingMessage, res: ServerResponse, url: string, ctx: RouteCtx): Promise<boolean>;
@@ -7,29 +7,56 @@ export async function handleCapabilities(req, res, url, ctx) {
7
7
  await handleCapabilitiesBody(req, res, url, ctx, miss);
8
8
  return !miss.fell;
9
9
  }
10
+ /** 路由体 = 从 `server.ts` 的 `handle()` 里**整段剪切**过来的原文(唯一改动:统一去缩进两格)。裸 `return;`
11
+ * 的语义原样 =「本域已应答」;走到函数尾才是「没匹配上」,置 `miss.fell` 交回装配器继续下一个域。
12
+ * 跨域的东西(deps / 助手 / 单域状态 / 每请求量)一律在首行解构出来,于是下面每一行都逐字不变。 */
10
13
  async function handleCapabilitiesBody(req, res, url, ctx, miss) {
11
14
  const { deps } = ctx;
15
+ // E5 定稿:场景详情只读端点——web 专家模式渲染工具面选项+提示词概览。source 语义=selectScenario
16
+ // 实际取用的定义(main.ts 组装时 center 条目与 overlay 同判定源盖同名,约定①)。鉴权=与 /v1/capabilities
17
+ // 同门(全局 service-credential 门后,config 面非密);未知名 404 typed code(人话归壳/web)。
12
18
  if (req.method === "GET" && url.startsWith("/v1/capabilities/scenarios/")) {
13
19
  const name = url.slice("/v1/capabilities/scenarios/".length).split("?")[0];
14
20
  const detail = deps.scenarioDetails?.[name];
15
21
  if (!detail) {
22
+ // [939] 信封统一:本路曾是全站唯一对象形 error(`{error:{code}}`)——SDK toApiError 对它特判过一轮
23
+ // TypeError 加固。统一为「字符串 error + 顶层 errorCode」邻位形(cancel/decide 同款),机器判据保留。
16
24
  sendError(res, 404, "scenario_not_found", "scenario not found");
17
25
  return;
18
26
  }
19
27
  sendJson(res, 200, detail);
20
28
  return;
21
29
  }
30
+ // Capability discovery: one call tells a consumer which surfaces this worker has,
31
+ // instead of probing each verb for a 501. Open set — unknown keys must be ignored by consumers.
32
+ // Auth'd like /v1/models (config surface, non-secret). Booleans derive from the SAME deps that gate
33
+ // the routes, so this can never drift from actual 501 behavior.
22
34
  if (req.method === "GET" && url === "/v1/capabilities") {
35
+ // Deployment bag first, derived booleans LAST: the bag extends the set but can never shadow the
36
+ // route-gating truths (a config typo must not make capabilities lie about what 501s).
23
37
  sendJson(res, 200, {
24
38
  ...deps.capabilities,
25
39
  asyncRuns: Boolean(deps.runStore),
26
40
  artifacts: Boolean(deps.runStore),
41
+ // TRUE when durable HITL can FIRE = checkpointStore present (DURABLE_APPROVAL=true): it mounts
42
+ // AskUserQuestion-suspend + the approval center + resumable checkpoints, independent of whether any
43
+ // TOOL is gated (APPROVAL_REQUIRE = the additive F4 layer). Legacy poll-gate approvalStore does NOT
44
+ // count: alone it can't suspend (the P2-preflight lie).
27
45
  approvals: Boolean(deps.checkpointStore),
28
46
  sessions: Boolean(deps.sessionAudit),
47
+ // [1196] session 级 SSE 订阅面:与 /v1/sessions/:id/events 的 501 谓词同源(sessionWatch 只在
48
+ // sessionStorage 具备 getLeafId/ownerOf 时由 main.ts 构建)——web 据此换轨,false=回落 /head 轮询。
29
49
  sessionEvents: Boolean(deps.sessionWatch && deps.sessionStorage?.getLeafId && deps.sessionStorage?.ownerOf),
50
+ // #13([1871] web asks,clay 排批 2026-07-27):fleet 面能力族——一个诚实对象或 false(无 fleetBus=
51
+ // 无 /v1/fleet/stream,路由 501 同谓词)。`resume:"snapshot"` 是刻意的语义广告而非搪塞:总线是
52
+ // latest-state 不是事件日志,**每次连接开头就是全量 snapshot 帧** ⇒ 重连=重快照,行状态不存在
53
+ // 「丢帧」;通知帧(bg_notification)另有 durable inbox 兜底重投。做 last-event-id 重放缓冲=与
54
+ // snapshot 机制重复建设,收益为零(SDK streamFleet 的「NOT RESUMABLE」旧自述按此口径改写)。
55
+ // `steerPriority:"advisory"` 诚实:steer body.priority 收下+枚举校验但 no-op(E15,候 core 队列 seam)。
30
56
  fleet: deps.fleetBus
31
57
  ? { stream: true, sessionScope: true, observe: true, resume: "snapshot", bgNotifyFailClosed: true, steerPriority: "advisory" }
32
58
  : false,
59
+ // #3 workspace 浏览面([1894]④:与 fleet 同姿势——对象=面在场,false=501 同谓词)。
33
60
  workspace: (() => {
34
61
  const wfs = deps.fileSnapshotStore;
35
62
  return wfs && typeof wfs.listKeys === "function" && typeof wfs.exportManifest === "function" && typeof wfs.getBlob === "function" && Boolean(deps.sessionStorage?.ownerOf)
@@ -37,57 +64,216 @@ async function handleCapabilitiesBody(req, res, url, ctx, miss) {
37
64
  : false;
38
65
  })(),
39
66
  leader: Boolean(deps.leaderEndpoint),
67
+ // design/138 S1 (clay 2026-07-08): the legacy MemoryStore surface (GET/DELETE /v1/memory + the MF-30
68
+ // session write verbs) was DEPRECATED with the store itself — the new memory engine is model file skills
69
+ // over the injected memory dir, with NO service HTTP verbs. Hard-coded false so a shell that still knows
70
+ // the old caps honestly hides the affordances (the adaptation was pre-announced).
40
71
  memory: false,
41
72
  memoryWrite: false,
73
+ // CLI surfaces: /v1/policy is always served (config surface); /v1/usage returns real
74
+ // cumulative spend only when a per-principal quota is configured (else enabled:false).
42
75
  policy: true,
43
76
  usage: Boolean(deps.costQuota),
77
+ // E5 (shell-host contract): permission-mode WRITE is not a cloud-worker capability. Autonomy is
78
+ // compile-time tighten-only + worker-global config (a cloud supervisor shell CANNOT change server-side
79
+ // gating, ~L2075; "autonomy is CONFIG, not steer", core checkpoint-store.ts:513). The READ side is served
80
+ // honestly via GET /v1/policy (PolicyInfo.autonomy). A runtime per-session mutation verb + mode_changed push
81
+ // need a core seam (SERVICE-GAP-DOSSIER §2 row 5) — advertise false so the shell keeps a read-only mode
82
+ // banner instead of a 501-able write affordance ("says yes but 501s" must be impossible).
44
83
  permissionModeWrite: false,
84
+ // E7 (shell-host contract): model selection (body.model) + reasoning-effort selection
85
+ // (body.reasoningEffort→TaskSpec.thinking) are accepted on every task request → both true.
86
+ // 🔴 CORRECTION (2026-07-25, blackboard [1664]→[1668]): this used to say "the RESOLVED effectiveModel ECHO
87
+ // is a separate, still-core-blocked cap (SERVICE-GAP-DOSSIER §2 row 7)". THAT WAS WRONG, and it was wrong in
88
+ // an instructive way — the capability exists, it just isn't SPELLED `effectiveModel`. core's `TaskResult.model`
89
+ // (core `src/core/types.ts:1871`, design/99 MF-25) is documented verbatim as "the EFFECTIVE model id that
90
+ // served this task — the RESOLVED `Model.id`, not the requested `TaskSpec.model` ref … Lets a UI echo
91
+ // 'served by X'". A grep for the identifier `effectiveModel` returns zero hits in core and that was mistaken
92
+ // for "core doesn't have it" (search by SEMANTICS, not by identifier name). It already reaches the wire:
93
+ // `POST /v1/tasks` returns the TaskResult verbatim (~L1852), the SDK declares `TaskResult.model`, and this
94
+ // server already consumes it internally for cache-family accounting (~L1843). Pinned by
95
+ // `test/effective-model-echo-wire.test.ts` (real HTTP: resolved id echoed, absent key stays absent) so a
96
+ // future projection/whitelist on this leg can't silently drop it — the `toolEndEventData`-label bug class.
97
+ // Nothing is advertised as a capability BIT here because an additive result field needs no gate
98
+ // (gate-don't-trial-by-501 governs endpoints/verbs, not additive response fields).
45
99
  modelSelection: true,
46
100
  effortSelection: true,
101
+ // E1 (shell-host contract): tool_end now carries the model-facing `output` (core 1.121.0) — wired onto the durable +
102
+ // live + replay streams (redacted at every boundary). E2: content events carry `eventId` (+ `parentToolCallId`
103
+ // for sub-agent tasks). Both true now that the pinned core emits them and the service threads them through.
47
104
  toolOutput: true,
48
105
  messageIdentity: true,
106
+ // C1/C2 (core 1.219): `forwardSubagentEvents` = body flag accepted (a delegated child's live
107
+ // content events ride the run stream, parentToolCallId-attributed); `subagentSteer` = the
108
+ // POST /v1/runs/:id/subagents/:target/steer verb routes (requires the run store the route 501s without —
109
+ // same derive-from-deps discipline as the rest of this block; the registry itself is always constructed).
49
110
  forwardSubagentEvents: true,
111
+ // G3([820]③):TaskRequest.scratchpadDir 壳供半场已接(env-facts.acceptShellScratchpadDir 验收门;
112
+ // 单用户 + host lane 生效,拒收形回落自算)。TRUE=键会被消费(而非静默丢),不是「必然生效」。
50
113
  scratchpadDir: true,
51
114
  subagentSteer: Boolean(deps.subagentSteerRegistry) && Boolean(deps.runStore),
115
+ // design/122 (core 1.225): body.retainSubagentSessions accepted + POST /v1/runs/:id/subagents/:target/resume
116
+ // routes (same gate as steer — the verbs share the registry + run store; retain-off runs 409 resume.retain_off).
52
117
  subagentResume: Boolean(deps.subagentSteerRegistry) && Boolean(deps.runStore),
118
+ // TaskRequest.settings (client per-request SemaSettings stamp) → projected into the engine TIGHTEN-ONLY
119
+ // (deny-wins, after the deployment + operator baseline). v1 wires permissions + permissionMode (default/
120
+ // acceptEdits/plan — `bypassPermissions` is NEVER honored from settings) + model + outputStyle. `env` is
121
+ // DEFERRED (TaskSpec deliberately has no per-task env injection) — advertised here so the client never
122
+ // silently loses a setting (it can warn the user / withhold those fields).
123
+ // `hooks`(hook-runner 阶段一):TRUE 当本部署会真跑 hook 命令 = 单用户闸(hook 命令跑在
124
+ // worker host,class ② 能力授予;resolveSpec 的 taskHooks 装配同一谓词)。多租户 = false(收到警告忽略)。
53
125
  taskSettings: { permissions: true, permissionMode: true, model: true, outputStyle: true, env: false, hooks: deps.config.requirePrincipal !== true },
126
+ // [1476] R1 / [1478] R2: TaskRequest.appendSystemPrompt is accepted top-level → TaskSpec.appendSystemPrompt
127
+ // (first-class lane for the shell's product-knowledge block). A shell probes THIS flag: false/absent ⇒ fall
128
+ // back to the settings.outputStyle ride-along (older servers fold that into the same spec field).
54
129
  appendSystemPrompt: true,
130
+ // [1479]① TaskRequest.compactionModel → TaskSpec.compactionModel (design/145 cheap compaction gear;
131
+ // catalog-gated like body.model). Probe this before offering the picker — older servers drop the field.
55
132
  compactionModel: true,
133
+ // [1488]③(b): GET /v1/runs/:id/subagents/:handle/output — a BACKGROUND child's (a… agent handle) final
134
+ // report body + status via the core TaskRegistry (the TaskOutput-tool face over HTTP; bg children are
135
+ // never in the run store and bg_notification only carries a summary). background_agent ONLY (codex R1
136
+ // type gate — wa… workflow rows read via the workflow journal). Replica-local like steer.
56
137
  subagentOutput: Boolean(deps.subagentTaskOutput) && Boolean(deps.runStore),
138
+ // S2([1520]{core},server 1.251): GET /v1/runs/:id/subagents/:handle/stream — per-agent live tail
139
+ // (SSE;core 1.370 bgAgentId 路由键)。「replay+tail」的 tail 半场(replay=subagentOutput 面);
140
+ // live 帧 replica-local(帧只在宿主 run 所在副本产生),meta 帧如实声明。同门同寻址同 404 形。
57
141
  subagentStream: Boolean(deps.subagentTaskOutput) && Boolean(deps.runStore),
142
+ // [1499] CC TaskOutput/TaskStop 人侧对位: GET/POST /v1/runs/:id/tasks/:handle/{output,stop} — the
143
+ // GENERIC background task-handle verbs (b* bash stdout consuming the cursor, m* monitor batches, a*
144
+ // agent final report; workflow handles refused — journal face owns them). SESSION-enforced from birth
145
+ // (?session= required on a session-bound run). Replica-local like subagentOutput.
58
146
  taskHandles: Boolean(deps.taskHandleOutput) && Boolean(deps.taskHandleStop) && Boolean(deps.runStore),
147
+ // [876] per-task subagents (core 1.295 body.agents → TaskSpec.agents): honored on SINGLE-USER deployments
148
+ // only — multi-tenant has no per-tenant caps face yet, so it's fail-closed there (resolveSpec warns +
149
+ // ignores; same predicate as mcpInjection/hooks so the shell never pretends its agent bundle took effect).
150
+ // ⚠️ Semantics = "the HTTP face accepts + forwards the field", NOT "every scenario honors it": scenarios
151
+ // without a delegation tool (scan/oa/…) fail-loud in core prepare (`config.agents.no_delegation_tool`) —
152
+ // a per-scenario projection needs the capability face to know the requested scenario (it doesn't; next batch).
59
153
  taskAgents: deps.config.requirePrincipal !== true,
154
+ // [854]② body.retainBackgroundProcesses → TaskSpec.retainBackgroundProcesses: a resource-residency grant
155
+ // (task-end keeps session bg processes alive), single-user gate like backgroundShell/hooks — multi-tenant
156
+ // warns + ignores, advertised false here so the shell greys the affordance.
157
+ // ⚠️ Best-effort per env lifecycle: on an isolated env destroyed at task end (e2b/k8s/local-docker/ephemeral
158
+ // host) core skips retention (`ownedEnvDying`, dist-read) — the grant only means anything where the env outlives the task.
60
159
  retainBackgroundProcesses: deps.config.requirePrincipal !== true,
160
+ // [922]①/[915]② core 1.296 interactiveTools 三态旋钮经 body 透传(per-run 工具面选择,无租户门)——
161
+ // 壳 capability 探测门用(旧 server 剥字段,壳 fail-soft 白发;此旗=真转发)。
61
162
  interactiveTools: true,
163
+ // [#40 / TOC cwd seam] TRUE when this deployment HONORS a caller-supplied `cwd` (the agent's host workspace =
164
+ // the TOC launch dir) — only the single-user `host` lane (task-cwd.ts cwdHonored). FALSE on cloud/container
165
+ // lanes + multi-tenant (cwd ignored there) so the shell never pretends `sema` operates on the project dir.
166
+ // Also gates `body.additionalDirectories` (CC --add-dir, design/119) — SAME host-lane trust boundary (extra
167
+ // host paths the file tools may read), so one flag covers both project-context host seams (no fragmentation).
62
168
  projectContext: cwdHonored(deps.config),
169
+ // [R3 / TOC MCP seam] TRUE when this deployment HONORS a caller-supplied `mcpServers` (the TOC local
170
+ // `.mcp.json`) — any SINGLE-USER deployment (task-mcp.ts mcpInjectionHonored = `requirePrincipal!==true`), on
171
+ // ANY execution lane. FALSE on multi-tenant (per-request MCP ignored) so the shell never pretends its `.mcp.json` took effect.
63
172
  mcpInjection: mcpInjectionHonored(deps.config),
173
+ // E8 (shell-host contract): per-model usage echo on TaskStats.modelUsage — sourced from durable model_usage events,
174
+ // so it requires BOTH the durable run store AND the tracker that feeds them (a store-without-
175
+ // tracker deploy would otherwise lie). Absent either → the shell shows aggregate cost only.
64
176
  modelUsage: Boolean(deps.runStore && deps.modelUsage),
177
+ // E11 (shell-host contract): GET /v1/sessions/:id/init startup bundle. Pure config assembly (model+mode), always
178
+ // served (no 501 path) — safe unconditionally, like policy:true.
65
179
  sessionInit: true,
180
+ // E9 (shell-host contract): GET /v1/sessions/:id/mcp materializes MCP server status on demand. The route is always
181
+ // served (returns an empty panel when no MCP is configured), so the query capability is unconditional.
66
182
  mcp: true,
183
+ // E23 (shell-host contract): inbound MCP elicitation HITL — true ONLY when the onElicit producing path is wired
184
+ // (MCP_ELICITATION_ENABLED), so "says yes but no-ops" is impossible. Per-server opt-in (McpServerSpec.
185
+ // elicitation, default OFF) is the second, orthogonal gate; this flag advertises the deployment capability.
186
+ // SCOPE: elicitation fires only on the streaming + durable run legs (POST /v1/tasks/stream, POST /v1/runs,
187
+ // and a durable resume) — a synchronous POST /v1/tasks, a verify/cascade attempt, and leader sub-tasks have
188
+ // no live stream to surface a prompt on, so an elicitation there fail-closed DECLINES (honest, not a hang).
67
189
  mcpElicitation: Boolean(deps.elicitation),
190
+ // §4④: AskUserQuestion LIVE HITL — true ONLY when the onQuestion producing path is wired
191
+ // (ASK_QUESTION_ENABLED). Same SCOPE as mcpElicitation (streaming + durable legs; a synchronous /v1/tasks or a
192
+ // sub-task with no live stream headless-defaults — honest, not a hang). The durable-disconnected-human leg is
193
+ // always available (createDurableQuestionPolicy on the durable path), independent of this live capability.
68
194
  askUserQuestion: Boolean(deps.question),
195
+ // [816]/[820]②: live tool-approval HITL — true ONLY when the onAsk producing path is wired
196
+ // (TOOL_APPROVAL_ENABLED). LIVE sync-stream leg only; since [879] G1 (OnAsk 三值化) every other leg
197
+ // (no ALS context / undeliverable card) returns "unavailable" → core durable-parks where a checkpoint
198
+ // exists, and only fail-closed denies without one ([819]⑤). The durable-approval leg (checkpoint park +
199
+ // /decide) is independent of this.
69
200
  toolApproval: Boolean(deps.toolApproval),
201
+ // [1469] POST /v1/side-query(core 1.361 Runner.sideQuery 包装):一次性 brain 路由问答,无 session
202
+ // 副作用。恒可用(runner 自带)——探测位供壳判「引擎腿在」而非 trial-by-404。
70
203
  sideQuery: true,
204
+ // E16/E17/E21 (§0.5 session-ownership): list/fork/delete are homed on the durable SESSION abstraction.
205
+ // Each flag is true ONLY when its PRODUCING path exists (never a bare const) — list needs an enumerator
206
+ // (session store OR legacy run-store aggregate), fork needs sessionStorage.fork, delete needs the
207
+ // purgeSession coordinator. Absent backend (in-memory dev) ⇒ false, so "says yes but 501s" can't happen.
71
208
  sessionList: Boolean(deps.sessionStorage?.listSessions ?? deps.runStore?.listSessions),
72
- sessionSearch: Boolean(deps.sessionStorage?.listSessions ?? deps.runStore?.listSessions),
209
+ sessionSearch: Boolean(deps.sessionStorage?.listSessions ?? deps.runStore?.listSessions), // GET /v1/sessions?q= (all lister backends carry it)
73
210
  sessionFork: Boolean(deps.sessionStorage?.fork),
74
211
  sessionDelete: Boolean(deps.purgeSession),
212
+ // E18 (shell-host contract): resume-at (rewind to a prior message). True ONLY when BOTH the eventId→entryId anchor map
213
+ // (resumeAnchorStore) AND the leaf-read path (sessionStorage.getLeafId, the §0.5 durable session abstraction)
214
+ // exist — so a `resumeAt` submit can be resolved + captured. "Says yes but 4xx/no-ops" is impossible. Works
215
+ // local + cloud (the anchor store is present on all backends); false only on the env-only/no-backend worker.
75
216
  resumeAt: Boolean(deps.resumeAnchorStore && deps.sessionStorage?.getLeafId),
217
+ // E12 (shell-host contract): opt-in post-completion prompt suggestions (body.suggestNextPrompts → a `suggestions` event
218
+ // on the run's events tail). A core 1.128 runner feature, no store dependency → always available on a worker.
76
219
  promptSuggestions: true,
220
+ // E6 (shell-host contract): operator-tightened per-session tool rules (PUT/GET /v1/sessions/:id/policy + core reads them
221
+ // at prepare-time, subtract-only). True when the durable/local SessionPolicyStore is wired.
77
222
  sessionPolicy: Boolean(deps.sessionPolicyStore),
223
+ // E19 (shell-host contract): rewind-files (body.rewindFiles → snapshot per turn + restore on a resumeAt branch). core's
224
+ // gate-split (1.134.0) snapshots for ANY ExecutionEnv when fileSnapshotStore is wired (host/local-mode +
225
+ // e2b/k8s/ssh/adb/local-docker all active) → advertise whenever the store is wired.
78
226
  rewindFiles: Boolean(deps.fileSnapshotStore),
227
+ // R8 code-only rewind (CC "Restore code", core 1.166 body.rewindFilesTo → restore files to a prior user message
228
+ // WITHOUT forking). Needs BOTH the snapshot store (to restore) AND the anchor map (to resolve the target handle),
229
+ // so it's the conjunction of `rewindFiles` and `resumeAt` — "says yes ⟺ the code-only submit resolves + restores".
79
230
  rewindFilesTo: Boolean(deps.fileSnapshotStore && deps.resumeAnchorStore && deps.sessionStorage?.getLeafId),
231
+ // R7 自唤醒 (CC parity): the self-wake scheduler is LIVE — the host env exposes core's SchedulerCapability
232
+ // (CronCreate/CronDelete/CronList mount——L8 订正旧名) and the TOC shell daemon should run to fire due intents. True
233
+ // only on the single-user host lane with SCHEDULER_ENABLED (multi-tenant routes scheduling to center).
80
234
  scheduler: Boolean(deps.config.schedulerEnabled && deps.config.requirePrincipal !== true && deps.config.remoteExec?.provider === "host"),
235
+ // 2c session-sync (P1d): the /v1/sessions/:id/sync/* peer routes (manifest/blobs/import/plan). True only when
236
+ // the whole backend + the entry export seam + a snapshot store are all wired (so export/import + blob transfer
237
+ // all resolve) — absent backend ⇒ false (the routes 501); "says yes ⟺ route works".
81
238
  sessionSync: Boolean(deps.backend && deps.sessionStorage?.exportEntries && deps.fileSnapshotStore),
239
+ // SendUserFile(S3 双轨公网直链,契约 settled 2026-07-14):flag=READY 语义(F7 codex 审)——
240
+ // emitter 存在(=工具真挂载,lane/租户/签发面三门在 main.ts 已判)∧ 公网端点在场(publicEndpoint
241
+ // 缺席时 issue()/prepareDirectUpload() 一律 fail-loud,工具挂着也必失败)。"says yes ⟺ 调用真能
242
+ // 成功":只看 config.sendUserFile(签发面已配)会在工具缺席的形态(adb/local-docker lane、多租户
243
+ // host/ssh)假 yes(配置自查 agent 抓获 2026-07-14);只看 emitter 会在无公网端点时假 yes。
244
+ // s3PublicEndpoint=web 渲染/拼接要的公网 base(bootstrap 单一真源判决——server 透出,web 不猜、
245
+ // 不走 registry env 双源;工具挂不挂载它都照透——纯感知面,web 可提前接线)。
82
246
  sendUserFile: Boolean(deps.sendUserFile && deps.config.sendUserFile?.publicEndpoint),
83
247
  s3PublicEndpoint: deps.config.sendUserFile?.publicEndpoint ?? null,
248
+ // SendUserFile 账本(多租户治理面):true ⇔ 签发面已配 + store backend 在(记账写点活 + GET
249
+ // /v1/sendfile-links 可列)。false = env-only worker(不记账,读面 501)——诚实缺席。
84
250
  sendUserFileLedger: Boolean(deps.sendFileLedger),
251
+ // K-2 (shell §K) — core ruling = SPLIT into two ORTHOGONAL axes so the shell gates each honestly:
252
+ // • `workflows` = ENGINE-CAN (can the engine self-orchestrate / run ultracode) = core's single-source
253
+ // `workflowsCapability(deps)` (hardened script runner ∧ governance), boot-computed in main.ts. Falls back
254
+ // to the `Boolean(workflowRunStore)` proxy when the boot flag isn't wired (older callers / tests).
255
+ // • `workflowsList` = can durably LIST workflow runs = `Boolean(workflowRunStore)` (GET /v1/workflows* 501s
256
+ // without it — list AND detail/stream, see the store gate ~L731).
257
+ // ⚠️ In the CURRENT service wiring these two COINCIDE: `workflowRunStore` is built IFF self-orchestration is on
258
+ // (InMemoryWorkflowRunStore when WORKFLOW_RUN_STORE=memory, else File — main.ts ~L527), the SAME gate that
259
+ // wires the safe script runner `workflowsCapability` checks → `Boolean(workflowRunStore)` ≡ `workflowsCapability`
260
+ // always today. So this split is core's FORWARD-LOOKING orthogonal-axes CONTRACT, NOT a fix for a live
261
+ // divergence (the earlier "memory backend → no store → divergence" framing was WRONG — InMemory IS a store;
262
+ // double-review caught it). It becomes load-bearing only if a future wiring decouples them (e.g. a run store
263
+ // present without a safe runner → engine-not-capable but listable). Both values are correct today.
85
264
  workflows: deps.workflowsCapable ?? Boolean(deps.workflowRunStore),
86
265
  workflowsList: Boolean(deps.workflowRunStore),
266
+ // K-1c (shell §K): manual /compact verb (POST /v1/runs/:id/compact → core 1.156 TaskStream.compact()). Needs
267
+ // the runs ledger (live-run lookup); advertise on runStore presence so the shell un-greys /compact only where
268
+ // the endpoint exists (it 409s for a non-live run, 501s without the store). core ≥1.156 guaranteed by the pin.
87
269
  manualCompact: Boolean(deps.runStore),
88
270
  });
89
271
  return;
90
272
  }
273
+ // Model catalog for consumers (e.g. OA's @-model autocomplete). NON-secret: names/capabilities
274
+ // only — never baseUrl/apiKey. `name` is the `@handle`; any of these may be @-mentioned. Source
275
+ // today = env-derived config.models; later the sema registry (sema-registry). The internal
276
+ // `default` alias is hidden (it's a fallback ref, not a user-pickable model).
91
277
  if (req.method === "GET" && url === "/v1/models") {
92
278
  const models = Object.entries(deps.config.models)
93
279
  .filter(([name]) => name !== "default")
@@ -97,10 +283,25 @@ async function handleCapabilitiesBody(req, res, url, ctx, miss) {
97
283
  provider: m.provider,
98
284
  reasoning: m.reasoning,
99
285
  vision: Array.isArray(m.input) ? m.input.includes("image") : false,
286
+ // E4 (shell-host contract): the context-window DENOMINATOR for the "% context used / N tokens until
287
+ // compact / low-context warning" gauge. Pure passthrough of the Model the service already holds
288
+ // (config.ts:603-604). Soft-degrade — omit when unknown (0) so the shell renders a raw token count
289
+ // without a %. The NUMERATOR (turn_end.usage.contextTokens) is core-blocked (SERVICE-GAP-DOSSIER §2 row 4);
290
+ // the denominator ships now with zero core dependency.
100
291
  ...(m.contextWindow ? { contextWindow: m.contextWindow } : {}),
101
292
  ...(m.maxTokens ? { maxOutputTokens: m.maxTokens } : {}),
293
+ // E7 (shell-host contract): the `/effort` picker's options. core's authoritative default tier set
294
+ // (DEFAULT_EFFORT_LEVELS = minimal/low/medium/high) for a reasoning model; omitted for a non-reasoning
295
+ // model (effort doesn't apply). The accept-set on a request is broader (any core ThinkingLevel) — this is
296
+ // the advertised picker default, not a hard allow-list.
102
297
  ...(m.reasoning ? { supportedEffortLevels: [...DEFAULT_EFFORT_LEVELS] } : {}),
103
298
  }));
299
+ // [865]③ id/name 撕裂消解:`default` 历史上是 **id 形**(壳面板行 value 却是 name 形,壳侧只能打补丁
300
+ // 拼回)。additive 双给:`default` 保持 id 形字节不动(既有消费者),新 `defaultModel = { id, name }`
301
+ // 一次给全。name = 目录里与 config.model 同一实例的键("default" 别名除外;registry 未生效的 env 单模型
302
+ // 目录也可能无命中 → 退 id 匹配,再退 undefined 时省略 name)。
303
+ // 双程匹配(codex M1):先引用相等(applyEffective 后 config.model 与目录真身同实例——重复 id 目录下
304
+ // 唯一无歧义的判据),仅 env 单模型 lane 等无引用命中时才退 id 匹配(目录序第一,确定性)。
104
305
  const nonAlias = Object.entries(deps.config.models).filter(([n]) => n !== "default");
105
306
  const defaultName = (nonAlias.find(([, m]) => m === deps.config.model) ?? nonAlias.find(([, m]) => m.id === deps.config.model.id))?.[0];
106
307
  sendJson(res, 200, { models, default: deps.config.model.id, defaultModel: { id: deps.config.model.id, ...(defaultName ? { name: defaultName } : {}) } });
@@ -1,3 +1,9 @@
1
+ /**
2
+ * design/158 A9 域模块 —— MF-Fleet 实时舰队流。
3
+ *
4
+ * 路由:`GET /v1/fleet/stream`(SSE PUSH:连上先快照,之后每条 per-row delta)。跑在服务凭据门**之前**
5
+ * (按 principal 自门,与 workflow 只读路由同列)。本域零可变状态。
6
+ */
1
7
  import type { IncomingMessage, ServerResponse } from "node:http";
2
8
  import type { RouteCtx } from "../route-ctx.js";
3
9
  export declare function handleFleet(req: IncomingMessage, res: ServerResponse, url: string, ctx: RouteCtx): Promise<boolean>;
@@ -6,38 +6,79 @@ export async function handleFleet(req, res, url, ctx) {
6
6
  await handleFleetBody(req, res, url, ctx, miss);
7
7
  return !miss.fell;
8
8
  }
9
+ /** 路由体 = 从 `server.ts` 的 `handle()` 里**整段剪切**过来的原文(唯一改动:统一去缩进两格)。裸 `return;`
10
+ * = 「本域已应答」;走到函数尾才是「没匹配上」。跨域的东西一律在首行解构出来。 */
9
11
  async function handleFleetBody(req, res, url, ctx, miss) {
10
12
  const { deps } = ctx;
11
13
  const { sessionOwnerScope } = ctx.helpers;
12
- void url;
14
+ void url; // 本域按 `req.url` 的完整 pathname 判路(带 query),`url` 只为域入口签名一致
15
+ // MF-Fleet (shell-host data contract): GET /v1/fleet/stream — the LIVE multi-row task/workflow fleet view as
16
+ // an SSE PUSH stream (status/elapsed/tokens/doneCount transitions over time). Owner-gated by scope (the
17
+ // caller's own active runs) UNLESS fleet-wide (a deployment trace/auth token sees every tenant's rows, like
18
+ // the trace API). Before the service-credential gate (self-gates by principal), parity with the workflow routes.
13
19
  if (req.method === "GET" && new URL(req.url ?? "", "http://x").pathname === "/v1/fleet/stream") {
14
20
  if (!deps.fleetBus) {
15
21
  sendError(res, 501, "capability.self_orchestration_required", "fleet stream requires self-orchestration / fleet wiring");
16
22
  return;
17
23
  }
18
- const { fleetWide } = sessionOwnerScope(req);
19
- const principal = gatedPrincipal(req, deps.config);
24
+ const { fleetWide } = sessionOwnerScope(req); // trace-token / system authToken ⇒ fleet-wide (all tenants)
25
+ const principal = gatedPrincipal(req, deps.config); // direct-door-safe identity (NOT the spoofable header)
20
26
  if (deps.config.requirePrincipal && !principal && !fleetWide) {
21
27
  sendError(res, 401, "auth.principal_required", `missing principal header '${deps.config.principalHeader}'`);
22
28
  return;
23
29
  }
30
+ // #3 fleet per-session scope (clay 2026-06-30): the shell sends its current sessionId as `?session=` to see ONLY
31
+ // this session's rows (not other sessions of the same principal — the "他会话 token" leak). Absent ⇒
32
+ // unscoped (all of the principal's rows — back-compat).
33
+ // 🔴 cli[1524] HIGH-1(V5c 回归锁首跑抓获):此前 fleetWide 把 callerSession 也强制 null——无 auth
34
+ // 部署(isFleetWide 第一臂:无 token/无 traceToken/无 requirePrincipal=恒 fleetWide,TOC loopback
35
+ // 默认形全中)下会话过滤/通知 fail-closed 门整体旁路成全量广播,而 meta 的 bgNotifyFailClosed 照报
36
+ // true=标说谎;1.245 的注入 fail-closed 与 1.247 的代际标在默认部署从未真正生效(一直是壳侧台账
37
+ // 在兜)。修:fleetWide 是**能力上限**(可看全量=豁免 scope 授权轴),不是「强制 unscoped」——
38
+ // 显式带 `?session=` 的请求无论 fleetWide 与否都按会话过滤(观察者要全量=不带 session;要跟单
39
+ // 会话且不烧 durable 副本=带 session+observe=1,既有防烧口)。meta 的 sessionScoped 由此自动如实,
40
+ // bgNotifyFailClosed 对 session-bound 连接从此真实。
24
41
  const fleetParams = new URL(req.url ?? "", "http://x").searchParams;
25
42
  const callerSession = fleetParams.get("session");
43
+ // `?observe=1` = a session-bound lane that must NOT serve-fence the durable copy
44
+ // (a non-shell observer following one session). Default (absent) keeps the frame-即-投递 semantics —
45
+ // today's only session-bound consumer IS the model-injecting shell.
26
46
  const observeOnly = fleetParams.get("observe") === "1";
27
47
  await streamFleet(req, res, deps.fleetBus, fleetWide ? null : (principal ?? "default"), callerSession || null, observeOnly ? undefined : deps.workflowCompletionInbox);
28
48
  return;
29
49
  }
30
50
  miss.fell = true;
31
51
  }
52
+ /** MF-Fleet: SSE the live fleet (active task + workflow rows) — a SNAPSHOT on connect, then every per-row delta
53
+ * the {@link FleetEventBus} fans out. `callerScope === null` ⇒ fleet-wide (a trace/auth token sees all tenants);
54
+ * else owner-scoped (only rows whose `scope` matches). The tenant-internal `scope` field is STRIPPED from every
55
+ * emitted row (it's a gate input, never rendered). A removal is forwarded ONLY for a row this connection actually
56
+ * saw (no id-existence oracle for an unseen tenant's run). Heartbeat + dual-close cleanup unsubscribe the bus. */
32
57
  function streamFleet(req, res, bus, callerScope, callerSession = null, completionInbox) {
33
58
  return new Promise((resolve) => {
34
59
  sseHeaders(res);
60
+ // [1508] 1.247 `bgNotifyFailClosed` — the GENERATION marker cli asked for ([1500]📌/[1502] F2): declares
61
+ // this server's bg_notification injection path fails CLOSED for scoped subscribers (1.245+ [1493] fix), so
62
+ // a new-generation shell can drop its frame-level own/foreign checks entirely (incl. the cross-shell
63
+ // restart edge) while keeping them against older servers whose meta lacks the field. Additive (version
64
+ // stays 1): older shells ignore unknown fields.
35
65
  res.write(`event: meta\ndata: ${JSON.stringify({ version: 1, scoped: callerScope !== null, sessionScoped: callerSession !== null, bgNotifyFailClosed: true })}\n\n`);
36
66
  const seenTasks = new Set();
37
67
  const seenWf = new Set();
68
+ // #3 fleet per-session scope (clay 2026-06-30): a row is visible iff it matches the caller's principal scope AND
69
+ // — when the caller sent `?session=` — its `sessionId`. A row WITHOUT a sessionId stays visible (back-compat for
70
+ // unscoped rows); the leak this closes is a row whose sessionId is ANOTHER session of the same principal.
38
71
  const sessionOk = (rowSession) => callerSession === null || rowSession === undefined || rowSession === callerSession;
39
72
  const visT = (r) => (callerScope === null || r.scope === callerScope) && sessionOk(r.sessionId);
40
73
  const visW = (r) => (callerScope === null || r.scope === callerScope) && sessionOk(r.sessionId);
74
+ // [1493] fable5 R1 (display plane): an UNATTRIBUTED row (no sessionId — restart lazy-mint / core version
75
+ // skew edges; post-Part-A every normal spawn is tagged) stays fail-open VISIBLE to a scoped subscriber
76
+ // (liveness back-compat: your own row after a restart still shows as running), but its content fields are
77
+ // conversation-derived text — `name` is the objective preview, `description`/`agentType`/`agentName` label
78
+ // the ask, `currentAction` is a live tool line. None of that may cross the session boundary, so a SCOPED
79
+ // subscriber gets a content-scrubbed projection (ids/status/progress/timing kept); a fleet-wide observer
80
+ // (trace/dashboard, callerSession === null) keeps the full row. Rows tagged with the caller's own session
81
+ // pass sessionOk and are never scrubbed (r.sessionId present ⇒ it equals callerSession here).
41
82
  const stripT = (r) => {
42
83
  const { scope: _s, sessionId: _sid, ...rest } = r;
43
84
  if (callerSession !== null && r.sessionId === undefined) {
@@ -56,6 +97,7 @@ function streamFleet(req, res, bus, callerScope, callerSession = null, completio
56
97
  };
57
98
  const send = (event, data) => { if (!res.writableEnded)
58
99
  res.write(`event: ${event}\ndata: ${JSON.stringify(data)}\n\n`); };
100
+ // connect-time snapshot (filtered + scope-stripped) — the visible rows become this connection's "seen" set.
59
101
  const snap = bus.snapshot();
60
102
  const tasks = snap.tasks.filter(visT);
61
103
  const workflows = snap.workflows.filter(visW);
@@ -85,35 +127,81 @@ function streamFleet(req, res, bus, callerScope, callerSession = null, completio
85
127
  send("workflow_remove", { id: frame.id, ts: frame.ts });
86
128
  break;
87
129
  case "hook_notice": {
130
+ // cli [1786]:一次 hook 判定**未能完成**的观测帧。可见性与 bg_notification **同为 fail-CLOSED** ——
131
+ // 一条关于**别人会话**的「这轮没看住」落到这个壳上,会让用户以为是自己这轮出了问题
132
+ // (而且 `/goal enforced` 面板会据此说一句不属于这个会话的话)。
133
+ // ⇒ scoped 订阅方只收能证明是自己的:`ownerSessionId === callerSession`;`undefined` ⇒ **丢弃**。
134
+ // fleet-wide 观察者(callerSession === null:trace/dashboard)照收。
88
135
  const hn = frame.notice;
89
136
  const hScopeOk = callerScope === null || hn.ownerScope === callerScope;
90
137
  const hSessionOk = callerSession === null || hn.ownerSessionId === callerSession;
91
138
  if (hScopeOk && hSessionOk) {
92
139
  const { ownerScope: _hs, ownerSessionId: _hsid, ...wire } = hn;
140
+ // 与 bg_notification 同一帧契约:`type` 也放进 payload(壳的帧桥按 data.type 分派)。
93
141
  send("hook_notice", { type: "hook_notice", ...wire, ts: frame.ts });
94
142
  }
95
143
  break;
96
144
  }
97
145
  case "bg_notification": {
146
+ // design/129-B 缺口②(帧契约): a bg child's completion pushed on THIS always-open lane — the
147
+ // idle shell renders the receipt immediately (no more one-input-cycle durable-drain lag). Visibility:
148
+ // tenant filter on ownerScope (same rule as rows; a notification without one is operator/fleet-wide
149
+ // visible only — fail-closed for scoped callers) + `?session=` on ownerSessionId (the HOST session;
150
+ // the payload sessionId is the CHILD's uuid — the contract's stable anchor — and never matches the caller's).
98
151
  const n = frame.notification;
99
152
  const scopeOk = callerScope === null || n.ownerScope === callerScope;
153
+ // [1493] fail-CLOSED on the MODEL-INJECTION path. bg_notification is auto-injected into the idle
154
+ // shell's model (the receipt drives the LLM's next turn). Unlike the display rows — whose absent-
155
+ // session `sessionOk` stays fail-OPEN for back-compat (an untagged row is at worst visible, never
156
+ // actionable) — an untagged completion delivered to a SCOPED subscriber would inject a DIFFERENT
157
+ // session's result into this shell's model (clay's dual-shell repro: two shells sharing one engine +
158
+ // principal). So a scoped caller (callerSession !== null) receives a completion ONLY when it is
159
+ // provably its own: ownerSessionId === callerSession. undefined ⇒ NOT proven ⇒ dropped. A fleet-wide
160
+ // observer (callerSession === null: trace/dashboard) still sees everything. Part A (fleet-bus) is what
161
+ // populates ownerSessionId for the legit owner so this gate delivers to it and drops only strangers.
100
162
  const sessionInjectOk = callerSession === null || n.ownerSessionId === callerSession;
101
163
  if (scopeOk && sessionInjectOk) {
102
164
  const { ownerScope: _os, ownerSessionId: _osid, ...wire } = n;
165
+ // The frame contract puts `type:'bg_notification'` INSIDE the object (the shell's frame
166
+ // bridge dispatches on data.type, not only the SSE event name) — carry it in the payload too.
103
167
  send("bg_notification", { type: "bg_notification", ...wire, ts: frame.ts });
168
+ // The frame IS the delivery when it reaches the OWNING shell's session-bound lane —
169
+ // serve-fence the durable park (both orders hold: an already-parked entry is acked; a park landing
170
+ // AFTER this is refused by the serve fence) so the next stream-open drain can't re-inject the same
171
+ // completion into the model (the engine-side steer-inject double the shell cannot dedup — the
172
+ // 129-bg variant of that double-injection class, proven from real session logs). ONLY a `?session=`-bound subscriber counts: a fleet-wide
173
+ // dashboard consuming the frame must NOT burn the owning shell's durable copy — the park keeps its
174
+ // offline/no-active-lane semantics. Keys line up by contract: frame taskId = BackgroundChildEvent
175
+ // .taskId = the a*-domain registry handle (stable across kinds) = the parked entry's
176
+ // runId (leg onTaskNotification's n.task_id, same domain); ownerSessionId = HOST session = entry key.
177
+ // design/144 键升级:park 键=域:taskId:status[#seq],fleet 帧不带 seq → 传家族前缀
178
+ // (taskNotificationFoldKey 无 seq 形),markTerminalServed 家族 ack 清同族 seq 键成员。
179
+ // PAIR-REVIEW F-2:mark 延至 **write flush 回调** + socket 存活双检——「res.write 已调用」≠投递
180
+ // (对端已断本端未感知的窗口里,帧写进死 socket 而 durable 副本被烧=通知永丢,1.334 教训)。
181
+ // flush 回调=数据出到内核缓冲(尽力而为的最强本端信号;真端到端 ack 需协议位,另议),回调时
182
+ // 再验 socket.destroyed——断连时 Node 会先触发 destroy,此时不 ack,park 副本留给下次开流 drain。
183
+ // fence 的防双注入语义不变(已 ack 的重复帧仍被拒),只推迟 ack 时点。
104
184
  if (completionInbox && n.ownerSessionId && callerSession !== null && callerSession === n.ownerSessionId && !res.writableEnded) {
105
185
  const ownerSid = n.ownerSessionId;
186
+ // codex R1-H1(修车批):帧带 seq(1.239/core 1.352)→ **精确键** ack(servedAt 只 fence 该
187
+ // 周期;revive 周期 N+1 的 park/enqueue 不被连坐)。legacy 无 seq 帧保持家族键 ack(原语义)。
106
188
  const family = taskNotificationFoldKey({ task_id: n.taskId, status: n.status, ...(n.seq !== undefined ? { seq: n.seq } : {}) });
189
+ // codex R2-H1(server belt):revive 周期的 park 键在 **uuid 域**(core ≤1.353 的 revive 通知
190
+ // task_id=childSessionId,subagent.js:598/655——identity 对齐转 core 在单),帧键在 a\* 域——
191
+ // 单键 ack 必 miss=开流二次注入。帧带 sessionId(uuid 别名)时**双域各 ack 一次**,两种 core
192
+ // 版本的 park 键都被 fence 住;core 修齐后 uuid 臂自然空转(无同键 park,无害)。
107
193
  const familyUuid = n.sessionId !== undefined && n.sessionId !== n.taskId
108
194
  ? taskNotificationFoldKey({ task_id: n.sessionId, status: n.status, ...(n.seq !== undefined ? { seq: n.seq } : {}) })
109
195
  : undefined;
110
196
  const ackIfAlive = () => {
111
197
  if (res.writableEnded || res.socket?.destroyed)
112
- return;
198
+ return; // 死连接:不烧 durable 副本
113
199
  void completionInbox.markTerminalServed(ownerSid, family).catch(() => undefined);
114
200
  if (familyUuid !== undefined)
115
201
  void completionInbox.markTerminalServed(ownerSid, familyUuid).catch(() => undefined);
116
202
  };
203
+ // res.write 的 flush 回调在上面 send() 内不可达(send 不透传 cb)——补一个零字节注释帧承载回调:
204
+ // SSE 注释行(`: ack\n\n`)对消费者不可见(SDK 吞注释),flush 语义等同。
117
205
  res.write(`: ack
118
206
 
119
207
  `, ackIfAlive);
@@ -122,9 +210,10 @@ function streamFleet(req, res, bus, callerScope, callerSession = null, completio
122
210
  break;
123
211
  }
124
212
  default:
125
- break;
213
+ break; // snapshot frames are connect-time only, never fanned out
126
214
  }
127
215
  });
216
+ // Real frame (not an SSE comment) — a per-frame-parsing BFF drops comments (zero-frame window downstream)
128
217
  const hb = setInterval(() => { if (!res.writableEnded)
129
218
  res.write(`event: heartbeat\ndata: {}\n\n`); }, 15_000);
130
219
  if (typeof hb.unref === "function")