@sema-agent/server 1.323.0 → 2.0.1

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 (565) 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/budget-tracing.d.ts +48 -0
  46. package/dist/boot/budget-tracing.js +86 -0
  47. package/dist/boot/config-center.d.ts +62 -0
  48. package/dist/boot/config-center.js +995 -0
  49. package/dist/boot/coordinators.d.ts +33 -0
  50. package/dist/boot/coordinators.js +97 -0
  51. package/dist/boot/execution-env.d.ts +26 -0
  52. package/dist/boot/execution-env.js +370 -0
  53. package/dist/boot/leader.d.ts +27 -0
  54. package/dist/boot/leader.js +81 -0
  55. package/dist/boot/reapers.d.ts +53 -0
  56. package/dist/boot/reapers.js +252 -0
  57. package/dist/boot/resolve-spec.d.ts +70 -0
  58. package/dist/boot/resolve-spec.js +1072 -0
  59. package/dist/boot/runner-deps.d.ts +101 -0
  60. package/dist/boot/runner-deps.js +343 -0
  61. package/dist/boot/runtime-caps.d.ts +21 -0
  62. package/dist/boot/runtime-caps.js +62 -0
  63. package/dist/boot/session-faces.d.ts +57 -0
  64. package/dist/boot/session-faces.js +157 -0
  65. package/dist/boot/shutdown.d.ts +50 -0
  66. package/dist/boot/shutdown.js +129 -0
  67. package/dist/boot/stores.d.ts +32 -0
  68. package/dist/boot/stores.js +361 -0
  69. package/dist/boot/workflow-orchestration.d.ts +46 -0
  70. package/dist/boot/workflow-orchestration.js +150 -0
  71. package/dist/boot-reclaim.d.ts +19 -0
  72. package/dist/boot-reclaim.js +20 -0
  73. package/dist/brain.d.ts +25 -0
  74. package/dist/brain.js +61 -1
  75. package/dist/budget.d.ts +66 -0
  76. package/dist/budget.js +128 -4
  77. package/dist/capabilities/builtin-tools.d.ts +3 -0
  78. package/dist/capabilities/builtin-tools.js +3 -0
  79. package/dist/capabilities/center-plugins.d.ts +17 -1
  80. package/dist/capabilities/center-plugins.js +45 -4
  81. package/dist/capabilities/center-prompts.d.ts +46 -0
  82. package/dist/capabilities/center-prompts.js +57 -3
  83. package/dist/capabilities/code-review-council.d.ts +28 -0
  84. package/dist/capabilities/code-review-council.js +40 -7
  85. package/dist/capabilities/collab-wire.d.ts +2 -0
  86. package/dist/capabilities/collab-workflows.d.ts +7 -0
  87. package/dist/capabilities/collab-workflows.js +44 -1
  88. package/dist/capabilities/oa-tools.d.ts +6 -0
  89. package/dist/capabilities/oa-tools.js +10 -0
  90. package/dist/capabilities/prompt.d.ts +14 -0
  91. package/dist/capabilities/prompt.js +14 -0
  92. package/dist/capabilities/prompts/code-review.d.ts +14 -0
  93. package/dist/capabilities/prompts/code-review.js +14 -0
  94. package/dist/capabilities/prompts/identity.d.ts +6 -0
  95. package/dist/capabilities/prompts/identity.js +6 -0
  96. package/dist/capabilities/prompts/team.d.ts +4 -0
  97. package/dist/capabilities/prompts/team.js +4 -0
  98. package/dist/capabilities/repo-tools.d.ts +11 -0
  99. package/dist/capabilities/repo-tools.js +8 -0
  100. package/dist/capabilities/sandbox-file-send.d.ts +95 -0
  101. package/dist/capabilities/sandbox-file-send.js +91 -3
  102. package/dist/capabilities/scenarios.d.ts +130 -0
  103. package/dist/capabilities/scenarios.js +180 -7
  104. package/dist/capabilities/select-environment-tool.d.ts +7 -0
  105. package/dist/capabilities/select-environment-tool.js +30 -0
  106. package/dist/capabilities/send-user-file-tool.d.ts +33 -0
  107. package/dist/capabilities/send-user-file-tool.js +65 -1
  108. package/dist/capabilities/skills.d.ts +29 -0
  109. package/dist/capabilities/skills.js +13 -2
  110. package/dist/capabilities/team.d.ts +22 -0
  111. package/dist/capabilities/team.js +22 -2
  112. package/dist/capabilities/tool-defer.d.ts +26 -0
  113. package/dist/capabilities/tool-defer.js +3 -0
  114. package/dist/config-center/apply-effective.d.ts +65 -0
  115. package/dist/config-center/apply-effective.js +204 -12
  116. package/dist/config-center/http-client.d.ts +34 -0
  117. package/dist/config-center/http-client.js +68 -0
  118. package/dist/config-center/restart-signal.d.ts +22 -0
  119. package/dist/config-center/restart-signal.js +39 -0
  120. package/dist/config-center/skills-mcp.d.ts +20 -1
  121. package/dist/config-center/skills-mcp.js +42 -7
  122. package/dist/config-center/types.d.ts +92 -1
  123. package/dist/config-lkg.d.ts +12 -0
  124. package/dist/config-lkg.js +41 -0
  125. package/dist/config-provider.d.ts +78 -0
  126. package/dist/config-provider.js +165 -2
  127. package/dist/config-types.d.ts +585 -1
  128. package/dist/config.d.ts +78 -2
  129. package/dist/config.js +874 -301
  130. package/dist/degenerate-instrument.d.ts +38 -0
  131. package/dist/degenerate-instrument.js +55 -3
  132. package/dist/elicitation.d.ts +39 -0
  133. package/dist/elicitation.js +87 -3
  134. package/dist/env-facts.d.ts +61 -0
  135. package/dist/env-facts.js +73 -7
  136. package/dist/fleet/fleet-bus.d.ts +185 -0
  137. package/dist/fleet/fleet-bus.js +333 -27
  138. package/dist/fleet/subagent-tail-bus.d.ts +11 -0
  139. package/dist/fleet/subagent-tail-bus.js +33 -2
  140. package/dist/fleet-client.d.ts +38 -0
  141. package/dist/fleet-client.js +44 -9
  142. package/dist/fleet-lease.d.ts +46 -0
  143. package/dist/fleet-lease.js +73 -5
  144. package/dist/hooks/branch-transcript.d.ts +8 -0
  145. package/dist/hooks/branch-transcript.js +33 -0
  146. package/dist/hooks/cc-stop-prompt.d.ts +42 -0
  147. package/dist/hooks/cc-stop-prompt.js +43 -1
  148. package/dist/hooks/hook-llm.d.ts +15 -0
  149. package/dist/hooks/hook-llm.js +47 -0
  150. package/dist/hooks/hook-runner.d.ts +89 -0
  151. package/dist/hooks/hook-runner.js +327 -18
  152. package/dist/http/idempotency.d.ts +31 -0
  153. package/dist/http/idempotency.js +34 -0
  154. package/dist/http/principal-gate.d.ts +17 -0
  155. package/dist/http/principal-gate.js +35 -3
  156. package/dist/http/route-ctx.d.ts +36 -0
  157. package/dist/http/routes/approvals-assistant.d.ts +25 -0
  158. package/dist/http/routes/approvals-assistant.js +253 -23
  159. package/dist/http/routes/attachments.js +22 -4
  160. package/dist/http/routes/capabilities.d.ts +7 -0
  161. package/dist/http/routes/capabilities.js +202 -1
  162. package/dist/http/routes/fleet.d.ts +6 -0
  163. package/dist/http/routes/fleet.js +94 -5
  164. package/dist/http/routes/images.d.ts +17 -0
  165. package/dist/http/routes/images.js +222 -14
  166. package/dist/http/routes/leader.d.ts +7 -0
  167. package/dist/http/routes/leader.js +10 -0
  168. package/dist/http/routes/memory-policy.d.ts +6 -0
  169. package/dist/http/routes/memory-policy.js +38 -6
  170. package/dist/http/routes/notify-wake.d.ts +10 -0
  171. package/dist/http/routes/notify-wake.js +19 -3
  172. package/dist/http/routes/observability.d.ts +6 -0
  173. package/dist/http/routes/observability.js +19 -2
  174. package/dist/http/routes/runs.d.ts +15 -0
  175. package/dist/http/routes/runs.js +464 -41
  176. package/dist/http/routes/session-sync.d.ts +15 -0
  177. package/dist/http/routes/session-sync.js +229 -19
  178. package/dist/http/routes/sessions-list.d.ts +6 -0
  179. package/dist/http/routes/sessions-list.js +35 -4
  180. package/dist/http/routes/sessions.d.ts +14 -0
  181. package/dist/http/routes/sessions.js +176 -31
  182. package/dist/http/routes/side-query.d.ts +8 -0
  183. package/dist/http/routes/side-query.js +26 -1
  184. package/dist/http/routes/tasks.d.ts +18 -0
  185. package/dist/http/routes/tasks.js +501 -38
  186. package/dist/http/routes/trace-usage.d.ts +10 -0
  187. package/dist/http/routes/trace-usage.js +66 -14
  188. package/dist/http/routes/workflows.d.ts +12 -0
  189. package/dist/http/routes/workflows.js +180 -19
  190. package/dist/http/run-meta.d.ts +11 -0
  191. package/dist/http/run-meta.js +6 -0
  192. package/dist/http/send.d.ts +19 -0
  193. package/dist/http/send.js +11 -0
  194. package/dist/http/server.d.ts +255 -0
  195. package/dist/http/server.js +921 -75
  196. package/dist/http/sse-log.d.ts +15 -0
  197. package/dist/http/sse-log.js +16 -0
  198. package/dist/http/tar.d.ts +9 -0
  199. package/dist/http/tar.js +21 -5
  200. package/dist/http/wire-gate.d.ts +9 -0
  201. package/dist/http/wire-gate.js +9 -0
  202. package/dist/http/wire-types.d.ts +187 -0
  203. package/dist/http/workspace-content.d.ts +8 -0
  204. package/dist/http/workspace-content.js +10 -0
  205. package/dist/images/bake-validate.d.ts +63 -0
  206. package/dist/images/bake-validate.js +71 -1
  207. package/dist/images/manifest.d.ts +19 -0
  208. package/dist/images/manifest.js +6 -1
  209. package/dist/index.d.ts +1 -5
  210. package/dist/index.js +10 -5
  211. package/dist/key-resolver.d.ts +23 -0
  212. package/dist/key-resolver.js +27 -2
  213. package/dist/leader/diffout.d.ts +23 -0
  214. package/dist/leader/diffout.js +8 -1
  215. package/dist/leader/diffup.d.ts +32 -0
  216. package/dist/leader/diffup.js +43 -0
  217. package/dist/leader/endpoint.d.ts +20 -0
  218. package/dist/leader/endpoint.js +25 -2
  219. package/dist/leader/fanout.d.ts +60 -0
  220. package/dist/leader/fanout.js +29 -3
  221. package/dist/leader/grader-env-factory.d.ts +74 -0
  222. package/dist/leader/grader-env-factory.js +62 -3
  223. package/dist/leader/leader.d.ts +97 -0
  224. package/dist/leader/leader.js +151 -4
  225. package/dist/leader/merge.d.ts +94 -0
  226. package/dist/leader/merge.js +112 -9
  227. package/dist/leader/planner.d.ts +52 -0
  228. package/dist/leader/planner.js +47 -3
  229. package/dist/leader/repair-oracle.d.ts +61 -0
  230. package/dist/leader/repair-oracle.js +59 -1
  231. package/dist/leader/repair-wire.d.ts +78 -0
  232. package/dist/leader/repair-wire.js +79 -2
  233. package/dist/leader/wire.d.ts +79 -0
  234. package/dist/leader/wire.js +255 -8
  235. package/dist/lsp/e2b-bridge.d.ts +16 -0
  236. package/dist/lsp/e2b-bridge.js +32 -4
  237. package/dist/lsp/e2b-manager.d.ts +10 -0
  238. package/dist/lsp/e2b-manager.js +18 -2
  239. package/dist/lsp/lsp-frames.d.ts +12 -0
  240. package/dist/lsp/lsp-frames.js +12 -0
  241. package/dist/lsp/manager.d.ts +12 -0
  242. package/dist/lsp/manager.js +35 -2
  243. package/dist/lsp/types.d.ts +10 -0
  244. package/dist/lsp/ws-transport.d.ts +12 -0
  245. package/dist/lsp/ws-transport.js +53 -5
  246. package/dist/lsp-evict.d.ts +14 -0
  247. package/dist/lsp-evict.js +15 -1
  248. package/dist/main.js +530 -2129
  249. package/dist/memory-export.d.ts +1 -0
  250. package/dist/memory-export.js +4 -0
  251. package/dist/memory-scope.d.ts +49 -0
  252. package/dist/memory-scope.js +87 -4
  253. package/dist/memory-sync-client.d.ts +24 -0
  254. package/dist/memory-sync-client.js +41 -2
  255. package/dist/memory-sync.d.ts +23 -0
  256. package/dist/memory-sync.js +70 -1
  257. package/dist/model-select.d.ts +39 -0
  258. package/dist/model-select.js +42 -1
  259. package/dist/observability/cost-quota.d.ts +20 -0
  260. package/dist/observability/cost-quota.js +4 -0
  261. package/dist/observability/cost-taxonomy.d.ts +45 -0
  262. package/dist/observability/cost-taxonomy.js +34 -0
  263. package/dist/observability/logger.d.ts +1 -0
  264. package/dist/observability/logger.js +6 -0
  265. package/dist/observability/metrics.d.ts +13 -0
  266. package/dist/observability/metrics.js +63 -0
  267. package/dist/observability/otel-exporter.d.ts +9 -0
  268. package/dist/observability/otel-exporter.js +11 -3
  269. package/dist/observability/principal-context.d.ts +9 -0
  270. package/dist/observability/principal-context.js +9 -0
  271. package/dist/observability/prompt-manifest.d.ts +37 -0
  272. package/dist/observability/prompt-manifest.js +35 -1
  273. package/dist/observability/rate-limit.d.ts +10 -0
  274. package/dist/observability/rate-limit.js +1 -0
  275. package/dist/observability/tool-trace.d.ts +24 -0
  276. package/dist/observability/tool-trace.js +41 -1
  277. package/dist/orchestration/hardened-vm-runner.d.ts +107 -0
  278. package/dist/orchestration/hardened-vm-runner.js +119 -4
  279. package/dist/orchestration/hardened-vm-worker-runner.d.ts +14 -0
  280. package/dist/orchestration/hardened-vm-worker-runner.js +26 -1
  281. package/dist/orchestration/hardened-vm-worker.js +27 -0
  282. package/dist/orchestration/subagent-steer.d.ts +44 -0
  283. package/dist/orchestration/subagent-steer.js +45 -1
  284. package/dist/orchestration/workflow-agent-steer.d.ts +54 -0
  285. package/dist/orchestration/workflow-agent-steer.js +80 -1
  286. package/dist/orchestration/workflow-completion-inbox.d.ts +189 -2
  287. package/dist/orchestration/workflow-completion-inbox.js +283 -32
  288. package/dist/orchestration/workflow-notify-journal.d.ts +132 -1
  289. package/dist/orchestration/workflow-notify-journal.js +187 -13
  290. package/dist/parked-decide.d.ts +61 -0
  291. package/dist/parked-decide.js +58 -1
  292. package/dist/per-task-image.d.ts +54 -0
  293. package/dist/per-task-image.js +41 -0
  294. package/dist/plan-cache-probe.d.ts +35 -0
  295. package/dist/plan-cache-probe.js +18 -3
  296. package/dist/plugins/approval-exemption-store.d.ts +7 -0
  297. package/dist/plugins/approval-exemption-store.js +28 -2
  298. package/dist/plugins/approval-store-sql.d.ts +64 -0
  299. package/dist/plugins/approval-store-sql.js +32 -0
  300. package/dist/plugins/background-agent-store-sql.d.ts +55 -0
  301. package/dist/plugins/background-agent-store-sql.js +91 -4
  302. package/dist/plugins/background-shell-support.d.ts +98 -0
  303. package/dist/plugins/background-shell-support.js +117 -13
  304. package/dist/plugins/blob-backend.d.ts +104 -0
  305. package/dist/plugins/blob-backend.js +163 -6
  306. package/dist/plugins/breaker-state-sql.d.ts +65 -1
  307. package/dist/plugins/breaker-state-sql.js +46 -8
  308. package/dist/plugins/caching-session-store.d.ts +42 -0
  309. package/dist/plugins/caching-session-store.js +63 -3
  310. package/dist/plugins/checkpoint-store-sql.d.ts +179 -0
  311. package/dist/plugins/checkpoint-store-sql.js +239 -11
  312. package/dist/plugins/file-outcome-sink.d.ts +4 -0
  313. package/dist/plugins/file-outcome-sink.js +9 -0
  314. package/dist/plugins/file-resume-anchor-store.d.ts +20 -0
  315. package/dist/plugins/file-resume-anchor-store.js +43 -4
  316. package/dist/plugins/file-run-store.d.ts +90 -0
  317. package/dist/plugins/file-run-store.js +145 -13
  318. package/dist/plugins/file-snapshot-store-sql.d.ts +133 -1
  319. package/dist/plugins/file-snapshot-store-sql.js +178 -10
  320. package/dist/plugins/file-workflow-journal-store.d.ts +10 -0
  321. package/dist/plugins/file-workflow-journal-store.js +10 -0
  322. package/dist/plugins/fork-routing-session-store.d.ts +47 -0
  323. package/dist/plugins/fork-routing-session-store.js +51 -3
  324. package/dist/plugins/host-platform.d.ts +69 -0
  325. package/dist/plugins/host-platform.js +81 -2
  326. package/dist/plugins/image-bake-store-sql.d.ts +136 -1
  327. package/dist/plugins/image-bake-store-sql.js +241 -7
  328. package/dist/plugins/image-index-sql.d.ts +46 -0
  329. package/dist/plugins/image-index-sql.js +113 -4
  330. package/dist/plugins/k8s-bg-scripts.d.ts +34 -0
  331. package/dist/plugins/k8s-bg-scripts.js +88 -4
  332. package/dist/plugins/k8s-exec-protocol.d.ts +33 -0
  333. package/dist/plugins/k8s-exec-protocol.js +41 -0
  334. package/dist/plugins/local-checkpoint-store.d.ts +40 -0
  335. package/dist/plugins/local-checkpoint-store.js +86 -7
  336. package/dist/plugins/local-session-store.d.ts +157 -0
  337. package/dist/plugins/local-session-store.js +289 -34
  338. package/dist/plugins/local-task-attachment-store.js +14 -2
  339. package/dist/plugins/mailbox-store-sql.d.ts +38 -0
  340. package/dist/plugins/mailbox-store-sql.js +39 -6
  341. package/dist/plugins/memory-engine-pg.d.ts +30 -0
  342. package/dist/plugins/memory-engine-pg.js +122 -4
  343. package/dist/plugins/memory-engine-tidb.d.ts +26 -0
  344. package/dist/plugins/memory-engine-tidb.js +115 -5
  345. package/dist/plugins/memory-engine-vector-util.d.ts +5 -0
  346. package/dist/plugins/memory-engine-vector-util.js +5 -0
  347. package/dist/plugins/memory-resume-anchor-store.d.ts +8 -0
  348. package/dist/plugins/memory-resume-anchor-store.js +17 -0
  349. package/dist/plugins/memory-run-store.d.ts +63 -0
  350. package/dist/plugins/memory-run-store.js +73 -8
  351. package/dist/plugins/memory-session-policy-store.d.ts +17 -0
  352. package/dist/plugins/memory-session-policy-store.js +17 -0
  353. package/dist/plugins/memory-sync-store-pg.d.ts +42 -0
  354. package/dist/plugins/memory-sync-store-pg.js +45 -2
  355. package/dist/plugins/memory-sync-store-tidb.d.ts +9 -0
  356. package/dist/plugins/memory-sync-store-tidb.js +31 -1
  357. package/dist/plugins/outcome-ledger-sql.d.ts +63 -0
  358. package/dist/plugins/outcome-ledger-sql.js +97 -3
  359. package/dist/plugins/pg-approval-store.d.ts +7 -0
  360. package/dist/plugins/pg-approval-store.js +7 -0
  361. package/dist/plugins/pg-breaker-state.d.ts +6 -0
  362. package/dist/plugins/pg-breaker-state.js +6 -0
  363. package/dist/plugins/pg-checkpoint-store.d.ts +8 -0
  364. package/dist/plugins/pg-checkpoint-store.js +8 -0
  365. package/dist/plugins/pg-cost-quota.d.ts +17 -0
  366. package/dist/plugins/pg-cost-quota.js +6 -0
  367. package/dist/plugins/pg-file-snapshot-store.d.ts +6 -0
  368. package/dist/plugins/pg-file-snapshot-store.js +6 -0
  369. package/dist/plugins/pg-image-bake.d.ts +9 -0
  370. package/dist/plugins/pg-image-bake.js +9 -0
  371. package/dist/plugins/pg-image-index.d.ts +9 -0
  372. package/dist/plugins/pg-image-index.js +9 -0
  373. package/dist/plugins/pg-outcome-ledger.d.ts +9 -0
  374. package/dist/plugins/pg-outcome-ledger.js +9 -0
  375. package/dist/plugins/pg-pool.d.ts +50 -0
  376. package/dist/plugins/pg-pool.js +78 -0
  377. package/dist/plugins/pg-query.d.ts +11 -0
  378. package/dist/plugins/pg-rate-limiter.d.ts +23 -0
  379. package/dist/plugins/pg-rate-limiter.js +12 -2
  380. package/dist/plugins/pg-resume-anchor-store.d.ts +5 -0
  381. package/dist/plugins/pg-resume-anchor-store.js +5 -0
  382. package/dist/plugins/pg-run-store.d.ts +7 -0
  383. package/dist/plugins/pg-run-store.js +7 -0
  384. package/dist/plugins/pg-safe-json.d.ts +13 -0
  385. package/dist/plugins/pg-safe-json.js +40 -4
  386. package/dist/plugins/pg-session-policy-store.d.ts +5 -0
  387. package/dist/plugins/pg-session-policy-store.js +5 -0
  388. package/dist/plugins/pg-session-storage.d.ts +72 -0
  389. package/dist/plugins/pg-session-storage.js +152 -20
  390. package/dist/plugins/pg-session-store.d.ts +10 -0
  391. package/dist/plugins/pg-session-store.js +10 -0
  392. package/dist/plugins/pg-tool-result-store.d.ts +7 -0
  393. package/dist/plugins/pg-tool-result-store.js +7 -0
  394. package/dist/plugins/pg-workflow-journal-store.d.ts +7 -0
  395. package/dist/plugins/pg-workflow-journal-store.js +7 -0
  396. package/dist/plugins/pg-workflow-run-store.d.ts +7 -0
  397. package/dist/plugins/pg-workflow-run-store.js +7 -0
  398. package/dist/plugins/posix-shell-fs.d.ts +3 -0
  399. package/dist/plugins/posix-shell-fs.js +31 -1
  400. package/dist/plugins/remote-env-adb.d.ts +25 -0
  401. package/dist/plugins/remote-env-adb.js +95 -12
  402. package/dist/plugins/remote-env-e2b.d.ts +146 -0
  403. package/dist/plugins/remote-env-e2b.js +371 -40
  404. package/dist/plugins/remote-env-file-error.d.ts +34 -0
  405. package/dist/plugins/remote-env-file-error.js +37 -0
  406. package/dist/plugins/remote-env-host.d.ts +151 -0
  407. package/dist/plugins/remote-env-host.js +468 -70
  408. package/dist/plugins/remote-env-k8s.d.ts +135 -0
  409. package/dist/plugins/remote-env-k8s.js +318 -32
  410. package/dist/plugins/remote-env-local-docker.d.ts +65 -0
  411. package/dist/plugins/remote-env-local-docker.js +149 -24
  412. package/dist/plugins/remote-env-ssh.d.ts +35 -0
  413. package/dist/plugins/remote-env-ssh.js +117 -20
  414. package/dist/plugins/remote-scratchpad.d.ts +38 -0
  415. package/dist/plugins/remote-scratchpad.js +32 -2
  416. package/dist/plugins/remote-shell.d.ts +22 -0
  417. package/dist/plugins/remote-shell.js +27 -1
  418. package/dist/plugins/resume-anchor-store-sql.d.ts +28 -0
  419. package/dist/plugins/resume-anchor-store-sql.js +11 -0
  420. package/dist/plugins/roster-store-sql.d.ts +27 -0
  421. package/dist/plugins/roster-store-sql.js +54 -0
  422. package/dist/plugins/run-store-sql.d.ts +194 -0
  423. package/dist/plugins/run-store-sql.js +210 -9
  424. package/dist/plugins/s3-presign.d.ts +20 -0
  425. package/dist/plugins/s3-presign.js +49 -2
  426. package/dist/plugins/scheduler-support.d.ts +12 -0
  427. package/dist/plugins/scheduler-support.js +75 -3
  428. package/dist/plugins/send-file-ledger.d.ts +15 -0
  429. package/dist/plugins/send-file-ledger.js +53 -4
  430. package/dist/plugins/send-user-file.d.ts +77 -0
  431. package/dist/plugins/send-user-file.js +92 -4
  432. package/dist/plugins/session-policy-store-sql.d.ts +15 -0
  433. package/dist/plugins/session-policy-store-sql.js +75 -3
  434. package/dist/plugins/session-store.d.ts +45 -0
  435. package/dist/plugins/session-store.js +51 -0
  436. package/dist/plugins/sql-driver.d.ts +77 -0
  437. package/dist/plugins/sql-driver.js +4 -0
  438. package/dist/plugins/sql-escape.d.ts +8 -0
  439. package/dist/plugins/sql-escape.js +8 -0
  440. package/dist/plugins/sql-row-helpers.d.ts +25 -0
  441. package/dist/plugins/sql-row-helpers.js +25 -0
  442. package/dist/plugins/store-backend.d.ts +103 -0
  443. package/dist/plugins/store-backend.js +120 -27
  444. package/dist/plugins/store-contracts.d.ts +62 -0
  445. package/dist/plugins/store-contracts.js +3 -0
  446. package/dist/plugins/task-attachment-store.d.ts +60 -0
  447. package/dist/plugins/task-attachment-store.js +49 -3
  448. package/dist/plugins/task-list-store-sql.d.ts +25 -0
  449. package/dist/plugins/task-list-store-sql.js +21 -0
  450. package/dist/plugins/tidb-approval-store.d.ts +6 -0
  451. package/dist/plugins/tidb-approval-store.js +6 -0
  452. package/dist/plugins/tidb-breaker-state.d.ts +5 -0
  453. package/dist/plugins/tidb-breaker-state.js +5 -0
  454. package/dist/plugins/tidb-checkpoint-store.d.ts +7 -0
  455. package/dist/plugins/tidb-checkpoint-store.js +7 -0
  456. package/dist/plugins/tidb-cost-quota.d.ts +6 -0
  457. package/dist/plugins/tidb-cost-quota.js +1 -0
  458. package/dist/plugins/tidb-file-snapshot-store.d.ts +6 -0
  459. package/dist/plugins/tidb-file-snapshot-store.js +6 -0
  460. package/dist/plugins/tidb-image-bake.d.ts +8 -0
  461. package/dist/plugins/tidb-image-bake.js +8 -0
  462. package/dist/plugins/tidb-image-index.d.ts +8 -0
  463. package/dist/plugins/tidb-image-index.js +8 -0
  464. package/dist/plugins/tidb-outcome-ledger.d.ts +10 -0
  465. package/dist/plugins/tidb-outcome-ledger.js +10 -0
  466. package/dist/plugins/tidb-pool.d.ts +56 -0
  467. package/dist/plugins/tidb-pool.js +181 -1
  468. package/dist/plugins/tidb-rate-limiter.d.ts +11 -0
  469. package/dist/plugins/tidb-rate-limiter.js +5 -2
  470. package/dist/plugins/tidb-resume-anchor-store.d.ts +5 -0
  471. package/dist/plugins/tidb-resume-anchor-store.js +5 -0
  472. package/dist/plugins/tidb-run-store.d.ts +7 -0
  473. package/dist/plugins/tidb-run-store.js +7 -0
  474. package/dist/plugins/tidb-session-policy-store.d.ts +5 -0
  475. package/dist/plugins/tidb-session-policy-store.js +5 -0
  476. package/dist/plugins/tidb-session-storage.d.ts +43 -0
  477. package/dist/plugins/tidb-session-storage.js +62 -3
  478. package/dist/plugins/tidb-session-store.d.ts +142 -0
  479. package/dist/plugins/tidb-session-store.js +264 -16
  480. package/dist/plugins/tidb-tool-result-store.d.ts +5 -0
  481. package/dist/plugins/tidb-tool-result-store.js +7 -0
  482. package/dist/plugins/tidb-workflow-journal-store.d.ts +7 -0
  483. package/dist/plugins/tidb-workflow-journal-store.js +7 -0
  484. package/dist/plugins/tidb-workflow-run-store.d.ts +8 -0
  485. package/dist/plugins/tidb-workflow-run-store.js +8 -0
  486. package/dist/plugins/tool-result-store-sql.d.ts +58 -0
  487. package/dist/plugins/tool-result-store-sql.js +38 -2
  488. package/dist/plugins/web-search.d.ts +35 -0
  489. package/dist/plugins/web-search.js +45 -9
  490. package/dist/plugins/workflow-journal-limits.d.ts +10 -0
  491. package/dist/plugins/workflow-journal-limits.js +10 -0
  492. package/dist/plugins/workflow-journal-store-sql.d.ts +78 -0
  493. package/dist/plugins/workflow-journal-store-sql.js +58 -2
  494. package/dist/plugins/workflow-run-store-sql.d.ts +84 -0
  495. package/dist/plugins/workflow-run-store-sql.js +84 -6
  496. package/dist/plugins/worktree-isolation.d.ts +45 -0
  497. package/dist/plugins/worktree-isolation.js +105 -6
  498. package/dist/plugins/write-behind-counter.d.ts +56 -1
  499. package/dist/plugins/write-behind-counter.js +53 -14
  500. package/dist/principal-jwt.d.ts +24 -0
  501. package/dist/principal-jwt.js +60 -5
  502. package/dist/project-memory.d.ts +22 -0
  503. package/dist/project-memory.js +144 -15
  504. package/dist/prompts-domain-validate.d.ts +28 -0
  505. package/dist/prompts-domain-validate.js +42 -1
  506. package/dist/question.d.ts +33 -0
  507. package/dist/question.js +69 -2
  508. package/dist/resource-suspend.d.ts +21 -0
  509. package/dist/resource-suspend.js +16 -0
  510. package/dist/router/route-orchestration.d.ts +78 -0
  511. package/dist/router/route-orchestration.js +77 -0
  512. package/dist/run-local.d.ts +32 -0
  513. package/dist/run-local.js +172 -8
  514. package/dist/runs.d.ts +189 -4
  515. package/dist/runs.js +465 -24
  516. package/dist/runtime-caps-resolver.d.ts +106 -0
  517. package/dist/runtime-caps-resolver.js +89 -4
  518. package/dist/runtime-governance.d.ts +84 -0
  519. package/dist/runtime-governance.js +127 -1
  520. package/dist/sandbox-pkg-source.d.ts +23 -0
  521. package/dist/sandbox-pkg-source.js +37 -0
  522. package/dist/sealed-key.d.ts +54 -0
  523. package/dist/sealed-key.js +68 -3
  524. package/dist/security.d.ts +108 -0
  525. package/dist/security.js +145 -6
  526. package/dist/sema-registry.d.ts +21 -0
  527. package/dist/sema-registry.js +21 -0
  528. package/dist/session-leaf-bus.d.ts +31 -0
  529. package/dist/session-leaf-bus.js +32 -0
  530. package/dist/session-sync-content.d.ts +46 -0
  531. package/dist/session-sync-content.js +47 -1
  532. package/dist/session-sync-kernel.d.ts +89 -0
  533. package/dist/session-sync-kernel.js +48 -3
  534. package/dist/session-sync.d.ts +125 -0
  535. package/dist/session-sync.js +181 -8
  536. package/dist/session-titler.d.ts +26 -0
  537. package/dist/session-titler.js +41 -7
  538. package/dist/session-watch.d.ts +53 -1
  539. package/dist/session-watch.js +73 -9
  540. package/dist/sighup-idle.d.ts +30 -0
  541. package/dist/sighup-idle.js +12 -1
  542. package/dist/spec-fields.d.ts +91 -3
  543. package/dist/spec-fields.js +116 -4
  544. package/dist/task-cwd.d.ts +50 -0
  545. package/dist/task-cwd.js +68 -1
  546. package/dist/task-mcp.d.ts +47 -0
  547. package/dist/task-mcp.js +29 -0
  548. package/dist/task-settings.d.ts +175 -0
  549. package/dist/task-settings.js +226 -11
  550. package/dist/task-workflow.d.ts +67 -0
  551. package/dist/task-workflow.js +75 -8
  552. package/dist/tool-approval.d.ts +91 -0
  553. package/dist/tool-approval.js +215 -0
  554. package/dist/trace/artifacts.d.ts +9 -0
  555. package/dist/trace/artifacts.js +30 -5
  556. package/dist/trace/core-keyset-guard.d.ts +18 -0
  557. package/dist/trace/ledger-sink.d.ts +43 -0
  558. package/dist/trace/ledger-sink.js +64 -5
  559. package/dist/trace/project.d.ts +133 -0
  560. package/dist/trace/project.js +189 -2
  561. package/dist/trace/redact.d.ts +19 -0
  562. package/dist/trace/redact.js +66 -9
  563. package/dist/usage-analytics.d.ts +26 -0
  564. package/dist/usage-analytics.js +26 -3
  565. package/package.json +1 -1
@@ -1,6 +1,34 @@
1
+ /**
2
+ * MF-Fleet (shell-host data-contract, the dynamic-stream obligation) — the SERVICE-side live fleet
3
+ * aggregation bus + state, backing `GET /v1/fleet/stream`.
4
+ *
5
+ * The fleet view (CC 187 0616_053) animates a MULTI-ROW tree: every active task's `status/elapsedMs/tokens/
6
+ * queuedCount` and every workflow's `doneCount N/M · failedCount` TRANSITION over time. That is a *push* stream,
7
+ * not a one-shot read: the backend must emit every transition for as long as a run is live, with STABLE per-row
8
+ * identity so the UI updates the right row in place.
9
+ *
10
+ * This bus is the in-process aggregator: the run lifecycle (createRun → queued/running, per-turn token accrual,
11
+ * terminal → completed/failed) and the workflow lifecycle (WorkflowRun put/update → doneCount/status) publish
12
+ * their per-row deltas here; `GET /v1/fleet/stream` subscribes, sends a SNAPSHOT on connect, then forwards every
13
+ * delta. Identity: tasks keyed by `id` (the durable runId/taskId), workflows by their workflow runId, subagent
14
+ * sub-rows (round 5, pending core's `task_progress` arm) by `parentId`+agent id (E2 `parentToolCallId`).
15
+ *
16
+ * 🔒 boundary (design/99 §0): the FLEET aggregation + the SSE wire is **service** (UI/deployment-state view over
17
+ * the runs ledger + workflow store). The engine semantics (a run's own events, a subagent's usage ticks) are
18
+ * core's — the bus only AGGREGATES what the lifecycle already produces. It carries NO new engine state.
19
+ *
20
+ * NOT durable / NOT cross-replica: a live fleet is this replica's active runs (mirrors `steerableRuns` —
21
+ * replica-local). A cross-replica fleet roll-up is a fleet-token-gated trace-API concern (separate), not this.
22
+ */
1
23
  import { EventEmitter } from "node:events";
2
24
  import { canonicalToolName } from "@sema-agent/core";
3
25
  import { redactSecrets } from "../trace/redact.js";
26
+ /**
27
+ * The process-local fleet aggregation bus. Holds the current active set + fans out deltas to SSE subscribers.
28
+ * Upserts MERGE (a partial delta patches the existing row), so a publisher can emit just the field that changed
29
+ * (e.g. only `tokens`) and the row stays whole. Removal drops the row (terminal). Subscribers get a snapshot of
30
+ * the current set immediately, then every subsequent delta.
31
+ */
4
32
  export class FleetEventBus {
5
33
  now;
6
34
  emitter = new EventEmitter();
@@ -8,39 +36,51 @@ export class FleetEventBus {
8
36
  workflows = new Map();
9
37
  constructor(now = () => Date.now()) {
10
38
  this.now = now;
11
- this.emitter.setMaxListeners(0);
39
+ this.emitter.setMaxListeners(0); // unbounded SSE subscribers (each /v1/fleet/stream connection)
12
40
  }
41
+ /** Upsert a task row (MERGE onto any existing row by `id`) + fan out the merged row. Publishers may send a
42
+ * partial `{ id, tokens }` etc.; the row keeps its other fields. */
13
43
  publishTask(delta) {
14
44
  const merged = { ...(this.tasks.get(delta.id) ?? { id: delta.id, name: delta.id, status: "running" }), ...delta };
15
45
  this.tasks.set(delta.id, merged);
16
46
  this.emit({ type: "task", row: merged, ts: this.now() });
17
47
  }
48
+ /** 推一帧 hook 判定未完成的观测通知(事件语义,不进 snapshot —— 与 `bg_notification` 同族)。 */
18
49
  publishHookNotice(notice) {
19
50
  this.emit({ type: "hook_notice", notice, ts: this.now() });
20
51
  }
52
+ /** Drop a task row (terminal + swept) + fan out the removal. Idempotent (a no-op if already gone). */
21
53
  removeTask(id) {
22
54
  if (this.tasks.delete(id))
23
55
  this.emit({ type: "task_remove", id, ts: this.now() });
24
56
  }
57
+ /** Upsert a workflow row (MERGE by `id`) + fan out. */
25
58
  publishWorkflow(delta) {
26
59
  const merged = { ...(this.workflows.get(delta.id) ?? { id: delta.id, name: delta.id, status: "running" }), ...delta };
27
60
  this.workflows.set(delta.id, merged);
28
61
  this.emit({ type: "workflow", row: merged, ts: this.now() });
29
62
  }
63
+ /** Drop a workflow row + fan out the removal. Idempotent. */
30
64
  removeWorkflow(id) {
31
65
  if (this.workflows.delete(id))
32
66
  this.emit({ type: "workflow_remove", id, ts: this.now() });
33
67
  }
68
+ /** design/129-B 缺口②: fan out a background-child completion notification (EVENT — not stored, never in the
69
+ * snapshot; a subscriber that connects later reads the durable inbox instead). */
34
70
  publishBgNotification(notification) {
35
71
  this.emit({ type: "bg_notification", notification, ts: this.now() });
36
72
  }
73
+ /** The current full state (the connect-time snapshot frame). */
37
74
  snapshot() {
38
75
  return { type: "snapshot", tasks: [...this.tasks.values()], workflows: [...this.workflows.values()], ts: this.now() };
39
76
  }
77
+ /** Subscribe to deltas. Returns an unsubscribe thunk. The caller typically sends `snapshot()` first, then every
78
+ * delta this delivers — the snapshot+delta sequence is the live fleet view. */
40
79
  subscribe(cb) {
41
80
  this.emitter.on("frame", cb);
42
81
  return () => this.emitter.off("frame", cb);
43
82
  }
83
+ /** Live counts (test/observability). */
44
84
  get size() {
45
85
  return { tasks: this.tasks.size, workflows: this.workflows.size };
46
86
  }
@@ -48,18 +88,37 @@ export class FleetEventBus {
48
88
  this.emitter.emit("frame", frame);
49
89
  }
50
90
  }
91
+ /** A run-scoped lifecycle publisher — wire it into a run's TaskEvent loop so the fleet row TRANSITIONS with the
92
+ * run. `onStart()` adds the top-level row (running); `onEvent(ev)` accrues tokens (turn_end usage) + adds/updates
93
+ * subagent CHILD rows (core `task_progress`, keyed by its `taskId`, nested under the run via `parentId`);
94
+ * `onTerminal(status)` flips the row terminal + removes it (and its children) from the active set. No-op when no
95
+ * bus is wired. The token accrual is CUMULATIVE across the run's turns (turn_end carries a per-turn delta). */
51
96
  export function fleetRunPublisher(bus, run) {
52
97
  if (!bus)
53
98
  return { onStart: () => undefined, onEvent: () => undefined, onForwardEvent: () => undefined, onChildTerminal: () => false, onTerminal: () => undefined };
54
99
  let tokens = 0;
55
100
  const startedAt = Date.now();
101
+ // #3 fleet per-session scope (clay 2026-06-30): tag every row of THIS run with its rootTaskId (= sessionId) so
102
+ // /v1/fleet/stream can filter to the caller's CURRENT session (a TUI footer no longer shows other sessions of the
103
+ // same principal). publishTask MERGEs, so tagging the CREATE frame suffices — status/token updates keep the field.
56
104
  const sessionField = run.rootTaskId ? { sessionId: run.rootTaskId } : {};
57
- const children = new Set();
58
- const childStartedAt = new Map();
105
+ const children = new Set(); // subagent child row ids (removed with the run)
106
+ const childStartedAt = new Map(); // [1332]④:child 行时长轴(首 tick 起表)
107
+ // codex R2:spawning tool-call id → cid。core 的失败/killed 收尾通知不带 sessionId(成功路径才有条件带),
108
+ // 此时 task_id(a*)解不到 uuid 键的 tick 行——但 tick 的 ident() 带 parentToolCallId,通知带同源 toolUseId,
109
+ // 这是两 id 域之外唯一贯穿 spawn→terminal 的关联轴。一次 Task 调用只 spawn 一个 child,键不撞。
59
110
  const childByToolCall = new Map();
111
+ // Once the leg SETTLED, a LATE subagent tick must not resurrect a child
112
+ // row — the settle's removeTask IS the shell's release signal (auto-exit watches the evict); a post-settle
113
+ // re-publish left a zombie "running" row with no terminal/remove ever coming. Freeze all publishes after
114
+ // onTerminal (a resume runs on a FRESH publisher — this leg's handle is done).
60
115
  let settledLeg = false;
61
116
  const childId = (taskId) => `${run.runId} ${taskId}`;
117
+ /** [1415]③:task_progress.status 值域映射(1.354 settle 终态 tick)——completed/failed 直译,其余(含
118
+ * undefined/"running"/suspended 不发的诚实面)恒 running(旧 core 行为逐位不变)。 */
62
119
  const tickStatus = (st) => (st === "completed" ? "completed" : st === "failed" ? "failed" : "running");
120
+ /** [1748] 从一拍 usage 里取**累计**工具调用次数。与 `sumTokens` 同样防御式取值(该位在这两处的
121
+ * 静态类型是 `{}`)。⚠️ 缺席就返回 undefined —— 调用点据此**不发这个键**(缺席 ≠ 0)。 */
63
122
  const toolUsesOf = (usage) => {
64
123
  const t = usage?.toolUses;
65
124
  return typeof t === "number" ? t : undefined;
@@ -70,6 +129,12 @@ export function fleetRunPublisher(bus, run) {
70
129
  return 0;
71
130
  if (typeof u.totalTokens === "number")
72
131
  return u.totalTokens;
132
+ // #9 (workflow 2nd-pass re-review): a turn_end.usage has NO totalTokens → this field-sum. core's turn_end.inputTokens
133
+ // is the NORMALIZED TOTAL INPUT *INCLUDING CACHE* (usage-accounting promptTokensOf — input + cacheRead + cacheWrite
134
+ // for the Anthropic family; OpenAI already folds cacheRead into input). So inputTokens + outputTokens ALREADY is the
135
+ // turn total — the old code ALSO added cacheRead/cacheWrite, double-counting them (~2x with prompt caching, the
136
+ // normal case). Display-only (the leader fleet-row token number); billing (costMicroUsd) + context/compaction use
137
+ // totalTokens and were never affected; child rows use task_progress.usage.totalTokens (the early-return) — correct.
73
138
  return (u.inputTokens ?? 0) + (u.outputTokens ?? 0);
74
139
  };
75
140
  return {
@@ -78,44 +143,105 @@ export function fleetRunPublisher(bus, run) {
78
143
  },
79
144
  onEvent(ev) {
80
145
  if (settledLeg)
81
- return;
146
+ return; // no post-settle publishes (zombie-row resurrection)
82
147
  if (ev.type === "turn_end" && !ev.parentToolCallId) {
83
- tokens += sumTokens(ev.usage);
148
+ // #9 orchestration token attribution (core 1.180 TaskEventIdentity on turn_end): accrue ONLY the LEADER's own
149
+ // turns onto the run row. A turn_end WITH a parentToolCallId is an orchestration/subagent SUB-turn (a
150
+ // run_workflow agent or a spawned subagent) — its usage belongs to that child's own row / the workflow's
151
+ // budget, NOT the leader. Before core threaded the identity onto turn_end (1.121 left it the only boundary
152
+ // event without it), the leader row over-counted sub-turn usage on self-orchestration runs.
153
+ tokens += sumTokens(ev.usage); // turn_end carries a per-turn usage delta → accumulate
84
154
  bus.publishTask({ id: run.runId, tokens, elapsedMs: Date.now() - startedAt });
85
155
  }
86
156
  else if (ev.type === "task_progress" && ev.taskId) {
157
+ // core 1.147 subagent usage tick (per-turn, cumulative) → a CHILD fleet row nested under the run.
87
158
  const cid = childId(ev.taskId);
88
159
  children.add(cid);
160
+ // BC-2 (core 1.151): use the subagent's sanitized display `name` (taskName/agent-type) for the child row;
161
+ // fall back to the taskId when absent (an anonymous subagent — core deliberately omits name rather than leak
162
+ // the delegated objective). The row IDENTITY stays `cid` (runId+taskId); only the display label improves.
163
+ // [WF2-A] redact the subagent display name for PARITY with the top-level run name (fleetRunLabels): core
164
+ // sanitizes it for RENDERING (ANSI/NUL strip + truncate) but does NOT secret-redact, so a secret-shaped
165
+ // taskName would leak verbatim on the child row without this.
166
+ // §K-7: `ev.name` IS the subagent TYPE (BC-2: taskName / selected agent-type) → ALSO surface it as
167
+ // `agentType` (the picker's short-label field), not only the display `name`. Absent name (anonymous
168
+ // subagent) → no agentType (the row falls back to name=taskId). One redacted value (name === agentType).
89
169
  const childName = redactSecrets(ev.name ?? ev.taskId);
90
170
  if (!childStartedAt.has(cid))
91
171
  childStartedAt.set(cid, Date.now());
92
172
  if (ev.parentToolCallId)
93
173
  childByToolCall.set(ev.parentToolCallId, cid);
174
+ // [1415]③ 点亮半场:core 1.354 起 settle 时补终态 tick(status 值域 additive 扩 completed|failed;
175
+ // 此前恒 "running"=行为逐位不变)——workflow 子的 uuid 行终于有完成态可见(running→removed 的
176
+ // [1414]#3 形就此闭)。
94
177
  bus.publishTask({ id: cid, name: childName, ...(ev.name ? { agentType: childName } : {}), parentId: run.runId, scope: run.scope, ...sessionField, status: tickStatus(ev.status), tokens: sumTokens(ev.usage), ...(() => { const t = toolUsesOf(ev.usage); return t !== undefined ? { toolUses: t } : {}; })(), elapsedMs: Date.now() - childStartedAt.get(cid) });
95
178
  }
96
179
  else if (ev.type === "tool_start" && ev.toolName) {
180
+ // BC-1 (clay 2026-06-27): the top-level run row's `description` = LIVE ACTIVITY (the tool now running), NOT
181
+ // the objective. `name` already carries an objective preview (fleetRunLabels); ALSO putting the objective in
182
+ // `description` showed it TWICE (the dup the shell flagged). So `description` tracks the current tool, CC-like.
183
+ // Tool NAME only — args are untrusted/redacted, a row label must never leak them. Subagent CHILD rows keep
184
+ // their task_progress display name (BC-2); this updates the TOP-LEVEL run row only.
185
+ // PascalCase double-belt (core 1.176): canonicalize so a legacy snake CONTROL verb (e.g. a
186
+ // pre-1.176 emit / a stray report_blocked) renders as its CC name (ReportBlocked) and the shell's PascalCase
187
+ // suppression Set still hides it — never re-leaking a control verb as fleet-row activity.
97
188
  bus.publishTask({ id: run.runId, description: canonicalToolName(ev.toolName) });
98
189
  }
99
190
  },
100
191
  onForwardEvent(ev) {
192
+ // core 1.154 (design/99 nested-subagent live tree): a SUBAGENT's `task_progress` tick forwarded from its
193
+ // ISOLATED stream to the top run's opt-in sink (`RunInternals.onForwardEvent`). This is the ONLY path a
194
+ // subagent tick reaches the top consumer — the top run's own stream does NOT carry it (the tick lives in the
195
+ // child's stream, consumed by the parent's runTask). So this builds the fleet's per-subagent CHILD rows at ANY
196
+ // depth: `parentTaskId` names the spawner — the TOP run (= `rootTaskId` → nest under run.runId) or another
197
+ // subagent (→ nest under that subagent's row). core sets a child's `parentTaskId` = its spawner's task_progress
198
+ // `taskId` (prepare-task.ts), so the tree keys line up. Forwarded ticks are UNTRUSTED display hints (name is
199
+ // core-sanitized; we carry NAME + token rollup only, never args).
200
+ // 🟡 parentTaskId is NOT validated against known runs (documented as LOW). It needn't be: the
201
+ // isolation guarantee is the SCOPE BOUND, not a parentTaskId check — every child row we publish is tagged
202
+ // `scope: run.scope` (this run's owner) and id-prefixed with the real `run.runId`. So a tool forging a
203
+ // `parentTaskId` can at worst MIS-NEST a row WITHIN this run's own scope view (cosmetic); it can never cross
204
+ // into another run / tenant. (core corrected its prepare-task note that had over-promised "deployment
205
+ // validates parentTaskId" — the bound is structural here.) Validation would be optional defense-in-depth only.
101
206
  if (settledLeg)
102
- return;
207
+ return; // a late forwarded tick must not resurrect a removed child row
103
208
  if (ev.type !== "task_progress" || !ev.taskId)
104
209
  return;
105
210
  const cid = childId(ev.taskId);
106
211
  children.add(cid);
107
212
  const parentId = ev.parentTaskId && ev.parentTaskId !== run.rootTaskId ? childId(ev.parentTaskId) : run.runId;
213
+ // [WF2-A] redact the forwarded subagent name for parity with the top-level run name (see onEvent above).
214
+ // §K-7: ev.name IS the subagent type → also surface it as `agentType` (picker short label). Reuse the value.
108
215
  const fwdName = redactSecrets(ev.name ?? ev.taskId);
109
216
  if (!childStartedAt.has(cid))
110
217
  childStartedAt.set(cid, Date.now());
111
218
  if (ev.parentToolCallId)
112
219
  childByToolCall.set(ev.parentToolCallId, cid);
113
- bus.publishTask({ id: cid, name: fwdName, ...(ev.name ? { agentType: fwdName } : {}), parentId, scope: run.scope, ...sessionField, status: tickStatus(ev.status), tokens: sumTokens(ev.usage), ...(() => { const t = toolUsesOf(ev.usage); return t !== undefined ? { toolUses: t } : {}; })(), elapsedMs: Date.now() - childStartedAt.get(cid) });
220
+ bus.publishTask({ id: cid, name: fwdName, ...(ev.name ? { agentType: fwdName } : {}), parentId, scope: run.scope, ...sessionField, status: tickStatus(ev.status), tokens: sumTokens(ev.usage), ...(() => { const t = toolUsesOf(ev.usage); return t !== undefined ? { toolUses: t } : {}; })(), elapsedMs: Date.now() - childStartedAt.get(cid) }); // [1415]③ 同上;[1748] toolUses 同 bg lane 口径
114
221
  },
115
222
  onChildTerminal(taskId, status, altId, toolUseId) {
223
+ // A background subagent/bash CHILD settles — task_progress never emits a terminal tick,
224
+ // so without this the child row sat "running" until the PARENT leg settled (the shell measured 93s of
225
+ // phantom running; its auto-exit release condition never fired). Flip the status so subscribers SEE the
226
+ // terminal frame, then remove (mirroring onTerminal's leave-the-fleet posture). Idempotent on an unknown
227
+ // child. ⚠️ the notification's task_id is the a* domain while ticks key by the child uuid — a live
228
+ // mid-turn flip can therefore miss the tick-built row (flip-through mints the a* row instead); id-domain
229
+ // unification is core's half. Post-settle: rows are ALREADY removed (the settle evict is the
230
+ // shell's release signal) — a flip-through here would mint a fresh orphan row. No-op.
116
231
  if (settledLeg)
117
232
  return false;
233
+ // [1332]①:id 双域候选——tick 行键域(child sessionId uuid)与通知键域(a* task_id)因 core 版本/
234
+ // lane 而异,单键押注押错=真行永不落 completed(绿点不回,行滞留 running 到父 settle)。两候选谁
235
+ // 有活行翻谁;都没有才按首候选合成瞬态终帧(bash 无 tick 形,原语义)。
236
+ // codex R3:killed 保桶(与 a* 车道 fleetBackgroundChildPublisher 的终态映射一致)——操作员/系统
237
+ // 取消不得错报为执行失败;同一 child 两车道给订阅者的终态必须同色。
118
238
  const fleetStatus = status === "completed" ? "completed" : status === "killed" || status === "cancelled" ? "killed" : "failed";
239
+ // codex F1:两 id 域可能**同时**各有一行(重复/版本偏斜投递,onEvent 与 onForwardEvent 各按一域建)
240
+ // ——单选一行会漏掉另一域的行,滞留 running 到父 settle(绿点不回复发)。翻**全部**属本 publisher 的
241
+ // 候选行,逐一终帧+离场。
242
+ // codex R2:第三候选 = 通知 toolUseId 经 spawn 关联解出的 cid。core 的失败/killed 收尾通知缺 sessionId
243
+ // (subagent.js catch 分支两处只带 task_id;成功路径才条件带)——此时前两候选同为 a* 域,tick 建的 uuid
244
+ // 行押不中;toolUseId↔tick.parentToolCallId 是同一次 Task 调用的同源 id,把真行找回来。
119
245
  const candidateCids = [childId(taskId)];
120
246
  if (altId !== undefined && altId !== taskId)
121
247
  candidateCids.push(childId(altId));
@@ -124,6 +250,7 @@ export function fleetRunPublisher(bus, run) {
124
250
  candidateCids.push(viaToolCall);
125
251
  const liveCids = candidateCids.filter((c) => children.has(c));
126
252
  const hadRow = liveCids.length > 0;
253
+ // 都没活行 = bash 无 tick 形:按首候选合成瞬态终帧(建即离,诚实且无害)。
127
254
  for (const cid of hadRow ? liveCids : [childId(taskId)]) {
128
255
  const startedAtChild = childStartedAt.get(cid);
129
256
  bus.publishTask({ id: cid, ...(children.has(cid) ? {} : { name: taskId, parentId: run.runId, scope: run.scope, ...sessionField }), status: fleetStatus, ...(startedAtChild !== undefined ? { elapsedMs: Date.now() - startedAtChild } : {}) });
@@ -137,8 +264,9 @@ export function fleetRunPublisher(bus, run) {
137
264
  return hadRow;
138
265
  },
139
266
  onTerminal(status, residuals) {
140
- settledLeg = true;
267
+ settledLeg = true; // freeze — nothing publishes on this leg's publisher after the settle
141
268
  const fleetStatus = runStatusToFleet(status);
269
+ // [1839]①/(a) 案:真终态帧带残局键(有源才带,键逐挑不 spread);parked 帧不带(行还活着)。
142
270
  const terminal = fleetStatus === "completed" || fleetStatus === "failed" || fleetStatus === "killed";
143
271
  const res = terminal && residuals
144
272
  ? {
@@ -148,17 +276,27 @@ export function fleetRunPublisher(bus, run) {
148
276
  }
149
277
  : {};
150
278
  bus.publishTask({ id: run.runId, status: fleetStatus, tokens, elapsedMs: Date.now() - startedAt, ...res });
279
+ // Subagent CHILD rows leave on ANY settle — terminal OR parked (TOC review #8: a suspended/needs_review run
280
+ // keeps its row, but its subagents are NOT running while the parent is parked — their work is checkpointed; a
281
+ // task_progress never emits a terminal, so without this the child rows leak forever as stale "running" under a
282
+ // parked parent). On resume, fresh task_progress/onForwardEvent re-adds the active children.
151
283
  for (const cid of children)
152
284
  bus.removeTask(cid);
153
285
  children.clear();
154
- childStartedAt.clear();
155
- childByToolCall.clear();
286
+ childStartedAt.clear(); // codex F2:长寿 bg child 的计时项不得随 publisher 句柄泄漏累积(晚到回调可达期)
287
+ childByToolCall.clear(); // codex R2 同理:spawn 关联表随叶 settle 清空
288
+ // A truly-terminal run LEAVES the fleet (the shell saw the terminal frame first). A PARKED run
289
+ // (suspended→waiting / needs_review→awaiting approval) is still active → its ROW STAYS in the fleet.
156
290
  if (terminal) {
157
291
  bus.removeTask(run.runId);
158
292
  }
159
293
  },
160
294
  };
161
295
  }
296
+ /** [1839]①/(a) 案:TaskResult → 终态行帧残局键映射(sync/background/resume 三条腿各自 settle,共用一处
297
+ * 映射——键名映射写三遍必漂移)。usage 与 {@link BgNotification.usage} 同形:stats.tokens→totalTokens、
298
+ * stats.toolCalls→toolUses(名对齐,消费端一个形状)。errorCode "cancelled" ⇒ stoppedBy:"user"(与
299
+ * markStopSource 的归因值同源);transcriptId 顶层 = run 的 sessionId([1840]§二拍)。缺源的键不铸。 */
162
300
  export function fleetRunResiduals(result) {
163
301
  if (!result)
164
302
  return {};
@@ -177,6 +315,22 @@ export function fleetRunResiduals(result) {
177
315
  ...(result.sessionId ? { transcriptId: result.sessionId } : {}),
178
316
  };
179
317
  }
318
+ /**
319
+ * design/129-B (core 1.240.0) — the PROCESS-LEVEL background-child fleet publisher, wired once
320
+ * onto `RunnerDeps.onBackgroundChildEvent`. Unlike {@link fleetRunPublisher} (per-leg: dies at leg settle —
321
+ * the root cause: a session-scoped bg child outliving its turn had NO forward path, fleet showed zero
322
+ * child frames), this observer lives as long as the process and covers the child's WHOLE lifecycle:
323
+ * spawn → row appears the moment the child registers (launch→turn-tail 零帧 fixed: no more waiting for a
324
+ * first tick that a slow child never emits inside the turn);
325
+ * tick → token rollup onto the row; ALSO best-effort removes the per-leg uuid-keyed TWIN row the leg's
326
+ * onForwardEvent built for the same child (`${parentTaskId} ${progressTaskId}` composite — the
327
+ * per-leg childId shape), so the child shows ONCE, keyed by its stable a* handle;
328
+ * terminal → terminal frame under the a* row id, row leaves the fleet, and the contract
329
+ * `bg_notification` frame rides the always-open stream (缺口②'s immediate idle delivery).
330
+ * Rows are tagged `scope` (tenant filter) from the registry scope and `sessionId` (the `?session=` filter)
331
+ * from the registry owner when session-scoped (owner IS the host sessionId; task-scoped children have no
332
+ * session attribution → unscoped, back-compat visible). Names ride the same redactSecrets discipline.
333
+ */
180
334
  export function fleetBackgroundChildPublisher(bus, log) {
181
335
  if (!bus)
182
336
  return () => undefined;
@@ -185,6 +339,7 @@ export function fleetBackgroundChildPublisher(bus, log) {
185
339
  log?.(msg, fields);
186
340
  }
187
341
  catch {
342
+ /* observability must never fault the observer */
188
343
  }
189
344
  };
190
345
  const meta = new Map();
@@ -194,6 +349,11 @@ export function fleetBackgroundChildPublisher(bus, log) {
194
349
  meta.delete(id);
195
350
  meta.set(id, m);
196
351
  if (meta.size > MAX) {
352
+ // codex 两轮([1338]④ 复审):逐出**只打墓碑**(done)。R1:逐最老会把在跑 child 的 spawnedAt 挤掉,
353
+ // 下个 tick lazy-mint 重起表=elapsedMs 归零。R2(更重):全活时垫底逐活儿,重生条目 tenantScope 落
354
+ // "default"、owner/parent 全失——**跨租户错归因**(scoped 流按 "default" 键还能收到别家 child 的终态
355
+ // 通知残料)。活溯源绝不逐出:无墓碑=不逐,活基数由 registry 真并发界定(每条 Meta 极小);病态膨胀
356
+ // 打一次 warn 供观测。墓碑仍受 MAX 界(terminal 后条目=墓碑,自然轮换)。
197
357
  let victim;
198
358
  for (const [k, v] of meta) {
199
359
  if (v.done) {
@@ -210,12 +370,28 @@ export function fleetBackgroundChildPublisher(bus, log) {
210
370
  }
211
371
  }
212
372
  };
373
+ // [1338]③ 换算臂:core spawn emit 现把 hostSessionId 装进 parentTaskId(会话 id,非行 id)→ 子行
374
+ // parentId 指向不存在的行=孤儿伪影(值域修在 core)。server 兜:parentTaskId 不是现存行 id、却恰是
375
+ // 某 TOP-LEVEL run 行的 sessionId 时,换算成该 run 行 id。guard 式——core 修后 parentTaskId 直接命中
376
+ // 行 id,此臂自然失活;无命中(run 行未起/已离场)保持原值,孤儿顶格渲染,不误挂。
377
+ // codex R3(M1):首次**成功**解析即冻结进 Meta.resolvedParentId——逐拍重解会把跨 run 存活的长寿
378
+ // child 重挂到同会话后起的 run 行(launch 溯源被静默改写);孤儿(未成功)下拍再试。
213
379
  const resolveParentId = (parentInput, domain, childScope) => {
380
+ // codex R5:**每一条**解析分支都同租户校验(r.scope === childScope)——submit 收任意 sessionId,
381
+ // 碰撞可让 A 家的孙冻结到 B 家的行(fleet-wide 视图伪嵌套)。跨租户一律按未命中:孤儿顶格,fail-closed。
382
+ // codex(1.350 四轮):解析带**域标**——session 域链接(parentSessionLink)跳过行 id 直查与 uuid 别名
383
+ // 两分支(会话 id 由调用方任报,与既有 run 行 id 撞值时直查会把孩子冻到无关 run 上),只走 sessionId
384
+ // 匹配译臂;task 域三分支全走。
214
385
  const rows = bus.snapshot().tasks;
215
386
  if (domain === "task") {
216
387
  if (rows.some((r) => r.id === parentInput && r.scope === childScope))
217
388
  return { id: parentInput, resolved: true };
218
389
  }
390
+ // codex R4(M-B)+ PAIR-REVIEW F-1:嵌套 bg 孙的父链接=父 **agent 的 uuid**——core 1.350+ 真实帧形里
391
+ // 该值落 **parentSessionId**(session 域;[1344]② 钳掉了洗域 parentTaskId),所以别名逆查必须对
392
+ // **两个域**开放(此前只挂 task 域=1.351 下三臂死代码,PAIR-REVIEW F-1 CONFIRMED)。scope-safe:
393
+ // 别名命中恒要求同租户(R5 的禁令针对**行 id 直查**分支——那才是任报值撞行的面;别名表是本
394
+ // publisher 自记的 spawn 事实,加租户校验后无跨户面)。
219
395
  for (const [aStar, pm] of meta) {
220
396
  if (pm.aliasUuid === parentInput && pm.tenantScope === childScope) {
221
397
  if (rows.some((r) => r.id === aStar && r.scope === childScope))
@@ -224,14 +400,20 @@ export function fleetBackgroundChildPublisher(bus, log) {
224
400
  }
225
401
  let match;
226
402
  for (const r of rows) {
403
+ // codex R7(high):会话译只认**真 run 行**——排除一切本 publisher 记账的 a* child 行(meta 键)。
404
+ // session-scoped a* 孤儿行同样带 sessionId、R6 后无 parentId、同 scope,不排除则孤儿 tick 会把
405
+ // **自己**(或同门孤儿)选成父并冻结=自环树,晚到的真 run 行永远接不上。
227
406
  if (r.sessionId === parentInput && r.parentId === undefined && r.scope === childScope && !meta.has(r.id))
228
- match = r.id;
407
+ match = r.id; // 后写覆盖=取最近的同租户 run 行
229
408
  }
230
409
  return match !== undefined ? { id: match, resolved: true } : { id: parentInput, resolved: false };
231
410
  };
232
411
  const rowTags = (m) => {
412
+ // codex R6:未解析成功=**不发 parentId**(原值只留 Meta 供下拍重试)。发原值就是 [1338]③ 伪影本身
413
+ // (悬空 parentId 指向不存在的行),且 fleet-wide 视图上一个撞值的外租户行 id 会在渲染端伪嵌套——
414
+ // 行早发孤儿顶格、解析成功后 MERGE 升级补 parentId,两边都诚实。
233
415
  let parentId;
234
- const parentInput = m.parentTaskId ?? m.parentSessionLink;
416
+ const parentInput = m.parentTaskId ?? m.parentSessionLink; // 1.350 fallback 形:会话域链接同走解析臂(带域标)
235
417
  if (parentInput) {
236
418
  if (m.resolvedParentId !== undefined) {
237
419
  parentId = m.resolvedParentId;
@@ -248,8 +430,8 @@ export function fleetBackgroundChildPublisher(bus, log) {
248
430
  ...(m.tenantScope ? { scope: m.tenantScope } : {}),
249
431
  ...(m.hostSessionId ? { sessionId: m.hostSessionId } : {}),
250
432
  ...(parentId !== undefined ? { parentId } : {}),
251
- ...(m.workflowRunId !== undefined ? { workflowRunId: m.workflowRunId } : {}),
252
- ...(m.parentToolCallId !== undefined ? { parentToolCallId: m.parentToolCallId } : {}),
433
+ ...(m.workflowRunId !== undefined ? { workflowRunId: m.workflowRunId } : {}), // [1440] 附注位透传
434
+ ...(m.parentToolCallId !== undefined ? { parentToolCallId: m.parentToolCallId } : {}), // P1-2(core 1.432)E2 原值域
253
435
  ...(m.spawnedAt !== undefined ? { startedAt: m.spawnedAt, elapsedMs: Date.now() - m.spawnedAt } : {}),
254
436
  };
255
437
  };
@@ -262,25 +444,51 @@ export function fleetBackgroundChildPublisher(bus, log) {
262
444
  return u.tokens;
263
445
  return undefined;
264
446
  };
447
+ // design/158 A13: the three event-kind branches below are named local functions — same closure scope/capture
448
+ // as when they were inline `if (e.kind === "...") { ... }` blocks in the returned dispatcher (behavior
449
+ // identical), alongside the already-named helpers above (dlog/remember/resolveParentId/rowTags/sumUsage).
265
450
  const handleSpawn = (e) => {
451
+ // PAIR-REVIEW F-3:revive spawn(spawn-after-tombstone)缺父字段时**继承墓碑 Meta 的父链**——
452
+ // 上一周期已解析冻结的 parentTaskId/resolvedParentId 不因重建丢失(core 1.351 revive spawn 不回放
453
+ // 父链;1.352 回放件到货后此臂自然让位,双保险)。只在新帧零父字段时继承,新值恒赢。
266
454
  const tomb = meta.get(e.taskId);
267
455
  const inheritParent = !e.parentTaskId && !e.parentSessionId && tomb?.done === true;
268
456
  const m = {
457
+ // codex 两轮(1.350 适配):core 1.350 起 fallback 形不再发洗域 parentTaskId([1364]②),补偿链接改走
458
+ // 声明字段 parentSessionId(/v1/tasks/stream 主车道 spec.taskId 未设=恰此形)。**两域分存**——
459
+ // parentTaskId=真任务域(可直出 wire),parentSessionLink=会话域(仅作行嵌套解析输入,绝不冒充
460
+ // 任务 id 出 bg_notification)。
269
461
  ...(e.parentTaskId ? { parentTaskId: e.parentTaskId } : {}),
270
462
  ...(!e.parentTaskId && e.parentSessionId ? { parentSessionLink: e.parentSessionId } : {}),
271
463
  ...(inheritParent && tomb?.parentTaskId !== undefined ? { parentTaskId: tomb.parentTaskId } : {}),
272
464
  ...(inheritParent && tomb?.parentSessionLink !== undefined ? { parentSessionLink: tomb.parentSessionLink } : {}),
273
465
  ...(inheritParent && tomb?.resolvedParentId !== undefined ? { resolvedParentId: tomb.resolvedParentId } : {}),
466
+ // session-scoped: registry owner IS the host sessionId (design/129 owner key); fork spawns also carry
467
+ // the child's uuid sessionId — that is the a*↔uuid cross-system anchor, NOT the host session, so it is not used here.
468
+ // [1522] LOW4:session-scoped 臂同样 root-first(另两臂 1.250 已升)——嵌套 session-scoped 形
469
+ // 的 owner=中间层子会话 uuid,标它=over-filter;显式 root 到货即锚 root(近死码但一处改齐)。
274
470
  ...(e.sessionScoped && e.owner ? { hostSessionId: e.rootSessionId ?? e.owner } : {}),
471
+ // 🔴 scope DOMAIN mapping: core's registry scope is `ctx.principal ?? deployment scope` —
472
+ // UNDEFINED on a single-user no-principal deployment — while the service fleet domain keys the
473
+ // no-principal caller as "default" (`gatedPrincipal ?? "default"`, streamFleet's callerScope). Without
474
+ // this map the row/notification carried NO scope and the scoped stream dropped EVERYTHING (fail-closed
475
+ // — the "terminal/bg_notification 零帧" repro). Same principal string in both domains when
476
+ // a principal exists, so the map is exact.
275
477
  tenantScope: e.scope ?? "default",
276
478
  sessionScoped: e.sessionScoped,
479
+ // core 1.367 δ:真 launch 锚(revive=wake 时刻)优先;旧 core 帧回落收帧时刻([1338]④ 原形)
277
480
  spawnedAt: e.startedAt ?? Date.now(),
278
481
  ...(e.rootSessionId ? { rootSessionId: e.rootSessionId } : {}),
279
- ...(e.parentToolCallId ? { parentToolCallId: e.parentToolCallId } : {}),
280
- ...(e.sessionId ? { aliasUuid: e.sessionId } : {}),
281
- ...(e.workflowRunId ? { workflowRunId: e.workflowRunId } : {}),
482
+ ...(e.parentToolCallId ? { parentToolCallId: e.parentToolCallId } : {}), // P1-2(core 1.432,12 发射点全带)
483
+ ...(e.sessionId ? { aliasUuid: e.sessionId } : {}), // codex R4(M-B):uuid↔a* 别名(fork spawn 带 forkedId)
484
+ ...(e.workflowRunId ? { workflowRunId: e.workflowRunId } : {}), // [1440] wa* 归属附注
485
+ // codex 1.240-R1/R2(H 行半场):wa\* 帧 sessionScoped:false 无 host owner → 行无 sessionId=
486
+ // 「absent=同 principal 全会话可见」(bg 兼容语义,对 wa\* 是泄露面)。归属源两级:①**信任源**
487
+ // core 帧的 parentSessionId(发起会话,1.350 声明字段——R2:无 runStore 的瞬态 sync 部署没有宿主
488
+ // fleet 行,行查 fallback 必空);②宿主行 sessionId 查表(同租户)兜底。
282
489
  ...(e.workflowRunId && !(e.sessionScoped && e.owner)
283
490
  ? (() => {
491
+ // core 1.367 δ:显式 root 锚(spawnAttribution 把 root 传进每个 workflow-agent)——信任源第一
284
492
  if (e.rootSessionId)
285
493
  return { hostSessionId: e.rootSessionId };
286
494
  if (e.parentSessionId)
@@ -289,6 +497,33 @@ export function fleetBackgroundChildPublisher(bus, log) {
289
497
  return host?.sessionId ? { hostSessionId: host.sessionId } : {};
290
498
  })()
291
499
  : {}),
500
+ // [1493] cross-session isolation: a NON-session-scoped, non-wa* bg child (owner = the run taskId — the
501
+ // norm when backgroundScope!="session", i.e. every multi-tenant deployment, and any local path where the
502
+ // session isn't adopted at spawn) STILL carries a host session on core's declared parentSessionId
503
+ // (subagent.js registerBackgroundAgent). Without promoting it to hostSessionId the row/notification is
504
+ // session-UNTAGGED → streamFleet's `?session=` filter fails OPEN → the completion is broadcast (and
505
+ // model-injected) into every same-principal shell (clay's dual-shell repro). Promote it so the filter
506
+ // narrows precisely. (Session-scoped children already tag via the `owner` arm above; wa* via its own arm
507
+ // just above — both are excluded by this condition, so no double-write.) The terminal event does NOT
508
+ // repeat parentSessionId (core emits it on spawn only), so this MUST be captured into Meta here at spawn.
509
+ //
510
+ // codex R1 (nested-agent mis-tag): parentSessionId is core's `ctx.sessionId`, which for a NESTED bg child
511
+ // (spawned BY a subagent) is the PARENT AGENT's child-session uuid, NOT the shell's root session. Tagging
512
+ // that uuid as hostSessionId would make the outer host shell FAIL the ownerSessionId check (row +
513
+ // completion suppressed, durable ack fence keyed wrong). So resolve through the alias table (same reverse
514
+ // lookup resolveParentId uses): if some agent Meta's aliasUuid === parentSessionId, this is nested —
515
+ // inherit THAT agent's already-resolved hostSessionId (the root shell session), or stay UNTAGGED when the
516
+ // parent itself is untagged. Only a TOP-LEVEL bg child (parentSessionId is the shell root, aliased by no
517
+ // agent) uses parentSessionId directly. Tenant-scoped like every other alias/parent resolution (R5).
518
+ // fable5 R1 (honest residual): a nested child whose parent Meta is ABSENT (restart lazy-mint edge — live
519
+ // Meta is never evicted, so within one process the parent always exists at spawn time) is
520
+ // INDISTINGUISHABLE from top-level and gets tagged with the given uuid. That is still SAFE: a
521
+ // child-session uuid is never any shell's own session, so no scoped subscriber matches it — the failure
522
+ // direction is over-filtering (the true owner misses live delivery; durable inbox/stream-open drain
523
+ // compensate), never cross-delivery. Root fix = core carrying an explicit root-host-session (or a
524
+ // top-level/nested discriminator) on the spawn event — asked as a core seam follow-up ([1493]).
525
+ // core 1.367 δ:[1493] fable5-R1 注里请的 root fix **到货**——spawn 帧显式带 rootSessionId
526
+ // (固定点语义,嵌套孙代恒=root shell 会话),信任源直用;alias 反查臂降为旧 core 帧回落。
292
527
  ...(!(e.sessionScoped && e.owner) && !e.workflowRunId && (e.rootSessionId ?? e.parentSessionId)
293
528
  ? (() => {
294
529
  if (e.rootSessionId)
@@ -296,19 +531,34 @@ export function fleetBackgroundChildPublisher(bus, log) {
296
531
  const childScope = e.scope ?? "default";
297
532
  for (const pm of meta.values()) {
298
533
  if (pm.aliasUuid === e.parentSessionId && (pm.tenantScope ?? "default") === childScope) {
299
- return pm.hostSessionId ? { hostSessionId: pm.hostSessionId } : {};
534
+ return pm.hostSessionId ? { hostSessionId: pm.hostSessionId } : {}; // nested: inherit root (or stay untagged → Part B)
300
535
  }
301
536
  }
302
- return { hostSessionId: e.parentSessionId };
537
+ return { hostSessionId: e.parentSessionId }; // top-level: parentSessionId IS the shell root session
303
538
  })()
304
539
  : {}),
305
540
  };
306
541
  remember(e.taskId, m);
542
+ // [1364]③:spawn 帧 1.349+ 也带 agentType(类型名)/name——行 name 位保 description(display 标签,
543
+ // 历史语义),TYPE 列自 spawn 即亮(此前要等首 tick 自愈)。
544
+ // [1827]①(cli):spawn 行也透传 transcriptId(委派 prompt 的映射,详情页运行中即可取件)。
545
+ // 现状 core 只在 terminal 事件带此键(三发射点亲核)⇒ 本透传对旧 core 惰性;core 停 spawn/tick
546
+ // 源头补上即通,tick 臂(下方 :78x)早已同姿。server 不自行以 sessionId 推导——fork lane 的
547
+ // forkTranscriptId 与 sessionId 的等价关系归 core 所有,不在消费端烙死。
307
548
  bus.publishTask({ id: e.taskId, name: redactSecrets(e.description ?? e.name ?? e.taskId), ...(e.agentType ? { agentType: redactSecrets(e.agentType) } : {}), ...rowTags(m), status: "running", tokens: 0, ...(e.transcriptId ? { transcriptId: e.transcriptId } : {}) });
308
549
  dlog("bg_child_event", { kind: "spawn", taskId: e.taskId, sessionScoped: e.sessionScoped, scope: m.tenantScope, hostSessionId: m.hostSessionId ?? null, parentTaskId: m.parentTaskId ?? null });
309
550
  };
310
551
  const handleTick = (e, m) => {
552
+ // dedup the per-leg uuid-keyed twin ONCE: the leg's onForwardEvent keys the same child's rows by
553
+ // `${runId} ${uuid}` and on the /v1/runs path runId === the host canonical taskId (spec.taskId is the
554
+ // durable run id). The tick that carries the child's OWN frame has progressParentTaskId === the host
555
+ // taskId (a NESTED grandchild carries the child's uuid instead — never suppressed here). A miss is a
556
+ // no-op remove (best-effort; worst case = a transient duplicate row until the leg settles, old behavior).
311
557
  if (!m.suppressedTwin && e.progressTaskId && (!e.progressParentTaskId || e.progressParentTaskId === (m.parentTaskId ?? m.parentSessionLink))) {
558
+ // The per-leg childId is `${run.runId} ${uuid}` and runId ≠ the core hostTaskId on the
559
+ // sync-stream/resume paths (durableTaskId vs canonical sessionId), so a composite-key guess misses there.
560
+ // Scan-by-suffix instead: the uuid tail uniquely names the child across every leg's runId prefix. One-shot
561
+ // (suppressedTwin) so the O(rows) scan runs once per child.
312
562
  const tail = ` ${e.progressTaskId}`;
313
563
  for (const row of bus.snapshot().tasks) {
314
564
  if (row.id.endsWith(tail))
@@ -316,6 +566,13 @@ export function fleetBackgroundChildPublisher(bus, log) {
316
566
  }
317
567
  m.suppressedTwin = true;
318
568
  }
569
+ // codex R8:普通(非 fork)bg producer 的 spawn 不带 sessionId,uuid 别名要等 terminal 才现——嵌套孙
570
+ // 在父运行期解析全 miss。但 child 本人的 tick 恒带 progressTaskId=其 uuid(与双生抑制同一判别形),
571
+ // 首 tick 即学别名;孙侧 retry-until-success 语义随后一拍自然接上(spawn 路径已带 sessionId 的 fork 形
572
+ // 不受影响,??= 只补缺)。
573
+ // codex R9:别名习得**即回填**——快孙可能已无后续帧(spawn+tick+terminal 全在父首 tick 前),等孙自己
574
+ // retry 就永远孤儿。习得此刻主动扫在场未解析孤儿,替它们把行升级(rowTags 内解析+冻结)。彻底闭窗
575
+ // (孙整个生命周期都在别名前走完的瞬态孤儿)在 core:普通形 spawn emit 补 sessionId(fork 形已带)。
319
576
  if (m.aliasUuid === undefined && e.progressTaskId && (!e.progressParentTaskId || e.progressParentTaskId === (m.parentTaskId ?? m.parentSessionLink))) {
320
577
  m.aliasUuid = e.progressTaskId;
321
578
  for (const [cid, cm] of meta) {
@@ -326,15 +583,30 @@ export function fleetBackgroundChildPublisher(bus, log) {
326
583
  }
327
584
  const tokens = sumUsage(e.usage);
328
585
  const name = e.name ? redactSecrets(e.name) : undefined;
586
+ // [1364]③ K-7 换位:TYPE 列取 tick 帧的行级 `agentType`(core 1.350 定谳:`name` 位=display 标签
587
+ // ——description 充是历史语义非 bug,类型名在 agentType 位)。缺省回落 name(旧 core 兼容,原行为)。
329
588
  const agentType = e.agentType ? redactSecrets(e.agentType) : name;
589
+ // The sink tick carries core's currentAction (its only attachment point today) —
590
+ // UNTRUSTED (tool argument head) → redact, same discipline as name. Additive; absent until a tool runs.
330
591
  const currentAction = e.currentAction ? redactSecrets(e.currentAction) : undefined;
592
+ // [1827]②/core 1.429:结构化同源体。字段 PICKED(不整对象 spread——future core 键不得裸骑);
593
+ // toolName verbatim,target 与 currentAction 同边界(redact + 300 bound,brainStatus.detail 同惯例)。
331
594
  const currentTool = e.currentTool
332
595
  ? { toolName: e.currentTool.toolName, ...(e.currentTool.target !== undefined ? { target: redactSecrets(e.currentTool.target).slice(0, 300) } : {}) }
333
596
  : undefined;
597
+ // cli [1748]:两个 additive 位。`toolUses` 是**累计值**(与 turn_end 的每轮增量相反)⇒ 直接上行不累加;
598
+ // 缺席时**不发这个键**(消费方不得把缺席当 0)。`transcriptId` 是委派 prompt 的**映射** ——
599
+ // prompt 本身不在 `BackgroundChildEvent` 上,server 收不到就不造。
334
600
  bus.publishTask({ id: e.taskId, ...rowTags(m), status: "running", ...(tokens !== undefined ? { tokens } : {}), ...(name ? { name } : {}), ...(agentType ? { agentType } : {}), ...(currentAction ? { currentAction } : {}), ...(currentTool ? { currentTool } : {}), ...(e.usage?.toolUses !== undefined ? { toolUses: e.usage.toolUses } : {}), ...(e.transcriptId ? { transcriptId: e.transcriptId } : {}) });
335
601
  };
336
602
  const handleTerminal = (e, m) => {
603
+ // terminal: flip the row so subscribers SEE the terminal frame, then leave the fleet — and push the
604
+ // contract bg_notification on the always-open lane (缺口②: idle delivery is immediate; the durable
605
+ // inbox park stays as the offline/replay belt, shell dedups by (taskId,status)).
337
606
  const status = e.status === "completed" ? "completed" : e.status === "killed" ? "killed" : "failed";
607
+ // [1839]①/(a) 案:终态**行帧**同带残局键——此前只有 {id,status},看行卡(不订通知帧)的 idle 观察者
608
+ // 拿不到终局。与下方 bg_notification 同源同姿势:键逐挑不 spread、editedFiles path 过 redactSecrets
609
+ // + 100 界、缺席不铸。(recentSteps 不进行帧——通知卡语义,行卡不渲染步骤列表。)
338
610
  bus.publishTask({
339
611
  id: e.taskId, ...rowTags(m), status,
340
612
  ...(e.stoppedBy ? { stoppedBy: e.stoppedBy } : {}),
@@ -355,6 +627,9 @@ export function fleetBackgroundChildPublisher(bus, log) {
355
627
  : {}),
356
628
  });
357
629
  bus.removeTask(e.taskId);
630
+ // codex 1.240-R1(M2):1.356 的回调序=bceTick 先于 host forward——tick 处的双生抑制扫在 uuid 双生
631
+ // 行发布**之前**,one-shot 空扫后置旗,双生行永存。terminal 补扫一次(aliasUuid=tick 学到的 child
632
+ // uuid),把 run-leg 的复合键行清场。
358
633
  if (m.aliasUuid) {
359
634
  const tail = ` ${m.aliasUuid}`;
360
635
  for (const row of bus.snapshot().tasks) {
@@ -362,19 +637,32 @@ export function fleetBackgroundChildPublisher(bus, log) {
362
637
  bus.removeTask(row.id);
363
638
  }
364
639
  }
640
+ // codex 1.240-R1(H1):wa\*(workflowRunId 在)不走 bg_notification 契约——该帧族=后台任务完成通知
641
+ // (壳注入模型),workflow 的完成通知已有 workflow_complete 专链;且 1.356 wa\* 帧 sessionScoped:false
642
+ // 无 host owner → 通知无 ownerSessionId=同租户**全会话**可见(streamFleet 的 absent-放行是 bg 兼容位,
643
+ // 不是 wa\* 的授权)。per-agent 完成本就不该打断模型(CC 亦无此形)。
365
644
  if (m.workflowRunId !== undefined) {
366
- m.done = true;
645
+ m.done = true; // codex 1.240-R2(M):早退分支必须先落墓碑——迟到/重放 tick 不得复活已离场的 wa* 行
367
646
  dlog("bg_child_event", { kind: "terminal-wa-no-notification", taskId: e.taskId, workflowRunId: m.workflowRunId });
368
647
  return;
369
648
  }
370
649
  bus.publishBgNotification({
371
650
  taskId: e.taskId,
372
651
  ...(e.sessionId ? { sessionId: e.sessionId } : {}),
652
+ // [1392]①(PAIR-REVIEW F-1@cli 的 wire 前置):终帧 seq(core 1.352 BackgroundChildEvent.terminal 补位,
653
+ // tolerate-absent——旧 core 无此位=不发,cli 键折 seq 的修依赖它区分 revive 周期)。
373
654
  ...(typeof e.seq === "number" ? { seq: e.seq } : {}),
374
655
  status: e.status ?? "failed",
375
656
  ...(e.summary ? { summary: redactSecrets(e.summary) } : {}),
376
657
  scope: (m.sessionScoped || e.sessionScoped) ? "session" : "task",
658
+ // codex(1.350 二轮):wire 的 parentTaskId 位只出真任务域;fallback 形出解析成功的 run 行 id
659
+ // (=durable run id,消费者拿它绑父行),解析未成=省略,绝不让会话 id 冒充任务 id 出 wire。
377
660
  ...(m.parentTaskId ? { parentTaskId: m.parentTaskId } : m.resolvedParentId ? { parentTaskId: m.resolvedParentId } : {}),
661
+ // The residual fields must ride THIS lane too (the "kill across turns" main line renders
662
+ // off it). Same posture as project.ts/inbox; fields picked, arrays defensively bounded.
663
+ // P1-3(core 1.452,[1925] 一轮批):completionId=子代完成的幂等锚,消费端(cli)按它对同一完成的
664
+ // 多路通知(bg_notification/task_notification/inbox 重放)去重。verbatim 透传,仅通知帧带
665
+ // (行帧不带——行的身份是 taskId,幂等锚是通知语义)。
378
666
  ...(e.completionId ? { completionId: e.completionId } : {}),
379
667
  ...(e.stoppedBy ? { stoppedBy: e.stoppedBy } : {}),
380
668
  ...(e.resumable !== undefined ? { resumable: e.resumable } : {}),
@@ -382,6 +670,7 @@ export function fleetBackgroundChildPublisher(bus, log) {
382
670
  ? { recentSteps: e.recentSteps.slice(0, 10).map((s) => ({ tool: s.tool, target: redactSecrets(s.target), outcome: redactSecrets(s.outcome) })) }
383
671
  : {}),
384
672
  ...(e.editedFiles !== undefined ? { editedFiles: e.editedFiles.slice(0, 100).map((f) => ({ path: redactSecrets(f.path), edits: f.edits })) } : {}),
673
+ // [1543]§二 LOW:usage/transcriptId 补齐(fields picked——usage 六数值键逐一挑,不整对象 spread)。
385
674
  ...(e.usage
386
675
  ? {
387
676
  usage: {
@@ -395,13 +684,14 @@ export function fleetBackgroundChildPublisher(bus, log) {
395
684
  }
396
685
  : {}),
397
686
  ...(e.transcriptId ? { transcriptId: e.transcriptId } : {}),
398
- ...(e.parentToolCallId ? { parentToolCallId: e.parentToolCallId } : {}),
687
+ ...(e.parentToolCallId ? { parentToolCallId: e.parentToolCallId } : {}), // P1-2(core 1.432)——通知帧同带,cli「全部生命周期事件在场」
399
688
  ...(m.tenantScope ? { ownerScope: m.tenantScope } : {}),
400
689
  ...(m.hostSessionId ? { ownerSessionId: m.hostSessionId } : {}),
401
690
  ...(m.rootSessionId ? { rootSessionId: m.rootSessionId } : {}),
402
691
  });
692
+ // One info line per terminal so the emit-vs-filter bisect is a log-grep, not a rerun.
403
693
  dlog("bg_child_event", { kind: "terminal", taskId: e.taskId, status, scope: m.tenantScope ?? null, hostSessionId: m.hostSessionId ?? null, childSessionId: e.sessionId ?? null, bgNotificationPublished: true });
404
- m.done = true;
694
+ m.done = true; // tombstone (kept in the bounded map) — see Meta.done
405
695
  m.suppressedTwin = true;
406
696
  };
407
697
  return (e) => {
@@ -409,18 +699,20 @@ export function fleetBackgroundChildPublisher(bus, log) {
409
699
  handleSpawn(e);
410
700
  return;
411
701
  }
412
- const m = meta.get(e.taskId) ?? { sessionScoped: e.sessionScoped, tenantScope: "default", spawnedAt: Date.now() };
702
+ const m = meta.get(e.taskId) ?? { sessionScoped: e.sessionScoped, tenantScope: "default", spawnedAt: Date.now() }; // scope domain map holds on the lazily-minted path too([1338]④ 首见起表)
413
703
  if (!meta.has(e.taskId)) {
414
- remember(e.taskId, m);
704
+ remember(e.taskId, m); // tick/terminal without a seen spawn (restart/eviction edge) — row minted lazily
415
705
  dlog("bg_child_event", { kind: `${e.kind}-lazy-mint`, taskId: e.taskId, sessionScoped: e.sessionScoped });
416
706
  }
417
707
  else {
418
- remember(e.taskId, m);
708
+ remember(e.taskId, m); // codex:活儿每拍刷新近度——LRU 兜底永远先挤最久没动静的,不挤在跑的
419
709
  }
420
710
  if (m.done) {
711
+ // tombstone: this child already settled — a late tick must not resurrect a running row (settle-freeze 同族).
421
712
  dlog("bg_child_event", { kind: `${e.kind}-after-terminal-ignored`, taskId: e.taskId });
422
713
  return;
423
714
  }
715
+ // P1-2(core 1.432):lazy-mint/spawn 前旧 core 帧路径——parentToolCallId「出生就在场」,首见即补
424
716
  if (m.parentToolCallId === undefined && e.parentToolCallId)
425
717
  m.parentToolCallId = e.parentToolCallId;
426
718
  if (e.kind === "tick") {
@@ -430,15 +722,26 @@ export function fleetBackgroundChildPublisher(bus, log) {
430
722
  handleTerminal(e, m);
431
723
  };
432
724
  }
725
+ /** BC-1 (clay-decided 2026-06-27): a top-level run's fleet-row `name` = a SHORT, single-line **objective preview**
726
+ * (the readable "what is this task" label) — NOT the full objective dumped in, and NOT duplicated into `description`.
727
+ * `description` is left to the publisher's LIVE-ACTIVITY update (`onEvent` tool_start → the current tool), so the row
728
+ * shows `name`=objective + `description`=current activity (two DISTINCT things, killing the earlier "objective shown
729
+ * twice" dup). Whitespace-collapsed + capped ≤48. (A subagent CHILD row's name = its agent-type — BC-2.)
730
+ * SECRET-SAFE: redact secret shapes (redactSecrets) BEFORE truncating — a secret in the objective must not leak in
731
+ * the row name. The durable objective is already redacted; the name preview was asymmetric (raw) until this. */
433
732
  export function fleetRunLabels(objective) {
434
733
  const oneLine = redactSecrets((objective ?? "").replace(/\s+/g, " ")).trim();
435
734
  if (!oneLine)
436
735
  return { name: "task" };
736
+ // [1414]④:控制帧形 objective(注入 turn 的 `<task-notification>…` 等 XML 头)不得当行名——用户底部
737
+ // 会看到「<task-notifica…」尖括号伪影。以 `<` 开头且形如 XML tag 的 objective 给中性名;真实用户
738
+ // objective 以 `<` 开头的形(粘贴 HTML 片段)极罕且中性名无害。
437
739
  if (/^<[a-z][a-z0-9_-]*[\s>/]/i.test(oneLine))
438
740
  return { name: "(notification turn)" };
439
741
  const name = oneLine.length > 48 ? `${oneLine.slice(0, 47)}…` : oneLine;
440
742
  return { name };
441
743
  }
744
+ /** Map a service run status onto the neutral fleet vocabulary the shell renders. */
442
745
  export function runStatusToFleet(status, opts) {
443
746
  if (opts?.awaitingPlanApproval)
444
747
  return "awaiting approval";
@@ -451,10 +754,13 @@ export function runStatusToFleet(status, opts) {
451
754
  return "completed";
452
755
  case "failed":
453
756
  case "error":
454
- case "blocked":
757
+ case "blocked": // report_blocked = a non-success TERMINAL outcome (agent gave up) → the "failed" bucket (the
758
+ // neutral fleet vocab has no "blocked"). CRUCIAL: this also lets onTerminal REMOVE the row — the removal set is
759
+ // {completed,failed,killed}, so without mapping "blocked" here it fell through to the "idle" default and a
760
+ // terminal blocked run LEAKED a permanent stale "idle" row on the fleet (caught by on-box e2e, 2026-06-28).
455
761
  return "failed";
456
762
  case "suspended":
457
- return "waiting";
763
+ return "waiting"; // a durable suspend = parked, awaiting resume
458
764
  case "needs_review":
459
765
  return "awaiting approval";
460
766
  case "killed":