@sema-agent/server 1.322.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (539) hide show
  1. package/dist/approval-hmac.d.ts +40 -0
  2. package/dist/approval-hmac.js +67 -0
  3. package/dist/approval.d.ts +31 -0
  4. package/dist/approval.js +72 -4
  5. package/dist/audit.d.ts +26 -0
  6. package/dist/audit.js +40 -1
  7. package/dist/auth-bridge.d.ts +10 -0
  8. package/dist/auth-bridge.js +47 -4
  9. package/dist/auth-keys.d.ts +19 -0
  10. package/dist/auth-keys.js +13 -0
  11. package/dist/bake-runner/main.d.ts +5 -0
  12. package/dist/bake-runner/main.js +43 -4
  13. package/dist/bake-runner/protocol.d.ts +57 -0
  14. package/dist/bake-runner/protocol.js +58 -3
  15. package/dist/bake-runner/runner.d.ts +54 -0
  16. package/dist/bake-runner/runner.js +87 -5
  17. package/dist/bench/l8/artifact.d.ts +63 -0
  18. package/dist/bench/l8/artifact.js +61 -2
  19. package/dist/bench/l8/escape.d.ts +36 -0
  20. package/dist/bench/l8/escape.js +25 -0
  21. package/dist/bench/l8/index.d.ts +14 -0
  22. package/dist/bench/l8/index.js +14 -0
  23. package/dist/bench/l8/probes.d.ts +74 -0
  24. package/dist/bench/l8/probes.js +60 -0
  25. package/dist/bench/l8/run-probes.d.ts +43 -0
  26. package/dist/bench/l8/run-probes.js +45 -2
  27. package/dist/bench/s1/arms.d.ts +126 -0
  28. package/dist/bench/s1/arms.js +188 -13
  29. package/dist/bench/s1/live-deps.d.ts +66 -0
  30. package/dist/bench/s1/live-deps.js +249 -11
  31. package/dist/bench/s1/oracle.d.ts +49 -0
  32. package/dist/bench/s1/oracle.js +36 -1
  33. package/dist/bench/s1/repair-oracle-adapter.d.ts +33 -0
  34. package/dist/bench/s1/repair-oracle-adapter.js +30 -0
  35. package/dist/bench/s1/reviewer.d.ts +38 -0
  36. package/dist/bench/s1/reviewer.js +34 -0
  37. package/dist/bench/s1/row.d.ts +77 -0
  38. package/dist/bench/s1/row.js +62 -0
  39. package/dist/bench/s1/run-firm.d.ts +47 -0
  40. package/dist/bench/s1/run-firm.js +70 -4
  41. package/dist/bench/s1/runner-ctx.d.ts +71 -0
  42. package/dist/bench/s1/runner-ctx.js +36 -0
  43. package/dist/bench/s1/tasks.d.ts +108 -0
  44. package/dist/bench/s1/tasks.js +115 -0
  45. package/dist/boot-reclaim.d.ts +19 -0
  46. package/dist/boot-reclaim.js +20 -0
  47. package/dist/brain.d.ts +25 -0
  48. package/dist/brain.js +61 -1
  49. package/dist/budget.d.ts +66 -0
  50. package/dist/budget.js +128 -4
  51. package/dist/capabilities/builtin-tools.d.ts +3 -0
  52. package/dist/capabilities/builtin-tools.js +3 -0
  53. package/dist/capabilities/center-plugins.d.ts +17 -1
  54. package/dist/capabilities/center-plugins.js +45 -4
  55. package/dist/capabilities/center-prompts.d.ts +46 -0
  56. package/dist/capabilities/center-prompts.js +57 -3
  57. package/dist/capabilities/code-review-council.d.ts +28 -0
  58. package/dist/capabilities/code-review-council.js +40 -7
  59. package/dist/capabilities/collab-wire.d.ts +2 -0
  60. package/dist/capabilities/collab-workflows.d.ts +7 -0
  61. package/dist/capabilities/collab-workflows.js +44 -1
  62. package/dist/capabilities/oa-tools.d.ts +6 -0
  63. package/dist/capabilities/oa-tools.js +10 -0
  64. package/dist/capabilities/prompt.d.ts +14 -0
  65. package/dist/capabilities/prompt.js +14 -0
  66. package/dist/capabilities/prompts/code-review.d.ts +14 -0
  67. package/dist/capabilities/prompts/code-review.js +14 -0
  68. package/dist/capabilities/prompts/identity.d.ts +6 -0
  69. package/dist/capabilities/prompts/identity.js +6 -0
  70. package/dist/capabilities/prompts/team.d.ts +4 -0
  71. package/dist/capabilities/prompts/team.js +4 -0
  72. package/dist/capabilities/repo-tools.d.ts +11 -0
  73. package/dist/capabilities/repo-tools.js +8 -0
  74. package/dist/capabilities/sandbox-file-send.d.ts +95 -0
  75. package/dist/capabilities/sandbox-file-send.js +91 -3
  76. package/dist/capabilities/scenarios.d.ts +130 -0
  77. package/dist/capabilities/scenarios.js +180 -7
  78. package/dist/capabilities/select-environment-tool.d.ts +7 -0
  79. package/dist/capabilities/select-environment-tool.js +30 -0
  80. package/dist/capabilities/send-user-file-tool.d.ts +33 -0
  81. package/dist/capabilities/send-user-file-tool.js +65 -1
  82. package/dist/capabilities/skills.d.ts +29 -0
  83. package/dist/capabilities/skills.js +13 -2
  84. package/dist/capabilities/team.d.ts +22 -0
  85. package/dist/capabilities/team.js +22 -2
  86. package/dist/capabilities/tool-defer.d.ts +26 -0
  87. package/dist/capabilities/tool-defer.js +3 -0
  88. package/dist/config-center/apply-effective.d.ts +65 -0
  89. package/dist/config-center/apply-effective.js +204 -12
  90. package/dist/config-center/http-client.d.ts +34 -0
  91. package/dist/config-center/http-client.js +68 -0
  92. package/dist/config-center/restart-signal.d.ts +22 -0
  93. package/dist/config-center/restart-signal.js +39 -0
  94. package/dist/config-center/skills-mcp.d.ts +20 -1
  95. package/dist/config-center/skills-mcp.js +42 -7
  96. package/dist/config-center/types.d.ts +92 -1
  97. package/dist/config-lkg.d.ts +12 -0
  98. package/dist/config-lkg.js +41 -0
  99. package/dist/config-provider.d.ts +78 -0
  100. package/dist/config-provider.js +165 -2
  101. package/dist/config-types.d.ts +546 -0
  102. package/dist/config.d.ts +64 -0
  103. package/dist/config.js +455 -60
  104. package/dist/degenerate-instrument.d.ts +38 -0
  105. package/dist/degenerate-instrument.js +55 -3
  106. package/dist/elicitation.d.ts +39 -0
  107. package/dist/elicitation.js +87 -3
  108. package/dist/env-facts.d.ts +61 -0
  109. package/dist/env-facts.js +73 -7
  110. package/dist/fleet/fleet-bus.d.ts +185 -0
  111. package/dist/fleet/fleet-bus.js +333 -27
  112. package/dist/fleet/subagent-tail-bus.d.ts +11 -0
  113. package/dist/fleet/subagent-tail-bus.js +33 -2
  114. package/dist/fleet-client.d.ts +38 -0
  115. package/dist/fleet-client.js +44 -9
  116. package/dist/fleet-lease.d.ts +46 -0
  117. package/dist/fleet-lease.js +73 -5
  118. package/dist/hooks/branch-transcript.d.ts +8 -0
  119. package/dist/hooks/branch-transcript.js +33 -0
  120. package/dist/hooks/cc-stop-prompt.d.ts +42 -0
  121. package/dist/hooks/cc-stop-prompt.js +43 -1
  122. package/dist/hooks/hook-llm.d.ts +15 -0
  123. package/dist/hooks/hook-llm.js +47 -0
  124. package/dist/hooks/hook-runner.d.ts +89 -0
  125. package/dist/hooks/hook-runner.js +327 -18
  126. package/dist/http/idempotency.d.ts +31 -0
  127. package/dist/http/idempotency.js +34 -0
  128. package/dist/http/principal-gate.d.ts +17 -0
  129. package/dist/http/principal-gate.js +35 -3
  130. package/dist/http/route-ctx.d.ts +36 -0
  131. package/dist/http/routes/approvals-assistant.d.ts +25 -0
  132. package/dist/http/routes/approvals-assistant.js +253 -23
  133. package/dist/http/routes/attachments.js +22 -4
  134. package/dist/http/routes/capabilities.d.ts +7 -0
  135. package/dist/http/routes/capabilities.js +202 -1
  136. package/dist/http/routes/fleet.d.ts +6 -0
  137. package/dist/http/routes/fleet.js +94 -5
  138. package/dist/http/routes/images.d.ts +17 -0
  139. package/dist/http/routes/images.js +222 -14
  140. package/dist/http/routes/leader.d.ts +7 -0
  141. package/dist/http/routes/leader.js +10 -0
  142. package/dist/http/routes/memory-policy.d.ts +6 -0
  143. package/dist/http/routes/memory-policy.js +38 -6
  144. package/dist/http/routes/notify-wake.d.ts +10 -0
  145. package/dist/http/routes/notify-wake.js +19 -3
  146. package/dist/http/routes/observability.d.ts +6 -0
  147. package/dist/http/routes/observability.js +19 -2
  148. package/dist/http/routes/runs.d.ts +15 -0
  149. package/dist/http/routes/runs.js +464 -41
  150. package/dist/http/routes/session-sync.d.ts +15 -0
  151. package/dist/http/routes/session-sync.js +229 -19
  152. package/dist/http/routes/sessions-list.d.ts +6 -0
  153. package/dist/http/routes/sessions-list.js +35 -4
  154. package/dist/http/routes/sessions.d.ts +14 -0
  155. package/dist/http/routes/sessions.js +176 -31
  156. package/dist/http/routes/side-query.d.ts +8 -0
  157. package/dist/http/routes/side-query.js +26 -1
  158. package/dist/http/routes/tasks.d.ts +18 -0
  159. package/dist/http/routes/tasks.js +501 -38
  160. package/dist/http/routes/trace-usage.d.ts +10 -0
  161. package/dist/http/routes/trace-usage.js +66 -14
  162. package/dist/http/routes/workflows.d.ts +12 -0
  163. package/dist/http/routes/workflows.js +180 -19
  164. package/dist/http/run-meta.d.ts +11 -0
  165. package/dist/http/run-meta.js +6 -0
  166. package/dist/http/send.d.ts +19 -0
  167. package/dist/http/send.js +11 -0
  168. package/dist/http/server.d.ts +255 -0
  169. package/dist/http/server.js +921 -75
  170. package/dist/http/sse-log.d.ts +15 -0
  171. package/dist/http/sse-log.js +16 -0
  172. package/dist/http/tar.d.ts +9 -0
  173. package/dist/http/tar.js +21 -5
  174. package/dist/http/wire-gate.d.ts +9 -0
  175. package/dist/http/wire-gate.js +9 -0
  176. package/dist/http/wire-types.d.ts +187 -0
  177. package/dist/http/workspace-content.d.ts +8 -0
  178. package/dist/http/workspace-content.js +10 -0
  179. package/dist/images/bake-validate.d.ts +63 -0
  180. package/dist/images/bake-validate.js +71 -1
  181. package/dist/images/manifest.d.ts +19 -0
  182. package/dist/images/manifest.js +6 -1
  183. package/dist/index.d.ts +1 -5
  184. package/dist/index.js +10 -5
  185. package/dist/key-resolver.d.ts +23 -0
  186. package/dist/key-resolver.js +27 -2
  187. package/dist/leader/diffout.d.ts +23 -0
  188. package/dist/leader/diffout.js +8 -1
  189. package/dist/leader/diffup.d.ts +32 -0
  190. package/dist/leader/diffup.js +43 -0
  191. package/dist/leader/endpoint.d.ts +20 -0
  192. package/dist/leader/endpoint.js +25 -2
  193. package/dist/leader/fanout.d.ts +60 -0
  194. package/dist/leader/fanout.js +29 -3
  195. package/dist/leader/grader-env-factory.d.ts +74 -0
  196. package/dist/leader/grader-env-factory.js +62 -3
  197. package/dist/leader/leader.d.ts +97 -0
  198. package/dist/leader/leader.js +151 -4
  199. package/dist/leader/merge.d.ts +94 -0
  200. package/dist/leader/merge.js +112 -9
  201. package/dist/leader/planner.d.ts +52 -0
  202. package/dist/leader/planner.js +47 -3
  203. package/dist/leader/repair-oracle.d.ts +61 -0
  204. package/dist/leader/repair-oracle.js +59 -1
  205. package/dist/leader/repair-wire.d.ts +78 -0
  206. package/dist/leader/repair-wire.js +79 -2
  207. package/dist/leader/wire.d.ts +79 -0
  208. package/dist/leader/wire.js +255 -8
  209. package/dist/lsp/e2b-bridge.d.ts +16 -0
  210. package/dist/lsp/e2b-bridge.js +32 -4
  211. package/dist/lsp/e2b-manager.d.ts +10 -0
  212. package/dist/lsp/e2b-manager.js +18 -2
  213. package/dist/lsp/lsp-frames.d.ts +12 -0
  214. package/dist/lsp/lsp-frames.js +12 -0
  215. package/dist/lsp/manager.d.ts +12 -0
  216. package/dist/lsp/manager.js +35 -2
  217. package/dist/lsp/types.d.ts +10 -0
  218. package/dist/lsp/ws-transport.d.ts +12 -0
  219. package/dist/lsp/ws-transport.js +53 -5
  220. package/dist/lsp-evict.d.ts +14 -0
  221. package/dist/lsp-evict.js +15 -1
  222. package/dist/main.js +2132 -96
  223. package/dist/memory-export.d.ts +1 -0
  224. package/dist/memory-export.js +4 -0
  225. package/dist/memory-scope.d.ts +49 -0
  226. package/dist/memory-scope.js +87 -4
  227. package/dist/memory-sync-client.d.ts +24 -0
  228. package/dist/memory-sync-client.js +41 -2
  229. package/dist/memory-sync.d.ts +23 -0
  230. package/dist/memory-sync.js +70 -1
  231. package/dist/model-select.d.ts +39 -0
  232. package/dist/model-select.js +42 -1
  233. package/dist/observability/cost-quota.d.ts +20 -0
  234. package/dist/observability/cost-quota.js +4 -0
  235. package/dist/observability/cost-taxonomy.d.ts +45 -0
  236. package/dist/observability/cost-taxonomy.js +34 -0
  237. package/dist/observability/logger.d.ts +1 -0
  238. package/dist/observability/logger.js +6 -0
  239. package/dist/observability/metrics.d.ts +13 -0
  240. package/dist/observability/metrics.js +63 -0
  241. package/dist/observability/otel-exporter.d.ts +9 -0
  242. package/dist/observability/otel-exporter.js +11 -3
  243. package/dist/observability/principal-context.d.ts +9 -0
  244. package/dist/observability/principal-context.js +9 -0
  245. package/dist/observability/prompt-manifest.d.ts +37 -0
  246. package/dist/observability/prompt-manifest.js +35 -1
  247. package/dist/observability/rate-limit.d.ts +10 -0
  248. package/dist/observability/rate-limit.js +1 -0
  249. package/dist/observability/tool-trace.d.ts +24 -0
  250. package/dist/observability/tool-trace.js +41 -1
  251. package/dist/orchestration/hardened-vm-runner.d.ts +107 -0
  252. package/dist/orchestration/hardened-vm-runner.js +119 -4
  253. package/dist/orchestration/hardened-vm-worker-runner.d.ts +14 -0
  254. package/dist/orchestration/hardened-vm-worker-runner.js +26 -1
  255. package/dist/orchestration/hardened-vm-worker.js +27 -0
  256. package/dist/orchestration/subagent-steer.d.ts +44 -0
  257. package/dist/orchestration/subagent-steer.js +45 -1
  258. package/dist/orchestration/workflow-agent-steer.d.ts +54 -0
  259. package/dist/orchestration/workflow-agent-steer.js +80 -1
  260. package/dist/orchestration/workflow-completion-inbox.d.ts +189 -2
  261. package/dist/orchestration/workflow-completion-inbox.js +283 -32
  262. package/dist/orchestration/workflow-notify-journal.d.ts +132 -1
  263. package/dist/orchestration/workflow-notify-journal.js +187 -13
  264. package/dist/parked-decide.d.ts +61 -0
  265. package/dist/parked-decide.js +58 -1
  266. package/dist/per-task-image.d.ts +54 -0
  267. package/dist/per-task-image.js +41 -0
  268. package/dist/plan-cache-probe.d.ts +35 -0
  269. package/dist/plan-cache-probe.js +18 -3
  270. package/dist/plugins/approval-exemption-store.d.ts +7 -0
  271. package/dist/plugins/approval-exemption-store.js +28 -2
  272. package/dist/plugins/approval-store-sql.d.ts +64 -0
  273. package/dist/plugins/approval-store-sql.js +32 -0
  274. package/dist/plugins/background-agent-store-sql.d.ts +55 -0
  275. package/dist/plugins/background-agent-store-sql.js +91 -4
  276. package/dist/plugins/background-shell-support.d.ts +98 -0
  277. package/dist/plugins/background-shell-support.js +117 -13
  278. package/dist/plugins/blob-backend.d.ts +104 -0
  279. package/dist/plugins/blob-backend.js +163 -6
  280. package/dist/plugins/breaker-state-sql.d.ts +65 -1
  281. package/dist/plugins/breaker-state-sql.js +46 -8
  282. package/dist/plugins/caching-session-store.d.ts +42 -0
  283. package/dist/plugins/caching-session-store.js +63 -3
  284. package/dist/plugins/checkpoint-store-sql.d.ts +179 -0
  285. package/dist/plugins/checkpoint-store-sql.js +239 -11
  286. package/dist/plugins/file-outcome-sink.d.ts +4 -0
  287. package/dist/plugins/file-outcome-sink.js +9 -0
  288. package/dist/plugins/file-resume-anchor-store.d.ts +20 -0
  289. package/dist/plugins/file-resume-anchor-store.js +43 -4
  290. package/dist/plugins/file-run-store.d.ts +90 -0
  291. package/dist/plugins/file-run-store.js +145 -13
  292. package/dist/plugins/file-snapshot-store-sql.d.ts +133 -1
  293. package/dist/plugins/file-snapshot-store-sql.js +178 -10
  294. package/dist/plugins/file-workflow-journal-store.d.ts +10 -0
  295. package/dist/plugins/file-workflow-journal-store.js +10 -0
  296. package/dist/plugins/fork-routing-session-store.d.ts +47 -0
  297. package/dist/plugins/fork-routing-session-store.js +51 -3
  298. package/dist/plugins/host-platform.d.ts +69 -0
  299. package/dist/plugins/host-platform.js +81 -2
  300. package/dist/plugins/image-bake-store-sql.d.ts +136 -1
  301. package/dist/plugins/image-bake-store-sql.js +241 -7
  302. package/dist/plugins/image-index-sql.d.ts +46 -0
  303. package/dist/plugins/image-index-sql.js +113 -4
  304. package/dist/plugins/k8s-bg-scripts.d.ts +34 -0
  305. package/dist/plugins/k8s-bg-scripts.js +88 -4
  306. package/dist/plugins/k8s-exec-protocol.d.ts +33 -0
  307. package/dist/plugins/k8s-exec-protocol.js +41 -0
  308. package/dist/plugins/local-checkpoint-store.d.ts +40 -0
  309. package/dist/plugins/local-checkpoint-store.js +86 -7
  310. package/dist/plugins/local-session-store.d.ts +157 -0
  311. package/dist/plugins/local-session-store.js +289 -34
  312. package/dist/plugins/local-task-attachment-store.js +14 -2
  313. package/dist/plugins/mailbox-store-sql.d.ts +38 -0
  314. package/dist/plugins/mailbox-store-sql.js +39 -6
  315. package/dist/plugins/memory-engine-pg.d.ts +30 -0
  316. package/dist/plugins/memory-engine-pg.js +122 -4
  317. package/dist/plugins/memory-engine-tidb.d.ts +26 -0
  318. package/dist/plugins/memory-engine-tidb.js +115 -5
  319. package/dist/plugins/memory-engine-vector-util.d.ts +5 -0
  320. package/dist/plugins/memory-engine-vector-util.js +5 -0
  321. package/dist/plugins/memory-resume-anchor-store.d.ts +8 -0
  322. package/dist/plugins/memory-resume-anchor-store.js +17 -0
  323. package/dist/plugins/memory-run-store.d.ts +63 -0
  324. package/dist/plugins/memory-run-store.js +73 -8
  325. package/dist/plugins/memory-session-policy-store.d.ts +17 -0
  326. package/dist/plugins/memory-session-policy-store.js +17 -0
  327. package/dist/plugins/memory-sync-store-pg.d.ts +42 -0
  328. package/dist/plugins/memory-sync-store-pg.js +45 -2
  329. package/dist/plugins/memory-sync-store-tidb.d.ts +9 -0
  330. package/dist/plugins/memory-sync-store-tidb.js +31 -1
  331. package/dist/plugins/outcome-ledger-sql.d.ts +63 -0
  332. package/dist/plugins/outcome-ledger-sql.js +97 -3
  333. package/dist/plugins/pg-approval-store.d.ts +7 -0
  334. package/dist/plugins/pg-approval-store.js +7 -0
  335. package/dist/plugins/pg-breaker-state.d.ts +6 -0
  336. package/dist/plugins/pg-breaker-state.js +6 -0
  337. package/dist/plugins/pg-checkpoint-store.d.ts +8 -0
  338. package/dist/plugins/pg-checkpoint-store.js +8 -0
  339. package/dist/plugins/pg-cost-quota.d.ts +17 -0
  340. package/dist/plugins/pg-cost-quota.js +6 -0
  341. package/dist/plugins/pg-file-snapshot-store.d.ts +6 -0
  342. package/dist/plugins/pg-file-snapshot-store.js +6 -0
  343. package/dist/plugins/pg-image-bake.d.ts +9 -0
  344. package/dist/plugins/pg-image-bake.js +9 -0
  345. package/dist/plugins/pg-image-index.d.ts +9 -0
  346. package/dist/plugins/pg-image-index.js +9 -0
  347. package/dist/plugins/pg-outcome-ledger.d.ts +9 -0
  348. package/dist/plugins/pg-outcome-ledger.js +9 -0
  349. package/dist/plugins/pg-pool.d.ts +50 -0
  350. package/dist/plugins/pg-pool.js +78 -0
  351. package/dist/plugins/pg-query.d.ts +11 -0
  352. package/dist/plugins/pg-rate-limiter.d.ts +23 -0
  353. package/dist/plugins/pg-rate-limiter.js +12 -2
  354. package/dist/plugins/pg-resume-anchor-store.d.ts +5 -0
  355. package/dist/plugins/pg-resume-anchor-store.js +5 -0
  356. package/dist/plugins/pg-run-store.d.ts +7 -0
  357. package/dist/plugins/pg-run-store.js +7 -0
  358. package/dist/plugins/pg-safe-json.d.ts +13 -0
  359. package/dist/plugins/pg-safe-json.js +40 -4
  360. package/dist/plugins/pg-session-policy-store.d.ts +5 -0
  361. package/dist/plugins/pg-session-policy-store.js +5 -0
  362. package/dist/plugins/pg-session-storage.d.ts +72 -0
  363. package/dist/plugins/pg-session-storage.js +152 -20
  364. package/dist/plugins/pg-session-store.d.ts +10 -0
  365. package/dist/plugins/pg-session-store.js +10 -0
  366. package/dist/plugins/pg-tool-result-store.d.ts +7 -0
  367. package/dist/plugins/pg-tool-result-store.js +7 -0
  368. package/dist/plugins/pg-workflow-journal-store.d.ts +7 -0
  369. package/dist/plugins/pg-workflow-journal-store.js +7 -0
  370. package/dist/plugins/pg-workflow-run-store.d.ts +7 -0
  371. package/dist/plugins/pg-workflow-run-store.js +7 -0
  372. package/dist/plugins/posix-shell-fs.d.ts +3 -0
  373. package/dist/plugins/posix-shell-fs.js +31 -1
  374. package/dist/plugins/remote-env-adb.d.ts +25 -0
  375. package/dist/plugins/remote-env-adb.js +95 -12
  376. package/dist/plugins/remote-env-e2b.d.ts +146 -0
  377. package/dist/plugins/remote-env-e2b.js +371 -40
  378. package/dist/plugins/remote-env-file-error.d.ts +34 -0
  379. package/dist/plugins/remote-env-file-error.js +37 -0
  380. package/dist/plugins/remote-env-host.d.ts +151 -0
  381. package/dist/plugins/remote-env-host.js +468 -70
  382. package/dist/plugins/remote-env-k8s.d.ts +135 -0
  383. package/dist/plugins/remote-env-k8s.js +318 -32
  384. package/dist/plugins/remote-env-local-docker.d.ts +65 -0
  385. package/dist/plugins/remote-env-local-docker.js +149 -24
  386. package/dist/plugins/remote-env-ssh.d.ts +35 -0
  387. package/dist/plugins/remote-env-ssh.js +117 -20
  388. package/dist/plugins/remote-scratchpad.d.ts +38 -0
  389. package/dist/plugins/remote-scratchpad.js +32 -2
  390. package/dist/plugins/remote-shell.d.ts +22 -0
  391. package/dist/plugins/remote-shell.js +27 -1
  392. package/dist/plugins/resume-anchor-store-sql.d.ts +28 -0
  393. package/dist/plugins/resume-anchor-store-sql.js +11 -0
  394. package/dist/plugins/roster-store-sql.d.ts +27 -0
  395. package/dist/plugins/roster-store-sql.js +54 -0
  396. package/dist/plugins/run-store-sql.d.ts +194 -0
  397. package/dist/plugins/run-store-sql.js +210 -9
  398. package/dist/plugins/s3-presign.d.ts +20 -0
  399. package/dist/plugins/s3-presign.js +49 -2
  400. package/dist/plugins/scheduler-support.d.ts +12 -0
  401. package/dist/plugins/scheduler-support.js +75 -3
  402. package/dist/plugins/send-file-ledger.d.ts +15 -0
  403. package/dist/plugins/send-file-ledger.js +53 -4
  404. package/dist/plugins/send-user-file.d.ts +77 -0
  405. package/dist/plugins/send-user-file.js +92 -4
  406. package/dist/plugins/session-policy-store-sql.d.ts +15 -0
  407. package/dist/plugins/session-policy-store-sql.js +75 -3
  408. package/dist/plugins/session-store.d.ts +45 -0
  409. package/dist/plugins/session-store.js +51 -0
  410. package/dist/plugins/sql-driver.d.ts +77 -0
  411. package/dist/plugins/sql-driver.js +4 -0
  412. package/dist/plugins/sql-escape.d.ts +8 -0
  413. package/dist/plugins/sql-escape.js +8 -0
  414. package/dist/plugins/sql-row-helpers.d.ts +25 -0
  415. package/dist/plugins/sql-row-helpers.js +25 -0
  416. package/dist/plugins/store-backend.d.ts +103 -0
  417. package/dist/plugins/store-backend.js +120 -27
  418. package/dist/plugins/store-contracts.d.ts +62 -0
  419. package/dist/plugins/store-contracts.js +3 -0
  420. package/dist/plugins/task-attachment-store.d.ts +60 -0
  421. package/dist/plugins/task-attachment-store.js +49 -3
  422. package/dist/plugins/task-list-store-sql.d.ts +25 -0
  423. package/dist/plugins/task-list-store-sql.js +21 -0
  424. package/dist/plugins/tidb-approval-store.d.ts +6 -0
  425. package/dist/plugins/tidb-approval-store.js +6 -0
  426. package/dist/plugins/tidb-breaker-state.d.ts +5 -0
  427. package/dist/plugins/tidb-breaker-state.js +5 -0
  428. package/dist/plugins/tidb-checkpoint-store.d.ts +7 -0
  429. package/dist/plugins/tidb-checkpoint-store.js +7 -0
  430. package/dist/plugins/tidb-cost-quota.d.ts +6 -0
  431. package/dist/plugins/tidb-cost-quota.js +1 -0
  432. package/dist/plugins/tidb-file-snapshot-store.d.ts +6 -0
  433. package/dist/plugins/tidb-file-snapshot-store.js +6 -0
  434. package/dist/plugins/tidb-image-bake.d.ts +8 -0
  435. package/dist/plugins/tidb-image-bake.js +8 -0
  436. package/dist/plugins/tidb-image-index.d.ts +8 -0
  437. package/dist/plugins/tidb-image-index.js +8 -0
  438. package/dist/plugins/tidb-outcome-ledger.d.ts +10 -0
  439. package/dist/plugins/tidb-outcome-ledger.js +10 -0
  440. package/dist/plugins/tidb-pool.d.ts +56 -0
  441. package/dist/plugins/tidb-pool.js +181 -1
  442. package/dist/plugins/tidb-rate-limiter.d.ts +11 -0
  443. package/dist/plugins/tidb-rate-limiter.js +5 -2
  444. package/dist/plugins/tidb-resume-anchor-store.d.ts +5 -0
  445. package/dist/plugins/tidb-resume-anchor-store.js +5 -0
  446. package/dist/plugins/tidb-run-store.d.ts +7 -0
  447. package/dist/plugins/tidb-run-store.js +7 -0
  448. package/dist/plugins/tidb-session-policy-store.d.ts +5 -0
  449. package/dist/plugins/tidb-session-policy-store.js +5 -0
  450. package/dist/plugins/tidb-session-storage.d.ts +43 -0
  451. package/dist/plugins/tidb-session-storage.js +62 -3
  452. package/dist/plugins/tidb-session-store.d.ts +142 -0
  453. package/dist/plugins/tidb-session-store.js +264 -16
  454. package/dist/plugins/tidb-tool-result-store.d.ts +5 -0
  455. package/dist/plugins/tidb-tool-result-store.js +7 -0
  456. package/dist/plugins/tidb-workflow-journal-store.d.ts +7 -0
  457. package/dist/plugins/tidb-workflow-journal-store.js +7 -0
  458. package/dist/plugins/tidb-workflow-run-store.d.ts +8 -0
  459. package/dist/plugins/tidb-workflow-run-store.js +8 -0
  460. package/dist/plugins/tool-result-store-sql.d.ts +58 -0
  461. package/dist/plugins/tool-result-store-sql.js +38 -2
  462. package/dist/plugins/web-search.d.ts +35 -0
  463. package/dist/plugins/web-search.js +45 -9
  464. package/dist/plugins/workflow-journal-limits.d.ts +10 -0
  465. package/dist/plugins/workflow-journal-limits.js +10 -0
  466. package/dist/plugins/workflow-journal-store-sql.d.ts +78 -0
  467. package/dist/plugins/workflow-journal-store-sql.js +59 -3
  468. package/dist/plugins/workflow-run-store-sql.d.ts +84 -0
  469. package/dist/plugins/workflow-run-store-sql.js +84 -6
  470. package/dist/plugins/worktree-isolation.d.ts +45 -0
  471. package/dist/plugins/worktree-isolation.js +105 -6
  472. package/dist/plugins/write-behind-counter.d.ts +56 -1
  473. package/dist/plugins/write-behind-counter.js +53 -14
  474. package/dist/principal-jwt.d.ts +24 -0
  475. package/dist/principal-jwt.js +60 -5
  476. package/dist/project-memory.d.ts +22 -0
  477. package/dist/project-memory.js +144 -15
  478. package/dist/prompts-domain-validate.d.ts +28 -0
  479. package/dist/prompts-domain-validate.js +42 -1
  480. package/dist/question.d.ts +33 -0
  481. package/dist/question.js +69 -2
  482. package/dist/resource-suspend.d.ts +21 -0
  483. package/dist/resource-suspend.js +16 -0
  484. package/dist/router/route-orchestration.d.ts +78 -0
  485. package/dist/router/route-orchestration.js +77 -0
  486. package/dist/run-local.d.ts +32 -0
  487. package/dist/run-local.js +172 -8
  488. package/dist/runs.d.ts +189 -4
  489. package/dist/runs.js +465 -24
  490. package/dist/runtime-caps-resolver.d.ts +106 -0
  491. package/dist/runtime-caps-resolver.js +89 -4
  492. package/dist/runtime-governance.d.ts +84 -0
  493. package/dist/runtime-governance.js +127 -1
  494. package/dist/sandbox-pkg-source.d.ts +23 -0
  495. package/dist/sandbox-pkg-source.js +37 -0
  496. package/dist/sealed-key.d.ts +54 -0
  497. package/dist/sealed-key.js +68 -3
  498. package/dist/security.d.ts +108 -0
  499. package/dist/security.js +145 -6
  500. package/dist/sema-registry.d.ts +21 -0
  501. package/dist/sema-registry.js +21 -0
  502. package/dist/session-leaf-bus.d.ts +31 -0
  503. package/dist/session-leaf-bus.js +32 -0
  504. package/dist/session-sync-content.d.ts +46 -0
  505. package/dist/session-sync-content.js +47 -1
  506. package/dist/session-sync-kernel.d.ts +89 -0
  507. package/dist/session-sync-kernel.js +48 -3
  508. package/dist/session-sync.d.ts +125 -0
  509. package/dist/session-sync.js +181 -8
  510. package/dist/session-titler.d.ts +26 -0
  511. package/dist/session-titler.js +41 -7
  512. package/dist/session-watch.d.ts +53 -1
  513. package/dist/session-watch.js +73 -9
  514. package/dist/sighup-idle.d.ts +30 -0
  515. package/dist/sighup-idle.js +12 -1
  516. package/dist/spec-fields.d.ts +91 -3
  517. package/dist/spec-fields.js +116 -4
  518. package/dist/task-cwd.d.ts +50 -0
  519. package/dist/task-cwd.js +68 -1
  520. package/dist/task-mcp.d.ts +47 -0
  521. package/dist/task-mcp.js +29 -0
  522. package/dist/task-settings.d.ts +175 -0
  523. package/dist/task-settings.js +226 -11
  524. package/dist/task-workflow.d.ts +67 -0
  525. package/dist/task-workflow.js +75 -8
  526. package/dist/tool-approval.d.ts +91 -0
  527. package/dist/tool-approval.js +215 -0
  528. package/dist/trace/artifacts.d.ts +9 -0
  529. package/dist/trace/artifacts.js +30 -5
  530. package/dist/trace/core-keyset-guard.d.ts +18 -0
  531. package/dist/trace/ledger-sink.d.ts +43 -0
  532. package/dist/trace/ledger-sink.js +64 -5
  533. package/dist/trace/project.d.ts +133 -0
  534. package/dist/trace/project.js +189 -2
  535. package/dist/trace/redact.d.ts +19 -0
  536. package/dist/trace/redact.js +66 -9
  537. package/dist/usage-analytics.d.ts +26 -0
  538. package/dist/usage-analytics.js +26 -3
  539. package/package.json +1 -1
@@ -1,8 +1,31 @@
1
+ /**
2
+ * 件3d `/decide` 消费 parked 后台子代——server 半场辅件(设计稿:sema-internal
3
+ * server/docs/DECIDE-PARKED-DESIGN.md;黑板 [1587];core 裁定 [1574]/[1584])。
4
+ *
5
+ * 本模块先落判别器:`POST /v1/approvals/:sessionId/decide` 路由在既有 session→token 映射拿到
6
+ * pending checkpoint 后,用它判定该 cp 是否属于一个 parked 后台子代——命中则走 claim →
7
+ * 裸 `ToolSpec.execute`(ctx.reviveClaim)赎回腿,不中则零回归走既有任务级 resumeCheckpoint 腿。
8
+ * 判别必须 parked-first:legacy 腿的 `resumeStream` 会绕开 bg registry(无 consumeParkedFlip、
9
+ * 行永 parked、生命周期分叉)。
10
+ */
1
11
  import type { BackgroundAgentRecord, BackgroundAgentStore, CheckpointStore, TaskRegistry, ToolSpec } from "@sema-agent/core";
2
12
  export interface ParkedAgentMatch {
3
13
  handle: string;
4
14
  row: BackgroundAgentRecord;
5
15
  }
16
+ /**
17
+ * pending checkpoint → parked bg 行匹配。
18
+ *
19
+ * 键链(core 1.390 事实):park 时 cp 落 `sourceTaskId: sessionId`(子会话 id,**不是** bg handle),
20
+ * 而 bg 行同样存该子会话 id(`row.sessionId`)与绑定 token(`row.parkedCheckpointToken`)。
21
+ * `listByScope` 只回 summary(含 handle/sessionId、不含 token),故两步:summary.sessionId 初筛 →
22
+ * `get(handle, scope)` 全行复核 token。
23
+ *
24
+ * token 复核是硬门,不是优化:行 REOPENED 后可在**新** token 下 re-park,旧 cp 的 decide 不得
25
+ * 匹配到它(后续 `claimParkedAgent` 的 CAS/binding_broken 是兜底,不是第一道门)。同理,list 与
26
+ * get 之间行被 stop/decide 抢走(离开 parked)时诚实 miss——调用方拿 undefined 走 legacy 腿,
27
+ * 该腿对已消失的 pending cp 有自己的 404/409 处置。
28
+ */
6
29
  export declare function findParkedAgentForCheckpoint(agentStore: BackgroundAgentStore, cp: {
7
30
  token: string;
8
31
  scope: string;
@@ -11,9 +34,19 @@ export declare function findParkedAgentForCheckpoint(agentStore: BackgroundAgent
11
34
  export interface ParkedDecideDeps {
12
35
  agentStore: BackgroundAgentStore;
13
36
  checkpointStore: Pick<CheckpointStore, "get">;
37
+ /** 与 reaper/scenarios 同一个 registry(claim/rollback 的 CAS 与 in-memory handle 收敛在同处)。 */
14
38
  registry: Pick<TaskRegistry, "claimParkedAgent" | "rollbackParkedClaim">;
39
+ /** boot 期从生产装配(buildScenarios)取的裸 Agent ToolSpec——与 spawn 用同一装配路径,
40
+ * subRunner/bg opts/checkpointStore 同实例天然成立([1587] 设计稿 §4)。 */
15
41
  reviveTool: ToolSpec;
42
+ /** revive args 的 `subagent_type` 成员性判定集([1588] Q1 修正:非 roster 成员必须省略,否则
43
+ * unknown subagent_type 拒;字面比对 general-purpose 在 roster 撞名时会错省)。缺省空集=恒省略。 */
16
44
  knownAgentTypes?: ReadonlySet<string>;
45
+ /** [1596]/[1597] 跨进程父约束重供席:按部署配置**重建的同语义**父策略链工厂(host 任务的 toolPolicy
46
+ * 解析槽一条,单层链;exempt 探针锚= row.rootSessionId,与 remember grant 锚同键)。core 1.396 起
47
+ * `parkedResume.inheritedGate` 席位把它透传进 resume 的官方重供通道——不供 = 重启后带
48
+ * requiresParentConstraint 的 checkpoint 恒被 pre-CAS 门拒(retryable 假话,永不可赎回)。链长形状
49
+ * 校验在 core(fail-closed,供错链长照拒)。 */
17
50
  rebuildInheritedGate?: (row: BackgroundAgentRecord) => unknown;
18
51
  warn?: (event: string, fields: Record<string, unknown>) => void;
19
52
  }
@@ -21,21 +54,49 @@ export interface ParkedDecideRequest {
21
54
  token: string;
22
55
  scope: string;
23
56
  sessionId: string;
57
+ /** cp.pendingAction 原样(outcome 铸造的 persisted 回落源,与 legacy 腿 D-1 姿势逐字同形)。 */
24
58
  pendingAction: unknown;
25
59
  decision: "approve" | "deny";
26
60
  reason?: string;
61
+ /** D-1 decision-binding echo(操作员在 GET 看到的 boundCallId/boundInputHash 原样透传;server
62
+ * 绝不重算,core resume 侧做 fail-closed 等值校验——与 legacy 腿同姿势)。 */
27
63
  binding?: {
28
64
  boundCallId?: string;
29
65
  boundInputHash?: string;
30
66
  updatedInput?: unknown;
31
67
  };
68
+ /** body 带了 `remember:"session"` 时路由传入的 grant 执行器([1591] 候裁② 的 server 侧修,经两轮
69
+ * 行为探针实证):豁免必须锚在**行的 root/host 会话 id**——部署侧三个豁免探针(policy 层/fs-write
70
+ * 门/workflow 门)的闭包统一捕获 host 会话键且签名不携身份(1.393 seam 亲读:`sourceTaskId` 只在
71
+ * onAsk 层的 AskRequest,durable 车道无 onAsk),grant 落子代会话则键永不相交(G-F4 原案);落
72
+ * root 会话则宿主键闭包立即命中,复活子代的后续同工具 ask 被短路(探针 v2 实证),语义与同步车道/
73
+ * 宿主任务的「本会话不再询问」一致(= host 会话树全域)。行无 root 锚(病态形)⇒ claim 前诚实 400。 */
32
74
  grantRemember?: (rootSessionId: string) => Promise<void>;
75
+ /** body 带了 `answer`(复审 F6):parked 腿无 onQuestion 挂点,显式 400 与 legacy 腿对同一
76
+ * 畸形输入的拒绝姿势对齐(legacy:「answer 仅在 approve AskUserQuestion 时合法」),不静默吞。 */
33
77
  answerPresent?: boolean;
78
+ /** claim CAS 赢了(≈ legacy 腿的 markResuming 赢)之后、execute 之前触发——remember 豁免 grant
79
+ * 的挂点(调用方自吞错,绝不抛落赎回)。claim 败/判别 miss 恒不触发。 */
34
80
  onDecideCommitted?: () => Promise<void>;
35
81
  }
36
82
  export interface ParkedDecideResult {
37
83
  status: number;
38
84
  body: Record<string, unknown>;
39
85
  }
86
+ /**
87
+ * `/decide` parked 赎回腿(design/153 件3d server 半场;[1574]/[1584]/[1588] core 裁定形)。
88
+ *
89
+ * 返回 `undefined` = 该 pending checkpoint 不属于任何 parked 后台子代——调用方走既有任务级
90
+ * resumeCheckpoint 腿(零回归);返回结果对象 = 赎回腿已受理/已拒,调用方直接回 HTTP。
91
+ *
92
+ * 链:判别(findParkedAgentForCheckpoint)→ `claimParkedAgent`(access = 行镜像双轴
93
+ * `{scope: row.scope, owner: row.owner}`,[1588] Q3)→ outcome 铸造(D-1 echo/persisted 回落)
94
+ * → 裸 `reviveTool.execute(args, ctx.reviveClaim)`。execute 一旦发起 drive,rollback 全在 core 内
95
+ * (driveParkedResume);server 只在「claim 成功但 drive 从未发起」窗口补 `rollbackParkedClaim`
96
+ * ([1588] Q2:isError 入参级早退 + throw 两形,已核幂等/双滚=无害 lost)。
97
+ *
98
+ * 200 是**受理**语义(drive 是 core 内 fire-and-forget):失败经行/notification 面 + REOPENED
99
+ * re-park 诚实可见,操作员可再决。
100
+ */
40
101
  export declare function decideParkedAgent(deps: ParkedDecideDeps, req: ParkedDecideRequest): Promise<ParkedDecideResult | undefined>;
41
102
  //# sourceMappingURL=parked-decide.d.ts.map
@@ -1,3 +1,16 @@
1
+ /**
2
+ * pending checkpoint → parked bg 行匹配。
3
+ *
4
+ * 键链(core 1.390 事实):park 时 cp 落 `sourceTaskId: sessionId`(子会话 id,**不是** bg handle),
5
+ * 而 bg 行同样存该子会话 id(`row.sessionId`)与绑定 token(`row.parkedCheckpointToken`)。
6
+ * `listByScope` 只回 summary(含 handle/sessionId、不含 token),故两步:summary.sessionId 初筛 →
7
+ * `get(handle, scope)` 全行复核 token。
8
+ *
9
+ * token 复核是硬门,不是优化:行 REOPENED 后可在**新** token 下 re-park,旧 cp 的 decide 不得
10
+ * 匹配到它(后续 `claimParkedAgent` 的 CAS/binding_broken 是兜底,不是第一道门)。同理,list 与
11
+ * get 之间行被 stop/decide 抢走(离开 parked)时诚实 miss——调用方拿 undefined 走 legacy 腿,
12
+ * 该腿对已消失的 pending cp 有自己的 404/409 处置。
13
+ */
1
14
  export async function findParkedAgentForCheckpoint(agentStore, cp) {
2
15
  const parked = await agentStore.listByScope(cp.scope, { status: "parked" });
3
16
  for (const s of parked) {
@@ -12,6 +25,9 @@ export async function findParkedAgentForCheckpoint(agentStore, cp) {
12
25
  }
13
26
  return undefined;
14
27
  }
28
+ /** [1588] Q1 裁定的 revive args 铸法:占位 prompt(objective 在 driveParkedResume 被丢弃,仅过非空门)、
29
+ * `run_in_background: true` 必须(revive.no_background 拒)、`name` 必传承重(名门校验+下游 park 资格
30
+ * 谓词吃 agentName)、`subagent_type` 按 roster 成员性判。 */
15
31
  function mintReviveArgs(row, knownAgentTypes) {
16
32
  return {
17
33
  prompt: row.description ?? "resume parked agent",
@@ -21,16 +37,34 @@ function mintReviveArgs(row, knownAgentTypes) {
21
37
  ...(row.agentType !== undefined && knownAgentTypes.has(row.agentType) ? { subagent_type: row.agentType } : {}),
22
38
  };
23
39
  }
40
+ /**
41
+ * `/decide` parked 赎回腿(design/153 件3d server 半场;[1574]/[1584]/[1588] core 裁定形)。
42
+ *
43
+ * 返回 `undefined` = 该 pending checkpoint 不属于任何 parked 后台子代——调用方走既有任务级
44
+ * resumeCheckpoint 腿(零回归);返回结果对象 = 赎回腿已受理/已拒,调用方直接回 HTTP。
45
+ *
46
+ * 链:判别(findParkedAgentForCheckpoint)→ `claimParkedAgent`(access = 行镜像双轴
47
+ * `{scope: row.scope, owner: row.owner}`,[1588] Q3)→ outcome 铸造(D-1 echo/persisted 回落)
48
+ * → 裸 `reviveTool.execute(args, ctx.reviveClaim)`。execute 一旦发起 drive,rollback 全在 core 内
49
+ * (driveParkedResume);server 只在「claim 成功但 drive 从未发起」窗口补 `rollbackParkedClaim`
50
+ * ([1588] Q2:isError 入参级早退 + throw 两形,已核幂等/双滚=无害 lost)。
51
+ *
52
+ * 200 是**受理**语义(drive 是 core 内 fire-and-forget):失败经行/notification 面 + REOPENED
53
+ * re-park 诚实可见,操作员可再决。
54
+ */
24
55
  export async function decideParkedAgent(deps, req) {
25
56
  let match;
26
57
  try {
27
58
  match = await findParkedAgentForCheckpoint(deps.agentStore, { token: req.token, scope: req.scope, sessionId: req.sessionId });
28
59
  }
29
60
  catch (e) {
61
+ // 复审 F2:bg 店瞬态读故障绝不能把(含任务级在内的)decide 变裸 500——诚实按 miss 处理,
62
+ // legacy 腿对 parked cp 有自己的 409 处置(retriable),任务级 cp 照常 resume。
30
63
  try {
31
64
  deps.warn?.("parked_decide_probe_failed", { error: e instanceof Error ? e.message : String(e) });
32
65
  }
33
66
  catch {
67
+ // warn 自身故障不改变结果面
34
68
  }
35
69
  return undefined;
36
70
  }
@@ -39,16 +73,22 @@ export async function decideParkedAgent(deps, req) {
39
73
  const row = match.row;
40
74
  const rememberRoot = req.grantRemember !== undefined ? (row.rootSessionId ?? row.parentSessionId) : undefined;
41
75
  if (req.grantRemember !== undefined && rememberRoot === undefined) {
76
+ // remember 的 grant 必须锚在 root/host 会话(探针闭包键);行无任何会话锚 = 无处可落,claim 前诚实拒。
42
77
  return { status: 400, body: { error: "remember cannot be applied: this parked agent row carries no root/parent session anchor for the exemption", errorCode: "decide.parked_remember_unsupported", taskId: match.handle } };
43
78
  }
44
79
  if (req.answerPresent === true) {
80
+ // 复审 F6:与 legacy 腿同姿势显式拒,不静默丢弃操作员的输入。
45
81
  return { status: 400, body: { error: "body.answer is not supported when deciding a parked background agent (no question hookpoint on the revive path)", errorCode: "decide.parked_answer_unsupported", taskId: match.handle } };
46
82
  }
47
83
  const pendingTool = req.pendingAction?.toolName;
48
84
  if (pendingTool === "AskUserQuestion" && req.decision === "approve") {
85
+ // 复审 F1:只拦 approve(approve 必须携 answer 才有意义,而 parked 腿无 onQuestion 挂点);
86
+ // deny 放行走赎回(deny outcome 不需要 answer),决策面不留死角。claim 之前拒,claim 不被消费。
49
87
  return { status: 400, body: { error: "pending action is AskUserQuestion — approve is not supported for a parked background agent (deny it, stop the agent, or let the gate expire)", errorCode: "decide.parked_question_unsupported", taskId: match.handle } };
50
88
  }
51
89
  if (row.name === undefined) {
90
+ // forwardDurableApproval 只对具名子代成立,parked 行理应恒有 name;缺 = 行受损,claim 前诚实拒
91
+ // ([1588] Q1:name 必传承重——省略会把 revive 降级成匿名形)。
52
92
  return { status: 409, body: { error: "parked row carries no agent name — the revive path requires a named agent (row damaged?)", errorCode: "decide.row_unrevivable", taskId: match.handle } };
53
93
  }
54
94
  const stores = { agentStore: deps.agentStore, checkpointStore: deps.checkpointStore };
@@ -58,11 +98,13 @@ export async function decideParkedAgent(deps, req) {
58
98
  case "store_unreachable":
59
99
  return { status: 503, body: { error: "the durable agent store is unreachable — retry", errorCode: "decide.store_unreachable", taskId: match.handle } };
60
100
  case "claim_lost":
101
+ // 复审 F8:claim_lost 也覆盖「上一轮 rollback 落 retry(claim 悬挂)」的形——那时要等 reaper 的
102
+ // stale-claim 清算窗(BG_AGENT_PARK_CLAIM_STALE_MS)过后才能再决,文案如实给出两种可能。
61
103
  return { status: 409, body: { error: "the parked agent is already claimed — either a concurrent decide won (re-check the pending list), or a stale claim is pending automatic cleanup (retry after the stale-claim window)", errorCode: "decide.claim_lost", taskId: match.handle } };
62
104
  case "binding_broken":
63
105
  case "checkpoint_not_pending":
64
106
  return { status: 409, body: { error: "the approval gate moved under this decide (re-parked or already settled) — re-check the pending list", errorCode: "decide.gate_moved", taskId: match.handle } };
65
- default:
107
+ default: // not_found | not_parked——行在判别与 claim 之间被 stop/另一 decide 抢走
66
108
  return { status: 409, body: { error: "the parked agent moved under this decide (stopped or already decided)", errorCode: "decide.not_parked", taskId: match.handle } };
67
109
  }
68
110
  }
@@ -71,12 +113,17 @@ export async function decideParkedAgent(deps, req) {
71
113
  await req.onDecideCommitted?.();
72
114
  }
73
115
  catch {
116
+ // remember-grant 类挂点自吞错(与 legacy 腿 grantOnCommit 同姿势):绝不让豁免记账故障打断赎回。
74
117
  }
75
118
  if (req.grantRemember !== undefined && rememberRoot !== undefined) {
76
119
  try {
120
+ // claim 赢(≈ legacy 腿 markResuming CAS 赢)后、drive 前落店——复活腿自己的下一个同工具 ask
121
+ // 即可命中豁免(与 legacy 腿 1.294 grant-timing 裁定同向)。grant 失败由路由闭包自记 warn 并
122
+ // 让 rememberApplied 如实为 false,不阻断赎回。
77
123
  await req.grantRemember(rememberRoot);
78
124
  }
79
125
  catch {
126
+ // 同上:豁免记账故障不进赎回结果面
80
127
  }
81
128
  }
82
129
  const pa = req.pendingAction;
@@ -98,15 +145,20 @@ export async function decideParkedAgent(deps, req) {
98
145
  parkedResume: {
99
146
  ticket,
100
147
  outcome,
148
+ // [1597] 席位:重建父约束链(同进程时 core 的内存 registry 也能自动重供,席位供了也无害
149
+ // ——core 侧 count 校验对得上即用;跨进程/重启形全靠这里)。
101
150
  ...(deps.rebuildInheritedGate ? { inheritedGate: deps.rebuildInheritedGate(row) } : {}),
102
151
  },
103
152
  },
104
153
  };
154
+ // 复审 F7:warn 回调自身故障(duck-typed logger 缺方法/日志面抖动)绝不能改写 rollback 的结果面——
155
+ // 已成功的回滚若因 warn 抛错逃逸成 500/reject,操作员会对着"失败"重试一个其实已回纯的行。
105
156
  const quietWarn = (event, fields) => {
106
157
  try {
107
158
  deps.warn?.(event, fields);
108
159
  }
109
160
  catch {
161
+ // 观测面故障不进结果面
110
162
  }
111
163
  };
112
164
  const rollback = async (why) => {
@@ -138,6 +190,11 @@ export async function decideParkedAgent(deps, req) {
138
190
  }
139
191
  const isErr = typeof receipt === "object" && receipt !== null && receipt.isError === true;
140
192
  if (isErr) {
193
+ // execute 的入参级早退臂(revive.no_background/name 门/type 门等)return 于任何 registry 动作之前,
194
+ // core 不代滚([1588] Q2 核定)——这仍在「drive 未发起」窗口,server 补滚。
195
+ // 复审 G-F5 口径补充:isError 不恒等于「早退未滚」——core 的 parked_resume.startup_failed 臂是
196
+ // drive 已发起且 core 已自滚后的 isError;此处补滚在 rollbackParkedClaim 的 claimId CAS 下退化为
197
+ // 无害 "lost"([1588] Q2 幂等核定),结果面仍诚实(操作员重查 pending 列表即可自愈)。
141
198
  const disp = await rollback("execute_rejected");
142
199
  const content = receipt.content;
143
200
  return {
@@ -1,4 +1,20 @@
1
+ /**
2
+ * §7 P0.5 — per-task sandbox image binding (門B "用户按需选像"). IMAGE-API-DESIGN §7.
3
+ *
4
+ * The caller sends a PROFILE (intent) on the run body — NEVER a digest. The trusted control plane (this service,
5
+ * with the caller's principal) resolves the profile → a pullable `repo@digest`, FAIL-CLOSED, re-admitting by the
6
+ * SAME per-principal visibility the `/v1/images/select` admission uses. Why profile-not-digest: a digest is a
7
+ * stable, enumerable sha256 with no caller-binding — trusting a caller-supplied digest is fail-OPEN (a user could
8
+ * pass another tenant's digest to pull an image they can't see). Resolving inside the trust boundary closes that.
9
+ *
10
+ * The resolved ref reaches the worker-global {@link import("@sema-agent/core").ExecutionEnvFactory} (which
11
+ * only receives core's deliberately-minimal `{sessionId}` context) via {@link PerTaskImageRegistry} — core's own
12
+ * doctrine: "richer routing is captured in the factory closure by the trusted control plane". This module is that
13
+ * capture, kept narrow + unit-testable.
14
+ */
1
15
  import type { ImageViewer, ImageIndexEntry } from "./plugins/store-contracts.js";
16
+ /** Minimal slice of the image index the per-task resolver needs (a testable seam — the real `imageIndex`'s
17
+ * `latestPublished` returns the full {@link ImageIndexEntry}, which is assignable to this Pick). */
2
18
  export interface SandboxImageResolver {
3
19
  latestPublished(profile: string, viewer: ImageViewer): Promise<Pick<ImageIndexEntry, "repo" | "digest" | "capabilities"> | null>;
4
20
  }
@@ -11,17 +27,55 @@ export type SandboxImageResolution = {
11
27
  status: number;
12
28
  message: string;
13
29
  };
30
+ /**
31
+ * Resolve a requested sandbox image PROFILE to a pullable `repo@digest`, FAIL-CLOSED, re-admitting by `viewer`:
32
+ * - `latestPublished(profile, viewer)` applies the SAME `visibilityClause` + `status='published'` filter the
33
+ * select admission uses. Not visible / not published ⇒ `{ok:false, 404}` (never silent-allow).
34
+ * - each `capabilitiesNeeded` entry must be a known boolean capability AND true on the resolved image, else fail.
35
+ * Pure over the injected `index` ⇒ unit-testable with a fake resolver.
36
+ *
37
+ * NOTE (review LOW — error-code asymmetry, DELIBERATE): a not-visible / capability-miss here returns 404, whereas
38
+ * the operator-facing `POST /v1/images/select` returns 409 + `missing`. That is intentional: task admission is an
39
+ * UNTRUSTED-caller gate that must NOT distinguish "profile exists but you can't see it" from "doesn't exist"
40
+ * (revealing that leaks the existence of other tenants' images), so it collapses both to 404. The select catalog
41
+ * is the operator's own scoped view, where the richer 409 + `missing` detail is safe.
42
+ */
14
43
  export declare function resolveSandboxImageRef(opts: {
15
44
  profile: string;
16
45
  capabilitiesNeeded?: readonly string[];
17
46
  viewer: ImageViewer;
18
47
  index: SandboxImageResolver;
19
48
  }): Promise<SandboxImageResolution>;
49
+ /**
50
+ * The trusted-control-plane bridge from `resolveSpec` (resolves the per-task image with the caller's principal) to
51
+ * the worker-global `ExecutionEnvFactory` (gets only core's minimal `{sessionId, taskId?}`). NOT a durable store
52
+ * and NOT a cache: `resolveSpec` REPOPULATES it on EVERY call — initial AND resume, on whichever replica runs
53
+ * resolveSpec immediately before the factory — so a cross-replica resume re-resolves LIVE (the resume re-admit
54
+ * discipline: a stale persisted digest can never bypass admission), and there is nothing durable to go stale.
55
+ *
56
+ * KEYED BY sessionId — the ONLY identifier stable across the factory `ctx` on every path (adversarial-review
57
+ * round-2): `/v1/runs` mints its OWN durable taskId that clobbers `spec.taskId`, so keying by taskId misses on the
58
+ * primary path; `sessionId` survives the spec spread on every path. `get()` is NON-removing (the factory may be
59
+ * invoked >once per logical task). Cleanup is by bounded eviction (oldest-first) — each entry is a tiny string; an
60
+ * evicted task is long finished.
61
+ *
62
+ * ⚠️ KNOWN narrow edge (same-principal correctness, NOT a security breach): two CONCURRENT requests for the SAME
63
+ * session (necessarily the same owner — session ownership is enforced) race `set()`; a request the run-claim later
64
+ * rejects (409) can leave its image bound for the active run. Both images are the same principal's own admitted
65
+ * images, so the worst case is the user's run using the user's OTHER selected image. The hardening
66
+ * (register-after-claim, keyed by the durable run id) needs the registry threaded into the server claim path —
67
+ * tracked as a follow-up. cascade/verify + a profile are rejected up front (they strip/replace the session).
68
+ */
20
69
  export declare class PerTaskImageRegistry {
21
70
  private readonly maxEntries;
22
71
  private readonly map;
23
72
  constructor(maxEntries?: number);
73
+ /** Register the resolved `repo@digest` for a session. A re-set (resume / a later same-session task) overwrites;
74
+ * on overflow the oldest insertion is evicted so an orphaned entry (a resolveSpec not followed by a factory
75
+ * call, e.g. a rejected/pre-exec-failed request) stays bounded. */
24
76
  set(sessionId: string, ref: string): void;
77
+ /** Read the ref for a session (NON-removing — the factory may be invoked more than once per logical task).
78
+ * `undefined` ⇒ no per-task image for this session ⇒ the factory uses its worker-global default image. */
25
79
  get(sessionId: string | undefined): string | undefined;
26
80
  }
27
81
  //# sourceMappingURL=per-task-image.d.ts.map
@@ -1,4 +1,19 @@
1
+ /** Boolean capability keys a caller may require. `nestedBuildMode` is a posture string, not a boolean gate, so it
2
+ * is intentionally NOT requestable here (capability admission is allow-on-true only). */
1
3
  const REQUESTABLE_CAPS = new Set(["browser", "db", "nestedBuild"]);
4
+ /**
5
+ * Resolve a requested sandbox image PROFILE to a pullable `repo@digest`, FAIL-CLOSED, re-admitting by `viewer`:
6
+ * - `latestPublished(profile, viewer)` applies the SAME `visibilityClause` + `status='published'` filter the
7
+ * select admission uses. Not visible / not published ⇒ `{ok:false, 404}` (never silent-allow).
8
+ * - each `capabilitiesNeeded` entry must be a known boolean capability AND true on the resolved image, else fail.
9
+ * Pure over the injected `index` ⇒ unit-testable with a fake resolver.
10
+ *
11
+ * NOTE (review LOW — error-code asymmetry, DELIBERATE): a not-visible / capability-miss here returns 404, whereas
12
+ * the operator-facing `POST /v1/images/select` returns 409 + `missing`. That is intentional: task admission is an
13
+ * UNTRUSTED-caller gate that must NOT distinguish "profile exists but you can't see it" from "doesn't exist"
14
+ * (revealing that leaks the existence of other tenants' images), so it collapses both to 404. The select catalog
15
+ * is the operator's own scoped view, where the richer 409 + `missing` detail is safe.
16
+ */
2
17
  export async function resolveSandboxImageRef(opts) {
3
18
  const entry = await opts.index.latestPublished(opts.profile, opts.viewer);
4
19
  if (!entry) {
@@ -13,14 +28,38 @@ export async function resolveSandboxImageRef(opts) {
13
28
  return { ok: false, status: 404, message: `sandbox image for profile "${opts.profile}" does not provide capability "${cap}"` };
14
29
  }
15
30
  }
31
+ // capabilities ride along for RFC A1 envFacts (the resolved entry is already in hand — no second query).
16
32
  return { ok: true, ref: `${entry.repo}@${entry.digest}`, capabilities: entry.capabilities };
17
33
  }
34
+ /**
35
+ * The trusted-control-plane bridge from `resolveSpec` (resolves the per-task image with the caller's principal) to
36
+ * the worker-global `ExecutionEnvFactory` (gets only core's minimal `{sessionId, taskId?}`). NOT a durable store
37
+ * and NOT a cache: `resolveSpec` REPOPULATES it on EVERY call — initial AND resume, on whichever replica runs
38
+ * resolveSpec immediately before the factory — so a cross-replica resume re-resolves LIVE (the resume re-admit
39
+ * discipline: a stale persisted digest can never bypass admission), and there is nothing durable to go stale.
40
+ *
41
+ * KEYED BY sessionId — the ONLY identifier stable across the factory `ctx` on every path (adversarial-review
42
+ * round-2): `/v1/runs` mints its OWN durable taskId that clobbers `spec.taskId`, so keying by taskId misses on the
43
+ * primary path; `sessionId` survives the spec spread on every path. `get()` is NON-removing (the factory may be
44
+ * invoked >once per logical task). Cleanup is by bounded eviction (oldest-first) — each entry is a tiny string; an
45
+ * evicted task is long finished.
46
+ *
47
+ * ⚠️ KNOWN narrow edge (same-principal correctness, NOT a security breach): two CONCURRENT requests for the SAME
48
+ * session (necessarily the same owner — session ownership is enforced) race `set()`; a request the run-claim later
49
+ * rejects (409) can leave its image bound for the active run. Both images are the same principal's own admitted
50
+ * images, so the worst case is the user's run using the user's OTHER selected image. The hardening
51
+ * (register-after-claim, keyed by the durable run id) needs the registry threaded into the server claim path —
52
+ * tracked as a follow-up. cascade/verify + a profile are rejected up front (they strip/replace the session).
53
+ */
18
54
  export class PerTaskImageRegistry {
19
55
  maxEntries;
20
56
  map = new Map();
21
57
  constructor(maxEntries = 4096) {
22
58
  this.maxEntries = maxEntries;
23
59
  }
60
+ /** Register the resolved `repo@digest` for a session. A re-set (resume / a later same-session task) overwrites;
61
+ * on overflow the oldest insertion is evicted so an orphaned entry (a resolveSpec not followed by a factory
62
+ * call, e.g. a rejected/pre-exec-failed request) stays bounded. */
24
63
  set(sessionId, ref) {
25
64
  this.map.delete(sessionId);
26
65
  this.map.set(sessionId, ref);
@@ -30,6 +69,8 @@ export class PerTaskImageRegistry {
30
69
  this.map.delete(oldest);
31
70
  }
32
71
  }
72
+ /** Read the ref for a session (NON-removing — the factory may be invoked more than once per logical task).
73
+ * `undefined` ⇒ no per-task image for this session ⇒ the factory uses its worker-global default image. */
33
74
  get(sessionId) {
34
75
  return sessionId === undefined ? undefined : this.map.get(sessionId);
35
76
  }
@@ -1,21 +1,56 @@
1
+ /**
2
+ * Plan-cache recurrence probe — INSTRUMENT-FIRST (search AI → service, 团队/给service-AI.md [1];
3
+ * core design/42). Zero-LLM, zero-dependency, pure in-memory.
4
+ *
5
+ * Measures the **per-scope recurrence rate of task objectives**: the unproven "省钱" premise behind a
6
+ * proposed core *plan-caching* feature (store a successful run's generalized plan → a similar new task
7
+ * retrieves it as a hint). The 2-juror review wanted real data before core builds the producer hook:
8
+ * does an agent's traffic actually re-pose near-duplicate objectives per tenant? (arXiv 2602.18922:
9
+ * heterogeneous queries can hit 0–12%.) We hold the real multi-tenant traffic, so this is ours to count.
10
+ *
11
+ * **The token criterion is copied verbatim from core `src/core/strategy-store.ts`** (`tokens()` /
12
+ * `significant()` / `find()` lines 46-52, 107-110) — otherwise we'd measure something other than what
13
+ * plan-cache retrieval would actually use. Note the **asymmetry**: a stored problem is matched on its
14
+ * full `tokens()` set, the query on its `significant()` set, and a hit = every significant query token
15
+ * is present in some stored problem (`significant(new) ⊆ tokens(historical)`).
16
+ *
17
+ * Fidelity choices (stated to search AI for confirmation): the history ring holds only **completed**
18
+ * tasks (plan-cache only stores plans from successful runs), while the hit test runs for **every**
19
+ * finished task; `qSig` length is bucketed so a hit can be told apart from a short-objective fluke
20
+ * (the juror's `qSig>=3` gate).
21
+ */
1
22
  import type { Metrics } from "./observability/metrics.js";
2
23
  import type { Logger } from "./observability/logger.js";
24
+ /** Lowercased word tokens (core口径). */
3
25
  export declare function tokens(s: string): string[];
26
+ /** Meaningful tokens: ≥3 chars, not a stopword (core口径). */
4
27
  export declare function significant(s: string): string[];
28
+ /** Per-scope view for the 2-week handoff back to search AI. */
5
29
  export interface ScopeRecurrence {
6
30
  tasks: number;
7
31
  hits: number;
8
32
  hitRate: number;
33
+ /** qSig-length histogram (index 0..QSIG_CAP; last bucket = QSIG_CAP+). */
9
34
  qsig: number[];
10
35
  }
11
36
  export declare const QSIG_CAP = 12;
37
+ /**
38
+ * In-memory recurrence tracker. One per process (single replica per worker in prod; cross-replica
39
+ * aggregation is unnecessary for a 2-week instrument — each instance reports its own slice).
40
+ */
12
41
  export declare class PlanCacheProbe {
13
42
  private readonly metrics?;
14
43
  private readonly logger?;
15
44
  private readonly byScope;
16
45
  constructor(metrics?: Metrics | undefined, logger?: Logger | undefined);
46
+ /**
47
+ * Record one finished task. `completed` = it succeeded (only those enter the history ring). Pure
48
+ * in-memory + a counter/histogram + a debug log line; never throws into the caller.
49
+ */
17
50
  record(scopeRaw: string | undefined, objective: string, completed: boolean): void;
51
+ /** Per-scope recurrence snapshot for the handoff (token-gated dump endpoint). */
18
52
  dump(): Record<string, ScopeRecurrence>;
53
+ /** LRU get-or-create: re-insert on access so the oldest-touched scope is evicted past the cap. */
19
54
  private touch;
20
55
  }
21
56
  //# sourceMappingURL=plan-cache-probe.d.ts.map
@@ -1,18 +1,25 @@
1
+ // Verbatim from core strategy-store.ts (keep in sync if core changes its stopword set).
1
2
  const STOP = new Set([
2
3
  "the", "and", "for", "with", "from", "this", "that", "into", "your", "you", "are", "was", "were", "has",
3
4
  "have", "had", "not", "but", "all", "any", "can", "use", "using", "via", "then", "than", "out", "get",
4
5
  "got", "its", "it's", "their", "them", "they", "what", "when", "which", "who", "how", "why", "a", "an",
5
6
  "of", "to", "in", "on", "is", "it", "or", "as", "at", "by", "be", "do", "if", "so", "no", "up", "we",
6
7
  ]);
8
+ /** Lowercased word tokens (core口径). */
7
9
  export function tokens(s) {
8
10
  return s.toLowerCase().match(/[a-z0-9]+/g) ?? [];
9
11
  }
12
+ /** Meaningful tokens: ≥3 chars, not a stopword (core口径). */
10
13
  export function significant(s) {
11
14
  return tokens(s).filter((t) => t.length >= 3 && !STOP.has(t));
12
15
  }
13
- const RING = 1000;
14
- const MAX_SCOPES = 2000;
15
- export const QSIG_CAP = 12;
16
+ const RING = 1000; // most-recent completed tasks per scope (= search AI's N=1000)
17
+ const MAX_SCOPES = 2000; // LRU cap on tracked scopes — bounds memory under high tenant cardinality
18
+ export const QSIG_CAP = 12; // qSig-length histogram cap (>=12 collapses into the last bucket)
19
+ /**
20
+ * In-memory recurrence tracker. One per process (single replica per worker in prod; cross-replica
21
+ * aggregation is unnecessary for a 2-week instrument — each instance reports its own slice).
22
+ */
16
23
  export class PlanCacheProbe {
17
24
  metrics;
18
25
  logger;
@@ -21,10 +28,16 @@ export class PlanCacheProbe {
21
28
  this.metrics = metrics;
22
29
  this.logger = logger;
23
30
  }
31
+ /**
32
+ * Record one finished task. `completed` = it succeeded (only those enter the history ring). Pure
33
+ * in-memory + a counter/histogram + a debug log line; never throws into the caller.
34
+ */
24
35
  record(scopeRaw, objective, completed) {
25
36
  const scope = scopeRaw && scopeRaw.length > 0 ? scopeRaw : "anon";
26
37
  const qSig = significant(objective);
27
38
  const st = this.touch(scope);
39
+ // Hit = some historical (completed) task's full token set ⊇ this task's significant tokens.
40
+ // qSig empty → never a hit (mirrors find()'s `qSig.length===0 → []`, no injection).
28
41
  let hit = false;
29
42
  if (qSig.length > 0) {
30
43
  for (const hist of st.ring) {
@@ -47,6 +60,7 @@ export class PlanCacheProbe {
47
60
  this.metrics?.observe("plan_cache_qsig", qSig.length);
48
61
  this.logger?.debug("plan-cache recurrence probe", { scope, qSig: qSig.length, hit, completed });
49
62
  }
63
+ /** Per-scope recurrence snapshot for the handoff (token-gated dump endpoint). */
50
64
  dump() {
51
65
  const out = {};
52
66
  for (const [scope, st] of this.byScope) {
@@ -59,6 +73,7 @@ export class PlanCacheProbe {
59
73
  }
60
74
  return out;
61
75
  }
76
+ /** LRU get-or-create: re-insert on access so the oldest-touched scope is evicted past the cap. */
62
77
  touch(scope) {
63
78
  let st = this.byScope.get(scope);
64
79
  if (st) {
@@ -6,10 +6,15 @@ export interface ApprovalExemptionRow {
6
6
  createdAt: number;
7
7
  }
8
8
  export interface ApprovalExemptionStore {
9
+ /** Record the exemption (idempotent upsert; a re-grant refreshes grantedBy, createdAt keeps the FIRST grant). */
9
10
  grant(sessionId: string, toolName: string, grantedBy: string | null): Promise<void>;
11
+ /** The ask-gate probe. Callers MUST fail-closed on a rejected promise (ask anyway). */
10
12
  has(sessionId: string, toolName: string): Promise<boolean>;
13
+ /** All exemptions for a session (the GET /v1/approvals UI surface). */
11
14
  list(sessionId: string): Promise<ApprovalExemptionRow[]>;
15
+ /** Revoke one exemption; false = nothing to revoke (idempotent). */
12
16
  revoke(sessionId: string, toolName: string): Promise<boolean>;
17
+ /** E21 — purge ALL exemptions for a session (session delete wiring). Idempotent (affected count). */
13
18
  deleteBySession(sessionId: string): Promise<number>;
14
19
  }
15
20
  export declare class TiDBApprovalExemptionStore implements ApprovalExemptionStore {
@@ -44,6 +49,7 @@ export declare class FileApprovalExemptionStore implements ApprovalExemptionStor
44
49
  private readonly logs;
45
50
  constructor(root: string);
46
51
  private pathFor;
52
+ /** Replay every session log (torn-tail-safe; last-wins with revoke tombstones). Index keyed by the SANITIZED id. */
47
53
  private hydrate;
48
54
  private logFor;
49
55
  grant(sessionId: string, toolName: string, grantedBy: string | null): Promise<void>;
@@ -51,6 +57,7 @@ export declare class FileApprovalExemptionStore implements ApprovalExemptionStor
51
57
  list(sessionId: string): Promise<ApprovalExemptionRow[]>;
52
58
  revoke(sessionId: string, toolName: string): Promise<boolean>;
53
59
  deleteBySession(sessionId: string): Promise<number>;
60
+ /** Release every open append-log fd (LocalBackend.close → graceful-restart re-open). */
54
61
  dispose(): void;
55
62
  }
56
63
  //# sourceMappingURL=approval-exemption-store.d.ts.map
@@ -1,6 +1,22 @@
1
+ /**
2
+ * Per-session per-toolName approval exemption ("本会话不再询问",
3
+ * design: docs/design/APPROVAL-SESSION-EXEMPTION.md).
4
+ *
5
+ * SEMANTICS (the boundary that keeps this an APPROVAL MEMORY, not a policy loosen): a granted row makes the
6
+ * F4 ask-gate SKIP the human ask for that (sessionId, canonicalToolName) — it is consulted ONLY after
7
+ * `APPROVAL_DENY` and `APPROVAL_NEVER_AUTO` (both always win), and never touches the session-policy layer
8
+ * (tighten-only stays intact). Keyed in CANONICAL tool-name space (the same rename-smuggling discipline as
9
+ * the require/deny sets). Lifecycle = session-bound: E21 session DELETE purges via deleteBySession.
10
+ *
11
+ * Four twins behind one interface (the resume-anchor pattern): TiDB/PG = durable cross-replica SQL rows
12
+ * (idempotent upsert on the (session_id, tool_name) PK); File = per-session JSONL append log (fsync — a
13
+ * lost grant re-asks, but a torn log must not FABRICATE one), hydrated on boot, torn-tail-safe; Memory =
14
+ * tests / ephemeral. Consumers treat store FAILURE as fail-closed (ask anyway) — enforced at the call site.
15
+ */
1
16
  import { join } from "node:path";
2
17
  import { existsSync, readdirSync, rmSync } from "node:fs";
3
18
  import { AppendLog, ensureDir, readJsonlRecords, sanitizePathComponent } from "@sema-agent/core";
19
+ // ─── TiDB / MySQL twin ───────────────────────────────────────────────────────────────────────────────────
4
20
  export class TiDBApprovalExemptionStore {
5
21
  pool;
6
22
  constructor(pool) {
@@ -8,7 +24,8 @@ export class TiDBApprovalExemptionStore {
8
24
  }
9
25
  async grant(sessionId, toolName, grantedBy) {
10
26
  await this.pool.query("INSERT INTO approval_exemption (session_id, tool_name, granted_by, created_at) VALUES (?,?,?,?) " +
11
- "ON DUPLICATE KEY UPDATE granted_by = VALUES(granted_by)", [sessionId, toolName, grantedBy, new Date()]);
27
+ "ON DUPLICATE KEY UPDATE granted_by = VALUES(granted_by)", // created_at keeps the first grant
28
+ [sessionId, toolName, grantedBy, new Date()]);
12
29
  }
13
30
  async has(sessionId, toolName) {
14
31
  const [rows] = await this.pool.query("SELECT 1 FROM approval_exemption WHERE session_id = ? AND tool_name = ?", [sessionId, toolName]);
@@ -31,6 +48,7 @@ export class TiDBApprovalExemptionStore {
31
48
  return r.affectedRows;
32
49
  }
33
50
  }
51
+ // ─── PG twin (dialect twin of the TiDB store — same contract, $n placeholders + ON CONFLICT) ─────────────
34
52
  export class PgApprovalExemptionStore {
35
53
  pool;
36
54
  constructor(pool) {
@@ -67,6 +85,7 @@ export class PgApprovalExemptionStore {
67
85
  return res.rowCount ?? 0;
68
86
  }
69
87
  }
88
+ // ─── Memory twin (tests / ephemeral) ─────────────────────────────────────────────────────────────────────
70
89
  export class MemoryApprovalExemptionStore {
71
90
  bySession = new Map();
72
91
  async grant(sessionId, toolName, grantedBy) {
@@ -110,6 +129,7 @@ export class FileApprovalExemptionStore {
110
129
  pathFor(sessionId) {
111
130
  return join(this.dir, `${sanitizePathComponent(sessionId)}.jsonl`);
112
131
  }
132
+ /** Replay every session log (torn-tail-safe; last-wins with revoke tombstones). Index keyed by the SANITIZED id. */
113
133
  hydrate() {
114
134
  let names;
115
135
  try {
@@ -191,9 +211,13 @@ export class FileApprovalExemptionStore {
191
211
  log.close();
192
212
  this.logs.delete(key);
193
213
  }
214
+ // 🔴 unlink BEFORE dropping the index, and FAIL LOUD if the file survives: a
215
+ // swallowed rm would let hydrate() resurrect purged exemptions after a restart — an E21 right-to-delete
216
+ // violation with PRIVILEGE attached (auto-approve rights), unlike the inert anchor-store twin. Throwing
217
+ // here aborts the caller's session purge before it deletes the session metadata (fail-loud, retryable).
194
218
  const path = this.pathFor(sessionId);
195
219
  try {
196
- rmSync(path, { force: true });
220
+ rmSync(path, { force: true }); // force: missing file is fine (idempotent delete)
197
221
  }
198
222
  catch (e) {
199
223
  if (existsSync(path))
@@ -202,12 +226,14 @@ export class FileApprovalExemptionStore {
202
226
  this.bySession.delete(key);
203
227
  return removed;
204
228
  }
229
+ /** Release every open append-log fd (LocalBackend.close → graceful-restart re-open). */
205
230
  dispose() {
206
231
  for (const log of this.logs.values()) {
207
232
  try {
208
233
  log.close();
209
234
  }
210
235
  catch {
236
+ /* best-effort */
211
237
  }
212
238
  }
213
239
  this.logs.clear();