@sema-agent/server 7.131.0 → 7.133.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 (509) hide show
  1. package/MIGRATION.md +575 -0
  2. package/README.md +12 -9
  3. package/README.zh-CN.md +9 -6
  4. package/USAGE.md +326 -98
  5. package/deploy/sema-up/README.md +19 -1
  6. package/deploy/sema-up/chart/templates/server-v4pro.yaml +5 -2
  7. package/deploy/sema-up/chart/templates/server.yaml +5 -2
  8. package/deploy/sema-up/stack/compose.yaml +3 -0
  9. package/deploy/sema-up/stack/sema-stack-cluster.yaml +4 -2
  10. package/dist/adoption/plan.d.ts +3 -2
  11. package/dist/adoption/plan.js +7 -5
  12. package/dist/adoption/runner.js +3 -10
  13. package/dist/adoption/sql.d.ts +3 -2
  14. package/dist/adoption/sql.js +3 -5
  15. package/dist/adoption/wire.d.ts +4 -1
  16. package/dist/adoption/wire.js +1 -0
  17. package/dist/approval-ask-audit-store.d.ts +31 -13
  18. package/dist/approval-ask-audit-store.js +272 -74
  19. package/dist/approval-ask-machine.d.ts +15 -0
  20. package/dist/approval-ask-machine.js +6 -0
  21. package/dist/approval-ask-retention.d.ts +136 -0
  22. package/dist/approval-ask-retention.js +102 -0
  23. package/dist/approval-card.d.ts +82 -20
  24. package/dist/approval-card.js +46 -16
  25. package/dist/approval-deny-reasons.d.ts +1 -1
  26. package/dist/approval.d.ts +9 -0
  27. package/dist/approval.js +24 -3
  28. package/dist/audit.d.ts +33 -19
  29. package/dist/audit.js +12 -16
  30. package/dist/auth-bridge.d.ts +4 -0
  31. package/dist/auth-bridge.js +10 -11
  32. package/dist/bake-runner/main.js +3 -2
  33. package/dist/boot/deferred-sandbox-path-env.js +1 -1
  34. package/dist/boot/deployment-mods.d.ts +31 -0
  35. package/dist/boot/deployment-mods.js +26 -0
  36. package/dist/boot/execution-env.d.ts +1 -1
  37. package/dist/boot/execution-env.js +27 -12
  38. package/dist/boot/execution-lane.js +11 -0
  39. package/dist/boot/leader.js +2 -0
  40. package/dist/boot/memory-boundary.d.ts +2 -2
  41. package/dist/boot/memory-boundary.js +2 -2
  42. package/dist/boot/memory-consolidation.d.ts +5 -4
  43. package/dist/boot/memory-consolidation.js +7 -6
  44. package/dist/boot/org-delivery.d.ts +28 -0
  45. package/dist/boot/org-delivery.js +20 -0
  46. package/dist/boot/read-deny-anchor-audit.d.ts +17 -0
  47. package/dist/boot/read-deny-anchor-audit.js +36 -0
  48. package/dist/boot/reapers.d.ts +3 -0
  49. package/dist/boot/reapers.js +21 -1
  50. package/dist/boot/resolve-spec.d.ts +4 -5
  51. package/dist/boot/resolve-spec.js +74 -123
  52. package/dist/boot/runner-deps.d.ts +19 -8
  53. package/dist/boot/runner-deps.js +15 -2
  54. package/dist/boot/session-faces.d.ts +2 -7
  55. package/dist/boot/session-faces.js +4 -2
  56. package/dist/boot/stage-02-web-admin-pull.js +4 -1
  57. package/dist/boot/stage-03-store-backend.d.ts +1 -1
  58. package/dist/boot/stage-03-store-backend.js +2 -2
  59. package/dist/boot/stage-04-stores.d.ts +1 -1
  60. package/dist/boot/stage-05-execution-env.d.ts +4 -4
  61. package/dist/boot/stage-05-execution-env.js +7 -10
  62. package/dist/boot/stage-06-runners.d.ts +4 -2
  63. package/dist/boot/stage-06-runners.js +11 -7
  64. package/dist/boot/stage-07-capability-layer.d.ts +4 -2
  65. package/dist/boot/stage-07-capability-layer.js +27 -6
  66. package/dist/boot/stage-08-reapers.d.ts +4 -2
  67. package/dist/boot/stage-08-reapers.js +2 -2
  68. package/dist/boot/stage-09-leader.d.ts +6 -9
  69. package/dist/boot/stage-10-http-server.d.ts +6 -9
  70. package/dist/boot/stage-10-http-server.js +7 -9
  71. package/dist/boot/stores.d.ts +1 -1
  72. package/dist/boot/stores.js +7 -8
  73. package/dist/boot/web-admin.d.ts +4 -3
  74. package/dist/boot/web-admin.js +186 -98
  75. package/dist/boot/workflow-orchestration.d.ts +2 -0
  76. package/dist/boot/workflow-orchestration.js +2 -1
  77. package/dist/brain.js +25 -25
  78. package/dist/breaker-key.d.ts +6 -0
  79. package/dist/breaker-key.js +29 -0
  80. package/dist/budget.js +5 -4
  81. package/dist/caller-text-echo.d.ts +23 -0
  82. package/dist/caller-text-echo.js +21 -0
  83. package/dist/capabilities/brand-identity.d.ts +26 -0
  84. package/dist/capabilities/brand-identity.js +27 -0
  85. package/dist/capabilities/center-plugins.d.ts +7 -0
  86. package/dist/capabilities/center-plugins.js +1 -1
  87. package/dist/capabilities/center-prompts.d.ts +32 -59
  88. package/dist/capabilities/center-prompts.js +18 -32
  89. package/dist/capabilities/composite-members.d.ts +1 -1
  90. package/dist/capabilities/composite-members.js +1 -1
  91. package/dist/capabilities/engine-capabilities.js +2 -1
  92. package/dist/capabilities/execution-lane.js +2 -2
  93. package/dist/capabilities/hands-lane.d.ts +30 -6
  94. package/dist/capabilities/hands-lane.js +11 -1
  95. package/dist/capabilities/mcp-probe.d.ts +48 -3
  96. package/dist/capabilities/mcp-probe.js +47 -135
  97. package/dist/capabilities/scenarios.d.ts +95 -45
  98. package/dist/capabilities/scenarios.js +53 -38
  99. package/dist/capabilities/skills.d.ts +19 -4
  100. package/dist/capabilities/skills.js +30 -10
  101. package/dist/capability-facts.d.ts +34 -4
  102. package/dist/capability-facts.js +28 -2
  103. package/dist/center-config-tier.d.ts +69 -0
  104. package/dist/center-config-tier.js +42 -0
  105. package/dist/checkpoint-identity.d.ts +16 -0
  106. package/dist/checkpoint-identity.js +19 -0
  107. package/dist/config-catalog.d.ts +17 -10
  108. package/dist/config-catalog.js +47 -32
  109. package/dist/config-d-migration.d.ts +3 -1
  110. package/dist/config-d-migration.js +2 -2
  111. package/dist/config-dir-trust.d.ts +114 -0
  112. package/dist/config-dir-trust.js +388 -0
  113. package/dist/config-invariants.d.ts +18 -5
  114. package/dist/config-invariants.js +35 -3
  115. package/dist/config-lkg.d.ts +9 -9
  116. package/dist/config-lkg.js +20 -4
  117. package/dist/config-provider.d.ts +9 -2
  118. package/dist/config-provider.js +18 -6
  119. package/dist/config-types.d.ts +75 -20
  120. package/dist/config-types.js +8 -0
  121. package/dist/config.d.ts +13 -0
  122. package/dist/config.js +137 -62
  123. package/dist/delegated-session-owner.d.ts +185 -0
  124. package/dist/delegated-session-owner.js +119 -0
  125. package/dist/device-protocol.d.ts +5 -3
  126. package/dist/device-protocol.js +1 -1
  127. package/dist/device-ws-hub.js +21 -2
  128. package/dist/device-ws-protocol.d.ts +70 -6
  129. package/dist/device-ws-protocol.js +50 -22
  130. package/dist/elicitation.js +3 -2
  131. package/dist/entry-problems.d.ts +34 -0
  132. package/dist/entry-problems.js +14 -0
  133. package/dist/env-name-allowlist-knobs.d.ts +12 -2
  134. package/dist/env-name-allowlist-knobs.js +5 -4
  135. package/dist/exec-bounds.d.ts +15 -3
  136. package/dist/exec-bounds.js +4 -0
  137. package/dist/execution-lane-caps.d.ts +56 -10
  138. package/dist/execution-lane-caps.js +50 -0
  139. package/dist/field-conflict.d.ts +43 -0
  140. package/dist/field-conflict.js +20 -0
  141. package/dist/fleet/fleet-bus.d.ts +80 -6
  142. package/dist/fleet/fleet-bus.js +41 -9
  143. package/dist/hooks/classic-stations.d.ts +91 -0
  144. package/dist/hooks/classic-stations.js +27 -0
  145. package/dist/hooks/command-spawn.d.ts +57 -0
  146. package/dist/hooks/command-spawn.js +139 -0
  147. package/dist/hooks/hook-llm.d.ts +8 -5
  148. package/dist/hooks/hook-llm.js +79 -36
  149. package/dist/hooks/hook-runner.d.ts +349 -95
  150. package/dist/hooks/hook-runner.js +855 -568
  151. package/dist/hooks/hook-source.d.ts +44 -0
  152. package/dist/hooks/hook-source.js +40 -0
  153. package/dist/http/active-run-conflict.d.ts +5 -13
  154. package/dist/http/active-run-conflict.js +17 -27
  155. package/dist/http/admission.d.ts +8 -2
  156. package/dist/http/admission.js +188 -101
  157. package/dist/http/approval-sweeps.js +99 -21
  158. package/dist/http/caller-trust.d.ts +77 -0
  159. package/dist/http/caller-trust.js +143 -0
  160. package/dist/http/checkpoint-ctx.d.ts +41 -24
  161. package/dist/http/checkpoint-ctx.js +23 -16
  162. package/dist/http/claimed-run.d.ts +14 -0
  163. package/dist/http/claimed-run.js +15 -0
  164. package/dist/http/device-placement.d.ts +2 -4
  165. package/dist/http/device-placement.js +7 -11
  166. package/dist/http/dispatch.d.ts +0 -4
  167. package/dist/http/dispatch.js +15 -13
  168. package/dist/http/durable-run-leg.d.ts +6 -33
  169. package/dist/http/durable-run-leg.js +36 -10
  170. package/dist/http/health-self-report.d.ts +7 -5
  171. package/dist/http/health-self-report.js +4 -18
  172. package/dist/http/owner-access.d.ts +56 -0
  173. package/dist/http/owner-access.js +42 -0
  174. package/dist/http/principal-gate.d.ts +70 -28
  175. package/dist/http/principal-gate.js +61 -15
  176. package/dist/http/readiness.d.ts +11 -5
  177. package/dist/http/readiness.js +10 -3
  178. package/dist/http/refusal-body.d.ts +21 -0
  179. package/dist/http/refusal-body.js +4 -0
  180. package/dist/http/request-guards.d.ts +43 -23
  181. package/dist/http/request-guards.js +53 -17
  182. package/dist/http/resume-ctx-read.d.ts +2 -5
  183. package/dist/http/resume-ctx-read.js +7 -4
  184. package/dist/http/resume-legs.d.ts +28 -4
  185. package/dist/http/resume-legs.js +169 -91
  186. package/dist/http/retired-service-deps.d.ts +43 -0
  187. package/dist/http/retired-service-deps.js +18 -0
  188. package/dist/http/route-ctx.d.ts +44 -28
  189. package/dist/http/route-ctx.js +4 -0
  190. package/dist/http/route-table.js +2 -0
  191. package/dist/http/routes/a2a-serve.js +3 -4
  192. package/dist/http/routes/admin-config-refresh.js +1 -1
  193. package/dist/http/routes/admin-drain.js +1 -1
  194. package/dist/http/routes/admin-memory-optout.js +5 -1
  195. package/dist/http/routes/adoption.js +2 -9
  196. package/dist/http/routes/approvals-assistant.js +49 -48
  197. package/dist/http/routes/background.js +3 -2
  198. package/dist/http/routes/capabilities.js +21 -5
  199. package/dist/http/routes/config-catalog.d.ts +3 -3
  200. package/dist/http/routes/config-catalog.js +1 -1
  201. package/dist/http/routes/devices.js +3 -17
  202. package/dist/http/routes/diagnostics.js +6 -2
  203. package/dist/http/routes/images.js +6 -7
  204. package/dist/http/routes/leader.js +1 -8
  205. package/dist/http/routes/mcp-reconnect.d.ts +1 -1
  206. package/dist/http/routes/mcp-reconnect.js +3 -2
  207. package/dist/http/routes/memory-bundle.js +1 -1
  208. package/dist/http/routes/memory-compliance.js +1 -1
  209. package/dist/http/routes/memory-consolidation.js +1 -1
  210. package/dist/http/routes/memory-origin.js +1 -1
  211. package/dist/http/routes/memory-policy.d.ts +1 -1
  212. package/dist/http/routes/memory-policy.js +3 -2
  213. package/dist/http/routes/notify-wake.js +8 -21
  214. package/dist/http/routes/observability.js +2 -2
  215. package/dist/http/routes/principal-inbox.d.ts +39 -0
  216. package/dist/http/routes/principal-inbox.js +76 -0
  217. package/dist/http/routes/retention-ops.js +2 -9
  218. package/dist/http/routes/rules.js +5 -18
  219. package/dist/http/routes/runs.d.ts +5 -0
  220. package/dist/http/routes/runs.js +34 -107
  221. package/dist/http/routes/session-sync.js +15 -26
  222. package/dist/http/routes/sessions.js +30 -40
  223. package/dist/http/routes/shared-memory.js +2 -13
  224. package/dist/http/routes/side-query.js +8 -7
  225. package/dist/http/routes/tasks.js +67 -21
  226. package/dist/http/routes/workflows.d.ts +351 -0
  227. package/dist/http/routes/workflows.js +153 -119
  228. package/dist/http/send.d.ts +33 -10
  229. package/dist/http/send.js +21 -4
  230. package/dist/http/server.d.ts +27 -18
  231. package/dist/http/server.js +34 -6
  232. package/dist/http/stored-body-replay.js +17 -4
  233. package/dist/http/submit-ctx.d.ts +25 -0
  234. package/dist/http/submit-ctx.js +40 -0
  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 +11 -8
  238. package/dist/index.d.ts +2 -2
  239. package/dist/index.js +1 -2
  240. package/dist/lane-home-probe.d.ts +112 -0
  241. package/dist/lane-home-probe.js +101 -0
  242. package/dist/leader/endpoint.d.ts +4 -1
  243. package/dist/leader/endpoint.js +11 -10
  244. package/dist/limit-refusal.d.ts +59 -0
  245. package/dist/limit-refusal.js +15 -0
  246. package/dist/main.js +1 -1
  247. package/dist/mcp-assertion-header.d.ts +32 -19
  248. package/dist/mcp-assertion-header.js +10 -9
  249. package/dist/mcp-tool-faces.d.ts +5 -0
  250. package/dist/mcp-tool-faces.js +6 -4
  251. package/dist/memory-project-layer.d.ts +37 -0
  252. package/dist/memory-project-layer.js +46 -0
  253. package/dist/memory-scope.d.ts +24 -17
  254. package/dist/memory-scope.js +24 -8
  255. package/dist/memory-sync-client.d.ts +27 -13
  256. package/dist/memory-sync-client.js +107 -18
  257. package/dist/model-entry-refusal.d.ts +9 -1
  258. package/dist/model-entry-refusal.js +6 -1
  259. package/dist/model-plane-face.d.ts +51 -0
  260. package/dist/model-plane-face.js +24 -0
  261. package/dist/model-provider.d.ts +44 -12
  262. package/dist/model-provider.js +21 -2
  263. package/dist/model-route-endpoint.d.ts +9 -12
  264. package/dist/model-route-endpoint.js +8 -11
  265. package/dist/model-route-env.d.ts +22 -0
  266. package/dist/model-route-env.js +2 -0
  267. package/dist/model-route-gap.d.ts +60 -30
  268. package/dist/model-route-gap.js +21 -15
  269. package/dist/observability/corrupt-read-seat.d.ts +7 -0
  270. package/dist/observability/corrupt-read-seat.js +9 -0
  271. package/dist/observability/cost-taxonomy.d.ts +7 -7
  272. package/dist/observability/err-text.d.ts +6 -0
  273. package/dist/observability/err-text.js +18 -4
  274. package/dist/observability/fail-open.d.ts +76 -14
  275. package/dist/observability/fail-open.js +76 -14
  276. package/dist/observability/metrics.js +4 -1
  277. package/dist/observability/prompt-manifest.d.ts +33 -82
  278. package/dist/observability/prompt-manifest.js +122 -17
  279. package/dist/observability/run-terminal.js +14 -6
  280. package/dist/observability/secret-env-scrub.d.ts +13 -1
  281. package/dist/observability/secret-env-scrub.js +13 -1
  282. package/dist/observability/tool-trace.d.ts +16 -21
  283. package/dist/observability/tool-trace.js +58 -49
  284. package/dist/operator-ask.d.ts +10 -0
  285. package/dist/operator-ask.js +3 -0
  286. package/dist/orchestration/workflow-agent-session-index.d.ts +12 -12
  287. package/dist/orchestration/workflow-agent-session-index.js +9 -13
  288. package/dist/orchestration/workflow-completion-inbox.d.ts +42 -15
  289. package/dist/orchestration/workflow-completion-inbox.js +13 -0
  290. package/dist/orchestration/workflow-notify-journal.d.ts +13 -32
  291. package/dist/orchestration/workflow-notify-journal.js +27 -34
  292. package/dist/orchestration/workflow-park-decision.d.ts +89 -0
  293. package/dist/orchestration/workflow-park-decision.js +118 -0
  294. package/dist/org-delivery-gate.d.ts +81 -0
  295. package/dist/org-delivery-gate.js +59 -0
  296. package/dist/panel-tool-names.d.ts +23 -0
  297. package/dist/panel-tool-names.js +8 -0
  298. package/dist/parked-decide.d.ts +39 -6
  299. package/dist/parked-decide.js +98 -51
  300. package/dist/parked-revive-surface.d.ts +9 -2
  301. package/dist/parked-revive-surface.js +11 -8
  302. package/dist/per-task-image.d.ts +7 -1
  303. package/dist/per-task-image.js +3 -3
  304. package/dist/permission-rule-list.d.ts +1 -1
  305. package/dist/permission-rule-list.js +2 -2
  306. package/dist/plain-string-record.d.ts +25 -0
  307. package/dist/plain-string-record.js +32 -0
  308. package/dist/plugins/approval-ask-store-file.d.ts +16 -1
  309. package/dist/plugins/approval-ask-store-file.js +21 -0
  310. package/dist/plugins/approval-ask-store-memory.d.ts +18 -1
  311. package/dist/plugins/approval-ask-store-memory.js +34 -2
  312. package/dist/plugins/approval-ask-store-sql.d.ts +25 -0
  313. package/dist/plugins/approval-ask-store-sql.js +37 -1
  314. package/dist/plugins/blob-backend.d.ts +83 -15
  315. package/dist/plugins/blob-backend.js +68 -15
  316. package/dist/plugins/breaker-state-sql.d.ts +2 -2
  317. package/dist/plugins/breaker-state-sql.js +4 -4
  318. package/dist/plugins/caching-session-store.d.ts +3 -0
  319. package/dist/plugins/caching-session-store.js +3 -0
  320. package/dist/plugins/checkpoint-store-sql.d.ts +28 -4
  321. package/dist/plugins/checkpoint-store-sql.js +59 -28
  322. package/dist/plugins/file-history-store-sql.d.ts +5 -2
  323. package/dist/plugins/file-history-store-sql.js +3 -1
  324. package/dist/plugins/file-run-store.d.ts +5 -13
  325. package/dist/plugins/file-run-store.js +9 -0
  326. package/dist/plugins/fork-routing-session-store.d.ts +9 -1
  327. package/dist/plugins/fork-routing-session-store.js +12 -1
  328. package/dist/plugins/host-platform.d.ts +2 -0
  329. package/dist/plugins/host-platform.js +2 -1
  330. package/dist/plugins/k8s-bg-scripts.d.ts +11 -0
  331. package/dist/plugins/k8s-bg-scripts.js +22 -0
  332. package/dist/plugins/local-checkpoint-store.d.ts +2 -0
  333. package/dist/plugins/local-checkpoint-store.js +11 -3
  334. package/dist/plugins/local-session-store.d.ts +1 -1
  335. package/dist/plugins/local-session-store.js +1 -1
  336. package/dist/plugins/local-session-window.d.ts +39 -0
  337. package/dist/plugins/local-session-window.js +54 -0
  338. package/dist/plugins/mailbox-recipient-lifecycle.d.ts +3 -2
  339. package/dist/plugins/mailbox-store-sql.d.ts +30 -48
  340. package/dist/plugins/mailbox-store-sql.js +77 -52
  341. package/dist/plugins/memory-embedder-fingerprint.js +2 -1
  342. package/dist/plugins/memory-run-store.d.ts +5 -13
  343. package/dist/plugins/memory-run-store.js +8 -0
  344. package/dist/plugins/one-time-migrations.d.ts +245 -93
  345. package/dist/plugins/one-time-migrations.js +668 -207
  346. package/dist/plugins/org-delivery-quota-store.d.ts +123 -0
  347. package/dist/plugins/org-delivery-quota-store.js +228 -0
  348. package/dist/plugins/permission-rule-store-sql.d.ts +13 -7
  349. package/dist/plugins/permission-rule-store-sql.js +4 -18
  350. package/dist/plugins/pg-pool.js +39 -7
  351. package/dist/plugins/pg-session-storage.d.ts +20 -8
  352. package/dist/plugins/pg-session-storage.js +34 -21
  353. package/dist/plugins/remote-env-adb.d.ts +12 -12
  354. package/dist/plugins/remote-env-adb.js +21 -6
  355. package/dist/plugins/remote-env-device.js +3 -0
  356. package/dist/plugins/remote-env-e2b.d.ts +1 -1
  357. package/dist/plugins/remote-env-e2b.js +21 -9
  358. package/dist/plugins/remote-env-host.d.ts +9 -9
  359. package/dist/plugins/remote-env-host.js +10 -32
  360. package/dist/plugins/remote-env-k8s.d.ts +103 -38
  361. package/dist/plugins/remote-env-k8s.js +288 -95
  362. package/dist/plugins/remote-env-local-docker.d.ts +27 -13
  363. package/dist/plugins/remote-env-local-docker.js +82 -11
  364. package/dist/plugins/remote-env-ssh.d.ts +21 -12
  365. package/dist/plugins/remote-env-ssh.js +117 -5
  366. package/dist/plugins/remote-shell.d.ts +0 -1
  367. package/dist/plugins/remote-shell.js +1 -2
  368. package/dist/plugins/retention-store-sql.js +6 -2
  369. package/dist/plugins/run-store-sql.d.ts +16 -14
  370. package/dist/plugins/run-store-sql.js +22 -2
  371. package/dist/plugins/schema-consistency.d.ts +54 -0
  372. package/dist/plugins/schema-consistency.js +52 -0
  373. package/dist/plugins/schema-indexes.js +2 -0
  374. package/dist/plugins/send-user-file.js +2 -2
  375. package/dist/plugins/session-epoch-anchor.d.ts +39 -0
  376. package/dist/plugins/session-epoch-anchor.js +22 -0
  377. package/dist/plugins/session-store.d.ts +18 -8
  378. package/dist/plugins/session-store.js +15 -4
  379. package/dist/plugins/shared-memory-store-sql.d.ts +9 -3
  380. package/dist/plugins/shared-memory-store-sql.js +5 -16
  381. package/dist/plugins/sql-driver.d.ts +205 -1
  382. package/dist/plugins/sql-driver.js +325 -13
  383. package/dist/plugins/sql-errors.d.ts +64 -0
  384. package/dist/plugins/sql-errors.js +57 -0
  385. package/dist/plugins/store-backend.d.ts +36 -1
  386. package/dist/plugins/store-backend.js +42 -15
  387. package/dist/plugins/store-contracts.d.ts +42 -0
  388. package/dist/plugins/store-contracts.js +1 -0
  389. package/dist/plugins/tidb-pool.d.ts +6 -1
  390. package/dist/plugins/tidb-pool.js +44 -10
  391. package/dist/plugins/tidb-session-storage.d.ts +8 -11
  392. package/dist/plugins/tidb-session-storage.js +6 -16
  393. package/dist/plugins/tidb-session-store.d.ts +24 -4
  394. package/dist/plugins/tidb-session-store.js +29 -5
  395. package/dist/plugins/workflow-journal-store-sql.d.ts +73 -19
  396. package/dist/plugins/workflow-journal-store-sql.js +19 -6
  397. package/dist/plugins/workflow-run-store-sql.d.ts +30 -8
  398. package/dist/plugins/workflow-run-store-sql.js +50 -9
  399. package/dist/posture-source.d.ts +18 -10
  400. package/dist/posture-source.js +4 -1
  401. package/dist/project-identity.d.ts +45 -6
  402. package/dist/project-identity.js +162 -8
  403. package/dist/project-layer-key.d.ts +28 -0
  404. package/dist/project-layer-key.js +29 -0
  405. package/dist/prompts-domain-validate.d.ts +17 -61
  406. package/dist/prompts-domain-validate.js +9 -119
  407. package/dist/question.js +3 -2
  408. package/dist/read-deny-entry.d.ts +25 -0
  409. package/dist/read-deny-entry.js +12 -0
  410. package/dist/read-face-posture.d.ts +37 -11
  411. package/dist/read-face-posture.js +32 -3
  412. package/dist/request-key-closure.d.ts +9 -2
  413. package/dist/request-key-closure.js +11 -5
  414. package/dist/request-value-closure.d.ts +5 -0
  415. package/dist/request-value-closure.js +11 -3
  416. package/dist/rule-entry-list.d.ts +38 -11
  417. package/dist/rule-entry-list.js +106 -30
  418. package/dist/rules-consent.js +3 -4
  419. package/dist/run-acceptance.d.ts +19 -3
  420. package/dist/run-acceptance.js +13 -1
  421. package/dist/run-local.js +54 -24
  422. package/dist/runs.d.ts +15 -8
  423. package/dist/runs.js +35 -1
  424. package/dist/runtime-caps-resolver.d.ts +16 -6
  425. package/dist/runtime-caps-resolver.js +18 -5
  426. package/dist/sandbox-pkg-source.d.ts +19 -1
  427. package/dist/sandbox-pkg-source.js +29 -7
  428. package/dist/security.d.ts +87 -9
  429. package/dist/security.js +52 -9
  430. package/dist/server-secret-env.d.ts +44 -18
  431. package/dist/server-secret-env.js +49 -8
  432. package/dist/session-error-wire.d.ts +19 -2
  433. package/dist/session-error-wire.js +5 -1
  434. package/dist/session-incarnation.d.ts +15 -5
  435. package/dist/session-incarnation.js +16 -9
  436. package/dist/session-titled-frame.d.ts +33 -0
  437. package/dist/session-titled-frame.js +4 -0
  438. package/dist/session-titler.d.ts +9 -1
  439. package/dist/session-titler.js +27 -6
  440. package/dist/spec-fields.d.ts +28 -16
  441. package/dist/spec-fields.js +66 -54
  442. package/dist/sql-engine-posture.d.ts +31 -4
  443. package/dist/sql-engine-posture.js +36 -1
  444. package/dist/stored-request-tool-axes-m19.d.ts +19 -4
  445. package/dist/stored-request-tool-axes-m19.js +30 -2
  446. package/dist/task-a2a.d.ts +9 -1
  447. package/dist/task-a2a.js +73 -47
  448. package/dist/task-cwd.d.ts +1 -1
  449. package/dist/task-mcp.d.ts +46 -58
  450. package/dist/task-mcp.js +82 -107
  451. package/dist/task-settings.d.ts +95 -108
  452. package/dist/task-settings.js +77 -98
  453. package/dist/text-bidi.d.ts +1 -48
  454. package/dist/text-bidi.js +3 -5
  455. package/dist/tighten-only-seats.d.ts +150 -0
  456. package/dist/tighten-only-seats.js +196 -0
  457. package/dist/tool-approval.d.ts +304 -88
  458. package/dist/tool-approval.js +623 -239
  459. package/dist/trace/core-keyset-guard.d.ts +122 -20
  460. package/dist/trace/engine-notice-wire.d.ts +11 -3
  461. package/dist/trace/engine-notice-wire.js +8 -1
  462. package/dist/trace/exit-seat.d.ts +28 -0
  463. package/dist/trace/exit-seat.js +76 -0
  464. package/dist/trace/ledger-events.d.ts +6 -3
  465. package/dist/trace/ledger-sink.js +4 -1
  466. package/dist/trace/model-segment.js +1 -1
  467. package/dist/trace/project.d.ts +98 -17
  468. package/dist/trace/project.js +98 -50
  469. package/dist/trace/projection-table.d.ts +100 -0
  470. package/dist/trace/projection-table.js +130 -0
  471. package/dist/trace/redact.d.ts +54 -0
  472. package/dist/trace/redact.js +778 -152
  473. package/dist/trace/self-minted-wire.d.ts +345 -1
  474. package/dist/trace/self-minted-wire.js +117 -1
  475. package/dist/trace/wire-projection-faces.d.ts +377 -3
  476. package/dist/trace/wire-projection-faces.js +164 -1
  477. package/dist/url-refusal.js +2 -0
  478. package/dist/web-admin-client/apply-effective.d.ts +12 -0
  479. package/dist/web-admin-client/apply-effective.js +56 -5
  480. package/dist/web-admin-client/candidate-gate.d.ts +6 -6
  481. package/dist/web-admin-client/candidate-gate.js +3 -3
  482. package/dist/web-admin-client/facade.d.ts +1 -1
  483. package/dist/web-admin-client/facade.js +1 -1
  484. package/dist/web-admin-client/http-client.js +0 -6
  485. package/dist/web-admin-client/read-face.js +5 -9
  486. package/dist/web-admin-client/read-warnings.d.ts +13 -0
  487. package/dist/web-admin-client/read-warnings.js +10 -0
  488. package/dist/web-admin-client/skills-mcp.d.ts +3 -0
  489. package/dist/web-admin-client/skills-mcp.js +11 -9
  490. package/dist/web-admin-client/types.d.ts +2 -3
  491. package/dist/workspace-cache.d.ts +35 -0
  492. package/dist/workspace-cache.js +36 -0
  493. package/dist/workspace-space.d.ts +3 -2
  494. package/dist/workspace-space.js +2 -0
  495. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +65 -10
  496. package/package.json +8 -4
  497. package/scripts/drain-check-local.mjs +34 -1
  498. package/scripts/drain-check.mysql.sql +30 -2
  499. package/scripts/drain-check.pg.sql +29 -2
  500. package/dist/capabilities/memory-notice.d.ts +0 -138
  501. package/dist/capabilities/memory-notice.js +0 -64
  502. package/dist/capabilities/prompt.d.ts +0 -17
  503. package/dist/capabilities/prompt.js +0 -6
  504. package/dist/mcp-content-origin.d.ts +0 -34
  505. package/dist/mcp-content-origin.js +0 -10
  506. package/dist/tool-axis-words.d.ts +0 -27
  507. package/dist/tool-axis-words.js +0 -9
  508. package/dist/wire-name-bound.d.ts +0 -14
  509. package/dist/wire-name-bound.js +0 -13
@@ -27,12 +27,12 @@
27
27
  * `APPROVAL_REQUIRE` (an ask rule), `APPROVAL_NEVER_AUTO` (a person, mandated), `MANUAL_MODE_SHELL_GATE=always` (shell).
28
28
  * A request-carried skill's `allowedTools` is the same member's twin (same grammar, same predicate, same admission judge
29
29
  * `rule-entry-list.ts`). Pinned on the real assembly: `test/allow-layer-operator-knobs.test.ts`.
30
- * - permissionMode(轴B #2 注释保鲜,1.254——[ref]/[ref] 后的真实现):`defaultMode` 收 core `PERMISSION_MODES` **全集**
31
- * (default | acceptEdits | plan | auto | bypassPermissions | dontAsk),bypass/auto 被 HONOR 为 gate-shape 选择
32
- * ——但深层不变量未变:bypass=「不加 ask 门」,恒不越部署基线(tightenTaskSpec deny-wins,基线 deny/
33
- * ask 照压);精化语义见 :2xx 行内注释。旧头注的「NEVER honored/三模式白名单」是 pre-[ref] 拍照。
30
+ * - permissionMode:`defaultMode` 收 core `PERMISSION_MODES` **全集**(default | acceptEdits | plan | auto | bypassPermissions | dontAsk),
31
+ * 生效词原样过境 `TaskSpec.permissionMode`,模式**做什么**只在引擎里答(core `modePolicyOf` / `arbitrateByMode`)。本模块的折叠
32
+ * **不读**模式词:deny / ask 两张表在每一个词下编出同一只策略,部署基线照压(tightenTaskSpec deny-wins);bypass 放行的只是引擎
33
+ * 能放行的那几类问,部署 / 请求的 deny 与 ask 规则它一条都掀不掉。
34
34
  *
35
- * 🔴 SYNC WITH sema-cli(壳仓)的 `src/sema/settings/seam.ts`: the permissions→toolPolicy + §6.4 permissionMode derive MIRRORS
35
+ * 🔴 SYNC WITH sema-cli(壳仓)的 `src/sema/settings/seam.ts`: the permissions→toolPolicy compile MIRRORS
36
36
  * the shell's LOCAL-Runner resolver — both compose the SAME core primitives (`createAllowDenyPolicy` /
37
37
  * `combinePolicies` / `tightenTaskSpec`), so the deny-wins ENFORCEMENT is core-single-source. Only the COMPOSITION
38
38
  * is duplicated for the remote path; a proposed follow-up extracts it to `@sema-agent/sdk` for true
@@ -47,27 +47,29 @@
47
47
  * - (`hooks` NO LONGER deferred either — 轴B #2 注释保鲜:applied 形已接线(本文件 hooks 分片 +
48
48
  * main.ts 单用户闸),仅 malformed 才报 deferred;旧「需要 remote hook-runner」是接线前拍照。)
49
49
  */
50
- import { type PathRuleBases, type ExecutionEnv, type TaskSpec, type ThinkingLevel, type ToolPolicy, type PromptProvider, type PermissionMode } from "@sema-agent/core";
50
+ import { type PathRuleBases, type TaskSpec, type ThinkingLevel, type ToolPolicy, type PermissionMode } from "@sema-agent/core";
51
+ import { type EntryProblem } from "./entry-problems.js";
51
52
  import { type KeyClosureIssue } from "./request-key-closure.js";
52
53
  import { type RunnableHooksConfig } from "./hooks/hook-runner.js";
53
54
  import type { StoredHooksRereadM20 } from "./stored-request-hooks-m20.js";
54
55
  import { type EntryPermissionMode } from "./runtime-governance.js";
56
+ import { type TightenOnlySeatValues } from "./tighten-only-seats.js";
55
57
  /**
56
58
  * 请求面 `permissionMode` 的闭集 = core `PERMISSION_MODES` **全集**(顶层 `permissionMode` / `settings.permissions.defaultMode` /
57
59
  * `?permissionMode=` 查询串三处同读)。本仓不持有第二份词表,也不持有「收 / 不收」的表态:判据 = core 的 `isPermissionMode`,型 = core 的
58
- * `PermissionMode`,wire 句子里的词表只从这里取词({@link PERMISSION_MODE_WORDS})。core 加一个词 ⇒ 请求面自动收它,它在派生腿上的去向由
59
- * {@link deriveSettingsPolicy} 的穷举 `switch` 逼出来(缺一臂 ⇒ 编译红);core 删 / 改名一个词 ⇒ 本文件里按名写出它的那一臂编译红。
60
+ * `PermissionMode`,wire 句子里的词表只从这里取词({@link PERMISSION_MODE_WORDS})。core 加一个词 ⇒ 请求面自动收它、原样过境,本仓没有
61
+ * 按词分的臂要补;core 删 / 改名一个词 ⇒ 本仓按名写出它的地方(`PLAN_APPROVE_PERMISSION_MODES_AFTER` 等)编译红。
60
62
  * 生效模式原样过境 `TaskSpec.permissionMode`(S-877):引擎自己解释模式 —— 含 `dontAsk`(CC 的「自动拒」档:凡是要问的一律由模式拒,零卡,
61
- * 门记录 `deniedBy:"mode"`),本仓不另写判。
63
+ * 门记录 `deniedBy:"mode"`)与 acceptEdits 的免问写域(引擎的写根:任务根 + `additionalDirectories` + 宣告的可写目录),本仓不另写判。
62
64
  */
63
65
  /** 请求面闭集的 wire 文案形(`"a" | "b" | …`,core 序)—— 三处 400(顶层 / bundle / 查询串)的句子从这里取词,不再各抄一份。 */
64
66
  export declare const PERMISSION_MODE_WORDS: string;
65
67
  /**
66
68
  * R4: coerce a raw top-level `body.permissionMode` (the LIGHT per-turn wire — the shell sends
67
69
  * the CC permission mode RAW, axis-agnostic; the service interprets) to a service-honored mode, or undefined.
68
- * 🔴 TIGHTEN-ONLY vs the DEPLOYMENT baseline still holds for every value: the mode only selects the CLIENT-derived
69
- * gate ({@link deriveSettingsPolicy}); it can never subtract from the deployment/operator policy (applyTaskSettings
70
- * folds via tightenTaskSpec, deny-wins). The honored set is core's `PERMISSION_MODES` in full — every word passes
70
+ * 🔴 TIGHTEN-ONLY vs the DEPLOYMENT baseline still holds for every value: the word rides verbatim into `TaskSpec.permissionMode`
71
+ * and only the engine interprets it; no mode subtracts from the deployment/operator policy or from the request's own
72
+ * deny / ask rules (applyTaskSettings folds them via tightenTaskSpec, deny-wins, under every word alike). The honored set is core's `PERMISSION_MODES` in full — every word passes
71
73
  * through verbatim (`dontAsk` included: folding the auto-deny mode to `default`, the asking mode, would turn a refusal
72
74
  * into a card). An UNKNOWN string coerces to `default` (fail-safe: the most-asking mode).
73
75
  * [ref]-②: fresh submits can no longer REACH the unknown-word arm — the HTTP gate 400s a non-member value
@@ -147,19 +149,13 @@ export declare function storedBodyPermissionMode(body: {
147
149
  * (= "max"), never a hardcoded literal — so an explicit higher tier still wins (none exists above max today;
148
150
  * future-proof). Awareness rides for free: core composes ORCHESTRATION_AWARENESS from thinking∈{xhigh,max}, no field. */
149
151
  export declare function effectiveThinking(reasoningEffort: unknown, ultracode: boolean): ThinkingLevel | undefined;
150
- /** R4: fold a top-level `body.permissionMode` onto the parsed settings as `permissions.defaultMode` (the top-level
151
- * field is the explicit per-turn intent → it WINS over a bundle defaultMode). Creates a minimal settings object when
152
- * no `body.settings` bundle was sent. The result flows through {@link applyTaskSettings} (tighten-only). */
153
- export declare function withPermissionMode(settings: ParsedTaskSettings | undefined, mode: PermissionMode): ParsedTaskSettings;
154
152
  /**
155
- * [ref] §6-1 —— 本请求的**生效** permission mode,单点。优先序逐字同 {@link withPermissionMode}:
156
- * 顶层 `body.permissionMode`(本轮显式表态)赢过 bundle 的 `settings.permissions.defaultMode`;两处
157
- * 都没有 ⇒ `undefined` = **无表态**(调用点据此不写键,而不是替调用方选一个默认值)。
153
+ * [ref] §6-1 —— 本请求的**生效** permission mode,单点。优先序:顶层 `body.permissionMode`(本轮显式表态)赢过 bundle 的
154
+ * `settings.permissions.defaultMode`;两处都没有 ⇒ `undefined` = **无表态**(调用点据此不写键,而不是替调用方选一个默认值;引擎把缺席读成 `default`)。
158
155
  *
159
- * 🔴 为什么必须是一只函数:同一个「生效模式」此前在 resolve-spec 里被算了两次(hooks 腿的
160
- * `permission_mode` 载荷、settings 折叠腿的 `withPermissionMode`),三审同点判定翻译表**不得**成为
161
- * 第三个算点 —— 三处各算各的,任何一次优先序修订都会让三面分家,而分家在这条轴上的形态是
162
- * 「壳发的 bundle bypass 在 A 面生效、在 B 面没生效」这种最难被外部发现的静默偏差。
156
+ * 🔴 为什么必须是一只函数:同一个「生效模式」此前在 resolve-spec 里被算过两次(hooks 腿的 `permission_mode` 载荷、settings 折叠腿),
157
+ * 两处各算各的,任何一次优先序修订都会让两面分家,而分家在这条轴上的形态是「壳发的 bundle bypass 在 A 面生效、在 B 面没生效」这种
158
+ * 最难被外部发现的静默偏差。settings 折叠今天不再读模式词,这只函数的读者是 spec 过境点、托管天花板与存储体读法。
163
159
  */
164
160
  export declare function effectivePermissionMode(body: {
165
161
  permissionMode?: unknown;
@@ -216,7 +212,7 @@ export interface ParsedTaskSettings {
216
212
  ultracode?: boolean;
217
213
  /** hooks hook-runner(阶段一):经 `parseHooksConfig`(契约包分类器 + 服务侧上限 + 本仓会跑的条目类型)判过的 hooks 配置。像 shellEnv 一样
218
214
  * 这里只 PARSE;应用点(main.ts resolveSpec)按单用户闸(`requirePrincipal !== true`)决定翻不翻成
219
- * core `TaskSpec.hooks` 回调——多租户 lane 收到只警告忽略(hook 命令跑在 worker host = class ② 能力授予)。 */
215
+ * 任务座 `TaskSpec.mods` 上的一张注册 `settings.hooks`——多租户 lane 收到只警告忽略(hook 命令跑在 worker host = class ② 能力授予)。 */
220
216
  hooks?: RunnableHooksConfig;
221
217
  /** [ref](7.77.0)—— CC settings 同名键:上下文窗口里**留给技能清单**的比例((0,1];CC 默认 0.01 = 1%)。
222
218
  * 超预算时引擎把描述裁短、再不够退成 name-only(`cli259.js` 的清单渲染算法),**从不**拒掉一条技能 ——
@@ -225,6 +221,10 @@ export interface ParsedTaskSettings {
225
221
  skillListingBudgetFraction?: number;
226
222
  /** 同族第二键:每条技能描述在清单里的字符帽(正整数;CC 默认 1536)。超出由引擎**截断**,不是拒。 */
227
223
  skillListingMaxDescChars?: number;
224
+ /** S-1351 —— 「只收紧」座位族(`tighten-only-seats.ts` 的四座:读拒模式 / 写保护名的加法 / 合规额外禁项 / 永不自动放行名单)的归一值,**一个键**而不是四个散字段:
225
+ * wire 位置由座位表说(三座在 `settings` 顶层,`neverAuto` 在 `settings.permissions`),解析后与位置无关。空数组 ≡ 缺席(不铸键)。
226
+ * 去处:三座经 {@link applyTaskSettings} 落 core 任务层席;`neverAuto` 经 {@link deriveSettingsPolicy} 落请求叶策略。 */
227
+ tightenOnly?: TightenOnlySeatValues;
228
228
  }
229
229
  /** The result of parsing an untrusted `body.settings`: the applied subset + the names of present-but-deferred
230
230
  * fields (so the caller can log/advertise them — no silent drop). `null` settings ⇒ `{ settings: undefined }`. */
@@ -285,13 +285,17 @@ export declare function settingsPermissionBucketIssue(perms: unknown): SettingsP
285
285
  * {@link parseTaskSettings};`webSearch` 在 `capabilities/scenarios.ts`(判决 `judgeRequestWebSearch`,单用户闸;形错在受理面 400,S-199)。
286
286
  * 加键必须同时加消费点,否则就是往闭集里塞一个新的静默丢。
287
287
  *
288
+ * 🔴 `readDenyPatterns` / `writeProtectedExtra` / `complianceAdditionalDenies` 与 `permissions.neverAuto`(S-1351)= **「只收紧」座位族**:消费点 = `tighten-only-seats.ts`
289
+ * 的座位表(位置、条目律、去处都由那张表说),读入在 {@link parseTaskSettings},投影在 {@link applyTaskSettings} / {@link deriveSettingsPolicy}。这四个键不是 CC settings 键
290
+ * (sdk 的 `SemaSettings` 尚未声明 —— 对账门 `test/task-settings-sdk-key-parity.test.ts` 的「server 先于 sdk」登记表记着它们)。
291
+ *
288
292
  * 🔴 两个 `skillListing*`([ref],7.77.0)= **CC settings 同名键**,值域抄 CC 的 schema 声明
289
293
  * (`skillListingBudgetFraction` 是 `gt(0).lte(1)`、`skillListingMaxDescChars` 是 `int().positive()`);
290
294
  * 消费点 = 本文件的 parse + `boot/resolve-spec.ts` 的 `TaskSpec` 透传。语义(预算怎么花、描述怎么裁、
291
295
  * 溢出怎么退成 name-only)整个归引擎,本仓一个字节都不渲染,也**不复刻默认值**——缺席即整键不写。 */
292
- export declare const TASK_SETTINGS_KEYS: readonly ["env", "hooks", "model", "outputStyle", "permissions", "skillListingBudgetFraction", "skillListingMaxDescChars", "ultracode", "webSearch"];
296
+ export declare const TASK_SETTINGS_KEYS: readonly ["complianceAdditionalDenies", "env", "hooks", "model", "outputStyle", "permissions", "readDenyPatterns", "skillListingBudgetFraction", "skillListingMaxDescChars", "ultracode", "webSearch", "writeProtectedExtra"];
293
297
  /** 本 service 消费的 `settings.permissions` 子键 —— 闭集(值形校验另有既有门,本门只判键名)。 */
294
- export declare const TASK_SETTINGS_PERMISSION_KEYS: readonly ["allow", "ask", "defaultMode", "deny", "disableAutoMode"];
298
+ export declare const TASK_SETTINGS_PERMISSION_KEYS: readonly ["allow", "ask", "defaultMode", "deny", "disableAutoMode", "neverAuto"];
295
299
  /** CC/SDK 合约里合法、本 service **不接线**的顶层键。词表外的 CC 键落 `unknown` —— 两列都是 400,标签只影响
296
300
  * 文案,不影响判决。前三个的出处 = `@sema-agent/sdk` `SemaSettings` 尾注逐字点名的 deferred CC 键。
297
301
  *
@@ -324,7 +328,7 @@ export declare function taskSettingsKeyIssue(raw: unknown): KeyClosureIssue | nu
324
328
  * 🔒 **`settings.hooks` 会不会被采纳** —— 全仓**唯一**的车道谓词(S-995,主会话裁):hook 命令跑在 WORKER HOST([ref] class ② 能力授予),所以只有单用户车道
325
329
  * (`requirePrincipal !== true`,与 scheduler / backgroundShell / lspHost / MCP 注入同一姿势)采纳;多租户车道收到 hooks **整只忽略**(`task_hooks_ignored`),绝不执行。
326
330
  * 三处读它,谁也不许内联 `requirePrincipal`(各写各的 = 迟早漂):
327
- * · `boot/resolve-spec.ts` —— 装配:不采纳 ⇒ 不装 `TaskSpec.hooks` + 一条 `task_hooks_ignored`;
331
+ * · `boot/resolve-spec.ts` —— 装配:不采纳 ⇒ 不铸 `TaskSpec.mods` 的 `settings.hooks` 注册 + 一条 `task_hooks_ignored`;
328
332
  * · `http/routes/capabilities.ts` —— 能力位 `taskSettings.hooks`(「says yes ⟺ route works」);
329
333
  * · `http/admission.ts` —— fresh 受理面的「别名 matcher 永不命中」判据的**求值深度**:采纳 ⇒ `"regex"`(运行期同一只匹配函数,带资源闸);不采纳 ⇒ `"literal"`
330
334
  * (7.112.0 的字面判:零调用方正则执行 —— 受理面是所有车道,租户不能借一只灾难回溯的 matcher 占满事件循环)。
@@ -350,71 +354,39 @@ export declare function parseTaskSettings(raw: unknown, seats?: ParseTaskSetting
350
354
  * value must not become active prompt content after rollout (context exhaustion / spend hole). Over-cap ⇒ dropped +
351
355
  * warned — the rider was inert pre-upgrade, so dropping preserves the stored task's prior behavior; a 4xx here would
352
356
  * permanently brick that task's resume instead (same defensive posture as parseTaskSettings' outputStyle drop).
353
- * Cap value = the submit gate's (16384; MAX_SETTINGS_OUTPUT_STYLE_CHARS — both land in the same spec field). */
354
- /** TRUE when `text` is an ALREADY-ASSEMBLED system prompt — core's migration guard detects the same three
355
- * constitution anchors and takes the pass-through assembler arm, whose section subset (OPAQUE_KEPT, dist-read)
356
- * has NO `core/role.append`: any append rider (top-level or settings.outputStyle) would be SILENTLY discarded
357
- * there. Shared predicate for the submit 400 gate, the resolveSpec resume mirror, and the center-declaration
358
- * probe — one definition so the three gates can't drift. */
359
- export declare function hasConstitutionAnchors(text: unknown): boolean;
360
- /** codex R9 (provider-aware append-less detection): mirrors core's ACTUAL pass-through triggers instead of a raw
361
- * body-text heuristic — the assembler's migration guard probes (a) `stableBlocks` identity declarations and
362
- * (b) `stableSystem` OUTPUT for the three anchors; a plain `userSystemPrompt` under the DEFAULT provider (no
363
- * scenario provider) never triggers it and `core/role.append` is retained, so an anchored systemPrompt there
364
- * must NOT block/strip a rider (R9 false-positive: unbranded default / scan rejected valid combos). Probing
365
- * calls the provider hooks with a minimal ctx — server providers (and centerPromptProvider) are pure functions
366
- * of ctx, and the same hooks run again inside core's assembly; a hook throw = conservative false (core will
367
- * fail the task loudly on its own). `replaceAll` owns the whole prompt(legacy free-form `system()` 腿已随 core 2.0.0 删除)
368
- * (REPLACE_ALL_EXCLUDED strips role.append) → append-less true. */
369
- export declare function providerDropsAppend(provider: PromptProvider | undefined, userSystemPrompt: string | undefined): boolean;
370
- export declare function acceptAppendSystemPrompt(v: unknown, warn?: (detail: string) => void, packDropsAppend?: boolean): string | undefined;
357
+ * Cap value = the submit gate's (16384; MAX_SETTINGS_OUTPUT_STYLE_CHARS — both land in the same spec field).
358
+ * A well-formed rider always mounts: the engine (core 7.52.0) lands it in its own task-append band whatever the role
359
+ * text is — there is no "already-assembled" pass-through arm left that could drop it. */
360
+ export declare function acceptAppendSystemPrompt(v: unknown, warn?: (detail: string) => void): string | undefined;
361
+ export declare function createWorkflowAskPolicy(isExempt?: WorkflowGateWiring["isExempt"]): ToolPolicy;
371
362
  /** [ref]②/codex F2 — what the workflow ask leg needs from the deployment, on EVERY lane. It is name-keyed and
372
- * fs-independent, so it never had the lane split {@link FsWriteGateWiring} carried (that split is itself gone
373
- * since [ref] — the sandbox lanes wire a gate of their own shape instead of no gate). */
363
+ * fs-independent: one shape on every execution lane. */
374
364
  export interface WorkflowGateWiring {
375
- /** The session "don't ask again" probe (approvalExemptionStore.has, canonical toolName key) — same store and
376
- * key space as the fs-write gate's probe; one remember="session" grant serves both. */
365
+ /** The session "don't ask again" probe (approvalExemptionStore.has, raw toolName key) — the same store and key space the
366
+ * approval seat's standing grants read; one remember="session" grant serves them all. */
377
367
  isExempt?: (toolName: string) => boolean | Promise<boolean>;
378
368
  }
379
- /** [ref]/[ref]① — everything the mode-derived fs-write ask gate needs from the deployment, provided by
380
- * `resolve-spec.ts`. Absent ⇒ no gate is derived (the pre-[ref] behavior).
381
- *
382
- * WHY the `env` matters: core's `createFsWriteGatePolicy` canonicalizes every target/dir through the given `env`
383
- * (real `exists`/`canonicalPath`/`readLink` fs access — read in dist, fs-write-gate-policy.js), so on a
384
- * HOST-SEMANTICS lane (`REMOTE_EXEC` unset or "host") the env MUST be the fs the hand tools write.
369
+ /**
370
+ * 请求的 deny / ask 两张表解析路径形规则用的**基**(`resolve-spec.ts` 每请求供)。只有这两件事:这条 task 的真根、执行环境的 home。
371
+ * 缺席 ⇒ 不声明(规则锚在装入这只策略的那条腿的真根,`~/` 形由 {@link rejectUnmatchableSettingsNames} 响亮拒)。
385
372
  *
386
- * [ref]/[ref] — the sandbox lanes (e2b/k8s/ssh/adb/local-docker) wire a gate TOO, but a different-shaped one: the
387
- * tools run OFF this box and the per-task sandbox env is minted inside core (executionEnvFactory) AFTER spec
388
- * build, so a worker-local env would adjudicate against the WRONG fs (a wrong ALLOW is worse than no gate — that
389
- * is why [ref] left those lanes gate-less). They supply a `DeferredSandboxPathEnv`
390
- * (`src/boot/deferred-sandbox-path-env.ts`) instead: a proxy that forwards the fs READ primitives to the task's
391
- * REAL sandbox env at adjudication time (a per-session slot the factory decorator fills), keeping only
392
- * `absolutePath` lexical so no relative path is resolved against the wrong base. Empty slot ⇒ fail-closed. */
373
+ * 修前本型还承运本仓自己的 acceptEdits cwd 域写门的四件(裁决 env / cwd / scratchpad 豁免域 / 会话豁免探针):acceptEdits 能免问写哪里
374
+ * 现在只由引擎的模式门答(写根 = 任务根 + `additionalDirectories` + 宣告的可写目录),本仓不再构造写门,那四件随之退役。
375
+ * 部署级旋钮(`SENSITIVE_WRITE_PATTERNS` 守卫集、`MANUAL_MODE_SHELL_GATE` 地板)早已不经本型:它们在治理层无条件施加
376
+ * (`runtime-governance.ts` `applyRuntimeGovernance`),client 表态掀不掉([ref] / [ref])。
377
+ */
393
378
  export interface FsWriteGateWiring {
394
- /** The env the gate canonicalizes against — the worker host env on the host lane, the
395
- * `DeferredSandboxPathEnv` proxy over the task's real sandbox env on the sandbox lanes ([ref]). */
396
- env: ExecutionEnv;
397
- /** The task's working directory: the factory's `rootPath` (relative-path base) AND the acceptEdits accept domain.
398
- * ABSENT on the sandbox lanes ([ref]/[ref]): the sandbox cwd is the ENGINE's tracked cwd, not the env's own, so
399
- * neither spec time nor the env proxy can supply the right base — inventing one would mint a bogus auto-allow
400
- * domain. With it absent the gate gets no `rootPath` and no `acceptDirs`, so relative paths fail to resolve
401
- * (⇒ ask) and `acceptEdits` degrades to the `default` arm — the same fail-safe direction as the host lane's
402
- * never-created sentinel dir (resolve-spec 修5). */
403
- cwd?: string;
404
379
  /**
405
- * 🔴 S-177 / codex r1 [high](验真后修)—— **权限规则**的路径基,与上面那个 `cwd` **刻意分成两个字段**。
380
+ * 🔴 S-177 / codex r1 [high](验真后修)—— **权限规则**的路径基(core `PathRuleBases.root`),**只在真任务根已知时**在场。
406
381
  *
407
- * 两者在 host 腿上常常同值,但它们回答的不是同一个问题,而混用一个字段会让其中一个静默失效:
408
- * · `cwd` 是**写门**的基。它在「有 remoteExec 但这条 session 还没登记工作目录」时取的是一个
409
- * **永不创建的哨兵目录**(`resolve-spec` 的 `fs-write-gate-unrooted`)。对写门那是 fail-SAFE 的:
410
- * 相对目标在哨兵下解析不出真身 ⇒ 落 ask。
411
- * · `taskRoot` 是**规则模式**的基(core `PathRuleBases.root`)。规则编译器按**词法**匹配,不问目录
412
- * 存不存在 ⇒ 把哨兵递给它,`deny Edit(src/**)` 会编译成功、指向一个谁也不会写的目录,对真实工作区
413
- * 的 `<工作区>/src/secret.ts` 这类目标判 allow —— 一条运维亲手写下的收紧规则**静默失效**,方向与写门那条正相反。
382
+ * host 腿上「这条 session 还没登记工作目录」时,`resolve-spec` 的路径裁决 env 落在一个**永不创建的哨兵目录**上
383
+ * (`fs-write-gate-unrooted`,治理层守卫集的 cwd)。那对守卫是 fail-SAFE 的(相对目标在哨兵下解析不出真身);但规则编译器按**词法**匹配、
384
+ * 不问目录存不存在 ⇒ 把哨兵当根递进来,`deny Edit(src/**)` 会编译成功、指向一个谁也不会写的目录,对真实工作区的
385
+ * `<工作区>/src/secret.ts` 判 allow —— 一条亲手写下的收紧规则**静默失效**。所以哨兵从不被声明成基。
414
386
  *
415
- * ⇒ 本字段**只在真任务根已知时**在场。缺席 ⇒ 不声明根 ⇒ 需要该基的拼法(`Edit(src/**)` / `Edit(/etc/**)`)锚在**装入这只策略的那条腿**
416
- * 的真根(core 7.46.0 #1383 车 B:锚装一次、在被装入处;`unsupported.path_base` 只剩「声明了一个用不了的基」)—— 哨兵从不被声明成基。
417
- * 修前(core ≤7.45)缺席 ⇒ 整表拒(→ 422):沙箱车道上相对 / `/x` 形规则恒 422。绝对形(`//abs`)不需要基;`~/` 形见下一字段。
387
+ * 缺席 ⇒ 不声明根 ⇒ 需要该基的拼法(`Edit(src/**)` / `Edit(/etc/**)`)锚在**装入这只策略的那条腿**的真根(core 7.46.0 #1383 车 B:
388
+ * 锚装一次、在被装入处;`unsupported.path_base` 只剩「声明了一个用不了的基」)。修前(core ≤7.45)缺席 ⇒ 整表拒(→ 422):沙箱车道上
389
+ * 相对 / `/x` 形规则恒 422。绝对形(`//abs`)不需要基;`~/` 形见下一字段。
418
390
  */
419
391
  taskRoot?: string;
420
392
  /**
@@ -444,29 +416,20 @@ export interface FsWriteGateWiring {
444
416
  * 运维在**下单那一刻**就知道这条规则这条车道读不了,而不是等到跑起来每次都弹一张 ask。
445
417
  */
446
418
  taskHome?: string;
447
- /** The session scratchpad dir (envFacts.scratchpadDir, [ref]③) — writes there are always auto-allowed. */
448
- scratchpadDir?: string;
449
- /** [ref]① / core 1.294 exemption seam: the session "don't ask again" probe (approvalExemptionStore.has),
450
- * called by core as `(canonicalToolName, canonicalPath)`. The host arm ignores the second argument (the key
451
- * comes from a real-fs canonicalize and the grant is deliberately name-keyed); the sandbox arm ([ref]) uses it
452
- * to confine the exemption to POSIX-absolute canonical keys — core's `canonicalizeTarget` short-circuits
453
- * backslash-UNC forms to `ok:true, key=raw` WITHOUT consulting the env, and an unconfined name-keyed grant
454
- * would turn those unresolvable forms into an allow (codex review 2026-08-05).
455
- * 🔴 **坐标刷新(7.74.0 / core 7.17.0 [ref];结论不变,前提收窄了)**:那条短路现在**只在 `win` 家族上**
456
- * (`dist/tools/fs/safety.js` 的 `canonicalizeTarget`:`family === "win" && isUncSpelling(...)` 才折 UNC
457
- * 并直接返回);在 `posix` 家族上,同一个反斜杠 UNC 拼法在更早一步的 `win32NamespaceScreen` 上就被
458
- * **拒**(`unc_on_posix_tree`),压根到不了短路。⇒ 今日部署形(posix 树)这条腿的暴露面比当年更小,
459
- * 而本臂的 POSIX-absolute 收敛**继续是对的**:它挡的是「未经 env 解析的 key 拿到 name-keyed 放行」,
460
- * 在两个家族上都成立,且方向仍是 fail-closed。不改实现。
461
- * The probe is consulted by the gate RIGHT BEFORE it would ask (after the exempt/accept dir layering — dist 亲读:true ⇒
462
- * allow with decisionReason "rule", a THROWN probe ⇒ not exempt = fail-closed to ask). Same canonical
463
- * toolName key space as the ask-policy layer's exemption probe — ONE grant serves both layers; the gate-level
464
- * check is what makes "allow all session" bite SAME-TURN for the parent and inherited child tasks (the ask
465
- * path is never re-entered). (codex M1 的边界注记:sensitive-path DENY 腿与本探针的「豁免越不过 deny」
466
- * 保证仍成立——但那条腿已随 [ref] 搬到 governance 层,deny-wins 是 tightenTaskSpec 折叠给的,不再依赖
467
- * 本 wiring 的组合点。) */
468
- isExempt?: (toolName: string, canonicalPath: string) => boolean | Promise<boolean>;
469
419
  }
420
+ /**
421
+ * 请求的 `settings.permissions.deny` / `ask` 有永远不生效的条目 ⇒ 拒点({@link rejectUnmatchableSettingsNames})抛的错:句子(`message`)与这一遍判下来的**全部**问题(`problems`,机读位的原料)。
422
+ * `resolveSpec` 的折叠口把它装成 422 体(句子照旧、码 {@link SETTINGS_RULE_REFUSAL_CODE}、体带 `field` + `detail.problems`);其余出口(收紧不得放宽)仍抛普通 `Error`。
423
+ */
424
+ export declare class SettingsRuleRefusalError extends Error {
425
+ readonly problems: readonly EntryProblem[];
426
+ constructor(message: string, problems: readonly EntryProblem[]);
427
+ }
428
+ /**
429
+ * 请求设置里 deny / ask 规则拒的**码**:422 在折叠口上的状态派生粗码(`http/send.ts` 的 `httpErrorCode(422)`;`test/entry-problems.test.ts` 钉两者同值)。拒点铸 422 体、存体预判铸 409 的 `blockedBy`、
430
+ * 机读位每条问题的 `code` 三处读这一只常量,不各写一份字面量。
431
+ */
432
+ export declare const SETTINGS_RULE_REFUSAL_CODE = "request.unprocessable";
470
433
  /**
471
434
  * deny / ask 两桶(core 规则编译器读的收紧表)的**问序,单表**:{@link rulePolicyBucketsRefusal} 的两段循环(名字层 + 文法 · `~/` 要 home)都迭代它 ——
472
435
  * 两桶都有坏条目时,拒点与存体预判点名同一个桶、说同一句。表里每个词同时是 core 规则的 `behavior`。
@@ -475,7 +438,8 @@ export declare const RULE_POLICY_BUCKETS: readonly ["ask", "deny"];
475
438
  export type RulePolicyBucket = (typeof RULE_POLICY_BUCKETS)[number];
476
439
  /**
477
440
  * deny / ask 两桶的**完整规则判**,唯一一只(拒点 {@link rejectUnmatchableSettingsNames} 与存体预判 `http/stored-body-replay.ts` 同调):
478
- * ② 按 {@link RULE_POLICY_BUCKETS} 的序逐桶问 `unmatchableToolNamesRefusal`(名字层 + core 规则文法);③ 都过了,再逐桶判 `~/` 形要 home 的那一拒。第一个坏处答 `{ bucket, message }`。
441
+ * ② 按 {@link RULE_POLICY_BUCKETS} 的序逐桶问 `judgeUnmatchableToolNames`(名字层 + core 规则文法);③ 再逐桶判 `~/` 形要 home 的那一拒。答 `{ bucket, message, problems }`:`bucket` 与 `message` 是**第一处**坏处的
442
+ * (句子冻结,先撞上的那一条),`problems` 是**两段、两只桶判下来的全部**坏条目(机读位的原料,形的属主 `entry-problems.ts`)。
479
443
  * 入参:桶、{@link RulePolicyBases}。**home 同源**:拒点的 home 是 `resolve-spec.ts` 的 `laneHomeBase()` 经 `executionLaneHomeDir(config)` 算出的,预判传同一个函数对同一份部署配置算出的。
480
444
  * **声明给文法的基**只有拒点有(根 + home 的并集,执行车道才知道根):core 的规则文法对**没声明**的基不下判词(见 `config.ts` `uncompilableRuleGuidance`),所以预判什么也不声明、两腿逐字同句;
481
445
  * 预判不能把 home 当「半个基」声明给文法 —— core 的路径族只从根推,缺根时一个合法的 Windows 形 home 会按默认族被判 `unsupported.path_base`(V6-k)。
@@ -490,12 +454,35 @@ export interface RulePolicyBases {
490
454
  export declare function rulePolicyBucketsRefusal(permissions: Readonly<Partial<Record<RulePolicyBucket, readonly string[]>>>, bases: RulePolicyBases): {
491
455
  readonly bucket: RulePolicyBucket;
492
456
  readonly message: string;
457
+ readonly problems: readonly EntryProblem[];
493
458
  } | undefined;
494
459
  /** 请求的 settings 编不成生效的规则 / 有永远不生效的条目 ⇒ 422 的句首(三只桶同一个出口;`resolveSpec` 的拒点与存体重放预判的 409 句子同用这一个,不各写一份)。 */
495
460
  export declare const REQUEST_SETTINGS_REFUSAL_PREFIX = "request settings cannot be applied as written: ";
496
- export declare function deriveSettingsPolicy(settings: ParsedTaskSettings, gate?: FsWriteGateWiring, workflowGate?: WorkflowGateWiring): {
461
+ /**
462
+ * Build the per-request permission ToolPolicy from the parsed settings: the two **rule lists** (`deny` / `ask`) through ONE compiler
463
+ * ({@link createRuleListPolicy} → core `createPermissionRulePolicy`) — a `deny` rule hard-blocks, an `ask` rule forces an approval
464
+ * gate, `deny` > `ask` on overlap. 两表的 **covering 语义同源**([ref]):底下是 core 的同一只 `namespacedRuleNameCovers`,本仓不持第二套 glob。
465
+ * The `allow` bucket is not here: a policy says deny / ask only (core 7.42.0); the list rides into `TaskSpec.allowedTools` at
466
+ * {@link applyTaskSettings}, the one write point.
467
+ *
468
+ * 🔴 **本函数不读模式词**:两张表在六个词与缺席下编出同一只策略(`test/settings-fold-mode-arms.test.ts` A2)。模式做什么只在引擎里答 ——
469
+ * 写门(`default` / `auto` / `dontAsk`:每次写先问;`acceptEdits`:写根内免问;`plan`:写与非只读调用以计划句问;`bypassPermissions`:不设门)
470
+ * 是引擎的模式门,`Workflow` 的问句腿在 `resolve-spec.ts` 按「这条 run 挂不挂得出 Workflow」装、由引擎的仲裁按模式处置({@link createWorkflowAskPolicy})。
471
+ * 修前这里按模式分四臂(acceptEdits 另铸一只 cwd 域写门、bypass / 缺席不装问句腿):本仓对模式的第二份解释,随之退役。
472
+ * Returns `{}` when there is no permission rule (nothing to project).
473
+ */
474
+ export declare function deriveSettingsPolicy(settings: ParsedTaskSettings, bases?: FsWriteGateWiring): {
497
475
  toolPolicy?: ToolPolicy;
498
476
  };
477
+ /**
478
+ * 请求的 `settings.permissions.neverAuto` 有永远不生效的名字 ⇒ 拒因(句子 + 机读位),与 {@link rulePolicyBucketsRefusal} 同形 —— 拒点({@link deriveSettingsPolicy},422)与存体预判
479
+ * (`http/stored-body-replay.ts`)调这一只。判据与部署 `APPROVAL_NEVER_AUTO` 的 env 腿是**同一只**(`unmatchableToolNamesRefusal` 的名表消费者:退役名 / 无协议前缀的短名 / 缺段协议名 /
480
+ * 近似名 …),一条规则一种读法;机读位的 `field` = 座位在体内的坐标。无名字 / 全合法 ⇒ `undefined`。
481
+ */
482
+ export declare function neverAutoNamesRefusal(names: readonly string[]): {
483
+ readonly message: string;
484
+ readonly problems: readonly EntryProblem[];
485
+ } | undefined;
499
486
  /**
500
487
  * Apply a client's parsed per-request settings onto a base `TaskSpec`, TIGHTEN-ONLY, in a SINGLE {@link
501
488
  * tightenTaskSpec} pass (so the permission override composes deny-wins onto the baseline — TRAP #1). `tightenTaskSpec`
@@ -506,5 +493,5 @@ export declare function deriveSettingsPolicy(settings: ParsedTaskSettings, gate?
506
493
  *
507
494
  * Returns `base` untouched when the parsed settings project nothing onto the spec.
508
495
  */
509
- export declare function applyTaskSettings(base: TaskSpec, settings: ParsedTaskSettings, gate?: FsWriteGateWiring, workflowGate?: WorkflowGateWiring): TaskSpec;
496
+ export declare function applyTaskSettings(base: TaskSpec, settings: ParsedTaskSettings, bases?: FsWriteGateWiring): TaskSpec;
510
497
  //# sourceMappingURL=task-settings.d.ts.map
@@ -1,13 +1,17 @@
1
- import { combinePolicies, createFsWriteGatePolicy, parseRuleText, resolveReasoningProfile, rankOf, isThinkingLevel, CYBER_RISK, URL_SAFETY, HARNESS_SECTION_ANCHOR, RUN_WORKFLOW_TOOL_NAME, PERMISSION_MODES, isPermissionMode, ruleToolGrammarOf, } from "@sema-agent/core";
2
- import { unmatchableToolNamesRefusal } from "./config.js";
1
+ import { combinePolicies, parseRuleText, resolveReasoningProfile, rankOf, isThinkingLevel, RUN_WORKFLOW_TOOL_NAME, PERMISSION_MODES, isPermissionMode, ruleToolGrammarOf, } from "@sema-agent/core";
2
+ import { judgeUnmatchableToolNames } from "./config.js";
3
+ import { entryProblem } from "./entry-problems.js";
3
4
  import { MAX_PERMISSION_RULES_PER_LIST, createRuleListPolicy } from "./permission-rule-list.js";
4
5
  import { allowLayerEntryCountIssue, describeAllowLayerOverCap, ruleEntryListShapeOk } from "./rule-entry-list.js";
6
+ import { limitRefusal } from "./limit-refusal.js";
5
7
  import { tightenGoverned } from "./governance-overrides.js";
6
8
  import { MAX_KEY_ECHO, keyClosureClause, scanKeyClosure } from "./request-key-closure.js";
7
9
  import { parseHooksConfig } from "./hooks/hook-runner.js";
8
10
  import { heldRuleName } from "./tool-rule-names.js";
9
11
  import { entryPermissionMode } from "./runtime-governance.js";
10
12
  import { policyAskStandingAnswerFacts, standingAnswerDurablyRecordable } from "./tool-approval.js";
13
+ import { createRequestNeverAutoPolicy } from "./approval.js";
14
+ import { readTightenOnlySeats, tightenOnlySeatField, tightenOnlySpecSeats } from "./tighten-only-seats.js";
11
15
  export const PERMISSION_MODE_WORDS = PERMISSION_MODES.map((m) => `"${m}"`).join(" | ");
12
16
  export function coercePermissionMode(raw) {
13
17
  const strict = coercePermissionModeStrict(raw);
@@ -47,10 +51,6 @@ export function effectiveThinking(reasoningEffort, ultracode) {
47
51
  const ultra = resolveReasoningProfile("ultra").thinking;
48
52
  return explicit && rankOf(explicit) > rankOf(ultra) ? explicit : ultra;
49
53
  }
50
- export function withPermissionMode(settings, mode) {
51
- const base = settings ?? {};
52
- return { ...base, permissions: { ...base.permissions, defaultMode: mode } };
53
- }
54
54
  export function effectivePermissionMode(body, settings) {
55
55
  const requested = coercePermissionMode(body.permissionMode) ?? settings?.permissions?.defaultMode;
56
56
  const kill = settings?.permissions?.disableAutoMode;
@@ -93,8 +93,9 @@ function bucketIssueMessage(f, rule) {
93
93
  case "over_cap":
94
94
  switch (rule) {
95
95
  case "rule_policy":
96
- return (`${f.field} has ${f.count} entries — at most ${f.cap} are accepted. Refused rather than truncated: a truncated list silently drops the rules past the cap, ` +
97
- `and a dropped deny / ask rule is a tightening that never happened. Merge rules into broader patterns or trim the list`);
96
+ return limitRefusal(f.field, "entries", f.count, f.cap, {
97
+ tail: "Refused rather than truncated: a truncated list silently drops the rules past the cap, and a dropped deny / ask rule is a tightening that never happened. Merge rules into broader patterns or trim the list",
98
+ }).message;
98
99
  case "allow_layer":
99
100
  return describeAllowLayerOverCap(f.field, f.count);
100
101
  }
@@ -138,7 +139,7 @@ export function settingsPermissionBucketIssue(perms) {
138
139
  case "allow_layer": {
139
140
  const over = allowLayerEntryCountIssue(field, v);
140
141
  if (over !== undefined)
141
- fields = { field, reason: "over_cap", count: over.count, cap: over.cap };
142
+ fields = { field, reason: "over_cap", count: over.facts.count, cap: over.facts.cap };
142
143
  else if (!ruleEntryListShapeOk(v))
143
144
  fields = { field, reason: "bad_entry", index: v.findIndex((x) => typeof x !== "string") };
144
145
  break;
@@ -153,8 +154,8 @@ export function settingsPermissionBucketIssue(perms) {
153
154
  function acceptedRuleList(v) {
154
155
  return Array.isArray(v) && v.length > 0 ? v.slice() : undefined;
155
156
  }
156
- export const TASK_SETTINGS_KEYS = ["env", "hooks", "model", "outputStyle", "permissions", "skillListingBudgetFraction", "skillListingMaxDescChars", "ultracode", "webSearch"];
157
- export const TASK_SETTINGS_PERMISSION_KEYS = ["allow", "ask", "defaultMode", "deny", "disableAutoMode"];
157
+ export const TASK_SETTINGS_KEYS = ["complianceAdditionalDenies", "env", "hooks", "model", "outputStyle", "permissions", "readDenyPatterns", "skillListingBudgetFraction", "skillListingMaxDescChars", "ultracode", "webSearch", "writeProtectedExtra"];
158
+ export const TASK_SETTINGS_PERMISSION_KEYS = ["allow", "ask", "defaultMode", "deny", "disableAutoMode", "neverAuto"];
158
159
  export const TASK_SETTINGS_UNSUPPORTED_KEYS = ["apiKeyHelper", "crossSessionInbound", "dialogExpiry", "sandbox", "statusLine"];
159
160
  export const TASK_SETTINGS_UNSUPPORTED_PERMISSION_KEYS = ["additionalDirectories", "disableBypassPermissionsMode"];
160
161
  const ACCEPTED_TOP = new Set(TASK_SETTINGS_KEYS);
@@ -193,6 +194,9 @@ export function taskSettingsKeyIssue(raw) {
193
194
  export function taskHooksHonored(config) {
194
195
  return config.requirePrincipal !== true;
195
196
  }
197
+ function tightenOnlySeatDeferredName(name) {
198
+ return tightenOnlySeatField(name).replace(/^settings\./, "");
199
+ }
196
200
  export function parseTaskSettings(raw, seats = {}) {
197
201
  if (raw === null || raw === undefined || typeof raw !== "object")
198
202
  return { deferred: [] };
@@ -260,36 +264,14 @@ export function parseTaskSettings(raw, seats = {}) {
260
264
  const maxDesc = s.skillListingMaxDescChars;
261
265
  if (skillListingMaxDescOk(maxDesc))
262
266
  out.skillListingMaxDescChars = maxDesc;
267
+ const tightenSeats = readTightenOnlySeats(raw);
268
+ for (const name of tightenSeats.rejected)
269
+ deferred.push(tightenOnlySeatDeferredName(name));
270
+ if (Object.keys(tightenSeats.values).length > 0)
271
+ out.tightenOnly = tightenSeats.values;
263
272
  return { settings: Object.keys(out).length > 0 ? out : undefined, deferred, ...(hooksReread !== undefined ? { hooksReread } : {}) };
264
273
  }
265
- export function hasConstitutionAnchors(text) {
266
- return typeof text === "string" && text.includes(CYBER_RISK) && text.includes(URL_SAFETY) && text.includes(HARNESS_SECTION_ANCHOR);
267
- }
268
- export function providerDropsAppend(provider, userSystemPrompt) {
269
- if (!provider)
270
- return false;
271
- if (provider.replaceAll === true)
272
- return true;
273
- const ctx = { userSystemPrompt, tools: [], memoryEnabled: false, consolidationEnabled: false };
274
- if (provider.stableBlocks) {
275
- try {
276
- return provider.stableBlocks(ctx).some((d) => d.slot === "identity" && hasConstitutionAnchors(d.text));
277
- }
278
- catch {
279
- return false;
280
- }
281
- }
282
- if (provider.stableSystem) {
283
- try {
284
- return hasConstitutionAnchors(provider.stableSystem(ctx));
285
- }
286
- catch {
287
- return false;
288
- }
289
- }
290
- return false;
291
- }
292
- export function acceptAppendSystemPrompt(v, warn, packDropsAppend) {
274
+ export function acceptAppendSystemPrompt(v, warn) {
293
275
  if (v === undefined)
294
276
  return undefined;
295
277
  if (typeof v !== "string" || v.length === 0) {
@@ -300,16 +282,12 @@ export function acceptAppendSystemPrompt(v, warn, packDropsAppend) {
300
282
  warn?.(`appendSystemPrompt dropped: ${v.length} chars exceeds the ${MAX_SETTINGS_OUTPUT_STYLE_CHARS} cap (pre-cap stored body on a resume leg?)`);
301
283
  return undefined;
302
284
  }
303
- if (packDropsAppend === true) {
304
- warn?.("appendSystemPrompt dropped: the effective prompt pack cannot mount the append rider (assembled-identity/stableSystem pass-through, replaceAll, or legacy provider — no core/role.append section)");
305
- return undefined;
306
- }
307
285
  return v;
308
286
  }
309
287
  const RULE_SOURCE_BY_BEHAVIOR = { ask: "settings.permissions.ask", deny: "settings.permissions.deny" };
310
288
  const WORKFLOW_ASK_NAMES = [RUN_WORKFLOW_TOOL_NAME];
311
289
  const isWorkflowName = (name) => name === RUN_WORKFLOW_TOOL_NAME;
312
- function createWorkflowAskPolicy(isExempt) {
290
+ export function createWorkflowAskPolicy(isExempt) {
313
291
  return {
314
292
  async check(req) {
315
293
  if (heldRuleName(req, isWorkflowName) === undefined)
@@ -331,17 +309,31 @@ function createWorkflowAskPolicy(isExempt) {
331
309
  function rejectUnmatchableSettingsNames(perms, pathBases) {
332
310
  const refused = rulePolicyBucketsRefusal(perms, { ...(pathBases !== undefined ? { declared: pathBases } : {}), ...(pathBases?.home !== undefined ? { home: pathBases.home } : {}) });
333
311
  if (refused !== undefined)
334
- throw new Error(refused.message);
312
+ throw new SettingsRuleRefusalError(refused.message, refused.problems);
313
+ }
314
+ export class SettingsRuleRefusalError extends Error {
315
+ problems;
316
+ constructor(message, problems) {
317
+ super(message);
318
+ this.problems = problems;
319
+ this.name = "SettingsRuleRefusalError";
320
+ }
335
321
  }
322
+ export const SETTINGS_RULE_REFUSAL_CODE = "request.unprocessable";
336
323
  export const RULE_POLICY_BUCKETS = ["ask", "deny"];
337
324
  export function rulePolicyBucketsRefusal(permissions, bases) {
325
+ let first;
326
+ const problems = [];
338
327
  for (const bucket of RULE_POLICY_BUCKETS) {
339
328
  const names = permissions[bucket];
340
329
  if (!names)
341
330
  continue;
342
- const unmatchable = unmatchableToolNamesRefusal(`permissions.${bucket}`, names, { consumer: "rule-policy", behavior: bucket, ...(bases.declared !== undefined ? { pathBases: bases.declared } : {}) });
343
- if (unmatchable !== undefined)
344
- return { bucket, message: unmatchable.message };
331
+ const judged = judgeUnmatchableToolNames(`permissions.${bucket}`, names, { consumer: "rule-policy", behavior: bucket, ...(bases.declared !== undefined ? { pathBases: bases.declared } : {}) });
332
+ if (judged === undefined)
333
+ continue;
334
+ first ??= { bucket, message: judged.message };
335
+ for (const b of judged.bad)
336
+ problems.push(entryProblem(SETTINGS_RULE_REFUSAL_CODE, `settings.permissions.${bucket}`, b.name, b.reason));
345
337
  }
346
338
  if (bases.home === undefined) {
347
339
  for (const bucket of RULE_POLICY_BUCKETS) {
@@ -349,73 +341,60 @@ export function rulePolicyBucketsRefusal(permissions, bases) {
349
341
  for (const name of permissions[bucket] ?? []) {
350
342
  const parsed = parseRuleText(name, bucket);
351
343
  if ("rule" in parsed && ruleToolGrammarOf(parsed.rule.tool) === "path" && parsed.rule.command.startsWith("~/")) {
352
- return {
344
+ first ??= {
353
345
  bucket,
354
346
  message: `${field} has a home-relative path rule (${name}) but this deployment cannot resolve the EXECUTION environment's home directory — ` +
355
347
  `the engine never guesses one: without a home base the rule resolves to "unreadable" and every matching call stops to ask, so it guards nothing. ` +
356
348
  `Spell the path absolutely (${"Edit(//abs/path/**)"} form), declare the lane's home with REMOTE_EXEC_HOME_DIR, or run the task on a lane whose home this worker knows.`,
357
349
  };
350
+ problems.push(entryProblem(SETTINGS_RULE_REFUSAL_CODE, `settings.${field}`, name, "home_unresolvable"));
358
351
  }
359
352
  }
360
353
  }
361
354
  }
362
- return undefined;
355
+ return first === undefined ? undefined : { ...first, problems };
363
356
  }
364
357
  export const REQUEST_SETTINGS_REFUSAL_PREFIX = "request settings cannot be applied as written: ";
365
- export function deriveSettingsPolicy(settings, gate, workflowGate) {
358
+ export function deriveSettingsPolicy(settings, bases) {
366
359
  const perms = settings.permissions;
367
- if (!perms)
360
+ const neverAuto = settings.tightenOnly?.neverAuto;
361
+ if (!perms && neverAuto === undefined)
368
362
  return {};
369
- const { deny, ask, defaultMode } = perms;
370
- const pathBases = gate?.taskRoot !== undefined || gate?.taskHome !== undefined
371
- ? { ...(gate.taskRoot !== undefined ? { root: gate.taskRoot } : {}), ...(gate.taskHome !== undefined ? { home: gate.taskHome } : {}) }
372
- : undefined;
373
- rejectUnmatchableSettingsNames(perms, pathBases);
374
363
  const policies = [];
375
- if (deny)
376
- policies.push(createRuleListPolicy(deny, "deny", RULE_SOURCE_BY_BEHAVIOR.deny, pathBases));
377
- if (ask)
378
- policies.push(createRuleListPolicy(ask, "ask", RULE_SOURCE_BY_BEHAVIOR.ask, pathBases));
379
- const fsWriteGate = (acceptCwd) => {
380
- if (!gate)
381
- return undefined;
382
- const gatePolicy = createFsWriteGatePolicy({
383
- env: gate.env,
384
- ...(gate.cwd !== undefined ? { rootPath: gate.cwd } : {}),
385
- ...(acceptCwd && gate.cwd !== undefined ? { acceptDirs: [gate.cwd] } : {}),
386
- ...(gate.scratchpadDir ? { exemptDirs: [gate.scratchpadDir] } : {}),
387
- ...(gate.isExempt ? { isExempt: gate.isExempt } : {}),
388
- defaultWrite: "ask",
389
- });
390
- return gatePolicy;
391
- };
392
- const compose = (...extra) => {
393
- const all = [...policies, ...extra.filter((p) => p !== undefined)];
394
- return all.length === 0 ? undefined : all.length === 1 ? all[0] : combinePolicies(...all);
395
- };
396
- const basePolicy = compose();
397
- switch (defaultMode) {
398
- case "acceptEdits": {
399
- const p = compose(fsWriteGate(true), createWorkflowAskPolicy(workflowGate?.isExempt));
400
- return p ? { toolPolicy: p } : {};
401
- }
402
- case "default":
403
- case "auto":
404
- case "dontAsk":
405
- case "plan": {
406
- const p = compose(createWorkflowAskPolicy(workflowGate?.isExempt));
407
- return p ? { toolPolicy: p } : {};
408
- }
409
- case "bypassPermissions":
410
- case undefined:
411
- return basePolicy ? { toolPolicy: basePolicy } : {};
364
+ if (perms) {
365
+ const { deny, ask } = perms;
366
+ const pathBases = bases?.taskRoot !== undefined || bases?.taskHome !== undefined
367
+ ? { ...(bases.taskRoot !== undefined ? { root: bases.taskRoot } : {}), ...(bases.taskHome !== undefined ? { home: bases.taskHome } : {}) }
368
+ : undefined;
369
+ rejectUnmatchableSettingsNames(perms, pathBases);
370
+ if (deny)
371
+ policies.push(createRuleListPolicy(deny, "deny", RULE_SOURCE_BY_BEHAVIOR.deny, pathBases));
372
+ if (ask)
373
+ policies.push(createRuleListPolicy(ask, "ask", RULE_SOURCE_BY_BEHAVIOR.ask, pathBases));
374
+ }
375
+ if (neverAuto !== undefined) {
376
+ const refused = neverAutoNamesRefusal(neverAuto);
377
+ if (refused !== undefined)
378
+ throw new SettingsRuleRefusalError(refused.message, refused.problems);
379
+ policies.push(createRequestNeverAutoPolicy(neverAuto, tightenOnlySeatField("neverAuto")));
412
380
  }
381
+ if (policies.length === 0)
382
+ return {};
383
+ return { toolPolicy: policies.length === 1 ? policies[0] : combinePolicies(...policies) };
384
+ }
385
+ export function neverAutoNamesRefusal(names) {
386
+ const field = tightenOnlySeatField("neverAuto");
387
+ const judged = judgeUnmatchableToolNames(field.replace(/^settings\./, ""), names, { consumer: "tool-name-table", behavior: "deny" });
388
+ if (judged === undefined)
389
+ return undefined;
390
+ return { message: judged.message, problems: judged.bad.map((b) => entryProblem(SETTINGS_RULE_REFUSAL_CODE, field, b.name, b.reason)) };
413
391
  }
414
- export function applyTaskSettings(base, settings, gate, workflowGate) {
415
- const { toolPolicy } = deriveSettingsPolicy(settings, gate, workflowGate);
392
+ export function applyTaskSettings(base, settings, bases) {
393
+ const { toolPolicy } = deriveSettingsPolicy(settings, bases);
394
+ const seatSpec = settings.tightenOnly !== undefined ? tightenOnlySpecSeats(settings.tightenOnly) : {};
416
395
  let next = base;
417
- if (toolPolicy !== undefined)
418
- next = tightenGoverned(next, { toolPolicy });
396
+ if (toolPolicy !== undefined || Object.keys(seatSpec).length > 0)
397
+ next = tightenGoverned(next, { ...(toolPolicy !== undefined ? { toolPolicy } : {}), ...seatSpec });
419
398
  const allow = settings.permissions?.allow;
420
399
  if (allow !== undefined)
421
400
  next = { ...next, allowedTools: allow };