@sema-agent/server 7.132.0 → 7.134.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 (473) hide show
  1. package/MIGRATION.md +353 -0
  2. package/README.md +8 -9
  3. package/README.zh-CN.md +7 -6
  4. package/USAGE.md +301 -64
  5. package/deploy/sema-up/README.md +35 -1
  6. package/deploy/sema-up/chart/Chart.yaml +1 -1
  7. package/deploy/sema-up/chart/templates/NOTES.txt +15 -0
  8. package/deploy/sema-up/chart/templates/_helpers.tpl +129 -0
  9. package/deploy/sema-up/chart/templates/sealed-key.yaml +24 -0
  10. package/deploy/sema-up/chart/templates/server-v4pro.yaml +19 -2
  11. package/deploy/sema-up/chart/templates/server.yaml +19 -2
  12. package/deploy/sema-up/chart/values-full-single.yaml +5 -1
  13. package/deploy/sema-up/chart/values.yaml +34 -0
  14. package/deploy/sema-up/stack/compose.yaml +3 -0
  15. package/deploy/sema-up/stack/sema-stack-cluster.yaml +4 -2
  16. package/dist/adoption/plan.d.ts +3 -2
  17. package/dist/adoption/plan.js +7 -5
  18. package/dist/adoption/runner.js +3 -10
  19. package/dist/adoption/sql.d.ts +3 -2
  20. package/dist/adoption/sql.js +3 -5
  21. package/dist/adoption/wire.d.ts +4 -1
  22. package/dist/adoption/wire.js +1 -0
  23. package/dist/approval-ask-audit-store.d.ts +32 -14
  24. package/dist/approval-ask-audit-store.js +272 -74
  25. package/dist/approval-ask-machine.d.ts +15 -0
  26. package/dist/approval-ask-machine.js +6 -0
  27. package/dist/approval-ask-retention.d.ts +136 -0
  28. package/dist/approval-ask-retention.js +102 -0
  29. package/dist/approval-card.d.ts +83 -23
  30. package/dist/approval-card.js +45 -15
  31. package/dist/approval-content-kind.d.ts +5 -2
  32. package/dist/approval-content-kind.js +16 -3
  33. package/dist/approval-deny-reasons.d.ts +1 -1
  34. package/dist/approval-gate-currency.d.ts +72 -0
  35. package/dist/approval-gate-currency.js +94 -0
  36. package/dist/approval.d.ts +15 -0
  37. package/dist/approval.js +55 -17
  38. package/dist/audit.d.ts +27 -10
  39. package/dist/audit.js +12 -16
  40. package/dist/bake-runner/main.js +3 -2
  41. package/dist/boot/coordinators.d.ts +6 -1
  42. package/dist/boot/coordinators.js +6 -3
  43. package/dist/boot/deferred-sandbox-path-env.js +1 -1
  44. package/dist/boot/execution-env.js +9 -7
  45. package/dist/boot/execution-lane.js +11 -0
  46. package/dist/boot/leader.d.ts +2 -0
  47. package/dist/boot/leader.js +4 -1
  48. package/dist/boot/memory-boundary.js +2 -2
  49. package/dist/boot/memory-consolidation.d.ts +5 -4
  50. package/dist/boot/memory-consolidation.js +7 -6
  51. package/dist/boot/org-delivery.d.ts +28 -0
  52. package/dist/boot/org-delivery.js +20 -0
  53. package/dist/boot/read-deny-anchor-audit.js +2 -2
  54. package/dist/boot/reapers.d.ts +3 -0
  55. package/dist/boot/reapers.js +21 -1
  56. package/dist/boot/resolve-spec.d.ts +3 -0
  57. package/dist/boot/resolve-spec.js +60 -81
  58. package/dist/boot/runner-deps.d.ts +18 -5
  59. package/dist/boot/runner-deps.js +10 -0
  60. package/dist/boot/session-faces.d.ts +1 -0
  61. package/dist/boot/session-faces.js +4 -2
  62. package/dist/boot/stage-02-web-admin-pull.js +4 -1
  63. package/dist/boot/stage-06-runners.d.ts +6 -3
  64. package/dist/boot/stage-06-runners.js +20 -4
  65. package/dist/boot/stage-07-capability-layer.d.ts +4 -1
  66. package/dist/boot/stage-07-capability-layer.js +24 -3
  67. package/dist/boot/stage-08-reapers.d.ts +4 -1
  68. package/dist/boot/stage-08-reapers.js +2 -2
  69. package/dist/boot/stage-09-leader.d.ts +5 -1
  70. package/dist/boot/stage-09-leader.js +2 -2
  71. package/dist/boot/stage-10-http-server.d.ts +5 -1
  72. package/dist/boot/stage-10-http-server.js +6 -6
  73. package/dist/boot/stores.d.ts +8 -0
  74. package/dist/boot/stores.js +10 -14
  75. package/dist/boot/web-admin.d.ts +10 -0
  76. package/dist/boot/web-admin.js +162 -65
  77. package/dist/boot/workflow-orchestration.d.ts +2 -0
  78. package/dist/boot/workflow-orchestration.js +2 -1
  79. package/dist/brain.js +8 -3
  80. package/dist/breaker-key.d.ts +6 -0
  81. package/dist/breaker-key.js +29 -0
  82. package/dist/budget.js +5 -1
  83. package/dist/caller-text-echo.d.ts +11 -6
  84. package/dist/caller-text-echo.js +10 -12
  85. package/dist/canonical-json.d.ts +2 -41
  86. package/dist/canonical-json.js +2 -13
  87. package/dist/capabilities/center-plugins.d.ts +7 -0
  88. package/dist/capabilities/center-plugins.js +1 -1
  89. package/dist/capabilities/composite-members.d.ts +1 -1
  90. package/dist/capabilities/composite-members.js +1 -1
  91. package/dist/capabilities/execution-lane.js +2 -2
  92. package/dist/capabilities/hands-lane.d.ts +21 -0
  93. package/dist/capabilities/hands-lane.js +10 -0
  94. package/dist/capabilities/mcp-probe.d.ts +36 -4
  95. package/dist/capabilities/mcp-probe.js +29 -6
  96. package/dist/capabilities/scenarios.d.ts +63 -7
  97. package/dist/capabilities/scenarios.js +39 -7
  98. package/dist/capability-facts.d.ts +36 -4
  99. package/dist/capability-facts.js +30 -4
  100. package/dist/center-config-tier.d.ts +69 -0
  101. package/dist/center-config-tier.js +42 -0
  102. package/dist/checkpoint-ctx-seal-m28.d.ts +42 -0
  103. package/dist/checkpoint-ctx-seal-m28.js +19 -0
  104. package/dist/checkpoint-identity.d.ts +16 -0
  105. package/dist/checkpoint-identity.js +19 -0
  106. package/dist/config-catalog.d.ts +17 -10
  107. package/dist/config-catalog.js +43 -28
  108. package/dist/config-d-migration.d.ts +3 -1
  109. package/dist/config-d-migration.js +2 -2
  110. package/dist/config-dir-trust.d.ts +114 -0
  111. package/dist/config-dir-trust.js +388 -0
  112. package/dist/config-invariants.d.ts +18 -5
  113. package/dist/config-invariants.js +35 -3
  114. package/dist/config-provider.d.ts +6 -1
  115. package/dist/config-provider.js +6 -2
  116. package/dist/config-types.d.ts +71 -14
  117. package/dist/config-types.js +8 -0
  118. package/dist/config.d.ts +13 -0
  119. package/dist/config.js +121 -59
  120. package/dist/delegated-session-owner.d.ts +185 -0
  121. package/dist/delegated-session-owner.js +119 -0
  122. package/dist/device-protocol.d.ts +5 -3
  123. package/dist/device-protocol.js +1 -1
  124. package/dist/device-ws-hub.js +21 -2
  125. package/dist/device-ws-protocol.d.ts +70 -6
  126. package/dist/device-ws-protocol.js +50 -23
  127. package/dist/elicitation.js +3 -2
  128. package/dist/entry-problems.d.ts +34 -0
  129. package/dist/entry-problems.js +14 -0
  130. package/dist/execution-lane-caps.d.ts +49 -10
  131. package/dist/execution-lane-caps.js +43 -4
  132. package/dist/field-conflict.d.ts +44 -0
  133. package/dist/field-conflict.js +21 -0
  134. package/dist/file-history-disclosure.d.ts +34 -5
  135. package/dist/file-history-disclosure.js +2 -2
  136. package/dist/fleet/fleet-bus.d.ts +84 -6
  137. package/dist/fleet/fleet-bus.js +42 -9
  138. package/dist/hooks/classic-stations.d.ts +10 -5
  139. package/dist/hooks/classic-stations.js +4 -4
  140. package/dist/hooks/command-spawn.d.ts +57 -0
  141. package/dist/hooks/command-spawn.js +139 -0
  142. package/dist/hooks/hook-llm.js +2 -2
  143. package/dist/hooks/hook-runner.d.ts +127 -25
  144. package/dist/hooks/hook-runner.js +668 -287
  145. package/dist/hooks/hook-source.d.ts +44 -0
  146. package/dist/hooks/hook-source.js +40 -0
  147. package/dist/http/active-run-conflict.d.ts +5 -13
  148. package/dist/http/active-run-conflict.js +17 -27
  149. package/dist/http/admission.js +111 -60
  150. package/dist/http/approval-sweeps.js +58 -19
  151. package/dist/http/caller-trust.d.ts +77 -0
  152. package/dist/http/caller-trust.js +143 -0
  153. package/dist/http/checkpoint-ctx.d.ts +173 -18
  154. package/dist/http/checkpoint-ctx.js +171 -12
  155. package/dist/http/claimed-run.d.ts +4 -3
  156. package/dist/http/device-placement.d.ts +2 -4
  157. package/dist/http/device-placement.js +2 -1
  158. package/dist/http/dispatch.js +13 -7
  159. package/dist/http/durable-run-leg.d.ts +4 -32
  160. package/dist/http/durable-run-leg.js +37 -12
  161. package/dist/http/idempotency.d.ts +2 -2
  162. package/dist/http/idempotency.js +2 -2
  163. package/dist/http/owner-access.d.ts +56 -0
  164. package/dist/http/owner-access.js +42 -0
  165. package/dist/http/principal-gate.d.ts +78 -27
  166. package/dist/http/principal-gate.js +64 -14
  167. package/dist/http/readiness.d.ts +11 -5
  168. package/dist/http/readiness.js +10 -3
  169. package/dist/http/refusal-body.d.ts +12 -0
  170. package/dist/http/refusal-body.js +11 -0
  171. package/dist/http/request-guards.d.ts +16 -32
  172. package/dist/http/request-guards.js +31 -30
  173. package/dist/http/resume-ctx-read.d.ts +50 -6
  174. package/dist/http/resume-ctx-read.js +33 -7
  175. package/dist/http/resume-legs.d.ts +5 -5
  176. package/dist/http/resume-legs.js +163 -91
  177. package/dist/http/retired-service-deps.d.ts +43 -0
  178. package/dist/http/retired-service-deps.js +18 -0
  179. package/dist/http/route-ctx.d.ts +44 -37
  180. package/dist/http/route-ctx.js +4 -0
  181. package/dist/http/route-table.js +2 -0
  182. package/dist/http/routes/a2a-serve.js +3 -4
  183. package/dist/http/routes/admin-config-refresh.js +1 -1
  184. package/dist/http/routes/admin-drain.js +1 -1
  185. package/dist/http/routes/admin-memory-optout.js +5 -1
  186. package/dist/http/routes/adoption.js +2 -9
  187. package/dist/http/routes/agents-roster.js +2 -3
  188. package/dist/http/routes/approvals-assistant.js +91 -56
  189. package/dist/http/routes/background.js +3 -2
  190. package/dist/http/routes/capabilities.js +20 -4
  191. package/dist/http/routes/config-catalog.d.ts +3 -3
  192. package/dist/http/routes/config-catalog.js +1 -1
  193. package/dist/http/routes/devices.js +3 -17
  194. package/dist/http/routes/diagnostics.d.ts +3 -3
  195. package/dist/http/routes/diagnostics.js +6 -2
  196. package/dist/http/routes/fleet.js +4 -4
  197. package/dist/http/routes/images.js +6 -7
  198. package/dist/http/routes/leader.js +1 -8
  199. package/dist/http/routes/mcp-reconnect.d.ts +1 -1
  200. package/dist/http/routes/mcp-reconnect.js +3 -2
  201. package/dist/http/routes/memory-bundle.js +1 -1
  202. package/dist/http/routes/memory-compliance.js +1 -1
  203. package/dist/http/routes/memory-consolidation.js +1 -1
  204. package/dist/http/routes/memory-origin.d.ts +1 -1
  205. package/dist/http/routes/memory-origin.js +1 -1
  206. package/dist/http/routes/memory-policy.d.ts +1 -1
  207. package/dist/http/routes/memory-policy.js +3 -2
  208. package/dist/http/routes/notify-wake.js +8 -21
  209. package/dist/http/routes/observability.js +2 -2
  210. package/dist/http/routes/principal-inbox.d.ts +39 -0
  211. package/dist/http/routes/principal-inbox.js +76 -0
  212. package/dist/http/routes/retention-ops.js +2 -9
  213. package/dist/http/routes/rules.js +9 -22
  214. package/dist/http/routes/runs.d.ts +5 -0
  215. package/dist/http/routes/runs.js +63 -115
  216. package/dist/http/routes/session-sync.d.ts +3 -2
  217. package/dist/http/routes/session-sync.js +53 -48
  218. package/dist/http/routes/sessions-list.d.ts +1 -1
  219. package/dist/http/routes/sessions-list.js +3 -4
  220. package/dist/http/routes/sessions.js +33 -43
  221. package/dist/http/routes/side-query.js +6 -4
  222. package/dist/http/routes/tasks.js +71 -30
  223. package/dist/http/routes/trace-usage.js +7 -9
  224. package/dist/http/routes/workflows.d.ts +351 -0
  225. package/dist/http/routes/workflows.js +153 -119
  226. package/dist/http/run-declared-families.d.ts +16 -0
  227. package/dist/http/run-declared-families.js +12 -0
  228. package/dist/http/send.d.ts +24 -3
  229. package/dist/http/send.js +14 -2
  230. package/dist/http/server.d.ts +23 -18
  231. package/dist/http/server.js +20 -15
  232. package/dist/http/stored-body-replay.js +17 -4
  233. package/dist/http/submit-ctx.d.ts +4 -3
  234. package/dist/http/submit-ctx.js +23 -6
  235. package/dist/http/submit-replay.d.ts +4 -3
  236. package/dist/http/submit-replay.js +5 -4
  237. package/dist/http/wire-types.d.ts +17 -10
  238. package/dist/index.d.ts +3 -1
  239. package/dist/index.js +1 -1
  240. package/dist/lane-home-probe.d.ts +78 -9
  241. package/dist/lane-home-probe.js +78 -12
  242. package/dist/leader/endpoint.d.ts +4 -1
  243. package/dist/leader/endpoint.js +11 -10
  244. package/dist/leader/wire.d.ts +4 -0
  245. package/dist/leader/wire.js +8 -7
  246. package/dist/limit-refusal.d.ts +17 -5
  247. package/dist/limit-refusal.js +4 -1
  248. package/dist/main.js +1 -1
  249. package/dist/mcp-assertion-header.d.ts +31 -10
  250. package/dist/mcp-assertion-header.js +10 -3
  251. package/dist/memory-origin-fence.js +2 -2
  252. package/dist/memory-project-layer.d.ts +37 -0
  253. package/dist/memory-project-layer.js +46 -0
  254. package/dist/memory-scope.d.ts +23 -16
  255. package/dist/memory-scope.js +24 -8
  256. package/dist/memory-sync-client.d.ts +27 -13
  257. package/dist/memory-sync-client.js +107 -18
  258. package/dist/model-compat.d.ts +1 -1
  259. package/dist/model-entry-refusal.d.ts +9 -1
  260. package/dist/model-entry-refusal.js +6 -1
  261. package/dist/model-plane-face.d.ts +51 -0
  262. package/dist/model-plane-face.js +24 -0
  263. package/dist/model-provider.d.ts +5 -0
  264. package/dist/model-provider.js +4 -2
  265. package/dist/model-route-endpoint.d.ts +8 -11
  266. package/dist/model-route-endpoint.js +4 -7
  267. package/dist/model-route-env.d.ts +22 -0
  268. package/dist/model-route-env.js +2 -0
  269. package/dist/model-route-gap.d.ts +60 -30
  270. package/dist/model-route-gap.js +21 -15
  271. package/dist/observability/corrupt-read-seat.d.ts +7 -0
  272. package/dist/observability/corrupt-read-seat.js +9 -0
  273. package/dist/observability/err-text.d.ts +6 -0
  274. package/dist/observability/err-text.js +18 -4
  275. package/dist/observability/fail-open.d.ts +35 -9
  276. package/dist/observability/fail-open.js +35 -9
  277. package/dist/observability/metrics.js +1 -0
  278. package/dist/observability/prompt-manifest.d.ts +22 -25
  279. package/dist/observability/prompt-manifest.js +54 -50
  280. package/dist/observability/tool-trace.js +9 -10
  281. package/dist/operator-ask.d.ts +10 -0
  282. package/dist/operator-ask.js +3 -0
  283. package/dist/orchestration/workflow-agent-session-index.d.ts +12 -12
  284. package/dist/orchestration/workflow-agent-session-index.js +9 -13
  285. package/dist/orchestration/workflow-completion-inbox.d.ts +42 -15
  286. package/dist/orchestration/workflow-completion-inbox.js +13 -0
  287. package/dist/orchestration/workflow-notify-journal.d.ts +13 -32
  288. package/dist/orchestration/workflow-notify-journal.js +27 -34
  289. package/dist/orchestration/workflow-park-decision.d.ts +89 -0
  290. package/dist/orchestration/workflow-park-decision.js +119 -0
  291. package/dist/org-delivery-gate.d.ts +81 -0
  292. package/dist/org-delivery-gate.js +59 -0
  293. package/dist/panel-tool-names.d.ts +23 -0
  294. package/dist/panel-tool-names.js +8 -0
  295. package/dist/parked-decide.d.ts +43 -11
  296. package/dist/parked-decide.js +100 -51
  297. package/dist/parked-revive-surface.d.ts +9 -2
  298. package/dist/parked-revive-surface.js +11 -8
  299. package/dist/permission-rule-list.d.ts +1 -1
  300. package/dist/permission-rule-list.js +2 -2
  301. package/dist/permission-rule-vocab.d.ts +1 -23
  302. package/dist/permission-rule-vocab.js +0 -13
  303. package/dist/plugins/approval-ask-store-file.d.ts +16 -1
  304. package/dist/plugins/approval-ask-store-file.js +21 -0
  305. package/dist/plugins/approval-ask-store-memory.d.ts +18 -1
  306. package/dist/plugins/approval-ask-store-memory.js +34 -2
  307. package/dist/plugins/approval-ask-store-sql.d.ts +25 -0
  308. package/dist/plugins/approval-ask-store-sql.js +37 -1
  309. package/dist/plugins/approval-payload-fingerprint.d.ts +14 -6
  310. package/dist/plugins/approval-payload-fingerprint.js +1 -1
  311. package/dist/plugins/blob-backend.d.ts +38 -25
  312. package/dist/plugins/blob-backend.js +29 -19
  313. package/dist/plugins/breaker-state-sql.d.ts +2 -2
  314. package/dist/plugins/breaker-state-sql.js +4 -4
  315. package/dist/plugins/caching-session-store.d.ts +4 -1
  316. package/dist/plugins/caching-session-store.js +7 -3
  317. package/dist/plugins/checkpoint-store-sql.d.ts +36 -1
  318. package/dist/plugins/checkpoint-store-sql.js +65 -3
  319. package/dist/plugins/file-history-store-sql.d.ts +5 -2
  320. package/dist/plugins/file-history-store-sql.js +3 -1
  321. package/dist/plugins/file-run-store.d.ts +5 -13
  322. package/dist/plugins/file-run-store.js +9 -0
  323. package/dist/plugins/fork-routing-session-store.d.ts +9 -1
  324. package/dist/plugins/fork-routing-session-store.js +12 -1
  325. package/dist/plugins/host-platform.d.ts +2 -0
  326. package/dist/plugins/host-platform.js +2 -1
  327. package/dist/plugins/local-checkpoint-store.d.ts +15 -2
  328. package/dist/plugins/local-checkpoint-store.js +32 -1
  329. package/dist/plugins/local-session-store.d.ts +13 -10
  330. package/dist/plugins/local-session-store.js +23 -14
  331. package/dist/plugins/local-session-window.d.ts +45 -0
  332. package/dist/plugins/local-session-window.js +38 -0
  333. package/dist/plugins/mailbox-recipient-lifecycle.d.ts +3 -2
  334. package/dist/plugins/mailbox-store-sql.d.ts +30 -48
  335. package/dist/plugins/mailbox-store-sql.js +77 -52
  336. package/dist/plugins/memory-embedder-fingerprint.js +2 -1
  337. package/dist/plugins/memory-run-store.d.ts +5 -13
  338. package/dist/plugins/memory-run-store.js +8 -0
  339. package/dist/plugins/one-time-migrations.d.ts +121 -5
  340. package/dist/plugins/one-time-migrations.js +332 -8
  341. package/dist/plugins/org-delivery-quota-store.d.ts +123 -0
  342. package/dist/plugins/org-delivery-quota-store.js +228 -0
  343. package/dist/plugins/permission-rule-store-file.js +10 -6
  344. package/dist/plugins/permission-rule-store-sql.js +8 -8
  345. package/dist/plugins/pg-pool.js +39 -7
  346. package/dist/plugins/pg-session-storage.d.ts +18 -5
  347. package/dist/plugins/pg-session-storage.js +68 -23
  348. package/dist/plugins/remote-env-adb.d.ts +6 -12
  349. package/dist/plugins/remote-env-adb.js +12 -2
  350. package/dist/plugins/remote-env-device.d.ts +14 -7
  351. package/dist/plugins/remote-env-device.js +23 -15
  352. package/dist/plugins/remote-env-k8s.d.ts +8 -12
  353. package/dist/plugins/remote-env-k8s.js +23 -5
  354. package/dist/plugins/remote-env-local-docker.d.ts +10 -15
  355. package/dist/plugins/remote-env-local-docker.js +12 -9
  356. package/dist/plugins/remote-env-ssh.d.ts +10 -16
  357. package/dist/plugins/remote-env-ssh.js +17 -11
  358. package/dist/plugins/run-store-sql.d.ts +16 -14
  359. package/dist/plugins/run-store-sql.js +22 -2
  360. package/dist/plugins/schema-indexes.js +2 -0
  361. package/dist/plugins/send-user-file.js +2 -2
  362. package/dist/plugins/session-epoch-anchor.d.ts +32 -6
  363. package/dist/plugins/session-epoch-anchor.js +2 -3
  364. package/dist/plugins/session-ownership.d.ts +11 -0
  365. package/dist/plugins/session-ownership.js +11 -0
  366. package/dist/plugins/session-placement.d.ts +12 -14
  367. package/dist/plugins/session-placement.js +2 -15
  368. package/dist/plugins/session-store.d.ts +18 -8
  369. package/dist/plugins/session-store.js +15 -4
  370. package/dist/plugins/sql-driver.d.ts +74 -11
  371. package/dist/plugins/sql-driver.js +210 -12
  372. package/dist/plugins/sql-errors.d.ts +23 -0
  373. package/dist/plugins/sql-errors.js +21 -0
  374. package/dist/plugins/store-backend.d.ts +36 -1
  375. package/dist/plugins/store-backend.js +40 -14
  376. package/dist/plugins/store-contracts.d.ts +42 -0
  377. package/dist/plugins/store-contracts.js +1 -0
  378. package/dist/plugins/tidb-pool.d.ts +6 -1
  379. package/dist/plugins/tidb-pool.js +44 -10
  380. package/dist/plugins/tidb-session-storage.d.ts +3 -2
  381. package/dist/plugins/tidb-session-storage.js +2 -2
  382. package/dist/plugins/tidb-session-store.d.ts +25 -5
  383. package/dist/plugins/tidb-session-store.js +67 -21
  384. package/dist/plugins/workflow-journal-store-sql.d.ts +73 -19
  385. package/dist/plugins/workflow-journal-store-sql.js +19 -6
  386. package/dist/plugins/workflow-run-store-sql.d.ts +30 -8
  387. package/dist/plugins/workflow-run-store-sql.js +50 -9
  388. package/dist/posture-source.d.ts +18 -10
  389. package/dist/posture-source.js +4 -1
  390. package/dist/project-identity.d.ts +45 -6
  391. package/dist/project-identity.js +162 -8
  392. package/dist/project-layer-key.d.ts +28 -0
  393. package/dist/project-layer-key.js +29 -0
  394. package/dist/question.js +3 -2
  395. package/dist/read-deny-entry.d.ts +25 -0
  396. package/dist/read-deny-entry.js +12 -0
  397. package/dist/read-face-posture.d.ts +37 -11
  398. package/dist/read-face-posture.js +32 -3
  399. package/dist/request-key-closure.d.ts +7 -0
  400. package/dist/request-key-closure.js +9 -1
  401. package/dist/request-tool-axes.d.ts +12 -0
  402. package/dist/request-tool-axes.js +20 -0
  403. package/dist/request-value-closure.d.ts +5 -0
  404. package/dist/request-value-closure.js +11 -3
  405. package/dist/rule-entry-list.d.ts +26 -2
  406. package/dist/rule-entry-list.js +72 -12
  407. package/dist/rules-consent.js +3 -4
  408. package/dist/run-acceptance.d.ts +19 -3
  409. package/dist/run-acceptance.js +13 -1
  410. package/dist/run-local.js +37 -6
  411. package/dist/runs.d.ts +12 -10
  412. package/dist/runs.js +25 -6
  413. package/dist/runtime-caps-resolver.d.ts +16 -6
  414. package/dist/runtime-caps-resolver.js +18 -5
  415. package/dist/sandbox-pkg-source.d.ts +19 -1
  416. package/dist/sandbox-pkg-source.js +29 -7
  417. package/dist/sealed-key.d.ts +32 -0
  418. package/dist/sealed-key.js +55 -1
  419. package/dist/security.d.ts +95 -15
  420. package/dist/security.js +52 -9
  421. package/dist/session-error-wire.d.ts +31 -7
  422. package/dist/session-error-wire.js +9 -2
  423. package/dist/session-sync-kernel.d.ts +37 -10
  424. package/dist/session-sync-kernel.js +10 -0
  425. package/dist/session-titled-frame.d.ts +33 -0
  426. package/dist/session-titled-frame.js +4 -0
  427. package/dist/session-titler.d.ts +9 -1
  428. package/dist/session-titler.js +15 -4
  429. package/dist/spec-fields.js +21 -2
  430. package/dist/sql-engine-posture.d.ts +3 -1
  431. package/dist/task-a2a.js +4 -3
  432. package/dist/task-cwd.d.ts +1 -1
  433. package/dist/task-mcp.d.ts +5 -5
  434. package/dist/task-mcp.js +27 -74
  435. package/dist/task-settings.d.ts +93 -88
  436. package/dist/task-settings.js +71 -63
  437. package/dist/text-bidi.d.ts +0 -4
  438. package/dist/text-bidi.js +1 -3
  439. package/dist/tighten-only-seats.d.ts +150 -0
  440. package/dist/tighten-only-seats.js +196 -0
  441. package/dist/tool-approval.d.ts +451 -136
  442. package/dist/tool-approval.js +733 -256
  443. package/dist/tool-rule-names.d.ts +6 -0
  444. package/dist/trace/core-keyset-guard.d.ts +108 -25
  445. package/dist/trace/exit-seat.d.ts +40 -0
  446. package/dist/trace/exit-seat.js +130 -0
  447. package/dist/trace/ledger-events.d.ts +6 -3
  448. package/dist/trace/project.d.ts +98 -13
  449. package/dist/trace/project.js +57 -32
  450. package/dist/trace/projection-table.d.ts +100 -0
  451. package/dist/trace/projection-table.js +130 -0
  452. package/dist/trace/redact.d.ts +57 -0
  453. package/dist/trace/redact.js +962 -168
  454. package/dist/trace/self-minted-wire.d.ts +349 -1
  455. package/dist/trace/self-minted-wire.js +118 -1
  456. package/dist/trace/wire-projection-faces.d.ts +304 -2
  457. package/dist/trace/wire-projection-faces.js +160 -13
  458. package/dist/url-refusal.js +2 -0
  459. package/dist/web-admin-client/apply-effective.d.ts +12 -0
  460. package/dist/web-admin-client/apply-effective.js +56 -5
  461. package/dist/web-admin-client/facade.d.ts +1 -1
  462. package/dist/web-admin-client/facade.js +1 -1
  463. package/dist/web-admin-client/read-face.js +5 -9
  464. package/dist/web-admin-client/skills-mcp.d.ts +1 -1
  465. package/dist/web-admin-client/skills-mcp.js +6 -8
  466. package/dist/web-admin-client/types.d.ts +1 -1
  467. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +57 -9
  468. package/package.json +8 -4
  469. package/scripts/drain-check-local.mjs +34 -2
  470. package/scripts/drain-check.mysql.sql +20 -2
  471. package/scripts/drain-check.pg.sql +20 -2
  472. package/dist/mcp-tool-faces.d.ts +0 -69
  473. package/dist/mcp-tool-faces.js +0 -106
@@ -6,10 +6,11 @@
6
6
  * symbols WITHOUT touching the orchestration module — session-sync.ts value-imports StoreBackend and type-imports
7
7
  * security's OwnerAwareSessionStore, so importing it from security.ts formed the repo's only true type cycle
8
8
  * (security ↔ session-sync; lens2 §B/§E). This file imports nothing from the repo but TYPES from leaves (core types, and
9
- * the session-face type from `session-incarnation.ts`, itself a leaf) — a leaf, same shape as session-sync-content.ts. session-sync.ts re-exports everything here, so existing import sites
9
+ * the session-face type from `session-incarnation.ts`, itself a leaf) — a leaf, same shape as session-sync-content.ts. Its one VALUE import is
10
+ * core's `SessionError` class (the closed-set store error the three adapters already throw). session-sync.ts re-exports everything here, so existing import sites
10
11
  * keep working unchanged.
11
12
  */
12
- import type { SessionTreeEntry } from "@sema-agent/core";
13
+ import { SessionError, type SessionTreeEntry } from "@sema-agent/core";
13
14
  import type { SessionFace } from "./session-incarnation.js";
14
15
  /**
15
16
  * P1d-β (PUSH streaming, sema-internal server/docs/DESIGN-session-sync.md §15 + the persistence synthesis) — a TWO-PHASE STAGED import
@@ -23,8 +24,9 @@ import type { SessionFace } from "./session-incarnation.js";
23
24
  * Invariants the implementations uphold:
24
25
  * - The staging rows live under `stagingId = ${realSessionId}#stg-${token}` (the `#` is illegal in a real uuidv7, so
25
26
  * it can NEVER collide with a real session id) and have NO `session_meta` row → they are INVISIBLE to wake / ownerOf
26
- * / listSessions (the existing orphan invariant) until `commit` writes the real session_meta LAST as the sole
27
- * commit point. A crash before commit leaves only collectable orphan staging rows, never a half-session.
27
+ * / listSessions (the existing orphan invariant) until `commit`'s transaction COMMITs the real session_meta row together
28
+ * with the swap (the sole commit point; a fresh push claims that row first inside the same txn, invisible to everyone else
29
+ * until COMMIT). A crash before commit leaves only collectable orphan staging rows, never a half-session.
28
30
  * - `appendBatch` is IDEMPOTENT (INSERT … ON DUPLICATE KEY / ON CONFLICT DO NOTHING on the `(session_id, entry_id)`
29
31
  * uk), so a re-streamed batch (a resumed Phase B) is a no-op.
30
32
  * - `commit` re-classifies the relation IN-TXN against the dst's CURRENT entry ids (closing the Phase-A plan→commit
@@ -38,23 +40,48 @@ export interface StagingHandle {
38
40
  /** Append a bounded batch of entries to the staging id, re-seq'd dense from a running counter held in the handle.
39
41
  * Idempotent (ON DUPLICATE KEY / ON CONFLICT DO NOTHING) — a re-streamed batch is a no-op. One txn per batch. */
40
42
  appendBatch(entries: SessionTreeEntry[]): Promise<void>;
41
- /** ATOMICALLY swap the staged rows into the real session id (ONE txn): in-txn re-classify (TOCTOU close) → purge dst
42
- * → row-key rename staging→real → session_meta LAST (the commit point). `owner` is re-stamped (§9). Throws
43
- * {@link SyncConflictError} on an unconsented fork/stale flip. Returns the committed relation **and the settled session
43
+ /** ATOMICALLY swap the staged rows into the real session id (ONE txn): owner CAS ({@link StagedCommitOptions.expectedOwner},
44
+ * before anything about the row is classified or reported, so a refused commit reveals nothing about a row it did not judge — no
45
+ * placement, no relation, no entry ids) → in-txn re-classify
46
+ * (TOCTOU close) → purge dst → row-key rename staging→real → session_meta settled; COMMIT is the commit point. `owner` is re-stamped (§9).
47
+ * Throws {@link StagedCommitOwnerChangedError} when the owner cell is not the one the import's gate judged, and
48
+ * {@link SyncConflictError} on an unconsented fork/stale flip — both after rolling back. Returns the committed relation **and the settled session
44
49
  * face** — the occupant (owner + incarnation) the commit left in the real session id, read INSIDE the same txn (the local
45
50
  * store: the same hold of the session's write lock), never re-read afterwards. The post-commit replays conditioned on the
46
51
  * occupant (the session row's two bits) write on exactly this face — a session deleted and re-created after the commit,
47
52
  * even by the same owner, is a different occupant and is not written. A row without an incarnation is refused at that read
48
53
  * (`sessionFaceFromRow`, the same law as every face read). */
49
- commit(owner: string | null, opts?: {
50
- resolution?: "overwrite-dst";
51
- }): Promise<{
54
+ commit(owner: string | null, opts: StagedCommitOptions): Promise<{
52
55
  relation: SyncRelation["relation"];
53
56
  face: SessionFace;
54
57
  }>;
55
58
  /** Drop the staging rows (Phase B aborted before commit) — DELETE the staging-id session_event rows. Idempotent. */
56
59
  abort(): Promise<void>;
57
60
  }
61
+ /**
62
+ * What a staged commit is conditioned on (S-1938 — one gate predicate, two phases). `expectedOwner` = the owner cell the import's gate
63
+ * judged when it opened the staging, in the `ownerOf` reading: `undefined` = no such session (a fresh push), `null` = ownerless, a string =
64
+ * that owner. The route judges `mayTouch` on that cell at Phase A and again on the session's current cell right before Phase B commits; the
65
+ * commit itself lands only on that same cell — each store compares it inside the commit txn (local: inside the session's write lock) and, when
66
+ * the cell differs, rolls back and throws {@link StagedCommitOwnerChangedError} without writing a byte. The compare is on the owner cell, not
67
+ * on the incarnation: the gate's predicate reads only the owner (plus placement, which the commit gate refuses on its own), so a same-owner
68
+ * re-create is judged the same and is not a reason to refuse.
69
+ */
70
+ export interface StagedCommitOptions {
71
+ readonly expectedOwner: string | null | undefined;
72
+ readonly resolution?: "overwrite-dst";
73
+ }
74
+ /**
75
+ * The staged commit's owner CAS did not hold: the session's owner cell at commit time is not the one the import's gate judged (another replica
76
+ * deleted / re-created / claimed / created the session while the import streamed). Code = core's closed-set `conflict` (wire: the import face's
77
+ * row in `session-error-wire.ts`, 409); thrown after the commit txn rolled back — the destination is untouched. The three stores throw this one
78
+ * class (one sentence, minted here).
79
+ */
80
+ export declare class StagedCommitOwnerChangedError extends SessionError {
81
+ constructor(sessionId: string);
82
+ }
83
+ /** The owner-cell comparison of {@link StagedCommitOptions.expectedOwner} against a store's own `ownerOf`-shaped read (`undefined` = no row). */
84
+ export declare function ownerCellIs(expectedOwner: string | null | undefined, actual: string | null | undefined): boolean;
58
85
  /** A session store that can stage a streamed import (P1d-β). The 3 backends implement it; the in-memory dev store
59
86
  * does not → the method is optional (the route 501s when absent, parity with the other §0.5 optional seams). */
60
87
  export type ImportStagingStore = {
@@ -1,3 +1,13 @@
1
+ import { SessionError } from "@sema-agent/core";
2
+ export class StagedCommitOwnerChangedError extends SessionError {
3
+ constructor(sessionId) {
4
+ super("conflict", `session ${sessionId}: owner changed while the import streamed — the staged commit was rolled back`);
5
+ this.name = "StagedCommitOwnerChangedError";
6
+ }
7
+ }
8
+ export function ownerCellIs(expectedOwner, actual) {
9
+ return expectedOwner === undefined ? actual === undefined : actual !== undefined && (actual ?? null) === expectedOwner;
10
+ }
1
11
  export function stagingIdFor(realSessionId, token) {
2
12
  return `${realSessionId}#stg-${token}`;
3
13
  }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * **会话标题帧 `session_titled`** —— 标题器把标题写进会话行**之后**,在**这条 run 的活流**上自铸的一帧(契约 §4a-ttl)。
3
+ *
4
+ * ## 为什么有这一帧
5
+ * 标题器是 fire-and-forget:run 被引擎受理之后才起、在 run 跑的同时生成,写成时那条 run 的流往往还开着。此前写成只落行
6
+ * (`setTitleIfNull`)+ 一行运维日志 —— wire 上零通知,端上(桌面 / web 座位)只能在首轮之后有界轮询读会话行。
7
+ * 这一帧把「标题写成了」交给已经在 tail 这条流的人,轮询可以删。
8
+ *
9
+ * ## 律(一条)
10
+ * **只活不存**:会话行是标题的唯一真源,本帧只是「行刚刚变了」的活通知 —— 不落账本(`GET /v1/runs/:id/events` 回放读不出它)、
11
+ * 不进任何重放面;冷启动 / 多窗口 / 断线重连读会话行(`GET /v1/sessions` 的列表行 `title`;`/v1/sessions/:id/head` 只带 `leafId`,不是标题的读面)。因此:
12
+ * · 读者 = **这条 run 的流读者**,与会话行的读权同一(流是提交这条 run 的人开的,会话行归同一个人);
13
+ * · 只有持活流的腿才收得到(今天 = `POST /v1/tasks/stream`);同步 JSON 腿 / durable 后台腿没有活流 ⇒ 这一帧结构上不存在,读行;
14
+ * · 流已经走到终帧(`done`)或连接已断 ⇒ 丢弃(终帧是流的最后一帧);
15
+ * · `PATCH /v1/sessions/:id` 的改名 / 置顶不经标题器 ⇒ 不发(调用方自知);用户清空标题后下一次提交由标题器重填,那一次重填照发(例外:本进程里此前为这个会话生成失败 / 回空过 —— 标题器不再为它重试,直到进程重启)。
16
+ *
17
+ * ## 谁铸
18
+ * 唯一铸点 = {@link buildSessionTitledFrame},唯一调用方 = `session-titler.ts`(落行成功的那一支,实参 = 落进行里的**同一个**标题 ——
19
+ * 已脱敏、已清洗;帧上的标题与行上的标题是一个值,不从模型原文另铸)。键集登记在 `trace/self-minted-wire.ts` 的 `sessionTitledFrameKey`
20
+ * (成员集 `satisfies Record<keyof SessionTitledFrame, …>`:加一个键而登记没跟 ⇒ tsc 红)。
21
+ *
22
+ * 帧上没有 `eventId` ⇒ SSE 不发 `id:` 行(契约 §0.6「无锚不发行」):它不是引擎的内容帧,没有续流位置可言。
23
+ */
24
+ /** 标题帧的形 —— 键集就是这个接口的键(登记表按 `keyof` 绑定)。 */
25
+ export interface SessionTitledFrame {
26
+ readonly type: "session_titled";
27
+ readonly sessionId: string;
28
+ /** 落进会话行的那个标题(已过标题器的脱敏与清洗,≤ `TITLE_MAX_CHARS` 个字符)。 */
29
+ readonly title: string;
30
+ }
31
+ /** 唯一铸点:纯数据,无行为。 */
32
+ export declare function buildSessionTitledFrame(sessionId: string, title: string): SessionTitledFrame;
33
+ //# sourceMappingURL=session-titled-frame.d.ts.map
@@ -0,0 +1,4 @@
1
+ export function buildSessionTitledFrame(sessionId, title) {
2
+ return { type: "session_titled", sessionId, title };
3
+ }
4
+ //# sourceMappingURL=session-titled-frame.js.map
@@ -13,6 +13,11 @@
13
13
  * cheap-model one-liner via the deployment's hookLlm face (summarize role → MODEL_CHEAP_ID when configured, else the
14
14
  * main model; bounded + timed out).
15
15
  *
16
+ * WRITE-AFTER NOTICE: the title that lands is announced to the run that triggered it — `maybeTitle`'s `onTitled` hands the
17
+ * seat (`run-acceptance.ts`) the one `session_titled` frame (`session-titled-frame.ts`, contract §4a-ttl) built from the
18
+ * SAME string the row now holds; the seat forwards it to the live stream when the leg has one. Live-only: the row is the
19
+ * truth, nothing else stores the frame.
20
+ *
16
21
  * FAILURE POSTURE: everything is best-effort — a generation/store failure logs and leaves title null (the
17
22
  * list falls back to objectivePreview). The fail-open tag it leaves names the CAUSE FAMILY (one tag, one family):
18
23
  * the llm face's failure CODE picks it (`failOpenTagFor`), never the error's wording. An in-process pending set dedupes concurrent submits on the same
@@ -20,6 +25,7 @@
20
25
  * call at worst, and exactly one title lands).
21
26
  */
22
27
  import type { HookLlmFailureCode } from "./hooks/hook-runner.js";
28
+ import { type SessionTitledFrame } from "./session-titled-frame.js";
23
29
  export interface SessionTitlerDeps {
24
30
  /** Secret scrub applied to the RAW llm text before sanitize/persist (workflow audit 2026-07-13: the
25
31
  * objective may carry a pasted secret and the model can echo it into the title — titles are persisted,
@@ -58,7 +64,9 @@ export interface SessionTitlerDeps {
58
64
  export interface SessionTitler {
59
65
  /** Fire-and-forget: maybe generate + persist a title for this session. Never throws, never blocks the caller. */
60
66
  /** `model`([ref]②)= 本 turn 真实驱动的模型——带上则标题 hook 同链路,不再裸落 env 缺省。 */
61
- maybeTitle(sessionId: string, objective: string, model?: string): void;
67
+ /** `onTitled` = 这一次调用**自己**把标题写成之后(`setTitleIfNull` 落行)交出的活通知(`session_titled` 帧,契约 §4a-ttl):只在落行的那一支调用恰一次 ——
68
+ * 已有标题 / 竞态输了 / 模型失败 / 空标题 / 这个会话已有一次在飞的调用,都不调。回调同步执行、**不许抛**;抛了也不影响已落行的标题(见下 `frame_failed`)。 */
69
+ maybeTitle(sessionId: string, objective: string, model?: string, onTitled?: (frame: SessionTitledFrame) => void): void;
62
70
  }
63
71
  export declare const TITLE_MAX_CHARS = 80;
64
72
  /** Single line, control chars stripped, hard cap; surrounding quotes (a common LLM tic) trimmed. */
@@ -1,7 +1,8 @@
1
- import { CONTROL_AND_BIDI_STRIP_RE } from "./text-bidi.js";
1
+ import { stripControlAndBidi } from "@sema-agent/settings-schema";
2
2
  import { recordFailOpen } from "./observability/fail-open.js";
3
3
  import { redactSecrets } from "./trace/redact.js";
4
4
  import { userAuthoredText } from "./user-authored-text.js";
5
+ import { buildSessionTitledFrame } from "./session-titled-frame.js";
5
6
  export const TITLE_MAX_CHARS = 80;
6
7
  const OBJECTIVE_SNIPPET_CHARS = 600;
7
8
  const LLM_TIMEOUT_MS = 15_000;
@@ -29,7 +30,7 @@ function failOpenTagFor(code) {
29
30
  }
30
31
  }
31
32
  export function sanitizeTitle(raw) {
32
- const oneLine = raw.replace(/[\r\n]+/g, " ").replace(CONTROL_AND_BIDI_STRIP_RE, "").trim();
33
+ const oneLine = stripControlAndBidi(raw.replace(/[\r\n]+/g, " ")).trim();
33
34
  const unquoted = oneLine.replace(/^["'「『]+/, "").replace(/["'」』]+$/, "").trim();
34
35
  return unquoted.length > TITLE_MAX_CHARS ? `${unquoted.slice(0, TITLE_MAX_CHARS - 1)}…` : unquoted;
35
36
  }
@@ -45,8 +46,9 @@ export function buildTitlePrompt(objective) {
45
46
  }
46
47
  export function createSessionTitler(deps) {
47
48
  const seen = new Set();
49
+ const redactedError = (error) => redactSecrets(error);
48
50
  const logFailure = (sessionId, error, code) => {
49
- const safe = redactSecrets(error);
51
+ const safe = redactedError(error);
50
52
  deps.logger?.debug?.("session_title_failed", { sessionId, error: safe.slice(0, 200) });
51
53
  recordFailOpen(failOpenTagFor(code), safe.slice(0, FAIL_CAUSE_KEY_CHARS));
52
54
  };
@@ -55,7 +57,7 @@ export function createSessionTitler(deps) {
55
57
  .then((state) => ({ state, unreadable: false }))
56
58
  .catch(() => ({ state: continueWord, unreadable: true }));
57
59
  return {
58
- maybeTitle(sessionId, objective, model) {
60
+ maybeTitle(sessionId, objective, model, onTitled) {
59
61
  if (!sessionId || !userAuthoredText(objective))
60
62
  return;
61
63
  if (seen.has(sessionId))
@@ -104,6 +106,15 @@ export function createSessionTitler(deps) {
104
106
  seen.delete(sessionId);
105
107
  deps.metrics?.inc("session_title_total", { outcome: "set" });
106
108
  deps.logger?.info?.("session_titled", { sessionId, titleChars: title.length });
109
+ if (onTitled) {
110
+ try {
111
+ onTitled(buildSessionTitledFrame(sessionId, title));
112
+ }
113
+ catch (e) {
114
+ deps.metrics?.inc("session_title_total", { outcome: "frame_failed" });
115
+ deps.logger?.warn?.("session_titled_frame_failed", { sessionId, error: redactedError(String(e)).slice(0, 200) });
116
+ }
117
+ }
107
118
  })().catch((e) => {
108
119
  deps.metrics?.inc("session_title_total", { outcome: "error" });
109
120
  logFailure(sessionId, String(e));
@@ -1,6 +1,6 @@
1
1
  import { isThinkingLevel } from "@sema-agent/core";
2
2
  import { taskWallClockSec } from "./task-workflow.js";
3
- import { isAbsoluteHostPath } from "@sema-agent/settings-schema";
3
+ import { ABSOLUTE_HOST_PATH_MAX, isAbsoluteHostPath } from "@sema-agent/settings-schema";
4
4
  import { ruleEntryListShapeOk, skillToolListsOverCap } from "./rule-entry-list.js";
5
5
  import { describeLimit, limitFacts, limitRefusal } from "./limit-refusal.js";
6
6
  import { quotedCallerText } from "./caller-text-echo.js";
@@ -110,6 +110,23 @@ const skillOk = (s) => {
110
110
  }
111
111
  return true;
112
112
  };
113
+ const skillsLimit = (v) => {
114
+ if (!Array.isArray(v))
115
+ return undefined;
116
+ const j = v.findIndex((s) => !skillOk(s));
117
+ const s = j < 0 ? undefined : v[j];
118
+ if (!plainObject(s))
119
+ return undefined;
120
+ const content = s["content"];
121
+ const baseDir = s["baseDir"];
122
+ if (typeof content === "string" && content.length > MAX_AGENT_SKILL_CONTENT_CHARS) {
123
+ return { sub: `[${j}].content`, measure: "characters", count: content.length, cap: MAX_AGENT_SKILL_CONTENT_CHARS, keepShapeSentence: true };
124
+ }
125
+ if (typeof baseDir === "string" && baseDir.length > ABSOLUTE_HOST_PATH_MAX) {
126
+ return { sub: `[${j}].baseDir`, measure: "characters", count: baseDir.length, cap: ABSOLUTE_HOST_PATH_MAX, keepShapeSentence: true };
127
+ }
128
+ return undefined;
129
+ };
113
130
  const memoryOk = (v) => {
114
131
  if (!plainObject(v))
115
132
  return false;
@@ -140,6 +157,7 @@ const TASK_AGENT_FIELD_SHAPES = {
140
157
  skills: {
141
158
  desc: "an array of { name, description, content } skill objects (optional allowedTools/disallowedTools/files/baseDir; allowedTools/disallowedTools are arrays of strings; files entries need { path, content }; baseDir must be an absolute path with no \"..\" segment) — no count cap; the engine renders the listing within its own byte budget",
142
159
  ok: (v) => Array.isArray(v) && v.every(skillOk),
160
+ limit: skillsLimit,
143
161
  },
144
162
  background: { desc: "a boolean", ok: (v) => typeof v === "boolean" },
145
163
  isolation: { desc: '"worktree"', ok: (v) => v === "worktree" },
@@ -180,7 +198,8 @@ export function taskAgentIssue(item) {
180
198
  if (hit === undefined)
181
199
  return { message: `agent.${k} must be ${shape.desc}` };
182
200
  const rel = `${k}${hit.sub}`;
183
- return { message: describeLimit(`agent.${rel}`, hit.measure, hit.count, hit.cap), limit: { rel, measure: hit.measure, count: hit.count, cap: hit.cap } };
201
+ const limit = { rel, measure: hit.measure, count: hit.count, cap: hit.cap };
202
+ return hit.keepShapeSentence === true ? { message: `agent.${k} must be ${shape.desc}`, limit } : { message: describeLimit(`agent.${rel}`, hit.measure, hit.count, hit.cap), limit };
184
203
  }
185
204
  return null;
186
205
  }
@@ -60,7 +60,9 @@ export interface SqlEngineCapability {
60
60
  }
61
61
  /**
62
62
  * Boot 期建立引擎事实:借一条池连接(初始化随之跑),再原样归还。返回本池的**引擎读口**(驱动本身:方言 + 活的 `facts`)—— 事实由
63
- * 驱动持有,重连后它会被下一次初始化刷新,快照会说谎;方言与事实同出这一只,写入要装进的墙(`sqlWallsOf`)只读它。
63
+ * 驱动持有,重连后它会被下一次初始化刷新,快照会说谎;方言与事实同出这一只,写入要装进的墙(`sqlWallsOf`)只读它。读到的是**最近一次初始化的那条连接**的事实:隔离级 / 事务模式每条连接
64
+ * 同钉同验,所以就是池的事实;包墙 `maxPacketBytes` 是会话值、随连接不同,这里只是那一条连接的读数(池见过的最新读数 —— 只在有连接初始化时才更新,DBA 调了全局值之后、下一条连接初始化之前它仍是旧值;
65
+ * 运维读面与提交受理口的提前一跑读它),终判读将要执行写入的那条连接自己的读数(`sql-driver.ts` `connectJudged`)。
64
66
  *
65
67
  * 抛出 = 拒启:连接初始化拒绝了这个后端(TiDB 乐观模式设不成悲观、隔离级复核不符、服务器太旧读不出
66
68
  * `@@transaction_isolation`)。这条错**刻意不吞** —— 本仓所有 `FOR UPDATE` 判据都以它为前提。
package/dist/task-a2a.js CHANGED
@@ -1,7 +1,8 @@
1
- import { readToolAxes, resolveComplianceDenies } from "@sema-agent/core";
1
+ import { resolveComplianceDenies } from "@sema-agent/core";
2
2
  import { isUsableWireName } from "@sema-agent/settings-schema";
3
3
  import { HttpError } from "./security.js";
4
4
  import { readPlainStringRecord } from "./plain-string-record.js";
5
+ import { readRequestToolAxes } from "./request-tool-axes.js";
5
6
  import { echoKeyName } from "./request-key-closure.js";
6
7
  import { GOVERNANCE_HTTP_STATUS } from "./governance-http-status.js";
7
8
  export const MAX_REQUEST_A2A_PEERS = 32;
@@ -45,12 +46,12 @@ function normalizeA2aPeer(e, leg, storedToolAxes) {
45
46
  if (Array.isArray(o.allowSkills))
46
47
  spec.allowSkills = o.allowSkills;
47
48
  if (o.toolAxes !== undefined) {
48
- const axes = readToolAxes(o.toolAxes, "a2a");
49
+ const axes = readRequestToolAxes(o.toolAxes, "a2a");
49
50
  if (!axes.ok && storedToolAxes !== undefined) {
50
51
  const before = storedToolAxes.a2a(o.toolAxes);
51
52
  if (before === null)
52
53
  return dropped;
53
- const again = readToolAxes(before, "a2a");
54
+ const again = readRequestToolAxes(before, "a2a");
54
55
  if (!again.ok)
55
56
  return dropped;
56
57
  if (again.toolAxes !== undefined)
@@ -34,7 +34,7 @@ export declare function cwdHonored(config: {
34
34
  }): boolean;
35
35
  /**
36
36
  * S-377 —— 「**工具跑的那台机器**就是本进程这台吗」。回答的是一个**文件系统同一性**问题,不是权限问题:
37
- * server 盘上的一条绝对路径(出厂 `SKILLS_DIR` 下某个技能自己的目录)对模型的工具**有没有意义**。
37
+ * server 盘上的一条绝对路径(出厂 `SKILLS_DIR` 下、或中心 plugin 缓存里某个技能自己的目录)对模型的工具**有没有意义**。
38
38
  *
39
39
  * 判据 = 能力表两位的合取 {@link handsOnWorkerFilePlane}(`coreRemoteExecutionEnv ∧ hostFilePlane`,都读表,
40
40
  * 本函数不手写任何车道词):
@@ -158,13 +158,13 @@ export interface RequestMcpRefusal {
158
158
  * ② **键名**:条目层、或 `transport` 按 `kind` 那一形的键闭集之外的键 ⇒ `400 request.body_shape`,拒体带 `unknownKeys`(拼错的键被悄悄不读,同样读起来像生效了)。
159
159
  * ③ **身份头的键组合**(`principalHeader` 与 `assertionHeader` 同设 / `assertionHeader` 非串)⇒ {@link requestEntryIdentityRefusal}(同设那一句对契约包解析期原句逐字)。
160
160
  * ④ **受理键的值** ⇒ 逐键问判官表 {@link ENTRY_KEY_JUDGES},`400 request.field_invalid`,拒句点名 `mcpServers[i].<键路径>`、server 名与**该键判官的原因句**({@link entryFieldRefusal})。
161
- * 判官**就是读器用的那一只**,不是第二份:`toolAxes` = 引擎根导出的 `readMcpToolAxes`;`toolFaces` = `readMcpToolFaces`;`contentOrigin` = `isContentOriginWord`;`source` = `isMcpSourceLabel`;
162
- * `name` = `isUsableWireName`;`allowTools` / `transport.args` = {@link isStringArray};`transport.env` / `headers` = {@link readPlainStringRecord};`elicitation` = {@link isElicitationFlag};
163
- * `transport` 的硬字段(`kind` / `command` / `url`)与软字段(`args` / `env` / `headers` / `principalHeader`)= {@link readRequestTransport}(读器投影 transport 的那一只函数,门读它报的 `lost`)。
164
- * 判官只在引擎里、包根没给读口的键(今天只有 `startupTimeoutMs`)不在这里判,原样过境、由引擎在拨号时按 server 拒(不写第二份判据;到货读口即换)。
161
+ * 判官**就是读器用的那一只**,不是第二份:`toolAxes` = {@link readRequestToolAxes}(引擎根导出的 `readToolAxes` + 请求腿不收 `boundaryFlow`);`toolFaces` = 引擎根导出的 `readToolFaces`;
162
+ * `startupTimeoutMs` = 引擎根导出的 `mcpStartupTimeoutMs`(坏值抛 `config.mcp_startup_timeout_invalid`,本门把那一句作原因句);`contentOrigin` = `isContentOriginWord`;`source` = `isMcpSourceLabel`;
163
+ * `name` = `isUsableWireName`;`allowTools` / `transport.args` = {@link isStringArray};`transport.env` / `headers` = 契约包读器 {@link readRequestMcpTransport} 的纯数据记录读法;`elicitation` = {@link isElicitationFlag};
164
+ * `transport` 的硬字段(`kind` / `command` / `url`)与软字段(`args` / `env` / `headers` / `principalHeader`)= {@link readRequestMcpTransport}(读器投影 transport 的那一只函数,门读它报的 `lost`;读器在契约包,本仓只据 `lost[0]` 拒、据 `lost` 在重放腿逐处点名)。
165
165
  * 于是判官受理的条目,读器({@link normalizeServer})交回的就是申报本身(只差判官自己的合法归一:空容器 / `skillScopeEligible:false` 折成缺席、`toolAxes` 取引擎的拷贝)——
166
166
  * 探测口拨的那一份因此就是提交腿会挂的那一份,不另比一遍(另比就是第二只回答者)。唯一按门分的后果是「声明了 `assertionHeader`」这一个事实(引擎尚无座,
167
- * 承载、不发送):新提交照挂 + 运维 info,探测口整条拒 —— 判据是同一只谓词 `declaresMcpAssertionHeader`,不是第二份判法(见 `readMcpProbeBody`)。
167
+ * 承载、不发送):新提交照挂 + 运维 info,探测口整条拒 —— 判据是同一只谓词 `specWithholdsMcpAssertionHeader`(开关 `MCP_ASSERTION_HEADER_SENT` 假时「声明了」即「被扣下」),不是第二份判法(见 `readMcpProbeBody`)。
168
168
  *
169
169
  * ## 射程
170
170
  * 纯值域、与租户车道无关(一个写坏的请求在哪条车道上都是写坏的;多租户腿本来就忽略整只数组,告诉调用方「你写错了」只多不少)。
package/dist/task-mcp.js CHANGED
@@ -1,14 +1,11 @@
1
- import { mcpInjectionDroppedNotice, readMcpToolAxes, resolveComplianceDenies } from "@sema-agent/core";
2
- import { MCP_CONTENT_ORIGINS, describeNotStringArray, describeValueShape, isContentOriginWord, isStringArray, isUsableWireName, readMcpIdentityHeaders, } from "@sema-agent/settings-schema";
3
- import { describeBadContentOrigin, describeBadWireName } from "./caller-text-echo.js";
1
+ import { mcpInjectionDroppedNotice, mcpStartupTimeoutMs, readToolFaces, resolveComplianceDenies } from "@sema-agent/core";
2
+ import { MCP_CONTENT_ORIGINS, describeBadContentOrigin, describeBadWireName, describeNotStringArray, describeValueShape, isContentOriginWord, isStringArray, isUsableWireName, readRequestMcpTransport, stripControlAndBidi, } from "@sema-agent/settings-schema";
4
3
  import { HttpError, createCodedHttpError } from "./security.js";
5
4
  import { GOVERNANCE_HTTP_STATUS } from "./governance-http-status.js";
6
5
  import { MCP_SOURCE_LABEL_MAX, isMcpSourceLabel, readMcpSourceLabel } from "./mcp-source-label.js";
7
- import { declaresMcpAssertionHeader, describeMcpAssertionHeaderNotAString, describeMcpIdentityHeadersConflict, mcpIdentityHeadersIssue, noteMcpAssertionHeaderIgnored, noteMcpAssertionHeaderNotSent, toCoreMcpServerSpec } from "./mcp-assertion-header.js";
6
+ import { describeMcpAssertionHeaderNotAString, describeMcpIdentityHeadersConflict, mcpIdentityHeadersIssue, noteMcpAssertionHeaderIgnored, noteMcpAssertionHeaderNotSent, specWithholdsMcpAssertionHeader, toCoreMcpServerSpec } from "./mcp-assertion-header.js";
8
7
  import { MAX_KEY_ECHO, echoKeyName, keyClosureClause, scanKeyClosure } from "./request-key-closure.js";
9
- import { CONTROL_AND_BIDI_STRIP_RE } from "./text-bidi.js";
10
- import { readMcpToolFaces } from "./mcp-tool-faces.js";
11
- import { readPlainStringRecord } from "./plain-string-record.js";
8
+ import { readRequestToolAxes } from "./request-tool-axes.js";
12
9
  export const MAX_REQUEST_MCP_SERVERS = 32;
13
10
  export const MAX_REQUEST_MCP_DROP_NAMES = MAX_REQUEST_MCP_SERVERS;
14
11
  export const MCP_SERVER_ENTRY_KEYS = ["allowTools", "contentOrigin", "elicitation", "name", "source", "startupTimeoutMs", "toolAxes", "toolFaces", "transport"];
@@ -27,62 +24,6 @@ function isRecord(v) {
27
24
  function isElicitationFlag(v) {
28
25
  return typeof v === "boolean";
29
26
  }
30
- const transportBad = (path, reason) => ({ ok: false, issue: { path, reason } });
31
- function readRequestTransport(t) {
32
- if (!t || typeof t !== "object")
33
- return transportBad("transport", `must be an object with a "kind" of "stdio" or "http" — got ${describeValueShape(t)}`);
34
- const tr = t;
35
- const lost = [];
36
- if (tr.kind === "stdio") {
37
- if (typeof tr.command !== "string" || tr.command.length === 0)
38
- return transportBad("transport.command", `must be a non-empty string (the command to run) — got ${describeValueShape(tr.command)}`);
39
- if (tr.args !== undefined && !isStringArray(tr.args))
40
- lost.push({ path: "transport.args", reason: `must be an array of strings — got ${describeNotStringArray(tr.args)}` });
41
- const env = readTransportRecord("transport.env", tr.env, lost);
42
- return {
43
- ok: true,
44
- transport: {
45
- kind: "stdio",
46
- command: tr.command,
47
- ...(isStringArray(tr.args) ? { args: tr.args } : {}),
48
- ...(env !== undefined ? { env } : {}),
49
- },
50
- lost,
51
- };
52
- }
53
- if (tr.kind === "http") {
54
- if (typeof tr.url !== "string" || !/^https?:\/\//i.test(tr.url))
55
- return transportBad("transport.url", "must be an absolute http(s) URL (put credentials in transport.headers, never in the URL)");
56
- const ids = readMcpIdentityHeaders(tr);
57
- const headers = readTransportRecord("transport.headers", tr.headers, lost);
58
- if (tr.principalHeader !== undefined && ids.principalHeader === undefined) {
59
- lost.push({ path: "transport.principalHeader", reason: `must be a string (the HTTP header NAME the end-user principal is injected into) — got ${describeValueShape(tr.principalHeader)}` });
60
- }
61
- return {
62
- ok: true,
63
- transport: {
64
- kind: "http",
65
- url: tr.url,
66
- ...(headers !== undefined ? { headers } : {}),
67
- ...ids,
68
- },
69
- lost,
70
- };
71
- }
72
- return transportBad("transport.kind", `must be "stdio" or "http" — got ${describeValueShape(tr.kind)}`);
73
- }
74
- function readTransportRecord(path, raw, lost) {
75
- if (raw === undefined)
76
- return undefined;
77
- const read = readPlainStringRecord(raw);
78
- if (!read.ok) {
79
- lost.push({ path, reason: `must be a plain object of string values — ${read.member === undefined ? read.fault : `its member "${echoKeyName("", read.member)}" ${read.fault}`}` });
80
- return undefined;
81
- }
82
- for (const m of read.stripped)
83
- lost.push({ path: echoKeyName(`${path}.`, m.name), reason: m.fault });
84
- return read.record;
85
- }
86
27
  const bad = (field) => ({ ok: false, field });
87
28
  const MALFORMED_NAME = "<malformed>";
88
29
  function declaredName(e) {
@@ -96,7 +37,7 @@ function normalizeServer(e, noteBadOrigin, storedToolAxes) {
96
37
  const o = e;
97
38
  if (!isUsableWireName(o.name))
98
39
  return bad("name");
99
- const read = readRequestTransport(o.transport);
40
+ const read = readRequestMcpTransport(o.transport);
100
41
  if (!read.ok)
101
42
  return bad(read.issue.path);
102
43
  const spec = { name: o.name, transport: read.transport };
@@ -107,14 +48,14 @@ function normalizeServer(e, noteBadOrigin, storedToolAxes) {
107
48
  }
108
49
  if (isElicitationFlag(o.elicitation))
109
50
  spec.elicitation = o.elicitation;
110
- const axes = readMcpToolAxes(o.toolAxes);
51
+ const axes = readRequestToolAxes(o.toolAxes, "mcp");
111
52
  let judged = axes;
112
53
  let toolAxesReread;
113
54
  if (!axes.ok && storedToolAxes !== undefined) {
114
- const again = readMcpToolAxes(storedToolAxes.mcp(o.toolAxes));
55
+ const again = readRequestToolAxes(storedToolAxes.mcp(o.toolAxes), "mcp");
115
56
  if (again.ok) {
116
57
  judged = again;
117
- toolAxesReread = axes.problem.replace(CONTROL_AND_BIDI_STRIP_RE, "");
58
+ toolAxesReread = stripControlAndBidi(axes.problem);
118
59
  }
119
60
  }
120
61
  if (!judged.ok)
@@ -130,7 +71,7 @@ function normalizeServer(e, noteBadOrigin, storedToolAxes) {
130
71
  Object.assign(spec, readMcpSourceLabel(spec.name, o.source));
131
72
  if (o.startupTimeoutMs !== undefined)
132
73
  spec.startupTimeoutMs = o.startupTimeoutMs;
133
- const faces = readMcpToolFaces(o.toolFaces);
74
+ const faces = readToolFaces(o.toolFaces);
134
75
  if (!faces.ok)
135
76
  return bad("toolFaces");
136
77
  if (faces.faces !== undefined)
@@ -247,17 +188,29 @@ const ENTRY_KEY_JUDGES = {
247
188
  source: (o) => o.source === undefined || isMcpSourceLabel(o.source)
248
189
  ? undefined
249
190
  : { path: "source", reason: `must be a non-empty string of at most ${MCP_SOURCE_LABEL_MAX} characters (a display label) — got ${describeValueShape(o.source)}` },
250
- startupTimeoutMs: () => undefined,
191
+ startupTimeoutMs: (o) => {
192
+ if (o.startupTimeoutMs === undefined)
193
+ return undefined;
194
+ try {
195
+ mcpStartupTimeoutMs({ name: typeof o.name === "string" ? o.name : "", startupTimeoutMs: o.startupTimeoutMs });
196
+ return undefined;
197
+ }
198
+ catch (e) {
199
+ if (e.code !== "config.mcp_startup_timeout_invalid")
200
+ throw e;
201
+ return { path: "startupTimeoutMs", reason: e instanceof Error ? e.message : String(e) };
202
+ }
203
+ },
251
204
  toolAxes: (o) => {
252
- const read = readMcpToolAxes(o.toolAxes);
205
+ const read = readRequestToolAxes(o.toolAxes, "mcp");
253
206
  return read.ok ? undefined : { path: "toolAxes", reason: read.problem };
254
207
  },
255
208
  toolFaces: (o) => {
256
- const read = readMcpToolFaces(o.toolFaces);
209
+ const read = readToolFaces(o.toolFaces);
257
210
  return read.ok ? undefined : { path: "toolFaces", reason: read.problem };
258
211
  },
259
212
  transport: (o) => {
260
- const read = readRequestTransport(o.transport);
213
+ const read = readRequestMcpTransport(o.transport);
261
214
  return read.ok ? read.lost[0] : read.issue;
262
215
  },
263
216
  };
@@ -267,7 +220,7 @@ function entryFieldRefusal(entry, at, issue) {
267
220
  const server = echoKeyName("", declaredName(entry));
268
221
  return {
269
222
  errorCode: "request.field_invalid",
270
- message: `${at}.${issue.path} (server "${server}") is not a usable declaration — ${issue.reason.replace(CONTROL_AND_BIDI_STRIP_RE, "")}. ${ENTRY_REFUSAL_TAIL}`,
223
+ message: `${at}.${issue.path} (server "${server}") is not a usable declaration — ${stripControlAndBidi(issue.reason)}. ${ENTRY_REFUSAL_TAIL}`,
271
224
  };
272
225
  }
273
226
  function requestEntryRefusal(entry, at) {
@@ -341,7 +294,7 @@ function classifyHonored(baseline, entries, config, logger, storedToolAxes) {
341
294
  const closed = deploymentClosedMcpNames(baseline, reservedNames);
342
295
  const blocked = v.ok.filter((s) => closed.has(s.name)).map((s) => s.name);
343
296
  for (const s of v.ok)
344
- if (declaresMcpAssertionHeader(s) && !closed.has(s.name))
297
+ if (specWithholdsMcpAssertionHeader(s) && !closed.has(s.name))
345
298
  noteMcpAssertionHeaderNotSent(logger, s.name);
346
299
  const mounted = new Set(v.ok.filter((s) => !closed.has(s.name)).map((s) => s.name));
347
300
  for (const e of entries.slice(0, MAX_REQUEST_MCP_SERVERS)) {