@sema-agent/core 7.55.0 → 7.56.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 (418) hide show
  1. package/CHANGELOG.md +513 -0
  2. package/dist/agents/cascade.js +1 -1
  3. package/dist/agents/cc-peer-directory.js +1 -0
  4. package/dist/agents/child-model-seat.d.ts +0 -11
  5. package/dist/agents/child-model-seat.js +0 -3
  6. package/dist/agents/list-agents-tool.d.ts +3 -1
  7. package/dist/agents/list-agents-tool.js +7 -7
  8. package/dist/agents/peer-directory.d.ts +22 -4
  9. package/dist/agents/peer-directory.js +24 -2
  10. package/dist/agents/peer-session-drain.js +2 -2
  11. package/dist/agents/repair-loop.js +2 -2
  12. package/dist/agents/send-message-tool.js +4 -4
  13. package/dist/agents/subagent.d.ts +6 -4
  14. package/dist/agents/subagent.js +64 -60
  15. package/dist/agents/tool-filter.d.ts +7 -5
  16. package/dist/agents/tool-filter.js +12 -9
  17. package/dist/agents/verify.d.ts +3 -2
  18. package/dist/agents/verify.js +3 -3
  19. package/dist/brain/anthropic.js +30 -73
  20. package/dist/brain/media-degrade.d.ts +18 -7
  21. package/dist/brain/media-degrade.js +13 -2
  22. package/dist/brain/model-capability.d.ts +37 -0
  23. package/dist/brain/model-capability.js +34 -0
  24. package/dist/brain/model-presets.d.ts +2 -8
  25. package/dist/brain/model-presets.js +1 -6
  26. package/dist/brain/open-responses.js +13 -26
  27. package/dist/brain/openai.js +14 -87
  28. package/dist/brain/reasoning-request.d.ts +96 -0
  29. package/dist/brain/reasoning-request.js +174 -0
  30. package/dist/brain/reasoning.d.ts +11 -11
  31. package/dist/brain/reasoning.js +4 -3
  32. package/dist/brain/request-params.d.ts +7 -4
  33. package/dist/brain/request-params.js +7 -4
  34. package/dist/brain/status-sink.d.ts +20 -0
  35. package/dist/brain/status-sink.js +7 -0
  36. package/dist/core/a2a.d.ts +2 -1
  37. package/dist/core/a2a.js +19 -13
  38. package/dist/core/agent-definition.d.ts +10 -0
  39. package/dist/core/allow-entry.d.ts +20 -13
  40. package/dist/core/allow-entry.js +26 -22
  41. package/dist/core/allow-rule-shadow.d.ts +3 -3
  42. package/dist/core/ask-origin.d.ts +64 -18
  43. package/dist/core/ask-origin.js +63 -23
  44. package/dist/core/ask-question.d.ts +51 -8
  45. package/dist/core/ask-question.js +3 -4
  46. package/dist/core/ask-unresolvable-notice.d.ts +8 -3
  47. package/dist/core/ask-unresolvable-notice.js +16 -2
  48. package/dist/core/checkpoint-generation.d.ts +53 -0
  49. package/dist/core/checkpoint-generation.js +35 -0
  50. package/dist/core/checkpoint-queries.d.ts +180 -0
  51. package/dist/core/checkpoint-queries.js +272 -0
  52. package/dist/core/checkpoint-requirements.d.ts +13 -1
  53. package/dist/core/checkpoint-requirements.js +4 -0
  54. package/dist/core/checkpoint-store.d.ts +88 -24
  55. package/dist/core/checkpoint-store.js +24 -9
  56. package/dist/core/cross-boundary-taint.d.ts +6 -5
  57. package/dist/core/cross-boundary-taint.js +1 -3
  58. package/dist/core/decision-receipt.d.ts +37 -3
  59. package/dist/core/decision-receipt.js +17 -17
  60. package/dist/core/delegation-not-started.d.ts +6 -0
  61. package/dist/core/delegation-not-started.js +17 -0
  62. package/dist/core/engine-attestation.d.ts +93 -0
  63. package/dist/core/engine-attestation.js +70 -0
  64. package/dist/core/engine-capabilities.d.ts +4 -1
  65. package/dist/core/engine-capabilities.js +1 -1
  66. package/dist/core/engine-notice.d.ts +30 -11
  67. package/dist/core/file-history-store.d.ts +90 -14
  68. package/dist/core/file-history-store.js +23 -15
  69. package/dist/core/gate-fold.d.ts +1 -1
  70. package/dist/core/gate-fold.js +22 -10
  71. package/dist/core/gate-lanes.js +73 -64
  72. package/dist/core/gate-outcome.d.ts +26 -5
  73. package/dist/core/gate-outcome.js +26 -0
  74. package/dist/core/governance-codes.d.ts +5 -1
  75. package/dist/core/governance-codes.js +6 -0
  76. package/dist/core/hooks.d.ts +17 -16
  77. package/dist/core/hooks.js +3 -1
  78. package/dist/core/host-floor.d.ts +128 -0
  79. package/dist/core/host-floor.js +206 -0
  80. package/dist/core/host-target.d.ts +38 -3
  81. package/dist/core/host-target.js +38 -5
  82. package/dist/core/mcp.d.ts +5 -1
  83. package/dist/core/mcp.js +67 -41
  84. package/dist/core/memory-engine/delegation-settlement.js +15 -24
  85. package/dist/core/memory-engine/engine.js +4 -4
  86. package/dist/core/memory-engine/layout.d.ts +60 -8
  87. package/dist/core/memory-engine/layout.js +65 -6
  88. package/dist/core/model-seat.d.ts +10 -3
  89. package/dist/core/mods/classic-events.d.ts +67 -0
  90. package/dist/core/mods/classic-events.js +1 -0
  91. package/dist/core/mods/dollar.d.ts +13 -0
  92. package/dist/core/mods/extension-call.d.ts +31 -0
  93. package/dist/core/mods/extension-call.js +43 -0
  94. package/dist/core/mods/kernel/dispatch.d.ts +20 -3
  95. package/dist/core/mods/kernel/dispatch.js +140 -69
  96. package/dist/core/mods/kernel/events.d.ts +47 -11
  97. package/dist/core/mods/kernel/events.js +66 -42
  98. package/dist/core/mods/kernel/index.d.ts +4 -4
  99. package/dist/core/mods/kernel/index.js +2 -2
  100. package/dist/core/mods/kernel/receive.d.ts +39 -5
  101. package/dist/core/mods/kernel/receive.js +290 -17
  102. package/dist/core/mods/kernel/registration.d.ts +33 -2
  103. package/dist/core/mods/kernel/registration.js +6 -7
  104. package/dist/core/mods/kernel/site-rules.d.ts +44 -16
  105. package/dist/core/mods/kernel/site-rules.js +24 -42
  106. package/dist/core/mods/spec-seats.d.ts +69 -0
  107. package/dist/core/mods/spec-seats.js +114 -0
  108. package/dist/core/mods/stations.d.ts +28 -8
  109. package/dist/core/mods/stations.js +29 -13
  110. package/dist/core/mods/tool-call.d.ts +79 -0
  111. package/dist/core/mods/tool-call.js +152 -0
  112. package/dist/core/namespaced-rule-name.d.ts +32 -38
  113. package/dist/core/namespaced-rule-name.js +29 -36
  114. package/dist/core/parent-spec-seat.d.ts +6 -1
  115. package/dist/core/parent-spec-seat.js +2 -0
  116. package/dist/core/park-selfcheck.js +1 -0
  117. package/dist/core/permission-rule-consent.d.ts +19 -0
  118. package/dist/core/permission-rule-consent.js +116 -26
  119. package/dist/core/permission-rule-model.d.ts +14 -3
  120. package/dist/core/permission-rule-model.js +39 -24
  121. package/dist/core/permission-rule-org.d.ts +6 -2
  122. package/dist/core/permission-rule-org.js +7 -3
  123. package/dist/core/permission-rule-provider.d.ts +5 -2
  124. package/dist/core/permission-rule-provider.js +41 -11
  125. package/dist/core/permission-rule-store.d.ts +3 -2
  126. package/dist/core/permission-rule-store.js +11 -2
  127. package/dist/core/permission-rule-sync.js +3 -2
  128. package/dist/core/permission-rule-syntax.d.ts +5 -4
  129. package/dist/core/permission-rule-syntax.js +2 -2
  130. package/dist/core/permission-rules.d.ts +4 -4
  131. package/dist/core/permission-rules.js +11 -20
  132. package/dist/core/persisted-rule-arms.d.ts +2 -2
  133. package/dist/core/persisted-rule-arms.js +10 -12
  134. package/dist/core/principal-name.d.ts +20 -0
  135. package/dist/core/principal-name.js +22 -0
  136. package/dist/core/prompt-section-seat.js +4 -6
  137. package/dist/core/protocol-http-auth.d.ts +26 -5
  138. package/dist/core/protocol-http-auth.js +137 -4
  139. package/dist/core/retired-keys.d.ts +16 -0
  140. package/dist/core/retired-keys.js +16 -4
  141. package/dist/core/rewrite-rejudge.d.ts +60 -0
  142. package/dist/core/rewrite-rejudge.js +36 -0
  143. package/dist/core/roles.d.ts +28 -1
  144. package/dist/core/roles.js +31 -19
  145. package/dist/core/rule-lane-reads.d.ts +20 -15
  146. package/dist/core/rule-lane-reads.js +45 -17
  147. package/dist/core/rule-owner.d.ts +3 -3
  148. package/dist/core/rule-owner.js +3 -2
  149. package/dist/core/runner/announce-once-ledger.d.ts +14 -0
  150. package/dist/core/runner/announce-once-ledger.js +5 -0
  151. package/dist/core/runner/assemble-result.d.ts +1 -0
  152. package/dist/core/runner/assemble-result.js +1 -1
  153. package/dist/core/runner/call-hook-stations.d.ts +3 -2
  154. package/dist/core/runner/caller-roster.d.ts +16 -4
  155. package/dist/core/runner/caller-roster.js +33 -6
  156. package/dist/core/runner/capability-withheld-seat.d.ts +5 -0
  157. package/dist/core/runner/capability-withheld-seat.js +24 -0
  158. package/dist/core/runner/classifier-ladder.d.ts +7 -9
  159. package/dist/core/runner/classifier-ladder.js +3 -3
  160. package/dist/core/runner/construction-doors.js +3 -0
  161. package/dist/core/runner/contracts.d.ts +28 -25
  162. package/dist/core/runner/cross-boundary-lane.d.ts +17 -13
  163. package/dist/core/runner/cross-boundary-lane.js +40 -27
  164. package/dist/core/runner/denial-limit-arms.d.ts +2 -2
  165. package/dist/core/runner/denial-limit-arms.js +1 -1
  166. package/dist/core/runner/file-history-request.d.ts +18 -0
  167. package/dist/core/runner/file-history-request.js +21 -13
  168. package/dist/core/runner/file-history-restore.d.ts +45 -0
  169. package/dist/core/runner/file-history-restore.js +46 -0
  170. package/dist/core/runner/gate-exit.d.ts +3 -3
  171. package/dist/core/runner/gate-exit.js +4 -3
  172. package/dist/core/runner/image.d.ts +7 -17
  173. package/dist/core/runner/image.js +9 -60
  174. package/dist/core/runner/permission-rule-lanes.d.ts +4 -4
  175. package/dist/core/runner/permission-rule-lanes.js +26 -10
  176. package/dist/core/runner/person-path-rows.d.ts +12 -9
  177. package/dist/core/runner/person-path-rows.js +18 -7
  178. package/dist/core/runner/prepare-ask-lane.d.ts +2 -2
  179. package/dist/core/runner/prepare-ask-lane.js +5 -2
  180. package/dist/core/runner/prepare-caps-and-workflow.d.ts +4 -6
  181. package/dist/core/runner/prepare-caps-and-workflow.js +4 -3
  182. package/dist/core/runner/prepare-config-doors.d.ts +29 -38
  183. package/dist/core/runner/prepare-config-doors.js +42 -25
  184. package/dist/core/runner/prepare-defer-classify.d.ts +4 -3
  185. package/dist/core/runner/prepare-defer-classify.js +7 -8
  186. package/dist/core/runner/prepare-file-history.d.ts +48 -8
  187. package/dist/core/runner/prepare-file-history.js +7 -39
  188. package/dist/core/runner/prepare-gate-stations.d.ts +1 -1
  189. package/dist/core/runner/prepare-gate-stations.js +10 -1
  190. package/dist/core/runner/prepare-hands-readface.d.ts +2 -8
  191. package/dist/core/runner/prepare-hands-readface.js +15 -14
  192. package/dist/core/runner/prepare-inherited-gate.d.ts +6 -3
  193. package/dist/core/runner/prepare-inherited-gate.js +5 -3
  194. package/dist/core/runner/prepare-memory-engine-session.js +1 -1
  195. package/dist/core/runner/prepare-park-ask.js +5 -5
  196. package/dist/core/runner/prepare-policy-chain.d.ts +6 -3
  197. package/dist/core/runner/prepare-policy-chain.js +65 -72
  198. package/dist/core/runner/prepare-prompt-assembly.d.ts +5 -7
  199. package/dist/core/runner/prepare-prompt-assembly.js +10 -8
  200. package/dist/core/runner/prepare-prompt-inputs.d.ts +11 -9
  201. package/dist/core/runner/prepare-prompt-inputs.js +3 -5
  202. package/dist/core/runner/prepare-protocol-tools.d.ts +2 -0
  203. package/dist/core/runner/prepare-protocol-tools.js +3 -3
  204. package/dist/core/runner/prepare-safety-scan.d.ts +1 -1
  205. package/dist/core/runner/prepare-safety-scan.js +0 -17
  206. package/dist/core/runner/prepare-suspend-saga.d.ts +2 -0
  207. package/dist/core/runner/prepare-suspend-saga.js +5 -6
  208. package/dist/core/runner/prepare-task.d.ts +1 -1
  209. package/dist/core/runner/prepare-task.js +29 -20
  210. package/dist/core/runner/prepare-tool-disclosure-mount.d.ts +7 -4
  211. package/dist/core/runner/prepare-tool-disclosure-mount.js +20 -16
  212. package/dist/core/runner/prepare-turn-wiring.d.ts +0 -4
  213. package/dist/core/runner/prepare-turn-wiring.js +2 -7
  214. package/dist/core/runner/prepare-wiring-manifest.d.ts +6 -2
  215. package/dist/core/runner/prepare-wiring-manifest.js +3 -3
  216. package/dist/core/runner/resume-admission.js +1 -1
  217. package/dist/core/runner/resume-apply.js +11 -12
  218. package/dist/core/runner/resume-checkpoint-screen.js +3 -0
  219. package/dist/core/runner/resume-claim.d.ts +4 -2
  220. package/dist/core/runner/resume-claim.js +15 -8
  221. package/dist/core/runner/retired-runner-deps.js +1 -0
  222. package/dist/core/runner/rewind-files.d.ts +15 -0
  223. package/dist/core/runner/rewind-files.js +132 -0
  224. package/dist/core/runner/run-attachment-seats.js +2 -1
  225. package/dist/core/runner/run-brain-sinks.d.ts +4 -1
  226. package/dist/core/runner/run-brain-sinks.js +4 -2
  227. package/dist/core/runner/run-harness-handlers.js +12 -4
  228. package/dist/core/runner/run-leg.d.ts +1 -1
  229. package/dist/core/runner/run-leg.js +30 -18
  230. package/dist/core/runner/run-settle-and-teardown.js +2 -1
  231. package/dist/core/runner/run-turn-boundary.js +1 -10
  232. package/dist/core/runner/runtask.d.ts +3 -0
  233. package/dist/core/runner/runtask.js +8 -9
  234. package/dist/core/runner/session-read-file-states.d.ts +15 -0
  235. package/dist/core/runner/session-read-file-states.js +28 -0
  236. package/dist/core/runner/session-rule-policy.js +4 -3
  237. package/dist/core/runner/shell-env-withheld.d.ts +33 -0
  238. package/dist/core/runner/shell-env-withheld.js +51 -0
  239. package/dist/core/runner/skills-seat.js +6 -2
  240. package/dist/core/runner/stream-settle-backstop.js +1 -1
  241. package/dist/core/runner/sub-agent-deny-lists.js +4 -7
  242. package/dist/core/runner/synthetic-tools.d.ts +6 -0
  243. package/dist/core/runner/synthetic-tools.js +4 -1
  244. package/dist/core/runner/tool-disclosure.d.ts +10 -12
  245. package/dist/core/runner/tool-disclosure.js +1 -3
  246. package/dist/core/runner/tool-end-body.d.ts +1 -1
  247. package/dist/core/runner/tool-end-body.js +10 -9
  248. package/dist/core/runner/tool-not-executed.d.ts +5 -0
  249. package/dist/core/runner/tool-not-executed.js +11 -0
  250. package/dist/core/runner/tool-occurrence.d.ts +8 -0
  251. package/dist/core/runner/tool-occurrence.js +7 -0
  252. package/dist/core/runner/turn-attachments.d.ts +33 -15
  253. package/dist/core/runner/turn-attachments.js +62 -37
  254. package/dist/core/runner-deps.d.ts +5 -5
  255. package/dist/core/safety-axis-vocab.d.ts +6 -4
  256. package/dist/core/safety-axis-vocab.js +6 -5
  257. package/dist/core/safety-merge-corpus.js +11 -3
  258. package/dist/core/secret-env.d.ts +26 -3
  259. package/dist/core/secret-env.js +44 -8
  260. package/dist/core/select-model.js +3 -3
  261. package/dist/core/session-policy-store.d.ts +27 -15
  262. package/dist/core/session-policy-store.js +156 -36
  263. package/dist/core/session-store.d.ts +29 -10
  264. package/dist/core/session-store.js +51 -19
  265. package/dist/core/session.d.ts +82 -16
  266. package/dist/core/session.js +53 -0
  267. package/dist/core/shell-read-silence.d.ts +11 -12
  268. package/dist/core/shell-read-silence.js +9 -5
  269. package/dist/core/shell-run-candidates.js +3 -1
  270. package/dist/core/shell-wrapper-projection.js +1 -1
  271. package/dist/core/shell-wrapper-table.d.ts +14 -7
  272. package/dist/core/shell-wrapper-table.js +5 -4
  273. package/dist/core/side-query.js +10 -1
  274. package/dist/core/skill-grant.d.ts +7 -2
  275. package/dist/core/skill-grant.js +5 -0
  276. package/dist/core/skills-directory.js +6 -2
  277. package/dist/core/store-contracts/checkpoint-store-contract.d.ts +11 -1
  278. package/dist/core/store-contracts/checkpoint-store-contract.js +140 -2
  279. package/dist/core/store-contracts/file-history-store-contract.js +31 -1
  280. package/dist/core/store-contracts/peer-directory-contract.d.ts +7 -2
  281. package/dist/core/store-contracts/peer-directory-contract.js +14 -2
  282. package/dist/core/store-contracts/session-repo-contract.js +51 -0
  283. package/dist/core/store-contracts/session-store-contract.d.ts +2 -1
  284. package/dist/core/store-contracts/session-store-contract.js +150 -14
  285. package/dist/core/stub-env.d.ts +2 -0
  286. package/dist/core/stub-env.js +1 -0
  287. package/dist/core/synthetic-read-verdict.js +3 -3
  288. package/dist/core/task-event.d.ts +32 -4
  289. package/dist/core/task-notification.d.ts +16 -12
  290. package/dist/core/task-registry.d.ts +9 -0
  291. package/dist/core/task-registry.js +11 -1
  292. package/dist/core/task-result.d.ts +18 -0
  293. package/dist/core/task-spec.d.ts +18 -13
  294. package/dist/core/tighten-task-spec.js +2 -1
  295. package/dist/core/tool-catalog-entries.d.ts +17 -0
  296. package/dist/core/tool-catalog-entries.js +13 -2
  297. package/dist/core/tool-check-reading.d.ts +11 -0
  298. package/dist/core/tool-check-reading.js +11 -6
  299. package/dist/core/tool-model-gate.d.ts +2 -2
  300. package/dist/core/tool-name-aliases.d.ts +16 -16
  301. package/dist/core/tool-name-aliases.js +13 -19
  302. package/dist/core/tool-name-readings.d.ts +5 -35
  303. package/dist/core/tool-name-readings.js +1 -9
  304. package/dist/core/tool-policy.d.ts +68 -198
  305. package/dist/core/tool-policy.js +149 -198
  306. package/dist/core/tool-result-store.js +3 -0
  307. package/dist/core/tool-roster.d.ts +14 -19
  308. package/dist/core/tool-roster.js +11 -44
  309. package/dist/core/tool-spec-members.js +7 -2
  310. package/dist/core/tool-spec.d.ts +19 -11
  311. package/dist/core/tools.js +49 -9
  312. package/dist/core/trace.d.ts +2 -2
  313. package/dist/core/types.d.ts +1 -1
  314. package/dist/core/user-attachment.d.ts +8 -1
  315. package/dist/core/user-attachment.js +64 -4
  316. package/dist/core/wiring-manifest.d.ts +9 -0
  317. package/dist/core/wiring-manifest.js +1 -0
  318. package/dist/core/workflow-journal-store.js +1 -1
  319. package/dist/engine/compaction/compaction.js +3 -2
  320. package/dist/engine/execution-env/node-execution-env.d.ts +7 -3
  321. package/dist/engine/execution-env/node-execution-env.js +11 -2
  322. package/dist/engine/harness/agent-harness.d.ts +25 -1
  323. package/dist/engine/harness/agent-harness.js +54 -7
  324. package/dist/engine/harness/types.d.ts +29 -2
  325. package/dist/engine/llm/types.d.ts +28 -11
  326. package/dist/engine/loop/agent-loop.d.ts +22 -0
  327. package/dist/engine/loop/agent-loop.js +16 -26
  328. package/dist/engine/loop/types.d.ts +16 -6
  329. package/dist/engine/session/memory-repo.d.ts +9 -2
  330. package/dist/engine/session/memory-repo.js +11 -1
  331. package/dist/engine/session/repo-utils.d.ts +6 -5
  332. package/dist/engine/session/repo-utils.js +14 -6
  333. package/dist/index.d.ts +22 -10
  334. package/dist/index.js +15 -7
  335. package/dist/internal/harness-types.d.ts +1 -1
  336. package/dist/internal/llm.d.ts +1 -1
  337. package/dist/orchestration/run-workflow-tool.d.ts +6 -4
  338. package/dist/orchestration/run-workflow-tool.js +5 -3
  339. package/dist/orchestration/workflow.d.ts +3 -0
  340. package/dist/orchestration/workflow.js +36 -18
  341. package/dist/prompt-assembly/artifact.d.ts +2 -2
  342. package/dist/prompt-assembly/artifact.js +5 -3
  343. package/dist/prompt-assembly/assemble.d.ts +3 -2
  344. package/dist/prompt-assembly/assemble.js +1 -1
  345. package/dist/prompt-assembly/catalog/schema.d.ts +43 -12
  346. package/dist/prompt-assembly/catalog/schema.js +34 -2
  347. package/dist/prompt-assembly/catalog/sections.js +0 -1
  348. package/dist/prompt-assembly/composer.d.ts +3 -1
  349. package/dist/prompt-assembly/composer.js +1 -1
  350. package/dist/prompt-assembly/event-registry.js +1 -0
  351. package/dist/prompt-assembly/overlay.js +3 -3
  352. package/dist/prompt-assembly/renderers.d.ts +1 -1
  353. package/dist/prompt-assembly/renderers.js +0 -3
  354. package/dist/prompt-assembly/role-base.d.ts +15 -0
  355. package/dist/prompt-assembly/role-base.js +9 -0
  356. package/dist/prompt-assembly/select.d.ts +39 -14
  357. package/dist/prompt-assembly/select.js +47 -16
  358. package/dist/prompt-assembly/sugar.d.ts +17 -11
  359. package/dist/prompt-assembly/sugar.js +8 -3
  360. package/dist/prompt-assembly/tool-catalog.d.ts +37 -3
  361. package/dist/prompt-assembly/tool-catalog.js +114 -4
  362. package/dist/prompt-assembly/turn-snapshot.d.ts +4 -10
  363. package/dist/prompt-assembly/turn-snapshot.js +0 -3
  364. package/dist/prompt-assembly/types.d.ts +0 -7
  365. package/dist/scenarios/full-body.d.ts +11 -11
  366. package/dist/scenarios/full-body.js +4 -3
  367. package/dist/shell/lex.js +10 -1
  368. package/dist/stores/file/adoption/adopt.js +4 -3
  369. package/dist/stores/file/adoption/marker.js +3 -2
  370. package/dist/stores/file/checkpoint-store.d.ts +21 -0
  371. package/dist/stores/file/checkpoint-store.js +38 -6
  372. package/dist/stores/file/file-history-store.js +6 -7
  373. package/dist/stores/file/index.js +2 -1
  374. package/dist/stores/file/permission-rule-adopt.js +4 -3
  375. package/dist/stores/file/permission-rule-store.js +11 -5
  376. package/dist/stores/file/session-store.d.ts +29 -6
  377. package/dist/stores/file/session-store.js +42 -50
  378. package/dist/tools/artifact/artifact-tool.js +3 -2
  379. package/dist/tools/fs/bash-program-position.d.ts +19 -2
  380. package/dist/tools/fs/bash-program-position.js +56 -9
  381. package/dist/tools/fs/fs-bash.js +5 -5
  382. package/dist/tools/fs/fs-glob.d.ts +86 -0
  383. package/dist/tools/fs/fs-glob.js +226 -0
  384. package/dist/tools/fs/fs-read.js +14 -14
  385. package/dist/tools/fs/fs-search-tools.js +7 -7
  386. package/dist/tools/fs/pattern-kill-guard.d.ts +22 -0
  387. package/dist/tools/fs/pattern-kill-guard.js +397 -0
  388. package/dist/tools/fs/pdf.d.ts +9 -6
  389. package/dist/tools/fs/pdf.js +3 -3
  390. package/dist/tools/fs/program-read-model.d.ts +57 -7
  391. package/dist/tools/fs/program-read-model.js +11 -1
  392. package/dist/tools/fs/program-read-model.rows.js +78 -21
  393. package/dist/tools/fs/read-deny-home.js +3 -2
  394. package/dist/tools/fs/removal-targets.d.ts +17 -7
  395. package/dist/tools/fs/removal-targets.js +47 -20
  396. package/dist/tools/fs/search.d.ts +10 -0
  397. package/dist/tools/fs/search.js +20 -26
  398. package/dist/tools/fs/shell-read-argv.js +89 -12
  399. package/dist/tools/fs/shell-read-bindings.d.ts +31 -0
  400. package/dist/tools/fs/shell-read-bindings.js +41 -0
  401. package/dist/tools/fs/shell-read-check.js +6 -19
  402. package/dist/tools/fs/shell-read-environment.d.ts +5 -1
  403. package/dist/tools/fs/shell-read-environment.js +3 -2
  404. package/dist/tools/fs/shell-read-establish.d.ts +15 -0
  405. package/dist/tools/fs/shell-read-establish.js +19 -20
  406. package/dist/tools/fs/shell-read-plan.js +24 -16
  407. package/dist/tools/fs/shell-read-start.d.ts +6 -1
  408. package/dist/tools/fs/shell-read-write-targets.d.ts +5 -1
  409. package/dist/tools/fs/shell-read-write-targets.js +2 -3
  410. package/dist/tools/fs/shell-reentry-text.d.ts +9 -0
  411. package/dist/tools/fs/shell-reentry-text.js +40 -2
  412. package/dist/tools/todo.js +63 -63
  413. package/dist/tools/web.d.ts +19 -14
  414. package/dist/tools/web.js +38 -55
  415. package/package.json +1 -1
  416. package/test/export-surface.snapshot.json +143 -5
  417. package/wire-changes/core@7.56.0.json +3891 -0
  418. package/wire-changes/mods-kernel@7.56.0.json +303 -0
@@ -1,22 +1,12 @@
1
1
  import type { ImageContent } from "../../internal/llm.js";
2
+ import { type HostFloor } from "../host-floor.js";
2
3
  import type { ImageInput } from "../types.js";
3
4
  /**
4
- * Block obviously-internal hosts (loopback / private ranges / link-local incl. cloud metadata / CGNAT / IPv6
5
- * ULA, site-local, unspecified, IPv4-mapped, NAT64). Classifies with `net.isIP` rather than a string-prefix
6
- * regex — the old regex both UNDER-matched (IPv4-mapped `::ffff:`, NAT64, CGNAT 100.64/10, `::`) and
7
- * OVER-matched (any DNS name starting `fc`/`fd`, e.g. `fdpartners.com`). Numeric IPv4 forms (decimal/octal/hex)
8
- * are normalized to dotted-decimal by `URL` before this is called, so they're already covered.
9
- * Note: this checks the LITERAL host; it does NOT resolve DNS, so a hostname resolving to a private IP is not
10
- * caught here (documented limitation — a deployment needing that supplies its own resolve-and-pin guard).
5
+ * The guard of a remote image URL: https only, then the one egress hop judge with the private-network floor (`hopRefusal`,
6
+ * host-floor.ts) — the deployment's host floor (`RunnerDeps.hostFloor`, `floor`) must admit the host, and a private host is
7
+ * reachable only when the floor's `only` list names it — so an end-user-supplied `images[].url` can't make the server fetch
8
+ * `169.254.169.254` or a private box. The host is read literally (no DNS resolution). Throws on a refused URL.
11
9
  */
12
- export declare function isPrivateHost(host: string): boolean;
13
- /**
14
- * Default SSRF guard for a remote image URL: https only, and no internal/reserved hosts (so an
15
- * end-user-supplied `images[].url` can't make the server fetch `169.254.169.254` or a private box).
16
- * Note: this checks the URL host literally — it does not resolve DNS, so a hostname that resolves to
17
- * a private IP is not caught here; a deployment needing that should supply `RunnerDeps.allowImageUrl`
18
- * (e.g. a CDN allowlist or a resolve-and-pin check). Throws on a disallowed URL.
19
- */
20
- export declare function defaultImageUrlGuard(raw: string): void;
10
+ export declare function defaultImageUrlGuard(raw: string, floor?: HostFloor): void;
21
11
  /** Resolve an {@link ImageInput} (inline base64 or a URL to fetch) into a vendored `ImageContent` block. */
22
- export declare function toImageContent(img: ImageInput, allowUrl?: (url: string) => boolean): Promise<ImageContent>;
12
+ export declare function toImageContent(img: ImageInput, floor: HostFloor | undefined): Promise<ImageContent>;
@@ -1,55 +1,10 @@
1
- import { isIP } from "node:net";
1
+ import { hopRefusal } from "../host-floor.js";
2
2
  import { ADMITTED_IMAGE_MIME_TYPES, imageMagicMatches } from "../image-admission.js";
3
3
  import { admitInlineImage } from "./inline-image.js";
4
4
  function sniffImageMime(bytes) {
5
5
  return ADMITTED_IMAGE_MIME_TYPES.find((mime) => imageMagicMatches(bytes, mime));
6
6
  }
7
- function isPrivateV4(ip) {
8
- const o = ip.split(".").map(Number);
9
- if (o.length !== 4 || o.some((n) => !Number.isInteger(n) || n < 0 || n > 255))
10
- return true;
11
- const [a, b] = o;
12
- return (a === 127 ||
13
- a === 10 ||
14
- a === 0 ||
15
- (a === 172 && b >= 16 && b <= 31) ||
16
- (a === 192 && b === 168) ||
17
- (a === 169 && b === 254) ||
18
- (a === 100 && b >= 64 && b <= 127));
19
- }
20
- function embeddedV4(h) {
21
- const fromHex = (hi, lo) => {
22
- const a = parseInt(hi, 16), c = parseInt(lo, 16);
23
- return `${(a >> 8) & 255}.${a & 255}.${(c >> 8) & 255}.${c & 255}`;
24
- };
25
- let m = /^(?:::ffff:|64:ff9b::)(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/.exec(h);
26
- if (m)
27
- return m[1];
28
- m = /^(?:::ffff:|64:ff9b::)([0-9a-f]{1,4}):([0-9a-f]{1,4})$/.exec(h);
29
- if (m)
30
- return fromHex(m[1], m[2]);
31
- return undefined;
32
- }
33
- export function isPrivateHost(host) {
34
- const h = host
35
- .replace(/^\[|\]$/g, "")
36
- .replace(/\.+$/, "")
37
- .toLowerCase();
38
- if (h === "localhost")
39
- return true;
40
- const fam = isIP(h);
41
- if (fam === 0)
42
- return false;
43
- if (fam === 4)
44
- return isPrivateV4(h);
45
- const v4 = embeddedV4(h);
46
- if (v4)
47
- return isPrivateV4(v4);
48
- if (h === "::1" || h === "::")
49
- return true;
50
- return /^fe[89ab]/.test(h) || /^f[cd]/.test(h) || /^fe[c-f]/.test(h);
51
- }
52
- export function defaultImageUrlGuard(raw) {
7
+ export function defaultImageUrlGuard(raw, floor) {
53
8
  let u;
54
9
  try {
55
10
  u = new URL(raw);
@@ -60,9 +15,9 @@ export function defaultImageUrlGuard(raw) {
60
15
  if (u.protocol !== "https:") {
61
16
  throw new Error(`image url must be https (got "${u.protocol}")`);
62
17
  }
63
- if (isPrivateHost(u.hostname)) {
64
- throw new Error(`image url host not allowed (private/reserved): ${u.hostname}`);
65
- }
18
+ const refused = hopRefusal(u, floor, true);
19
+ if (refused !== undefined)
20
+ throw new Error(`image url not fetched — ${refused}`);
66
21
  }
67
22
  const IMAGE_FETCH_TIMEOUT_MS = 30_000;
68
23
  const IMAGE_MAX_BYTES = 20 * 1024 * 1024;
@@ -112,17 +67,11 @@ async function fetchImageCapped(url) {
112
67
  }
113
68
  return { buf, mimeType: sniffed };
114
69
  }
115
- export async function toImageContent(img, allowUrl) {
70
+ export async function toImageContent(img, floor) {
116
71
  if ("url" in img) {
117
- if (allowUrl) {
118
- if (!allowUrl(img.url)) {
119
- throw new Error(`image url rejected by policy: ${img.url}`);
120
- }
121
- }
122
- else {
123
- defaultImageUrlGuard(img.url);
124
- }
125
- const { buf, mimeType } = await fetchImageCapped(img.url);
72
+ const url = img.url;
73
+ defaultImageUrlGuard(url, floor);
74
+ const { buf, mimeType } = await fetchImageCapped(url);
126
75
  return { type: "image", data: buf.toString("base64"), mimeType };
127
76
  }
128
77
  return admitInlineImage(img);
@@ -121,7 +121,7 @@ export interface PermissionRuleLanes {
121
121
  * `onDegraded` receives the snapshot's degraded line ({@link describeUnreadableOrgRows}) on every adjudication over a
122
122
  * snapshot carrying a row this layer cannot read. */
123
123
  export declare function orgRuleLane(cfg: {
124
- read: (toolCallId: string) => Promise<Pick<EffectivePermissionRules, "org">>;
124
+ read: (toolCallId: string, judged: unknown) => Promise<Pick<EffectivePermissionRules, "org">>;
125
125
  questionToolMounted: boolean;
126
126
  questionToolName: string;
127
127
  onRevisionDefect: (message: string) => void;
@@ -177,10 +177,10 @@ export declare function createPermissionRuleLanes(cfg: {
177
177
  onRevisionDefect: (message: string) => void;
178
178
  /** Sink for a judgment against the rows that threw, and for the org lane's degraded-snapshot line. */
179
179
  onDisclosure: (message: string) => void;
180
- /** The run's one reader of the person's rules: the call's ONE read, pinned, that the read station, the org lane and the
181
- * personal lane all take (the lanes consume a reader; they do not make one). */
180
+ /** The run's one reader of the person's rules: the call's ONE read of the bytes judged, pinned, that the read station, the
181
+ * org lane and the personal lane all take (the lanes consume a reader; they do not make one). */
182
182
  rows: {
183
- pin(toolCallId: string): Promise<PersonRowsRead>;
183
+ pin(toolCallId: string, judged?: unknown): Promise<PersonRowsRead>;
184
184
  };
185
185
  /** The allow layer's auto strip over a stored ALLOW row (true ⇒ out of this call's table BEFORE the coverage is chosen). */
186
186
  stripsAllow?: (rule: PersistedRule, req: ToolCallRequest) => boolean;
@@ -1,6 +1,6 @@
1
1
  import { persistedRuleMandateOf, ruleClearanceOf } from "../ask-origin.js";
2
2
  import {} from "../hooks.js";
3
- import { adjudicatePersistedDomainRules, adjudicatePersistedNameRules, adjudicatePersistedPathRules, adjudicatePersistedRules, callPathFaceOf, escapeForDisclosure, faceRowsSpeakFor, laneToolNamesOf, nameRuleSubjectOf, ruleToolGrammarOf, segmentCoverageOf, suggestRuleForHost, suggestRuleForName, suggestRulesForCommand } from "../permission-rule-model.js";
3
+ import { adjudicatePersistedDomainRules, adjudicatePersistedNameRules, adjudicatePersistedPathRules, adjudicatePersistedRules, callPathFaceOf, eligiblePersisted, escapeForDisclosure, faceRowsSpeakFor, parseRuleText, laneToolNamesOf, nameRuleSubjectOf, ruleToolGrammarOf, segmentCoverageOf, suggestRuleForHost, suggestRuleForName, suggestRulesForCommand } from "../permission-rule-model.js";
4
4
  import { callHostTargetOf } from "../host-target.js";
5
5
  import { callTargetViewsOf, validatePath } from "../effective-path-target.js";
6
6
  import { bindPathRules, persistedRowAnchors, projectScopeIdentity } from "../path-rule-binding.js";
@@ -8,6 +8,7 @@ import { heldBy, seatOf, wireOf } from "../tool-name-readings.js";
8
8
  import { describeUnreadableOrgRows, readOrgRules, settleOrgVerdictWithin } from "../permission-rule-org.js";
9
9
  import { ASK_USER_QUESTION_TOOL_NAME } from "../ask-question.js";
10
10
  import { ownerStoreOf } from "../permission-rule-provider.js";
11
+ import { readPrincipal } from "../principal-name.js";
11
12
  import { thrownText } from "../thrown-value.js";
12
13
  import { strongestAnswer } from "../persisted-rule-arms.js";
13
14
  import { ORG_ADJUDICATION_TIMEOUT_MS } from "../permission-rule-org.js";
@@ -59,7 +60,7 @@ export function orgRuleLane(cfg) {
59
60
  return { status: "available" };
60
61
  let resolution;
61
62
  try {
62
- resolution = (await cfg.read(req.toolCallId)).org;
63
+ resolution = (await cfg.read(req.toolCallId, req.args)).org;
63
64
  }
64
65
  catch (err) {
65
66
  return { status: "unavailable", disclosures: [`the permission-rule store threw while resolving the org partition: ${thrownText(err)}`] };
@@ -106,10 +107,10 @@ export function createPermissionRuleLanes(cfg) {
106
107
  }
107
108
  if (provider === undefined)
108
109
  return { personal: undefined, org: undefined };
109
- const anonymous = cfg.principal === undefined || cfg.principal === "";
110
+ const anonymous = readPrincipal(cfg.principal).kind === "absent";
110
111
  const reader = cfg.rows;
111
- const orgViewOf = async (toolCallId) => {
112
- const read = await reader.pin(toolCallId);
112
+ const orgViewOf = async (toolCallId, judged) => {
113
+ const read = await reader.pin(toolCallId, judged);
113
114
  if (read.org === undefined)
114
115
  throw new Error(read.unreadable ?? "the store did not answer");
115
116
  return { org: read.org };
@@ -121,14 +122,24 @@ export function createPermissionRuleLanes(cfg) {
121
122
  const judged = laneToolNamesOf(req).map((n) => [n, ruleToolGrammarOf(n)]);
122
123
  if (!judged.some(([, g]) => g === "path") && faceRowsSpeakFor(callPathFaceOf(req)))
123
124
  judged.push([req.toolName, "path"]);
124
- const view = await reader.pin(req.toolCallId);
125
+ const view = await reader.pin(req.toolCallId, req.args);
125
126
  if (judged.length === 0)
126
127
  return view.unreadable !== undefined ? { unreadable: true } : undefined;
127
128
  try {
128
- const table = view.rules.filter((r) => r.behavior !== "allow" || cfg.stripsAllow?.(r, req) !== true);
129
- const leads = judged.some(([, g]) => g === "path") ? await cfg.leads.resolve(bindPathRules(table.filter((r) => r.match === "path" || r.match === "subpath").map((r) => ({ parsed: r, ruleText: r.rule, rule: r })), (spec) => anchorsOf(spec.rule))) : NO_LEADS;
129
+ const stripped = view.rules.filter((r) => r.behavior !== "allow" || cfg.stripsAllow?.(r, req) !== true);
130
+ const judgesPath = judged.some(([, g]) => g === "path");
131
+ const noRule = [];
132
+ const table = stripped.filter((r) => {
133
+ const read = judged.some(([n]) => n === r.tool) || (judgesPath && (r.match === "path" || r.match === "subpath")) ? parseRuleText(r.rule, r.behavior) : undefined;
134
+ if (read !== undefined && "reject" in read)
135
+ noRule.push({ row: r, why: read.reject.message });
136
+ return read === undefined || !("reject" in read) || r.behavior !== "allow";
137
+ });
138
+ const leads = judgesPath ? await cfg.leads.resolve(bindPathRules(table.filter((r) => r.match === "path" || r.match === "subpath").map((r) => ({ parsed: r, ruleText: r.rule, rule: r })), (spec) => anchorsOf(spec.rule))) : NO_LEADS;
130
139
  const scopeIdentity = await projectScopeIdentity(table, cfg.rootCanonical, cfg.leads);
131
- const answer = strongestAnswer(judged.map(([n, grammar]) => judgeAgainst(table, { ...req, toolName: n }, grammar, leads, scopeIdentity)));
140
+ const judgedAnswer = strongestAnswer(judged.map(([n, grammar]) => judgeAgainst(table, { ...req, toolName: n }, grammar, leads, scopeIdentity)));
141
+ const unjudged = noRule.find(({ row }) => (row.behavior === "deny" || row.behavior === "ask") && eligiblePersisted(row, { tool: row.tool, cwd: cfg.root, sessionId: cfg.sessionId, ...(scopeIdentity !== undefined ? { scopeIdentity } : {}) }, row.behavior));
142
+ const answer = unjudged !== undefined && !(judgedAnswer !== undefined && "behavior" in judgedAnswer && judgedAnswer.behavior === "deny") ? unjudgedRowAnswer(unjudged.row, unjudged.why, req.toolName) : judgedAnswer;
132
143
  const stands = answer !== undefined && (("behavior" in answer && answer.behavior === "deny") || "unreadable" in answer);
133
144
  return view.unreadable !== undefined && !stands ? { unreadable: true } : answer;
134
145
  }
@@ -138,6 +149,11 @@ export function createPermissionRuleLanes(cfg) {
138
149
  return { unreadable: true, reason: why };
139
150
  }
140
151
  };
152
+ const unjudgedRowAnswer = (row, refusal, tool) => {
153
+ const why = `the stored ${row.behavior} rule ${escapeForDisclosure(row.rule)} is no rule this engine reads (${refusal})`;
154
+ cfg.onDisclosure(`the persisted rule lane could not judge a ${tool} call against the rows it read — ${why}`);
155
+ return { unreadable: true, reason: why };
156
+ };
141
157
  const anchorsOf = (rule) => persistedRowAnchors(rule.scope, cfg.chainTop);
142
158
  const judgeAgainst = (table, req, grammar, leads, scopeIdentity) => {
143
159
  const liveCwd = cfg.liveCwd();
@@ -167,7 +183,7 @@ export function createRuleOffersOf(cfg) {
167
183
  const grammar = ruleToolGrammarOf(toolName);
168
184
  if (!cfg.laneArmed || (toolName !== PERSISTED_RULE_TOOL && grammar !== "name" && grammar !== "domain"))
169
185
  return {};
170
- if ((cfg.principal === undefined || cfg.principal === "") && !cfg.localOwnerDeclared)
186
+ if (readPrincipal(cfg.principal).kind === "absent" && !cfg.localOwnerDeclared)
171
187
  return {};
172
188
  const tierSeat = seatOf("offer.marks", cfg.irreversibilityTier, call);
173
189
  const closedDoor = ruleClearanceOf(ask, {
@@ -1,12 +1,13 @@
1
1
  /**
2
2
  * The person's persisted rules as ONE run reads them.
3
3
  *
4
- * ## One read per adjudicated call
4
+ * ## One read per judgment of a call's bytes
5
5
  *
6
- * A call is judged against ONE read of the store, pinned to its `toolCallId` ({@link PersonPathRows.pin}): whichever of the
7
- * call's consumers asks first — the read station's judgment, the org layer, the personal rule lane — takes the read, the
8
- * others are handed the same answer, and the tables the call's tool judges with when it executes are compiled from it
9
- * ({@link PathTablesFacade.forCall}). A call is an attempt the leg's occurrence table holds; the pin is released when the
6
+ * A call's bytes are judged against ONE read of the store, pinned to its `toolCallId` ({@link PersonPathRows.pin}): whichever
7
+ * of the consumers judging those bytes asks first — the read station's judgment, the org layer, the personal rule lane —
8
+ * takes the read, the others are handed the same answer, and the tables the call's tool judges with when it executes are
9
+ * compiled from it ({@link PathTablesFacade.forCall}). Judging other bytes of the same call (an approved edit) is another
10
+ * judgment: it takes a new read, which the call then holds — a rule written while a person decided binds their edit. A call is an attempt the leg's occurrence table holds; the pin is released when the
10
11
  * table no longer holds that attempt. A judgment that is no call of the leg (a visibility probe's fixed id, a gate with no
11
12
  * leg) keeps nothing: its rule lanes take a read of their own, its read station the run's latest tables.
12
13
  *
@@ -106,10 +107,12 @@ export interface PersonPathRows {
106
107
  readonly holdsPersonRows: boolean;
107
108
  /** The prepare read — the unit's first write. `undefined`, synchronously, when there is no person's rows to read. */
108
109
  prime(): Promise<void> | undefined;
109
- /** The rows of a call's one read — a call the leg's occurrence table holds: taken by its first consumer, handed to every
110
- * other until the table no longer holds that attempt; any other judgment (no leg, or an id the table does not hold — a
111
- * visibility probe) takes a read of its own, kept by nobody. Bounded ({@link PERSON_READ_BOUND_MS}); never rejects. */
112
- pin(toolCallId: string): Promise<PersonRowsRead>;
110
+ /** The rows of a call's one read of the bytes it judges (`judged`) — a call the leg's occurrence table holds: taken by its
111
+ * first consumer, handed to every other that judges the same bytes (or names none) until the table no longer holds that
112
+ * attempt; a judgment of OTHER bytes of the call (an approved edit, its outlet form) takes a new read, which the call then
113
+ * holds — a judgment reads the store, as the session rules' does. Any other judgment (no leg, or an id the table does not
114
+ * hold — a visibility probe) takes a read of its own, kept by nobody. Bounded ({@link PERSON_READ_BOUND_MS}); never rejects. */
115
+ pin(toolCallId: string, judged?: unknown): Promise<PersonRowsRead>;
113
116
  /** Settles once the tables a reader takes are compiled: a pinned call's own; any other reader's (no id, or a call holding
114
117
  * no pin), the unit's newest — through every change that lands meanwhile, within {@link PATH_TABLES_READY_BOUND_MS} —
115
118
  * or at `signal` or the run's cut ({@link PersonPathRowsConfig.signal}). Never rejects: a reader whose wait was cut
@@ -1,5 +1,7 @@
1
1
  import { ownerStoreOf } from "../permission-rule-provider.js";
2
+ import { readPrincipal } from "../principal-name.js";
2
3
  import { ORG_ADJUDICATION_TIMEOUT_MS } from "../permission-rule-org.js";
4
+ import { canonicalize } from "../canonical-json.js";
3
5
  import { PATH_RULE_FACES, READ_RULE_TOOL, eligiblePersisted, noticeRuleText } from "../permission-rule-model.js";
4
6
  import { bindPathRules, persistedRowAnchors, projectScopeIdentity } from "../path-rule-binding.js";
5
7
  import { DEFAULT_GATE_AWAIT_TIMEOUT_MS, gateWaitFailureOf, withGateTimeout } from "../gate-bounded-await.js";
@@ -21,7 +23,7 @@ const COMPILED_TABLES_KEPT = 8;
21
23
  export const EMPTY_READ_ROOTS = Object.assign(() => [], { forCall: () => () => [], ready: () => Promise.resolve() });
22
24
  export function createPersonPathRows(cfg) {
23
25
  const provider = cfg.provider;
24
- const anonymous = cfg.principal === undefined || cfg.principal === "";
26
+ const anonymous = readPrincipal(cfg.principal).kind === "absent";
25
27
  const holdsPersonRows = provider !== undefined && provider.partitions.durable && (!anonymous || cfg.localOwnerDeclared);
26
28
  const partitions = PARTITIONS.filter((p) => (p === "durable" ? provider?.partitions.durable === true : provider?.partitions.session === true));
27
29
  const unit = { durable: { failedSeq: 0 }, session: { failedSeq: 0 } };
@@ -186,20 +188,29 @@ export function createPersonPathRows(cfg) {
186
188
  pins.delete(toolCallId);
187
189
  return undefined;
188
190
  };
189
- const enter = (toolCallId, attempt) => {
191
+ const enter = (toolCallId, attempt, judged) => {
190
192
  const rows = readOnce("call").then((read) => (entry.read = read));
191
- const entry = { attempt, rows, tables: holdsPersonRows ? rows.then((read) => settleTables(entry, read)) : Promise.resolve(), ...(holdsPersonRows ? {} : { settled: {} }) };
193
+ const entry = { attempt, rows, tables: holdsPersonRows ? rows.then((read) => settleTables(entry, read)) : Promise.resolve(), ...(holdsPersonRows ? {} : { settled: {} }), ...(judged !== undefined ? { judged: { value: judged } } : {}) };
192
194
  pins.set(toolCallId, entry);
193
195
  return entry;
194
196
  };
195
- const pin = (toolCallId) => {
197
+ const serves = (p, judged) => {
198
+ if (judged === undefined || p.judged === undefined || p.judged.value === judged)
199
+ return true;
200
+ p.judged.canonical ??= canonicalize(p.judged.value);
201
+ return p.judged.canonical === canonicalize(judged);
202
+ };
203
+ const pin = (toolCallId, judged) => {
196
204
  for (const id of [...pins.keys()])
197
205
  pinOf(id);
198
206
  const known = pinOf(toolCallId);
199
- if (known !== undefined)
207
+ if (known !== undefined && serves(known, judged)) {
208
+ if (judged !== undefined)
209
+ known.judged ??= { value: judged };
200
210
  return known.rows;
211
+ }
201
212
  const attempt = cfg.occurrences?.get(toolCallId);
202
- return attempt === undefined ? readOnce("call") : enter(toolCallId, attempt).rows;
213
+ return attempt === undefined ? readOnce("call") : enter(toolCallId, attempt, judged).rows;
203
214
  };
204
215
  const settleTables = async (entry, read) => {
205
216
  try {
@@ -317,7 +328,7 @@ export function onPinnedRead(rows, stations) {
317
328
  const id = callOpts.toolCallId;
318
329
  if (readStationMemberOf(call, members) === undefined)
319
330
  return check.judge(call, args, cwd, signal, callOpts);
320
- const ready = id !== undefined && rows.holds(id) ? rows.pin(id).then(() => rows.tablesReady(id)) : rows.tablesReady(undefined, signal);
331
+ const ready = id !== undefined && rows.holds(id) ? rows.pin(id, args).then(() => rows.tablesReady(id)) : rows.tablesReady(undefined, signal);
321
332
  return ready.then(() => check.judge(call, args, cwd, signal, callOpts) ?? VOUCHED);
322
333
  },
323
334
  unanswered: (call, cause) => check.unanswered(call, cause),
@@ -38,8 +38,8 @@ export interface PrepareAskLaneInput {
38
38
  advertisedWritableDirs: Pick<AdvertisedWritableDirs, "roots"> | undefined;
39
39
  /** borrowed-readonly — the leg's ONE exempt root, stamped on every request a policy judges (`ToolCallRequest.exemptRoots`). */
40
40
  exemptRoots: readonly string[];
41
- /** borrowed-readonly — the shared mount roster; read at RUN time by the approval-preview projection (alias-aware
42
- * lookup over whatever the roster holds when the ask is minted). Never mutated here. */
41
+ /** borrowed-readonly — the shared mount roster; read at RUN time by the approval-preview projection (the dispatcher's
42
+ * resolution over whatever the roster holds when the ask is minted). Never mutated here. */
43
43
  tools: readonly AgentTool[];
44
44
  /** borrowed-mutable — the inherited-unavailable marker set. Writer here: `resolveAskBound` consumes (`delete`) a
45
45
  * marked call at its fail-closed intercept; the policy-chain phase records, the gate station sweeps. */
@@ -6,9 +6,11 @@ import { exactBoundInputHashOf } from "../canonical-json.js";
6
6
  import { composeCallSignal, raceSettlementAgainstSignal } from "./abort-race.js";
7
7
  import { failedJudgmentDeny, policyCheckAbortedDeny } from "./policy-throw.js";
8
8
  import { askMandateMember } from "../ask-origin.js";
9
- import { approvalCardMemberOf } from "../tool-roster.js";
9
+ import { approvalCardMemberOf, survivorsByName } from "../tool-roster.js";
10
+ import { toolNameIndex } from "../../internal/llm.js";
10
11
  import { gateAskCarry, lateAskSettlementObserver } from "./denial-limit-arms.js";
11
12
  import { consumeInheritedAskGrant } from "./inherited-ask-grants.js";
13
+ import { requesterOf } from "../mods/extension-call.js";
12
14
  import { settleReadRootGrant } from "./read-root-grant.js";
13
15
  function createDenyObserverNotifier(bus, signal) {
14
16
  if (bus === undefined || !bus.hasHandlers("classic.PermissionDenied"))
@@ -32,7 +34,7 @@ const sanitizePreview = (node, depth = 0) => {
32
34
  return out;
33
35
  };
34
36
  function resolveApprovalPreview(tools, toolName, args) {
35
- const t = tools.find((x) => x.name === toolName || (x.aliases?.includes(toolName) ?? false));
37
+ const t = toolNameIndex([...survivorsByName(tools).values()])(toolName);
36
38
  if (t?.approvalPreview === undefined)
37
39
  return {};
38
40
  try {
@@ -106,6 +108,7 @@ export function prepareAskLane(input) {
106
108
  ...askSourceIdentity(),
107
109
  ...riskAxesOf(req),
108
110
  ...approvalCardMemberOf(req),
111
+ ...requesterOf(modBus, req.toolCallId),
109
112
  ...(decision.action === "ask" && decision.requiresRealApproval === true ? { requiresRealApproval: true } : {}),
110
113
  ...(decision.action === "ask" ? askMandateMember(decision) : {}),
111
114
  ...(decision.action === "ask" ? gateAskCarry(decision, isLiveApproverSeat(onAsk), autoModeDenialTracking.current) : {}),
@@ -36,7 +36,7 @@ import type { AssertAllKeysHandled } from "../ask-origin.js";
36
36
  import { type ChildClampSource } from "../child-clamp-seats.js";
37
37
  import type { InheritedGate, Prepared, RunInternals, RunnerSelfSeat, ToolFaceSnapshot } from "./contracts.js";
38
38
  import { type BlockedRef } from "./synthetic-tools.js";
39
- import { RosterBuilder, type RosterAxisTables } from "../tool-roster.js";
39
+ import { RosterBuilder } from "../tool-roster.js";
40
40
  import type { ParentSpecSeat } from "../parent-spec-seat.js";
41
41
  import { type RosterSpec } from "./caller-roster.js";
42
42
  export interface PrepareCapsAndWorkflowInput {
@@ -56,7 +56,7 @@ export interface PrepareCapsAndWorkflowInput {
56
56
  /** borrowed-readonly — the trusted spawn-side channel; the Workflow mount forwards `rootSessionId`, `placementRoot`,
57
57
  * `onTaskNotification`, `workflowDepth`, the capture-floor getter reads `memoryCaptureAncestors`, and the arming reads
58
58
  * the chain's auto-mode face (`inheritedGate.autoModeFace`). */
59
- internals: Pick<RunInternals, "rootSessionId" | "placementRoot" | "onTaskNotification" | "workflowDepth" | "memoryCaptureAncestors" | "workflowParkedResume" | "questionFaceStripped" | "inheritedGate"> | undefined;
59
+ internals: Pick<RunInternals, "rootSessionId" | "placementRoot" | "onTaskNotification" | "workflowDepth" | "memoryCaptureAncestors" | "workflowParkedResume" | "holder" | "questionFaceStripped" | "inheritedGate"> | undefined;
60
60
  /** borrowed-readonly — the tree's cross-boundary token (inherited or minted), which the Workflow mount hands to its children. */ crossBoundaryTree: import("../cross-boundary-taint.js").CrossBoundaryTreeToken;
61
61
  /** borrowed-readonly — the acquired session; the classifier leg rebuilds its transcript window from `buildContext`. */
62
62
  session: Pick<StoredSession, "buildContext">;
@@ -78,12 +78,10 @@ export interface PrepareCapsAndWorkflowInput {
78
78
  lockedPreflight: Pick<LockedPreflight, "mcp">;
79
79
  /** borrowed-mutable — the effect collection (`Prepared.toolEffects`): the safety scan's caller entries, then the mounts' writes. */
80
80
  toolEffects: Prepared["toolEffects"];
81
- /** borrowed-mutable — the scan's axis tables, so the builder moves an alias's axes with its member (a phase test may omit them). */
82
- safetyAxes?: RosterAxisTables;
83
81
  /** borrowed-readonly — the frozen tool-face snapshot the Workflow mount forwards (exclude / defer / alwaysLoad / restoreGated). */
84
82
  toolFaceSnapshot: ToolFaceSnapshot;
85
- /** borrowed-readonly — the resolved prompt profile (the Workflow mount's parentPromptProfile). */
86
- promptProfile: ToolExecuteContext["promptProfile"];
83
+ /** borrowed-readonly — the task-level lean switch (the Workflow mount's parentPromptLean; absent ⇒ no key). */
84
+ promptLean: ToolExecuteContext["promptLean"];
87
85
  /** borrowed-readonly — the resolved interaction posture (the Workflow mount's parentInteractionPosture; absent ⇒ no key). */
88
86
  resolvedInteractionPosture: ToolExecuteContext["interactionPosture"];
89
87
  /** borrowed-readonly — the harness seat; the Workflow mount's parentModel / parentThinking getters read it call-time. */
@@ -117,8 +117,8 @@ function autoModeArmReasonOf(intent, facePresent, caps, capsFaulted) {
117
117
  return { armed: true, reason: "armed" };
118
118
  }
119
119
  export async function prepareCapsAndWorkflow(input) {
120
- const { spec, deps, parentSpecSeat, checkpointSeat, internals, session, sessionId, runId, hostTaskId, taskScope, taskRootFinal, model, thinking, lockedPreflight, toolEffects, safetyAxes, toolFaceSnapshot, promptProfile, resolvedInteractionPosture, harnessRef, askSeat, runClampSource, forwardEvent, inheritedGateForChildren, enrichSpecToolCtx, maybeOffload, requestReview, enterPlanMode, permissionMode, readDenyEntries, peerLaneActive, peerSendMessageBuiltIn, runnerSelf, delegated, sideCallBookRef } = input;
121
- const roster = new RosterBuilder(toolEffects, safetyAxes);
120
+ const { spec, deps, parentSpecSeat, checkpointSeat, internals, session, sessionId, runId, hostTaskId, taskScope, taskRootFinal, model, thinking, lockedPreflight, toolEffects, toolFaceSnapshot, promptLean, resolvedInteractionPosture, harnessRef, askSeat, runClampSource, forwardEvent, inheritedGateForChildren, enrichSpecToolCtx, maybeOffload, requestReview, enterPlanMode, permissionMode, readDenyEntries, peerLaneActive, peerSendMessageBuiltIn, runnerSelf, delegated, sideCallBookRef } = input;
121
+ const roster = new RosterBuilder(toolEffects);
122
122
  for (const t of spec.tools ?? []) {
123
123
  const mounted = mountCallerTool(t);
124
124
  roster.mount(mounted, { source: callerMountSource(mounted), mountedBy: "scenario" });
@@ -317,7 +317,7 @@ export async function prepareCapsAndWorkflow(input) {
317
317
  parentDeferTools: toolFaceSnapshot.defer,
318
318
  parentAlwaysLoadTools: toolFaceSnapshot.alwaysLoad,
319
319
  ...(toolFaceSnapshot.restoreGated !== undefined ? { parentRestoreGatedTools: toolFaceSnapshot.restoreGated } : {}),
320
- parentPromptProfile: promptProfile,
320
+ ...(promptLean !== undefined ? { parentPromptLean: promptLean } : {}),
321
321
  models: deps.models,
322
322
  agents: deps.agents,
323
323
  builtinAgents: deps.builtinAgents,
@@ -352,6 +352,7 @@ export async function prepareCapsAndWorkflow(input) {
352
352
  return mine.length > 0 ? mine : undefined;
353
353
  } }
354
354
  : {}),
355
+ ...(internals?.holder !== undefined ? { holder: internals.holder } : {}),
355
356
  parentSpecSeat, ...(internals?.questionFaceStripped === true ? { parentQuestionFaceStripped: true } : {}),
356
357
  ...(resolvedInteractionPosture !== undefined ? { parentInteractionPosture: resolvedInteractionPosture } : {}),
357
358
  parentMemoryCaptureState: () => {
@@ -23,6 +23,7 @@ import type { Model } from "../../internal/llm.js";
23
23
  import type { ThinkingLevel } from "../../internal/harness.js";
24
24
  import { type MicroCompactMachine } from "../context-edit.js";
25
25
  import { type CrossBoundaryPosture } from "../cross-boundary-taint.js";
26
+ import { type HostFloor } from "../host-floor.js";
26
27
  import { recordedModeSeed } from "../checkpoint-store.js";
27
28
  import { type ConfigDoorEntry, type LockedPreflight } from "../locked-config.js";
28
29
  import { type ResolvedRole } from "../roles.js";
@@ -33,10 +34,18 @@ import { type UsageWindow } from "../usage-window-store.js";
33
34
  import { type AskSeat } from "../wiring-manifest.js";
34
35
  import type { PrepareResume, RunInternals, ToolFaceLists } from "./contracts.js";
35
36
  import { resolveHost } from "../../prompt-assembly/select.js";
37
+ import type { PromptTraitName } from "../../prompt-assembly/catalog/schema.js";
36
38
  import { type RosterSpec } from "./caller-roster.js";
37
39
  export declare function limitConfigError(code: string, message: string): Error & {
38
40
  code?: string;
39
41
  };
42
+ /**
43
+ * `TaskSpec.principal`: absent (omitted, or the empty string the engine has always read as no principal) or a principal name. A
44
+ * principal that was PROVIDED and is no name (white space, an invisible or control character, a non-string) is refused at the task, on
45
+ * every leg a resume's re-supplied config included — read as "no principal" it would reach the unauthenticated floor, or, on a
46
+ * deployment that declared local-owner rules, the machine owner's standing approvals.
47
+ */
48
+ export declare function assertPrincipalValue(raw: unknown): void;
40
49
  /**
41
50
  * Validate `TaskSpec.limits` at the door and return it unchanged.
42
51
  *
@@ -52,8 +61,9 @@ export declare function limitConfigError(code: string, message: string): Error &
52
61
  */
53
62
  export declare function resolveTaskLimits(limits: TaskLimits | undefined): TaskLimits | undefined;
54
63
  /**
55
- * Validate the MODE-VALUED members of `TaskSpec.attachments` at the same door, and return the
56
- * config unchanged. Today that is exactly one member, `totalTokensReminderMode`.
64
+ * Validate the members of `TaskSpec.attachments` that refuse a value they cannot read at the same door, and return the
65
+ * config unchanged. Today that is two: the mode-valued `totalTokensReminderMode` and the boolean switch `mcpUnavailable`
66
+ * (read by its own reader, `mcpUnavailableOn`, which the leg asks as well).
57
67
  *
58
68
  * WHY A DOOR AT ALL (坏值响亮度律): a knob whose bad value silently folds to the default is a knob the
59
69
  * deployment believes is armed. `totalTokensReminderMode: "padded_countdown"` (underscore) or
@@ -86,36 +96,13 @@ export declare function resolveTaskLimits(limits: TaskLimits | undefined): TaskL
86
96
  */
87
97
  export declare function resolveAttachmentsConfig(attachments: TaskSpec["attachments"]): TaskSpec["attachments"];
88
98
  /**
89
- * R2 双形轴(追加令 2026-07-18): the reference's fable-variant prompt gate (
90
- * `fable_5_mitigations` capability / claude-mythos-5), ORTHOGONAL to the simple/classic profile.
91
- * sema is BYOM, so the id may carry provider prefixes ("anthropic/claude-fable-5",
92
- * "openrouter/anthropic/claude-fable-5"): BOUNDARY-AWARE family match on the last path segment
93
- * (raw substring classified "vendor/not-claude-fable-5" and "claude-mythos-50"
94
- * as fable), case-normalized. Recognition set = CC's _Nr (startsWith "claude-fable-") + b9e
95
- * (mythos-5). R3 system sections fork on the resulting fact.
96
- */
97
- export declare function isFableFamilyModelId(id: string): boolean;
98
- /**
99
- * The SINGLE decision point for the two prompt-shape axes.
100
- * Both were resolved in separate places with different mechanisms — `promptProfile` off a TaskSpec field,
101
- * `fableMitigations` off a raw model-id prefix test — so "which shape does this task speak" had no one
102
- * place to read. The reference's counterpart is a model-registry `capabilities` array (one table drives
103
- * `lean_prompt` + `fable_5_mitigations` alike).
104
- *
105
- * sema stays BYOM: we cannot key off a capability table for arbitrary model ids, so the RESOLUTION RULES
106
- * are unchanged — profile: spec > inherited internals > "simple"; mitigations: model family. This is a
107
- * consolidation, not a behavior change (the axes stay ORTHOGONAL: neither rewrites the other).
99
+ * The run's prompt traits — the one place prepare forms them: the model's declared set (`Model.promptTraits`, read
100
+ * through the model door: a retired `promptGuidance` or a name that is no trait refuses the task by name) with the
101
+ * task's switch on `lean_prompt` (`promptLean`, as the spec writes it — an engine-built child's spec carries its
102
+ * parent's), bundles expanded ({@link effectiveTraitsOf}). The reference's counterpart is a model registry's capability list; sema is
103
+ * BYOM, so the model entry carries the list and no model id is read.
108
104
  */
109
- export declare function resolveModelPromptTraits(model: {
110
- id: string;
111
- }, spec: {
112
- promptProfile?: "simple" | "classic";
113
- }, internals?: {
114
- promptProfile?: "simple" | "classic";
115
- }): {
116
- promptProfile: "simple" | "classic";
117
- fableMitigations: boolean;
118
- };
105
+ export declare function resolvePromptTraits(model: Model, promptLean: boolean | undefined): ReadonlySet<PromptTraitName>;
119
106
  export interface PrepareConfigDoorsInput {
120
107
  /** borrowed-readonly — the snapshot spec (its roster is faces). NEVER mutated here: the per-task agents rebind returns a
121
108
  * SHALLOW COPY on {@link PrepareConfigDoorsResult.spec} (only `tools` replaced, each rebuilt entry through the snapshot). */
@@ -130,7 +117,7 @@ export interface PrepareConfigDoorsInput {
130
117
  /** borrowed-readonly — presence gates the resumeAt-conflict door and exempts the empty-objective
131
118
  * door (a checkpoint resume passes `objective: ""` by design). */
132
119
  resume?: PrepareResume | undefined;
133
- /** borrowed-readonly — trusted engine channel: prompt-profile inheritance, the spawning run's
120
+ /** borrowed-readonly — trusted engine channel: the spawning run's
134
121
  * interaction posture, the engine question-strip flag. */
135
122
  internals?: RunInternals | undefined;
136
123
  }
@@ -142,8 +129,12 @@ export interface PrepareConfigDoorsResult {
142
129
  /** owned — the frozen task-start copies of the caller's tool-face control arrays; the driver compiles the leg's selector
143
130
  * from them, and the selector (with the disclosure lists) is the ONLY thing later face reads consult. Frozen-immutable. */
144
131
  toolFaceLists: ToolFaceLists;
145
- /** owned — the profile half of the single decision point (model-independent by contract). */
146
- promptProfile: "simple" | "classic";
132
+ /** owned — the task-level switch on the lean shape (`TaskSpec.promptLean`, validated; an engine-built child's spec
133
+ * carries its parent's): what the run hands its children and workflow agents, never its effective traits. */
134
+ promptLean: boolean | undefined;
135
+ /** owned, frozen-by-contract — the run's effective prompt traits ({@link resolvePromptTraits}): the catalog's
136
+ * variants, every overlay's `when.traits` and each tool's description variants select on them. */
137
+ promptTraits: ReadonlySet<PromptTraitName>;
147
138
  /** owned — the host selector values (`TaskSpec.promptRole` / `TaskSpec.promptForm`, validated) the assembly selects on. */
148
139
  promptHost: ReturnType<typeof resolveHost>;
149
140
  /** owned — the run's binding (`TaskSpec.promptBinding`, validated): the selector value every overlay's `when.binding` reads. */
@@ -170,8 +161,6 @@ export interface PrepareConfigDoorsResult {
170
161
  /** owned — the compaction model: explicit wins, else the `summarize` role, else undefined (main
171
162
  * model fallback inside maybeCompact). NOT derivable from {@link resolvedRole}. */
172
163
  compModel: Model | undefined;
173
- /** owned — the mitigations half of the decision point (model-family fact). */
174
- fableMitigations: boolean;
175
164
  /** owned, frozen — model-gate DISCLOSURE data (the application itself already
176
165
  * happened on {@link spec}: its `tools` is the survivor rebind when anything was removed).
177
166
  * prepareTask emits the notices from this after the doors return (the onNotice station);
@@ -214,6 +203,7 @@ export interface PrepareConfigDoorsResult {
214
203
  /** owned — the screened cross-boundary posture: the deps seat read ONCE, a bad value refused; absent stays `undefined` (undeclared is its own fact). */
215
204
  crossBoundaryPosture: CrossBoundaryPosture | undefined;
216
205
  advisorTool: "disabled" | undefined;
206
+ hostFloor: HostFloor | undefined;
217
207
  }
218
208
  /** The microCompact knob door (坏值响亮度默认律, the sibling knob doors' form:
219
209
  * interactionPosture / toolModelGate / staleToolResultOffload). Placement is load-bearing:
@@ -238,7 +228,7 @@ export declare const checkpointStoreSeat: (spec: {
238
228
  export declare function assertResumeConfigRecord(config: unknown): void;
239
229
  /** The spec the value doors read: a prepare's (its roster is faces) or a resume's re-supplied config (no objective, no session id). */
240
230
  type ValueDoorSpec = Omit<TaskSpec, "tools" | "objective" | "sessionId" | "userAttachments"> & Partial<Pick<TaskSpec, "objective" | "sessionId">>;
241
- type ConfigValueDoorsResult = Pick<PrepareConfigDoorsResult, "toolFaceLists" | "promptHost" | "promptBinding" | "lockedPreflight" | "microCompactKnob" | "memoryDelegationEvidence" | "memoryProvenance" | "memoryCapturePolicy" | "usageWindows" | "brainCallGuardrailMs" | "crossBoundaryPosture" | "advisorTool"> & {
231
+ type ConfigValueDoorsResult = Pick<PrepareConfigDoorsResult, "toolFaceLists" | "promptHost" | "promptBinding" | "lockedPreflight" | "microCompactKnob" | "memoryDelegationEvidence" | "memoryProvenance" | "memoryCapturePolicy" | "usageWindows" | "brainCallGuardrailMs" | "crossBoundaryPosture" | "advisorTool" | "promptLean" | "hostFloor"> & {
242
232
  skillListingSeats: {
243
233
  fraction: unknown;
244
234
  maxDescChars: unknown;
@@ -259,6 +249,7 @@ export declare function configValueDoors(input: {
259
249
  deps: RunnerDeps;
260
250
  resumeLeg: boolean;
261
251
  sessions: SessionStore;
252
+ holder?: string | undefined;
262
253
  }, enter?: ConfigDoorEntry): ConfigValueDoorsResult;
263
254
  /**
264
255
  * The doors a RESUMED leg's prepare refuses at, run as one screen BEFORE the claim — prepare's own functions, so a refusal carries
@@ -273,6 +264,6 @@ export declare function configValueDoors(input: {
273
264
  * corrected resume redeems the same token. A throw that is none of prepare's codes leaves as it was thrown. Returns the config the
274
265
  * leg is handed: the caller's, its MCP servers and A2A peers the frozen entries the lock layer judged (read once, dialed as judged).
275
266
  */
276
- export declare function refuseResumeDoors<C extends ValueDoorSpec & Pick<TaskSpec, "userAttachments">>(config: C, recordedGate: Parameters<typeof recordedModeSeed>[0], deps: RunnerDeps, sessions: SessionStore): C;
267
+ export declare function refuseResumeDoors<C extends ValueDoorSpec & Pick<TaskSpec, "userAttachments">>(config: C, recordedGate: Parameters<typeof recordedModeSeed>[0], deps: RunnerDeps, sessions: SessionStore, holder?: string): C;
277
268
  export declare function prepareConfigDoors(input: PrepareConfigDoorsInput): PrepareConfigDoorsResult;
278
269
  export {};