@sema-agent/server 7.146.0 → 7.147.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 (398) hide show
  1. package/MIGRATION.md +384 -0
  2. package/README.md +1 -1
  3. package/README.zh-CN.md +1 -1
  4. package/USAGE.md +170 -66
  5. package/deploy/facts/lanes.json +7 -0
  6. package/deploy/sema-up/README.md +2 -2
  7. package/deploy/sema-up/chart/templates/_helpers.tpl +22 -0
  8. package/deploy/sema-up/chart/templates/server-v4pro.yaml +5 -4
  9. package/deploy/sema-up/chart/templates/server.yaml +5 -4
  10. package/deploy/sema-up/chart/values.yaml +1 -1
  11. package/deploy/sema-up/cluster-up.sh +2 -1
  12. package/deploy/sema-up/lib/flagshape.sh +4 -0
  13. package/deploy/sema-up/lib/lanes.json +2 -5
  14. package/deploy/sema-up/sema-up.sh +12 -9
  15. package/deploy/sema-up/stack/compose.yaml +5 -4
  16. package/deploy/sema-up/stack/sema-stack-cluster.yaml +4 -3
  17. package/dist/approval-card.d.ts +4 -4
  18. package/dist/approval.d.ts +3 -3
  19. package/dist/audit.js +2 -2
  20. package/dist/bench/s1/live-deps.js +3 -1
  21. package/dist/boot/crash-last.js +2 -1
  22. package/dist/boot/device-lane.js +5 -5
  23. package/dist/boot/engine-lease.d.ts +12 -11
  24. package/dist/boot/execution-env.d.ts +2 -1
  25. package/dist/boot/execution-env.js +45 -33
  26. package/dist/boot/execution-lane.d.ts +37 -9
  27. package/dist/boot/execution-lane.js +74 -20
  28. package/dist/boot/exit-boundary.d.ts +1 -1
  29. package/dist/boot/exit-last.js +2 -1
  30. package/dist/boot/governance-seams.d.ts +2 -2
  31. package/dist/boot/leader.js +1 -1
  32. package/dist/boot/memory-boundary.d.ts +11 -11
  33. package/dist/boot/memory-boundary.js +3 -3
  34. package/dist/boot/memory-consolidation.d.ts +13 -24
  35. package/dist/boot/memory-consolidation.js +0 -13
  36. package/dist/boot/org-memory.js +3 -2
  37. package/dist/boot/parked-revive-gate.d.ts +1 -1
  38. package/dist/boot/parked-revive-gate.js +1 -1
  39. package/dist/boot/reapers.js +1 -1
  40. package/dist/boot/resolve-spec.js +91 -111
  41. package/dist/boot/retention-lane.d.ts +4 -42
  42. package/dist/boot/session-faces.d.ts +1 -0
  43. package/dist/boot/session-faces.js +8 -2
  44. package/dist/boot/stage-01-config.d.ts +1 -1
  45. package/dist/boot/stage-01-config.js +6 -2
  46. package/dist/boot/stage-02-web-admin-pull.d.ts +1 -1
  47. package/dist/boot/stage-02-web-admin-pull.js +10 -8
  48. package/dist/boot/stage-03-store-backend.d.ts +1 -1
  49. package/dist/boot/stage-04-stores.d.ts +1 -1
  50. package/dist/boot/stage-05-execution-env.d.ts +2 -2
  51. package/dist/boot/stage-05-execution-env.js +3 -3
  52. package/dist/boot/stage-06-runners.d.ts +3 -3
  53. package/dist/boot/stage-06-runners.js +1 -3
  54. package/dist/boot/stage-07-capability-layer.d.ts +3 -3
  55. package/dist/boot/stage-07-capability-layer.js +4 -9
  56. package/dist/boot/stage-08-reapers.d.ts +3 -3
  57. package/dist/boot/stage-09-leader.d.ts +4 -3
  58. package/dist/boot/stage-10-http-server.d.ts +4 -3
  59. package/dist/boot/stage-10-http-server.js +2 -1
  60. package/dist/boot/stores.d.ts +9 -0
  61. package/dist/boot/stores.js +18 -7
  62. package/dist/boot/web-admin.js +3 -3
  63. package/dist/capabilities/center-plugins.d.ts +2 -0
  64. package/dist/capabilities/center-plugins.js +6 -2
  65. package/dist/capabilities/composite-members.d.ts +1 -0
  66. package/dist/capabilities/composite-members.js +1 -0
  67. package/dist/capabilities/execution-lane.d.ts +7 -7
  68. package/dist/capabilities/execution-lane.js +2 -2
  69. package/dist/capabilities/hands-lane.d.ts +1 -1
  70. package/dist/capabilities/scenarios.d.ts +32 -18
  71. package/dist/capabilities/scenarios.js +13 -9
  72. package/dist/capabilities/settings-contract.d.ts +29 -0
  73. package/dist/capabilities/settings-contract.js +14 -0
  74. package/dist/capabilities/skills.d.ts +5 -5
  75. package/dist/capability-facts.d.ts +38 -0
  76. package/dist/capability-facts.js +34 -1
  77. package/dist/center-credential-renewer.js +3 -2
  78. package/dist/config-catalog.js +6 -5
  79. package/dist/config-invariants.d.ts +18 -3
  80. package/dist/config-invariants.js +36 -19
  81. package/dist/config-lkg.d.ts +1 -1
  82. package/dist/config-lkg.js +5 -6
  83. package/dist/config-provider.js +2 -0
  84. package/dist/config-types.d.ts +190 -186
  85. package/dist/config.d.ts +68 -5
  86. package/dist/config.js +80 -54
  87. package/dist/degenerate-instrument.js +1 -1
  88. package/dist/deploy-facts.js +3 -2
  89. package/dist/deployment-shape.d.ts +21 -12
  90. package/dist/deployment-shape.js +24 -6
  91. package/dist/env-facts.d.ts +7 -5
  92. package/dist/env-facts.js +10 -6
  93. package/dist/execution-config-root.d.ts +5 -5
  94. package/dist/execution-config-root.js +5 -5
  95. package/dist/execution-env-purpose.d.ts +14 -0
  96. package/dist/execution-env-purpose.js +29 -0
  97. package/dist/execution-lane-caps.d.ts +49 -86
  98. package/dist/execution-lane-caps.js +52 -62
  99. package/dist/execution-placement.d.ts +18 -2
  100. package/dist/execution-placement.js +19 -0
  101. package/dist/file-history-disclosure.d.ts +2 -2
  102. package/dist/fleet/drain-entry.d.ts +17 -10
  103. package/dist/fleet/drain-entry.js +1 -1
  104. package/dist/fleet/serving-lease.js +3 -4
  105. package/dist/history-anchor.d.ts +22 -0
  106. package/dist/history-anchor.js +14 -0
  107. package/dist/hooks/command-spawn.d.ts +1 -4
  108. package/dist/hooks/command-spawn.js +0 -11
  109. package/dist/hooks/hook-runner.d.ts +52 -8
  110. package/dist/hooks/hook-runner.js +160 -36
  111. package/dist/http/approval-sweeps.d.ts +2 -5
  112. package/dist/http/approval-sweeps.js +3 -2
  113. package/dist/http/checkpoint-ctx.d.ts +17 -0
  114. package/dist/http/checkpoint-ctx.js +6 -0
  115. package/dist/http/claim-latency.d.ts +10 -0
  116. package/dist/http/claim-latency.js +12 -0
  117. package/dist/http/dispatch.js +1 -1
  118. package/dist/http/durable-run-leg.js +2 -1
  119. package/dist/http/execution-context.d.ts +3 -1
  120. package/dist/http/execution-context.js +4 -0
  121. package/dist/http/memory-compliance-failure-reply.d.ts +1 -1
  122. package/dist/http/memory-compliance-failure-reply.js +3 -0
  123. package/dist/http/memory-store-refusal-reply.d.ts +3 -3
  124. package/dist/http/memory-store-refusal-reply.js +3 -0
  125. package/dist/http/owner-access.d.ts +11 -0
  126. package/dist/http/owner-access.js +7 -4
  127. package/dist/http/principal-gate.d.ts +3 -14
  128. package/dist/http/principal-gate.js +0 -13
  129. package/dist/http/request-guards.d.ts +1 -1
  130. package/dist/http/resume-legs.d.ts +7 -10
  131. package/dist/http/resume-legs.js +79 -50
  132. package/dist/http/rewind-files-reply.d.ts +34 -0
  133. package/dist/http/rewind-files-reply.js +36 -0
  134. package/dist/http/route-ctx.d.ts +32 -16
  135. package/dist/http/route-table.js +2 -0
  136. package/dist/http/routes/approvals-assistant.js +5 -25
  137. package/dist/http/routes/capabilities.js +8 -2
  138. package/dist/http/routes/devices.js +1 -1
  139. package/dist/http/routes/memory-origin.d.ts +1 -1
  140. package/dist/http/routes/notify-wake.js +2 -1
  141. package/dist/http/routes/projects.d.ts +70 -0
  142. package/dist/http/routes/projects.js +86 -0
  143. package/dist/http/routes/rules.js +30 -2
  144. package/dist/http/routes/runs.js +8 -8
  145. package/dist/http/routes/session-sync.js +27 -10
  146. package/dist/http/routes/sessions.d.ts +7 -1
  147. package/dist/http/routes/sessions.js +104 -2
  148. package/dist/http/routes/tasks.js +9 -3
  149. package/dist/http/server.d.ts +24 -10
  150. package/dist/http/server.js +17 -6
  151. package/dist/http/stored-body-replay.d.ts +5 -3
  152. package/dist/http/stored-body-replay.js +10 -1
  153. package/dist/http/wire-types.d.ts +19 -10
  154. package/dist/index.d.ts +2 -2
  155. package/dist/index.js +1 -1
  156. package/dist/instruction-source-notice.d.ts +1 -1
  157. package/dist/memory-embedder-reembed.d.ts +38 -0
  158. package/dist/memory-embedder-reembed.js +20 -0
  159. package/dist/memory-incident-sink.d.ts +0 -28
  160. package/dist/memory-incident-sink.js +5 -0
  161. package/dist/memory-scope.d.ts +2 -2
  162. package/dist/memory-scope.js +1 -1
  163. package/dist/memory-store-refusal.d.ts +17 -4
  164. package/dist/memory-store-refusal.js +1 -1
  165. package/dist/memory-sync-client.d.ts +2 -0
  166. package/dist/memory-sync-client.js +13 -11
  167. package/dist/memory-sync.js +1 -1
  168. package/dist/model-compat.d.ts +35 -21
  169. package/dist/model-compat.js +49 -21
  170. package/dist/model-entry-refusal.d.ts +11 -1
  171. package/dist/model-entry-refusal.js +7 -0
  172. package/dist/namespaced-rule-name.d.ts +18 -1
  173. package/dist/namespaced-rule-name.js +12 -0
  174. package/dist/observability/fail-open.d.ts +17 -9
  175. package/dist/observability/fail-open.js +17 -9
  176. package/dist/observability/metrics.d.ts +2 -0
  177. package/dist/observability/metrics.js +2 -0
  178. package/dist/observability/secret-env-scrub.d.ts +30 -4
  179. package/dist/observability/secret-env-scrub.js +15 -3
  180. package/dist/orchestration/workflow-agent-session-index.d.ts +7 -12
  181. package/dist/orchestration/workflow-agent-session-index.js +1 -6
  182. package/dist/orchestration/workflow-completion-inbox.d.ts +26 -6
  183. package/dist/orchestration/workflow-completion-inbox.js +63 -45
  184. package/dist/org-memory-admission.d.ts +5 -2
  185. package/dist/org-memory-admission.js +25 -10
  186. package/dist/parked-decide.d.ts +33 -26
  187. package/dist/parked-decide.js +36 -44
  188. package/dist/plugins/approval-ask-store-file.d.ts +10 -2
  189. package/dist/plugins/approval-ask-store-file.js +37 -4
  190. package/dist/plugins/approval-ask-store-memory.d.ts +5 -3
  191. package/dist/plugins/approval-ask-store-memory.js +11 -2
  192. package/dist/plugins/approval-ask-store-sql.d.ts +3 -0
  193. package/dist/plugins/approval-ask-store-sql.js +3 -1
  194. package/dist/plugins/blob-backend.d.ts +38 -195
  195. package/dist/plugins/blob-backend.js +33 -229
  196. package/dist/plugins/caching-session-store.d.ts +9 -4
  197. package/dist/plugins/checkpoint-index-columns.d.ts +1 -1
  198. package/dist/plugins/checkpoint-index-columns.js +3 -2
  199. package/dist/plugins/checkpoint-store-face.d.ts +1 -1
  200. package/dist/plugins/device-store-sql.d.ts +2 -2
  201. package/dist/plugins/device-store-sql.js +5 -10
  202. package/dist/plugins/execution-lane-rename-m40.d.ts +20 -0
  203. package/dist/plugins/execution-lane-rename-m40.js +10 -0
  204. package/dist/plugins/execution-placement-sql.d.ts +63 -88
  205. package/dist/plugins/execution-placement-sql.js +94 -54
  206. package/dist/plugins/file-run-store.d.ts +26 -12
  207. package/dist/plugins/file-run-store.js +63 -63
  208. package/dist/plugins/imported-layer-root-retirement.d.ts +17 -8
  209. package/dist/plugins/imported-layer-root-retirement.js +4 -8
  210. package/dist/plugins/inbox-payload-column.d.ts +14 -0
  211. package/dist/plugins/inbox-payload-column.js +13 -0
  212. package/dist/plugins/local-checkpoint-store.d.ts +5 -0
  213. package/dist/plugins/local-checkpoint-store.js +11 -7
  214. package/dist/plugins/local-data-dir-modes-m39.d.ts +48 -0
  215. package/dist/plugins/local-data-dir-modes-m39.js +182 -0
  216. package/dist/plugins/local-engine-high-water.d.ts +11 -0
  217. package/dist/plugins/local-engine-high-water.js +59 -0
  218. package/dist/plugins/local-session-store.d.ts +91 -25
  219. package/dist/plugins/local-session-store.js +124 -45
  220. package/dist/plugins/local-task-attachment-store.d.ts +2 -0
  221. package/dist/plugins/local-task-attachment-store.js +10 -11
  222. package/dist/plugins/memory-embedder-fingerprint.d.ts +33 -10
  223. package/dist/plugins/memory-embedder-fingerprint.js +52 -12
  224. package/dist/plugins/memory-embedder.d.ts +1 -1
  225. package/dist/plugins/memory-embedder.js +2 -2
  226. package/dist/plugins/memory-engine-pg.d.ts +4 -3
  227. package/dist/plugins/memory-engine-pg.js +4 -4
  228. package/dist/plugins/memory-engine-sql-apply.d.ts +13 -4
  229. package/dist/plugins/memory-engine-sql-apply.js +1 -1
  230. package/dist/plugins/memory-engine-tidb.d.ts +8 -5
  231. package/dist/plugins/memory-engine-tidb.js +7 -8
  232. package/dist/plugins/one-time-migrations.d.ts +145 -35
  233. package/dist/plugins/one-time-migrations.js +272 -120
  234. package/dist/plugins/owner-only-file-mode.d.ts +29 -0
  235. package/dist/plugins/owner-only-file-mode.js +141 -0
  236. package/dist/plugins/permission-rule-store-file.d.ts +8 -8
  237. package/dist/plugins/permission-rule-store-file.js +14 -2
  238. package/dist/plugins/pg-pool.d.ts +2 -1
  239. package/dist/plugins/pg-pool.js +11 -4
  240. package/dist/plugins/release-version.d.ts +20 -0
  241. package/dist/plugins/release-version.js +28 -0
  242. package/dist/plugins/remote-env-adb.d.ts +20 -4
  243. package/dist/plugins/remote-env-adb.js +39 -11
  244. package/dist/plugins/remote-env-e2b.d.ts +12 -3
  245. package/dist/plugins/remote-env-e2b.js +6 -4
  246. package/dist/plugins/remote-env-host.d.ts +9 -1
  247. package/dist/plugins/remote-env-host.js +6 -5
  248. package/dist/plugins/remote-env-k8s.d.ts +5 -2
  249. package/dist/plugins/remote-env-k8s.js +15 -4
  250. package/dist/plugins/remote-env-local-docker.d.ts +4 -1
  251. package/dist/plugins/remote-env-local-docker.js +3 -3
  252. package/dist/plugins/remote-env-ssh.d.ts +8 -2
  253. package/dist/plugins/remote-env-ssh.js +26 -24
  254. package/dist/plugins/remote-shell.d.ts +59 -30
  255. package/dist/plugins/remote-shell.js +175 -62
  256. package/dist/plugins/retention-declaration.d.ts +37 -0
  257. package/dist/plugins/retention-declaration.js +9 -0
  258. package/dist/plugins/retention-deployment.d.ts +126 -0
  259. package/dist/plugins/retention-deployment.js +88 -0
  260. package/dist/plugins/retention-lane-store-sql.d.ts +74 -4
  261. package/dist/plugins/retention-lane-store-sql.js +103 -1
  262. package/dist/plugins/retention-sql.d.ts +29 -0
  263. package/dist/plugins/retention-sql.js +8 -0
  264. package/dist/plugins/schema-consistency.d.ts +0 -6
  265. package/dist/plugins/schema-consistency.js +1 -2
  266. package/dist/plugins/schema-ensure-legs.d.ts +1 -1
  267. package/dist/plugins/schema-ensure-legs.js +11 -1
  268. package/dist/plugins/session-ext-table.d.ts +74 -0
  269. package/dist/plugins/session-ext-table.js +121 -0
  270. package/dist/plugins/session-fork.d.ts +1 -1
  271. package/dist/plugins/session-row-sql.d.ts +8 -7
  272. package/dist/plugins/session-row-sql.js +15 -7
  273. package/dist/plugins/session-store-sql.d.ts +131 -0
  274. package/dist/plugins/session-store-sql.js +298 -0
  275. package/dist/plugins/session-workspace-cell.d.ts +2 -2
  276. package/dist/plugins/session-workspace-cell.js +2 -2
  277. package/dist/plugins/shared-memory-store-sql.d.ts +10 -0
  278. package/dist/plugins/shared-memory-store-sql.js +13 -13
  279. package/dist/plugins/snapshot-bucket-presence.js +1 -1
  280. package/dist/plugins/sql-driver.d.ts +23 -7
  281. package/dist/plugins/sql-driver.js +41 -8
  282. package/dist/plugins/sql-errors.d.ts +5 -2
  283. package/dist/plugins/sql-errors.js +4 -0
  284. package/dist/plugins/store-backend.d.ts +35 -8
  285. package/dist/plugins/store-backend.js +184 -62
  286. package/dist/plugins/store-contracts.d.ts +9 -2
  287. package/dist/plugins/store-contracts.js +1 -0
  288. package/dist/plugins/task-attachment-store.d.ts +6 -8
  289. package/dist/plugins/task-attachment-store.js +15 -10
  290. package/dist/plugins/task-list-store-sql.d.ts +1 -1
  291. package/dist/plugins/text-column-capacity.d.ts +21 -0
  292. package/dist/plugins/text-column-capacity.js +5 -0
  293. package/dist/plugins/tidb-pool.d.ts +3 -2
  294. package/dist/plugins/tidb-pool.js +19 -31
  295. package/dist/plugins/user-input-ledger-sql.d.ts +1 -1
  296. package/dist/read-face-posture.d.ts +6 -6
  297. package/dist/read-face-posture.js +2 -2
  298. package/dist/request-value-closure.d.ts +5 -5
  299. package/dist/request-value-closure.js +1 -1
  300. package/dist/rules-consent.d.ts +41 -13
  301. package/dist/rules-consent.js +101 -53
  302. package/dist/run-local.js +17 -13
  303. package/dist/runs.d.ts +48 -30
  304. package/dist/runs.js +26 -16
  305. package/dist/runtime-caps-resolver.d.ts +15 -8
  306. package/dist/runtime-caps-resolver.js +14 -10
  307. package/dist/sealed-key-layout.d.ts +2 -3
  308. package/dist/sealed-key-layout.js +0 -1
  309. package/dist/sealed-key.js +7 -5
  310. package/dist/security.d.ts +5 -3
  311. package/dist/sema-config-dir.js +2 -2
  312. package/dist/server-secret-env.d.ts +2 -0
  313. package/dist/service-version.d.ts +2 -1
  314. package/dist/service-version.js +2 -2
  315. package/dist/session-error-wire.d.ts +1 -1
  316. package/dist/session-incarnation.d.ts +8 -5
  317. package/dist/session-resident-background.d.ts +85 -32
  318. package/dist/session-resident-background.js +75 -7
  319. package/dist/session-row.d.ts +1 -1
  320. package/dist/session-sync-kernel.d.ts +1 -1
  321. package/dist/session-workspace.d.ts +11 -2
  322. package/dist/session-workspace.js +5 -0
  323. package/dist/sighup-idle.d.ts +1 -1
  324. package/dist/store-posture.d.ts +2 -1
  325. package/dist/stored-request-hooks-m20.d.ts +3 -2
  326. package/dist/stored-request-hooks-m20.js +19 -14
  327. package/dist/stores-sql/blob-index-sql.d.ts +148 -0
  328. package/dist/stores-sql/blob-index-sql.js +154 -0
  329. package/dist/stores-sql/checkpoint-store-sql.d.ts +1 -1
  330. package/dist/stores-sql/checkpoint-store-sql.js +11 -27
  331. package/dist/{plugins → stores-sql}/file-history-store-sql.d.ts +23 -11
  332. package/dist/{plugins → stores-sql}/file-history-store-sql.js +23 -18
  333. package/dist/{plugins → stores-sql}/pg-session-storage.d.ts +23 -76
  334. package/dist/{plugins → stores-sql}/pg-session-storage.js +80 -209
  335. package/dist/{plugins → stores-sql}/retention-store-sql.d.ts +123 -217
  336. package/dist/{plugins → stores-sql}/retention-store-sql.js +66 -190
  337. package/dist/{plugins → stores-sql}/session-event-payload.d.ts +1 -1
  338. package/dist/{plugins → stores-sql}/session-event-payload.js +1 -1
  339. package/dist/stores-sql/session-policy-store-sql.d.ts +1 -1
  340. package/dist/stores-sql/session-write-hooks.d.ts +59 -0
  341. package/dist/stores-sql/session-write-hooks.js +2 -0
  342. package/dist/{plugins → stores-sql}/tidb-session-storage.d.ts +10 -11
  343. package/dist/{plugins → stores-sql}/tidb-session-storage.js +10 -21
  344. package/dist/{plugins → stores-sql}/tidb-session-store.d.ts +32 -122
  345. package/dist/{plugins → stores-sql}/tidb-session-store.js +71 -171
  346. package/dist/stores-sql/tool-result-store-sql.d.ts +1 -1
  347. package/dist/stores-sql/tool-result-store-sql.js +1 -1
  348. package/dist/stores-sql/windowed-session-storage.d.ts +56 -0
  349. package/dist/stores-sql/windowed-session-storage.js +61 -0
  350. package/dist/task-a2a.d.ts +7 -1
  351. package/dist/task-a2a.js +15 -14
  352. package/dist/task-cwd.d.ts +11 -3
  353. package/dist/task-cwd.js +17 -1
  354. package/dist/task-mcp.d.ts +10 -2
  355. package/dist/task-mcp.js +13 -16
  356. package/dist/task-settings.d.ts +9 -4
  357. package/dist/task-settings.js +17 -6
  358. package/dist/tool-approval.d.ts +21 -8
  359. package/dist/tool-approval.js +10 -6
  360. package/dist/trace/core-keyset-guard.d.ts +9 -3
  361. package/dist/trace/engine-notice-wire.d.ts +1 -1
  362. package/dist/trace/engine-notice-wire.js +2 -0
  363. package/dist/trace/exit-seat.d.ts +23 -1
  364. package/dist/trace/exit-seat.js +3 -0
  365. package/dist/trace/project.d.ts +33 -16
  366. package/dist/trace/project.js +12 -9
  367. package/dist/trace/redact.d.ts +1 -1
  368. package/dist/trace/redact.js +61 -73
  369. package/dist/trace/self-minted-wire.d.ts +263 -10
  370. package/dist/trace/self-minted-wire.js +90 -2
  371. package/dist/trace/sema-provenance.d.ts +45 -41
  372. package/dist/trace/sema-provenance.js +81 -10
  373. package/dist/trace/task-notification-facets.d.ts +70 -2
  374. package/dist/trace/task-notification-facets.js +71 -1
  375. package/dist/trace/wire-projection-faces.d.ts +38 -2
  376. package/dist/trace/wire-projection-faces.js +26 -1
  377. package/dist/unread-request-members.d.ts +66 -0
  378. package/dist/unread-request-members.js +41 -0
  379. package/dist/user-input-ledger.d.ts +2 -2
  380. package/dist/web-admin-client/apply-effective.js +22 -26
  381. package/dist/web-admin-client/candidate-gate.d.ts +35 -3
  382. package/dist/web-admin-client/candidate-gate.js +53 -5
  383. package/dist/web-admin-client/center-request.d.ts +4 -1
  384. package/dist/web-admin-client/center-request.js +2 -1
  385. package/dist/web-admin-client/effective-keys.js +0 -1
  386. package/dist/web-admin-client/facade.d.ts +1 -1
  387. package/dist/web-admin-client/http-client.d.ts +1 -0
  388. package/dist/web-admin-client/http-client.js +17 -9
  389. package/dist/web-admin-client/restart-signal.js +5 -2
  390. package/dist/web-admin-client/skills-mcp.d.ts +20 -6
  391. package/dist/web-admin-client/skills-mcp.js +26 -21
  392. package/dist/web-admin-client/types.d.ts +34 -49
  393. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +2 -2
  394. package/package.json +13 -12
  395. package/scripts/drain-check-local.mjs +2 -28
  396. package/scripts/drain-check.mysql.sql +2 -18
  397. package/scripts/drain-check.pg.sql +2 -18
  398. package/wire-changes/server@7.147.0.json +813 -0
@@ -19,7 +19,7 @@ import type { HostDecision } from "../host-decision.js";
19
19
  import type { EntryProblem } from "../entry-problems.js";
20
20
  import type { SessionOwnerCell } from "../security.js";
21
21
  import type { SessionNotifyDoor } from "../session-notify-door.js";
22
- import type { TaskStream, TaskSpec, TaskResult, QuestionAnswer, Checkpoint, CheckpointToken, ResumeOutcome, RunInternals, Runner, EngineNotice } from "@sema-agent/core";
22
+ import type { TaskStream, TaskSpec, TaskResult, QuestionAnswer, Checkpoint, CheckpointToken, ResumeOutcome, RunInternals, Runner, EngineNotice, PendingSteerInput } from "@sema-agent/core";
23
23
  import type { FlatServiceDeps, RequestAuth } from "./server.js";
24
24
  import type { TaskRequestBody, DecideBinding } from "./wire-types.js";
25
25
  import type { IdempotencyCache, SubmitOutcome } from "./idempotency.js";
@@ -36,6 +36,7 @@ import type { PeerLease } from "../peer-seat.js";
36
36
  import type { RootedTaskSpec } from "./execution-context.js";
37
37
  import type { GateCommitment, GateSettlementEvidence } from "../gate-settlement.js";
38
38
  import type { ResumeRestatement } from "./resume-restatement.js";
39
+ import type { RememberLaneCannotRecord } from "../parked-decide.js";
39
40
  /** 跨域可变状态 = lens1 §C2 实测的那 8 条「运行期登记簿」,一个对象。
40
41
  * [ref]:`cancelledViaVerb`(按 taskId 键控的「这次是取消动词」旁表)删除 —— 中止成因改挂在每条腿自己的
41
42
  * {@link RunAbort} 句柄上(`inflightRuns` 的值),同寿同删,不再有一张与腿不同寿的旁表。 */
@@ -421,6 +422,7 @@ export interface PreparedPlanReview {
421
422
  readonly sessionId: string;
422
423
  readonly token: CheckpointToken;
423
424
  readonly cp: Checkpoint;
425
+ /** 这条决断唯一的一次 ctx 读,**已盖过**续跑请求的重述键(缺席 = 存量体原样):存体预判判的、驱动段重建与写回读的都是这一份。 */
424
426
  readonly ctx: CheckpointCtx;
425
427
  }
426
428
  /** 提交/续跑「腿」= 跨域共享的**有状态**长流程(不像 {@link RouteHelpers} 那样只依赖 deps/config:它们要写
@@ -459,14 +461,8 @@ export interface RouteLegs {
459
461
  /** 这次决定落在哪一个动作上:调用方点名它看到的那一对(`boundCallId` + `boundInputHash`);缺任一 ⇒ 400 `decide_requires_binding`
460
462
  * (判在门型守卫之后,判官 `decidedActionOf`)。本函数从不拿当前停驻行补。 */
461
463
  binding: DecideBinding,
462
- /** [ref] codex R4(验真后修):remember 豁免的 grant 挂点。**工具名不再由路由自己读**(那是与本函数
463
- * 载入行分歧的第三次 scope-less 读,三读分歧下会给他人工具落豁免=提权)——由本函数把**已属主校验的
464
- * 载入 cp** 的可记工具名(`rememberableToolName`,非 tool_approval / AskUserQuestion / legacy null / [ref] 强制卡 ⇒ `null`
465
- * = 无可记)一并回传,路由只对这个逐字落店。`overrideSessionId` = parked 腿的 root/host 会话 grant 锚。 */
466
- onResumeCommitted?: (grant: {
467
- overrideSessionId?: string;
468
- rememberableToolName: string | null;
469
- }) => Promise<void>,
464
+ /** 这次决定带着「本会话放行」请求({@link RememberSessionRequest})⇒ 本函数是它的**唯一铸点**,结局的 `rememberApplied` 是它的答({@link ResumeCheckpointOutcome})。 */
465
+ remember?: RememberSessionRequest,
470
466
  /** [ref]:透传给 {@link DriveResumeArgs.acceptEarly}(200 受理语义)。HTTP `/decide` 腿传 `true`;
471
467
  * 内部 D-D SLA deny-sweep 不传 —— 它没有在等响应的人,提前受理对它零收益而少一条同步失败面。 */
472
468
  acceptEarly?: boolean,
@@ -477,7 +473,7 @@ export interface RouteLegs {
477
473
  explicitOperator: boolean;
478
474
  },
479
475
  /** 续跑请求的重述键(`mcpServers` / `a2aPeers`),门读出并判过的那一份;缺席 = 冻结读法。语义属主 = `resume-restatement.ts` 顶注。 */
480
- restatement?: ResumeRestatement): Promise<ResumeLegOutcome>;
476
+ restatement?: ResumeRestatement): Promise<ResumeCheckpointOutcome>;
481
477
  /** 全 resume 家族的共同下半场(lease admission + 写 run log + fleet 发布)。 */
482
478
  driveResumeIntoRunLog(args: DriveResumeArgs): Promise<ResumeLegOutcome>;
483
479
  /** assistant 抢占腿的复位(gate-kind 守卫 + 行级属主复核 + 驱动)。 */
@@ -493,7 +489,9 @@ export interface RouteLegs {
493
489
  /** 续跑请求的重述键(同 {@link RouteLegs.resumeCheckpoint} 末参)。 */
494
490
  restatement?: ResumeRestatement): Promise<ResumeLegOutcome>;
495
491
  /** notify-wake 域:唤醒一条 parked checkpoint。 */
496
- resumeWake(sessionId: string, message: string | undefined, caller: string | undefined, req: IncomingMessage | undefined,
492
+ resumeWake(sessionId: string,
493
+ /** 续跑首轮那段话连同框架位,由文本出处在铸点定好(HTTP `/wake` 正文 ⇒ `trusted: false`);语义属主 = `resume-legs.ts` 同名形参顶注。 */
494
+ message: PendingSteerInput | undefined, caller: string | undefined, req: IncomingMessage | undefined,
497
495
  /** [ref] 件 S-1:透传给 {@link DriveResumeArgs.acceptEarly}(200 受理语义)。HTTP `/wake` 腿传 `true`
498
496
  * —— 本腿走 `mintFreshRun`,受理体里的 `taskId` 因此是**新铸的**那个(壳的 poll 锚)。 */
499
497
  acceptEarly?: boolean,
@@ -522,7 +520,9 @@ export interface RouteLegs {
522
520
  explicitOperator: boolean;
523
521
  },
524
522
  /** [ref]:决断方看到的那道门(决断体的 `checkpointId`);不是当前门 ⇒ `409 approval_stale`(`approval_stale` 律,语义属主 = `resume-legs.ts` 的同名形参顶注)。 */
525
- sighting?: GateSighting): Promise<{
523
+ sighting?: GateSighting,
524
+ /** 续跑请求的重述键(同 {@link RouteLegs.resumeCheckpoint} 末参):盖在这一次 ctx 读上,存体预判按盖过的体判。 */
525
+ restatement?: ResumeRestatement): Promise<{
526
526
  readonly ok: false;
527
527
  readonly answer: {
528
528
  status: number;
@@ -540,9 +540,7 @@ export interface RouteLegs {
540
540
  acceptEarly?: boolean,
541
541
  /** [ref]:批准之后这条会话继续用的 permission mode(闭集 `PLAN_APPROVE_PERMISSION_MODES_AFTER`;只在把计划带出 plan 的决定
542
542
  * —— `approve` / `edit` —— 上有意义,缺席 ⇒ `"default"`)。语义与判据的唯一属主 = `resume-legs.ts` 的同名形参顶注。 */
543
- permissionModeAfter?: PlanApprovePermissionModeAfter,
544
- /** 续跑请求的重述键(同 {@link RouteLegs.resumeCheckpoint} 末参)。 */
545
- restatement?: ResumeRestatement): Promise<ResumeLegOutcome>;
543
+ permissionModeAfter?: PlanApprovePermissionModeAfter): Promise<ResumeLegOutcome>;
546
544
  /** 会话通知门(`POST /v1/sessions/:id/notify` 与 Runner 之外的后台子代完成共用的那一只;活流登记簿是本服务的,门随服务建一次)。 */
547
545
  sessionNotify: SessionNotifyDoor;
548
546
  }
@@ -694,7 +692,7 @@ interface RouteDeclIdentity {
694
692
  readonly methods: readonly RouteMethod[];
695
693
  /**
696
694
  * 「这条 GET 开的是一条**只读订阅**」—— 一条 SSE 读面(推送队列 / 账本 tail),它看着别人干活,自己不是活([ref])。
697
- * 在场 ⇒ 分派器不把它记进在飞(`drainState.inflight()`:排空等的、`/health` 报的、SIGHUP 空闲窗与附着租约读的那一只),只记进附着
695
+ * 在场 ⇒ 分派器不把它记进在飞(`http` 项:`/health.inflight` 报的总数与排空等的、SIGHUP 空闲窗与附着租约读的阻断集都从它起算),只记进附着
698
696
  * (`attachedStreams()`:壳还挂在这只引擎上);排空进入那一拍(以及硬停起点)由分派器发一帧 `draining` 终帧后关掉它
699
697
  * (`drainState.endSubscriptions`)。闭集 = 八条 GET SSE 读面,逐行理由见各行注;**唯一**一条「在飞腿的流」`POST /v1/tasks/stream`
700
698
  * 不带它 —— 那条流就是 sync 腿本身(关流 = 断连语义),照旧算在飞。漏标一条订阅的方向是**多算在飞**(排空多等),不是少等。
@@ -740,6 +738,24 @@ export interface ResumeLegOutcome {
740
738
  status: number;
741
739
  body: object;
742
740
  }
741
+ /**
742
+ * 「本会话不再询问」的请求 —— **两扇门同一只**:`/decide` 体上的 `remember:"session"`、应答口(`POST /v1/tool-approvals/:id/respond`)命中停驻行的
743
+ * `allow_session`。铸点只有一只:{@link RouteLegs.resumeCheckpoint} —— 可记与否从**已属主校验的载入停驻行**判(`standingAnswerDurablyRecordable`,
744
+ * 与运维队列行的 `rememberRefused` 同一只判据)、锚由车道定(任务级 = 这个会话;bg 停驻子代 = 行的 root/host 会话)、落豁免店**只在**这次决定
745
+ * 被证明已结清之后(`decisionCommittedOf`)、`rememberApplied` = 落没落(店抛 ⇒ `false` + warn,这次的放行不回滚)。门自己不写店、不判可记。
746
+ * 两口唯一的差 = `laneCannotRecord`(记不住的车道上怎么答;闭集与理由的属主 = `parked-decide.ts` 的 {@link RememberLaneCannotRecord})。
747
+ */
748
+ export interface RememberSessionRequest {
749
+ /** 豁免行的签发人(`grantedBy`)= 门已验的身份(`/decide` 的决断方 / 应答口的调用方);匿名开放部署 ⇒ `null`。 */
750
+ readonly grantedBy: string | null;
751
+ readonly laneCannotRecord: RememberLaneCannotRecord;
752
+ }
753
+ /** {@link RouteLegs.resumeCheckpoint} 的结局 = 腿的应答 + 带了「本会话放行」请求时铸点的答(`rememberApplied`:落没落)。键只在证得出提交的两条车道
754
+ * (bg 停驻子代赎回 / 任务级续跑)的结清点上铸;其余出口(拒 / workflow 投递 / 抛)键缺席 ⇒ 门读作「没记住」(`=== true`)。
755
+ * 这一位是进程内的结局位,不进 `body` —— 由门决定挂不挂到回执上(两扇门都只挂在这次真做了授予判定的回执上;幂等回放不挂)。 */
756
+ export type ResumeCheckpointOutcome = ResumeLegOutcome & {
757
+ readonly rememberApplied?: boolean;
758
+ };
743
759
  /**
744
760
  * **「决定/续跑已受理」那一枚 200 收据的单一铸点**([ref])。
745
761
  *
@@ -19,6 +19,7 @@ import { handlePrincipalInbox, PRINCIPAL_INBOX_ROUTES } from "./routes/principal
19
19
  import { handleRules, RULES_ROUTES } from "./routes/rules.js";
20
20
  import { handleSessionsList, SESSIONS_LIST_ROUTES } from "./routes/sessions-list.js";
21
21
  import { handleAgentRoster, AGENT_ROSTER_ROUTES } from "./routes/agents-roster.js";
22
+ import { handleProjects, PROJECTS_ROUTES } from "./routes/projects.js";
22
23
  import { handleSessions, SESSIONS_ROUTES } from "./routes/sessions.js";
23
24
  import { handleSessionSync, SESSION_SYNC_ROUTES } from "./routes/session-sync.js";
24
25
  import { handleAttachments, ATTACHMENTS_ROUTES } from "./routes/attachments.js";
@@ -81,6 +82,7 @@ export const ROUTES = [
81
82
  row({ handler: handlePrincipalInbox, decls: PRINCIPAL_INBOX_ROUTES, position: "post-credential", label: "principal-inbox" }),
82
83
  row({ handler: handleSessionsList, decls: SESSIONS_LIST_ROUTES, position: "post-credential", label: "sessions-list" }),
83
84
  row({ handler: handleAgentRoster, decls: AGENT_ROSTER_ROUTES, position: "post-credential", label: "agent-roster" }),
85
+ row({ handler: handleProjects, decls: PROJECTS_ROUTES, position: "post-credential", label: "projects" }),
84
86
  row({ handler: handleSessions, decls: SESSIONS_ROUTES, position: "post-credential", label: "sessions" }),
85
87
  row({ handler: handleSessionSync, decls: SESSION_SYNC_ROUTES, position: "post-credential", label: "session-sync" }),
86
88
  row({ handler: handleAttachments, decls: ATTACHMENTS_ROUTES, position: "post-credential", label: "attachments" }),
@@ -32,7 +32,7 @@ import { recordFailOpen } from "../../observability/fail-open.js";
32
32
  import { MAX_CHECKPOINT_ID_CHARS, durableRowIdentity } from "../../checkpoint-identity.js";
33
33
  import { MAX_KEY_ECHO, keyClosureClause, scanKeyClosure } from "../../request-key-closure.js";
34
34
  import { fieldConflictFacts } from "../../field-conflict.js";
35
- import { buildSettlementEvidence, decisionCommittedOf } from "../../gate-settlement.js";
35
+ import { buildSettlementEvidence } from "../../gate-settlement.js";
36
36
  import { seatText } from "../../trace/exit-seat.js";
37
37
  import { approvalQueueKindOfDoorId } from "../../approval-queue-kind.js";
38
38
  import { defaultPeerInboundFace, parsePeerInboundId, peerBoxScope } from "../../peer-inbound-face.js";
@@ -701,7 +701,7 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
701
701
  sendError(res, 404, "not_found.run", "task not found");
702
702
  return;
703
703
  }
704
- const plan = await preparePlanReview(run.sessionId, { taskId, principalPresent: principal !== undefined }, { principal: deciderPrincipal, explicitOperator }, sighting);
704
+ const plan = await preparePlanReview(run.sessionId, { taskId, principalPresent: principal !== undefined }, { principal: deciderPrincipal, explicitOperator }, sighting, restated.restatement);
705
705
  if (!plan.ok) {
706
706
  sendResumeOutcome(res, plan.answer, deps.logger);
707
707
  return;
@@ -725,7 +725,7 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
725
725
  return;
726
726
  }
727
727
  }
728
- const out = await drivePlanReview(plan.prepared, decision, decision === "edit" ? body.editedPlan : undefined, typeof body.reason === "string" ? body.reason : undefined, hostDecisionFacts(decidedByReading.decider, deciderPrincipal), req, true, isPlanApprovePermissionModeAfter(body.permissionModeAfter) ? body.permissionModeAfter : undefined, restated.restatement);
728
+ const out = await drivePlanReview(plan.prepared, decision, decision === "edit" ? body.editedPlan : undefined, typeof body.reason === "string" ? body.reason : undefined, hostDecisionFacts(decidedByReading.decider, deciderPrincipal), req, true, isPlanApprovePermissionModeAfter(body.permissionModeAfter) ? body.permissionModeAfter : undefined);
729
729
  sendResumeOutcome(res, out, deps.logger);
730
730
  return;
731
731
  }
@@ -893,27 +893,7 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
893
893
  return;
894
894
  }
895
895
  }
896
- let rememberApplied = false;
897
- let pendingGrant;
898
- const grantOnCommit = remember && deps.approvalExemptionStore
899
- ? async (grant) => {
900
- const canonical = grant.rememberableToolName;
901
- if (!canonical)
902
- return;
903
- pendingGrant = { sessionId: grant.overrideSessionId ?? sessionId, toolName: canonical };
904
- }
905
- : undefined;
906
- const out = await resumeCheckpoint(sessionId, decision, body.reason ?? undefined, hostDecisionFacts(decider, deciderPrincipal), req, answer, binding, grantOnCommit, true, { principal: deciderPrincipal, explicitOperator }, restated.restatement);
907
- if (pendingGrant !== undefined && decisionCommittedOf(out) && deps.approvalExemptionStore) {
908
- try {
909
- await deps.approvalExemptionStore.grant(pendingGrant.sessionId, pendingGrant.toolName, deciderPrincipal ?? null);
910
- rememberApplied = true;
911
- deps.logger?.info?.("approval_exemption_granted", { sessionId: pendingGrant.sessionId, toolName: pendingGrant.toolName, grantedBy: deciderPrincipal ?? null });
912
- }
913
- catch (e) {
914
- deps.logger?.warn?.("approval_exemption_grant_failed", { sessionId: pendingGrant.sessionId, toolName: pendingGrant.toolName, error: String(e).slice(0, 200) });
915
- }
916
- }
896
+ const out = await resumeCheckpoint(sessionId, decision, body.reason ?? undefined, hostDecisionFacts(decider, deciderPrincipal), req, answer, binding, remember ? { grantedBy: deciderPrincipal ?? null, laneCannotRecord: "refuse" } : undefined, true, { principal: deciderPrincipal, explicitOperator }, restated.restatement);
917
897
  const replay = await decideIdempotentReplay(cs, {
918
898
  sessionId,
919
899
  out,
@@ -933,7 +913,7 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
933
913
  sendResumeOutcome(res, replay, deps.logger);
934
914
  return;
935
915
  }
936
- sendResumeOutcome(res, out, deps.logger, remember && deps.approvalExemptionStore ? { rememberApplied } : undefined);
916
+ sendResumeOutcome(res, out, deps.logger, remember ? { rememberApplied: out.rememberApplied === true } : undefined);
937
917
  return;
938
918
  }
939
919
  }
@@ -25,6 +25,7 @@ import { projectWriteProtectionCapability } from "../../write-protection.js";
25
25
  import { projectStoreCapability } from "../../store-posture.js";
26
26
  import { projectWebSearchCapability } from "../../plugins/web-search.js";
27
27
  import { projectExecutionLaneCapability } from "../../capabilities/execution-lane.js";
28
+ import { SETTINGS_CONTRACT_CAPABILITY } from "../../capabilities/settings-contract.js";
28
29
  import { judgeSandboxGitPlane, sandboxGitPlanePremisesOf } from "../../sandbox-git-plane.js";
29
30
  import { MCP_ASSERTION_HEADER_SENT, MCP_REQUEST_TRANSPORT_KINDS } from "../../mcp-assertion-header.js";
30
31
  import { gateCompositeMembers } from "../../capabilities/composite-members.js";
@@ -96,10 +97,10 @@ export async function handleCapabilities(req, res, match, ctx) {
96
97
  ? {
97
98
  enabled: true,
98
99
  protocolVersion: DEVICE_PROTOCOL_VERSION,
99
- maxInflightPerDevice: deps.config.remoteExec?.provider === "device" ? (deps.config.remoteExec.maxInflightPerDevice ?? 4) : 4,
100
+ maxInflightPerDevice: deps.config.remoteExec.provider === "device" ? (deps.config.remoteExec.maxInflightPerDevice ?? 4) : 4,
100
101
  wsPath: DEVICE_WS_PATH,
101
102
  management: facts.deviceManagement(deps).available,
102
- ...(deps.config.remoteExec?.provider === "device" && deps.config.remoteExec.relay.kind === "url" ? { relayUrl: deps.config.remoteExec.relay.url } : {}),
103
+ ...(deps.config.remoteExec.provider === "device" && deps.config.remoteExec.relay.kind === "url" ? { relayUrl: deps.config.remoteExec.relay.url } : {}),
103
104
  }
104
105
  : false,
105
106
  sessionEvents: facts.sessionEventStream(deps).available,
@@ -151,6 +152,7 @@ export async function handleCapabilities(req, res, match, ctx) {
151
152
  subagentResume: facts.subagentSteer(deps).available,
152
153
  taskSettings: { permissions: true, permissionMode: true, model: true, outputStyle: true, env: DEPLOYMENT_SHAPE_PREDICATES.callerCwd.holds(deps.config), hooks: taskHooksHonored(deps.config), pluginHooks: taskHooksHonored(deps.config), managedHookGroups: taskHooksHonored(deps.config), httpHookAllowlists: taskHooksHonored(deps.config), tightenOnlySeats: true, approvalFrameFamilies: true, autoCompactEnabled: true },
153
154
  settings: { permissions: { allowGrant: true, allowLayer: true, layers: true, layeredAllow: true, callerTrust: callerTrust(req, deps.config).trust } },
155
+ settingsContract: SETTINGS_CONTRACT_CAPABILITY,
154
156
  permissionModeAuto: {
155
157
  accepted: true,
156
158
  classifierSeat: deps.autoModeFace?.seatMounted === true,
@@ -204,6 +206,7 @@ export async function handleCapabilities(req, res, match, ctx) {
204
206
  sessionReadRedaction: true,
205
207
  sideQuery: true,
206
208
  agentRoster: facts.agentRoster(deps).available,
209
+ projects: facts.projectRegistry(deps).available,
207
210
  retention: retentionAdvertisement(deps.config),
208
211
  peerLane: Boolean(deps.peerDirectory),
209
212
  sessionList: facts.sessionList(deps).available,
@@ -217,6 +220,8 @@ export async function handleCapabilities(req, res, match, ctx) {
217
220
  rewindFiles: Boolean(deps.fileHistoryStore),
218
221
  restoreFiles: Boolean(deps.fileHistoryStore),
219
222
  rewindFilesTo: Boolean(deps.fileHistoryStore && deps.resumeAnchorStore && headReadOf(deps.sessionStorage)),
223
+ sessionRewindFiles: facts.sessionRewindFiles(deps).available,
224
+ sessionRewindFilesPreview: facts.sessionRewindFilesPreview(deps).available,
220
225
  fileHistoryCapture: fileHistoryCaptureOf(deps.fileHistoryStore, deps.config.fileHistoryCapture),
221
226
  scheduler: facts.hostScheduler(deps.config).available,
222
227
  sessionSync: facts.sessionSync(deps).available,
@@ -298,6 +303,7 @@ export async function handleCapabilities(req, res, match, ctx) {
298
303
  ...(m.maxTokens ? { maxOutputTokens: m.maxTokens } : {}),
299
304
  ...((levels) => (levels !== undefined ? { supportedEffortLevels: [...levels] } : {}))(reasoningEffortLevelsOf(m)),
300
305
  ...(m.compat !== undefined ? { compat: m.compat } : {}),
306
+ ...(m.thinkingLevelMap !== undefined ? { thinkingLevelMap: m.thinkingLevelMap } : {}),
301
307
  ...mentionBit(name),
302
308
  routePairing: routePairingOf(deps, name, m),
303
309
  }));
@@ -163,7 +163,7 @@ export async function handleDevices(req, res, match, ctx) {
163
163
  }
164
164
  if ((await readClosedBody(req, res, readJson, [])) === null)
165
165
  return;
166
- const ttlSeconds = (deps.config.remoteExec?.provider === "device" ? deps.config.remoteExec.enrollTokenTtlSec : undefined) ?? DEFAULT_ENROLL_TOKEN_TTL_SEC;
166
+ const ttlSeconds = (deps.config.remoteExec.provider === "device" ? deps.config.remoteExec.enrollTokenTtlSec : undefined) ?? DEFAULT_ENROLL_TOKEN_TTL_SEC;
167
167
  const issued = await enrollment.issueEnrollToken({ target: domain, createdBy: domain.subject, ttlSeconds });
168
168
  if (!issued.ok) {
169
169
  sendDeviceRejection(res, issued.reject);
@@ -105,7 +105,7 @@ export declare function buildClearanceRowWire(r: OriginClearanceRow): {
105
105
  requestId: string;
106
106
  reason: string;
107
107
  at: number;
108
- status: "done" | "failed" | "pending";
108
+ status: "done" | "pending" | "failed";
109
109
  originUnknownKeys?: string[] | undefined;
110
110
  clearanceId: string;
111
111
  entryId: string;
@@ -119,7 +119,8 @@ export async function handleNotifyWake(req, res, match, ctx) {
119
119
  return;
120
120
  }
121
121
  const restatement = readResumeRestatement(wakeBody);
122
- const out = await resumeWake(wakeSession, wakeBody.message, principal, req, true, undefined, undefined, restatement);
122
+ const message = typeof wakeBody.message === "string" ? { text: wakeBody.message, trusted: false } : undefined;
123
+ const out = await resumeWake(wakeSession, message, principal, req, true, undefined, undefined, restatement);
123
124
  sendResumeOutcome(res, out, deps.logger);
124
125
  return;
125
126
  }
@@ -0,0 +1,70 @@
1
+ /**
2
+ * 项目登记簿的**读面** —— `GET /v1/projects`、`GET /v1/projects/:id`。
3
+ *
4
+ * ## 律(三句)
5
+ * · **一个项目 = settings-schema 的一只 `ProjectRegistration`**:形与判官只在 settings-schema;本仓把判过的登记原样放在 `config.projects` 一张表里
6
+ * (`web-admin-client/apply-effective.ts` 的 stage 是唯一写者),本面只读那一张。行 = `{ id, …登记的原键原名 }` —— 不铸 `name` / `repos` /
7
+ * `createdAt` 之类的别名(端侧要别的叫法自己投影),逐键处置在 {@link PROJECT_ROW_DISPOSITIONS} 一张表里(settings-schema 给登记加键 ⇒ 这里 tsc 红,
8
+ * 先表态再上 wire)。
9
+ * · **登记簿只由配置中心下发**:settings-schema 的本地读取集不收 `projects` 域 ⇒ 没有中心腿在应用配置的部署上没有登记簿 —— 两口 501
10
+ * `capability.unavailable`,能力位 `capabilities.projects`(布尔)读同一只事实(`capability-facts.ts` 的 `projectRegistry`)答 `false`;
11
+ * 有登记簿时答 `true`。本面不开写动词(写到哪里由另一张设计定;写面到货时另立一位,本位不改义)。
12
+ * · **可见性 fail-closed**:身份判在登记簿在场判**之前**(否则「这台有没有登记簿」先于 401 泄出去);fleet 调用方(`fleetViewOf` 读档)看全部;
13
+ * 带验过主体的调用方只看 `registeredBy` 恰是自己的登记;看不见的与不存在的同码同句(404 `not_found.project`,不给存在性预言机)。
14
+ *
15
+ * 归档:`archivedAt` 在场 = 已归档。列表缺省不列,`?archived=true` 只列已归档的,`?archived=false` 与缺省同;单项读不论归档与否都答(会话行引用它)。
16
+ */
17
+ import type { IncomingMessage, ServerResponse } from "node:http";
18
+ import type { ProjectRegistration } from "@sema-agent/settings-schema";
19
+ import type { RouteCtx, RouteMatch, RouteIdsOf } from "../route-ctx.js";
20
+ /** 404 的唯一句(不存在与看不见同句)。 */
21
+ export declare const PROJECT_NOT_FOUND_MESSAGE = "no such project";
22
+ /** 投影根:这只登记的 id(登记簿的键 —— 不是登记的成员)。 */
23
+ interface ProjectRowRoot {
24
+ readonly id: string;
25
+ }
26
+ /**
27
+ * 项目行的**逐键处置**(表序 = 出口序)。登记的每个键原样出门;`contextItems` 逐条按成员处置(闭集三形,成员同为 `kind` / `value`)。
28
+ * `id` 是本面铸的唯一键:登记簿的键,行上要有它才能回指 `GET /v1/projects/:id` 与提交体 `projectId`。
29
+ */
30
+ export declare const PROJECT_ROW_DISPOSITIONS: {
31
+ readonly id: {
32
+ readonly mint: (_reg: ProjectRegistration, root: ProjectRowRoot) => string;
33
+ };
34
+ readonly displayName: "forward";
35
+ readonly goal: "forward";
36
+ readonly contextItems: {
37
+ readonly nested: {
38
+ readonly kind: "forward";
39
+ readonly value: "forward";
40
+ };
41
+ readonly rows: "each";
42
+ };
43
+ readonly gitRemotes: "forward";
44
+ readonly defaultScopes: "forward";
45
+ readonly notes: "forward";
46
+ readonly icon: "forward";
47
+ readonly color: "forward";
48
+ readonly registeredBy: "forward";
49
+ readonly registeredAt: "forward";
50
+ readonly archivedAt: "forward";
51
+ };
52
+ /** 项目行的键全集(处置表的键 = wire 上可能出现的每一个键;自铸登记表 `trace/self-minted-wire.ts` 的 `projectRowKey` 按它 `satisfies`)。 */
53
+ export type ProjectRowKey = keyof typeof PROJECT_ROW_DISPOSITIONS;
54
+ /** 一只登记 → wire 行(唯一投影)。 */
55
+ export declare function projectRowOf(id: string, registration: ProjectRegistration): Record<string, unknown>;
56
+ export declare function handleProjects(req: IncomingMessage, res: ServerResponse, match: RouteMatch<ProjectsRouteId>, ctx: RouteCtx): Promise<void>;
57
+ export declare const PROJECTS_ROUTES: readonly [{
58
+ readonly id: "projects-list";
59
+ readonly path: "/v1/projects";
60
+ readonly methods: readonly ["GET"];
61
+ }, {
62
+ readonly id: "project-get";
63
+ readonly pattern: RegExp;
64
+ readonly label: "/v1/projects/:id";
65
+ readonly methods: readonly ["GET"];
66
+ }];
67
+ /** 本域可分派行的 `id` 闭集。 */
68
+ export type ProjectsRouteId = RouteIdsOf<typeof PROJECTS_ROUTES>;
69
+ export {};
70
+ //# sourceMappingURL=projects.d.ts.map
@@ -0,0 +1,86 @@
1
+ import { PROJECT_ID_REGEX } from "@sema-agent/core";
2
+ import { sendJson, sendError } from "../send.js";
3
+ import { fleetViewOf, sendUnauthorized } from "../principal-gate.js";
4
+ import { assertNever } from "../route-ctx.js";
5
+ import * as facts from "../../capability-facts.js";
6
+ import { projectByTable } from "../../trace/projection-table.js";
7
+ export const PROJECT_NOT_FOUND_MESSAGE = "no such project";
8
+ export const PROJECT_ROW_DISPOSITIONS = {
9
+ id: { mint: (_reg, root) => root.id },
10
+ displayName: "forward",
11
+ goal: "forward",
12
+ contextItems: { nested: { kind: "forward", value: "forward" }, rows: "each" },
13
+ gitRemotes: "forward",
14
+ defaultScopes: "forward",
15
+ notes: "forward",
16
+ icon: "forward",
17
+ color: "forward",
18
+ registeredBy: "forward",
19
+ registeredAt: "forward",
20
+ archivedAt: "forward",
21
+ };
22
+ export function projectRowOf(id, registration) {
23
+ return projectByTable("project", PROJECT_ROW_DISPOSITIONS, registration, { id });
24
+ }
25
+ function readArchivedQuery(raw) {
26
+ switch (raw) {
27
+ case null:
28
+ case "false":
29
+ return false;
30
+ case "true":
31
+ return true;
32
+ default:
33
+ return "invalid";
34
+ }
35
+ }
36
+ export async function handleProjects(req, res, match, ctx) {
37
+ const { deps } = ctx;
38
+ const { safeDecode } = ctx.helpers;
39
+ const { fleetWide, gateOwner } = fleetViewOf(req, deps, "read");
40
+ if (!fleetWide && gateOwner === null) {
41
+ sendUnauthorized(res, "identity");
42
+ return;
43
+ }
44
+ const registry = facts.projectRegistry(deps);
45
+ if (!registry.available) {
46
+ sendError(res, 501, "capability.unavailable", "the project registry is not available on this deployment: projects are published only by the configuration center, and no center configuration is applied here");
47
+ return;
48
+ }
49
+ const visible = (registration) => fleetWide || registration.registeredBy === gateOwner;
50
+ switch (match.decl.id) {
51
+ case "projects-list": {
52
+ const archived = readArchivedQuery(new URLSearchParams(match.search).get("archived"));
53
+ if (archived === "invalid") {
54
+ sendError(res, 400, "request.query_invalid", "archived must be `true` or `false`");
55
+ return;
56
+ }
57
+ const projects = Object.entries(registry.registry)
58
+ .filter(([, registration]) => visible(registration) && (registration.archivedAt !== undefined) === archived)
59
+ .map(([id, registration]) => projectRowOf(id, registration));
60
+ sendJson(res, 200, { projects });
61
+ return;
62
+ }
63
+ case "project-get": {
64
+ const raw = safeDecode(match.params.projectId);
65
+ if (raw === null || !PROJECT_ID_REGEX.test(raw)) {
66
+ sendError(res, 400, "request.id_invalid", "invalid project id (must be a canonical uuid)");
67
+ return;
68
+ }
69
+ const id = raw.toLowerCase();
70
+ const registration = Object.hasOwn(registry.registry, id) ? registry.registry[id] : undefined;
71
+ if (registration === undefined || !visible(registration)) {
72
+ sendError(res, 404, "not_found.project", PROJECT_NOT_FOUND_MESSAGE);
73
+ return;
74
+ }
75
+ sendJson(res, 200, projectRowOf(id, registration));
76
+ return;
77
+ }
78
+ default:
79
+ return assertNever(match.decl.id);
80
+ }
81
+ }
82
+ export const PROJECTS_ROUTES = [
83
+ { id: "projects-list", path: "/v1/projects", methods: ["GET"] },
84
+ { id: "project-get", pattern: /^\/v1\/projects\/(?<projectId>[^/]+)$/, label: "/v1/projects/:id", methods: ["GET"] },
85
+ ];
86
+ //# sourceMappingURL=projects.js.map
@@ -142,6 +142,10 @@ export async function handleRules(req, res, match, ctx) {
142
142
  logger.info("local rule import tightening write failed", { detail: prepared.detail, committed: prepared.committed });
143
143
  sendRuleWriteFailure(res, "import-tightening", prepared.committed);
144
144
  return;
145
+ case "record-store-refused":
146
+ logger.info("local rule import record store refused", { detail: prepared.detail, committed: prepared.committed });
147
+ sendRuleWriteFailure(res, "import-record", prepared.committed);
148
+ return;
145
149
  default: {
146
150
  const unknown = prepared;
147
151
  throw new Error(`unknown local import refusal: ${JSON.stringify(unknown)}`);
@@ -189,8 +193,19 @@ export async function handleRules(req, res, match, ctx) {
189
193
  }
190
194
  const prepared = await lane.prepareImport(principal, parsed.data.layers);
191
195
  if (!prepared.ok) {
192
- sendError(res, 413, "request.payload_too_large", "too many allow entries across the submitted settings layers");
193
- return;
196
+ switch (prepared.reason) {
197
+ case "too-many-candidates":
198
+ sendError(res, 413, "request.payload_too_large", "too many allow entries across the submitted settings layers");
199
+ return;
200
+ case "record-store-refused":
201
+ logger.info("rule import record store refused", { detail: prepared.detail, committed: prepared.committed });
202
+ sendRuleWriteFailure(res, "import-record", prepared.committed);
203
+ return;
204
+ default: {
205
+ const unknown = prepared;
206
+ throw new Error(`unknown rule import refusal: ${JSON.stringify(unknown)}`);
207
+ }
208
+ }
194
209
  }
195
210
  sendJson(res, 200, { preview: prepared.preview, ...(prepared.ticket !== undefined ? { ticket: prepared.ticket, expiresAtMs: prepared.expiresAtMs } : {}) });
196
211
  return;
@@ -306,6 +321,19 @@ function sendRuleWriteFailure(res, verb, committed) {
306
321
  throw new Error(`unknown rule-write committed word: ${JSON.stringify(unknownWord)}`);
307
322
  }
308
323
  }
324
+ case "import-record":
325
+ switch (committed) {
326
+ case "no":
327
+ sendError(res, 503, "state.rule_write_failed", "the import's approval record could not be created (no ticket was issued and no allow rule was written; deny / ask rows of a local batch may already be in force) — send the same request again", { committed });
328
+ return;
329
+ case "unknown":
330
+ sendError(res, 503, "state.rule_write_failed", "the import's approval record may or may not have been created (no ticket was issued and no allow rule was written; deny / ask rows of a local batch may already be in force) — send the same request again", { committed });
331
+ return;
332
+ default: {
333
+ const unknownWord = committed;
334
+ throw new Error(`unknown rule-import committed word: ${JSON.stringify(unknownWord)}`);
335
+ }
336
+ }
309
337
  case "revoke":
310
338
  switch (committed) {
311
339
  case "no":
@@ -440,10 +440,10 @@ export async function handleRuns(req, res, match, ctx) {
440
440
  const priority = body.priority;
441
441
  const steerIdemRaw = headerStr(req.headers["idempotency-key"]);
442
442
  const messageId = steerIdemRaw ? `idem-${idemKeyOf(steerIdemRaw, idemCallerOf(req, ctx), "run").slice(0, 32)}` : uuidv7();
443
- const trusted = explicitOperatorOk(principal, deps.config);
443
+ const operator = explicitOperatorOk(principal, deps.config);
444
444
  const steerInput = () => ({
445
445
  text,
446
- trusted,
446
+ trusted: false,
447
447
  inputId: messageId,
448
448
  ...(priority !== undefined ? { priority } : {}),
449
449
  });
@@ -462,7 +462,7 @@ export async function handleRuns(req, res, match, ctx) {
462
462
  sendError(res, 404, "not_found.run", runNotFoundMessage(taskId));
463
463
  return;
464
464
  }
465
- if (!trusted && !runOwnerOk(req, res, run.owner))
465
+ if (!operator && !runOwnerOk(req, res, run.owner))
466
466
  return;
467
467
  if (!runSessionAcceptOk(req, res, run, "run.steer"))
468
468
  return;
@@ -505,7 +505,7 @@ export async function handleRuns(req, res, match, ctx) {
505
505
  if (acceptance === "refused")
506
506
  return;
507
507
  try {
508
- await relayAcceptedInput(deps, acceptance, () => live.steer(text, { trusted, inputId: messageId, ...(priority !== undefined ? { priority } : {}) }));
508
+ await relayAcceptedInput(deps, acceptance, () => live.steer(text, { trusted: false, inputId: messageId, ...(priority !== undefined ? { priority } : {}) }));
509
509
  sendJson(res, 200, { taskId, status: "running", delivery: "applied", messageId, ...(priority ? { priority } : {}) });
510
510
  return;
511
511
  }
@@ -765,10 +765,10 @@ export async function handleRuns(req, res, match, ctx) {
765
765
  const interruptIdemRaw = headerStr(req.headers["idempotency-key"]);
766
766
  const interruptInputId = interruptIdemRaw ? `idem-${idemKeyOf(interruptIdemRaw, idemCallerOf(req, ctx), "run").slice(0, 32)}` : uuidv7();
767
767
  const interruptMessageId = interruptInputId;
768
- const trusted = explicitOperatorOk(principal, deps.config);
768
+ const operator = explicitOperatorOk(principal, deps.config);
769
769
  if (!interruptBare) {
770
770
  try {
771
- validatePendingSteer({ text, trusted, inputId: interruptInputId });
771
+ validatePendingSteer({ text, trusted: false, inputId: interruptInputId });
772
772
  }
773
773
  catch (e) {
774
774
  if (e instanceof CheckpointError && e.code === "steering.invalid_content") {
@@ -783,7 +783,7 @@ export async function handleRuns(req, res, match, ctx) {
783
783
  sendError(res, 404, "not_found.run", runNotFoundMessage(taskId));
784
784
  return;
785
785
  }
786
- if (!trusted && !runOwnerOk(req, res, run.owner))
786
+ if (!operator && !runOwnerOk(req, res, run.owner))
787
787
  return;
788
788
  if (!runSessionAcceptOk(req, res, run, "run.interrupt"))
789
789
  return;
@@ -838,7 +838,7 @@ export async function handleRuns(req, res, match, ctx) {
838
838
  if (acceptance === "refused")
839
839
  return;
840
840
  try {
841
- await relayAcceptedInput(deps, acceptance, () => liveStream.steer(text, { trusted, priority: "now", ...(interruptInputId !== undefined ? { inputId: interruptInputId } : {}) }));
841
+ await relayAcceptedInput(deps, acceptance, () => liveStream.steer(text, { trusted: false, priority: "now", ...(interruptInputId !== undefined ? { inputId: interruptInputId } : {}) }));
842
842
  }
843
843
  catch (e) {
844
844
  const code = e.code;
@@ -38,6 +38,21 @@ export function createSessionSyncLocal() {
38
38
  };
39
39
  return { pendingStagings, importLeases, touchImportLease, cleanupStaging };
40
40
  }
41
+ async function firstPhaseRefusal(sessionStorage, sessionId, relation, consented) {
42
+ if (consented || (relation !== "fork" && relation !== "stale"))
43
+ return undefined;
44
+ if (sessionStorage.assertArchiveAnonymous !== undefined && (await readSessionAgent(sessionStorage, sessionId)) === undefined) {
45
+ try {
46
+ await sessionStorage.assertArchiveAnonymous(sessionId);
47
+ }
48
+ catch (e) {
49
+ if (e instanceof StampedSessionArchiveError)
50
+ return { kind: "stamped", error: e };
51
+ throw e;
52
+ }
53
+ }
54
+ return { kind: "needs_consent" };
55
+ }
41
56
  export async function handleSessionSync(req, res, match, ctx) {
42
57
  const { deps } = ctx;
43
58
  const { readJson, readRawBody, safeDecode, rateLimited } = ctx.helpers;
@@ -358,16 +373,12 @@ export async function handleSessionSync(req, res, match, ctx) {
358
373
  const anchors = anchorsRead.anchors;
359
374
  const dstIds = (await sessionStorage.listEntryIds?.(sessionId)) ?? null;
360
375
  const relA = classifySyncRelationshipByIds(entryIds, dstIds);
361
- if ((relA.relation === "fork" || relA.relation === "stale") && resolution !== "overwrite-dst") {
362
- if (sessionStorage.assertArchiveAnonymous !== undefined && (await readSessionAgent(sessionStorage, sessionId)) === undefined) {
363
- try {
364
- await sessionStorage.assertArchiveAnonymous(sessionId);
365
- }
366
- catch (e) {
367
- if (e instanceof StampedSessionArchiveError && sendSessionError(res, e, "import"))
368
- return;
369
- throw e;
370
- }
376
+ const refusalA = await firstPhaseRefusal(sessionStorage, sessionId, relA.relation, resolution === "overwrite-dst");
377
+ if (refusalA !== undefined) {
378
+ if (refusalA.kind === "stamped") {
379
+ if (sendSessionError(res, refusalA.error, "import"))
380
+ return;
381
+ throw refusalA.error;
371
382
  }
372
383
  sendError(res, 409, "conflict", "sync conflict", { relation: relA });
373
384
  return;
@@ -683,6 +694,12 @@ export async function handleSessionSync(req, res, match, ctx) {
683
694
  }
684
695
  const dst = await sessionStorage.exportEntries(sessionId);
685
696
  const relation = classifySyncRelationshipByIds(body.entryIds, dst ? dst.map((e) => e.id) : null);
697
+ const refusal = await firstPhaseRefusal(sessionStorage, sessionId, relation.relation, false);
698
+ if (refusal?.kind === "stamped") {
699
+ if (sendSessionError(res, refusal.error, "import"))
700
+ return;
701
+ throw refusal.error;
702
+ }
686
703
  sendJson(res, 200, relation);
687
704
  return;
688
705
  }