@sema-agent/server 7.43.0 → 7.44.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 (345) hide show
  1. package/USAGE.md +18 -0
  2. package/dist/adoption/plan.js +31 -192
  3. package/dist/adoption/quiesce.js +3 -86
  4. package/dist/adoption/runner.js +3 -140
  5. package/dist/adoption/sql.js +0 -74
  6. package/dist/adoption/wire.js +0 -80
  7. package/dist/approval-ask-machine.js +0 -75
  8. package/dist/approval-card.js +0 -323
  9. package/dist/approval-deny-reasons.js +0 -42
  10. package/dist/approval-hmac.js +0 -35
  11. package/dist/approval-reconciler.js +8 -166
  12. package/dist/approval.js +4 -67
  13. package/dist/audit.js +1 -44
  14. package/dist/auth-bridge.js +4 -47
  15. package/dist/auth-keys.js +0 -23
  16. package/dist/bake-runner/main.js +4 -65
  17. package/dist/bake-runner/protocol.js +3 -58
  18. package/dist/bake-runner/runner.js +5 -91
  19. package/dist/bench/l8/artifact.js +2 -61
  20. package/dist/bench/l8/escape.js +0 -25
  21. package/dist/bench/l8/index.js +0 -14
  22. package/dist/bench/l8/probes.js +0 -60
  23. package/dist/bench/l8/run-probes.js +2 -45
  24. package/dist/bench/s1/arms.js +14 -189
  25. package/dist/bench/s1/live-deps.js +11 -253
  26. package/dist/bench/s1/oracle.js +1 -36
  27. package/dist/bench/s1/repair-oracle-adapter.js +0 -30
  28. package/dist/bench/s1/reviewer.js +0 -34
  29. package/dist/bench/s1/row.js +0 -62
  30. package/dist/bench/s1/run-firm.js +4 -70
  31. package/dist/bench/s1/runner-ctx.js +0 -40
  32. package/dist/bench/s1/tasks.js +0 -115
  33. package/dist/boot/adoption.js +0 -20
  34. package/dist/boot/budget-tracing.js +3 -55
  35. package/dist/boot/config-center.js +43 -551
  36. package/dist/boot/coordinators.js +1 -69
  37. package/dist/boot/crash-last.js +0 -18
  38. package/dist/boot/deferred-sandbox-path-env.js +3 -119
  39. package/dist/boot/execution-env.js +5 -171
  40. package/dist/boot/governance-seams.js +0 -92
  41. package/dist/boot/leader.js +0 -69
  42. package/dist/boot/limit-sync.js +0 -2
  43. package/dist/boot/memory-boundary.js +3 -91
  44. package/dist/boot/org-memory.js +1 -25
  45. package/dist/boot/parked-revive-gate.js +0 -150
  46. package/dist/boot/permission-rules-audit.js +1 -56
  47. package/dist/boot/reapers.js +15 -273
  48. package/dist/boot/resolve-spec.js +9 -768
  49. package/dist/boot/retention-lane.js +4 -87
  50. package/dist/boot/runner-deps.js +3 -297
  51. package/dist/boot/runtime-caps.js +0 -40
  52. package/dist/boot/session-faces.js +2 -133
  53. package/dist/boot/shutdown.js +9 -83
  54. package/dist/boot/side-query-lane.js +2 -137
  55. package/dist/boot/stores.js +15 -215
  56. package/dist/boot/task-list-lane.js +0 -18
  57. package/dist/boot/webfetch-summarize-lane.js +0 -47
  58. package/dist/boot/workflow-orchestration.js +3 -99
  59. package/dist/boot-reclaim.js +0 -20
  60. package/dist/bounded-session-map.js +0 -19
  61. package/dist/brain.js +2 -139
  62. package/dist/budget.js +9 -244
  63. package/dist/capabilities/builtin-tools.js +0 -3
  64. package/dist/capabilities/center-plugins.js +6 -51
  65. package/dist/capabilities/center-prompts.js +6 -71
  66. package/dist/capabilities/code-review-council.js +7 -40
  67. package/dist/capabilities/collab-workflows.js +1 -44
  68. package/dist/capabilities/hands-lane.js +0 -65
  69. package/dist/capabilities/memory-notice.js +0 -70
  70. package/dist/capabilities/prompt.js +0 -14
  71. package/dist/capabilities/prompts/code-review.js +0 -14
  72. package/dist/capabilities/prompts/identity.js +0 -6
  73. package/dist/capabilities/prompts/team.js +0 -4
  74. package/dist/capabilities/repo-tools.js +0 -34
  75. package/dist/capabilities/sandbox-file-send.js +3 -92
  76. package/dist/capabilities/scenarios.d.ts +0 -1
  77. package/dist/capabilities/scenarios.js +18 -279
  78. package/dist/capabilities/select-environment-tool.js +0 -32
  79. package/dist/capabilities/send-user-file-tool.js +2 -66
  80. package/dist/capabilities/skills.d.ts +1 -2
  81. package/dist/capabilities/skills.js +3 -21
  82. package/dist/capabilities/team.d.ts +3 -11
  83. package/dist/capabilities/team.js +3 -51
  84. package/dist/capabilities/tool-defer.js +0 -3
  85. package/dist/config-center/apply-effective.js +15 -330
  86. package/dist/config-center/apply-ledger.js +5 -38
  87. package/dist/config-center/facade.js +0 -41
  88. package/dist/config-center/hot-keys-registry.js +0 -20
  89. package/dist/config-center/http-client.js +2 -125
  90. package/dist/config-center/mcp-revocation.js +2 -34
  91. package/dist/config-center/read-face.js +0 -59
  92. package/dist/config-center/restart-signal.js +1 -85
  93. package/dist/config-center/skills-mcp.d.ts +1 -1
  94. package/dist/config-center/skills-mcp.js +9 -76
  95. package/dist/config-center/stage-limits.js +8 -35
  96. package/dist/config-invariants.js +0 -16
  97. package/dist/config-lkg.js +0 -42
  98. package/dist/config-provider.js +3 -186
  99. package/dist/config-types.js +0 -5
  100. package/dist/config.js +107 -1145
  101. package/dist/degenerate-instrument.js +3 -67
  102. package/dist/deployment-governance.js +0 -124
  103. package/dist/digest-form.js +0 -12
  104. package/dist/elicitation.js +3 -86
  105. package/dist/env-facts.js +7 -75
  106. package/dist/fleet/fleet-bus.js +34 -507
  107. package/dist/fleet/fleet-reconciler.js +9 -149
  108. package/dist/fleet/fleet-terminal-window.js +10 -178
  109. package/dist/fleet/subagent-tail-bus.js +3 -72
  110. package/dist/fleet-client.js +10 -70
  111. package/dist/fleet-lease.js +5 -79
  112. package/dist/git-api-kind.js +0 -3
  113. package/dist/governance-ask-marks.js +2 -78
  114. package/dist/hooks/branch-transcript.js +0 -74
  115. package/dist/hooks/cc-agent-hook-prompt.js +0 -29
  116. package/dist/hooks/cc-stop-prompt.js +1 -46
  117. package/dist/hooks/hook-llm.js +1 -53
  118. package/dist/hooks/hook-runner.js +20 -414
  119. package/dist/http/active-run-conflict.js +4 -129
  120. package/dist/http/cursor-fingerprint.d.ts +5 -0
  121. package/dist/http/cursor-fingerprint.js +5 -0
  122. package/dist/http/idempotency.js +0 -37
  123. package/dist/http/principal-gate.js +3 -40
  124. package/dist/http/route-ctx.js +0 -9
  125. package/dist/http/routes/a2a-serve.js +7 -319
  126. package/dist/http/routes/admin-config-refresh.js +0 -4
  127. package/dist/http/routes/admin-drain.js +0 -10
  128. package/dist/http/routes/adoption.js +1 -29
  129. package/dist/http/routes/agents-roster.js +1 -47
  130. package/dist/http/routes/approvals-assistant.js +32 -395
  131. package/dist/http/routes/attachments.js +4 -22
  132. package/dist/http/routes/capabilities.js +3 -420
  133. package/dist/http/routes/diagnostics.js +1 -81
  134. package/dist/http/routes/fleet.js +9 -185
  135. package/dist/http/routes/images.js +14 -239
  136. package/dist/http/routes/leader.js +0 -13
  137. package/dist/http/routes/memory-bundle.js +1 -61
  138. package/dist/http/routes/memory-policy.js +9 -99
  139. package/dist/http/routes/notify-wake.js +3 -37
  140. package/dist/http/routes/observability.js +2 -19
  141. package/dist/http/routes/retention-ops.js +2 -34
  142. package/dist/http/routes/rules.js +1 -93
  143. package/dist/http/routes/runs.js +64 -873
  144. package/dist/http/routes/session-sync.js +19 -258
  145. package/dist/http/routes/sessions-list.js +17 -43
  146. package/dist/http/routes/sessions.js +34 -226
  147. package/dist/http/routes/shared-memory.js +5 -36
  148. package/dist/http/routes/side-query.js +1 -87
  149. package/dist/http/routes/tasks.js +52 -722
  150. package/dist/http/routes/trace-usage.js +32 -195
  151. package/dist/http/routes/workflows.js +19 -195
  152. package/dist/http/run-meta.js +0 -6
  153. package/dist/http/send.js +0 -32
  154. package/dist/http/server.js +92 -1597
  155. package/dist/http/sse-lifecycle.js +2 -13
  156. package/dist/http/sse-log.js +3 -48
  157. package/dist/http/tar.js +5 -21
  158. package/dist/http/verify-rounds.js +0 -5
  159. package/dist/http/wire-gate.js +0 -9
  160. package/dist/http/workspace-content.js +0 -10
  161. package/dist/images/bake-validate.js +1 -70
  162. package/dist/images/manifest.js +1 -6
  163. package/dist/index.js +0 -21
  164. package/dist/key-resolver.js +2 -17
  165. package/dist/leader/diffout.js +1 -20
  166. package/dist/leader/diffup.js +0 -47
  167. package/dist/leader/endpoint.js +2 -57
  168. package/dist/leader/fanout.js +3 -45
  169. package/dist/leader/grader-env-factory.js +3 -72
  170. package/dist/leader/leader.js +5 -156
  171. package/dist/leader/merge.js +8 -115
  172. package/dist/leader/planner.js +3 -54
  173. package/dist/leader/repair-oracle.js +1 -60
  174. package/dist/leader/repair-wire.js +2 -79
  175. package/dist/leader/wire.js +8 -307
  176. package/dist/lsp/e2b-bridge.js +4 -64
  177. package/dist/lsp/e2b-manager.js +6 -94
  178. package/dist/lsp/lsp-frames.js +0 -12
  179. package/dist/lsp/manager.js +4 -96
  180. package/dist/lsp/ws-transport.js +5 -55
  181. package/dist/lsp-evict.js +1 -15
  182. package/dist/main.js +57 -765
  183. package/dist/memory-bundle-engine.js +0 -55
  184. package/dist/memory-export.js +0 -4
  185. package/dist/memory-posture.js +1 -15
  186. package/dist/memory-scope.js +11 -148
  187. package/dist/memory-sync-client.js +2 -44
  188. package/dist/memory-sync.js +1 -80
  189. package/dist/model-select.js +3 -80
  190. package/dist/observability/cost-quota.js +1 -17
  191. package/dist/observability/cost-taxonomy.js +0 -34
  192. package/dist/observability/fail-open.js +7 -86
  193. package/dist/observability/logger.js +0 -6
  194. package/dist/observability/metrics.js +0 -94
  195. package/dist/observability/otel-exporter.js +3 -13
  196. package/dist/observability/principal-context.js +0 -9
  197. package/dist/observability/prompt-manifest.js +1 -37
  198. package/dist/observability/rate-limit.js +0 -4
  199. package/dist/observability/secret-env-scrub.js +2 -56
  200. package/dist/observability/tool-trace.js +1 -70
  201. package/dist/orchestration/hardened-vm-runner.js +4 -118
  202. package/dist/orchestration/hardened-vm-worker-runner.js +1 -26
  203. package/dist/orchestration/hardened-vm-worker.js +0 -27
  204. package/dist/orchestration/subagent-steer.js +1 -45
  205. package/dist/orchestration/workflow-agent-steer.js +1 -80
  206. package/dist/orchestration/workflow-completion-inbox.js +32 -285
  207. package/dist/orchestration/workflow-notify-journal.js +16 -259
  208. package/dist/org-memory-admission.js +3 -47
  209. package/dist/parent-watch.js +2 -48
  210. package/dist/parked-decide.js +1 -109
  211. package/dist/per-task-image.js +0 -57
  212. package/dist/plan-cache-probe.js +3 -27
  213. package/dist/plugins/adoption-log-sql.js +2 -119
  214. package/dist/plugins/approval-ask-store-memory.js +3 -38
  215. package/dist/plugins/approval-ask-store-sql.js +6 -188
  216. package/dist/plugins/approval-exemption-store.js +2 -28
  217. package/dist/plugins/background-agent-store-sql.js +4 -105
  218. package/dist/plugins/background-shell-support.js +14 -122
  219. package/dist/plugins/blob-backend.js +6 -169
  220. package/dist/plugins/breaker-state-sql.js +8 -46
  221. package/dist/plugins/caching-session-store.js +4 -106
  222. package/dist/plugins/checkpoint-store-sql.js +18 -505
  223. package/dist/plugins/e2b-orphan-reclaim.js +0 -45
  224. package/dist/plugins/file-outcome-sink.js +0 -9
  225. package/dist/plugins/file-resume-anchor-store.js +4 -43
  226. package/dist/plugins/file-run-store.js +26 -364
  227. package/dist/plugins/file-snapshot-store-sql.js +10 -181
  228. package/dist/plugins/fork-routing-session-store.js +8 -111
  229. package/dist/plugins/host-platform.js +2 -91
  230. package/dist/plugins/image-bake-store-sql.js +7 -250
  231. package/dist/plugins/image-index-sql.js +4 -123
  232. package/dist/plugins/k8s-bg-scripts.js +4 -88
  233. package/dist/plugins/k8s-exec-protocol.js +0 -41
  234. package/dist/plugins/leader-run-store-sql.js +0 -101
  235. package/dist/plugins/local-checkpoint-store.js +8 -128
  236. package/dist/plugins/local-session-store.js +34 -296
  237. package/dist/plugins/local-task-attachment-store.js +2 -16
  238. package/dist/plugins/mailbox-store-sql.js +8 -65
  239. package/dist/plugins/memory-embedder-fingerprint.js +5 -166
  240. package/dist/plugins/memory-embedder.js +4 -70
  241. package/dist/plugins/memory-engine-pg.js +6 -170
  242. package/dist/plugins/memory-engine-tidb.js +7 -155
  243. package/dist/plugins/memory-engine-vector-util.js +0 -10
  244. package/dist/plugins/memory-key-guards.js +0 -34
  245. package/dist/plugins/memory-origin-law.js +0 -187
  246. package/dist/plugins/memory-resume-anchor-store.js +0 -17
  247. package/dist/plugins/memory-run-store.js +12 -89
  248. package/dist/plugins/memory-session-policy-store.js +0 -17
  249. package/dist/plugins/memory-sync-store-pg.js +4 -49
  250. package/dist/plugins/memory-sync-store-tidb.js +3 -35
  251. package/dist/plugins/outcome-ledger-sql.js +3 -97
  252. package/dist/plugins/permission-rule-store-file.js +5 -133
  253. package/dist/plugins/permission-rule-store-sql.d.ts +3 -0
  254. package/dist/plugins/permission-rule-store-sql.js +50 -307
  255. package/dist/plugins/pg-cost-quota.js +0 -7
  256. package/dist/plugins/pg-pool.js +0 -92
  257. package/dist/plugins/pg-rate-limiter.js +2 -13
  258. package/dist/plugins/pg-safe-json.js +4 -40
  259. package/dist/plugins/pg-session-storage.js +25 -189
  260. package/dist/plugins/posix-shell-fs.js +1 -31
  261. package/dist/plugins/remote-env-adb.js +12 -101
  262. package/dist/plugins/remote-env-e2b.js +40 -371
  263. package/dist/plugins/remote-env-file-error.js +0 -37
  264. package/dist/plugins/remote-env-host.js +63 -483
  265. package/dist/plugins/remote-env-k8s.js +32 -326
  266. package/dist/plugins/remote-env-local-docker.js +24 -157
  267. package/dist/plugins/remote-env-ssh.js +20 -128
  268. package/dist/plugins/remote-scratchpad.js +2 -32
  269. package/dist/plugins/remote-shell.js +1 -32
  270. package/dist/plugins/resume-anchor-store-sql.js +0 -11
  271. package/dist/plugins/retention-lane-store-sql.js +0 -108
  272. package/dist/plugins/retention-store-sql.js +4 -383
  273. package/dist/plugins/roster-store-sql.js +0 -55
  274. package/dist/plugins/run-store-sql.js +14 -251
  275. package/dist/plugins/s3-presign.js +2 -49
  276. package/dist/plugins/scheduler-support.js +3 -80
  277. package/dist/plugins/send-file-ledger.js +4 -53
  278. package/dist/plugins/send-user-file.js +4 -94
  279. package/dist/plugins/session-placement.js +1 -89
  280. package/dist/plugins/session-policy-store-sql.js +3 -81
  281. package/dist/plugins/session-store.js +0 -57
  282. package/dist/plugins/shared-memory-store-sql.js +4 -167
  283. package/dist/plugins/sql-driver.js +0 -17
  284. package/dist/plugins/sql-errors.js +0 -7
  285. package/dist/plugins/sql-escape.js +0 -8
  286. package/dist/plugins/sql-row-helpers.js +0 -25
  287. package/dist/plugins/store-backend.js +42 -222
  288. package/dist/plugins/store-contracts.js +2 -46
  289. package/dist/plugins/task-attachment-store.js +3 -49
  290. package/dist/plugins/task-list-store-sql.js +0 -79
  291. package/dist/plugins/tidb-cost-quota.js +1 -4
  292. package/dist/plugins/tidb-pool.js +1 -207
  293. package/dist/plugins/tidb-rate-limiter.js +3 -9
  294. package/dist/plugins/tidb-session-storage.js +4 -70
  295. package/dist/plugins/tidb-session-store.js +19 -341
  296. package/dist/plugins/tool-result-store-sql.js +4 -179
  297. package/dist/plugins/usage-window-store-sql.js +0 -8
  298. package/dist/plugins/web-search.js +10 -132
  299. package/dist/plugins/workflow-journal-store-sql.js +2 -58
  300. package/dist/plugins/workflow-run-store-sql.js +6 -91
  301. package/dist/plugins/worktree-isolation.js +6 -126
  302. package/dist/plugins/write-behind-counter.js +16 -75
  303. package/dist/principal-jwt.js +5 -60
  304. package/dist/project-memory.js +15 -146
  305. package/dist/prompts-domain-validate.js +1 -51
  306. package/dist/question.js +2 -111
  307. package/dist/resource-suspend.js +0 -18
  308. package/dist/router/route-orchestration.js +0 -77
  309. package/dist/rules-consent.d.ts +44 -5
  310. package/dist/rules-consent.js +75 -215
  311. package/dist/run-local.js +14 -381
  312. package/dist/runs.js +29 -617
  313. package/dist/runtime-caps-resolver.js +6 -132
  314. package/dist/runtime-governance.js +1 -232
  315. package/dist/sandbox-pkg-source.js +0 -37
  316. package/dist/sealed-key.js +3 -68
  317. package/dist/security.js +6 -291
  318. package/dist/session-leaf-bus.js +0 -32
  319. package/dist/session-sync-content.js +1 -69
  320. package/dist/session-sync-kernel.js +3 -60
  321. package/dist/session-sync.js +3 -66
  322. package/dist/session-titler.js +7 -41
  323. package/dist/session-watch.js +9 -73
  324. package/dist/shared-memory-scope-authorizer.js +0 -18
  325. package/dist/sighup-idle.js +1 -12
  326. package/dist/spec-fields.js +4 -143
  327. package/dist/store-live-probe.js +3 -49
  328. package/dist/task-a2a.js +1 -126
  329. package/dist/task-cwd.js +1 -103
  330. package/dist/task-mcp.js +1 -89
  331. package/dist/task-settings.js +10 -300
  332. package/dist/task-workflow.js +8 -75
  333. package/dist/tool-approval.d.ts +28 -1
  334. package/dist/tool-approval.js +70 -1430
  335. package/dist/trace/artifacts.js +5 -20
  336. package/dist/trace/engine-notice-wire.js +6 -138
  337. package/dist/trace/ledger-sink.js +7 -96
  338. package/dist/trace/project.js +4 -448
  339. package/dist/trace/redact.js +9 -77
  340. package/dist/turn-activity.js +1 -27
  341. package/dist/usage-analytics.js +4 -34
  342. package/dist/wall-clock-jump-guard.js +1 -68
  343. package/package.json +3 -3
  344. package/dist/capabilities/scenario-alias.d.ts +0 -27
  345. package/dist/capabilities/scenario-alias.js +0 -61
@@ -1,85 +1,17 @@
1
- /**
2
- * #261(docs/DESIGN-261-fleet-liveness-reconcile.md v1.2,四方零驳定稿)—— fleet 总线**存活对账腿**。
3
- *
4
- * ## 它修什么(§0 病灶机制链)
5
- * fleet 总线是进程内纯内存聚合(`fleet-bus.ts` 头注自陈 NOT durable / NOT cross-replica),行的**唯一**
6
- * 离场路径是发布方主动打 `onTerminal`/`onChildTerminal`。发布方没走到终态臂(run 事件环异常中断、引擎
7
- * 被壳 reuse 而旧 run 对象已死、BCE 终态通知丢失),行就**永久僵在** `tasks` Map 里 —— 此后每个订阅方
8
- * (含 snapshot 新连接)看到一条永远 "running" 的幽灵行。壳侧只能靠 overlay 防御(cli 1.0.74 过渡件)。
9
- *
10
- * ## 核心裁定:**不造第二个判死者**(§1)
11
- * 本腿**不判死**。它只做两件事:
12
- * (a) 副本本地活体登记面(`http/server.ts` 的 `inflightRuns` ∪ `steerableRuns`,经
13
- * {@link FleetReconcilerDeps.isLiveOnThisReplica} 探针注入 —— **不搬 Map**)在场 ⇒ 行活,跳过;
14
- * (b) 登记面无此 taskId ⇒ 读 durable run 行,把 durable **已有的判决**投影到总线上。
15
- * 判死的属主始终是 durable 侧既有机制(心跳 → reaper finalize → 行翻终态);本腿是**投影腿**,
16
- * 对 durable **恒只读**({@link FleetReconcileRunPort} 这只窄口连写方法都没有 —— 单写者不变量由类型执法)。
17
- *
18
- * `msSinceLastActivity` **显式排除**:它是「turn 卡死」诊断维,把它当退休输入会把真忙的后台 run 扫下
19
- * 面板,方向错。卡死的 run 行**该**留着(它确实在占资源),诊断走 `GET /v1/runs/:id`。
20
- *
21
- * ## 对账矩阵(§1;每周期对 bus 的顶层 run 行逐行判)
22
- * | 登记面 | durable 行 | 处置 |
23
- * |---|---|---|
24
- * | 在场 | 任意 | **跳过**(含 turn 卡死形) |
25
- * | 无 | 终局 | **投影退休**:终态 `task` 帧(durable 真状态 + `retiredBy:"reconcile"` + 被退代际)→ `task_remove`,**结算级** |
26
- * | 无 | `running`(本副本 claim / 他副本 claim) | **陈述级退场**:`task_remove` + `removeReason:"orphaned"`,**恒不造终态** |
27
- * | 无 | 行不存在 | 陈述级退场(见下方"静默一周期"的收窄) |
28
- *
29
- * 🔴 **对"行不存在"这一格的收窄**(实施稿承重,设计稿 §3 的「拿不准的恒答最弱主张」同源):bus 上
30
- * 一条 `parentId` 缺席的行**不一定**是顶层 run 行 —— BCE 车道的 `a*` 子代行在父链接尚未解析成功时
31
- * 同样不发 `parentId`(`rowTags` 的 R6 臂),两者在总线上**结构同形**。而 `getRun(a*)` 必然 miss。
32
- * 若照矩阵当周期就退场,一条**活着的**长寿 session-scoped bg 子代会被扫下面板。所以这一格额外要求
33
- * 「**静默满一个对账周期**」(本腿订阅总线自记每行的最后帧时刻):还在出帧 = 活着的证据。
34
- * durable 行**在场**的那三格没有这个歧义(`getRun` 命中 = 它就是一条 run 行),故照矩阵即时处置。
35
- *
36
- * ## 子代行(§1)
37
- * 随父:父行退休/退场时**同扫**(与 `onTerminal` 的 removal 集同姿势)。子代**不读 durable** ——
38
- * bg 子代的 durable 真源在 core 侧 registry,server 不越界重判。无父可循的孤儿子行(父行已不在 bus)
39
- * 按「bus 内滞留超一个对账周期且无新帧」陈述级退场。
40
- *
41
- * ## workflow 行(§1)
42
- * 只做同款「durable 终局投影」(#189 的 snapshot pull 腿 + reapers 的 workflow recover 腿已在场),
43
- * **不加新判据**:活行恒不动,没有陈述级退场这一形。
44
- *
45
- * ## 五条界(任何一条失手都只是幽灵行多活一个周期 ⇒ 整体 F 类 fail-open,登记 tag,不静默)
46
- * · 节律 {@link FLEET_RECONCILE_INTERVAL_MS} · 每周期读上限 {@link FLEET_RECONCILE_MAX_ROWS}
47
- * · 读预算 {@link FLEET_RECONCILE_READ_BUDGET_MS} · 熔断冷却 {@link FLEET_RECONCILE_COOLDOWN_MS}
48
- * · 待终局候补窗 {@link FLEET_RECONCILE_WATCH_MAX} × {@link FLEET_RECONCILE_WATCH_TTL_MS}
49
- * 任何读错/超预算 ⇒ `recordFailOpen("server.fleet.reconcile-read-failed")` + 熔断 + 本周期跳过。
50
- *
51
- * ## 为什么整套常数都不做旋钮
52
- * 与 `fleet-terminal-window.ts` 同一论证:两侧边界都由语义定死(比周期短 = 幽灵行仍在面板上,比周期长 =
53
- * 拿对账腿当历史列表),旋钮只会让部署方去调一个没有正确取值的数;fleet 面现有零旋钮,从之。
54
- */
55
1
  import { isTerminalWorkflowStatus } from "@sema-agent/core";
56
2
  import { recordFailOpen } from "../observability/fail-open.js";
57
3
  import { isParkedRunStatus, isTerminalRunStatus } from "../plugins/store-contracts.js";
58
4
  import { buildFleetWorkflowRow, fleetRunResiduals, runStatusToFleet } from "./fleet-bus.js";
59
5
  import { isTerminalWorkflowRowStatus } from "./fleet-terminal-window.js";
60
- /** 对账节律 —— 60s 档。比它短 = 每分钟给 durable 加一批点读却换不来更快的面板真相(幽灵行的时间尺度
61
- * 是"发布方已经死了",分钟级);比它长 = 壳的引擎温切门(cli engineSwapGate 读活行集)被幽灵行按住
62
- * 太久。不做旋钮,理由见模块头。 */
63
6
  export const FLEET_RECONCILE_INTERVAL_MS = 60_000;
64
- /** 每周期的**点读上限**。超出的行留到下一周期(顺序稳定 = bus 的插入序),不把一次扫描变成全表点读风暴。 */
65
7
  export const FLEET_RECONCILE_MAX_ROWS = 200;
66
- /** 一个周期的 durable 读**时间预算**。超时 = 放弃这一轮(记 F 类 fail-open),行留在面板上。
67
- * 与 `FLEET_SNAPSHOT_TERMINAL_READ_BUDGET_MS` 同值同理由:慢查询不该把整条腿钉死。 */
68
8
  export const FLEET_RECONCILE_READ_BUDGET_MS = 2_000;
69
- /** 熔断冷却:一次读失败/超预算之后,这段时间内**不再发起任何读**。`RunStore`/`WorkflowRunStore` 契约
70
- * 都没有取消面(发出去的查询撤不回),挂死的后端不该被每周期继续加压。冷却一过自动重探(自愈)。 */
71
9
  export const FLEET_RECONCILE_COOLDOWN_MS = 60_000;
72
- /** 陈述级退场之后的**待终局候补窗**行数上限(§1 矩阵的「终局候 durable 翻转后由下一周期投影」半场:
73
- * 行已不在 bus,故补发终态 `task` 帧 + remove 的**成对形**)。有界:超出即不再收新条目。 */
74
10
  export const FLEET_RECONCILE_WATCH_MAX = 200;
75
- /** 候补窗的存活时长。reaper 的孤儿宽限窗之外仍没翻终局的行 = 这条腿等不到了(它本来也只是投影),
76
- * 丢弃并不损失真相:`GET /v1/runs/:id` 永远是那条 run 的真源。 */
77
11
  export const FLEET_RECONCILE_WATCH_TTL_MS = 30 * 60_000;
78
12
  const emptyTally = () => ({
79
13
  scanned: 0, skippedLive: 0, skippedParked: 0, retired: 0, orphaned: 0, childrenSwept: 0, workflowsRetired: 0, reads: 0, cooling: false, failOpen: false,
80
14
  });
81
- /** 从 `cursor` 指的那一行开始的**环形**遍历(见 {@link createFleetReconciler} 里 `taskCursor` 的顶注)。
82
- * `cursor` 缺席/已不在集合里 ⇒ 从头开始(诚实回落)。返回新数组,调用方照常按序 `for…of`。 */
83
15
  function rotate(rows, cursor) {
84
16
  if (cursor === undefined || rows.length === 0)
85
17
  return rows;
@@ -88,26 +20,12 @@ function rotate(rows, cursor) {
88
20
  return rows;
89
21
  return [...rows.slice(at), ...rows.slice(0, at)];
90
22
  }
91
- /** 本周期该不该收这条行 —— 见模块头「对"行不存在"这一格的收窄」。 */
92
23
  const SILENT_FOR_A_CYCLE = FLEET_RECONCILE_INTERVAL_MS;
93
24
  export function createFleetReconciler(deps) {
94
25
  const now = deps.now ?? (() => Date.now());
95
- /**
96
- * 每行的**最后帧时刻**。存在理由:「无新帧」是设计稿对孤儿子行(以及本实施稿对"durable 无行"格)
97
- * 唯一诚实的活性证据 —— 长寿 session-scoped bg 子代在父 run 行离场之后照样出 tick,它必须留在面板上。
98
- * 从总线订阅得到(而不是自己给行打时间戳):**行的单写者不变量**不许被观察者破坏。
99
- */
100
26
  const lastFrameAt = new Map();
101
- /** 陈述级退场后的待终局候补窗(见 {@link FLEET_RECONCILE_WATCH_MAX})。 */
102
27
  const watch = new Map();
103
28
  let coolingUntil;
104
- /**
105
- * 🔴 轮转游标(codex 对抗复审 R1-F4 [medium],红先复现):读上限是**每周期**的,而扫描顺序是 bus 的
106
- * 稳定插入序 —— 于是「超出的行留到下一周期」这句承诺在**行不会自己走**的形下是假的:200 条长期
107
- * parked/活的行会把预算逐周期吃光,第 201 行往后**永远**读不到,它们的终局投影永不发生(而那正是本腿
108
- * 存在的理由)。游标记住"上一周期停在哪一行",下一周期从它接着扫,一圈之后必然轮到每一行。
109
- * 记 id(不是下标):行集会增删,下标会指到别的行上;id 找不到就从头开始(诚实回落,不猜)。
110
- */
111
29
  let taskCursor;
112
30
  let wfCursor;
113
31
  const unsubscribe = deps.bus.subscribe((frame) => {
@@ -125,14 +43,9 @@ export function createFleetReconciler(deps) {
125
43
  }
126
44
  coolingUntil = undefined;
127
45
  const deadline = now() + FLEET_RECONCILE_READ_BUDGET_MS;
128
- /** 读闸:上限/预算任一到顶就停(**不是**熔断——本周期已做的处置全部有效,余下的行下周期再来)。 */
129
46
  const budgetLeft = () => tally.reads < FLEET_RECONCILE_MAX_ROWS && now() < deadline;
130
- /** 一次点读。抛错/超预算 ⇒ 抛 {@link ReadAborted},由 runOnce 统一收成 F 类 fail-open + 熔断。 */
131
47
  const readRun = async (id) => {
132
48
  tally.reads++;
133
- // A-067 C5(F7):竞速一结束就 clearTimeout(A-002.10 同款,approval-reconciler withDeadline 正形)
134
- // ——unref 只保证不吊住进程退出,不回收定时器本身;每周期最多 FLEET_RECONCILE_MAX_ROWS 次点读,
135
- // 不清就是同数量级带闭包定时器的逐周期累积。finally 对胜败两路都清。
136
49
  let t;
137
50
  const rec = await Promise.race([
138
51
  deps.runs.getRun(id),
@@ -148,8 +61,6 @@ export function createFleetReconciler(deps) {
148
61
  return rec;
149
62
  };
150
63
  const snap = deps.bus.snapshot();
151
- // 静默钟的**首见播种**:本腿起动之前就已在 bus 上的行(重启/迟接线)没有帧记录,给它们记一个
152
- // "从现在开始静默"的起点 —— 否则首轮就会把一屏历史行当成静默满一周期的幽灵。
153
64
  for (const r of snap.tasks)
154
65
  if (!lastFrameAt.has(r.id))
155
66
  lastFrameAt.set(r.id, nowMs);
@@ -165,8 +76,6 @@ export function createFleetReconciler(deps) {
165
76
  else
166
77
  kids.set(r.parentId, [r]);
167
78
  }
168
- /** 随父同扫(与 `fleetRunPublisher.onTerminal` 的 removal 集同姿势)。子代恒**陈述级** ——
169
- * 我们对它们没有任何终局证据(子代不读 durable),说"离场"是诚实的,说"完成/失败"是编。 */
170
79
  const sweepChildren = (parentId) => {
171
80
  for (const c of kids.get(parentId) ?? []) {
172
81
  deps.bus.removeTask(c.id, { removeReason: "orphaned", ...(c.cycleSeq !== undefined ? { cycleSeq: c.cycleSeq } : {}) });
@@ -174,10 +83,7 @@ export function createFleetReconciler(deps) {
174
83
  tally.childrenSwept++;
175
84
  }
176
85
  };
177
- /** 投影退休(结算级):终态 `task` 帧 → `task_remove`,**成对且有序**。 */
178
86
  const retire = (row, rec) => {
179
- // 残局键走既有的**同一个** {@link fleetRunResiduals} 映射(键名映射写第二遍必漂;[1839]① 案:
180
- // 只带 {id,status} 的终态帧让 idle 观察者从行卡上拿不到终局)。源恒是 durable 那份 result,不编。
181
87
  deps.bus.publishTask({
182
88
  id: row.id,
183
89
  status: runStatusToFleet(rec.status),
@@ -190,7 +96,6 @@ export function createFleetReconciler(deps) {
190
96
  tally.retired++;
191
97
  deps.metrics?.inc("fleet_rows_reconciled_total", { disposition: "retired" });
192
98
  };
193
- /** 陈述级退场:只撤行,恒不造终态。行进候补窗,等 durable 翻终局后由后续周期补发成对终帧。 */
194
99
  const orphanExit = (row, why) => {
195
100
  sweepChildren(row.id);
196
101
  deps.bus.removeTask(row.id, { removeReason: "orphaned", ...(row.cycleSeq !== undefined ? { cycleSeq: row.cycleSeq } : {}) });
@@ -202,18 +107,11 @@ export function createFleetReconciler(deps) {
202
107
  deps.logger?.info("fleet_row_reconciled", { taskId: row.id, disposition: "orphaned", why, instanceId: deps.instanceId ?? null });
203
108
  };
204
109
  try {
205
- // ── ① 候补窗:陈述级退场过的行,等 durable 翻终局 ─────────────────────────────────────
206
- // 为什么要补这一拍:cli 的裁量是「渲**离场**不清行」([4044])—— 陈述级退场之后壳把行**保留**在
207
- // 面板上(中性离场形、active 扣除、折叠排后),所以那条行后来真的翻了终局时,补发的成对终帧是壳
208
- // 唯一能把"离场"升级成"真终局"的信号。行已不在 bus,故 publish 会**瞬时重铸**再撤(flip-through,
209
- // 与 `onChildTerminal` 的合成终帧同姿势);带上退场时记住的整行,可见性字段(scope/sessionId)
210
- // 才不会丢 —— 丢了就变成 scoped 订阅方一律看不见(fail-closed 到没人收得到)。
211
110
  for (const [id, w] of [...watch]) {
212
111
  if (nowMs - w.at > FLEET_RECONCILE_WATCH_TTL_MS) {
213
112
  watch.delete(id);
214
113
  continue;
215
114
  }
216
- // 行又出现在 bus 上 = **复活**(更大代际的首帧 = 正常出生):活发布方接管,候补窗让位。
217
115
  if (present.has(id)) {
218
116
  watch.delete(id);
219
117
  continue;
@@ -224,9 +122,9 @@ export function createFleetReconciler(deps) {
224
122
  if (!rec) {
225
123
  watch.delete(id);
226
124
  continue;
227
- } // 行被 reap 掉了:没有终局可投影,诚实丢弃
125
+ }
228
126
  if (!isTerminalRunStatus(rec.status))
229
- continue; // 还没定局 —— 下个周期再看
127
+ continue;
230
128
  deps.bus.publishTask({ ...w.row, status: runStatusToFleet(rec.status), retiredBy: "reconcile", ...fleetRunResiduals(rec.result) });
231
129
  deps.bus.removeTask(id, { ...(w.row.cycleSeq !== undefined ? { cycleSeq: w.row.cycleSeq } : {}) });
232
130
  lastFrameAt.delete(id);
@@ -234,39 +132,31 @@ export function createFleetReconciler(deps) {
234
132
  tally.retired++;
235
133
  deps.metrics?.inc("fleet_rows_reconciled_total", { disposition: "retired_deferred" });
236
134
  }
237
- // ── ② 顶层 run 行 ────────────────────────────────────────────────────────────────────
238
135
  for (const row of rotate(snap.tasks, taskCursor)) {
239
136
  if (row.parentId !== undefined)
240
- continue; // 子代行:随父(下面 ③ 收孤儿)
137
+ continue;
241
138
  tally.scanned++;
242
139
  if (deps.isLiveOnThisReplica(row.id)) {
243
- // 登记面在场 ⇒ 活。**含 turn 卡死形** —— 诊断不驱逐(§1)。一次 durable 读都不发。
244
140
  tally.skippedLive++;
245
141
  continue;
246
142
  }
247
143
  if (!deps.runs)
248
- continue; // 无 durable run 店的部署(memory 车道):没有可投影的判决,整格不动
144
+ continue;
249
145
  if (!budgetLeft()) {
250
146
  taskCursor = row.id;
251
147
  break;
252
- } // 轮转:下周期从这一行接着扫(见 rotate 顶注)
148
+ }
253
149
  const rec = await readRun(row.id);
254
- // 🔴 await 后**复核**(codex 对抗复审 R1-F3 [high],红先复现):`isLiveOnThisReplica` 在读之前只
255
- // 问过一次,而 durable 读的那几十毫秒里 parked run 完全可能被 resume —— 它会重新登记进在飞面并
256
- // 发出新行帧,而读回来的行还写着 `running`。不复核就等于把**刚复活**的顶层行删掉;顶层行按设计
257
- // 恒无 `cycleSeq`(「无此概念」),总线那道代际条件删也救不了这一格,只能在这里问第二次。
258
150
  if (deps.isLiveOnThisReplica(row.id)) {
259
151
  tally.skippedLive++;
260
152
  continue;
261
153
  }
262
154
  const nowRow = deps.bus.taskRow(row.id);
263
155
  if (nowRow === undefined)
264
- continue; // 行在读期间自己走了(发布方终于 settle 了):无事可做
156
+ continue;
265
157
  if (nowRow.cycleSeq !== row.cycleSeq)
266
- continue; // 代际翻过 = 已复活,活发布方接管
158
+ continue;
267
159
  if (rec === undefined) {
268
- // durable 无行。**必须**静默满一个周期才退场:`a*` 子代行在父链接未解析时同样无 parentId,
269
- // 与顶层行结构同形,而 `getRun(a*)` 必然 miss(见模块头收窄段)。还在出帧 = 活着的证据。
270
160
  if (idle(row.id))
271
161
  orphanExit(row, "durable_row_absent");
272
162
  continue;
@@ -275,42 +165,31 @@ export function createFleetReconciler(deps) {
275
165
  retire(row, rec);
276
166
  continue;
277
167
  }
278
- // 🔴 **park 不是孤儿**(codex 对抗复审 R1-F1 [high],红先复现):`suspended` / `needs_review` 的行
279
- // 还活着 —— `task_active` claim 还占着、checkpoint 还能被决议,而 fleet 契约(`fleetRunPublisher`
280
- // 的 `onTerminal`)明写 park 态的行**留在面板上**(waiting / awaiting approval)。它们恰恰**不在**
281
- // 任何在飞登记面里(park 的 run 没有活腿),所以上面那道活体谓词接不住它们 —— 不在这里显式跳过,
282
- // 每一轮对账都会把一条合法的待审批任务从面板上摘掉,而用户看到的是"任务凭空消失"。
283
168
  if (isParkedRunStatus(rec.status)) {
284
169
  tally.skippedParked++;
285
170
  continue;
286
171
  }
287
- // durable 还 `running` 而本副本没有它:发布方死了、durable 还没定局(reaper 宽限窗内),
288
- // 或 run 活在别的副本上。两形处置相同 —— **不造终态**,只陈述离场。
289
172
  orphanExit(row, rec.instanceId !== null && rec.instanceId !== (deps.instanceId ?? null) ? "durable_running_other_replica" : "durable_running_no_local_leg");
290
173
  }
291
- // ── ③ 无父可循的孤儿子行 ─────────────────────────────────────────────────────────────
292
- // 判据里**没有** durable 读:bg 子代的真源在 core 侧 registry,server 不越界重判。
293
174
  for (const row of snap.tasks) {
294
175
  if (row.parentId === undefined || present.has(row.parentId))
295
176
  continue;
296
177
  if (!idle(row.id))
297
- continue; // 还在出帧 = 长寿 session-scoped 子代活过了父 leg,留着
178
+ continue;
298
179
  deps.bus.removeTask(row.id, { removeReason: "orphaned", ...(row.cycleSeq !== undefined ? { cycleSeq: row.cycleSeq } : {}) });
299
180
  lastFrameAt.delete(row.id);
300
181
  tally.orphaned++;
301
182
  deps.metrics?.inc("fleet_rows_reconciled_total", { disposition: "orphaned_child" });
302
183
  }
303
- // ── ④ workflow 行:只做 durable 终局投影 ─────────────────────────────────────────────
304
184
  if (wfGet) {
305
185
  for (const wf of rotate(snap.workflows, wfCursor)) {
306
186
  if (isTerminalWorkflowRowStatus(wf.status))
307
- continue; // 已是终态行:活写路径自己会撤
187
+ continue;
308
188
  if (!budgetLeft()) {
309
189
  wfCursor = wf.id;
310
190
  break;
311
191
  }
312
192
  tally.reads++;
313
- // A-067 C5(F7):同上 readRun——竞速一结束 finally 清(A-002.10 同款)。
314
193
  let wfTimer;
315
194
  const run = await Promise.race([
316
195
  wfGet(wf.id),
@@ -325,8 +204,6 @@ export function createFleetReconciler(deps) {
325
204
  });
326
205
  if (!run || !isTerminalWorkflowStatus(run.status))
327
206
  continue;
328
- // 租户复核:`store.get` 是**无 scope 门**的裸读(带门的是 core 的 `getWorkflowRun`)——
329
- // id 来自本进程的行,仍按真行的 scope 复核一次(同 fleet-terminal-window 的姿势)。
330
207
  if (wf.scope !== undefined && run.scope !== wf.scope)
331
208
  continue;
332
209
  deps.bus.publishWorkflow(buildFleetWorkflowRow(wf.id, run));
@@ -337,12 +214,8 @@ export function createFleetReconciler(deps) {
337
214
  }
338
215
  }
339
216
  catch (err) {
340
- // F 类:读不出来 ≠ 该退休。**只向留行一侧** fail-open —— 库抖一下就把一屏在跑的任务从面板上
341
- // 抹掉,比多留一条幽灵行伤得多。本周期已经做完的处置全部有效(它们各自都有 durable 证据)。
342
217
  coolingUntil = now() + FLEET_RECONCILE_COOLDOWN_MS;
343
218
  tally.failOpen = true;
344
- // detail 用 `err.message` 而不是 `String(err)`:后者会调用抛出值自己的 toString,而那本身可能再抛
345
- // (逃出本兜底,把降级变成故障)。非 Error 抛出值就如实说"不是 Error",不去问它任何问题。
346
219
  recordFailOpen("server.fleet.reconcile-read-failed", err instanceof Error ? err.message : "fleet reconcile read threw a non-Error value");
347
220
  }
348
221
  return tally;
@@ -352,18 +225,8 @@ export function createFleetReconciler(deps) {
352
225
  stop: unsubscribe,
353
226
  };
354
227
  }
355
- /** 读预算到点的**具名**抛出值(与真实的店错误在日志里可分,且不会被误当成"店坏了"去查库)。 */
356
228
  class ReadAborted extends Error {
357
229
  }
358
- /**
359
- * 起对账定时器(60s 档,`unref`)+ 重入守卫。返回 handle 供收尾段 `clearInterval`。
360
- *
361
- * ⚠️ 装配点必须在 `createHttpServer` **之后** —— 活体谓词是 server 造出来的
362
- * ({@link FleetReconcilerDeps.isLiveOnThisReplica});这也是本腿不并进 `boot/reapers.ts` 那只 tick 的
363
- * 唯一原因(reaper 段按「位置即契约」必须在 server 之前建)。
364
- *
365
- * 重入守卫照 reapers 的四腿先例:本腿时长随 bus 行数与库延迟增长,短周期下无守卫会逐周期叠罗汉压同一批行。
366
- */
367
230
  export function startFleetReconciler(deps) {
368
231
  const reconciler = createFleetReconciler(deps);
369
232
  let inFlight = false;
@@ -378,13 +241,10 @@ export function startFleetReconciler(deps) {
378
241
  deps.logger?.info("fleet_reconcile_swept", { retired: t.retired, orphaned: t.orphaned, childrenSwept: t.childrenSwept, workflowsRetired: t.workflowsRetired, reads: t.reads });
379
242
  }
380
243
  }, (err) => {
381
- // runOnce 自己已把读面的失败收成 fail-open;能到这里的只剩"对账腿自己有 bug"这一族。
382
- // 观测绝不能变成故障(同 reapers 的 throttled catch 判据):整块 total/non-throwing。
383
244
  try {
384
245
  deps.logger?.warn("fleet_reconcile_failed", { err: err instanceof Error ? err.message : "non-Error throw" });
385
246
  }
386
247
  catch {
387
- /* observability must never become the outage */
388
248
  }
389
249
  })
390
250
  .finally(() => {