@sema-agent/core 7.47.0 → 7.49.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 (431) hide show
  1. package/CHANGELOG.md +472 -0
  2. package/README.md +2 -2
  3. package/dist/agents/cascade.d.ts +2 -5
  4. package/dist/agents/child-failure.d.ts +20 -0
  5. package/dist/agents/child-failure.js +28 -0
  6. package/dist/agents/cross-session-ref.d.ts +11 -3
  7. package/dist/agents/cross-session-ref.js +6 -0
  8. package/dist/agents/cumulative-stats.d.ts +12 -15
  9. package/dist/agents/cumulative-stats.js +1 -1
  10. package/dist/agents/extra-tool-names.js +1 -1
  11. package/dist/agents/inherited-tool-pool.d.ts +17 -13
  12. package/dist/agents/inherited-tool-pool.js +4 -3
  13. package/dist/agents/peer-session-drain.d.ts +3 -2
  14. package/dist/agents/peer-session-drain.js +5 -4
  15. package/dist/agents/send-message-tool.js +2 -9
  16. package/dist/agents/subagent.d.ts +10 -29
  17. package/dist/agents/subagent.js +65 -53
  18. package/dist/agents/suspend-guard.d.ts +1 -1
  19. package/dist/agents/tool-filter.d.ts +76 -65
  20. package/dist/agents/tool-filter.js +122 -92
  21. package/dist/agents/verify.d.ts +4 -7
  22. package/dist/agents/verify.js +6 -7
  23. package/dist/bench/metrics.d.ts +1 -2
  24. package/dist/brain/anthropic.js +133 -79
  25. package/dist/brain/errors.d.ts +53 -6
  26. package/dist/brain/errors.js +22 -2
  27. package/dist/brain/input-too-long.d.ts +40 -19
  28. package/dist/brain/input-too-long.js +3 -16
  29. package/dist/brain/open-responses.js +19 -10
  30. package/dist/brain/openai.js +123 -32
  31. package/dist/brain/provider-dialect.d.ts +214 -0
  32. package/dist/brain/provider-dialect.js +186 -0
  33. package/dist/brain/request-params.d.ts +27 -8
  34. package/dist/brain/request-params.js +7 -12
  35. package/dist/brain/request-route.d.ts +84 -0
  36. package/dist/brain/request-route.js +41 -0
  37. package/dist/brain/retry.d.ts +8 -0
  38. package/dist/brain/retry.js +10 -4
  39. package/dist/brain/route-adjudicator.d.ts +7 -0
  40. package/dist/brain/route-adjudicator.js +5 -1
  41. package/dist/brain/status-sink.d.ts +20 -0
  42. package/dist/brain/status-sink.js +11 -0
  43. package/dist/brain/stream-engine.d.ts +52 -1
  44. package/dist/brain/stream-engine.js +81 -24
  45. package/dist/brain/stream-shared.d.ts +57 -11
  46. package/dist/brain/stream-shared.js +28 -2
  47. package/dist/core/a2a.d.ts +1 -0
  48. package/dist/core/agent-config-dir.js +3 -2
  49. package/dist/core/allow-entry.d.ts +21 -12
  50. package/dist/core/allow-entry.js +39 -32
  51. package/dist/core/arg-summary.d.ts +17 -24
  52. package/dist/core/arg-summary.js +169 -68
  53. package/dist/core/ask-origin.d.ts +42 -24
  54. package/dist/core/ask-origin.js +18 -13
  55. package/dist/core/auto-mode-prompt-assets.d.ts +2 -2
  56. package/dist/core/auto-mode-prompt-assets.js +1 -1
  57. package/dist/core/auto-mode-prompt.d.ts +11 -1
  58. package/dist/core/auto-mode-prompt.js +13 -10
  59. package/dist/core/auto-mode-rebuild.d.ts +7 -0
  60. package/dist/core/auto-mode-rebuild.js +4 -1
  61. package/dist/core/canonical-json.d.ts +3 -0
  62. package/dist/core/canonical-json.js +2 -1
  63. package/dist/core/checkpoint-requirements.d.ts +892 -0
  64. package/dist/core/checkpoint-requirements.js +333 -0
  65. package/dist/core/checkpoint-store.d.ts +95 -66
  66. package/dist/core/checkpoint-store.js +14 -26
  67. package/dist/core/child-clamp-seats.d.ts +228 -69
  68. package/dist/core/child-clamp-seats.js +211 -17
  69. package/dist/core/classifier-unavailable-arm.d.ts +5 -1
  70. package/dist/core/classifier-unavailable-arm.js +3 -3
  71. package/dist/core/compliance.d.ts +3 -0
  72. package/dist/core/compliance.js +9 -4
  73. package/dist/core/credential-vocabulary.d.ts +140 -0
  74. package/dist/core/credential-vocabulary.js +131 -0
  75. package/dist/core/decision-receipt.js +1 -1
  76. package/dist/core/effective-path-target.d.ts +73 -16
  77. package/dist/core/effective-path-target.js +63 -33
  78. package/dist/core/engine-notice.d.ts +32 -7
  79. package/dist/core/file-history-store.js +2 -2
  80. package/dist/core/fs-write-gate-policy.d.ts +4 -0
  81. package/dist/core/fs-write-gate-policy.js +22 -5
  82. package/dist/core/gate-bounded-await.d.ts +28 -13
  83. package/dist/core/gate-bounded-await.js +41 -4
  84. package/dist/core/gate-fold.d.ts +1 -1
  85. package/dist/core/gate-fold.js +24 -25
  86. package/dist/core/gate-lanes.js +16 -15
  87. package/dist/core/gate-outcome.d.ts +20 -5
  88. package/dist/core/gate-outcome.js +5 -0
  89. package/dist/core/governance-codes.d.ts +11 -4
  90. package/dist/core/governance-codes.js +14 -3
  91. package/dist/core/hooks.d.ts +4 -0
  92. package/dist/core/locked-config.d.ts +8 -0
  93. package/dist/core/locked-config.js +14 -2
  94. package/dist/core/lsp.js +3 -5
  95. package/dist/core/mailbox-store.d.ts +3 -4
  96. package/dist/core/mcp-connection-pool.d.ts +75 -0
  97. package/dist/core/mcp-connection-pool.js +128 -0
  98. package/dist/core/mcp-failure.d.ts +2 -1
  99. package/dist/core/mcp-failure.js +13 -2
  100. package/dist/core/mcp-server-spec.d.ts +1 -1
  101. package/dist/core/mcp.d.ts +4 -0
  102. package/dist/core/mcp.js +70 -43
  103. package/dist/core/memory-engine/content-origin.js +2 -14
  104. package/dist/core/memory-engine/engine.d.ts +32 -22
  105. package/dist/core/memory-engine/engine.js +103 -55
  106. package/dist/core/memory-engine/file-backend.d.ts +13 -30
  107. package/dist/core/memory-engine/file-backend.js +37 -252
  108. package/dist/core/memory-engine/index.d.ts +1 -1
  109. package/dist/core/memory-engine/index.js +1 -1
  110. package/dist/core/memory-engine/layout.d.ts +139 -9
  111. package/dist/core/memory-engine/layout.js +350 -7
  112. package/dist/core/memory-engine/scope-contract.d.ts +10 -0
  113. package/dist/core/memory-engine/scope-contract.js +8 -0
  114. package/dist/core/memory-engine/session-incarnation.d.ts +14 -4
  115. package/dist/core/memory-engine/session-incarnation.js +5 -2
  116. package/dist/core/memory-engine/types.d.ts +10 -1
  117. package/dist/core/memory.js +5 -17
  118. package/dist/core/model-seat.d.ts +4 -4
  119. package/dist/core/model-seat.js +1 -1
  120. package/dist/core/mounted-mcp.d.ts +57 -0
  121. package/dist/core/mounted-mcp.js +19 -0
  122. package/dist/core/namespaced-rule-name.d.ts +29 -0
  123. package/dist/core/namespaced-rule-name.js +52 -0
  124. package/dist/core/park-selfcheck.d.ts +1 -1
  125. package/dist/core/park-selfcheck.js +16 -6
  126. package/dist/core/path-guard-rows.d.ts +99 -0
  127. package/dist/core/path-guard-rows.js +45 -0
  128. package/dist/core/path-identity.d.ts +22 -16
  129. package/dist/core/path-identity.js +10 -10
  130. package/dist/core/path-rule-binding.d.ts +2 -1
  131. package/dist/core/path-rule-binding.js +3 -1
  132. package/dist/core/pause-registry.d.ts +16 -2
  133. package/dist/core/pause-registry.js +6 -0
  134. package/dist/core/permission-rule-consent.js +0 -7
  135. package/dist/core/permission-rule-model.d.ts +68 -24
  136. package/dist/core/permission-rule-model.js +105 -24
  137. package/dist/core/permission-rule-store.js +2 -2
  138. package/dist/core/permission-rules.d.ts +3 -30
  139. package/dist/core/permission-rules.js +4 -54
  140. package/dist/core/read-root-candidate.d.ts +1 -3
  141. package/dist/core/read-root-candidate.js +4 -15
  142. package/dist/core/real-approval.d.ts +4 -3
  143. package/dist/core/retired-keys.d.ts +13 -0
  144. package/dist/core/retired-keys.js +14 -0
  145. package/dist/core/roles.d.ts +2 -3
  146. package/dist/core/roles.js +15 -6
  147. package/dist/core/runner/assemble-result.d.ts +0 -7
  148. package/dist/core/runner/assemble-result.js +19 -31
  149. package/dist/core/runner/caller-roster.d.ts +78 -0
  150. package/dist/core/runner/caller-roster.js +219 -0
  151. package/dist/core/runner/checkpoint-scope.d.ts +16 -16
  152. package/dist/core/runner/checkpoint-scope.js +2 -2
  153. package/dist/core/runner/child-tree.js +2 -2
  154. package/dist/core/runner/contracts.d.ts +68 -35
  155. package/dist/core/runner/decide-continuation.d.ts +51 -3
  156. package/dist/core/runner/decide-continuation.js +76 -21
  157. package/dist/core/runner/denial-limit-arms.d.ts +17 -5
  158. package/dist/core/runner/denial-limit-arms.js +11 -9
  159. package/dist/core/runner/extra-body-dropped-seat.d.ts +8 -0
  160. package/dist/core/runner/extra-body-dropped-seat.js +22 -0
  161. package/dist/core/runner/finish-reason-seat.d.ts +9 -0
  162. package/dist/core/runner/finish-reason-seat.js +40 -0
  163. package/dist/core/runner/gate-exit.d.ts +44 -32
  164. package/dist/core/runner/gate-exit.js +112 -25
  165. package/dist/core/runner/inherited-ask-grants.js +6 -4
  166. package/dist/core/runner/mcp-redial.d.ts +3 -3
  167. package/dist/core/runner/mcp-redial.js +3 -4
  168. package/dist/core/runner/park-commit.d.ts +1 -1
  169. package/dist/core/runner/permission-rule-lanes.d.ts +1 -2
  170. package/dist/core/runner/permission-rule-lanes.js +5 -4
  171. package/dist/core/runner/prepare-artifact.d.ts +4 -0
  172. package/dist/core/runner/prepare-artifact.js +2 -1
  173. package/dist/core/runner/prepare-ask-lane.d.ts +2 -0
  174. package/dist/core/runner/prepare-ask-lane.js +12 -6
  175. package/dist/core/runner/prepare-boundary-parks.d.ts +5 -8
  176. package/dist/core/runner/prepare-boundary-parks.js +4 -7
  177. package/dist/core/runner/prepare-caps-and-workflow.d.ts +11 -15
  178. package/dist/core/runner/prepare-caps-and-workflow.js +19 -27
  179. package/dist/core/runner/prepare-config-doors.d.ts +9 -9
  180. package/dist/core/runner/prepare-config-doors.js +10 -5
  181. package/dist/core/runner/prepare-defer-classify.d.ts +2 -2
  182. package/dist/core/runner/prepare-defer-classify.js +5 -3
  183. package/dist/core/runner/prepare-delegation-surface.d.ts +1 -1
  184. package/dist/core/runner/prepare-delegation-surface.js +3 -3
  185. package/dist/core/runner/prepare-gate-stations.d.ts +4 -4
  186. package/dist/core/runner/prepare-gate-stations.js +9 -7
  187. package/dist/core/runner/prepare-hands-readface.d.ts +7 -7
  188. package/dist/core/runner/prepare-hands-readface.js +7 -7
  189. package/dist/core/runner/prepare-inherited-gate.d.ts +7 -6
  190. package/dist/core/runner/prepare-inherited-gate.js +14 -15
  191. package/dist/core/runner/prepare-listings.d.ts +7 -24
  192. package/dist/core/runner/prepare-listings.js +4 -5
  193. package/dist/core/runner/prepare-memory-engine-session.d.ts +2 -0
  194. package/dist/core/runner/prepare-memory-engine-session.js +4 -3
  195. package/dist/core/runner/prepare-memory.d.ts +6 -0
  196. package/dist/core/runner/prepare-memory.js +13 -13
  197. package/dist/core/runner/prepare-offload-wrappers.d.ts +5 -0
  198. package/dist/core/runner/prepare-offload-wrappers.js +3 -3
  199. package/dist/core/runner/prepare-park-ask.d.ts +7 -8
  200. package/dist/core/runner/prepare-park-ask.js +17 -10
  201. package/dist/core/runner/prepare-policy-chain.js +24 -44
  202. package/dist/core/runner/prepare-project-context.d.ts +1 -1
  203. package/dist/core/runner/prepare-project-context.js +3 -4
  204. package/dist/core/runner/prepare-protocol-tools.d.ts +9 -3
  205. package/dist/core/runner/prepare-protocol-tools.js +3 -4
  206. package/dist/core/runner/prepare-run-refs.d.ts +3 -0
  207. package/dist/core/runner/prepare-run-refs.js +2 -1
  208. package/dist/core/runner/prepare-safety-scan.d.ts +4 -8
  209. package/dist/core/runner/prepare-safety-scan.js +1 -2
  210. package/dist/core/runner/prepare-suspend-saga.d.ts +7 -1
  211. package/dist/core/runner/prepare-suspend-saga.js +28 -12
  212. package/dist/core/runner/prepare-task.d.ts +1 -1
  213. package/dist/core/runner/prepare-task.js +67 -56
  214. package/dist/core/runner/prepare-wiring-manifest.d.ts +11 -10
  215. package/dist/core/runner/prepare-wiring-manifest.js +5 -8
  216. package/dist/core/runner/resume-apply.js +7 -14
  217. package/dist/core/runner/resume-checkpoint-screen.js +11 -4
  218. package/dist/core/runner/resume-internals-and-config.js +2 -2
  219. package/dist/core/runner/resume-policy-outcome.js +5 -32
  220. package/dist/core/runner/resume-review-outcome.js +4 -1
  221. package/dist/core/runner/retired-runner-deps.d.ts +6 -0
  222. package/dist/core/runner/retired-runner-deps.js +10 -1
  223. package/dist/core/runner/run-brain-sinks.d.ts +4 -0
  224. package/dist/core/runner/run-brain-sinks.js +5 -2
  225. package/dist/core/runner/run-harness-handlers.js +27 -34
  226. package/dist/core/runner/run-leg.d.ts +0 -2
  227. package/dist/core/runner/run-leg.js +32 -33
  228. package/dist/core/runner/run-terminal-adoption.js +4 -3
  229. package/dist/core/runner/runtask.js +8 -8
  230. package/dist/core/runner/session-rule-policy.js +5 -5
  231. package/dist/core/runner/stream-settle-backstop.js +7 -4
  232. package/dist/core/runner/sub-agent-deny-lists.d.ts +51 -12
  233. package/dist/core/runner/sub-agent-deny-lists.js +111 -80
  234. package/dist/core/runner/terminal-account.d.ts +48 -0
  235. package/dist/core/runner/terminal-account.js +186 -0
  236. package/dist/core/runner/tool-end-body.d.ts +54 -17
  237. package/dist/core/runner/tool-end-body.js +27 -2
  238. package/dist/core/runner/tool-face-overlay.d.ts +3 -1
  239. package/dist/core/runner/tool-face-overlay.js +6 -4
  240. package/dist/core/runner/tool-occurrence.d.ts +106 -0
  241. package/dist/core/runner/tool-occurrence.js +123 -0
  242. package/dist/core/runner/tool-progress-lane.d.ts +16 -8
  243. package/dist/core/runner/tool-progress-lane.js +25 -34
  244. package/dist/core/runner/turn-attachments.d.ts +1 -1
  245. package/dist/core/runner/write-protection-station.d.ts +21 -9
  246. package/dist/core/runner/write-protection-station.js +20 -17
  247. package/dist/core/runner-deps.d.ts +12 -22
  248. package/dist/core/safety-axis-vocab.d.ts +1 -1
  249. package/dist/core/safety-merge-corpus.d.ts +1 -1
  250. package/dist/core/secret-env.d.ts +16 -5
  251. package/dist/core/secret-env.js +23 -63
  252. package/dist/core/sensitive-path-policy.d.ts +19 -18
  253. package/dist/core/sensitive-path-policy.js +73 -49
  254. package/dist/core/session-policy-store.d.ts +6 -3
  255. package/dist/core/session-policy-store.js +28 -10
  256. package/dist/core/session-reconcile.d.ts +3 -0
  257. package/dist/core/session-reconcile.js +5 -4
  258. package/dist/core/session-store.d.ts +5 -0
  259. package/dist/core/session-store.js +12 -0
  260. package/dist/core/session.d.ts +13 -0
  261. package/dist/core/shared-memory/normalize.d.ts +17 -4
  262. package/dist/core/shared-memory/normalize.js +7 -7
  263. package/dist/core/shell-lexer.js +5 -4
  264. package/dist/core/shell-wrapper-table.d.ts +2 -2
  265. package/dist/core/shell-wrapper-table.js +1 -1
  266. package/dist/core/skill-grant.js +1 -1
  267. package/dist/core/store-contracts/checkpoint-store-contract.js +13 -0
  268. package/dist/core/store-contracts/mailbox-store-contract.d.ts +7 -14
  269. package/dist/core/store-contracts/session-store-incarnation-contract.d.ts +27 -0
  270. package/dist/core/store-contracts/session-store-incarnation-contract.js +92 -0
  271. package/dist/core/stub-env.d.ts +2 -0
  272. package/dist/core/stub-env.js +1 -0
  273. package/dist/core/synthetic-read-verdict.js +2 -2
  274. package/dist/core/task-event.d.ts +59 -5
  275. package/dist/core/task-result.d.ts +1 -1
  276. package/dist/core/task-spec.d.ts +42 -9
  277. package/dist/core/terminal-cause.d.ts +94 -11
  278. package/dist/core/tighten-task-spec.d.ts +5 -4
  279. package/dist/core/tighten-task-spec.js +20 -25
  280. package/dist/core/tool-catalog-entries.d.ts +5 -7
  281. package/dist/core/tool-catalog-entries.js +14 -15
  282. package/dist/core/tool-face.d.ts +47 -0
  283. package/dist/core/tool-face.js +5 -0
  284. package/dist/core/tool-model-gate.d.ts +5 -5
  285. package/dist/core/tool-name-aliases.d.ts +35 -10
  286. package/dist/core/tool-name-aliases.js +15 -0
  287. package/dist/core/tool-name-list.d.ts +30 -0
  288. package/dist/core/tool-name-list.js +55 -0
  289. package/dist/core/tool-name-readings.d.ts +1 -9
  290. package/dist/core/tool-name-readings.js +1 -3
  291. package/dist/core/tool-policy.d.ts +195 -85
  292. package/dist/core/tool-policy.js +165 -381
  293. package/dist/core/tool-registry.d.ts +44 -1
  294. package/dist/core/tool-registry.js +26 -0
  295. package/dist/core/tool-roster.d.ts +19 -1
  296. package/dist/core/tool-roster.js +21 -2
  297. package/dist/core/tool-spec-members.d.ts +45 -0
  298. package/dist/core/tool-spec-members.js +169 -0
  299. package/dist/core/tool-spec.d.ts +46 -8
  300. package/dist/core/tools.d.ts +6 -2
  301. package/dist/core/tools.js +8 -4
  302. package/dist/core/untrusted-egress.js +29 -26
  303. package/dist/core/untrusted-text.d.ts +13 -10
  304. package/dist/core/untrusted-text.js +6 -44
  305. package/dist/core/workflow-journal-store.d.ts +4 -1
  306. package/dist/core/write-protect.d.ts +65 -29
  307. package/dist/core/write-protect.js +235 -177
  308. package/dist/engine/compaction/compaction.d.ts +2 -2
  309. package/dist/engine/execution-env/node-execution-env.d.ts +5 -23
  310. package/dist/engine/execution-env/node-execution-env.js +16 -38
  311. package/dist/engine/execution-env/symlink-chain.d.ts +23 -0
  312. package/dist/engine/execution-env/symlink-chain.js +32 -0
  313. package/dist/engine/harness/types.d.ts +7 -0
  314. package/dist/engine/llm/tool-turns.d.ts +3 -0
  315. package/dist/engine/llm/tool-turns.js +1 -0
  316. package/dist/engine/llm/types.d.ts +59 -23
  317. package/dist/engine/loop/agent-loop.js +16 -2
  318. package/dist/engine/session/memory-repo.js +11 -3
  319. package/dist/engine/session/repo-utils.d.ts +8 -0
  320. package/dist/engine/session/repo-utils.js +13 -0
  321. package/dist/index.d.ts +20 -23
  322. package/dist/index.js +17 -20
  323. package/dist/internal/harness.d.ts +1 -1
  324. package/dist/internal/harness.js +1 -1
  325. package/dist/internal/llm.d.ts +2 -2
  326. package/dist/internal/llm.js +1 -1
  327. package/dist/orchestration/governance-baseline-validity.js +1 -1
  328. package/dist/orchestration/run-spec.js +3 -3
  329. package/dist/orchestration/run-workflow-tool.d.ts +16 -35
  330. package/dist/orchestration/run-workflow-tool.js +38 -78
  331. package/dist/orchestration/workflow-governance.d.ts +21 -25
  332. package/dist/orchestration/workflow-governance.js +38 -78
  333. package/dist/orchestration/workflow-primitives.d.ts +7 -22
  334. package/dist/orchestration/workflow-primitives.js +5 -12
  335. package/dist/orchestration/workflow-types.d.ts +1 -1
  336. package/dist/orchestration/workflow.d.ts +61 -11
  337. package/dist/orchestration/workflow.js +191 -119
  338. package/dist/prompt-assembly/types.d.ts +1 -1
  339. package/dist/scenarios/full-body.d.ts +1 -1
  340. package/dist/shell/lex.d.ts +0 -21
  341. package/dist/shell/lex.js +278 -70
  342. package/dist/shell/shell-words.d.ts +35 -0
  343. package/dist/shell/shell-words.js +65 -0
  344. package/dist/stores/file/checkpoint-store.d.ts +5 -5
  345. package/dist/stores/file/checkpoint-store.js +5 -2
  346. package/dist/stores/file/index.d.ts +0 -8
  347. package/dist/stores/file/index.js +0 -12
  348. package/dist/stores/file/session-store.d.ts +3 -0
  349. package/dist/stores/file/session-store.js +44 -19
  350. package/dist/tools/artifact/artifact-tool.js +2 -0
  351. package/dist/tools/fs/bash-program-position.d.ts +17 -3
  352. package/dist/tools/fs/bash-program-position.js +25 -10
  353. package/dist/tools/fs/bash-readonly-classifier.d.ts +1 -1
  354. package/dist/tools/fs/bash-readonly-classifier.js +8 -7
  355. package/dist/tools/fs/containment-face.d.ts +4 -0
  356. package/dist/tools/fs/containment-face.js +3 -0
  357. package/dist/tools/fs/fs-shared.d.ts +10 -0
  358. package/dist/tools/fs/fs-shared.js +18 -0
  359. package/dist/tools/fs/fs-write.js +4 -2
  360. package/dist/tools/fs/index.d.ts +3 -2
  361. package/dist/tools/fs/index.js +2 -2
  362. package/dist/tools/fs/program-read-model.d.ts +99 -23
  363. package/dist/tools/fs/program-read-model.js +129 -55
  364. package/dist/tools/fs/program-read-model.rows.d.ts +0 -14
  365. package/dist/tools/fs/program-read-model.rows.js +18 -10
  366. package/dist/tools/fs/read-deny-home.d.ts +35 -30
  367. package/dist/tools/fs/read-deny-home.js +45 -38
  368. package/dist/tools/fs/read-deny.d.ts +35 -27
  369. package/dist/tools/fs/read-deny.js +126 -92
  370. package/dist/tools/fs/removal-targets.d.ts +56 -23
  371. package/dist/tools/fs/removal-targets.js +74 -87
  372. package/dist/tools/fs/safety.d.ts +29 -22
  373. package/dist/tools/fs/safety.js +17 -11
  374. package/dist/tools/fs/search.js +10 -8
  375. package/dist/tools/fs/shell-read-argv.d.ts +4 -7
  376. package/dist/tools/fs/shell-read-argv.js +6 -8
  377. package/dist/tools/fs/shell-read-bindings.d.ts +203 -46
  378. package/dist/tools/fs/shell-read-bindings.js +488 -144
  379. package/dist/tools/fs/shell-read-builtins.d.ts +35 -0
  380. package/dist/tools/fs/shell-read-builtins.js +43 -0
  381. package/dist/tools/fs/shell-read-check.d.ts +15 -1
  382. package/dist/tools/fs/shell-read-check.js +51 -42
  383. package/dist/tools/fs/shell-read-establish.js +9 -10
  384. package/dist/tools/fs/shell-read-functions.d.ts +22 -0
  385. package/dist/tools/fs/shell-read-functions.js +29 -0
  386. package/dist/tools/fs/shell-read-judge.d.ts +48 -18
  387. package/dist/tools/fs/shell-read-judge.js +33 -4
  388. package/dist/tools/fs/shell-read-plan.d.ts +13 -20
  389. package/dist/tools/fs/shell-read-plan.js +200 -194
  390. package/dist/tools/fs/shell-read-start.d.ts +80 -0
  391. package/dist/tools/fs/shell-read-start.js +99 -0
  392. package/dist/tools/fs/shell-read-word.d.ts +35 -6
  393. package/dist/tools/fs/shell-read-word.js +89 -9
  394. package/dist/tools/fs/shell-read-workdir.d.ts +156 -0
  395. package/dist/tools/fs/shell-read-workdir.js +281 -0
  396. package/dist/tools/fs/shell-read-write-targets.d.ts +5 -2
  397. package/dist/tools/fs/shell-read-write-targets.js +14 -5
  398. package/dist/tools/fs/shell-reentry-text.d.ts +26 -26
  399. package/dist/tools/fs/shell-reentry-text.js +31 -34
  400. package/dist/tools/task-list.d.ts +1 -2
  401. package/dist/tools/web.js +1 -1
  402. package/package.json +4 -1
  403. package/test/export-surface.snapshot.json +107 -143
  404. package/wire-changes/core@7.48.0.json +252 -0
  405. package/wire-changes/core@7.49.0.json +4765 -0
  406. package/dist/agents/teacher.d.ts +0 -159
  407. package/dist/agents/teacher.js +0 -577
  408. package/dist/agents/team.d.ts +0 -226
  409. package/dist/agents/team.js +0 -257
  410. package/dist/core/strategy-store.d.ts +0 -238
  411. package/dist/core/strategy-store.js +0 -253
  412. package/dist/orchestration/builtin-workflows.d.ts +0 -133
  413. package/dist/orchestration/builtin-workflows.js +0 -159
  414. package/dist/scenarios/env.d.ts +0 -40
  415. package/dist/scenarios/env.js +0 -39
  416. package/dist/scenarios/scenario-registry.d.ts +0 -110
  417. package/dist/scenarios/scenario-registry.js +0 -140
  418. package/dist/scenarios/teacher-quickstart.d.ts +0 -40
  419. package/dist/scenarios/teacher-quickstart.js +0 -12
  420. package/dist/stores/cc/lockfile.d.ts +0 -10
  421. package/dist/stores/cc/lockfile.js +0 -98
  422. package/dist/stores/cc/mailbox-store.d.ts +0 -20
  423. package/dist/stores/cc/mailbox-store.js +0 -255
  424. package/dist/stores/cc/roster-adapter.d.ts +0 -12
  425. package/dist/stores/cc/roster-adapter.js +0 -117
  426. package/dist/stores/cc/sidecar-transcript.d.ts +0 -97
  427. package/dist/stores/cc/sidecar-transcript.js +0 -264
  428. package/dist/stores/cc/task-list-store.d.ts +0 -2
  429. package/dist/stores/cc/task-list-store.js +0 -125
  430. package/dist/stores/file/strategy-store.d.ts +0 -97
  431. package/dist/stores/file/strategy-store.js +0 -341
@@ -3,15 +3,15 @@ import { isNamespacedCoveringRuleName, namespacedRuleNameCovers, parsePermission
3
3
  import { judgeRuleToolName, splitNamespacedName } from "./tool-name-aliases.js";
4
4
  import { catalogToolNames, isShellFaceToolName } from "./tool-registry.js";
5
5
  import { ALLOW_RULE_MEMBERS } from "./allow-rule-shadow.js";
6
- import { COMMAND_RULE_TOOL, READ_RULE_TOOL, findAdmittingRule, laneToolNamesOf, parseRuleText, programRunReachOf, ruleToolGrammarOf } from "./permission-rule-model.js";
6
+ import { COMMAND_RULE_TOOL, adjudicatePersistedDomainRules, adjudicatePersistedNameRules, domainRuleSubjectOf, findAdmittingRule, laneToolNamesOf, nameRuleSubjectOf, parseRuleText, programRunReachOf, ruleToolGrammarOf } from "./permission-rule-model.js";
7
7
  import { pathRuleLaneAnswer } from "./runner/permission-rule-lanes.js";
8
8
  import { callTargetReadingOf } from "./effective-path-target.js";
9
9
  import { splitShellCompoundSegments } from "../tools/fs/bash-readonly-classifier.js";
10
10
  import { mandateDisclosureOf } from "./ask-origin.js";
11
11
  import { inlineUntrusted } from "./untrusted-text.js";
12
- import { valueTypeLabel } from "../agents/tool-filter.js";
12
+ import { valueTypeLabel } from "./tool-name-list.js";
13
13
  import { deliverEngineNotice } from "./engine-notice.js";
14
- export const ALLOW_ENTRY_INERT_REASONS = Object.freeze(["wildcard_all", "namespace_wildcard", "path_pattern", "domain", "content_unsupported", "grammar", "tool_name", "near_miss"]);
14
+ export const ALLOW_ENTRY_INERT_REASONS = Object.freeze(["wildcard_all", "namespace_wildcard", "content_unsupported", "grammar", "tool_name", "near_miss"]);
15
15
  export function nonStringMemberLabel(value) {
16
16
  return `<not a string: ${valueTypeLabel(value)}>`;
17
17
  }
@@ -69,30 +69,21 @@ function readAllowEntry(raw, behavior, roster) {
69
69
  }
70
70
  return row(isShellFaceToolName(name) ? { kind: "shell", name } : { kind: "tool", name });
71
71
  }
72
- if (name === COMMAND_RULE_TOOL) {
73
- const allowRead = parseRuleText(raw, behavior);
74
- if ("rule" in allowRead)
75
- return row({ kind: "command", rule: ruleRowOf(allowRead.rule) });
76
- if (behavior === "allow" && allowRead.reject.code === "invalid.bare_interpreter_prefix") {
77
- const wide = parseRuleText(raw, "deny");
78
- if ("rule" in wide)
79
- return row({ kind: "command", rule: ruleRowOf({ ...wide.rule, behavior: "allow" }) });
80
- }
81
- return inert("grammar");
82
- }
83
- if (ruleToolGrammarOf(name) === "path") {
84
- const read = parseRuleText(raw, behavior);
85
- if ("rule" in read) {
86
- if (read.rule.match === "subpath" && read.rule.tool === READ_RULE_TOOL && behavior === "allow")
87
- return row({ kind: "read_dir", rule: ruleRowOf(read.rule) });
88
- if (behavior === "deny")
89
- return row({ kind: "path", rule: ruleRowOf(read.rule) });
90
- }
91
- return inert("path_pattern");
72
+ const grammar = ruleToolGrammarOf(name);
73
+ if (grammar === undefined)
74
+ return inert("content_unsupported");
75
+ const read = parseRuleText(raw, behavior);
76
+ if ("rule" in read)
77
+ return row({ kind: grammar, rule: ruleRowOf(read.rule) });
78
+ if (grammar === "command" && behavior === "allow" && read.reject.code === "invalid.bare_interpreter_prefix") {
79
+ const wide = parseRuleText(raw, "deny");
80
+ if ("rule" in wide)
81
+ return row({ kind: "command", rule: ruleRowOf({ ...wide.rule, behavior: "allow" }) });
92
82
  }
93
- if (/^domain:/.test(parsed.ruleContent))
94
- return inert("domain");
95
- return inert("content_unsupported");
83
+ return inert(inertReasonOf(read.reject.code));
84
+ }
85
+ function inertReasonOf(code) {
86
+ return code === "unsupported.tool" ? "content_unsupported" : "grammar";
96
87
  }
97
88
  export function compileAllowEntry(raw, behavior, roster) {
98
89
  const read = readAllowEntry(raw, behavior, roster);
@@ -150,8 +141,9 @@ export function autoStripped(compiled, call) {
150
141
  case "command":
151
142
  return shellContentStripped(shellRuleContent(compiled.rule));
152
143
  case "namespace":
153
- case "read_dir":
154
144
  case "path":
145
+ case "name":
146
+ case "domain":
155
147
  return false;
156
148
  default: {
157
149
  const exhaustive = compiled;
@@ -199,8 +191,7 @@ export function judgeAllowEntries(rows, req, behavior, ctx) {
199
191
  }
200
192
  }
201
193
  }
202
- const pathKind = behavior === "allow" ? "read_dir" : "path";
203
- const pathRows = live.filter((r) => r.compiled.kind === pathKind);
194
+ const pathRows = live.filter((r) => r.compiled.kind === "path");
204
195
  if (pathRows.length > 0) {
205
196
  const table = pathRows.map((r) => r.compiled.rule);
206
197
  for (const name of laneToolNamesOf(req).filter((n) => ruleToolGrammarOf(n) === "path")) {
@@ -212,6 +203,18 @@ export function judgeAllowEntries(rows, req, behavior, ctx) {
212
203
  }
213
204
  }
214
205
  }
206
+ for (const grammar of ["name", "domain"]) {
207
+ const familyRows = live.filter((r) => r.compiled.kind === grammar);
208
+ if (familyRows.length === 0)
209
+ continue;
210
+ const table = familyRows.map((r) => r.compiled.rule);
211
+ for (const name of laneToolNamesOf(req).filter((n) => ruleToolGrammarOf(n) === grammar)) {
212
+ const at = { tool: name, cwd: ctx.root, ...(ctx.sessionId !== undefined ? { sessionId: ctx.sessionId } : {}) };
213
+ const verdict = grammar === "name" ? adjudicatePersistedNameRules(table, { ...at, name: nameRuleSubjectOf(name, req.args) }) : adjudicatePersistedDomainRules(table, { ...at, host: domainRuleSubjectOf(name, req.args) });
214
+ if (verdict !== undefined && verdict.behavior === behavior)
215
+ return [familyRows.find((r) => r.compiled.rule === verdict.rules[0]) ?? familyRows[0]];
216
+ }
217
+ }
215
218
  return undefined;
216
219
  }
217
220
  export function allowingRows(rows, req, mode) {
@@ -233,6 +236,9 @@ export class AllowEntryTable {
233
236
  entries() {
234
237
  return this.held.map((r) => r.entry);
235
238
  }
239
+ holdsPathRows() {
240
+ return this.held.some((r) => r.compiled.kind === "path");
241
+ }
236
242
  lane(ctx) {
237
243
  return {
238
244
  allowing: (req, mode) => {
@@ -319,6 +325,7 @@ const SHADOW_REASON = {
319
325
  ancestor: "the task that delegated this one owns this question",
320
326
  dangerous_delete: "this removal targets a protected location (the filesystem root, a top-level directory, a home directory, or a workspace directory or one of its ancestors) — it is cleared by confirming this call, never by an allow rule",
321
327
  unverifiable_delete: "this removal could not be verified safe — it is cleared by confirming this call, never by an allow rule",
328
+ unverifiable_shell_text: "the text this shell will run cannot be read by the engine — it is cleared by confirming this call, never by an allow rule",
322
329
  transcript_write: "this write targets the session transcript — it is cleared by confirming this call, never by an allow rule",
323
330
  org_rule: "an organization policy rule requires approval for this call",
324
331
  governance_unavailable: "this deployment is org-governed and cannot currently read its organization policy",
@@ -329,7 +336,7 @@ const SHADOW_REASON = {
329
336
  requires_user_interaction: "this tool's server declares that a call must be put to a person",
330
337
  operator_forced: "this call arrived already marked as requiring confirmation (an earlier layer of this run, or the task that delegated it, judged it so) — it is cleared by confirming this call, never by a standing allow rule",
331
338
  shell_floor: mandateDisclosureOf("operator_always"),
332
- write_protection_unresolved: mandateDisclosureOf("write_protection_unresolved"),
339
+ target_unresolved: mandateDisclosureOf("target_unresolved"),
333
340
  probe: mandateDisclosureOf("probe_mandate"),
334
341
  write_protection: mandateDisclosureOf("write_protection"),
335
342
  tool_marks_mcp: mandateDisclosureOf("tool_marks"),
@@ -405,7 +412,7 @@ export function inertEntryPhrase(e) {
405
412
  case "unprefixed_namespace":
406
413
  return 'tool_name: a "__" name with no protocol prefix';
407
414
  case "unmintable_segment":
408
- return `tool_name: a peer segment the engine never mints${spelling !== undefined ? `, write "${spelling}"` : ""}`;
415
+ return `tool_name: a namespaced name with a segment the engine never mints${spelling !== undefined ? `, write "${spelling}"` : ""}`;
409
416
  default: {
410
417
  const exhaustive = e.verdict;
411
418
  return exhaustive;
@@ -422,7 +429,7 @@ export function allowedToolsNotGrantedNotice(inert, sessionId) {
422
429
  return {
423
430
  code: ALLOWED_TOOL_NOT_GRANTED_CODE,
424
431
  message: `${inert.length} allowed-tools entr${inert.length === 1 ? "y grants" : "ies grant"} or refuse${inert.length === 1 ? "s" : ""} nothing — ${shown.join("; ")}${rest > 0 ? `; and ${rest} more` : ""}. ` +
425
- "A list holding `*` voids the list, `mcp__*` names no server, a write-path or domain entry has no allow reading, and a tool name must be spelled as the tool is mounted; name the tools (or `mcp__<server>`) instead." +
432
+ "A list holding `*` voids the list, `mcp__*` names no server, a rule the grammar refuses (`grammar`) or one on a tool with no such rule form (`content_unsupported`: an allow by path is an `Edit(…)` or `Read(…)` rule) grants nothing, and a tool name must be spelled as the tool is mounted; name the tools (or `mcp__<server>`) instead." +
426
433
  (refusing ? " Such an entry in a disallowed-tools list keeps its Skill from activating: a refusal that reads as nothing is not dropped." : ""),
427
434
  detail: { ...(sessionId !== undefined ? { sessionId } : {}), entries: inert.map((e) => ({ ...e })) },
428
435
  };
@@ -1,27 +1,15 @@
1
- /** Known credential SHAPES + `secretKey=value` — redacted from the FINAL abbreviated string, the single scrub
2
- * point before any store/SSE fan-out. Conservative (real credential formats). */
3
- /** every prefix is LEFT-ANCHORED with \`(?<![A-Za-z0-9])\` — without it, ordinary words whose
4
- * TAIL spells a prefix were silently redacted (NETWORK-attached → NETWO[redacted], RTMARK-100,
5
- * task_categories, monkey=abcd1234, MonkeyJumping…) while triggering unpredictably on suffix
6
- * length. \`_\` is deliberately NOT in the anchor class: \`api_key=\`, \`STRIPE=sk_live_…\`-style glued
7
- * assignments are REAL credential shapes that must keep scrubbing. The prefixed-token arm also
8
- * drops the \`i\` flag: the real vendors' prefixes are lowercase-only (sk_/pk_/rk_/ghp_…), and the
9
- * case-insensitive form is what turned every UPPERCASE technical word ending in RK/SK/PK into a
10
- * false positive. */
11
- export type RedactionConfidence = "high" | "medium" | "low";
12
- /** Which module's rule table minted a finding (ANG-11 provenance). A closed set, and there is no public
13
- * factory for a finding — a report's entries can only have been written by one of these tables running
14
- * here, so "this finding says X" is an engine statement, not something a caller can hand-assemble into
15
- * a report and have the pipeline endorse. */
16
- export type RedactionSource = "arg-summary" | "untrusted-egress" | "secret-env";
1
+ import { type RedactionConfidence, type RedactionSource, type ValueFamilyRow } from "./credential-vocabulary.js";
2
+ export type { RedactionConfidence, RedactionSource } from "./credential-vocabulary.js";
17
3
  /** One redaction hit: what was detected, where (ORIGINAL-input coordinates), how confidently, the marker
18
- * literal written in its place, and which rule table minted it. */
4
+ * literal written in its place, which rule table minted it, and — present when a vocabulary row minted it — the
5
+ * value family (the row's stable id; a host-leak hit such as a URL or a path names none). */
19
6
  export interface RedactionFinding {
20
7
  kind: string;
21
8
  span: readonly [number, number];
22
9
  confidence: RedactionConfidence;
23
10
  marker: string;
24
11
  source: RedactionSource;
12
+ family?: string;
25
13
  }
26
14
  /** The minimum a finding must declare to be summarizable. Both text findings ({@link RedactionFinding})
27
15
  * and the env arm's entry findings satisfy it, so {@link summarizeRedactions} is ONE helper rather than
@@ -56,13 +44,15 @@ export interface RedactionPass {
56
44
  kind: string;
57
45
  confidence: RedactionConfidence;
58
46
  marker: string;
59
- /** The module this pass is declared in — copied verbatim onto every finding it mints (ANG-11). It
60
- * travels WITH the pass, so a table composed into another module's pipeline (untrusted-egress chains
61
- * {@link SECRET_PASSES}) still attributes its hits to the table that owns the rule, not to whoever ran it. */
47
+ /** The rule table that owns this pass's rule — copied verbatim onto every finding it mints (ANG-11), whoever
48
+ * runs the pass. */
62
49
  source: RedactionSource;
63
50
  re: RegExp;
64
51
  /** A literal replacement (only `$1` substitution is used by these passes) or a replacer fn. */
65
52
  replace: string | ((match: string, ...groups: string[]) => string);
53
+ /** The value family a hit belongs to: one id, or — for a pass joining several rows — the id of the row that
54
+ * matches at the hit's offset in the pass input. Absent = the pass is no vocabulary row. */
55
+ family?: string | ((input: string, at: number) => string);
66
56
  }
67
57
  /**
68
58
  * Run the declared passes in order, collecting findings (original-input spans) when a report is given.
@@ -78,10 +68,13 @@ export interface RedactionPass {
78
68
  * over-stripping, never a leak.
79
69
  */
80
70
  export declare function runRedactionPasses(input: string, passes: readonly RedactionPass[], report?: RedactionReport): string;
81
- /** The credential-shape passes (the pre-channel SECRET_PATTERNS, now with declared kinds/confidence).
82
- * Exported for {@link runRedactionPasses} composition (untrusted-egress chains its URL passes after
83
- * these in ONE pipeline so its findings' spans stay in original coordinates). */
84
- export declare const SECRET_PASSES: readonly RedactionPass[];
71
+ /**
72
+ * The egress view rendered as passes, in the vocabulary's order: one pass per group (a group of several rows is ONE
73
+ * leftmost alternation, its hits attributed to the row that matches at the hit's offset). A row whose wide form
74
+ * captures a label keeps it ahead of the marker; `replacers` renders a kind whose marker placement is a policy (the
75
+ * URL userinfo).
76
+ */
77
+ export declare function egressPasses(groups: ReadonlyArray<readonly ValueFamilyRow[]>, replacers?: Readonly<Record<string, (match: string, ...groups: string[]) => string>>): RedactionPass[];
85
78
  export declare function scrubSecrets(s: string, report?: RedactionReport): string;
86
79
  /** A SHORT, SECRET-SCRUBBED primary-arg summary. Abbreviation REDUCES the surface; a final {@link scrubSecrets}
87
80
  * pass is the leak boundary (the value is PERSISTED + SSE-forwarded and may be read by a platform operator in a
@@ -1,4 +1,5 @@
1
1
  import { writtenAssignmentPrefix } from "../tools/fs/bash-program-position.js";
2
+ import { CREDENTIAL_VOCABULARY, egressPassGroups } from "./credential-vocabulary.js";
2
3
  const ACTIVITY_ARG_MAX = 80;
3
4
  const SENSITIVE_KEY = /token|secret|key|password|passwd|credential|auth/i;
4
5
  export function summarizeRedactions(findings) {
@@ -12,72 +13,179 @@ export function summarizeRedactions(findings) {
12
13
  const parts = [...counts].map(([label, n]) => `${label} x${n}`);
13
14
  return `${findings.length} redaction${findings.length === 1 ? "" : "s"}: ${parts.join(", ")}`;
14
15
  }
15
- function mapBackOnePass(edits, pos) {
16
- let delta = 0;
17
- for (const e of edits) {
18
- const outStart = e.at + delta;
19
- if (pos < outStart)
20
- return pos - delta;
21
- const outEnd = outStart + e.insertedLen;
22
- if (pos < outEnd)
23
- return e.at;
24
- delta += e.insertedLen - e.removedLen;
25
- }
26
- return pos - delta;
16
+ function passZeroMapper(batches) {
17
+ const cursors = batches.map(() => ({ i: 0, delta: 0 }));
18
+ return (pos) => {
19
+ let p = pos;
20
+ for (let b = batches.length - 1; b >= 0; b--) {
21
+ const edits = batches[b];
22
+ const c = cursors[b];
23
+ let mapped;
24
+ while (mapped === undefined && c.i < edits.length) {
25
+ const e = edits[c.i];
26
+ const outStart = e.at + c.delta;
27
+ if (p < outStart)
28
+ mapped = p - c.delta;
29
+ else if (p < outStart + e.insertedLen)
30
+ mapped = e.at;
31
+ else {
32
+ c.delta += e.insertedLen - e.removedLen;
33
+ c.i++;
34
+ }
35
+ }
36
+ p = mapped ?? p - c.delta;
37
+ }
38
+ return p;
39
+ };
27
40
  }
28
41
  const PREEXISTING_MARKER_RE = /\[redacted(?:-[a-z]+)?\]/g;
29
42
  const FORMAT_CHAR_RE = /\p{Cf}/u;
30
43
  const MAX_FORMAT_SLOT_SCANS = 64;
31
44
  const REDACTED_WHOLE = "[redacted]";
32
- function applyPasses(input, passes, report, toOriginal) {
45
+ function finding(pass, span, family) {
46
+ const f = { kind: pass.kind, confidence: pass.confidence, span, marker: pass.marker, source: pass.source };
47
+ if (family !== undefined)
48
+ f.family = family;
49
+ return f;
50
+ }
51
+ function insertedFor(pass, match, groups) {
52
+ return typeof pass.replace === "string"
53
+ ? pass.replace.replace(/\$(\d)/g, (_m, d) => groups[Number(d) - 1] ?? "")
54
+ : pass.replace(match, ...groups);
55
+ }
56
+ function removedRegion(match, inserted) {
57
+ let head = 0;
58
+ while (head < match.length && head < inserted.length && match[head] === inserted[head])
59
+ head++;
60
+ let tail = 0;
61
+ while (tail < match.length - head && tail < inserted.length - head && match[match.length - 1 - tail] === inserted[inserted.length - 1 - tail])
62
+ tail++;
63
+ return [head, match.length - tail];
64
+ }
65
+ function soloHits(input, passes) {
66
+ const hits = [];
67
+ passes.forEach((pass, i) => {
68
+ for (const m of input.matchAll(new RegExp(pass.re.source, pass.re.flags.includes("g") ? pass.re.flags : `${pass.re.flags}g`))) {
69
+ const inserted = insertedFor(pass, m[0], m.slice(1));
70
+ if (inserted === m[0])
71
+ continue;
72
+ const [a, b] = removedRegion(m[0], inserted);
73
+ if (b <= a)
74
+ continue;
75
+ const at = m.index;
76
+ const family = typeof pass.family === "function" ? pass.family(input, at) : pass.family;
77
+ hits.push({ start: at + a, end: at + b, marker: inserted.slice(a, inserted.length - (m[0].length - b)), pass: i, family, matchStart: at, matchEnd: at + m[0].length });
78
+ }
79
+ });
80
+ return hits;
81
+ }
82
+ function enclosingHits(hits) {
83
+ const sorted = [...hits].sort((x, y) => x.start - y.start || y.end - x.end);
84
+ const outer = new Set();
85
+ let reach;
86
+ for (const r of sorted) {
87
+ if (reach !== undefined && reach.pass !== r.pass && reach.end >= r.end && reach.end - reach.start > r.end - r.start)
88
+ outer.add(reach);
89
+ if (reach === undefined || r.end > reach.end)
90
+ reach = r;
91
+ }
92
+ return [...outer];
93
+ }
94
+ function sequentialRemovals(batches) {
95
+ const removals = [];
96
+ for (let j = 0; j < batches.length; j++) {
97
+ const toPassZero = passZeroMapper(batches.slice(0, j));
98
+ for (const e of batches[j]) {
99
+ const start = toPassZero(e.at + e.head);
100
+ const end = toPassZero(e.at + e.removedLen - e.tail);
101
+ removals.push({ start, end: Math.max(start, end), marker: e.inserted.slice(e.head, e.insertedLen - e.tail), pass: e.pass, family: e.family });
102
+ }
103
+ }
104
+ return removals;
105
+ }
106
+ function renderRemovals(input, removals) {
107
+ const sorted = removals.filter((r) => r.end > r.start || r.marker !== "").sort((x, y) => x.start - y.start || y.end - x.end);
108
+ const edits = [];
109
+ let out = "";
110
+ let cursor = 0;
111
+ for (let i = 0; i < sorted.length;) {
112
+ const start = sorted[i].start;
113
+ let end = sorted[i].end;
114
+ let widest;
115
+ for (; i < sorted.length && (sorted[i].start < end || sorted[i].start === start || (sorted[i].marker === "" && sorted[i].start === end)); i++) {
116
+ const r = sorted[i];
117
+ if (r.end > end)
118
+ end = r.end;
119
+ if (r.marker !== "" && (widest === undefined || r.end - r.start > widest.end - widest.start))
120
+ widest = r;
121
+ }
122
+ const marker = widest?.marker ?? REDACTED_WHOLE;
123
+ out += input.slice(cursor, start) + marker;
124
+ cursor = end;
125
+ edits.push({ at: start, removedLen: end - start, insertedLen: marker.length, inserted: marker, family: widest?.family, head: 0, tail: 0, pass: widest?.pass ?? sorted[i - 1].pass });
126
+ }
127
+ return { out: out + input.slice(cursor), edits };
128
+ }
129
+ function runPasses(input, passes, findings, toOriginal) {
33
130
  const batches = [];
34
131
  let cur = input;
35
- for (const pass of passes) {
132
+ passes.forEach((pass, passIndex) => {
36
133
  const edits = [];
134
+ const passInput = cur;
135
+ const toPassZero = passZeroMapper(batches.slice());
37
136
  cur = cur.replace(pass.re, (...args) => {
38
137
  const match = args[0];
39
138
  const offset = args[args.length - 2];
40
139
  const groups = args.slice(1, -2);
41
- const inserted = typeof pass.replace === "string"
42
- ? pass.replace.replace(/\$(\d)/g, (_m, d) => groups[Number(d) - 1] ?? "")
43
- : pass.replace(match, ...groups);
44
- if (inserted !== match) {
45
- if (report !== undefined) {
46
- let s0 = offset;
47
- let e0 = offset + match.length;
48
- for (let i = batches.length - 1; i >= 0; i--) {
49
- s0 = mapBackOnePass(batches[i], s0);
50
- e0 = mapBackOnePass(batches[i], e0);
51
- }
52
- report.findings.push({
53
- kind: pass.kind,
54
- confidence: pass.confidence,
55
- span: [toOriginal(s0), toOriginal(e0)],
56
- marker: pass.marker,
57
- source: pass.source,
58
- });
59
- }
60
- edits.push({ at: offset, removedLen: match.length, insertedLen: inserted.length, inserted });
61
- }
140
+ const inserted = insertedFor(pass, match, groups);
141
+ if (inserted === match)
142
+ return inserted;
143
+ const family = typeof pass.family === "function" ? pass.family(passInput, offset) : pass.family;
144
+ if (findings !== undefined)
145
+ findings.push({ pass: passIndex, f: finding(pass, [toOriginal(toPassZero(offset)), toOriginal(toPassZero(offset + match.length))], family) });
146
+ const [a, b] = removedRegion(match, inserted);
147
+ edits.push({ at: offset, removedLen: match.length, insertedLen: inserted.length, inserted, family, head: a, tail: match.length - b, pass: passIndex });
62
148
  return inserted;
63
149
  });
64
150
  batches.push(edits);
65
- }
151
+ });
66
152
  return { out: cur, batches };
67
153
  }
154
+ function applyPasses(input, passes, report, toOriginal) {
155
+ const found = report === undefined ? undefined : [];
156
+ const plain = runPasses(input, passes, found, toOriginal);
157
+ const outer = enclosingHits(soloHits(input, passes));
158
+ const whole = outer.length === 0 ? undefined : renderRemovals(input, [...sequentialRemovals(plain.batches), ...outer]);
159
+ if (whole === undefined || whole.out === plain.out) {
160
+ if (report !== undefined)
161
+ report.findings.push(...found.map((x) => x.f));
162
+ return plain;
163
+ }
164
+ if (report !== undefined) {
165
+ const seen = new Set(found.map((x) => `${x.pass}:${x.f.span[0]}:${x.f.span[1]}`));
166
+ for (const h of outer) {
167
+ const span = [toOriginal(h.matchStart), toOriginal(h.matchEnd)];
168
+ const key = `${h.pass}:${span[0]}:${span[1]}`;
169
+ if (seen.has(key))
170
+ continue;
171
+ seen.add(key);
172
+ found.push({ pass: h.pass, f: finding(passes[h.pass], span, h.family) });
173
+ }
174
+ found.sort((x, y) => x.pass - y.pass || x.f.span[0] - y.f.span[0]);
175
+ report.findings.push(...found.map((x) => x.f));
176
+ }
177
+ return { out: whole.out, batches: [whole.edits] };
178
+ }
68
179
  function replacedSpans(batches) {
69
180
  const spans = [];
70
181
  for (let j = 0; j < batches.length; j++) {
182
+ const toPassZero = passZeroMapper(batches.slice(0, j));
71
183
  for (const e of batches[j]) {
72
- let s0 = e.at;
73
- let e0 = e.at + e.removedLen;
74
- for (let i = j - 1; i >= 0; i--) {
75
- s0 = mapBackOnePass(batches[i], s0);
76
- e0 = mapBackOnePass(batches[i], e0);
77
- }
184
+ const s0 = toPassZero(e.at);
185
+ const e0 = toPassZero(e.at + e.removedLen);
78
186
  if (e0 - s0 !== e.removedLen)
79
187
  return undefined;
80
- spans.push({ start: s0, end: e0, inserted: e.inserted, pass: j });
188
+ spans.push({ start: s0, end: e0, inserted: e.inserted, pass: e.pass, family: e.family });
81
189
  }
82
190
  }
83
191
  spans.sort((a, b) => a.start - b.start);
@@ -159,7 +267,7 @@ export function runRedactionPasses(input, passes, report) {
159
267
  continue;
160
268
  for (const c of cutSpans) {
161
269
  const o = viewOffsetToOriginal(c.start + cut, c.end + cut);
162
- extra.push({ start: o.start, end: o.end, inserted: c.inserted, pass: c.pass });
270
+ extra.push({ ...c, start: o.start, end: o.end });
163
271
  }
164
272
  }
165
273
  extra.sort((a, b) => a.start - b.start);
@@ -173,10 +281,8 @@ export function runRedactionPasses(input, passes, report) {
173
281
  continue;
174
282
  }
175
283
  spans.push({ start: r.start, end: r.end, inserted: r.inserted });
176
- if (report !== undefined) {
177
- const pass = passes[r.pass];
178
- report.findings.push({ kind: pass.kind, confidence: pass.confidence, span: [r.start, r.end], marker: pass.marker, source: pass.source });
179
- }
284
+ if (report !== undefined)
285
+ report.findings.push(finding(passes[r.pass], [r.start, r.end], r.family));
180
286
  spans.sort((a, b) => a.start - b.start);
181
287
  }
182
288
  for (let i = 1; i < spans.length;) {
@@ -196,27 +302,22 @@ export function runRedactionPasses(input, passes, report) {
196
302
  result += input.slice(cursor);
197
303
  return result;
198
304
  }
199
- export const SECRET_PASSES = [
200
- { kind: "prefixed-token", confidence: "high", marker: "[redacted]", source: "arg-summary", re: /(?<![A-Za-z0-9])(?:sk|pk|rk|gh[opsur]|github_pat)[-_][A-Za-z0-9_-]{8,}/g, replace: "[redacted]" },
201
- { kind: "prefixed-token", confidence: "high", marker: "[redacted]", source: "arg-summary", re: /(?<![A-Za-z0-9])AIza[A-Za-z0-9_-]{20,}/g, replace: "[redacted]" },
202
- { kind: "prefixed-token", confidence: "high", marker: "[redacted]", source: "arg-summary", re: /(?<![A-Za-z0-9])xox[baprs]-[A-Za-z0-9-]{10,}/g, replace: "[redacted]" },
203
- { kind: "prefixed-token", confidence: "high", marker: "[redacted]", source: "arg-summary", re: /(?<![A-Za-z0-9])AKIA[0-9A-Z]{12,}/g, replace: "[redacted]" },
204
- { kind: "prefixed-token", confidence: "high", marker: "[redacted]", source: "arg-summary", re: /(?<![A-Za-z0-9])hf_[A-Za-z0-9]{20,}/g, replace: "[redacted]" },
205
- { kind: "jwt", confidence: "high", marker: "[redacted]", source: "arg-summary", re: /(?<![A-Za-z0-9])eyJ[A-Za-z0-9._-]{20,}/g, replace: "[redacted]" },
206
- { kind: "private-key-block", confidence: "high", marker: "[redacted]", source: "arg-summary", re: /-----BEGIN[ A-Z0-9]*PRIVATE KEY(?: BLOCK)?-----[\s\S]*?(?:-----END[ A-Z0-9]*PRIVATE KEY(?: BLOCK)?-----|$)/g, replace: "[redacted]" },
207
- { kind: "bearer-token", confidence: "high", marker: "[redacted]", source: "arg-summary", re: /(?<![A-Za-z0-9])Bearer\s+[A-Za-z0-9._~+/-]{8,}=*/gi, replace: "[redacted]" },
208
- { kind: "prefixed-token", confidence: "high", marker: "[redacted]", source: "arg-summary", re: /(AccountKey=)[A-Za-z0-9+/]{40,}={0,2}/g, replace: "$1[redacted]" },
209
- {
210
- kind: "keyword-value",
211
- confidence: "medium",
212
- marker: "[redacted]",
213
- source: "arg-summary",
214
- re: /(?<![A-Za-z0-9])((?:token|secret|key|password|passwd|credential|authorization)["']?\s*[=:]\s*["']?)[^\s"';|&]{4,}/gi,
215
- replace: "$1[redacted]",
216
- },
217
- ];
305
+ const BRACKET_MARKER = { "url-credentials": "[redacted-credentials]" };
306
+ const bracketMarker = (kind) => BRACKET_MARKER[kind] ?? "[redacted]";
307
+ const capturesLabel = (re) => new RegExp(`${re.source}|`).exec("").length > 1;
308
+ export function egressPasses(groups, replacers = {}) {
309
+ return groups.map((rows) => {
310
+ const head = rows[0];
311
+ const marker = bracketMarker(head.kind);
312
+ const re = rows.length === 1 ? head.match : new RegExp(rows.map((r) => `(?:${r.match.source})`).join("|"), head.match.flags);
313
+ const sticky = rows.map((r) => ({ id: r.id, re: new RegExp(r.match.source, r.match.flags.replace("g", "") + "y") }));
314
+ const family = rows.length === 1 ? head.id : (input, at) => sticky.find((s) => ((s.re.lastIndex = at), s.re.test(input)))?.id ?? head.id;
315
+ return { kind: head.kind, confidence: head.confidence, marker, source: head.source, re, replace: replacers[head.kind] ?? (capturesLabel(head.match) ? `$1${marker}` : marker), family };
316
+ });
317
+ }
318
+ const SHAPE_PASSES = egressPasses(egressPassGroups(CREDENTIAL_VOCABULARY).filter((rows) => rows[0].source === "arg-summary"));
218
319
  export function scrubSecrets(s, report) {
219
- return runRedactionPasses(s, SECRET_PASSES, report);
320
+ return runRedactionPasses(s, SHAPE_PASSES, report);
220
321
  }
221
322
  function truncCodePoints(s) {
222
323
  const cp = Array.from(s);