@sema-agent/core 7.51.2 → 7.53.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 (446) hide show
  1. package/CHANGELOG.md +698 -2
  2. package/README.md +3 -1
  3. package/dist/agents/agent-transcript-tool.d.ts +1 -1
  4. package/dist/agents/cascade.js +4 -0
  5. package/dist/agents/cross-session-envelope.d.ts +8 -0
  6. package/dist/agents/cross-session-envelope.js +6 -0
  7. package/dist/agents/cross-session-judge.d.ts +21 -1
  8. package/dist/agents/cross-session-judge.js +8 -0
  9. package/dist/agents/cross-session-ref.d.ts +5 -0
  10. package/dist/agents/cross-session-ref.js +1 -0
  11. package/dist/agents/cumulative-stats.d.ts +3 -0
  12. package/dist/agents/cumulative-stats.js +3 -0
  13. package/dist/agents/list-agents-tool.d.ts +1 -1
  14. package/dist/agents/org-delivery-gate.d.ts +122 -0
  15. package/dist/agents/org-delivery-gate.js +69 -0
  16. package/dist/agents/peer-held-queue.d.ts +9 -4
  17. package/dist/agents/peer-held-queue.js +6 -5
  18. package/dist/agents/peer-session-drain.d.ts +35 -5
  19. package/dist/agents/peer-session-drain.js +271 -180
  20. package/dist/agents/read-inbox-tool.d.ts +8 -1
  21. package/dist/agents/read-inbox-tool.js +5 -1
  22. package/dist/agents/repair-loop.js +4 -0
  23. package/dist/agents/send-message-tool.d.ts +11 -16
  24. package/dist/agents/send-message-tool.js +11 -13
  25. package/dist/agents/subagent.d.ts +3 -0
  26. package/dist/agents/subagent.js +105 -76
  27. package/dist/agents/tool-filter.d.ts +58 -13
  28. package/dist/agents/tool-filter.js +34 -14
  29. package/dist/bench/metrics.d.ts +1 -0
  30. package/dist/brain/anthropic.d.ts +6 -1
  31. package/dist/brain/anthropic.js +17 -13
  32. package/dist/brain/model-presets.d.ts +4 -5
  33. package/dist/brain/model-presets.js +6 -5
  34. package/dist/brain/open-responses.js +16 -12
  35. package/dist/brain/openai.js +16 -12
  36. package/dist/brain/request-params.d.ts +12 -33
  37. package/dist/brain/request-params.js +5 -2
  38. package/dist/brain/request-route.d.ts +9 -8
  39. package/dist/brain/request-route.js +1 -0
  40. package/dist/brain/route-adjudicator.d.ts +123 -47
  41. package/dist/brain/route-adjudicator.js +171 -42
  42. package/dist/brain/route-conformance.js +2 -2
  43. package/dist/brain/routing.d.ts +24 -1
  44. package/dist/brain/routing.js +54 -19
  45. package/dist/brain/status-sink.d.ts +18 -0
  46. package/dist/brain/status-sink.js +7 -0
  47. package/dist/brain/timeout.js +5 -4
  48. package/dist/core/a2a.d.ts +5 -2
  49. package/dist/core/a2a.js +30 -13
  50. package/dist/core/allow-entry.d.ts +42 -9
  51. package/dist/core/allow-entry.js +25 -18
  52. package/dist/core/auto-compaction.d.ts +80 -20
  53. package/dist/core/auto-compaction.js +65 -18
  54. package/dist/core/auto-promote.d.ts +2 -1
  55. package/dist/core/auto-promote.js +2 -2
  56. package/dist/core/caller-tool-name.d.ts +9 -0
  57. package/dist/core/caller-tool-name.js +13 -0
  58. package/dist/core/checkpoint-requirements.d.ts +7 -1
  59. package/dist/core/checkpoint-requirements.js +2 -0
  60. package/dist/core/checkpoint-store.d.ts +57 -24
  61. package/dist/core/checkpoint-store.js +3 -3
  62. package/dist/core/child-clamp-seats.d.ts +6 -0
  63. package/dist/core/child-clamp-seats.js +2 -1
  64. package/dist/core/compliance.js +3 -1
  65. package/dist/core/credential-vocabulary.d.ts +33 -8
  66. package/dist/core/credential-vocabulary.js +32 -7
  67. package/dist/core/decision-receipt.d.ts +2 -2
  68. package/dist/core/delegation-frames.d.ts +9 -2
  69. package/dist/core/delegation-name.d.ts +18 -0
  70. package/dist/core/delegation-name.js +47 -0
  71. package/dist/core/effective-path-target.d.ts +25 -6
  72. package/dist/core/effective-path-target.js +24 -2
  73. package/dist/core/engine-capabilities.d.ts +8 -1
  74. package/dist/core/engine-capabilities.js +1 -1
  75. package/dist/core/engine-notice.d.ts +49 -21
  76. package/dist/core/frontmatter-fence.d.ts +10 -0
  77. package/dist/core/frontmatter-fence.js +6 -0
  78. package/dist/core/gate-fold.js +8 -25
  79. package/dist/core/gate-lanes.js +358 -274
  80. package/dist/core/gate-outcome.d.ts +11 -6
  81. package/dist/core/governance-codes.d.ts +11 -4
  82. package/dist/core/governance-codes.js +12 -3
  83. package/dist/core/hands-band-screen.d.ts +7 -0
  84. package/dist/core/hands-band-screen.js +32 -0
  85. package/dist/core/hooks.d.ts +283 -739
  86. package/dist/core/hooks.js +100 -193
  87. package/dist/{tools/fs → core}/image-admission.d.ts +21 -3
  88. package/dist/{tools/fs → core}/image-admission.js +24 -6
  89. package/dist/core/locked-config.d.ts +84 -32
  90. package/dist/core/locked-config.js +128 -42
  91. package/dist/core/mcp-connection-pool.d.ts +4 -1
  92. package/dist/core/mcp-connection-pool.js +7 -2
  93. package/dist/core/mcp-probe.d.ts +12 -9
  94. package/dist/core/mcp-probe.js +3 -3
  95. package/dist/core/mcp-server-spec.d.ts +104 -10
  96. package/dist/core/mcp-server-spec.js +183 -33
  97. package/dist/core/mcp.d.ts +31 -20
  98. package/dist/core/mcp.js +66 -56
  99. package/dist/core/memory-engine/data-plane.js +5 -1
  100. package/dist/core/memory-engine/distiller.js +16 -2
  101. package/dist/core/memory-engine/engine.d.ts +22 -30
  102. package/dist/core/memory-engine/engine.js +16 -10
  103. package/dist/core/memory-engine/frontmatter.d.ts +6 -0
  104. package/dist/core/memory-engine/frontmatter.js +19 -16
  105. package/dist/core/memory.d.ts +2 -2
  106. package/dist/core/mode-policy.d.ts +5 -16
  107. package/dist/core/mode-policy.js +7 -19
  108. package/dist/core/model-seat.d.ts +4 -1
  109. package/dist/core/mods/dollar.d.ts +109 -0
  110. package/dist/core/mods/dollar.js +154 -0
  111. package/dist/core/mods/host.d.ts +23 -0
  112. package/dist/core/mods/host.js +21 -0
  113. package/dist/core/mods/kernel/budget.d.ts +43 -0
  114. package/dist/core/mods/kernel/budget.js +83 -0
  115. package/dist/core/mods/kernel/dispatch.d.ts +100 -0
  116. package/dist/core/mods/kernel/dispatch.js +699 -0
  117. package/dist/core/mods/kernel/events.d.ts +245 -0
  118. package/dist/core/mods/kernel/events.js +210 -0
  119. package/dist/core/mods/kernel/index.d.ts +6 -0
  120. package/dist/core/mods/kernel/index.js +5 -0
  121. package/dist/core/mods/kernel/receive.d.ts +94 -0
  122. package/dist/core/mods/kernel/receive.js +188 -0
  123. package/dist/core/mods/kernel/registration.d.ts +131 -0
  124. package/dist/core/mods/kernel/registration.js +102 -0
  125. package/dist/core/mods/kernel/site-rules.d.ts +149 -0
  126. package/dist/core/mods/kernel/site-rules.js +296 -0
  127. package/dist/core/mods/stations.d.ts +344 -0
  128. package/dist/core/mods/stations.js +437 -0
  129. package/dist/core/mounted-mcp.d.ts +57 -0
  130. package/dist/core/mounted-mcp.js +71 -2
  131. package/dist/core/own-property-receipt.d.ts +13 -0
  132. package/dist/core/own-property-receipt.js +13 -23
  133. package/dist/core/parent-spec-seat.d.ts +18 -7
  134. package/dist/core/parent-spec-seat.js +6 -2
  135. package/dist/core/path-identity.js +2 -1
  136. package/dist/core/permission-rule-model.d.ts +58 -9
  137. package/dist/core/permission-rule-model.js +81 -7
  138. package/dist/core/permission-rule-org.d.ts +163 -33
  139. package/dist/core/permission-rule-org.js +205 -71
  140. package/dist/core/permission-rule-syntax.d.ts +15 -0
  141. package/dist/core/permission-rule-syntax.js +24 -16
  142. package/dist/core/permission-rules.d.ts +14 -2
  143. package/dist/core/permission-rules.js +63 -23
  144. package/dist/core/prompt-section-seat.d.ts +15 -27
  145. package/dist/core/prompt-section-seat.js +73 -40
  146. package/dist/core/protocol-http-auth.d.ts +3 -1
  147. package/dist/core/protocol-http-auth.js +2 -0
  148. package/dist/core/reminder-mint.d.ts +2 -2
  149. package/dist/core/remote-env.d.ts +24 -12
  150. package/dist/core/remote-env.js +1 -0
  151. package/dist/core/resume-startup-cause.d.ts +16 -1
  152. package/dist/core/resume-startup-cause.js +4 -1
  153. package/dist/core/retention.js +7 -2
  154. package/dist/core/retired-keys.d.ts +12 -2
  155. package/dist/core/retired-keys.js +15 -1
  156. package/dist/core/roles.js +60 -10
  157. package/dist/core/rule-lane-reads.js +1 -1
  158. package/dist/core/runner/announce-once-ledger.d.ts +31 -1
  159. package/dist/core/runner/announce-once-ledger.js +22 -0
  160. package/dist/core/runner/assemble-result.d.ts +9 -0
  161. package/dist/core/runner/assemble-result.js +3 -1
  162. package/dist/core/runner/call-hook-stations.d.ts +23 -27
  163. package/dist/core/runner/call-hook-stations.js +58 -42
  164. package/dist/core/runner/caller-stop-gate.d.ts +25 -0
  165. package/dist/core/runner/caller-stop-gate.js +7 -0
  166. package/dist/core/runner/compaction-seams.d.ts +8 -22
  167. package/dist/core/runner/compaction-seams.js +28 -53
  168. package/dist/core/runner/construction-doors.js +11 -1
  169. package/dist/core/runner/contracts.d.ts +86 -83
  170. package/dist/core/runner/credential-origin-seat.d.ts +2 -0
  171. package/dist/core/runner/credential-origin-seat.js +19 -0
  172. package/dist/core/runner/extra-body-dropped-seat.d.ts +2 -6
  173. package/dist/core/runner/gate-exit.d.ts +47 -36
  174. package/dist/core/runner/gate-exit.js +12 -5
  175. package/dist/core/runner/image.js +1 -2
  176. package/dist/core/runner/inline-image.js +1 -1
  177. package/dist/core/runner/mcp-redial.d.ts +52 -10
  178. package/dist/core/runner/mcp-redial.js +38 -9
  179. package/dist/core/runner/notice-seat-input.d.ts +11 -0
  180. package/dist/core/runner/notice-seat-input.js +1 -0
  181. package/dist/core/runner/permission-rule-lanes.d.ts +5 -2
  182. package/dist/core/runner/permission-rule-lanes.js +22 -10
  183. package/dist/core/runner/person-path-rows.d.ts +3 -1
  184. package/dist/core/runner/person-path-rows.js +3 -2
  185. package/dist/core/runner/prepare-acquire-reconcile.js +5 -1
  186. package/dist/core/runner/prepare-ask-lane.d.ts +5 -7
  187. package/dist/core/runner/prepare-ask-lane.js +6 -15
  188. package/dist/core/runner/prepare-caps-and-workflow.d.ts +4 -2
  189. package/dist/core/runner/prepare-caps-and-workflow.js +25 -8
  190. package/dist/core/runner/prepare-config-doors.d.ts +52 -1
  191. package/dist/core/runner/prepare-config-doors.js +168 -143
  192. package/dist/core/runner/prepare-defer-classify.js +7 -11
  193. package/dist/core/runner/prepare-delegation-surface.d.ts +2 -2
  194. package/dist/core/runner/prepare-delegation-surface.js +7 -5
  195. package/dist/core/runner/prepare-gate-stations.d.ts +8 -11
  196. package/dist/core/runner/prepare-gate-stations.js +11 -10
  197. package/dist/core/runner/prepare-hands-readface.d.ts +1 -1
  198. package/dist/core/runner/prepare-hands-readface.js +2 -1
  199. package/dist/core/runner/prepare-inherited-gate.d.ts +8 -12
  200. package/dist/core/runner/prepare-inherited-gate.js +10 -23
  201. package/dist/core/runner/prepare-listings.d.ts +1 -1
  202. package/dist/core/runner/prepare-listings.js +4 -2
  203. package/dist/core/runner/prepare-memory-engine-session.d.ts +0 -6
  204. package/dist/core/runner/prepare-memory-engine-session.js +20 -7
  205. package/dist/core/runner/prepare-memory.d.ts +3 -2
  206. package/dist/core/runner/prepare-memory.js +6 -2
  207. package/dist/core/runner/prepare-offload-wrappers.d.ts +4 -4
  208. package/dist/core/runner/prepare-offload-wrappers.js +2 -1
  209. package/dist/core/runner/prepare-park-ask.js +10 -14
  210. package/dist/core/runner/prepare-policy-chain.d.ts +17 -15
  211. package/dist/core/runner/prepare-policy-chain.js +104 -109
  212. package/dist/core/runner/prepare-project-context.d.ts +1 -1
  213. package/dist/core/runner/prepare-project-context.js +11 -12
  214. package/dist/core/runner/prepare-prompt-assembly.d.ts +45 -40
  215. package/dist/core/runner/prepare-prompt-assembly.js +138 -101
  216. package/dist/core/runner/prepare-prompt-inputs.d.ts +28 -23
  217. package/dist/core/runner/prepare-prompt-inputs.js +11 -10
  218. package/dist/core/runner/prepare-protocol-tools.d.ts +11 -7
  219. package/dist/core/runner/prepare-protocol-tools.js +20 -13
  220. package/dist/core/runner/prepare-question-face.d.ts +4 -2
  221. package/dist/core/runner/prepare-question-face.js +4 -3
  222. package/dist/core/runner/prepare-safety-scan.js +6 -10
  223. package/dist/core/runner/prepare-suspend-saga.d.ts +6 -0
  224. package/dist/core/runner/prepare-suspend-saga.js +7 -5
  225. package/dist/core/runner/prepare-task.js +41 -23
  226. package/dist/core/runner/prepare-turn-wiring.d.ts +13 -15
  227. package/dist/core/runner/prepare-turn-wiring.js +29 -27
  228. package/dist/core/runner/prepare-wiring-manifest.d.ts +13 -9
  229. package/dist/core/runner/prepare-wiring-manifest.js +14 -11
  230. package/dist/core/runner/resume-admission.d.ts +4 -1
  231. package/dist/core/runner/resume-admission.js +7 -5
  232. package/dist/core/runner/resume-apply.d.ts +5 -2
  233. package/dist/core/runner/resume-apply.js +24 -42
  234. package/dist/core/runner/resume-checkpoint-screen.d.ts +1 -0
  235. package/dist/core/runner/resume-checkpoint-screen.js +9 -1
  236. package/dist/core/runner/resume-internals-and-config.d.ts +3 -3
  237. package/dist/core/runner/resume-internals-and-config.js +3 -8
  238. package/dist/core/runner/resume-preflight.js +38 -16
  239. package/dist/core/runner/retired-runner-deps.d.ts +5 -6
  240. package/dist/core/runner/retired-runner-deps.js +4 -5
  241. package/dist/core/runner/run-brain-sinks.d.ts +3 -2
  242. package/dist/core/runner/run-brain-sinks.js +5 -1
  243. package/dist/core/runner/run-compaction-machinery.d.ts +7 -1
  244. package/dist/core/runner/run-compaction-machinery.js +7 -33
  245. package/dist/core/runner/run-harness-handlers.js +4 -2
  246. package/dist/core/runner/run-identity-wiring.d.ts +3 -1
  247. package/dist/core/runner/run-identity-wiring.js +3 -2
  248. package/dist/core/runner/run-leg.js +103 -95
  249. package/dist/core/runner/run-notification-lane.js +1 -0
  250. package/dist/core/runner/run-recovery-lanes.d.ts +3 -0
  251. package/dist/core/runner/run-recovery-lanes.js +14 -11
  252. package/dist/core/runner/run-settle-and-teardown.js +9 -28
  253. package/dist/core/runner/run-stop-and-final-verify.js +18 -25
  254. package/dist/core/runner/run-terminal-adoption.d.ts +3 -0
  255. package/dist/core/runner/run-terminal-adoption.js +34 -22
  256. package/dist/core/runner/run-tool-mount-facts.js +5 -3
  257. package/dist/core/runner/run-turn-boundary.js +32 -37
  258. package/dist/core/runner/runtask.d.ts +6 -7
  259. package/dist/core/runner/runtask.js +15 -73
  260. package/dist/core/runner/session-rule-policy.d.ts +5 -5
  261. package/dist/core/runner/session-rule-policy.js +13 -8
  262. package/dist/core/runner/side-call-account.d.ts +68 -0
  263. package/dist/core/runner/side-call-account.js +61 -0
  264. package/dist/core/runner/skills-seat.d.ts +15 -0
  265. package/dist/core/runner/skills-seat.js +57 -0
  266. package/dist/core/runner/stream-halt-verbs.js +12 -17
  267. package/dist/core/runner/stream-lifecycle-verbs.js +8 -5
  268. package/dist/core/runner/stream-steer-verb.d.ts +1 -1
  269. package/dist/core/runner/stream-steer-verb.js +20 -38
  270. package/dist/core/runner/sub-agent-deny-lists.d.ts +124 -23
  271. package/dist/core/runner/sub-agent-deny-lists.js +230 -71
  272. package/dist/core/runner/synthetic-tools.d.ts +5 -2
  273. package/dist/core/runner/synthetic-tools.js +2 -12
  274. package/dist/core/runner/tool-end-body.d.ts +5 -6
  275. package/dist/core/runner/tool-end-body.js +6 -4
  276. package/dist/core/runner/tool-not-executed.d.ts +15 -0
  277. package/dist/core/runner/tool-not-executed.js +30 -0
  278. package/dist/core/runner/tool-occurrence.d.ts +8 -7
  279. package/dist/core/runner/tool-occurrence.js +5 -5
  280. package/dist/core/runner/tool-result-media-seat.d.ts +1 -1
  281. package/dist/core/runner-deps.d.ts +43 -36
  282. package/dist/core/safety-merge-corpus.js +18 -2
  283. package/dist/core/secret-env.d.ts +88 -20
  284. package/dist/core/secret-env.js +192 -38
  285. package/dist/core/session-policy-store.d.ts +71 -16
  286. package/dist/core/session-policy-store.js +138 -28
  287. package/dist/core/session-reconcile.d.ts +4 -0
  288. package/dist/core/session-reconcile.js +2 -1
  289. package/dist/core/shell-read-silence.js +3 -32
  290. package/dist/core/side-query.d.ts +5 -3
  291. package/dist/core/skill-grant.d.ts +3 -2
  292. package/dist/core/skill-grant.js +17 -9
  293. package/dist/core/skills-directory.d.ts +31 -11
  294. package/dist/core/skills-directory.js +655 -104
  295. package/dist/core/store-contracts/mailbox-store-contract.js +13 -0
  296. package/dist/core/task-event.d.ts +49 -3
  297. package/dist/core/task-notification.js +2 -2
  298. package/dist/core/task-result.d.ts +8 -0
  299. package/dist/core/task-spec.d.ts +20 -19
  300. package/dist/core/task-stream.d.ts +14 -4
  301. package/dist/core/tighten-task-spec.d.ts +4 -3
  302. package/dist/core/tighten-task-spec.js +2 -4
  303. package/dist/core/tool-check-reading.d.ts +74 -0
  304. package/dist/core/tool-check-reading.js +80 -0
  305. package/dist/core/tool-policy.d.ts +62 -18
  306. package/dist/core/tool-policy.js +86 -15
  307. package/dist/core/tool-registry.d.ts +20 -0
  308. package/dist/core/tool-registry.js +4 -0
  309. package/dist/core/tool-spec.d.ts +10 -6
  310. package/dist/core/tools.js +2 -0
  311. package/dist/core/trace.d.ts +51 -32
  312. package/dist/core/types.d.ts +2 -2
  313. package/dist/core/types.js +1 -1
  314. package/dist/core/unc-spelling.d.ts +10 -0
  315. package/dist/core/unc-spelling.js +3 -0
  316. package/dist/core/untrusted-egress.d.ts +8 -0
  317. package/dist/core/untrusted-egress.js +4 -1
  318. package/dist/core/untrusted-text.d.ts +16 -0
  319. package/dist/core/untrusted-text.js +7 -2
  320. package/dist/core/user-attachment.d.ts +25 -4
  321. package/dist/core/user-attachment.js +63 -42
  322. package/dist/core/wiring-manifest.d.ts +18 -15
  323. package/dist/core/wiring-manifest.js +2 -2
  324. package/dist/engine/compaction/utils.js +1 -2
  325. package/dist/engine/execution-env/node-execution-env.d.ts +4 -3
  326. package/dist/engine/execution-env/symlink-chain.js +1 -1
  327. package/dist/engine/harness/agent-harness.d.ts +1 -1
  328. package/dist/engine/harness/agent-harness.js +5 -4
  329. package/dist/engine/harness/types.d.ts +20 -16
  330. package/dist/engine/harness/types.js +7 -1
  331. package/dist/engine/llm/types.d.ts +12 -7
  332. package/dist/engine/loop/agent-loop.d.ts +12 -1
  333. package/dist/engine/loop/agent-loop.js +18 -6
  334. package/dist/engine/loop/types.d.ts +8 -2
  335. package/dist/engine/lsp/node-lsp-manager.d.ts +2 -2
  336. package/dist/engine/session/import-validate.js +3 -10
  337. package/dist/engine/session/session.d.ts +4 -4
  338. package/dist/engine/session/session.js +4 -4
  339. package/dist/index.d.ts +33 -23
  340. package/dist/index.js +23 -15
  341. package/dist/internal/harness.d.ts +2 -1
  342. package/dist/internal/harness.js +2 -1
  343. package/dist/orchestration/goal.d.ts +24 -1
  344. package/dist/orchestration/goal.js +3 -2
  345. package/dist/orchestration/run-spec.d.ts +4 -6
  346. package/dist/orchestration/run-spec.js +39 -63
  347. package/dist/orchestration/run-workflow-tool.js +1 -2
  348. package/dist/orchestration/workflow.d.ts +11 -3
  349. package/dist/orchestration/workflow.js +11 -2
  350. package/dist/prompt-assembly/artifact-store.d.ts +72 -56
  351. package/dist/prompt-assembly/artifact-store.js +60 -52
  352. package/dist/prompt-assembly/artifact.d.ts +90 -76
  353. package/dist/prompt-assembly/artifact.js +197 -145
  354. package/dist/prompt-assembly/assemble.d.ts +36 -29
  355. package/dist/prompt-assembly/assemble.js +34 -220
  356. package/dist/prompt-assembly/bands.d.ts +20 -0
  357. package/dist/prompt-assembly/bands.js +18 -0
  358. package/dist/prompt-assembly/catalog/constitution.d.ts +23 -0
  359. package/dist/prompt-assembly/catalog/constitution.js +69 -0
  360. package/dist/prompt-assembly/catalog/core-behavior.d.ts +9 -0
  361. package/dist/prompt-assembly/catalog/core-behavior.js +85 -0
  362. package/dist/prompt-assembly/catalog/index.d.ts +11 -0
  363. package/dist/prompt-assembly/catalog/index.js +60 -0
  364. package/dist/prompt-assembly/catalog/memory.d.ts +13 -0
  365. package/dist/prompt-assembly/catalog/memory.js +6 -0
  366. package/dist/prompt-assembly/catalog/modes.d.ts +15 -0
  367. package/dist/prompt-assembly/catalog/modes.js +137 -0
  368. package/dist/prompt-assembly/catalog/role.d.ts +10 -0
  369. package/dist/prompt-assembly/catalog/role.js +157 -0
  370. package/dist/prompt-assembly/catalog/schema.d.ts +138 -0
  371. package/dist/prompt-assembly/catalog/schema.js +25 -0
  372. package/dist/prompt-assembly/catalog/sections.d.ts +9 -0
  373. package/dist/prompt-assembly/catalog/sections.js +98 -0
  374. package/dist/prompt-assembly/catalog/team.d.ts +4 -0
  375. package/dist/prompt-assembly/catalog/team.js +258 -0
  376. package/dist/prompt-assembly/composer.d.ts +26 -28
  377. package/dist/prompt-assembly/composer.js +124 -46
  378. package/dist/prompt-assembly/epoch.d.ts +89 -79
  379. package/dist/prompt-assembly/epoch.js +115 -142
  380. package/dist/prompt-assembly/explain.d.ts +58 -34
  381. package/dist/prompt-assembly/explain.js +21 -24
  382. package/dist/prompt-assembly/overlay.d.ts +137 -0
  383. package/dist/prompt-assembly/overlay.js +339 -0
  384. package/dist/prompt-assembly/renderers.d.ts +21 -0
  385. package/dist/prompt-assembly/renderers.js +39 -0
  386. package/dist/prompt-assembly/section-usage.d.ts +3 -3
  387. package/dist/prompt-assembly/section-usage.js +1 -1
  388. package/dist/prompt-assembly/select.d.ts +71 -0
  389. package/dist/prompt-assembly/select.js +106 -0
  390. package/dist/prompt-assembly/sugar.d.ts +31 -0
  391. package/dist/prompt-assembly/sugar.js +20 -0
  392. package/dist/prompt-assembly/turn-snapshot.d.ts +3 -2
  393. package/dist/prompt-assembly/types.d.ts +45 -148
  394. package/dist/prompts/coordinator.d.ts +2 -21
  395. package/dist/prompts/coordinator.js +3 -255
  396. package/dist/prompts/cowork.d.ts +27 -16
  397. package/dist/prompts/cowork.js +2 -23
  398. package/dist/prompts/default.d.ts +38 -511
  399. package/dist/prompts/default.js +20 -288
  400. package/dist/prompts/supervisor.d.ts +6 -71
  401. package/dist/prompts/supervisor.js +6 -117
  402. package/dist/stores/file/permission-rule-store.d.ts +1 -1
  403. package/dist/stores/file/permission-rule-store.js +2 -1
  404. package/dist/tools/artifact/artifact-tool.js +4 -3
  405. package/dist/tools/fs/bash-readonly-classifier.d.ts +6 -5
  406. package/dist/tools/fs/dir-entries.d.ts +4 -2
  407. package/dist/tools/fs/dir-entries.js +16 -4
  408. package/dist/tools/fs/fs-bash.d.ts +1 -1
  409. package/dist/tools/fs/fs-bash.js +22 -11
  410. package/dist/tools/fs/fs-pdf.js +17 -13
  411. package/dist/tools/fs/fs-read.js +4 -3
  412. package/dist/tools/fs/fs-shared.d.ts +1 -10
  413. package/dist/tools/fs/fs-shared.js +3 -4
  414. package/dist/tools/fs/fs-write.js +2 -1
  415. package/dist/tools/fs/notebook.js +1 -1
  416. package/dist/tools/fs/pdf.d.ts +20 -10
  417. package/dist/tools/fs/pdf.js +19 -10
  418. package/dist/tools/fs/program-read-model.d.ts +68 -8
  419. package/dist/tools/fs/program-read-model.js +112 -33
  420. package/dist/tools/fs/program-read-model.rows.js +30 -10
  421. package/dist/tools/fs/read-deny-home.d.ts +25 -9
  422. package/dist/tools/fs/read-deny-home.js +28 -27
  423. package/dist/tools/fs/read-deny.d.ts +41 -11
  424. package/dist/tools/fs/read-deny.js +51 -5
  425. package/dist/tools/fs/safety.d.ts +4 -26
  426. package/dist/tools/fs/safety.js +10 -32
  427. package/dist/tools/fs/search.js +15 -10
  428. package/dist/tools/fs/shell-read-argv.d.ts +3 -2
  429. package/dist/tools/fs/shell-read-argv.js +118 -38
  430. package/dist/tools/fs/shell-read-establish.d.ts +5 -5
  431. package/dist/tools/fs/shell-read-establish.js +11 -61
  432. package/dist/tools/fs/shell-read-identity.js +6 -3
  433. package/dist/tools/fs/shell-read-judge.d.ts +13 -15
  434. package/dist/tools/fs/shell-read-judge.js +18 -4
  435. package/dist/tools/fs/shell-read-plan.d.ts +2 -2
  436. package/dist/tools/web.js +1 -1
  437. package/package.json +13 -1
  438. package/test/export-surface.snapshot.json +306 -103
  439. package/wire-changes/core@7.52.0.json +5859 -0
  440. package/wire-changes/core@7.53.0.json +1946 -0
  441. package/dist/core/hook-seats.d.ts +0 -66
  442. package/dist/core/hook-seats.js +0 -37
  443. package/dist/prompt-assembly/packs/sema-default.d.ts +0 -2
  444. package/dist/prompt-assembly/packs/sema-default.js +0 -147
  445. package/dist/prompts/simple-sections.d.ts +0 -58
  446. package/dist/prompts/simple-sections.js +0 -43
@@ -1,4 +1,23 @@
1
1
  import { SAFETY_AXIS_VOCABULARY } from "./safety-axis-vocab.js";
2
+ import { INLINE_TRUNCATION_MARK, inlineUntrusted } from "./untrusted-text.js";
3
+ import { DECLARATION_RECEIPT_MODE } from "./own-property-receipt.js";
4
+ import { isPlainRecord, receive } from "./mods/kernel/receive.js";
5
+ import { MODS_VALUE_DEPTH } from "./mods/kernel/site-rules.js";
6
+ const TOOL_AXES_SURFACES = {
7
+ mcp: { key: "tool", declarer: "MCP server" },
8
+ a2a: { key: "skill", declarer: "A2A peer" },
9
+ };
10
+ function invalidArgument(message) {
11
+ const refusal = new Error(message);
12
+ refusal.code = "config.invalid_argument";
13
+ return refusal;
14
+ }
15
+ function toolAxesSurfaceOf(at) {
16
+ if (typeof at === "string" && Object.hasOwn(TOOL_AXES_SURFACES, at))
17
+ return TOOL_AXES_SURFACES[at];
18
+ throw invalidArgument(`toolAxes is read for a surface, and the surfaces are ${Object.keys(TOOL_AXES_SURFACES).map((s) => JSON.stringify(s)).join(" | ")} ` +
19
+ `(an MCP server's tools, an A2A peer's skills); the surface named is not one of them.`);
20
+ }
2
21
  const TOOL_AXIS_MEMBERS = { effect: true, egress: true, irreversibility: true };
3
22
  const TOOL_AXIS_MEMBER_NAMES = Object.keys(TOOL_AXIS_MEMBERS);
4
23
  const TOOL_EFFECT_WORDS = SAFETY_AXIS_VOCABULARY.toolEffect;
@@ -6,25 +25,135 @@ const ENGINE_DERIVED_IRREVERSIBILITY = "maybe";
6
25
  const IRREVERSIBILITY_POLE_WORDS = SAFETY_AXIS_VOCABULARY.irreversibility.filter((word) => word !== ENGINE_DERIVED_IRREVERSIBILITY);
7
26
  const irreversibilityPolesLockstep = true;
8
27
  void irreversibilityPolesLockstep;
28
+ const toolAxesDeclarationsAreOne = true;
29
+ void toolAxesDeclarationsAreOne;
9
30
  function quotedName(name) {
10
31
  return JSON.stringify(name.length > 80 ? `${name.slice(0, 80)}…` : name);
11
32
  }
12
- function describeKind(value) {
13
- return value === null ? "null" : Array.isArray(value) ? "an array" : typeof value === "object" ? "an object that is not a plain data record (a map, a class instance, or members that are inherited or not enumerable)" : `a ${typeof value}`;
33
+ function memberNames(path) {
34
+ let rendered = "";
35
+ for (const [index, name] of path.entries()) {
36
+ if (rendered.length > 120)
37
+ return `${rendered}${INLINE_TRUNCATION_MARK}`;
38
+ rendered += `${index === 0 ? "" : "."}${quotedName(String(name))}`;
39
+ }
40
+ return rendered;
14
41
  }
15
- const ROOT_PROTOTYPE_NAMES = Object.getOwnPropertyNames(Object.prototype).sort().join("\n");
16
- function isRootPrototype(proto) {
17
- if (proto === Object.prototype)
18
- return true;
19
- return Object.getPrototypeOf(proto) === null && Object.getOwnPropertyNames(proto).sort().join("\n") === ROOT_PROTOTYPE_NAMES;
42
+ function dataKind(value) {
43
+ return value === null ? "null" : value === undefined ? "undefined" : Array.isArray(value) ? "an array" : typeof value === "object" ? "a record" : `a ${typeof value}`;
20
44
  }
21
- function isPlainRecord(value) {
22
- if (typeof value !== "object" || value === null)
23
- return false;
24
- const proto = Object.getPrototypeOf(value);
25
- if (proto !== null && !isRootPrototype(proto))
26
- return false;
27
- return Object.getOwnPropertyNames(value).length === Object.keys(value).length;
45
+ const RECEIPT_FAULT_PROBLEMS = {
46
+ proxy: "it is a Proxy, whose traps would run as it is read; copy it into plain data (a spread or a JSON round trip)",
47
+ "not-data": "it is not plain data (a function, a bigint, a symbol, or an object whose prototype is neither Object.prototype nor null: a class instance, " +
48
+ "a map, `process.env`, a record built on a prototype or in another realm — a `vm` context, a worker); copy it into plain data (a spread " +
49
+ "or a JSON round trip), writing out any member it inherits",
50
+ "getter-threw": "its getter threw while it was read",
51
+ "prototype-moved": "its prototype changed while it was read",
52
+ cycle: "it contains itself; declare it as plain data",
53
+ "too-deep": `it is nested past ${MODS_VALUE_DEPTH} levels`,
54
+ uncopyable: "it could not be copied whole",
55
+ accessor: "it is an accessor",
56
+ hidden: "it is a member that is not an enumerable data property",
57
+ };
58
+ export function declarationFaultOf(fault) {
59
+ return { path: fault.path.map((key) => (/^(?:0|[1-9]\d*)$/.test(key) ? Number(key) : key)), problem: RECEIPT_FAULT_PROBLEMS[fault.kind] };
60
+ }
61
+ export const DECLARATION_PATH_RULES = Object.freeze({
62
+ mcp: Object.freeze([
63
+ { path: ["name"], holds: "a string", required: true },
64
+ { path: ["transport", "env"], holds: "names to strings" },
65
+ { path: ["transport", "headers"], holds: "names to strings" },
66
+ ]),
67
+ a2a: Object.freeze([
68
+ { path: ["name"], holds: "a string", required: true },
69
+ { path: ["headers"], holds: "names to strings" },
70
+ ]),
71
+ });
72
+ const PROTO_MEMBER = `it is a member named "__proto__", which a copy by assignment would turn into a prototype — not a name a declaration can carry`;
73
+ function declarationVocabularyFault(root, rules) {
74
+ const asked = new Set();
75
+ const path = [];
76
+ const stack = [];
77
+ const ruleAt = () => rules.find((rule) => rule.path.length === path.length && rule.path.every((key, i) => key === path[i]));
78
+ const onRuleRoute = () => rules.some((rule) => rule.path.length > path.length && path.every((key, i) => key === rule.path[i]));
79
+ const ruleProblem = (rule, value) => {
80
+ if (rule.holds === "a string")
81
+ return typeof value === "string" ? undefined : `it is ${dataKind(value)}, not a string`;
82
+ if (!isPlainRecord(value))
83
+ return `it is ${dataKind(value)}, not a record of names to strings`;
84
+ for (const [key, member] of Object.entries(value)) {
85
+ path.push(key);
86
+ if (key === "__proto__")
87
+ return PROTO_MEMBER;
88
+ if (member !== undefined && typeof member !== "string")
89
+ return `it is ${dataKind(member)}, not a string: this record maps names to strings`;
90
+ path.pop();
91
+ }
92
+ return undefined;
93
+ };
94
+ const meet = (value) => {
95
+ if (typeof value !== "object" || value === null || (asked.has(value) && !onRuleRoute()))
96
+ return undefined;
97
+ asked.add(value);
98
+ if (Array.isArray(value)) {
99
+ for (let index = 0; index < value.length; index++) {
100
+ const own = Object.hasOwn(value, index);
101
+ if (own && typeof value[index] === "string")
102
+ continue;
103
+ path.push(index);
104
+ return `it is ${own ? dataKind(value[index]) : "a hole"}, not a string: every list a declaration carries is a list of names`;
105
+ }
106
+ const named = Object.keys(value).find((key) => !(/^(?:0|[1-9]\d*)$/.test(key) && Number(key) < value.length));
107
+ if (named === undefined)
108
+ return undefined;
109
+ path.push(named);
110
+ return "it is a list member that is not an index: a list declares its names at its indices only";
111
+ }
112
+ stack.push({ members: Object.entries(value), next: 0 });
113
+ return undefined;
114
+ };
115
+ for (const rule of rules) {
116
+ if (rule.required !== true)
117
+ continue;
118
+ let at = root;
119
+ for (const key of rule.path)
120
+ at = isPlainRecord(at) && Object.hasOwn(at, key) ? at[key] : undefined;
121
+ if (at === undefined)
122
+ return { path: [...rule.path], problem: `it is missing: a declaration carries ${rule.holds} here` };
123
+ }
124
+ let problem = meet(root);
125
+ while (problem === undefined && stack.length > 0) {
126
+ const frame = stack[stack.length - 1];
127
+ if (frame.next === frame.members.length) {
128
+ stack.pop();
129
+ if (stack.length > 0)
130
+ path.pop();
131
+ continue;
132
+ }
133
+ const [key, member] = frame.members[frame.next++];
134
+ path.push(key);
135
+ const rule = key === "__proto__" || member === undefined ? undefined : ruleAt();
136
+ if (key === "__proto__")
137
+ problem = PROTO_MEMBER;
138
+ else if (rule !== undefined)
139
+ problem = ruleProblem(rule, member);
140
+ else {
141
+ const depth = stack.length;
142
+ problem = meet(member);
143
+ if (problem === undefined && stack.length > depth)
144
+ continue;
145
+ }
146
+ if (problem === undefined)
147
+ path.pop();
148
+ }
149
+ return problem === undefined ? undefined : { path, problem };
150
+ }
151
+ export function receiveDeclaration(declared, rules = []) {
152
+ const received = receive(declared, DECLARATION_RECEIPT_MODE);
153
+ if (!received.ok)
154
+ return { ok: false, fault: declarationFaultOf(received.fault) };
155
+ const fault = isPlainRecord(received.value) ? declarationVocabularyFault(received.value, rules) : undefined;
156
+ return fault === undefined ? { ok: true, value: received.value } : { ok: false, fault };
28
157
  }
29
158
  function isToolEffectWord(value) {
30
159
  return typeof value === "string" && TOOL_EFFECT_WORDS.includes(value);
@@ -34,12 +163,19 @@ function isIrreversibilityPoleWord(value) {
34
163
  }
35
164
  function readToolAxisEntry(raw) {
36
165
  if (!isPlainRecord(raw))
37
- return `the declaration is ${describeKind(raw)}, not an object of axes`;
38
- for (const member of Object.keys(raw)) {
39
- if (!TOOL_AXIS_MEMBER_NAMES.includes(member))
40
- return `unknown member ${quotedName(member)} (the members are ${TOOL_AXIS_MEMBER_NAMES.join(", ")})`;
166
+ return `the declaration is ${dataKind(raw)}, not an object of axes`;
167
+ const listed = Object.keys(raw);
168
+ const unknown = listed.find((member) => !TOOL_AXIS_MEMBER_NAMES.includes(member));
169
+ if (unknown !== undefined)
170
+ return `unknown member ${quotedName(unknown)} (the members are ${TOOL_AXIS_MEMBER_NAMES.join(", ")})`;
171
+ const declared = Object.create(null);
172
+ for (const member of TOOL_AXIS_MEMBER_NAMES) {
173
+ const value = raw[member];
174
+ if (value !== undefined && !listed.includes(member))
175
+ return `member ${quotedName(member)} is a hidden member: its name answers a value the declaration does not list as its own`;
176
+ declared[member] = value;
41
177
  }
42
- const { effect, egress, irreversibility } = raw;
178
+ const { effect, egress, irreversibility } = declared;
43
179
  if (effect !== undefined && !isToolEffectWord(effect))
44
180
  return `member "effect" is not one of ${TOOL_EFFECT_WORDS.join(" | ")}`;
45
181
  if (egress !== undefined && typeof egress !== "boolean")
@@ -52,22 +188,25 @@ function readToolAxisEntry(raw) {
52
188
  ...(irreversibility !== undefined ? { irreversibility } : {}),
53
189
  };
54
190
  }
55
- export function readMcpToolAxes(declared) {
191
+ export function readToolAxes(declared, at) {
192
+ const unit = toolAxesSurfaceOf(at).key;
56
193
  if (declared === undefined)
57
194
  return { ok: true };
58
- let perTool;
59
- try {
60
- if (!isPlainRecord(declared))
61
- return { ok: false, problem: `toolAxes is ${describeKind(declared)}, not an object of per-tool axis declarations` };
62
- perTool = Object.entries(declared);
63
- }
64
- catch {
65
- return { ok: false, problem: "toolAxes could not be read: a property threw while it was read" };
195
+ const received = receiveDeclaration(declared);
196
+ if (!received.ok) {
197
+ const [key, ...member] = received.fault.path;
198
+ if (key === undefined)
199
+ return { ok: false, problem: `toolAxes cannot be read: ${received.fault.problem}` };
200
+ const where = member.length > 0 ? `member ${memberNames(member)}: ` : "";
201
+ return { ok: false, problem: `the axes declared for ${unit} ${quotedName(String(key))} do not fit: ${where}${received.fault.problem}` };
66
202
  }
203
+ const perTool = received.value;
204
+ if (!isPlainRecord(perTool))
205
+ return { ok: false, problem: `toolAxes is ${dataKind(perTool)}, not an object of per-${unit} axis declarations` };
67
206
  const entries = [];
68
- for (const [tool, raw] of perTool) {
69
- if (tool.length === 0)
70
- return { ok: false, problem: "toolAxes has an empty tool name" };
207
+ for (const [key, raw] of Object.entries(perTool)) {
208
+ if (key.length === 0)
209
+ return { ok: false, problem: `toolAxes has an empty ${unit} name` };
71
210
  let entry;
72
211
  try {
73
212
  entry = readToolAxisEntry(raw);
@@ -76,9 +215,20 @@ export function readMcpToolAxes(declared) {
76
215
  entry = "a member threw while it was read";
77
216
  }
78
217
  if (typeof entry === "string")
79
- return { ok: false, problem: `the axes declared for tool ${quotedName(tool)} do not fit: ${entry}` };
218
+ return { ok: false, problem: `the axes declared for ${unit} ${quotedName(key)} do not fit: ${entry}` };
80
219
  if (Object.keys(entry).length > 0)
81
- entries.push([tool, entry]);
220
+ entries.push([key, entry]);
82
221
  }
83
222
  return entries.length > 0 ? { ok: true, toolAxes: Object.fromEntries(entries) } : { ok: true };
84
223
  }
224
+ export function readMcpToolAxes(declared) {
225
+ return readToolAxes(declared, "mcp");
226
+ }
227
+ export function declarerWord(at) {
228
+ return toolAxesSurfaceOf(at).declarer;
229
+ }
230
+ export function toolAxesRefusal(at, name, problem) {
231
+ return invalidArgument(`${toolAxesSurfaceOf(at).declarer} ${name} declares toolAxes the engine cannot read: ${inlineUntrusted(problem, 240)}. A per-tool safety-axis declaration is the ` +
232
+ `caller's trust root for the approval gate, so it is refused rather than partly applied — dropping one key or defaulting one word ` +
233
+ `would leave a declaration that reads as in force while it is not.`);
234
+ }
@@ -1,4 +1,4 @@
1
- import { type McpInstructionsEntry, type PromptSectionSeat } from "./prompt-section-seat.js";
1
+ import { type McpInstructionsEntry, type PromptSectionDisposer } from "./prompt-section-seat.js";
2
2
  import { McpConnectionPool } from "./mcp-connection-pool.js";
3
3
  import { type McpDelivered, type McpFailureKind, type McpServerLiveness } from "./mcp-failure.js";
4
4
  import type { AgentTool } from "../internal/harness-types.js";
@@ -101,7 +101,7 @@ export interface MaterializedMcp {
101
101
  toolAxes: McpToolAxis[];
102
102
  /**
103
103
  * MCP server `instructions` (design/64 §17.3, CC `# MCP Server Instructions`): the optional guidance a
104
- * connected server returns from `initialize`, after the host's disposition (`PromptProvider.section`,
104
+ * connected server returns from `initialize`, after the host's disposition (the `prompt.section` station,
105
105
  * applied once at the dial: a dropped entry is absent, a replaced one carries `author: "host"`). The
106
106
  * Runner injects these into the (stable) system prompt. One entry per server whose entry survived.
107
107
  */
@@ -110,14 +110,15 @@ export interface MaterializedMcp {
110
110
  * G1 通告层续批 (CC `mcp_instructions_delta` parity) — the run-scoped instruction-delta ref the run
111
111
  * loop drains at turn boundaries (`spec.attachments.mcpInstructions` opt-in; `newTools` consumption
112
112
  * discipline: drained only when the announcement survived the byte cap intact).
113
- * - `pendingRemovals`: an INSTRUCTION-BEARING server whose transport closed mid-task (the CC
114
- * "servers have disconnected — their instructions above no longer apply" copy is instruction-scoped,
115
- * so instruction-less servers are not tracked). `dispose()` disarms first: task teardown is not a
116
- * disconnect.
117
- * - `pendingAdds`: the CC add lane ("# MCP Server Instructions" reminder). Structurally present for a
118
- * dynamic mid-task connect face; TODAY nothing populates it — sema connects all servers at prepare
119
- * and carries their initial instructions in the stable system prompt (design/64 §17.3, deliberate
120
- * CC deviation: prefix-cache-correct).
113
+ * - `pendingRemovals`: a server whose instructions are in the model's context and whose transport closed
114
+ * mid-task, or whose re-dial failed (the CC "servers have disconnected — their instructions above no
115
+ * longer apply" copy names only what the model holds — the lane's ledger, `instructionsTold`).
116
+ * `dispose()` disarms first: task teardown is not a disconnect.
117
+ * - `pendingAdds`: the CC add lane ("# MCP Server Instructions" reminder). A server's INITIAL
118
+ * instructions ride the stable system prompt instead (design/64 §17.3, deliberate CC deviation:
119
+ * prefix-cache-correct); this lane carries what comes later — a re-dial queues its new
120
+ * connection's text here, and a run adds the text of a server it is to teach and has not told.
121
+ * A materialization alone takes every entry of `serverInstructions` as taught; a run states its block.
121
122
  */
122
123
  instructionsDelta: {
123
124
  pendingAdds: McpInstructionsEntry[];
@@ -163,7 +164,7 @@ export interface MaterializedMcp {
163
164
  droppedTools: McpDroppedTool[];
164
165
  /**
165
166
  * design/99 §E9 — per-server status, a PURE PROJECTION of THIS materialization (no new connection logic).
166
- * One entry per declared server. **Semantics = the moment of this task leg's materialize** — core never
167
+ * One entry per declared server DIALED (none for one `dialable` kept from the dial). **Semantics = the moment of this task leg's materialize** — core never
167
168
  * persists MCP connections, so it is "did this leg connect", NOT a live session-health signal between tasks.
168
169
  * A consumer (service) surfacing it as session status must understand that. `toolNames` are the namespaced
169
170
  * (`<server>__<tool>`) names exposed.
@@ -178,7 +179,7 @@ export interface MaterializedMcp {
178
179
  /**
179
180
  * RefreshMcpTools (CC 2.1.218 parity, anchored to the CLI form) — re-read the tool list of one server (or
180
181
  * every CONNECTED server when `server` is omitted) over the EXISTING connection. NEVER dials or
181
- * re-dials: a dead/never-connected server reports `not_connected`; a live listTools failure
182
+ * re-dials: a dead/never-connected server reports `not_connected` (so does one whose connection closed while the walk was reading); a live listTools failure
182
183
  * reports `failed` (the connection is left as-is). A refreshed entry carries the NEW intake
183
184
  * result (tools/axes/dropped — the same schema-gate/namespacing/axis pipeline as connect) plus
184
185
  * the added/removed namespaced tool names relative to the previous listing; the caller (the
@@ -229,6 +230,7 @@ export interface McpRefreshResult {
229
230
  * contact it (no tools/list round trip; the engine must not hand a severed server a request
230
231
  * channel or splice its post-revocation text into the model catalog). */
231
232
  status: "refreshed" | "not_connected" | "failed" | "revoked";
233
+ /** The same reading as {@link McpReconnectResult.toolCount}: the server's tools the producer holds after the call. */
232
234
  toolCount: number;
233
235
  added: string[];
234
236
  /**
@@ -243,6 +245,9 @@ export interface McpRefreshResult {
243
245
  tools?: AgentTool[];
244
246
  axes?: McpToolAxis[];
245
247
  dropped?: McpDroppedTool[];
248
+ /** On a `"refreshed"` entry whose connection carries instructions: that connection's entry as its dial disposed of it (`author: "host"` when replaced) —
249
+ * a refresh re-reads tools, never instructions; a run whose roster change first leaves something of the server teaches it. */
250
+ instructions?: McpInstructionsEntry;
246
251
  /**
247
252
  * Set on `not_connected` / `failed` / `revoked`; ALSO set on a `"refreshed"` entry whose listing walk
248
253
  * did not finish (see {@link listingIncomplete}) — a refresh that produced usable tools is not a
@@ -287,12 +292,14 @@ export interface McpReconnectResult {
287
292
  /** Why, on every non-`reconnected` outcome (neutralized + bounded when it embeds remote text).
288
293
  * Never the only machine-readable fact: see {@link status}. */
289
294
  reason?: string;
295
+ /** How many of the server's tools the producer holds after the call — its roster: the run's (the valve and the deployment's
296
+ * overlay applied) for the run handle's `reconnectMcpServer`, this materialization's own handles for `MaterializedMcp.reconnect`
297
+ * (no run). A name no server is declared under holds nothing. Equal to `tools.length` whenever `tools` is present. */
290
298
  toolCount: number;
291
- /** Namespaced names this re-dial added / took away relative to what the server had mounted a moment
292
- * ago — a first successful dial adds its whole roster, a failed dial removes it. */
299
+ /** The namespaced names that came onto / left that roster (a first dial adds its whole roster, a failed dial removes it). */
293
300
  added: string[];
294
301
  removed: string[];
295
- /** See the type docstring: present iff this result asserts a roster for `prefix`. */
302
+ /** See the type docstring: present iff this result asserts a roster for `prefix` — and then it is that roster's tools of the server. */
296
303
  tools?: AgentTool[];
297
304
  axes?: McpToolAxis[];
298
305
  dropped?: McpDroppedTool[];
@@ -443,11 +450,15 @@ export declare const MCP_IDLE_TIMEOUT_HTTP_DEFAULT_MS: number;
443
450
  * `MCP_IDLE_TIMEOUT_HTTP`, else the CC-matched default). Exported for tests. */
444
451
  export declare function mcpIdleTimeoutMs(kind: "stdio" | "http"): number;
445
452
  /**
446
- * Startup-phase (connect + initial listTools) timeout override in ms (env `MCP_TIMEOUT`); undefined keeps
447
- * the SDK default. Startup deliberately stays bounded: a hung server at materialize time should fail open
448
- * into a skipped-server warning quickly, not stall task preparation indefinitely.
453
+ * Startup-phase (connect + initial listTools) timeout override in ms; undefined keeps the SDK default. Startup
454
+ * deliberately stays bounded: a hung server at materialize time should fail open into a skipped-server warning
455
+ * quickly, not stall task preparation indefinitely. THE one reader of the knob: with a `server`, that
456
+ * declaration's own `startupTimeoutMs` wins over env `MCP_TIMEOUT` (typed data held to the env knob's range
457
+ * [{@link MCP_ENV_MS_MIN}, {@link MCP_ENV_MS_MAX}], but REFUSED outside it — `config.mcp_startup_timeout_invalid`
458
+ * — where a process string is clamped and announced); without one, the process-level bound alone. The env value
459
+ * is resolved either way, so a bad one is announced even when a declaration shadows it.
449
460
  */
450
- export declare function mcpStartupTimeoutMs(): number | undefined;
461
+ export declare function mcpStartupTimeoutMs(server?: Pick<McpServerSpec, "name" | "startupTimeoutMs">): number | undefined;
451
462
  /** The protocol-range condition name for a JSON-RPC error code, or `undefined` for every other code
452
463
  * (see {@link MCP_SPEC_ERROR_CODE_NAMES}). */
453
464
  export declare function describeMcpSpecErrorCode(code: unknown): string | undefined;
@@ -605,7 +616,7 @@ reminderDisclosure?: {
605
616
  }, poolOpts?: {
606
617
  pool: McpConnectionPool;
607
618
  ownsPool?: boolean;
608
- }, promptSections?: PromptSectionSeat): Promise<MaterializedMcp>;
619
+ }, promptSections?: PromptSectionDisposer, dialable?: (spec: McpServerSpec) => boolean): Promise<MaterializedMcp>;
609
620
  /**
610
621
  * Fold the caller's AUTHORITATIVE per-tool override (design F: caller = trust root) over the server-hint axis.
611
622
  * Unlike server hints, the caller may RAISE or LOWER any axis: `effect` sets the repeat-safety class (lower to
package/dist/core/mcp.js CHANGED
@@ -7,7 +7,7 @@ import { disposeSectionEntry, sectionAnswerWarning } from "./prompt-section-seat
7
7
  import { findNamespacePrefixCollision, mintNamespacePrefix, mintNamespacedToolName, normalizeNameSegment } from "./protocol-naming.js";
8
8
  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
9
9
  import { McpConnectionPool } from "./mcp-connection-pool.js";
10
- import { MCP_RESOURCE_LIST_ALLOW, MCP_RESOURCE_READ_ALLOW } from "./mounted-mcp.js";
10
+ import { LIST_MCP_RESOURCES, MCP_RESOURCE_LIST_ALLOW, MCP_RESOURCE_READ_ALLOW, READ_MCP_RESOURCE, READ_MCP_RESOURCE_DIR, retractInstructions, tellInstructions, toldOnDial, unretractInstructions, withdrawInstructionAdds } from "./mounted-mcp.js";
11
11
  import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
12
12
  import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
13
13
  import { classifyMcpFailure, describeHttpTransportFailure, livenessOf } from "./mcp-failure.js";
@@ -154,8 +154,14 @@ function armMcpIdleWatchdog(health, idleMs, outerSignal) {
154
154
  },
155
155
  };
156
156
  }
157
- export function mcpStartupTimeoutMs() {
158
- return parseEnvMs("MCP_TIMEOUT");
157
+ export function mcpStartupTimeoutMs(server) {
158
+ const fromEnv = parseEnvMs("MCP_TIMEOUT");
159
+ const own = server?.startupTimeoutMs;
160
+ if (server === undefined || own === undefined)
161
+ return fromEnv;
162
+ if (typeof own === "number" && Number.isSafeInteger(own) && own >= MCP_ENV_MS_MIN && own <= MCP_ENV_MS_MAX)
163
+ return own;
164
+ throw Object.assign(new Error(`MCP server "${inlineUntrusted(server.name, 160)}": startupTimeoutMs must be a whole number of milliseconds from ${MCP_ENV_MS_MIN} to ${MCP_ENV_MS_MAX} (got ${typeof own === "number" ? String(own) : own === null ? "null" : typeof own}) — not dialed`), { code: "config.mcp_startup_timeout_invalid" });
159
165
  }
160
166
  function markMcpFailure(e, details) {
161
167
  e.details = details;
@@ -656,11 +662,11 @@ export function mcpToolSchemaProblem(schema) {
656
662
  }
657
663
  return undefined;
658
664
  }
659
- export async function materializeMcpTools(specs, principal, onElicit, imageResizer, reminderDisclosure, mcpRevocations, poolOpts, promptSections) {
665
+ export async function materializeMcpTools(specs, principal, onElicit, imageResizer, reminderDisclosure, mcpRevocations, poolOpts, promptSections, dialable) {
660
666
  const snapshot = snapshotMcpEntries(specs);
661
667
  const axesRefused = new WeakMap();
662
668
  const entries = snapshot.map((spec) => {
663
- const judged = judgeEntryToolAxes(spec);
669
+ const judged = judgeEntryToolAxes(spec, "mcp");
664
670
  if (judged.ok)
665
671
  return judged.entry;
666
672
  axesRefused.set(spec, judged.error);
@@ -725,7 +731,6 @@ export async function materializeMcpTools(specs, principal, onElicit, imageResiz
725
731
  serverHandles.push(handle);
726
732
  else
727
733
  serverHandles[hIdx] = handle;
728
- const hasInstructions = s.instructions !== undefined;
729
734
  const observe = (outcome) => {
730
735
  if (disposing)
731
736
  return;
@@ -739,8 +744,7 @@ export async function materializeMcpTools(specs, principal, onElicit, imageResiz
739
744
  return;
740
745
  s.status.transportClosed = true;
741
746
  observe("connection_closed");
742
- if (hasInstructions)
743
- instructionsDelta.pendingRemovals.push(spec.name);
747
+ retractInstructions(instructionsDelta, spec.name);
744
748
  };
745
749
  s.announce.fn = announceClose;
746
750
  if (s.health.dead)
@@ -786,41 +790,32 @@ export async function materializeMcpTools(specs, principal, onElicit, imageResiz
786
790
  return refusal !== undefined ? Promise.reject(refusal) : connectServer(spec, principal, onElicit, imageResizer, mcpDisclosure, isServerRevoked, dialKind, poolOpts?.pool, dialOpts);
787
791
  };
788
792
  const prefixOf = (name) => mintNamespacePrefix(MCP_NAMESPACE, name);
789
- const reconcileInstructions = (name, before, after, connected) => {
790
- let owedRemoval = false;
791
- for (let i = instructionsDelta.pendingRemovals.length - 1; i >= 0; i--) {
792
- if (instructionsDelta.pendingRemovals[i] !== name)
793
- continue;
794
- instructionsDelta.pendingRemovals.splice(i, 1);
795
- owedRemoval = true;
796
- }
797
- let hadPendingAdd = false;
798
- for (let i = instructionsDelta.pendingAdds.length - 1; i >= 0; i--) {
799
- if (instructionsDelta.pendingAdds[i].server !== name)
800
- continue;
801
- instructionsDelta.pendingAdds.splice(i, 1);
802
- hadPendingAdd = true;
803
- }
804
- if (after !== undefined) {
805
- instructionsDelta.pendingAdds.push(after);
806
- return;
807
- }
808
- if (connected)
809
- return;
810
- if (before !== undefined || owedRemoval || hadPendingAdd)
811
- instructionsDelta.pendingRemovals.push(name);
793
+ const heldCount = (name) => serverHandles.find((h) => h.name === name)?.tools.length ?? 0;
794
+ const reconcileInstructions = (name, after, connected) => {
795
+ if (!connected)
796
+ return retractInstructions(instructionsDelta, name);
797
+ unretractInstructions(instructionsDelta, name);
798
+ if (after !== undefined)
799
+ tellInstructions(instructionsDelta, after);
800
+ else
801
+ withdrawInstructionAdds(instructionsDelta, name);
812
802
  };
813
- const settled = await Promise.allSettled(entries.map((spec, i) => dialServer(spec, dialKinds[i], { sections: promptSections })));
803
+ const dialed = entries.map((spec) => dialDecision(dialable, spec));
804
+ const settled = await Promise.allSettled(entries.map((spec, i) => (dialed[i] ? dialServer(spec, dialKinds[i], { sections: promptSections }) : Promise.resolve(null))));
814
805
  try {
815
806
  for (let i = 0; i < entries.length; i++) {
816
807
  const r = settled[i];
817
808
  const spec = entries[i];
818
809
  if (r.status === "fulfilled") {
819
810
  const s = r.value;
811
+ if (s === null)
812
+ continue;
820
813
  tools.push(...s.tools);
821
814
  toolAxes.push(...s.axes);
822
- if (s.instructions)
815
+ if (s.instructions) {
823
816
  serverInstructions.push(s.instructions);
817
+ toldOnDial(instructionsDelta, spec.name);
818
+ }
824
819
  commitConnectedServer(spec, s, dialKinds[i]);
825
820
  }
826
821
  else {
@@ -835,12 +830,12 @@ export async function materializeMcpTools(specs, principal, onElicit, imageResiz
835
830
  toolAxes.push(...resourceTools.axes);
836
831
  }
837
832
  catch (mergeErr) {
838
- await Promise.allSettled(settled.map((r) => (r.status === "fulfilled" ? r.value.close() : Promise.resolve())));
833
+ await Promise.allSettled(settled.map((r) => (r.status === "fulfilled" && r.value !== null ? r.value.close() : Promise.resolve())));
839
834
  throw mergeErr;
840
835
  }
841
836
  const redialOnce = async (server) => {
842
837
  const prefix = prefixOf(server);
843
- const declined = (outcome, reason) => ({ server, prefix, outcome, reason, toolCount: 0, added: [], removed: [] });
838
+ const declined = (outcome, reason) => ({ server, prefix, outcome, reason, toolCount: heldCount(server), added: [], removed: [] });
844
839
  if (disposing)
845
840
  return declined("refused", "this materialization is being disposed — the task is tearing down");
846
841
  const spec = entries.find((e) => e.name === server);
@@ -855,7 +850,6 @@ export async function materializeMcpTools(specs, principal, onElicit, imageResiz
855
850
  const hIdx = serverHandles.findIndex((h) => h.name === server);
856
851
  const prior = hIdx === -1 ? undefined : serverHandles[hIdx];
857
852
  const priorNames = prior ? prior.tools.map((t) => t.name) : [];
858
- const priorInstructions = prior?.instructions;
859
853
  if (prior) {
860
854
  prior.announce.fn = undefined;
861
855
  prior.health.observe = undefined;
@@ -880,7 +874,7 @@ export async function materializeMcpTools(specs, principal, onElicit, imageResiz
880
874
  statuses[sIdx] = status;
881
875
  const raised = asServerWarning(spec, err);
882
876
  warnings.push(raised);
883
- reconcileInstructions(server, priorInstructions, undefined, false);
877
+ reconcileInstructions(server, undefined, false);
884
878
  return {
885
879
  server,
886
880
  prefix,
@@ -901,7 +895,7 @@ export async function materializeMcpTools(specs, principal, onElicit, imageResiz
901
895
  return declined("refused", "this materialization was disposed while the re-dial was in flight — the new connection was closed");
902
896
  }
903
897
  const raised = commitConnectedServer(spec, connected, dialKind);
904
- reconcileInstructions(server, priorInstructions, connected.instructions, true);
898
+ reconcileInstructions(server, connected.instructions, true);
905
899
  const newNames = connected.tools.map((t) => t.name);
906
900
  return {
907
901
  server,
@@ -938,11 +932,11 @@ export async function materializeMcpTools(specs, principal, onElicit, imageResiz
938
932
  }
939
933
  for (const h of targets) {
940
934
  if (disposing || h.health.dead) {
941
- results.push({ server: h.name, prefix: prefixOf(h.name), status: "not_connected", toolCount: 0, added: [], removed: [] });
935
+ results.push({ server: h.name, prefix: prefixOf(h.name), status: "not_connected", toolCount: h.tools.length, added: [], removed: [] });
942
936
  continue;
943
937
  }
944
938
  if (isServerRevoked(h.name)) {
945
- results.push({ server: h.name, prefix: prefixOf(h.name), status: "revoked", toolCount: 0, added: [], removed: [], error: "server revoked by the operator — the refresh did not contact it" });
939
+ results.push({ server: h.name, prefix: prefixOf(h.name), status: "revoked", toolCount: h.tools.length, added: [], removed: [], error: "server revoked by the operator — the refresh did not contact it" });
946
940
  continue;
947
941
  }
948
942
  try {
@@ -969,6 +963,7 @@ export async function materializeMcpTools(specs, principal, onElicit, imageResiz
969
963
  tools: serverTools,
970
964
  axes: serverAxes,
971
965
  dropped: dropped.map((d) => ({ server: inlineUntrusted(h.name, 160), ...d })),
966
+ ...(h.instructions !== undefined ? { instructions: h.instructions } : {}),
972
967
  ...(listed.incomplete !== undefined
973
968
  ? { listingIncomplete: listed.incomplete, error: `tool listing incomplete — ${listingIncompleteNote(listed.incomplete)}` }
974
969
  : {}),
@@ -991,17 +986,14 @@ export async function materializeMcpTools(specs, principal, onElicit, imageResiz
991
986
  const entry = results[i];
992
987
  if (entry.status !== "refreshed")
993
988
  continue;
994
- if (serverHandles.find((h) => h.name === entry.server)?.tools === entry.tools)
989
+ const live = serverHandles.find((h) => h.name === entry.server);
990
+ if (live !== undefined && live.tools === entry.tools && !live.health.dead)
995
991
  continue;
996
- results[i] = {
997
- server: entry.server,
998
- prefix: entry.prefix,
999
- status: "failed",
1000
- toolCount: 0,
1001
- added: [],
1002
- removed: [],
1003
- error: "this server was re-dialed while the refresh was reading another server — the listing is from the connection that re-dial replaced, so it was discarded",
1004
- };
992
+ const kept = { server: entry.server, prefix: entry.prefix, toolCount: heldCount(entry.server), added: [], removed: [] };
993
+ results[i] =
994
+ live?.tools === entry.tools
995
+ ? { ...kept, status: "not_connected" }
996
+ : { ...kept, status: "failed", error: "this server was re-dialed while the refresh was reading another server — the listing is from the connection that re-dial replaced, so it was discarded" };
1005
997
  }
1006
998
  return results;
1007
999
  },
@@ -1050,9 +1042,6 @@ export function applyCallerAxisOverride(name, hint, override) {
1050
1042
  axis.irreversibility = irrev;
1051
1043
  return axis.effect !== undefined || axis.egress !== undefined || axis.irreversibility !== undefined ? axis : undefined;
1052
1044
  }
1053
- const LIST_MCP_RESOURCES = "ListMcpResourcesTool";
1054
- const READ_MCP_RESOURCE = "ReadMcpResourceTool";
1055
- const READ_MCP_RESOURCE_DIR = "ReadMcpResourceDirTool";
1056
1045
  const MCP_SKILLS_EXTENSION = "io.modelcontextprotocol/skills";
1057
1046
  const MAX_DIR_READ_PAGES = 20;
1058
1047
  const DIR_READ_NOT_A_DIRECTORY_RE = /not a directory|isn'?t a directory|not a folder/i;
@@ -1540,7 +1529,7 @@ async function connectServer(spec, principal, onElicit, imageResizer, reminderDi
1540
1529
  const elicitOn = spec.elicitation === true && onElicit !== undefined;
1541
1530
  const health = { dead: false, pendingElicitations: 0, lastElicitationClosedAt: 0 };
1542
1531
  const announce = {};
1543
- const startupMs = mcpStartupTimeoutMs();
1532
+ const startupMs = mcpStartupTimeoutMs(spec);
1544
1533
  const startupOpts = startupMs !== undefined ? { timeout: startupMs } : undefined;
1545
1534
  const dialClient = async () => {
1546
1535
  const client = new Client({ name: `sema-core/${spec.name}`, version: "0.1.0" }, { capabilities: elicitOn ? { elicitation: { form: {} } } : {} });
@@ -1574,7 +1563,7 @@ async function connectServer(spec, principal, onElicit, imageResizer, reminderDi
1574
1563
  }
1575
1564
  return client;
1576
1565
  };
1577
- const lease = pool !== undefined && !elicitOn ? await pool.acquire(McpConnectionPool.keyOf(spec, principal, transportKind), dialClient, dialOpts) : undefined;
1566
+ const lease = pool !== undefined && !elicitOn ? await pool.acquire(McpConnectionPool.keyOf(spec, principal, transportKind, startupMs), dialClient, dialOpts) : undefined;
1578
1567
  const client = lease !== undefined ? lease.client : await dialClient();
1579
1568
  const close = () => (lease !== undefined ? lease.release() : client.close());
1580
1569
  const openListing = () => {
@@ -1603,7 +1592,7 @@ async function connectServer(spec, principal, onElicit, imageResizer, reminderDi
1603
1592
  : undefined;
1604
1593
  const rawInstructions = client.getInstructions();
1605
1594
  const sanitized = rawInstructions && rawInstructions.trim() ? sanitizeUntrustedText(rawInstructions.trim()) : undefined;
1606
- const disposed = sanitized === undefined ? undefined : disposeSectionEntry(dialOpts?.sections, { section: "core/discovery.mcp-instructions", server: spec.name, text: sanitized, mountedTools: serverTools.map((t) => t.name) });
1595
+ const disposed = sanitized === undefined ? undefined : await disposeSectionEntry(dialOpts?.sections, { section: "core/discovery.mcp-instructions", server: spec.name, text: sanitized, mountedTools: serverTools.map((t) => t.name) });
1607
1596
  const instructions = disposed?.kept === undefined ? undefined : { server: spec.name, ...disposed.kept };
1608
1597
  const info = client.getServerVersion();
1609
1598
  const status = {
@@ -1832,6 +1821,27 @@ function asServerWarning(spec, err) {
1832
1821
  warning.code = "mcp.server_unavailable";
1833
1822
  return warning;
1834
1823
  }
1824
+ function dialDecision(dialable, spec) {
1825
+ if (dialable === undefined)
1826
+ return true;
1827
+ let why;
1828
+ let cause;
1829
+ try {
1830
+ const answer = dialable(spec);
1831
+ if (typeof answer === "boolean")
1832
+ return answer;
1833
+ const thenable = typeof answer?.then === "function";
1834
+ if (thenable)
1835
+ Promise.resolve(answer).catch(() => undefined);
1836
+ const kind = typeof answer;
1837
+ why = `it answered ${thenable ? "a promise (the seat is synchronous)" : answer === null || answer === undefined ? String(answer) : `${/^[aeiou]/.test(kind) ? "an" : "a"} ${kind}`}, not a boolean`;
1838
+ }
1839
+ catch (e) {
1840
+ why = thrownText(e);
1841
+ cause = { cause: e };
1842
+ }
1843
+ throw Object.assign(new Error(`MCP materialization refused: the dialable seat could not decide whether to dial server "${inlineUntrusted(spec.name, 120)}" — ${inlineUntrusted(why, 240)}. No server was dialed.`, cause), { code: "config.mcp_dialable_failed" });
1844
+ }
1835
1845
  function sanitizedCause(err) {
1836
1846
  const copy = new Error(namedMcpFailureText(err));
1837
1847
  const name = thrownName(err);