@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,3 +1,31 @@
1
+ /**
2
+ * Entitlements resolver — the SERVICE-side wiring of core 1.157's `RunnerDeps.runtimeCapsResolver` (design/99 §K).
3
+ * (design/158 N11: this module's own exports were renamed `*Caps*` → `*Entitlements*` to stop sharing a word
4
+ * root with the UNRELATED `capabilities` face (deployment route discovery, `src/capabilities/`) and
5
+ * `ScenarioBundle` assembly — "caps" meant three different things across those three faces. `RuntimeCaps` /
6
+ * `EntitlementRuntimeCaps` themselves stay as-is below: they are core's / registry-core's own contract type
7
+ * names, not ours to rename.)
8
+ * It is the ENFORCE last-link of the three-stage workflows gate
9
+ * (engine-can ∧ center-may ∧ shell-show): core calls it ONCE per task at prepare time with `spec.principal`,
10
+ * and the engine enforces the two caps it CAN enforce — `allowWorkflows` (deny self-orchestration) and
11
+ * `forceDurableGate` (force a policy `ask` onto the durable-approval wire).
12
+ *
13
+ * It pulls the PER-PRINCIPAL entitlement from center's `GET /api/config/effective?principal=` (via
14
+ * {@link fetchPrincipalCaps}). center has ALREADY pre-resolved the tighten-only intersection (fleet defaults ∩
15
+ * tier ⊕ roles + time-bounded overrides); the service passes the resolved value through VERBATIM (per center
16
+ * ruling: "service 只透传 resolved 值、无需再 tighten"). The resolver adds only the data-plane concerns center can't:
17
+ * a per-principal TTL+ETag CACHE (so per-task prepare-time lookups don't hammer center) and FAIL-CLOSED degrade.
18
+ *
19
+ * 🔐 FAIL-CLOSED (core security mandate, prepare-task.ts): an entitlement-resolver outage must NEVER silently
20
+ * GRANT a capability center may have denied. On a hard fetch error we return `{ allowWorkflows: false }` (deny the
21
+ * OPTIONAL workflows privilege) and do NOT force the durable gate (that could strand an autonomous run on an
22
+ * absent operator — the same minimal degrade core applies when the resolver throws). We never serve a STALE
23
+ * cached GRANT past its TTL on a fresh-fetch failure (a revoked cap must not linger because center blipped).
24
+ *
25
+ * The resolver maps center's `EntitlementRuntimeCaps` → the SUBSET core enforces ({@link RuntimeCaps}): center
26
+ * also carries `allowUltracode` (a shell/UX reasoning-tier cap the engine has no primitive for), which we DROP —
27
+ * this seam feeds the ENGINE, and `allowUltracode` is enforced at the service settings-resolution layer, not here.
28
+ */
1
29
  import type { RuntimeCaps } from "@sema-agent/core";
2
30
  import type { EntitlementRuntimeCaps } from "@sema-agent/registry-core";
3
31
  import { fetchPrincipalCaps, type ExecutionRuling } from "./sema-registry.js";
@@ -5,25 +33,103 @@ import type { ScenarioRuling } from "./capabilities/scenarios.js";
5
33
  export interface EntitlementsResolverOpts {
6
34
  baseUrl: string;
7
35
  token: string;
36
+ /** This worker's name (`SEMA_REGISTRY_WORKER`), passed as `?worker=` so a worker-scoped `wpt_<self>` token can
37
+ * resolve its OWN worker's principal caps (caps-only); harmless on a full token (the caps value
38
+ * is worker-independent). Omitted ⇒ no `?worker=` (a full-token, non-fleet deployment). */
8
39
  worker?: string;
40
+ /** Per-principal cache TTL (ms). A resolved entitlement is reused for this long before an ETag-conditional
41
+ * re-pull, collapsing per-task prepare-time lookups to ~1 center call/principal/TTL. Default 60s. */
9
42
  ttlMs?: number;
43
+ /** Short window (ms) a FAIL-CLOSED deny is cached to avoid hammering center (8s timeout each) on a sustained
44
+ * outage, without pinning a deny long past a transient blip. Default min(ttlMs, 10s). */
10
45
  denyTtlMs?: number;
46
+ /** Injected for tests. */
11
47
  fetchImpl?: typeof fetch;
12
48
  fetchCaps?: typeof fetchPrincipalCaps;
13
49
  now?: () => number;
50
+ /** Observability hook for a resolve failure (defaults to a `runtime_caps_resolve_failed` warn). */
14
51
  onError?: (err: Error, principal: string) => void;
15
52
  }
53
+ /** Map center's `EntitlementRuntimeCaps` → the subset core's engine enforces. `allowUltracode` (shell/UX) is
54
+ * dropped on purpose (not a core primitive); `allowWorkflows` / `forceDurableGate` / `allowFork` are the three the
55
+ * engine enforces. Returns undefined when no enforceable cap is set (= no restriction). FAIL-CLOSED defense-in-depth:
56
+ * do NOT trust the wire to be boolean. center serializes these as zod-validated booleans, but a schema drift / proxy
57
+ * mangling that sent a TRUTHY non-boolean (e.g. the STRING "false") would slip past core's strict `=== false` deny
58
+ * check and silently GRANT. So a cap that is PRESENT but not a real boolean is a contract breach → THROW (the
59
+ * resolver's catch then fail-closes to deny). `allowFork` (registry-core 0.1.47): the per-principal Fork
60
+ * ceiling — core mounts Fork only when `runtimeCaps.allowFork !== false` (prepare-task), tighten-only like allowWorkflows.
61
+ *
62
+ * `allowObservers`(observer 开闸线,core 1.270.0/1.273.0):**极性与 allow* 相反** —
63
+ * core 是 `=== true` 显式 opt-in(默认 OFF,undefined ships dark)。registry-core 0.10.3 起该键已收编进
64
+ * `EntitlementRuntimeCaps` 类型(此前 0.10.2 走 unknown 宽读透传,现为类型直读,行为零变)。
65
+ * **缺键=不写键**(绝不把缺键补成显式 false —— core 是唯一默认源,补 false 语义上等价但会伪造「center
66
+ * 说过话」的显式判决,污染 env-baseline 合成序,见 applyObserverEnvOptIn)。非 boolean 虽然骗不过 core
67
+ * 的 `=== true`(不会误 GRANT),但 PRESENT-非-boolean 与 allow* 同属同一 body 的契约破损信号 → 同款 THROW。
68
+ *
69
+ * `autoMode`(core 1.276.0 `RuntimeCaps.autoMode`):auto-mode 分类器 per-principal
70
+ * 开闸线,极性同 allowObservers(`=== true` 显式 opt-in,默认 OFF;真执行还要 deployment 装配
71
+ * `RunnerDeps.autoMode` 分类器面=信任门,center 键只是 entitlement 半场)。registry-core 类型未收编
72
+ * → unknown 宽读透传(allowObservers 0.10.2 期同款先例);center 发键即活。 */
16
73
  export declare function toCoreRuntimeCaps(ent: EntitlementRuntimeCaps | null | undefined): RuntimeCaps | undefined;
74
+ /** A MISCONFIG diagnostic (review MEDIUM): a worker-scoped `wpt_<self>` pull token REQUIRES `?worker=<self>` to
75
+ * resolve per-principal caps — so a `wpt_` token with NO `SEMA_REGISTRY_WORKER` set will 403
76
+ * on every caps fetch → fail-closed DENY ALL workflows for ALL principals (correct degrade, but otherwise silent
77
+ * bar per-task warns). True ⇒ the caller should log a one-shot BOOT warning so the misconfig is diagnosable.
78
+ * (The orchestrator normally injects SEMA_REGISTRY_WORKER alongside a wpt_ token, so this is a hand-misconfig.) */
17
79
  export declare function scopedTokenNeedsWorker(token: string, worker: string | undefined): boolean;
80
+ /** The two per-principal faces served off ONE caps fetch + cache. */
18
81
  export interface PrincipalEntitlementsClient {
82
+ /** core's `RunnerDeps.runtimeCapsResolver` seam — FAIL-CLOSED on error (deny workflows/fork). */
19
83
  resolveRuntimeCaps: (principal: string | undefined) => Promise<RuntimeCaps | undefined>;
84
+ /** The resolved per-principal scenario ruling for resolveSpec's gateScenarioRequest —
85
+ * FAIL-OPEN on error / older center without scenario keys / no principal (undefined = no governance, legacy passthrough).
86
+ * Scenario switching is not a privilege-amplifying face; a center blip must not pin users to `default`. */
20
87
  scenarioRuling: (principal: string | undefined) => Promise<ScenarioRuling | undefined>;
88
+ /** (stage7 P5) The resolved per-principal execution-lane ruling for resolveSpec's
89
+ * gateExecutionLane. FAIL-OPEN + audit on error (this phase is "honest-but-bypassable";
90
+ * tightening to fail-closed is a future, separate decision) / older center without the execution key / no principal. */
21
91
  executionRuling: (principal: string | undefined) => Promise<ExecutionRuling | undefined>;
22
92
  }
93
+ /**
94
+ * Task-admission enforcement of the per-principal execution policy(stage7 P5 的「真强制」
95
+ * service 半场——壳侧锁定是易用性强制可绕,这里是引擎闸)。The lane is a WORKER-PROCESS identity
96
+ * (REMOTE_EXEC is boot wiring; there is no per-task lane switch), so the gate is "this worker's lane is not
97
+ * permitted for this principal ⇒ reject the task": typed 403 `execution_lane_not_allowed` carrying the
98
+ * allowlist + this worker's lane (machine code on the wire, prose stays with the shell/web).
99
+ * No ruling / required=false / caps blip ⇒ pass (fail-open + audit). `allowedLanes` is an
100
+ * OPEN domain — unknown names simply never match this worker's lane.
101
+ */
23
102
  export declare function gateExecutionLane(ruling: ExecutionRuling | undefined, ownLane: string): void;
103
+ /**
104
+ * Build the per-principal caps client: `resolveRuntimeCaps` matches core's seam signature
105
+ * `(principal) => Promise<RuntimeCaps | undefined>`; `scenarioRuling` rides the SAME fetch/cache/in-flight
106
+ * (zero extra center RTT — center attaches the ruling to the caps body). Wire ONLY when a center is
107
+ * configured (and not in dry-run) — absent ⇒ core sees `undefined` ⇒ NO per-principal restriction, and the
108
+ * scenario gate sees `undefined` ⇒ legacy body-or-default chain.
109
+ */
24
110
  export declare function createPrincipalEntitlementsClient(opts: EntitlementsResolverOpts): PrincipalEntitlementsClient;
111
+ /** Back-compat face for core's seam-only consumers: the caps half of {@link createPrincipalEntitlementsClient}. */
25
112
  export declare function createEntitlementsResolver(opts: EntitlementsResolverOpts): (principal: string | undefined) => Promise<RuntimeCaps | undefined>;
113
+ /** core's `RunnerDeps.runtimeCapsResolver` seam signature (types.d.ts): sync or async, undefined = no caps. */
26
114
  export type EntitlementsResolverFn = (principal: string | undefined) => RuntimeCaps | undefined | Promise<RuntimeCaps | undefined>;
115
+ /**
116
+ * observer 开闸线的 env 半场:`EXPERIMENTAL_OBSERVER_AGENTS=true` 时把
117
+ * `RuntimeCaps.allowObservers: true` 作为**部署基线**合成进 caps resolver(core 1.270.0/1.273.0 的
118
+ * observer 面是 `=== true` 显式 opt-in、默认 OFF —— 命名先例=CC 的 `CLAUDE_CODE_EXPERIMENTAL_OBSERVER_AGENTS`
119
+ * env 对儿)。租户姿势(与 FORK_ENABLED/SELF_ORCHESTRATION 同款判别):
120
+ * - **单用户部署**(`requirePrincipal !== true`,operator 即用户):env=true 直开 —— 无 center 时静态
121
+ * `{allowObservers:true}`;有 center 时作 BASELINE,**center caps 带键则 center 赢**(含显式 false;
122
+ * 缺键=center 没说话 → env 基线生效。这依赖 toCoreRuntimeCaps 缺键不补 false 的纪律 —— core 是唯一
123
+ * 默认源,center 只有真说了话才覆盖)。fail-closed 错误 entry(deny)不带 allowObservers 键 → 单用户
124
+ * env 基线在 center blip 期间维持(operator 在自己盒子上显式 opt-in 过;observers 非 workflows/fork
125
+ * 级的放大面,且 deny entry 的两把闸不受影响)。
126
+ * - **多租户**(`requirePrincipal === true`):env **不认**,只认 center caps(半配置 fail-loud:置了
127
+ * env 却多租户 → 一次 boot warn,行为零变——与 MEMORY_ENGINE_BACKEND 半配置同款姿势)。
128
+ * 返回合成后的 resolver;两边都无源(无 center、env 无效)⇒ undefined(RunnerDeps 不接线,零行为差)。
129
+ * ⚠️ 调用方注意:`Boolean(centerResolver)` 才是「entitlement resolver wired」语义(enableForkFromBody /
130
+ * selfOrchestrationFromBody 的多租户 fail-close 判别),不要改用本函数的返回值判 —— env-only lane 不是
131
+ * center 背书的 entitlement 源。
132
+ */
27
133
  export declare function applyObserverEnvOptIn(centerResolver: EntitlementsResolverFn | undefined, opts: {
28
134
  experimentalObserverAgents: boolean;
29
135
  requirePrincipal: boolean;
@@ -2,9 +2,30 @@ import { fetchPrincipalCaps } from "./sema-registry.js";
2
2
  import { HttpError } from "./security.js";
3
3
  import { createLogger } from "./observability/logger.js";
4
4
  const defaultLogger = createLogger();
5
+ /** Map center's `EntitlementRuntimeCaps` → the subset core's engine enforces. `allowUltracode` (shell/UX) is
6
+ * dropped on purpose (not a core primitive); `allowWorkflows` / `forceDurableGate` / `allowFork` are the three the
7
+ * engine enforces. Returns undefined when no enforceable cap is set (= no restriction). FAIL-CLOSED defense-in-depth:
8
+ * do NOT trust the wire to be boolean. center serializes these as zod-validated booleans, but a schema drift / proxy
9
+ * mangling that sent a TRUTHY non-boolean (e.g. the STRING "false") would slip past core's strict `=== false` deny
10
+ * check and silently GRANT. So a cap that is PRESENT but not a real boolean is a contract breach → THROW (the
11
+ * resolver's catch then fail-closes to deny). `allowFork` (registry-core 0.1.47): the per-principal Fork
12
+ * ceiling — core mounts Fork only when `runtimeCaps.allowFork !== false` (prepare-task), tighten-only like allowWorkflows.
13
+ *
14
+ * `allowObservers`(observer 开闸线,core 1.270.0/1.273.0):**极性与 allow* 相反** —
15
+ * core 是 `=== true` 显式 opt-in(默认 OFF,undefined ships dark)。registry-core 0.10.3 起该键已收编进
16
+ * `EntitlementRuntimeCaps` 类型(此前 0.10.2 走 unknown 宽读透传,现为类型直读,行为零变)。
17
+ * **缺键=不写键**(绝不把缺键补成显式 false —— core 是唯一默认源,补 false 语义上等价但会伪造「center
18
+ * 说过话」的显式判决,污染 env-baseline 合成序,见 applyObserverEnvOptIn)。非 boolean 虽然骗不过 core
19
+ * 的 `=== true`(不会误 GRANT),但 PRESENT-非-boolean 与 allow* 同属同一 body 的契约破损信号 → 同款 THROW。
20
+ *
21
+ * `autoMode`(core 1.276.0 `RuntimeCaps.autoMode`):auto-mode 分类器 per-principal
22
+ * 开闸线,极性同 allowObservers(`=== true` 显式 opt-in,默认 OFF;真执行还要 deployment 装配
23
+ * `RunnerDeps.autoMode` 分类器面=信任门,center 键只是 entitlement 半场)。registry-core 类型未收编
24
+ * → unknown 宽读透传(allowObservers 0.10.2 期同款先例);center 发键即活。 */
5
25
  export function toCoreRuntimeCaps(ent) {
6
26
  if (!ent)
7
27
  return undefined;
28
+ // 宽读(additive wide-read):registry-core 0.10.3 类型未含 autoMode,center 下发先行时走 unknown 读。
8
29
  const autoMode = ent.autoMode;
9
30
  const badCap = (v) => v !== undefined && typeof v !== "boolean";
10
31
  if (badCap(ent.allowWorkflows) || badCap(ent.forceDurableGate) || badCap(ent.allowFork) || badCap(ent.allowObservers) || badCap(autoMode)) {
@@ -23,9 +44,23 @@ export function toCoreRuntimeCaps(ent) {
23
44
  caps.autoMode = autoMode;
24
45
  return Object.keys(caps).length ? caps : undefined;
25
46
  }
47
+ /** A MISCONFIG diagnostic (review MEDIUM): a worker-scoped `wpt_<self>` pull token REQUIRES `?worker=<self>` to
48
+ * resolve per-principal caps — so a `wpt_` token with NO `SEMA_REGISTRY_WORKER` set will 403
49
+ * on every caps fetch → fail-closed DENY ALL workflows for ALL principals (correct degrade, but otherwise silent
50
+ * bar per-task warns). True ⇒ the caller should log a one-shot BOOT warning so the misconfig is diagnosable.
51
+ * (The orchestrator normally injects SEMA_REGISTRY_WORKER alongside a wpt_ token, so this is a hand-misconfig.) */
26
52
  export function scopedTokenNeedsWorker(token, worker) {
27
53
  return token.startsWith("wpt_") && !worker;
28
54
  }
55
+ /**
56
+ * Task-admission enforcement of the per-principal execution policy(stage7 P5 的「真强制」
57
+ * service 半场——壳侧锁定是易用性强制可绕,这里是引擎闸)。The lane is a WORKER-PROCESS identity
58
+ * (REMOTE_EXEC is boot wiring; there is no per-task lane switch), so the gate is "this worker's lane is not
59
+ * permitted for this principal ⇒ reject the task": typed 403 `execution_lane_not_allowed` carrying the
60
+ * allowlist + this worker's lane (machine code on the wire, prose stays with the shell/web).
61
+ * No ruling / required=false / caps blip ⇒ pass (fail-open + audit). `allowedLanes` is an
62
+ * OPEN domain — unknown names simply never match this worker's lane.
63
+ */
29
64
  export function gateExecutionLane(ruling, ownLane) {
30
65
  if (!ruling?.required)
31
66
  return;
@@ -36,6 +71,13 @@ export function gateExecutionLane(ruling, ownLane) {
36
71
  });
37
72
  }
38
73
  }
74
+ /**
75
+ * Build the per-principal caps client: `resolveRuntimeCaps` matches core's seam signature
76
+ * `(principal) => Promise<RuntimeCaps | undefined>`; `scenarioRuling` rides the SAME fetch/cache/in-flight
77
+ * (zero extra center RTT — center attaches the ruling to the caps body). Wire ONLY when a center is
78
+ * configured (and not in dry-run) — absent ⇒ core sees `undefined` ⇒ NO per-principal restriction, and the
79
+ * scenario gate sees `undefined` ⇒ legacy body-or-default chain.
80
+ */
39
81
  export function createPrincipalEntitlementsClient(opts) {
40
82
  const ttlMs = opts.ttlMs ?? 60_000;
41
83
  const denyTtlMs = opts.denyTtlMs ?? Math.min(ttlMs, 10_000);
@@ -45,6 +87,9 @@ export function createPrincipalEntitlementsClient(opts) {
45
87
  const onError = opts.onError ?? ((err, principal) => defaultLogger.warn("runtime_caps_resolve_failed", { principal, err: String(err) }));
46
88
  const cache = new Map();
47
89
  const inflight = new Map();
90
+ // Bound cache growth (review L1-1): `principal` is a per-user identity, so a long-lived worker — or a direct-door
91
+ // caller spoofing many principals — would accumulate one entry forever. On write, when the map crosses a soft cap,
92
+ // sweep logically-expired entries (TTL is a freshness gate, not eviction). Caps retention to ~the active set.
48
93
  const MAX_CACHE = 10_000;
49
94
  const putCache = (key, entry) => {
50
95
  if (cache.size >= MAX_CACHE) {
@@ -55,17 +100,25 @@ export function createPrincipalEntitlementsClient(opts) {
55
100
  }
56
101
  cache.set(key, entry);
57
102
  };
103
+ // ONE loader behind both faces: fresh-cached entry → as-is; else fetch (in-flight-deduped) → cache → entry.
58
104
  async function load(principal) {
59
105
  const cached = cache.get(principal);
60
106
  if (cached && cached.expiresAt > now())
61
107
  return cached;
108
+ // Collapse concurrent prepare-time lookups for the SAME principal onto one in-flight fetch.
62
109
  const dup = inflight.get(principal);
63
110
  if (dup)
64
111
  return dup;
65
112
  const p = (async () => {
66
113
  try {
114
+ // `cached?.etag` is set only on a real prior entry (an error entry clears it) → an `if-none-match` here can
115
+ // only 304-confirm a REAL value, never resurrect a stale deny. Pass `opts.worker` as `?worker=<self>` so a
116
+ // worker-scoped `wpt_<self>` token can resolve its OWN worker's principal caps; harmless
117
+ // on a full token (caps are worker-independent — the worker only scopes the config view we ignore).
67
118
  const r = await fetchCaps(opts.baseUrl, opts.token, principal, cached?.etag, fetchImpl, opts.worker);
68
119
  if (r === null) {
120
+ // 304 — unchanged. We only sent if-none-match because `cached` was a real entry → reuse caps AND the
121
+ // rulings (same body, same generation), refresh TTL.
69
122
  const entry = {
70
123
  caps: cached?.caps,
71
124
  ...(cached?.scenario ? { scenario: cached.scenario } : {}),
@@ -76,11 +129,14 @@ export function createPrincipalEntitlementsClient(opts) {
76
129
  putCache(principal, entry);
77
130
  return entry;
78
131
  }
132
+ // execution ruling shape drift = ruling dropped (fail-open) + THIS audit
133
+ // line — the "fail-open + audit" posture now covers the wire-drift direction too (previously a
134
+ // drifted allowedLanes coerced to [] = silent fleet-wide deny-all). Routed through onError (never throws).
79
135
  if (r.executionDrift) {
80
136
  try {
81
137
  onError(new Error(`execution ruling wire drift: ${r.executionDrift}`), principal);
82
138
  }
83
- catch { }
139
+ catch { /* observability never breaks the resolver */ }
84
140
  }
85
141
  const entry = {
86
142
  caps: toCoreRuntimeCaps(r.runtimeCaps),
@@ -94,12 +150,18 @@ export function createPrincipalEntitlementsClient(opts) {
94
150
  }
95
151
  catch (err) {
96
152
  const e = err instanceof Error ? err : new Error(String(err));
153
+ // Caps face FAIL CLOSED: deny the OPTIONAL amplification caps (workflows + fork); never force the durable
154
+ // gate on error. Scenario face FAIL OPEN: `scenario` stays undefined (no governance — never pin users to
155
+ // the default scenario on a center blip; deliberate posture split, see PrincipalEntitlementsClient). Cache the
156
+ // deny for a SHORT window (bound center hammering on a sustained outage) WITHOUT an etag — so the next
157
+ // fetch is a full 200 pull that re-reads the real caps the moment center recovers (a 304 can't resurrect
158
+ // this deny). Write the deny BEFORE onError so a throwing observability hook can't escape before recording.
97
159
  const entry = { caps: { allowWorkflows: false, allowFork: false }, expiresAt: now() + denyTtlMs };
98
160
  putCache(principal, entry);
99
161
  try {
100
162
  onError(e, principal);
101
163
  }
102
- catch { }
164
+ catch { /* an observability hook must never break the resolver */ }
103
165
  return entry;
104
166
  }
105
167
  finally {
@@ -110,25 +172,48 @@ export function createPrincipalEntitlementsClient(opts) {
110
172
  return p;
111
173
  }
112
174
  return {
175
+ // No principal = an anonymous/system run with no per-principal identity → no per-principal restriction
176
+ // (tighten-only: absence falls back to the deployment-level default; core treats undefined as "no caps").
113
177
  resolveRuntimeCaps: async (principal) => (principal ? (await load(principal)).caps : undefined),
114
178
  scenarioRuling: async (principal) => (principal ? (await load(principal)).scenario : undefined),
115
179
  executionRuling: async (principal) => (principal ? (await load(principal)).execution : undefined),
116
180
  };
117
181
  }
182
+ /** Back-compat face for core's seam-only consumers: the caps half of {@link createPrincipalEntitlementsClient}. */
118
183
  export function createEntitlementsResolver(opts) {
119
184
  return createPrincipalEntitlementsClient(opts).resolveRuntimeCaps;
120
185
  }
186
+ /**
187
+ * observer 开闸线的 env 半场:`EXPERIMENTAL_OBSERVER_AGENTS=true` 时把
188
+ * `RuntimeCaps.allowObservers: true` 作为**部署基线**合成进 caps resolver(core 1.270.0/1.273.0 的
189
+ * observer 面是 `=== true` 显式 opt-in、默认 OFF —— 命名先例=CC 的 `CLAUDE_CODE_EXPERIMENTAL_OBSERVER_AGENTS`
190
+ * env 对儿)。租户姿势(与 FORK_ENABLED/SELF_ORCHESTRATION 同款判别):
191
+ * - **单用户部署**(`requirePrincipal !== true`,operator 即用户):env=true 直开 —— 无 center 时静态
192
+ * `{allowObservers:true}`;有 center 时作 BASELINE,**center caps 带键则 center 赢**(含显式 false;
193
+ * 缺键=center 没说话 → env 基线生效。这依赖 toCoreRuntimeCaps 缺键不补 false 的纪律 —— core 是唯一
194
+ * 默认源,center 只有真说了话才覆盖)。fail-closed 错误 entry(deny)不带 allowObservers 键 → 单用户
195
+ * env 基线在 center blip 期间维持(operator 在自己盒子上显式 opt-in 过;observers 非 workflows/fork
196
+ * 级的放大面,且 deny entry 的两把闸不受影响)。
197
+ * - **多租户**(`requirePrincipal === true`):env **不认**,只认 center caps(半配置 fail-loud:置了
198
+ * env 却多租户 → 一次 boot warn,行为零变——与 MEMORY_ENGINE_BACKEND 半配置同款姿势)。
199
+ * 返回合成后的 resolver;两边都无源(无 center、env 无效)⇒ undefined(RunnerDeps 不接线,零行为差)。
200
+ * ⚠️ 调用方注意:`Boolean(centerResolver)` 才是「entitlement resolver wired」语义(enableForkFromBody /
201
+ * selfOrchestrationFromBody 的多租户 fail-close 判别),不要改用本函数的返回值判 —— env-only lane 不是
202
+ * center 背书的 entitlement 源。
203
+ */
121
204
  export function applyObserverEnvOptIn(centerResolver, opts) {
122
205
  if (!opts.experimentalObserverAgents)
123
- return centerResolver;
206
+ return centerResolver; // env 未置 = 纯透传(多数部署路径,零成本)
124
207
  if (opts.requirePrincipal) {
208
+ // 多租户不认 env(observer 是 per-principal 治理面,只认 center caps)——半配置 fail-loud 一次。
125
209
  opts.warn?.("observer_env_opt_in_ignored", {
126
210
  reason: "EXPERIMENTAL_OBSERVER_AGENTS=true is single-user only; a multi-tenant deployment (REQUIRE_PRINCIPAL=true) honors ONLY center caps allowObservers — env ignored, behavior unchanged",
127
211
  });
128
212
  return centerResolver;
129
213
  }
130
214
  if (!centerResolver)
131
- return () => ({ allowObservers: true });
215
+ return () => ({ allowObservers: true }); // 单用户无 center:env 即静态开闸
216
+ // 单用户 + center:env 作 baseline,center 带键(true/false 皆)覆盖;缺键 → baseline 生效。
132
217
  return async (principal) => ({ allowObservers: true, ...(await centerResolver(principal)) });
133
218
  }
134
219
  //# sourceMappingURL=runtime-caps-resolver.js.map
@@ -1,17 +1,101 @@
1
+ /**
2
+ * Runtime governance compiler — the "second baton" (center §10, core 1.114.0): turn the
3
+ * operator's declarative `runtime.autonomy` + `runtime.commandPolicy` (`@sema-agent/registry-core`,
4
+ * carried to the service via sema-registry `EffectiveConfig.runtime`) into TIGHTEN-ONLY overrides on the
5
+ * per-task `TaskSpec`. Pure so it is unit-testable in isolation (the spec is otherwise assembled inside
6
+ * main.ts's `resolveSpec`).
7
+ *
8
+ * 🪤 TWO TRAPS this module exists to NOT fall into (see core
9
+ * `tool-policy.ts` / `tighten-task-spec.ts` JSDoc):
10
+ *
11
+ * TRAP #1 — `TaskSpec.toolPolicy` OVERRIDES (not merges) `RunnerDeps.toolPolicy` (the runner does
12
+ * `spec.toolPolicy ?? deps.toolPolicy`). A bare `spec.toolPolicy = createCoarseCommandNamePolicy(…)` would
13
+ * SILENTLY DISCARD the deployment's approval/durable baseline. We compose via {@link tightenTaskSpec}, whose
14
+ * toolPolicy rule is `combinePolicies(base, override)` (deny-wins) — the command gate can only ADD denies/asks
15
+ * on top of the baseline, never clear it.
16
+ *
17
+ * TRAP #2 — `autonomy` must EXPAND INTO the three core primitives (`handsReadOnly` / `shellGate` / a
18
+ * `toolPolicy`), NOT become a parallel enum on the spec (design-research §10: a parallel `autonomy` field +
19
+ * `handsReadOnly:true` would conflict). The expansion is tighten-only and routed through `tightenTaskSpec`, so
20
+ * `auto` (the loosest mode) can never LOOSEN a stricter base — `tightenTaskSpec` THROWS instead.
21
+ *
22
+ * ⚠️ `commandPolicy` is a COARSE name-level filter, NOT a sandbox. `sh -c …` / `$(…)` / pipes / `env X=…` /
23
+ * path-prefixed commands all bypass the argv[0] match (they route to `ask`, fail-closed, but are not blocked by
24
+ * name). Real isolation is the `executionEnv` sandbox. Same caveat core documents on `createCoarseCommandNamePolicy`.
25
+ */
1
26
  import { type TaskSpec, type ToolPolicy } from "@sema-agent/core";
27
+ /** A per-command governance rule (registry `runtime.commandPolicy[]`). */
2
28
  export type CommandRule = {
3
29
  command: string;
4
30
  decision: "allow" | "ask" | "deny";
5
31
  };
32
+ /** True when `name` names a DELEGATION tool — the subagent tool (CC-187 canonical `"Agent"`, core 1.202
33
+ * `DEFAULT_SUBAGENT_TOOL_NAME`; legacy alias `"Task"`). CANONICAL-space compare (`canonicalToolName`) so both
34
+ * spellings match — the pre-1.202 raw `!== "Task"` compare in the read-only strip (main.ts) silently stopped
35
+ * matching when core renamed the tool (fail-open: a plan-mode / hands-read-only parent could delegate to a
36
+ * WRITABLE-hands child, because core does not propagate handsReadOnly to a delegated child).
37
+ * core 1.257 (design/136 BREAKING): the standalone `Fork` tool is retired — a fork is now
38
+ * `Agent(subagent_type:"fork")`, i.e. an Agent call, already matched by DEFAULT_SUBAGENT_TOOL_NAME. */
6
39
  export declare function isDelegationToolName(name: string): boolean;
40
+ /** The hands-read-only DELEGATION STRIP (the main.ts governed-spec site, extracted here so the actual filter —
41
+ * not just the name predicate — is pinned by tests): core does not propagate `handsReadOnly` to a delegated
42
+ * child, so a read-only (plan-mode) run must not mount a delegation tool at all — the child would get WRITABLE
43
+ * hands, defeating the read-only contract. Identity (the same array) when nothing matches, so the caller's
44
+ * spec-object churn stays minimal. */
7
45
  export declare function stripDelegationTools<T extends {
8
46
  name: string;
9
47
  }>(tools: readonly T[]): T[];
48
+ /** The operator autonomy mode (registry `runtime.autonomy`). */
10
49
  export type Autonomy = "read-only" | "ask" | "plan" | "auto";
50
+ /** 导出给 的枚举式行为钉用(见那里的顶注:从 core 行为反推再比对)。 */
11
51
  export declare const COARSE_SHELL_TOOLS_MIRROR: readonly string[];
52
+ /** Validate `commandPolicy` rules — the shape (array of {command, decision}), the `command` (a bare argv[0] name,
53
+ * see {@link VALID_COMMAND_NAME}), AND the `decision` enum. Returns the list of human-readable errors (empty =
54
+ * OK). Called at config-apply (sema-registry.ts `applyRuntimeHot`) so a malformed rule that BYPASSED the
55
+ * registry schema (a hand-edited config.d / a non-conformant publish) is rejected LOUDLY rather than
56
+ * silently mis-compiling — review MEDIUM: an out-of-enum `decision` (e.g. "DENY") would otherwise fall through
57
+ * {@link compileCommandPolicy}'s `decision==="deny"?…:"ask"` to ASK, silently WEAKENING an intended deny. */
12
58
  export declare function validateCommandRules(rules: CommandRule[]): string[];
59
+ /**
60
+ * Compile `runtime.commandPolicy` (per-command 3-way rules) into a single ToolPolicy, or `undefined` when there
61
+ * is nothing to govern. The registry model (per-command `allow`/`ask`/`deny`) and core's helper model
62
+ * (`allow[]` + `deny[]` + `defaultAction`) don't map 1:1, so the compilation picks a mode by the rules present:
63
+ *
64
+ * - **Allowlist mode** — triggered when ANY rule resolves to `allow`. Only `allow` commands pass; `deny` wins;
65
+ * EVERY other command — `ask`-decision AND unlisted — falls to `defaultAction:"ask"`.
66
+ * 🔴 OPERATOR FOOTGUN (documented contract): adding even one `allow` rule flips the whole policy to a strict
67
+ * allowlist — previously-passing unlisted commands now ASK.
68
+ * - **Blocklist mode** — no `allow` rules. Only `deny` commands are blocked; the rest pass THROUGH to the
69
+ * deployment baseline. Per-command `ask` is carried by {@link createCommandAskListPolicy} (the coarse helper
70
+ * can't express it). Un-parseable bypass commands fail toward `ask` in both the deny gate and the ask-list.
71
+ *
72
+ * Duplicate rules for the SAME command collapse to the STRICTEST decision (`deny > ask > allow`) BEFORE the mode
73
+ * split, so e.g. a command listed both `allow` and `ask` resolves to `ask` — honoring `combinePolicies`'
74
+ * strictest-wins (without this, the `allow` rule would shadow the `ask` for that command in allowlist mode).
75
+ *
76
+ * Either way the result only ever ADDS asks/denies — composed onto the baseline via `combinePolicies`
77
+ * (deny-wins) by {@link applyRuntimeGovernance}, so it is tighten-only. (Assumes commands are pre-validated by
78
+ * {@link validateCommandRules}; an un-matchable command here is simply inert, never a parse error.)
79
+ */
13
80
  export declare function compileCommandPolicy(rules: CommandRule[] | undefined): ToolPolicy | undefined;
81
+ /**
82
+ * Expand an autonomy mode into TIGHTEN-ONLY `TaskSpec` safety overrides (the three primitives — TRAP #2):
83
+ * - `read-only` / `plan` → `handsReadOnly: true` (read + propose, never mutate; the §6 verifier read-only
84
+ * boundary). `plan` shares the SAME safety boundary as `read-only`; the "present a plan for approval" intent
85
+ * is higher up (UX), not a distinct TaskSpec safety field, so both map to read-only hands.
86
+ * - `ask` → `shellGate: "always"` (every `Bash` command tightens to an `irreversible_ask` durable suspend —
87
+ * the fail-closed default for an unattended deployment with no parsed classifier).
88
+ * - `auto` / `undefined` → `{}` (no extra tightening; still subject to the deployment baseline + commandPolicy).
89
+ */
14
90
  export declare function autonomyOverrides(autonomy: Autonomy | undefined): Partial<TaskSpec>;
91
+ /**
92
+ * Apply the operator's runtime governance (autonomy + commandPolicy) onto a base `TaskSpec`, TIGHTEN-ONLY, in a
93
+ * SINGLE {@link tightenTaskSpec} call: commandPolicy compiles to a `toolPolicy` override (combined onto the
94
+ * baseline by `tightenTaskSpec` — TRAP #1), and autonomy expands to `handsReadOnly` / `shellGate` overrides
95
+ * (TRAP #2). `tightenTaskSpec` THROWS `TaskSpecTightenError` if any override would LOOSEN a stricter base safety
96
+ * field — surfacing a misconfiguration loudly instead of silently weakening the gate. Returns `base` untouched
97
+ * when there is nothing to apply (no autonomy override and no commandPolicy).
98
+ */
15
99
  export declare function applyRuntimeGovernance(base: TaskSpec, governance: {
16
100
  autonomy?: Autonomy;
17
101
  commandPolicy?: CommandRule[];
@@ -1,34 +1,117 @@
1
+ /**
2
+ * Runtime governance compiler — the "second baton" (center §10, core 1.114.0): turn the
3
+ * operator's declarative `runtime.autonomy` + `runtime.commandPolicy` (`@sema-agent/registry-core`,
4
+ * carried to the service via sema-registry `EffectiveConfig.runtime`) into TIGHTEN-ONLY overrides on the
5
+ * per-task `TaskSpec`. Pure so it is unit-testable in isolation (the spec is otherwise assembled inside
6
+ * main.ts's `resolveSpec`).
7
+ *
8
+ * 🪤 TWO TRAPS this module exists to NOT fall into (see core
9
+ * `tool-policy.ts` / `tighten-task-spec.ts` JSDoc):
10
+ *
11
+ * TRAP #1 — `TaskSpec.toolPolicy` OVERRIDES (not merges) `RunnerDeps.toolPolicy` (the runner does
12
+ * `spec.toolPolicy ?? deps.toolPolicy`). A bare `spec.toolPolicy = createCoarseCommandNamePolicy(…)` would
13
+ * SILENTLY DISCARD the deployment's approval/durable baseline. We compose via {@link tightenTaskSpec}, whose
14
+ * toolPolicy rule is `combinePolicies(base, override)` (deny-wins) — the command gate can only ADD denies/asks
15
+ * on top of the baseline, never clear it.
16
+ *
17
+ * TRAP #2 — `autonomy` must EXPAND INTO the three core primitives (`handsReadOnly` / `shellGate` / a
18
+ * `toolPolicy`), NOT become a parallel enum on the spec (design-research §10: a parallel `autonomy` field +
19
+ * `handsReadOnly:true` would conflict). The expansion is tighten-only and routed through `tightenTaskSpec`, so
20
+ * `auto` (the loosest mode) can never LOOSEN a stricter base — `tightenTaskSpec` THROWS instead.
21
+ *
22
+ * ⚠️ `commandPolicy` is a COARSE name-level filter, NOT a sandbox. `sh -c …` / `$(…)` / pipes / `env X=…` /
23
+ * path-prefixed commands all bypass the argv[0] match (they route to `ask`, fail-closed, but are not blocked by
24
+ * name). Real isolation is the `executionEnv` sandbox. Same caveat core documents on `createCoarseCommandNamePolicy`.
25
+ */
1
26
  import { canonicalToolName, combinePolicies, createCoarseCommandNamePolicy, DEFAULT_SUBAGENT_TOOL_NAME, parseLeadingCommandName, tightenTaskSpec, } from "@sema-agent/core";
27
+ /** True when `name` names a DELEGATION tool — the subagent tool (CC-187 canonical `"Agent"`, core 1.202
28
+ * `DEFAULT_SUBAGENT_TOOL_NAME`; legacy alias `"Task"`). CANONICAL-space compare (`canonicalToolName`) so both
29
+ * spellings match — the pre-1.202 raw `!== "Task"` compare in the read-only strip (main.ts) silently stopped
30
+ * matching when core renamed the tool (fail-open: a plan-mode / hands-read-only parent could delegate to a
31
+ * WRITABLE-hands child, because core does not propagate handsReadOnly to a delegated child).
32
+ * core 1.257 (design/136 BREAKING): the standalone `Fork` tool is retired — a fork is now
33
+ * `Agent(subagent_type:"fork")`, i.e. an Agent call, already matched by DEFAULT_SUBAGENT_TOOL_NAME. */
2
34
  export function isDelegationToolName(name) {
3
35
  const c = canonicalToolName(name);
4
36
  return c === DEFAULT_SUBAGENT_TOOL_NAME;
5
37
  }
38
+ /** The hands-read-only DELEGATION STRIP (the main.ts governed-spec site, extracted here so the actual filter —
39
+ * not just the name predicate — is pinned by tests): core does not propagate `handsReadOnly` to a delegated
40
+ * child, so a read-only (plan-mode) run must not mount a delegation tool at all — the child would get WRITABLE
41
+ * hands, defeating the read-only contract. Identity (the same array) when nothing matches, so the caller's
42
+ * spec-object churn stays minimal. */
6
43
  export function stripDelegationTools(tools) {
7
44
  const kept = tools.filter((t) => !isDelegationToolName(t.name));
8
45
  return kept.length === tools.length ? tools : kept;
9
46
  }
47
+ /** The shell tool names a command-name gate parses. Mirrors core's (un-exported) `COARSE_SHELL_TOOLS` default so
48
+ * the ask-list policy below gates the SAME tools `createCoarseCommandNamePolicy` does. A unit test pins behavior
49
+ * (a `Bash` ask-command asks) so a core rename surfaces as a red test, not silent drift.
50
+ * Q6 (core 1.161): tool names align to CC — `bash`→`Bash`; the old `bash_readonly` MERGED into `Bash` (read-only is
51
+ * now a toolEffect, not a separate tool).
52
+ *
53
+ * 🔴 2026-07-26:core 1.414 把默认从 `["Bash"]` 改成 `["Bash","Monitor"]`(Monitor 走同一条执行 seam,此前是
54
+ * 两条 always-on 门的旁门;core 的端到端实证:同一条 `rm -rf $(cat targets)`,Bash 被拒、**Monitor 零门执行**)。
55
+ * 我这份镜像因此漂了,后果是 **blocklist 模式下我的 ask-list 不覆盖 Monitor 而 core 的 deny 覆盖**。
56
+ * ⚠️ 更要紧的是**旧的钉抓不到这次加名** —— 它只钉了「一条 Bash 的 ask-command 会 ask」,加一个新名字它照样绿
57
+ * (core [1707]③ 明确点了这条)。现在的钉改成**枚举式且从 core 的行为反推**:
58
+ * `test/coarse-shell-tools-mirror.test.ts` 拿 core 导出的 `createCoarseCommandNamePolicy()`(默认参)去逐个探
59
+ * 候选工具名,把「core 真的门了哪些」测出来,再断言本常量**等于**那个集合。
60
+ * 这样做的理由:core 的 `COARSE_SHELL_TOOLS` **未导出**,而扫它的 dist 源码只能挡写法不挡行为
61
+ * (core RB-149 的教训:一个变异靠换写法就穿过了源码扫描)。 */
10
62
  const COARSE_SHELL_TOOLS = ["Bash", "Monitor"];
63
+ /** 导出给 的枚举式行为钉用(见那里的顶注:从 core 行为反推再比对)。 */
11
64
  export const COARSE_SHELL_TOOLS_MIRROR = COARSE_SHELL_TOOLS;
65
+ /**
66
+ * A per-command ask-list ToolPolicy: a parsed shell command whose `argv[0]` is in `askCommands` tightens to
67
+ * `ask`; everything else passes (`allow`). core's `createCoarseCommandNamePolicy` has NO per-command ask list
68
+ * (only `allow[]` / `deny[]` / `defaultAction`), so blocklist-mode "ask before THIS command, pass the rest"
69
+ * cannot be expressed by it — this thin policy carries the `ask` decisions. It reuses core's
70
+ * `parseLeadingCommandName` (the SINGLE source-of-truth simple-command parser used by the `Bash` tool and
71
+ * `createCoarseCommandNamePolicy`), so the argv[0]-bypass surface (operators / pipes / `env=` / path-prefix)
72
+ * routes to `ask` (fail toward the gate), never silent-allow.
73
+ */
12
74
  function createCommandAskListPolicy(askCommands, tools = COARSE_SHELL_TOOLS) {
13
75
  const askSet = new Set(askCommands);
14
76
  const shellTools = new Set(tools);
15
77
  const ask = (message) => ({ action: "ask", message, decisionReason: "rule" });
16
78
  return {
17
79
  check(req) {
80
+ // Out of scope for non-shell tools: this gate only speaks about shell command names. Canonical-space
81
+ // lookup ("Bash" has no alias today — identity; uniform with every other service policy face, so a
82
+ // future core alias or a pre-rename durable replay can't slip the gate).
18
83
  if (!shellTools.has(canonicalToolName(req.toolName)))
19
84
  return { action: "allow" };
20
85
  const command = req.args?.command;
21
86
  if (typeof command !== "string")
22
87
  return ask(`tool "${req.toolName}" call has no parseable command string`);
23
88
  const parsed = parseLeadingCommandName(command);
89
+ // Un-parseable (operators / path-prefix / env-assignment) = exactly the argv[0]-bypass surface → gate it.
24
90
  if ("reject" in parsed)
25
91
  return ask(`command is not a single simple command (${parsed.reject})`);
26
92
  return askSet.has(parsed.name) ? ask(`command "${parsed.name}" requires approval by policy`) : { action: "allow" };
27
93
  },
28
94
  };
29
95
  }
96
+ /** A valid `commandPolicy` rule targets a bare argv[0] command NAME. core's `createCoarseCommandNamePolicy` does
97
+ * EXACT `Set` matching (NOT glob, NOT last-match-wins — the §10 verdict deliberately downgraded the original
98
+ * `createCommandGlobPolicy` idea), so a glob like `git*` or a path `/usr/bin/rm` or `npm i`
99
+ * would SILENTLY never match a parsed argv[0] → the command would slip the gate. We accept only bare-name tokens
100
+ * (letters/digits and `. _ - +`, covering `python3.11`/`docker-compose`/`g++`) and reject the rest FAIL-LOUD at
101
+ * config-apply. 🔴 Kept ALIGNED with the `@sema-agent/registry-core` contract-layer regex (center fixed the
102
+ * glob→exact contract bug in 0.1.26 + publish-validates with this SAME pattern) so the contract gate and this
103
+ * defense-in-depth gate agree. The dep is
104
+ * `^0.1.26` (additive-compatible), so an additive contract bump stays aligned; a contract regex CHANGE would
105
+ * need this updated in lockstep (the two layers are coupled by design, not by a frozen byte-equality guarantee). */
30
106
  const VALID_COMMAND_NAME = /^[A-Za-z0-9._+-]+$/;
107
+ /** The three legal per-command decisions (mirrors the registry `runtime.commandPolicy[].decision` enum). */
31
108
  const VALID_DECISIONS = new Set(["allow", "ask", "deny"]);
109
+ /** Validate `commandPolicy` rules — the shape (array of {command, decision}), the `command` (a bare argv[0] name,
110
+ * see {@link VALID_COMMAND_NAME}), AND the `decision` enum. Returns the list of human-readable errors (empty =
111
+ * OK). Called at config-apply (sema-registry.ts `applyRuntimeHot`) so a malformed rule that BYPASSED the
112
+ * registry schema (a hand-edited config.d / a non-conformant publish) is rejected LOUDLY rather than
113
+ * silently mis-compiling — review MEDIUM: an out-of-enum `decision` (e.g. "DENY") would otherwise fall through
114
+ * {@link compileCommandPolicy}'s `decision==="deny"?…:"ask"` to ASK, silently WEAKENING an intended deny. */
32
115
  export function validateCommandRules(rules) {
33
116
  const errors = [];
34
117
  if (!Array.isArray(rules))
@@ -49,9 +132,31 @@ export function validateCommandRules(rules) {
49
132
  }
50
133
  return errors;
51
134
  }
135
+ /**
136
+ * Compile `runtime.commandPolicy` (per-command 3-way rules) into a single ToolPolicy, or `undefined` when there
137
+ * is nothing to govern. The registry model (per-command `allow`/`ask`/`deny`) and core's helper model
138
+ * (`allow[]` + `deny[]` + `defaultAction`) don't map 1:1, so the compilation picks a mode by the rules present:
139
+ *
140
+ * - **Allowlist mode** — triggered when ANY rule resolves to `allow`. Only `allow` commands pass; `deny` wins;
141
+ * EVERY other command — `ask`-decision AND unlisted — falls to `defaultAction:"ask"`.
142
+ * 🔴 OPERATOR FOOTGUN (documented contract): adding even one `allow` rule flips the whole policy to a strict
143
+ * allowlist — previously-passing unlisted commands now ASK.
144
+ * - **Blocklist mode** — no `allow` rules. Only `deny` commands are blocked; the rest pass THROUGH to the
145
+ * deployment baseline. Per-command `ask` is carried by {@link createCommandAskListPolicy} (the coarse helper
146
+ * can't express it). Un-parseable bypass commands fail toward `ask` in both the deny gate and the ask-list.
147
+ *
148
+ * Duplicate rules for the SAME command collapse to the STRICTEST decision (`deny > ask > allow`) BEFORE the mode
149
+ * split, so e.g. a command listed both `allow` and `ask` resolves to `ask` — honoring `combinePolicies`'
150
+ * strictest-wins (without this, the `allow` rule would shadow the `ask` for that command in allowlist mode).
151
+ *
152
+ * Either way the result only ever ADDS asks/denies — composed onto the baseline via `combinePolicies`
153
+ * (deny-wins) by {@link applyRuntimeGovernance}, so it is tighten-only. (Assumes commands are pre-validated by
154
+ * {@link validateCommandRules}; an un-matchable command here is simply inert, never a parse error.)
155
+ */
52
156
  export function compileCommandPolicy(rules) {
53
157
  if (!rules || rules.length === 0)
54
158
  return undefined;
159
+ // Collapse per command to the strictest decision (deny > ask > allow) so a duplicate can't shadow a stricter one.
55
160
  const RANK = { deny: 3, ask: 2, allow: 1 };
56
161
  const strictest = new Map();
57
162
  for (const r of rules) {
@@ -67,9 +172,13 @@ export function compileCommandPolicy(rules) {
67
172
  }
68
173
  const policies = [];
69
174
  if (allow.length > 0) {
175
+ // Allowlist mode: `allow` passes, `deny` wins, `ask`-decision + unlisted fall to defaultAction "ask".
70
176
  policies.push(createCoarseCommandNamePolicy({ allow, deny, defaultAction: "ask" }));
71
177
  }
72
178
  else {
179
+ // Blocklist mode: only `deny` blocks; per-command `ask` via the ask-list; unlisted pass through.
180
+ // (NOTE: never pass `allow: []` to the coarse helper — an empty array is truthy there and would turn it
181
+ // into an allowlist that asks on EVERYTHING. Omit allow entirely instead.)
73
182
  if (deny.length > 0)
74
183
  policies.push(createCoarseCommandNamePolicy({ deny }));
75
184
  if (ask.length > 0)
@@ -79,6 +188,15 @@ export function compileCommandPolicy(rules) {
79
188
  return undefined;
80
189
  return policies.length === 1 ? policies[0] : combinePolicies(...policies);
81
190
  }
191
+ /**
192
+ * Expand an autonomy mode into TIGHTEN-ONLY `TaskSpec` safety overrides (the three primitives — TRAP #2):
193
+ * - `read-only` / `plan` → `handsReadOnly: true` (read + propose, never mutate; the §6 verifier read-only
194
+ * boundary). `plan` shares the SAME safety boundary as `read-only`; the "present a plan for approval" intent
195
+ * is higher up (UX), not a distinct TaskSpec safety field, so both map to read-only hands.
196
+ * - `ask` → `shellGate: "always"` (every `Bash` command tightens to an `irreversible_ask` durable suspend —
197
+ * the fail-closed default for an unattended deployment with no parsed classifier).
198
+ * - `auto` / `undefined` → `{}` (no extra tightening; still subject to the deployment baseline + commandPolicy).
199
+ */
82
200
  export function autonomyOverrides(autonomy) {
83
201
  switch (autonomy) {
84
202
  case "read-only":
@@ -91,13 +209,21 @@ export function autonomyOverrides(autonomy) {
91
209
  return {};
92
210
  }
93
211
  }
212
+ /**
213
+ * Apply the operator's runtime governance (autonomy + commandPolicy) onto a base `TaskSpec`, TIGHTEN-ONLY, in a
214
+ * SINGLE {@link tightenTaskSpec} call: commandPolicy compiles to a `toolPolicy` override (combined onto the
215
+ * baseline by `tightenTaskSpec` — TRAP #1), and autonomy expands to `handsReadOnly` / `shellGate` overrides
216
+ * (TRAP #2). `tightenTaskSpec` THROWS `TaskSpecTightenError` if any override would LOOSEN a stricter base safety
217
+ * field — surfacing a misconfiguration loudly instead of silently weakening the gate. Returns `base` untouched
218
+ * when there is nothing to apply (no autonomy override and no commandPolicy).
219
+ */
94
220
  export function applyRuntimeGovernance(base, governance) {
95
221
  const overrides = { ...autonomyOverrides(governance.autonomy) };
96
222
  const coarse = compileCommandPolicy(governance.commandPolicy);
97
223
  if (coarse)
98
224
  overrides.toolPolicy = coarse;
99
225
  if (overrides.toolPolicy === undefined && overrides.handsReadOnly === undefined && overrides.shellGate === undefined) {
100
- return base;
226
+ return base; // nothing to govern → avoid a needless tightenTaskSpec pass
101
227
  }
102
228
  return tightenTaskSpec(base, overrides);
103
229
  }