@sema-agent/core 7.51.1 → 7.52.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 (372) hide show
  1. package/CHANGELOG.md +550 -2
  2. package/dist/agents/agent-transcript-tool.d.ts +1 -1
  3. package/dist/agents/cascade.js +4 -0
  4. package/dist/agents/cumulative-stats.d.ts +3 -0
  5. package/dist/agents/cumulative-stats.js +3 -0
  6. package/dist/agents/list-agents-tool.d.ts +1 -1
  7. package/dist/agents/read-inbox-tool.d.ts +1 -1
  8. package/dist/agents/repair-loop.js +4 -0
  9. package/dist/agents/send-message-tool.d.ts +11 -16
  10. package/dist/agents/send-message-tool.js +11 -13
  11. package/dist/agents/subagent.d.ts +5 -0
  12. package/dist/agents/subagent.js +7 -4
  13. package/dist/agents/tool-filter.d.ts +40 -13
  14. package/dist/agents/tool-filter.js +28 -14
  15. package/dist/bench/metrics.d.ts +1 -0
  16. package/dist/brain/anthropic.js +16 -12
  17. package/dist/brain/model-presets.d.ts +4 -5
  18. package/dist/brain/model-presets.js +4 -4
  19. package/dist/brain/open-responses.js +16 -12
  20. package/dist/brain/openai.js +16 -12
  21. package/dist/brain/request-params.d.ts +12 -33
  22. package/dist/brain/request-params.js +5 -2
  23. package/dist/brain/request-route.d.ts +9 -8
  24. package/dist/brain/request-route.js +1 -0
  25. package/dist/brain/route-adjudicator.d.ts +117 -47
  26. package/dist/brain/route-adjudicator.js +171 -42
  27. package/dist/brain/route-conformance.js +2 -2
  28. package/dist/brain/status-sink.d.ts +18 -0
  29. package/dist/brain/status-sink.js +7 -0
  30. package/dist/core/allow-entry.d.ts +42 -8
  31. package/dist/core/allow-entry.js +24 -17
  32. package/dist/core/auto-compaction.d.ts +23 -20
  33. package/dist/core/auto-compaction.js +37 -16
  34. package/dist/core/auto-promote.d.ts +2 -1
  35. package/dist/core/auto-promote.js +2 -2
  36. package/dist/core/caller-tool-name.d.ts +9 -0
  37. package/dist/core/caller-tool-name.js +13 -0
  38. package/dist/core/checkpoint-requirements.d.ts +7 -1
  39. package/dist/core/checkpoint-requirements.js +2 -0
  40. package/dist/core/checkpoint-store.d.ts +36 -12
  41. package/dist/core/checkpoint-store.js +1 -1
  42. package/dist/core/child-clamp-seats.d.ts +6 -0
  43. package/dist/core/child-clamp-seats.js +2 -1
  44. package/dist/core/credential-vocabulary.d.ts +33 -8
  45. package/dist/core/credential-vocabulary.js +32 -7
  46. package/dist/core/decision-receipt.d.ts +2 -2
  47. package/dist/core/delegation-frames.d.ts +9 -2
  48. package/dist/core/delegation-name.d.ts +18 -0
  49. package/dist/core/delegation-name.js +47 -0
  50. package/dist/core/engine-capabilities.d.ts +8 -1
  51. package/dist/core/engine-capabilities.js +1 -1
  52. package/dist/core/engine-notice.d.ts +36 -19
  53. package/dist/core/frontmatter-fence.d.ts +10 -0
  54. package/dist/core/frontmatter-fence.js +6 -0
  55. package/dist/core/gate-fold.js +5 -23
  56. package/dist/core/gate-lanes.js +356 -270
  57. package/dist/core/governance-codes.d.ts +9 -4
  58. package/dist/core/governance-codes.js +9 -3
  59. package/dist/core/hooks.d.ts +276 -734
  60. package/dist/core/hooks.js +97 -192
  61. package/dist/{tools/fs → core}/image-admission.d.ts +21 -3
  62. package/dist/{tools/fs → core}/image-admission.js +24 -6
  63. package/dist/core/locked-config.d.ts +26 -5
  64. package/dist/core/locked-config.js +31 -6
  65. package/dist/core/mcp-connection-pool.d.ts +4 -1
  66. package/dist/core/mcp-connection-pool.js +7 -2
  67. package/dist/core/mcp-probe.d.ts +12 -9
  68. package/dist/core/mcp-probe.js +2 -2
  69. package/dist/core/mcp-server-spec.d.ts +53 -7
  70. package/dist/core/mcp-server-spec.js +84 -1
  71. package/dist/core/mcp.d.ts +11 -7
  72. package/dist/core/mcp.js +27 -9
  73. package/dist/core/memory-engine/data-plane.js +5 -1
  74. package/dist/core/memory-engine/distiller.js +16 -2
  75. package/dist/core/memory-engine/engine.d.ts +8 -11
  76. package/dist/core/memory-engine/engine.js +9 -5
  77. package/dist/core/memory-engine/frontmatter.d.ts +6 -0
  78. package/dist/core/memory-engine/frontmatter.js +19 -16
  79. package/dist/core/memory.d.ts +2 -2
  80. package/dist/core/mode-policy.d.ts +4 -0
  81. package/dist/core/mode-policy.js +7 -5
  82. package/dist/core/model-seat.d.ts +4 -1
  83. package/dist/core/mods/dollar.d.ts +109 -0
  84. package/dist/core/mods/dollar.js +154 -0
  85. package/dist/core/mods/host.d.ts +23 -0
  86. package/dist/core/mods/host.js +21 -0
  87. package/dist/core/mods/kernel/budget.d.ts +43 -0
  88. package/dist/core/mods/kernel/budget.js +83 -0
  89. package/dist/core/mods/kernel/dispatch.d.ts +100 -0
  90. package/dist/core/mods/kernel/dispatch.js +701 -0
  91. package/dist/core/mods/kernel/events.d.ts +242 -0
  92. package/dist/core/mods/kernel/events.js +210 -0
  93. package/dist/core/mods/kernel/index.d.ts +6 -0
  94. package/dist/core/mods/kernel/index.js +5 -0
  95. package/dist/core/mods/kernel/receive.d.ts +65 -0
  96. package/dist/core/mods/kernel/receive.js +123 -0
  97. package/dist/core/mods/kernel/registration.d.ts +131 -0
  98. package/dist/core/mods/kernel/registration.js +102 -0
  99. package/dist/core/mods/kernel/site-rules.d.ts +84 -0
  100. package/dist/core/mods/kernel/site-rules.js +104 -0
  101. package/dist/core/mods/stations.d.ts +350 -0
  102. package/dist/core/mods/stations.js +444 -0
  103. package/dist/core/own-property-receipt.js +11 -23
  104. package/dist/core/parent-spec-seat.d.ts +18 -7
  105. package/dist/core/parent-spec-seat.js +6 -2
  106. package/dist/core/path-identity.js +2 -1
  107. package/dist/core/permission-rule-syntax.d.ts +15 -0
  108. package/dist/core/permission-rule-syntax.js +24 -16
  109. package/dist/core/permission-rules.d.ts +7 -1
  110. package/dist/core/permission-rules.js +26 -15
  111. package/dist/core/prompt-section-seat.d.ts +15 -27
  112. package/dist/core/prompt-section-seat.js +73 -40
  113. package/dist/core/protocol-http-auth.d.ts +3 -1
  114. package/dist/core/protocol-http-auth.js +2 -0
  115. package/dist/core/reminder-mint.d.ts +2 -2
  116. package/dist/core/remote-env.d.ts +24 -12
  117. package/dist/core/remote-env.js +1 -0
  118. package/dist/core/resume-startup-cause.d.ts +16 -1
  119. package/dist/core/resume-startup-cause.js +4 -1
  120. package/dist/core/retired-keys.d.ts +4 -0
  121. package/dist/core/retired-keys.js +3 -0
  122. package/dist/core/runner/announce-once-ledger.d.ts +31 -1
  123. package/dist/core/runner/announce-once-ledger.js +22 -0
  124. package/dist/core/runner/assemble-result.d.ts +9 -0
  125. package/dist/core/runner/assemble-result.js +3 -1
  126. package/dist/core/runner/call-hook-stations.d.ts +23 -27
  127. package/dist/core/runner/call-hook-stations.js +58 -42
  128. package/dist/core/runner/caller-stop-gate.d.ts +25 -0
  129. package/dist/core/runner/caller-stop-gate.js +7 -0
  130. package/dist/core/runner/compaction-seams.d.ts +8 -22
  131. package/dist/core/runner/compaction-seams.js +28 -53
  132. package/dist/core/runner/construction-doors.js +11 -1
  133. package/dist/core/runner/contracts.d.ts +85 -83
  134. package/dist/core/runner/credential-origin-seat.d.ts +2 -0
  135. package/dist/core/runner/credential-origin-seat.js +19 -0
  136. package/dist/core/runner/extra-body-dropped-seat.d.ts +2 -6
  137. package/dist/core/runner/gate-exit.d.ts +47 -36
  138. package/dist/core/runner/gate-exit.js +8 -2
  139. package/dist/core/runner/image.js +1 -2
  140. package/dist/core/runner/inline-image.js +1 -1
  141. package/dist/core/runner/notice-seat-input.d.ts +11 -0
  142. package/dist/core/runner/notice-seat-input.js +1 -0
  143. package/dist/core/runner/person-path-rows.js +1 -0
  144. package/dist/core/runner/prepare-acquire-reconcile.js +5 -1
  145. package/dist/core/runner/prepare-ask-lane.d.ts +5 -7
  146. package/dist/core/runner/prepare-ask-lane.js +6 -15
  147. package/dist/core/runner/prepare-caps-and-workflow.d.ts +4 -2
  148. package/dist/core/runner/prepare-caps-and-workflow.js +25 -8
  149. package/dist/core/runner/prepare-config-doors.d.ts +5 -0
  150. package/dist/core/runner/prepare-config-doors.js +9 -0
  151. package/dist/core/runner/prepare-defer-classify.js +3 -4
  152. package/dist/core/runner/prepare-gate-stations.d.ts +8 -11
  153. package/dist/core/runner/prepare-gate-stations.js +11 -10
  154. package/dist/core/runner/prepare-inherited-gate.d.ts +8 -12
  155. package/dist/core/runner/prepare-inherited-gate.js +8 -21
  156. package/dist/core/runner/prepare-memory-engine-session.js +1 -1
  157. package/dist/core/runner/prepare-park-ask.js +10 -14
  158. package/dist/core/runner/prepare-policy-chain.d.ts +18 -16
  159. package/dist/core/runner/prepare-policy-chain.js +98 -101
  160. package/dist/core/runner/prepare-project-context.js +7 -10
  161. package/dist/core/runner/prepare-prompt-assembly.d.ts +45 -40
  162. package/dist/core/runner/prepare-prompt-assembly.js +134 -101
  163. package/dist/core/runner/prepare-prompt-inputs.d.ts +18 -19
  164. package/dist/core/runner/prepare-prompt-inputs.js +5 -7
  165. package/dist/core/runner/prepare-protocol-tools.d.ts +6 -4
  166. package/dist/core/runner/prepare-protocol-tools.js +2 -2
  167. package/dist/core/runner/prepare-safety-scan.js +6 -10
  168. package/dist/core/runner/prepare-suspend-saga.d.ts +6 -0
  169. package/dist/core/runner/prepare-suspend-saga.js +7 -5
  170. package/dist/core/runner/prepare-task.js +33 -15
  171. package/dist/core/runner/prepare-turn-wiring.d.ts +13 -15
  172. package/dist/core/runner/prepare-turn-wiring.js +29 -27
  173. package/dist/core/runner/prepare-wiring-manifest.d.ts +5 -6
  174. package/dist/core/runner/prepare-wiring-manifest.js +7 -7
  175. package/dist/core/runner/resume-apply.d.ts +5 -2
  176. package/dist/core/runner/resume-apply.js +24 -42
  177. package/dist/core/runner/resume-checkpoint-screen.d.ts +1 -0
  178. package/dist/core/runner/resume-checkpoint-screen.js +9 -1
  179. package/dist/core/runner/resume-preflight.js +38 -16
  180. package/dist/core/runner/retired-runner-deps.js +3 -1
  181. package/dist/core/runner/run-brain-sinks.d.ts +3 -2
  182. package/dist/core/runner/run-brain-sinks.js +5 -1
  183. package/dist/core/runner/run-compaction-machinery.d.ts +7 -1
  184. package/dist/core/runner/run-compaction-machinery.js +7 -33
  185. package/dist/core/runner/run-harness-handlers.js +4 -2
  186. package/dist/core/runner/run-identity-wiring.d.ts +3 -1
  187. package/dist/core/runner/run-identity-wiring.js +3 -2
  188. package/dist/core/runner/run-leg.js +62 -84
  189. package/dist/core/runner/run-notification-lane.js +1 -0
  190. package/dist/core/runner/run-recovery-lanes.d.ts +3 -0
  191. package/dist/core/runner/run-recovery-lanes.js +11 -10
  192. package/dist/core/runner/run-settle-and-teardown.js +9 -28
  193. package/dist/core/runner/run-stop-and-final-verify.js +18 -25
  194. package/dist/core/runner/run-terminal-adoption.d.ts +3 -0
  195. package/dist/core/runner/run-terminal-adoption.js +33 -22
  196. package/dist/core/runner/run-tool-mount-facts.js +5 -3
  197. package/dist/core/runner/run-turn-boundary.js +23 -34
  198. package/dist/core/runner/runtask.d.ts +6 -7
  199. package/dist/core/runner/runtask.js +14 -72
  200. package/dist/core/runner/session-rule-policy.d.ts +6 -4
  201. package/dist/core/runner/session-rule-policy.js +17 -10
  202. package/dist/core/runner/side-call-account.d.ts +68 -0
  203. package/dist/core/runner/side-call-account.js +61 -0
  204. package/dist/core/runner/stream-halt-verbs.js +12 -17
  205. package/dist/core/runner/stream-lifecycle-verbs.js +8 -5
  206. package/dist/core/runner/stream-steer-verb.d.ts +1 -1
  207. package/dist/core/runner/stream-steer-verb.js +20 -38
  208. package/dist/core/runner/sub-agent-deny-lists.d.ts +121 -22
  209. package/dist/core/runner/sub-agent-deny-lists.js +228 -71
  210. package/dist/core/runner/tool-end-body.d.ts +5 -6
  211. package/dist/core/runner/tool-end-body.js +6 -4
  212. package/dist/core/runner/tool-not-executed.d.ts +15 -0
  213. package/dist/core/runner/tool-not-executed.js +30 -0
  214. package/dist/core/runner/tool-occurrence.d.ts +8 -7
  215. package/dist/core/runner/tool-occurrence.js +5 -5
  216. package/dist/core/runner/tool-result-media-seat.d.ts +1 -1
  217. package/dist/core/runner-deps.d.ts +20 -28
  218. package/dist/core/safety-merge-corpus.js +18 -2
  219. package/dist/core/secret-env.d.ts +93 -20
  220. package/dist/core/secret-env.js +192 -38
  221. package/dist/core/session-policy-store.d.ts +93 -17
  222. package/dist/core/session-policy-store.js +178 -25
  223. package/dist/core/session-reconcile.d.ts +4 -0
  224. package/dist/core/session-reconcile.js +2 -1
  225. package/dist/core/shell-read-silence.js +3 -32
  226. package/dist/core/side-query.d.ts +5 -3
  227. package/dist/core/skill-grant.d.ts +3 -2
  228. package/dist/core/skill-grant.js +17 -9
  229. package/dist/core/skills-directory.d.ts +31 -11
  230. package/dist/core/skills-directory.js +655 -104
  231. package/dist/core/task-event.d.ts +13 -3
  232. package/dist/core/task-result.d.ts +8 -0
  233. package/dist/core/task-spec.d.ts +20 -19
  234. package/dist/core/task-stream.d.ts +14 -4
  235. package/dist/core/tighten-task-spec.d.ts +4 -3
  236. package/dist/core/tighten-task-spec.js +2 -4
  237. package/dist/core/tool-check-reading.d.ts +74 -0
  238. package/dist/core/tool-check-reading.js +80 -0
  239. package/dist/core/tool-policy.d.ts +59 -18
  240. package/dist/core/tool-policy.js +77 -12
  241. package/dist/core/tool-registry.d.ts +20 -0
  242. package/dist/core/tool-registry.js +4 -0
  243. package/dist/core/tool-spec.d.ts +10 -6
  244. package/dist/core/tools.js +2 -0
  245. package/dist/core/trace.d.ts +51 -32
  246. package/dist/core/types.d.ts +2 -1
  247. package/dist/core/types.js +1 -0
  248. package/dist/core/unc-spelling.d.ts +10 -0
  249. package/dist/core/unc-spelling.js +3 -0
  250. package/dist/core/untrusted-egress.d.ts +8 -0
  251. package/dist/core/untrusted-egress.js +4 -1
  252. package/dist/core/user-attachment.d.ts +12 -2
  253. package/dist/core/user-attachment.js +17 -2
  254. package/dist/core/wiring-manifest.d.ts +14 -13
  255. package/dist/core/wiring-manifest.js +2 -2
  256. package/dist/engine/compaction/utils.js +1 -2
  257. package/dist/engine/execution-env/node-execution-env.d.ts +4 -3
  258. package/dist/engine/execution-env/symlink-chain.js +1 -1
  259. package/dist/engine/harness/agent-harness.d.ts +1 -1
  260. package/dist/engine/harness/agent-harness.js +3 -3
  261. package/dist/engine/harness/types.d.ts +17 -16
  262. package/dist/engine/harness/types.js +7 -1
  263. package/dist/engine/llm/types.d.ts +12 -7
  264. package/dist/engine/loop/agent-loop.js +1 -1
  265. package/dist/engine/loop/types.d.ts +1 -1
  266. package/dist/engine/lsp/node-lsp-manager.d.ts +2 -2
  267. package/dist/engine/session/import-validate.js +3 -10
  268. package/dist/engine/session/session.d.ts +4 -4
  269. package/dist/engine/session/session.js +4 -4
  270. package/dist/index.d.ts +24 -17
  271. package/dist/index.js +15 -12
  272. package/dist/internal/harness.d.ts +1 -1
  273. package/dist/internal/harness.js +1 -1
  274. package/dist/orchestration/run-spec.d.ts +4 -6
  275. package/dist/orchestration/run-spec.js +39 -63
  276. package/dist/orchestration/run-workflow-tool.js +1 -2
  277. package/dist/orchestration/workflow.d.ts +11 -3
  278. package/dist/orchestration/workflow.js +11 -2
  279. package/dist/prompt-assembly/artifact-store.d.ts +37 -56
  280. package/dist/prompt-assembly/artifact-store.js +31 -49
  281. package/dist/prompt-assembly/artifact.d.ts +89 -76
  282. package/dist/prompt-assembly/artifact.js +167 -146
  283. package/dist/prompt-assembly/assemble.d.ts +34 -29
  284. package/dist/prompt-assembly/assemble.js +33 -220
  285. package/dist/prompt-assembly/bands.d.ts +20 -0
  286. package/dist/prompt-assembly/bands.js +18 -0
  287. package/dist/prompt-assembly/catalog/constitution.d.ts +23 -0
  288. package/dist/prompt-assembly/catalog/constitution.js +69 -0
  289. package/dist/prompt-assembly/catalog/core-behavior.d.ts +9 -0
  290. package/dist/prompt-assembly/catalog/core-behavior.js +85 -0
  291. package/dist/prompt-assembly/catalog/index.d.ts +11 -0
  292. package/dist/prompt-assembly/catalog/index.js +59 -0
  293. package/dist/prompt-assembly/catalog/modes.d.ts +15 -0
  294. package/dist/prompt-assembly/catalog/modes.js +137 -0
  295. package/dist/prompt-assembly/catalog/role.d.ts +10 -0
  296. package/dist/prompt-assembly/catalog/role.js +157 -0
  297. package/dist/prompt-assembly/catalog/schema.d.ts +124 -0
  298. package/dist/prompt-assembly/catalog/schema.js +25 -0
  299. package/dist/prompt-assembly/catalog/sections.d.ts +9 -0
  300. package/dist/prompt-assembly/catalog/sections.js +98 -0
  301. package/dist/prompt-assembly/catalog/team.d.ts +4 -0
  302. package/dist/prompt-assembly/catalog/team.js +258 -0
  303. package/dist/prompt-assembly/composer.d.ts +24 -28
  304. package/dist/prompt-assembly/composer.js +124 -46
  305. package/dist/prompt-assembly/epoch.d.ts +89 -79
  306. package/dist/prompt-assembly/epoch.js +115 -142
  307. package/dist/prompt-assembly/explain.d.ts +58 -34
  308. package/dist/prompt-assembly/explain.js +21 -24
  309. package/dist/prompt-assembly/overlay.d.ts +127 -0
  310. package/dist/prompt-assembly/overlay.js +301 -0
  311. package/dist/prompt-assembly/renderers.d.ts +21 -0
  312. package/dist/prompt-assembly/renderers.js +39 -0
  313. package/dist/prompt-assembly/section-usage.d.ts +3 -3
  314. package/dist/prompt-assembly/section-usage.js +1 -1
  315. package/dist/prompt-assembly/select.d.ts +56 -0
  316. package/dist/prompt-assembly/select.js +69 -0
  317. package/dist/prompt-assembly/sugar.d.ts +31 -0
  318. package/dist/prompt-assembly/sugar.js +20 -0
  319. package/dist/prompt-assembly/turn-snapshot.d.ts +3 -2
  320. package/dist/prompt-assembly/types.d.ts +45 -148
  321. package/dist/prompts/coordinator.d.ts +2 -21
  322. package/dist/prompts/coordinator.js +3 -255
  323. package/dist/prompts/cowork.d.ts +27 -16
  324. package/dist/prompts/cowork.js +2 -23
  325. package/dist/prompts/default.d.ts +38 -500
  326. package/dist/prompts/default.js +20 -285
  327. package/dist/prompts/supervisor.d.ts +6 -71
  328. package/dist/prompts/supervisor.js +6 -117
  329. package/dist/stores/file/session-policy-store.d.ts +3 -3
  330. package/dist/tools/fs/bash-readonly-classifier.d.ts +6 -5
  331. package/dist/tools/fs/dir-entries.d.ts +4 -2
  332. package/dist/tools/fs/dir-entries.js +16 -4
  333. package/dist/tools/fs/fs-bash.d.ts +1 -1
  334. package/dist/tools/fs/fs-bash.js +22 -11
  335. package/dist/tools/fs/fs-pdf.js +17 -13
  336. package/dist/tools/fs/fs-read.js +4 -3
  337. package/dist/tools/fs/fs-shared.d.ts +1 -10
  338. package/dist/tools/fs/fs-shared.js +3 -4
  339. package/dist/tools/fs/fs-write.js +2 -1
  340. package/dist/tools/fs/notebook.js +1 -1
  341. package/dist/tools/fs/pdf.d.ts +20 -10
  342. package/dist/tools/fs/pdf.js +19 -10
  343. package/dist/tools/fs/program-read-model.d.ts +68 -8
  344. package/dist/tools/fs/program-read-model.js +112 -33
  345. package/dist/tools/fs/program-read-model.rows.js +30 -10
  346. package/dist/tools/fs/read-deny-home.d.ts +25 -9
  347. package/dist/tools/fs/read-deny-home.js +28 -27
  348. package/dist/tools/fs/read-deny.d.ts +41 -11
  349. package/dist/tools/fs/read-deny.js +51 -5
  350. package/dist/tools/fs/safety.d.ts +4 -26
  351. package/dist/tools/fs/safety.js +10 -32
  352. package/dist/tools/fs/search.js +15 -10
  353. package/dist/tools/fs/shell-read-argv.d.ts +3 -2
  354. package/dist/tools/fs/shell-read-argv.js +118 -38
  355. package/dist/tools/fs/shell-read-establish.d.ts +5 -5
  356. package/dist/tools/fs/shell-read-establish.js +11 -61
  357. package/dist/tools/fs/shell-read-identity.js +6 -3
  358. package/dist/tools/fs/shell-read-judge.d.ts +13 -15
  359. package/dist/tools/fs/shell-read-judge.js +18 -4
  360. package/dist/tools/fs/shell-read-plan.d.ts +2 -2
  361. package/dist/tools/web.js +1 -1
  362. package/package.json +13 -1
  363. package/test/export-surface.snapshot.json +256 -99
  364. package/wire-changes/core@7.51.1.json +5 -5
  365. package/wire-changes/core@7.51.2.json +293 -0
  366. package/wire-changes/core@7.52.0.json +5859 -0
  367. package/dist/core/hook-seats.d.ts +0 -66
  368. package/dist/core/hook-seats.js +0 -37
  369. package/dist/prompt-assembly/packs/sema-default.d.ts +0 -2
  370. package/dist/prompt-assembly/packs/sema-default.js +0 -147
  371. package/dist/prompts/simple-sections.d.ts +0 -58
  372. package/dist/prompts/simple-sections.js +0 -43
@@ -159,12 +159,12 @@ export interface RunnerDeps {
159
159
  */
160
160
  rosterStore?: import("../agents/roster-store.js").RosterStore;
161
161
  /**
162
- * design/148 S1 — the center prompt-artifact source (protocol §9.2). `current()` supplies the
163
- * validated candidate NEW sessions adopt at session_start; `get(digest)` resolves a PINNED
164
- * center artifact on resume (a miss is fail-loud `prompt.snapshot_unavailable` — core never
165
- * recomposes a hybrid from same-named newer content). Core bundles `CenterPromptSource`
166
- * (+ memory/file artifact & source-state stores); a server deployment feeds it verified
167
- * effective-snapshot envelopes via `applySnapshot`. Omitted = bundled-only (today's shape).
162
+ * The center prompt-artifact source (artifact v2 only — INTEGRATION-CORE §12.11). `current()` supplies the verified
163
+ * candidate a top-level session adopts at session start and at a compaction; `get(digest)` resolves a PINNED center
164
+ * layer on resume (a miss is fail-loud `prompt.snapshot_unavailable` — core never recomposes a hybrid from newer
165
+ * content); `sourceState()` is the tri-state every adoption decision keys on. What a source hands a run is re-checked
166
+ * before it is adopted. Core bundles `CenterPromptSource` (+ memory/file artifact & source-state stores); a server
167
+ * feeds it published artifacts via `applySnapshot`. Omitted = no center layer.
168
168
  */
169
169
  promptSource?: import("../prompt-assembly/artifact-store.js").PromptArtifactSource;
170
170
  /**
@@ -518,7 +518,7 @@ export interface RunnerDeps {
518
518
  resumePreflight?: (info: ResumePreflightInfo, signal: AbortSignal) => Promise<ResumePreflightVerdict>;
519
519
  /**
520
520
  * design/380 O2 — the {@link resumePreflight} deadline in ms. Default 10s (its own bound,
521
- * deliberately NOT the hooks-record default: a resume preflight sits on every redeem attempt of a
521
+ * deliberately its own: a resume preflight sits on every redeem attempt of a
522
522
  * parked row and must answer promptly or get out of the way). Bad values (non-finite, ≤ 0,
523
523
  * non-number) are DISCLOSED loudly through `onError` and fall back to the default (the bad-value
524
524
  * loudness default: announce, never silently absorb).
@@ -1117,7 +1117,7 @@ export interface RunnerDeps {
1117
1117
  * CLAUDE.md/git injection — the cure for "say hi → only greets"). The deployment/profile owns the CONTENT
1118
1118
  * (read CLAUDE.md / `.claude/` + fold in `git log -5`/status + a byte budget); core owns the seam + fence +
1119
1119
  * cache placement and NEVER hardcodes a filename (same trust posture as {@link executionEnvFactory}/
1120
- * {@link promptProvider}/{@link modelKnowledgeCutoffs}). A RunnerDeps FUNCTION, not a `TaskSpec` field: it is
1120
+ * {@link mods}/{@link modelKnowledgeCutoffs}). A RunnerDeps FUNCTION, not a `TaskSpec` field: it is
1121
1121
  * unserializable (durable resume) and reading files for an UNTRUSTED caller would be a confused-deputy hole
1122
1122
  * (design/44 §7 Q4). DECOUPLED from `memoryStore` — injects even with NO long-term memory configured (H5).
1123
1123
  *
@@ -1189,8 +1189,6 @@ export interface RunnerDeps {
1189
1189
  path: string;
1190
1190
  contentHash: string | null;
1191
1191
  }> | null>;
1192
- /** Override system-prompt assembly. Defaults to `defaultPromptProvider`. */
1193
- promptProvider?: import("../prompts/default.js").PromptProvider;
1194
1192
  /**
1195
1193
  * design/99 §E23 — the LIVE-ONLY inbound-elicitation seam (an MCP server asking the END USER for input
1196
1194
  * mid-tool-call). Wired ONLY for servers that opted in via {@link McpServerSpec.elicitation}; absent ⇒ core
@@ -1269,20 +1267,13 @@ export interface RunnerDeps {
1269
1267
  */
1270
1268
  artifactHost?: import("./artifact-host.js").ArtifactHost;
1271
1269
  /**
1272
- * Default in-process hooks for all tasks (design/37) — the FULL lifecycle seam of the `Hooks`
1273
- * interface, not just the tool-call trio: `preToolUse` (rewrite/restrict args + inject context),
1274
- * `postToolUse` (rewrite output + inject context), `userPromptSubmit` (design/373 §4.3: screens
1275
- * EVERY user-lane entrance — the objective, a live `TaskStream.steer`, a wake resume's message,
1276
- * and a parked steer's redelivery, discriminated by `ctx.source`; a hook that blocks
1277
- * unconditionally refuses steers/wakes too — see the ⚠️ WIDENED INVOCATION SET banner on
1278
- * {@link import("./hooks.js").Hooks.userPromptSubmit}), plus `stop` (push back when the run would otherwise end and continue
1279
- * it), `postToolUseFailure` / `postToolBatch` / `permissionDenied` (failure, batch-boundary and
1280
- * deny observers), `preCompact` / `postCompact` (compaction gate + observer), `stopFailure`
1281
- * (API-error terminal observer) and the `preToolUseObservational` declaration flag — each member's
1282
- * contract is documented on the `Hooks` interface itself. A task's own `hooks` overrides this. A
1283
- * PreToolUse hook's `allow` never bypasses `toolPolicy` — the policy is always the final say.
1284
- */
1285
- hooks?: import("./hooks.js").Hooks;
1270
+ * The deployment seat of the mods bus: extension registrations every task of this Runner carries (every leg — root,
1271
+ * delegated child, resume — admits them at its own prepare). Each declares its tier (`prepend`, `user` or `append`;
1272
+ * absent or another word refuses the prepare, `config.mods_invalid`). A task's own `TaskSpec.mods` run beside these,
1273
+ * never instead of them. A `classic.PreToolUse` handler's `allow` never bypasses `toolPolicy` — the policy is always
1274
+ * the final say.
1275
+ */
1276
+ mods?: readonly import("./mods/kernel/index.js").ModRegistration<import("./mods/dollar.js").EngineDollar>[];
1286
1277
  /**
1287
1278
  * Policy for remote image URLs (`TaskSpec.images[].url`). Return false to reject. When set it
1288
1279
  * **replaces** the built-in SSRF guard (https-only + private/reserved-host block) — e.g. supply a
@@ -1295,9 +1286,10 @@ export interface RunnerDeps {
1295
1286
  * summaries) is invisible without this and lets a session grow until it tops the window.
1296
1287
  * - `"prompt-cache"` — a prefix-cache hazard on the wire: a detected cache break (design/31), or a
1297
1288
  * mis-declared/mismatched `promptCacheFamily`. The prefix cache will miss. Log/alert on both.
1298
- * - `"prompt-constitution"` — a `stableSystem` provider returned an ALREADY-assembled prompt
1299
- * (constitution anchor found); core passed it through un-doubled. Upgrade the provider to return
1300
- * only the role base (or set `replaceAll: true` to own the whole base).
1289
+ * - `"prompt-constitution"` — a prompt overlay did not take effect as written: a later source (or a later
1290
+ * declaration in the same source) superseded it on the same target, its target was not in this run's
1291
+ * prompt, or a mods handler's `prompt.compose` answer was skipped (it rewrote another's overlay, or wrote
1292
+ * what the band table does not grant its seat). Each overlay is named once per run.
1301
1293
  * - `"degraded"` — the task kept running with a capability quietly reduced: a question auto-answered
1302
1294
  * with no human present, a skipped env git snapshot, a lost checkpoint-put confirmation, an
1303
1295
  * unroutable descendant notification, and similar best-effort arms. The run proceeds; the reduced
@@ -1496,7 +1488,7 @@ export interface RunnerDeps {
1496
1488
  * trusted control-plane injection), so it lives on `RunnerDeps` — NOT `TaskSpec`: `TaskSpec` is the
1497
1489
  * serializable, untrusted-caller, durable-resume-round-trippable per-task config (a function can be
1498
1490
  * neither serialized nor durably checkpointed, and the sandbox/env-class injections deliberately sit on
1499
- * `RunnerDeps` for the same trust reason). Same placement as `promptProvider` / `executionEnvFactory`.
1491
+ * `RunnerDeps` for the same trust reason). Same placement as `mods` / `executionEnvFactory`.
1500
1492
  *
1501
1493
  * When `summaryProvider` is set, BOTH compaction call sites (the within-task turn boundary AND `finish()`
1502
1494
  * at task end) consult it: a NON-EMPTY string is reused verbatim (the real `generateSummary` LLM call is
@@ -177,12 +177,28 @@ export const SAFETY_MERGE_CONFORMANCE_CORPUS = [
177
177
  },
178
178
  {
179
179
  name: "inert-deny-entry-removed-safe",
180
- intent: "removing a deny entry that reads as nothing (an empty entry, a wildcard peer, a `__` name with no protocol prefix) relaxes nothing — the comparison reads the EFFECTIVE entries on both sides",
181
- prior: { toolDeny: ["Bash", "", "mcp__*", "github__x"] },
180
+ intent: "removing a deny entry the grammar reads that names nothing (a wildcard peer, a `__` name with no protocol prefix) relaxes nothing — the comparison reads the EFFECTIVE entries on both sides",
181
+ prior: { toolDeny: ["Bash", "mcp__*", "github__x"] },
182
182
  next: { toolDeny: ["Bash"] },
183
183
  loosens: false,
184
184
  reasons: [],
185
185
  },
186
+ {
187
+ name: "unreadable-deny-prior-loosened",
188
+ intent: "rules whose toolDeny holds an entry no rule grammar reads (an empty entry) cannot be read and refuse every call — an override that can be read loosens them",
189
+ prior: { toolDeny: ["Bash", ""] },
190
+ next: { toolDeny: ["Bash"] },
191
+ loosens: true,
192
+ reasons: ['the prior rules refuse every call — their toolDeny holds "" (grammar), which no grammar reads'],
193
+ },
194
+ {
195
+ name: "unreadable-deny-next-safe",
196
+ intent: "an override whose toolDeny holds an entry no rule grammar reads refuses every call — it loosens nothing, whatever else it drops",
197
+ prior: { toolDeny: ["Bash"], allowDirs: ["/repo"] },
198
+ next: { toolDeny: [""] },
199
+ loosens: false,
200
+ reasons: [],
201
+ },
186
202
  {
187
203
  name: "inert-allow-entry-added-safe",
188
204
  intent: "adding an allowlist entry that reads as nothing admits nothing, so it widens nothing",
@@ -4,8 +4,9 @@
4
4
  * A child the engine spawns may run what the MODEL chose (a tool shell, a gate over model-written code, a language
5
5
  * server). Under the `"scrub"` policy (the default) it inherits every variable but those the judgment below names —
6
6
  * deleted whole, never rewritten; `"all"` and a `string[]` allow list are the caller's explicit alternatives
7
- * ({@link inheritedHostEnv}). Whatever the policy, a name the deployment declares as its own credential
8
- * ({@link declareWithheldEnv}) is never inherited. One judgment per variable ({@link classifySecretEnvEntry}), the first rule that answers:
7
+ * ({@link inheritedHostEnv}). Whatever the policy, an entry that is this deployment's own credential is never inherited:
8
+ * its name is one the deployment declared, or its value equals a credential value the deployment declared or the
9
+ * engine holds ({@link declareWithheldEnv}, {@link holdOwnCredentialValues}). One judgment per variable ({@link classifySecretEnvEntry}), the first rule that answers:
9
10
  * 1. exempt — git's environment config and the proxy variables, handed on as written ({@link isExemptEnvName});
10
11
  * 2. `exact-name` — a known credential name (the vocabulary's exact env names);
11
12
  * 3. `prefix-rule` — the OpenTelemetry settings ({@link OTEL_ENV_RE});
@@ -26,8 +27,9 @@ import { type EngineNotice } from "./engine-notice.js";
26
27
  * Reads the first {@link VALUE_SCAN_LIMIT} code units. The value half of the judgment, exported apart from the env
27
28
  * entry's exemptions ({@link isExemptEnvName}): a caller holding a value that is no environment variable asks this. */
28
29
  export declare function looksLikeCredentialValue(value: string): boolean;
29
- /** Which rule withheld an entry: one of the scrub's rules, or `own-credential` — the deployment declared the name as its
30
- * own credential ({@link declareWithheldEnv}), which every policy withholds. */
30
+ /** Which rule withheld an entry: one of the scrub's rules, or `own-credential` — the entry is this deployment's own
31
+ * credential (its name is declared, or its value equals a declared or engine-held credential value:
32
+ * {@link declareWithheldEnv}), which every policy withholds. */
31
33
  export type SecretEnvFindingKind = "exact-name" | "name-rule" | "namespace-rule" | "prefix-rule" | "value-rule" | "own-credential";
32
34
  /** One env entry withheld (deleted) from a child's environment: its name — never its value, so the record is
33
35
  * loggable —, the rule that withheld it, how strong that claim is, and the minting module. */
@@ -50,29 +52,100 @@ export declare function isSecretEnvKey(key: string, value?: string): boolean;
50
52
  export declare function scrubSecretEnv(env: NodeJS.ProcessEnv, findings?: SecretEnvFinding[]): NodeJS.ProcessEnv;
51
53
  /** How much of this process's environment a child spawned on this host inherits — the `inheritEnv` value. */
52
54
  export type InheritEnvPolicy = "all" | "scrub" | string[];
55
+ /** What {@link declareWithheldEnv} takes: this deployment's own credentials in this process's environment. */
56
+ export interface WithheldEnvDeclaration {
57
+ /** Names of variables that are this deployment's own credentials: never inherited, and an allow list naming one is refused. */
58
+ readonly names: readonly string[];
59
+ /** Credential values this deployment holds: an inherited entry whose value equals one — the same string, compared
60
+ * whole, never as a part — is never inherited, whatever its name. A value must be a credential: not white space only,
61
+ * a flag or placeholder word, one character repeated, or fewer than eight characters. */
62
+ readonly values: readonly string[];
63
+ }
53
64
  /**
54
- * Declare the names of this deployment's OWN credentials in this process's environment — the engine's or its host's:
55
- * an approval bearer, a service token. From then on no child spawned on this host inherits one, whatever the policy:
56
- * every spawn site reads its environment through {@link inheritedHostEnv}, which subtracts them from `"all"` and from
57
- * the scrub's result (each one present is a finding of kind `own-credential`), and {@link inheritEnvPolicyProblem}
58
- * refuses an allow list naming one. Compared as the platform compares variable names: exactly, but case-blind on
59
- * Windows. A variable a host hands a child itself (a shell's `shellEnv`, a per-exec `env`, a language server's `env`, an MCP server entry's `env`)
60
- * is its explicit grant and is not read against the list.
65
+ * Declare this deployment's OWN credentials in this process's environment — the engine's or its host's: an approval
66
+ * bearer, a service token — by name and by value. From then on no child spawned on this host inherits one, whatever the
67
+ * policy: every spawn site reads its environment through {@link inheritedHostEnv}, which subtracts from `"all"`, from the
68
+ * scrub's result and from an allow list's every entry that is this deployment's own credential (each one present is a
69
+ * finding of kind `own-credential`), and {@link inheritEnvPolicyProblem} refuses an allow list naming a declared name.
70
+ * A NAME is compared as the platform compares variable names: exactly, but case-blind on Windows. A VALUE is compared
71
+ * whole, as the same string: an entry holding it as a part (`Bearer <value>`, a URL, an encoding of it) is not its value.
72
+ * Besides the declared values, every value the engine took in itself ({@link holdOwnCredentialValues}) is withheld the
73
+ * same way. A variable a host hands a child itself (a shell's `shellEnv`, a per-exec `env`, a language server's `env`,
74
+ * an MCP server entry's `env`) is its explicit grant and is not read against the table.
75
+ *
76
+ * Declared once, at start-up, before anything spawns; a later call REPLACES the declaration whole (a configuration
77
+ * reload), read from the next spawn on — a spawn whose environment is already read (one announcing its findings) keeps
78
+ * it; the values the engine took in stay. The lists are copied, and a value is kept only as a digest (no credential is
79
+ * held by the table). A malformed table — not a plain object `{ names, values }` (the names-only list of earlier releases
80
+ * included), a member besides those two, a list that is a Proxy or whose element throws while it is read, a name that
81
+ * is no variable name or that the host hands every child anyway ({@link runtimeSuppliedEnv}), a value that is not a
82
+ * string a variable can hold or is no credential ({@link notACredentialReason}: white space only, a flag or placeholder
83
+ * word, one character repeated, fewer than {@link CREDENTIAL_MIN_CHARS} characters — withholding it would take a setting
84
+ * such as `CI=true` from every child) or that is, in this process's environment now, the value of such a variable —
85
+ * throws and leaves the declaration as it was. A value listed twice is the one value (the declaration is a set). No
86
+ * refusal sentence repeats a value.
61
87
  *
62
- * Declared once, at start-up, before anything spawns; a later call REPLACES the list (a configuration reload), read
63
- * from the next spawn on — a spawn whose environment is already read (one announcing its findings) keeps it. The
64
- * list is copied. A malformed list — not an array, an entry that is no variable name, or a name the host hands every
65
- * child anyway ({@link runtimeSuppliedEnv}) — throws and leaves the declaration as it was.
88
+ * Two Windows readings, measured on a real machine: a withheld name that the child's own shell or runtime re-creates
89
+ * with a DEFAULT of its own (`ComSpec`, `PATHEXT`, `HOME`, `CommonProgramFiles`, …) shows up in the child's table with
90
+ * that default, never with this process's value — withheld, not leaked; and the disclosure (`detail.ownCredentials`)
91
+ * spells each withheld name as this process's environment spells it, not as the declaration spelled it.
92
+ */
93
+ export declare function declareWithheldEnv(table: WithheldEnvDeclaration): void;
94
+ /**
95
+ * The engine takes credential values in — each where the engine receives it: a first-party brain's construction
96
+ * credential (`brainConfigSnapshot`), a model entry's own credential headers (`resolveRouteCredential`), a protocol
97
+ * peer's credential headers (`resolveProtocolHttpHeaders`), the memory distiller's chat seat key (`openAiCompatChatSeat`,
98
+ * and `RunnerDeps.memoryConsolidationDriver.chat` at `new Runner`, before that seat is built). From then on, for the
99
+ * life of the process, no child spawned on this host inherits an entry whose value equals one: the same table, the same
100
+ * subtraction, finding and disclosure as a declared value ({@link declareWithheldEnv}). A credential the engine is handed
101
+ * per request (a per-model auth hook's answer) is not taken in: the host that resolves it owns it and declares it.
102
+ * An absent or empty value adds nothing. A value that is no credential ({@link notACredentialReason}: white space, a
103
+ * flag or placeholder word, one character repeated, fewer than {@link CREDENTIAL_MIN_CHARS} characters — the key a local
104
+ * gateway is told to be handed) is not taken in: its holder uses it as given (it is no bad value), and the variables
105
+ * that hold the same string stay with every child. Said once per process per value, never the value, as the notice
106
+ * `config.credential_not_withheld` through the engine's one notice throat ({@link deliverEngineNotice}): to `onNotice`
107
+ * when the intake has the structured seat in hand (the `RunnerDeps` receipt at `new Runner`), else as that notice's
108
+ * line on `console.warn` (the throat's own arm for an absent seat — a brain's construction, a request's route reading,
109
+ * a peer's dial, a directly built distiller seat). A value that is, in this process's
110
+ * environment now, the value of a variable every child is handed whatever the spawn passes cannot be withheld: the intake
111
+ * throws (`config.invalid_argument`, the variable named, never the value) and takes nothing in — the brain is not built,
112
+ * the peer is not dialed.
66
113
  */
67
- export declare function declareWithheldEnv(names: readonly string[]): void;
68
- /** Test seam: never called by production code (a host re-declares `[]`). */
114
+ export declare function holdOwnCredentialValues(values: Iterable<string | undefined>, onNotice?: (notice: EngineNotice) => void): void;
115
+ /** THE one reading of which HTTP header carries a credential by its NAME — the credential vocabulary's header-name
116
+ * reading ({@link isSensitiveHeaderName}: `Authorization`, `Proxy-Authorization`, `X-Api-Key`, Azure's `api-key`,
117
+ * `x-goog-api-key`, `Cookie`, any name holding a credential word; not a gateway's own spelling of a name the
118
+ * vocabulary declares non-secret, `cf-aig-cache-key` / `X-Idempotency-Key`). The reading of a record MEMBER's name
119
+ * (`isSensitiveRecordKey`), which decides what a record shows, takes those declared names whole only. Every face that
120
+ * asks "which header is a credential, by its name" reads this one: the withheld-value intake below
121
+ * ({@link credentialHeaderValues}) and the route law — which bag carries a credential, which header values a per-model
122
+ * credential's identity is read from, which headers the per-model winner strips, which the user-header merge leaves to
123
+ * that strip, which the run-static stream options refuse. The NAME is the shared half: the intake adds a half of its
124
+ * own, a value that looks like a credential under any name ({@link looksLikeCredentialValue}) — a guess it may make,
125
+ * because withholding a value from a child costs little; the route law does not, because a header it reads as a
126
+ * credential replaces the deployment's key and is bound to an origin, and a guess that is wrong drops a key that should
127
+ * have gone out. */
128
+ export declare function isCredentialHeaderName(name: string): boolean;
129
+ /** Whether a credential header's value is `<auth-scheme> <credentials>` by definition (RFC 9110 §11.6.2 / §11.7.2:
130
+ * `Authorization`, `Proxy-Authorization`) — the scheme word is public and the credentials part is the secret. Any other
131
+ * credential header's value is opaque, read whole. */
132
+ export declare function isSchemedCredentialHeader(name: string): boolean;
133
+ /** The credential values a header bag carries: each header whose name is a credential header ({@link isCredentialHeaderName})
134
+ * or whose value carries one ({@link looksLikeCredentialValue}), as written and, when it reads `<scheme> <credentials>`,
135
+ * its credentials part too — the spelling a variable copied from it would carry. A schemed header's
136
+ * ({@link isSchemedCredentialHeader}) value over a credentials part that is no credential (`Bearer 1`) gives that part
137
+ * alone — the engine's intake then does not take it in — and not the whole value, which carries nothing else. Any other
138
+ * header (`User-Agent`, `Accept`, a region) is no credential. */
139
+ export declare function credentialHeaderValues(headers: Readonly<Record<string, string>> | undefined): string[];
140
+ /** Test seam: never called by production code (a host re-declares `{ names: [], values: [] }`; what the engine took in stays). */
69
141
  export declare function __resetWithheldEnv(): void;
70
142
  /**
71
- * THE environment a child spawned ON THIS HOST inherits: the policy's arm, less the declared own credentials
72
- * ({@link declareWithheldEnv}). The arms: `"scrub"` (and absent) is this process's environment through
143
+ * THE environment a child spawned ON THIS HOST inherits: the policy's arm, less this deployment's own credentials — a
144
+ * declared name, or a value equal to a declared or engine-held credential value ({@link declareWithheldEnv},
145
+ * {@link holdOwnCredentialValues}). The arms: `"scrub"` (and absent) is this process's environment through
73
146
  * {@link scrubSecretEnv}; `"all"` is this process's environment as written; a `string[]` is exactly the named
74
147
  * variables that are set, as written — a strict allow list, so a name it leaves out (`PATH` included) is not
75
- * inherited. `findings` collects every entry withheld: the scrub's, and each declared own credential the arm held.
148
+ * inherited. `findings` collects every entry withheld: the scrub's, and each own credential the arm held.
76
149
  *
77
150
  * A policy {@link inheritEnvPolicyProblem} refuses throws that reason HERE, at every spawn, read against the
78
151
  * declaration as it stands: a value that is no policy at all (never read as the scrub), and an allow list naming a
@@ -1,6 +1,9 @@
1
- import { CREDENTIAL_VOCABULARY, envNameView, splitCamelCase } from "./credential-vocabulary.js";
1
+ import { createHash } from "node:crypto";
2
+ import { types } from "node:util";
3
+ import { CREDENTIAL_MIN_CHARS, CREDENTIAL_VOCABULARY, envNameView, isSensitiveHeaderName, splitCamelCase } from "./credential-vocabulary.js";
2
4
  import { DEFAULT_INHERITED_ENV_VARS } from "@modelcontextprotocol/sdk/client/stdio.js";
3
5
  import { deliverEngineNotice } from "./engine-notice.js";
6
+ import { receiveOwnProperties } from "./own-property-receipt.js";
4
7
  const GIT_CONFIG_ENV_RE = /^GIT_CONFIG_(?:COUNT|PARAMETERS|(?:KEY|VALUE)_[0-9]+)$/;
5
8
  const PROXY_ENV_RE = /^(?:(?:https?|ftp|all|no)_proxy|npm_config_(?:https?_)?proxy|npm_config_noproxy|yarn_proxy|(?:yarn|global_agent|docker|claude_code)_(?:https?|no)_proxy|cloudsdk_proxy_[a-z]+|electron_get_use_proxy)$/i;
6
9
  function isExemptEnvName(name) {
@@ -66,13 +69,14 @@ function carriesSchemelessUserinfo(text) {
66
69
  const at = text.lastIndexOf("@", text.search(/\s|$/));
67
70
  return !isHostPortPathBeforeAt(text.slice(0, at), text.slice(at + 1)) && !/^(?:mailto|sips?|xmpp|im|acct):/i.test(text);
68
71
  }
69
- const CREDENTIAL_ASSIGNMENT_RE = /(?:(?:^|[;&?#,{]|\/:)\s*|\s)["']?(?!-*jobserver-auth\s*[=:])(?:[a-z0-9_.-]{0,64}(?:password|passwd|pwd|secret|token|(?:account|access|api|private|subscription)[-_]?key|signature|sig|credential)|[a-z0-9_.-]{0,63}[_.-]auth)["']?\s*[=:]\s*["']?(?!(?:true|false|none|null|yes|no|on|off|enabled|disabled|required|optional)(?:$|[;&,\s"']))[^;&,\s"']+/i;
72
+ const FLAG_WORDS = ["true", "false", "none", "null", "yes", "no", "on", "off", "enabled", "disabled", "required", "optional"];
73
+ const CREDENTIAL_ASSIGNMENT_RE = new RegExp(String.raw `(?:(?:^|[;&?#,{]|\/:)\s*|\s)["']?(?!-*jobserver-auth\s*[=:])(?:[a-z0-9_.-]{0,64}(?:password|passwd|pwd|secret|token|(?:account|access|api|private|subscription)[-_]?key|signature|sig|credential)|[a-z0-9_.-]{0,63}[_.-]auth)["']?\s*[=:]\s*["']?(?!(?:${FLAG_WORDS.join("|")})(?:$|[;&,\s"']))[^;&,\s"']+`, "i");
70
74
  const WEBHOOK_URL_RE = /https:\/\/(?:hooks\.slack\.com\/(?:services|workflows|triggers)\/|(?:ptb\.|canary\.)?discord(?:app)?\.com\/api\/webhooks\/\d+\/|[\w.-]+\.webhook\.office\.com\/webhookb2\/)[\w\/@.~-]{16,}/i;
71
- const SONAR_LOGIN_RE = /["']?sonar\.login["']?\s*[:=]\s*["']?[^\s"',}]{8,}/;
75
+ const SONAR_LOGIN_RE = new RegExp(String.raw `["']?sonar\.login["']?\s*[:=]\s*["']?[^\s"',}]{${CREDENTIAL_MIN_CHARS},}`);
72
76
  const PRIVATE_KEY_HEADER_RE = /-----BEGIN [A-Z ]*PRIVATE KEY(?: BLOCK)?-----/;
73
- const AUTHORIZATION_HEADER_RE = /\bauthorization\s*[:=]\s*["']?[a-z][a-z0-9_-]*\s+[A-Za-z0-9._~+\/=-]{8,}/i;
77
+ const AUTHORIZATION_HEADER_RE = new RegExp(String.raw `\bauthorization\s*[:=]\s*["']?[a-z][a-z0-9_-]*\s+[A-Za-z0-9._~+\/=-]{${CREDENTIAL_MIN_CHARS},}`, "i");
74
78
  const TOKEN_WORD_RE = /\b(?:[Tt]oken|TOKEN)\s+(?=[A-Za-z0-9_~+=-]*[0-9])(?=[A-Za-z0-9_~+=-]*[A-Z])(?=([A-Za-z0-9_~+=-]{20,}))\1(?![\/.])/;
75
- const BEARER_BASIC_RE = /\b(?:Bearer|Basic)\s+(?=[A-Za-z._~+\/=-]*[0-9]|(?:[A-Za-z0-9._~+\/=-]*?[a-z][A-Z](?![a-z])){2}|[A-Za-z0-9.-]*[_~+\/=])[A-Za-z0-9._~+\/=-]{8,}/;
79
+ const BEARER_BASIC_RE = new RegExp(String.raw `\b(?:Bearer|Basic)\s+(?=[A-Za-z._~+\/=-]*[0-9]|(?:[A-Za-z0-9._~+\/=-]*?[a-z][A-Z](?![a-z])){2}|[A-Za-z0-9.-]*[_~+\/=])[A-Za-z0-9._~+\/=-]{${CREDENTIAL_MIN_CHARS},}`);
76
80
  export function looksLikeCredentialValue(value) {
77
81
  const text = value.length > VALUE_SCAN_LIMIT ? value.slice(0, VALUE_SCAN_LIMIT) : value;
78
82
  for (let at = text.indexOf("://"); at !== -1; at = text.indexOf("://", at + 3)) {
@@ -149,39 +153,188 @@ const WINDOWS_REQUIRED_ENV = Object.freeze(["HOMEDRIVE", "HOMEPATH", "LOGONSERVE
149
153
  function runtimeSuppliedEnv() {
150
154
  return ["NODE_V8_COVERAGE", ...DEFAULT_INHERITED_ENV_VARS, ...(process.platform === "win32" ? WINDOWS_REQUIRED_ENV : [])];
151
155
  }
152
- const WITHHELD_ENV = Symbol.for("sema.core.withheldEnv");
153
- const NOTHING_WITHHELD = Object.freeze([]);
154
- const withheldEnvOf = () => {
155
- const held = Reflect.get(globalThis, WITHHELD_ENV);
156
- return Array.isArray(held) ? held : NOTHING_WITHHELD;
156
+ const valueDigest = (value) => createHash("sha256").update(value, "utf16le").digest("base64");
157
+ const indexHas = (index, value) => {
158
+ const digests = index.get(value.length);
159
+ return digests !== undefined && digests.has(valueDigest(value));
160
+ };
161
+ const indexAdd = (index, value) => {
162
+ const digests = index.get(value.length);
163
+ if (digests === undefined)
164
+ index.set(value.length, new Set([valueDigest(value)]));
165
+ else
166
+ digests.add(valueDigest(value));
157
167
  };
158
- const setWithheldEnv = (names) => {
159
- Reflect.set(globalThis, WITHHELD_ENV, Object.freeze([...names]));
168
+ const WITHHELD_ENV = Symbol.for("sema.core.withheldEnvTable");
169
+ const NOTHING_NAMED = Object.freeze([]);
170
+ const isWithheldEnvTable = (t) => typeof t === "object" && t !== null && Array.isArray(t.names) && t.declared instanceof Map && t.held instanceof Map;
171
+ const withheldEnvOf = () => {
172
+ const slot = Reflect.get(globalThis, WITHHELD_ENV);
173
+ if (isWithheldEnvTable(slot))
174
+ return slot;
175
+ const fresh = { names: NOTHING_NAMED, declared: new Map(), held: new Map() };
176
+ Reflect.set(globalThis, WITHHELD_ENV, fresh);
177
+ return fresh;
160
178
  };
161
- export function declareWithheldEnv(names) {
162
- const value = names;
163
- if (!Array.isArray(value))
164
- throw new Error(`declareWithheldEnv: the list must be an array of variable names (got ${typeof value === "string" ? JSON.stringify(value) : value === null ? "null" : typeof value})`);
165
- const problem = variableNameListProblem("names", value);
179
+ const kindOf = (v) => (v === null ? "null" : Array.isArray(v) ? "an array" : typeof v);
180
+ function listCopy(label, list) {
181
+ if (types.isProxy(list))
182
+ throw new Error(`declareWithheldEnv: ${label} must be a plain array, not a Proxy`);
183
+ const copy = [];
184
+ try {
185
+ for (let i = 0, n = list.length; i < n; i++)
186
+ copy[i] = list[i];
187
+ }
188
+ catch {
189
+ throw new Error(`declareWithheldEnv: an element of ${label} threw while it was read — refused`);
190
+ }
191
+ return Object.freeze(copy);
192
+ }
193
+ const CANNOT_BE_WITHHELD = "which a child is handed from this process's environment whatever the spawn passes (by Node, the MCP stdio transport or Windows) — it cannot be withheld";
194
+ function runtimeSuppliedHolderOf(value) {
195
+ const supplied = policyArm([...runtimeSuppliedEnv()]);
196
+ return Object.keys(supplied).find((k) => supplied[k] === value);
197
+ }
198
+ const PLACEHOLDER_KEY_WORDS = new Set([...FLAG_WORDS, "undefined", "placeholder", "lm-studio", "not-needed", "sk-no-key-required"]);
199
+ const ONE_REPEATED_CHARACTER_RE = /^(\S)\1{2,}$/u;
200
+ function notACredentialReason(value) {
201
+ const text = value.trim();
202
+ if (text === "")
203
+ return "white space only, which every blank variable equals";
204
+ if (text.length < CREDENTIAL_MIN_CHARS)
205
+ return `a string of fewer than ${CREDENTIAL_MIN_CHARS} characters, which names no secret`;
206
+ if (PLACEHOLDER_KEY_WORDS.has(text.toLowerCase()))
207
+ return "a flag or placeholder word, which names no secret";
208
+ if (ONE_REPEATED_CHARACTER_RE.test(text.replace(CREDENTIAL_VOCABULARY.tokenPrefix, "")))
209
+ return "one character repeated, which names no secret";
210
+ return undefined;
211
+ }
212
+ function credentialValueProblem(v) {
213
+ if (typeof v !== "string")
214
+ return kindOf(v);
215
+ if (v === "")
216
+ return "an empty string, which every variable set to nothing equals";
217
+ if (v.includes("\0") || UNPAIRED_SURROGATE_RE.test(v))
218
+ return `a value holding ${v.includes("\0") ? "a NUL" : "an unpaired surrogate"}, which no variable can hold`;
219
+ return notACredentialReason(v);
220
+ }
221
+ function credentialValueListProblem(value) {
222
+ for (const [i, v] of value.entries()) {
223
+ const why = credentialValueProblem(v);
224
+ if (why !== undefined)
225
+ return `values[${i}] is not a credential value (got ${why})`;
226
+ }
227
+ return undefined;
228
+ }
229
+ export function declareWithheldEnv(table) {
230
+ const given = table;
231
+ if (given === null || typeof given !== "object" || Array.isArray(given)) {
232
+ throw new Error(`declareWithheldEnv: the declaration must be a table { names, values } (got ${Array.isArray(given) ? "an array — a names-only list is no longer a declaration: pass { names, values }" : kindOf(given)})`);
233
+ }
234
+ const received = receiveOwnProperties(given, { subject: "declareWithheldEnv's table", unit: "member", moment: "at the declaration" });
235
+ const stray = Object.keys(received).find((k) => k !== "names" && k !== "values");
236
+ if (stray !== undefined)
237
+ throw new Error(`declareWithheldEnv: the table has a member ${JSON.stringify(stray.slice(0, 64))} — it holds names and values only`);
238
+ const givenNames = received.names;
239
+ if (!Array.isArray(givenNames))
240
+ throw new Error(`declareWithheldEnv: names must be an array of variable names (got ${kindOf(givenNames)})`);
241
+ const names = listCopy("names", givenNames);
242
+ const problem = variableNameListProblem("names", names);
166
243
  if (problem !== undefined)
167
244
  throw new Error(`declareWithheldEnv: ${problem}`);
168
245
  const supplied = new Set(runtimeSuppliedEnv().map(envNameKey));
169
- const unwithholdable = value.findIndex((k) => supplied.has(envNameKey(k)));
246
+ const unwithholdable = names.findIndex((k) => supplied.has(envNameKey(k)));
170
247
  if (unwithholdable !== -1)
171
- throw new Error(`declareWithheldEnv: names[${unwithholdable}] is ${value[unwithholdable]}, which a child is handed from this process's environment whatever the spawn passes (by Node, the MCP stdio transport or Windows) — it cannot be withheld`);
172
- setWithheldEnv(value);
248
+ throw new Error(`declareWithheldEnv: names[${unwithholdable}] is ${String(names[unwithholdable])}, ${CANNOT_BE_WITHHELD}`);
249
+ const givenValues = received.values;
250
+ if (!Array.isArray(givenValues))
251
+ throw new Error(`declareWithheldEnv: values must be an array of credential values (got ${kindOf(givenValues)})`);
252
+ const values = listCopy("values", givenValues);
253
+ const valueProblem = credentialValueListProblem(values);
254
+ if (valueProblem !== undefined)
255
+ throw new Error(`declareWithheldEnv: ${valueProblem}`);
256
+ for (const [i, v] of values.entries()) {
257
+ const holder = runtimeSuppliedHolderOf(v);
258
+ if (holder !== undefined)
259
+ throw new Error(`declareWithheldEnv: values[${i}] is the value of ${holder}, ${CANNOT_BE_WITHHELD}`);
260
+ }
261
+ const declared = new Map();
262
+ for (const v of values)
263
+ indexAdd(declared, v);
264
+ Reflect.set(globalThis, WITHHELD_ENV, { names: names, declared, held: withheldEnvOf().held });
265
+ }
266
+ export function holdOwnCredentialValues(values, onNotice) {
267
+ const given = [...values].filter((v) => typeof v === "string" && v.length > 0);
268
+ const taken = given.filter((v) => {
269
+ const why = notACredentialReason(v);
270
+ if (why !== undefined)
271
+ sayNotTaken(v, why, onNotice);
272
+ return why === undefined;
273
+ });
274
+ for (const v of taken) {
275
+ const holder = runtimeSuppliedHolderOf(v);
276
+ if (holder !== undefined)
277
+ throw Object.assign(new Error(`a credential the engine was handed is the value of ${holder}, ${CANNOT_BE_WITHHELD}; the credential is refused`), { code: "config.invalid_argument" });
278
+ }
279
+ const { held } = withheldEnvOf();
280
+ for (const v of taken)
281
+ indexAdd(held, v);
282
+ }
283
+ const AUTH_SCHEME_VALUE_RE = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+ +(\S[\s\S]*)$/;
284
+ const SCHEMED_HEADER_RE = /^(?:proxy-)?authorization$/i;
285
+ export function isCredentialHeaderName(name) {
286
+ return isSensitiveHeaderName(name);
287
+ }
288
+ export function isSchemedCredentialHeader(name) {
289
+ return SCHEMED_HEADER_RE.test(name);
290
+ }
291
+ export function credentialHeaderValues(headers) {
292
+ const out = [];
293
+ for (const [name, value] of Object.entries(headers ?? {})) {
294
+ if (typeof value !== "string" || !(isCredentialHeaderName(name) || looksLikeCredentialValue(value)))
295
+ continue;
296
+ const credentials = AUTH_SCHEME_VALUE_RE.exec(value)?.[1];
297
+ if (credentials !== undefined && isSchemedCredentialHeader(name) && notACredentialReason(credentials) !== undefined) {
298
+ out.push(credentials);
299
+ continue;
300
+ }
301
+ out.push(value);
302
+ if (credentials !== undefined)
303
+ out.push(credentials);
304
+ }
305
+ return out;
306
+ }
307
+ const intakeSaid = new Set();
308
+ function sayNotTaken(value, why, onNotice) {
309
+ const key = valueDigest(value.trim());
310
+ if (intakeSaid.has(key))
311
+ return;
312
+ intakeSaid.add(key);
313
+ try {
314
+ deliverEngineNotice(onNotice, {
315
+ code: "config.credential_not_withheld",
316
+ message: `a credential the engine was handed is ${why} — it is used as given, but a variable holding the same string is not withheld from a spawned child (said once per value; the value is not repeated)`,
317
+ detail: { reason: why },
318
+ });
319
+ }
320
+ catch {
321
+ }
173
322
  }
174
323
  export function __resetWithheldEnv() {
175
- setWithheldEnv([]);
324
+ Reflect.set(globalThis, WITHHELD_ENV, { names: NOTHING_NAMED, declared: new Map(), held: new Map() });
325
+ intakeSaid.clear();
176
326
  }
177
327
  function withholdOwnCredentials(inherited, findings) {
178
- if (withheldEnvOf().length === 0)
328
+ const table = withheldEnvOf();
329
+ if (table.names.length === 0 && table.declared.size === 0 && table.held.size === 0)
179
330
  return inherited;
180
- const own = new Set(withheldEnvOf().map(envNameKey));
331
+ const own = new Set(table.names.map(envNameKey));
181
332
  const kept = [];
182
333
  for (const key of Object.keys(inherited)) {
183
- if (!own.has(envNameKey(key)))
184
- kept.push([key, inherited[key]]);
334
+ const value = inherited[key];
335
+ const ownValue = typeof value === "string" && (indexHas(table.declared, value) || indexHas(table.held, value));
336
+ if (!own.has(envNameKey(key)) && !ownValue)
337
+ kept.push([key, value]);
185
338
  else
186
339
  findings?.push({ key, kind: "own-credential", confidence: SECRET_ENV_KIND_CONFIDENCE["own-credential"], source: "secret-env" });
187
340
  }
@@ -198,24 +351,25 @@ export function inheritedHostEnv(policy, findings) {
198
351
  const problem = inheritEnvPolicyProblem(policy);
199
352
  if (problem !== undefined)
200
353
  throw new Error(problem);
201
- let arm;
354
+ return withholdOwnCredentials(policyArm(policy, findings), findings);
355
+ }
356
+ function policyArm(policy, findings) {
202
357
  if (policy === "all")
203
- arm = { ...process.env };
204
- else if (Array.isArray(policy)) {
205
- arm = {};
206
- for (const k of policy)
207
- if (process.env[k] !== undefined)
208
- arm[k] = process.env[k];
209
- }
210
- else
211
- arm = scrubSecretEnv(process.env, findings);
212
- return withholdOwnCredentials(arm, findings);
358
+ return { ...process.env };
359
+ if (!Array.isArray(policy))
360
+ return scrubSecretEnv(process.env, findings);
361
+ const arm = {};
362
+ for (const k of policy)
363
+ if (process.env[k] !== undefined)
364
+ arm[k] = process.env[k];
365
+ return arm;
213
366
  }
214
367
  export function inheritEnvPolicyProblem(value) {
215
368
  const shape = policyShapeProblem(value);
216
- if (shape !== undefined || !Array.isArray(value) || withheldEnvOf().length === 0)
369
+ const { names } = withheldEnvOf();
370
+ if (shape !== undefined || !Array.isArray(value) || names.length === 0)
217
371
  return shape;
218
- const own = new Set(withheldEnvOf().map(envNameKey));
372
+ const own = new Set(names.map(envNameKey));
219
373
  const named = value.findIndex((k) => own.has(envNameKey(k)));
220
374
  return named === -1 ? undefined : `inheritEnv[${named}] names ${value[named]}, which is this deployment's own credential and cannot be inherited by a child (a configuration error: no retry succeeds until the policy or the declaration changes)`;
221
375
  }