@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
@@ -0,0 +1,281 @@
1
+ import { argvOf, lexShell } from "../../shell/lex.js";
2
+ import { shellWordsOf } from "../../shell/shell-words.js";
3
+ import { resolveOperandLexically } from "./bash-readonly-classifier.js";
4
+ import { readProgramPosition } from "./bash-program-position.js";
5
+ import { valueOf } from "./shell-read-bindings.js";
6
+ import { evalDefinedFunctions, functionCallOf } from "./shell-read-functions.js";
7
+ import { codeBodies } from "./shell-reentry-text.js";
8
+ import { isAbsoluteForFamily } from "./safety.js";
9
+ const TEXT_RUNNING_PROGRAMS = new Set(["eval", "source", "."]);
10
+ const BASE_CANDIDATE_MAX = 256;
11
+ const tableSays = (name, at, ctx) => ctx.textBinds(name) || at.table.commandSets.has(name);
12
+ export class WorkdirThread {
13
+ readable;
14
+ candidates;
15
+ lostAt = false;
16
+ floors;
17
+ physical;
18
+ movedAt = -1;
19
+ constructor(start, readable, startsPhysical = false) {
20
+ this.readable = readable;
21
+ this.physical = startsPhysical;
22
+ this.lostAt = start === "unmodelled";
23
+ this.candidates = start === "unmodelled" ? [] : start.map((c) => (typeof c === "string" ? { base: c, skippedCd: -1, ...(readable && isAbsoluteForFamily("own", c) ? { pwd: c } : {}), dirStack: [] } : { ...c, skippedCd: -1 }));
24
+ }
25
+ get lost() {
26
+ return this.lostAt;
27
+ }
28
+ get floorBases() {
29
+ return this.floors;
30
+ }
31
+ reachable(andRunStart) {
32
+ return this.candidates.filter((c) => c.skippedCd < andRunStart);
33
+ }
34
+ end() {
35
+ return this.lostAt ? "unmodelled" : this.candidates;
36
+ }
37
+ where(andRunStart) {
38
+ if (this.lostAt || !this.readable)
39
+ return { PWD: "unknown", OLDPWD: "unknown", movedAt: this.movedAt };
40
+ const reachable = this.reachable(andRunStart);
41
+ const values = (pick) => {
42
+ const out = new Set();
43
+ for (const c of reachable) {
44
+ const v = pick(c);
45
+ if (v === undefined)
46
+ return "unknown";
47
+ out.add(v);
48
+ }
49
+ return [...out].map((spelled) => ({ spelled }));
50
+ };
51
+ return { PWD: values((c) => c.pwd), OLDPWD: values((c) => c.old), movedAt: this.movedAt };
52
+ }
53
+ setPhysical() {
54
+ this.physical = true;
55
+ }
56
+ get mayBePhysical() {
57
+ return this.physical;
58
+ }
59
+ lose(at, reachable, floorTargets = []) {
60
+ this.movedAt = Math.max(this.movedAt, at);
61
+ this.lostAt = true;
62
+ this.floors ??= [...new Set([...reachable.map((c) => c.base), ...floorTargets])];
63
+ }
64
+ shift(si, at, ctx) {
65
+ if (this.lostAt) {
66
+ if (this.floors !== undefined && this.floors.length > 0)
67
+ this.floors = [...new Set([...this.floors, ...floorOf(at.shift, this.reachable(at.andRunStart), ctx)])];
68
+ return;
69
+ }
70
+ this.movedAt = si;
71
+ const reachable = this.reachable(at.andRunStart);
72
+ const s = at.shift;
73
+ if (s.kind === "lost")
74
+ return this.lose(si, reachable);
75
+ if (s.kind === "stack") {
76
+ this.candidates = this.candidates.map(({ dirStack: _, ...c }) => c);
77
+ return;
78
+ }
79
+ const branched = [];
80
+ for (const c of this.candidates) {
81
+ if (c.skippedCd < at.andRunStart) {
82
+ const moved = this.movedFrom(c, at, ctx);
83
+ if (moved === "lost")
84
+ return this.lose(si, reachable, floorOf(s, reachable, ctx));
85
+ for (const m of moved)
86
+ branched.push({ ...m, skippedCd: c.skippedCd });
87
+ }
88
+ branched.push({ ...c, skippedCd: at.provable ? si : c.skippedCd });
89
+ }
90
+ const byKey = new Map();
91
+ for (const c of branched) {
92
+ const key = JSON.stringify([c.base, c.pwd, c.old, c.dirStack]);
93
+ const prior = byKey.get(key);
94
+ if (prior === undefined || c.skippedCd < prior.skippedCd)
95
+ byKey.set(key, c);
96
+ }
97
+ const next = [...byKey.values()];
98
+ if (next.length > BASE_CANDIDATE_MAX)
99
+ this.lose(si, reachable);
100
+ else
101
+ this.candidates = next;
102
+ }
103
+ movedFrom(c, at, ctx) {
104
+ const s = at.shift;
105
+ if (s.kind === "eval") {
106
+ const ran = ctx.evalEnd(s.text, c, at.table);
107
+ if (ran.physical)
108
+ this.physical = true;
109
+ return ran.end === "unmodelled" ? "lost" : ran.end.map((e) => (this.physical ? withoutPwd(e) : e));
110
+ }
111
+ const old = tableSays("PWD", at, ctx) ? {} : c.pwd !== undefined ? { old: c.pwd } : {};
112
+ const land = (base, physical, stack) => ({ base, skippedCd: c.skippedCd, ...(physical || this.physical || !this.readable ? {} : { pwd: base }), ...old, ...(stack !== undefined ? { dirStack: stack } : {}) });
113
+ if (s.kind === "swap" || s.kind === "pop") {
114
+ const top = c.dirStack?.[0];
115
+ if (top === undefined)
116
+ return "lost";
117
+ return [land(top, false, s.kind === "swap" ? [c.base, ...c.dirStack.slice(1)] : c.dirStack.slice(1))];
118
+ }
119
+ if (s.kind !== "cd")
120
+ return "lost";
121
+ const stack = s.push === true ? (c.dirStack === undefined ? undefined : [c.base, ...c.dirStack]) : c.dirStack;
122
+ const targets = targetsOf(s.target, c, at, ctx);
123
+ if (targets === "lost")
124
+ return "lost";
125
+ const out = [];
126
+ for (const t of targets) {
127
+ if ((s.physical || this.physical || c.pwd === undefined) && t.split("/").includes(".."))
128
+ return "lost";
129
+ const moved = resolveOperandLexically(c.base, t, ctx.homeDir);
130
+ if (moved === undefined)
131
+ return "lost";
132
+ out.push(land(moved, s.physical, stack));
133
+ }
134
+ return out;
135
+ }
136
+ }
137
+ const withoutPwd = ({ pwd: _, ...c }) => c;
138
+ function floorOf(s, reachable, ctx) {
139
+ if (s.kind !== "cd")
140
+ return [];
141
+ if (s.target === "home")
142
+ return ctx.homeDir !== undefined ? [ctx.homeDir] : [];
143
+ if (typeof s.target === "string")
144
+ return [];
145
+ const target = s.target;
146
+ return [...(target.floorSpelled !== undefined ? [target.floorSpelled] : []), ...(target.expands === false ? reachable.flatMap((c) => resolveOperandLexically(c.base, target.spelled, ctx.homeDir) ?? []) : [])];
147
+ }
148
+ function targetsOf(target, c, at, ctx) {
149
+ if (target === "home")
150
+ return settledValues(at.table.stateOf("HOME"));
151
+ if (target === "previous")
152
+ return tableSays("OLDPWD", at, ctx) ? settledValues(at.table.stateOf("OLDPWD")) : c.old === undefined ? "lost" : [c.old];
153
+ if (target.expands !== false)
154
+ return "lost";
155
+ const dir = target.spelled;
156
+ if (!searchesCdPath(dir))
157
+ return [dir];
158
+ if (at.cdable && /^[A-Za-z_][A-Za-z0-9_]*$/.test(dir))
159
+ return "lost";
160
+ const cdPath = settledValues(at.table.stateOf("CDPATH"));
161
+ if (cdPath === "lost")
162
+ return "lost";
163
+ const entries = cdPath.flatMap((v) => (v === "" ? [] : v.split(":")));
164
+ return [...new Set([...entries.map((e) => (e === "" ? dir : `${e.replace(/\/+$/, "")}/${dir}`)), dir])];
165
+ }
166
+ export function searchesCdPath(dir) {
167
+ return dir !== "" && !isAbsoluteForFamily("own", dir) && !/^\.\.?(?:\/|$)/.test(dir) && !dir.startsWith("~");
168
+ }
169
+ function settledValues(state) {
170
+ if (state === "unknown" || state.some((v) => v.glob === true))
171
+ return "lost";
172
+ return state.map((v) => v.spelled);
173
+ }
174
+ export function baseShiftOf(program, args, targetOf) {
175
+ if (program === "cd") {
176
+ let physical = false;
177
+ let at = 0;
178
+ for (; at < args.length; at++) {
179
+ const w = args[at].folded;
180
+ if (w === "--") {
181
+ at++;
182
+ break;
183
+ }
184
+ if (!w.startsWith("-") || w === "-")
185
+ break;
186
+ for (const letter of w.slice(1)) {
187
+ if (letter === "P")
188
+ physical = true;
189
+ else if (letter === "L")
190
+ physical = false;
191
+ else if (letter !== "e" && letter !== "@")
192
+ return { shift: { kind: "lost" }, reported: "unmodelled" };
193
+ }
194
+ }
195
+ if (at >= args.length)
196
+ return { shift: { kind: "cd", target: "home", physical }, reported: "home" };
197
+ if (args[at].folded === "-")
198
+ return { shift: { kind: "cd", target: "previous", physical }, reported: "previous" };
199
+ const target = targetOf(args[at]);
200
+ return { shift: { kind: "cd", target, physical }, reported: target };
201
+ }
202
+ if (shellWordsOf("stack_mover").has(program)) {
203
+ const words = args.map((a) => a.folded);
204
+ if (words.some((w) => w === "-n"))
205
+ return { shift: { kind: "stack" }, reported: "unmodelled" };
206
+ if (words.some((w) => /^[+-]\d+$/.test(w)) || words.some((w) => w.startsWith("-") && w !== "--"))
207
+ return { shift: { kind: "lost" }, reported: "unmodelled" };
208
+ const operand = args.find((a) => a.folded !== "--");
209
+ if (program === "popd")
210
+ return { shift: operand === undefined ? { kind: "pop" } : { kind: "lost" }, reported: "unmodelled" };
211
+ if (operand === undefined)
212
+ return { shift: { kind: "swap" }, reported: "unmodelled" };
213
+ return { shift: { kind: "cd", target: targetOf(operand), physical: false, push: true }, reported: targetOf(operand) };
214
+ }
215
+ if (shellWordsOf("stack_editor").has(program) && args.some((a) => a.folded.startsWith("-") || a.folded.startsWith("+")))
216
+ return { shift: { kind: "stack" } };
217
+ return undefined;
218
+ }
219
+ export function textMayMove(text, functions) {
220
+ const lexed = lexShell(text);
221
+ if ("parseFailure" in lexed)
222
+ return true;
223
+ return lexed.segments.some((s) => segmentMayMove(argvOf(s), functions));
224
+ }
225
+ const programOf = (argv) => {
226
+ const pos = readProgramPosition(argv);
227
+ return pos.program === undefined ? undefined : { name: pos.program.basename, args: argv.slice(pos.program.index + 1).map((w) => w.folded) };
228
+ };
229
+ const setsPhysical = (p) => p?.name === "set" && p.args.some((a, k) => /^-[A-Za-z]*P/.test(a) || (a === "-o" && p.args[k + 1] === "physical"));
230
+ export function textSetsPhysical(text) {
231
+ const lexed = lexShell(text);
232
+ return !("parseFailure" in lexed) && lexed.segments.some((s) => setsPhysical(programOf(argvOf(s))));
233
+ }
234
+ export function withCommandEnvironment(table, argv) {
235
+ const overlay = new Map();
236
+ const overlaid = () => ({ ...table, stateOf: (name) => overlay.get(name) ?? table.stateOf(name) });
237
+ for (const k of readProgramPosition(argv).assignments) {
238
+ const a = argv[k].assignment;
239
+ if (a === undefined)
240
+ continue;
241
+ if (a.op !== "=" || a.subscript !== undefined || a.form !== "scalar" || a.value.unresolved !== undefined) {
242
+ overlay.set(a.name, "unknown");
243
+ continue;
244
+ }
245
+ const before = valueOf({ pieces: a.value.pieces }, table, true);
246
+ const ordered = valueOf({ pieces: a.value.pieces }, overlaid(), true);
247
+ overlay.set(a.name, before === "unknown" || ordered === "unknown" ? "unknown" : [...before, ...ordered.filter((v) => !before.some((b) => b.spelled === v.spelled))]);
248
+ }
249
+ return { ...overlaid(), commandSets: new Set(overlay.keys()) };
250
+ }
251
+ export function textCalls(text, functions) {
252
+ const lexed = lexShell(text);
253
+ if ("parseFailure" in lexed)
254
+ return true;
255
+ return lexed.segments.some((s) => functionCallOf(argvOf(s), functions) !== undefined);
256
+ }
257
+ export function segmentMayMove(argv, functions) {
258
+ const pos = readProgramPosition(argv);
259
+ if (pos.program === undefined)
260
+ return false;
261
+ const word = argv[pos.program.index];
262
+ return shellWordsOf("base_mover").has(pos.program.basename) || TEXT_RUNNING_PROGRAMS.has(pos.program.basename) || functionCallOf(argv, functions) !== undefined || word.pieces.some((p) => p.expansion !== undefined || p.literal === undefined);
263
+ }
264
+ export function textMovesOf(defined, argvs, inFunctionBody, inherited) {
265
+ const unread = new Set([...evalDefinedFunctions(argvs), ...(inherited?.unread ?? [])]);
266
+ const functions = new Set([...defined, ...unread, ...(inherited?.functions ?? [])]);
267
+ const programs = argvs.map(programOf);
268
+ const mayMove = argvs.map((argv) => segmentMayMove(argv, functions));
269
+ const bodyMoves = mayMove.some((m, si) => m && inFunctionBody(si));
270
+ const bodiesAt = programs.map((p) => (p === undefined ? [] : codeBodies(p.name, p.args)));
271
+ const mayCallAt = argvs.map((argv) => functionCallOf(argv, functions) !== undefined);
272
+ const runsTextAt = argvs.map((argv) => { const pos = readProgramPosition(argv); const word = pos.program === undefined ? undefined : argv[pos.program.index]; return word !== undefined && (["eval", "source", "."].includes(pos.program.basename) || word.pieces.some((p) => p.expansion !== undefined || p.literal === undefined)); });
273
+ const callAt = (si, table) => functionCallOf(argvs[si], functions, (name) => table.functionState(name));
274
+ const callsUnread = (si, table) => functionCallOf(argvs[si], unread, (name) => table.functionState(name)) !== undefined;
275
+ return {
276
+ functions, unread, mayMove, mayCallAt, runsBodyAt: mayCallAt.map((c, si) => c || runsTextAt[si] || bodiesAt[si].length > 0), bodiesAt, bodyMoves, callAt, callsUnread,
277
+ physicalAt: programs.map(setsPhysical),
278
+ cdableFrom: programs.findIndex((p) => p?.name === "shopt" && p.args.includes("-s") && p.args.includes("cdable_vars")),
279
+ losesBaseAt: (si, table) => (callAt(si, table) !== undefined && bodyMoves) || callsUnread(si, table) || bodiesAt[si].some((b) => bodyMoves || textMayMove(b, functions)),
280
+ };
281
+ }
@@ -5,7 +5,8 @@
5
5
  * writes, the operands an option made edited in place, a copy's destination and its children, an in-place edit's
6
6
  * backups), at the seats the role and the selected options name ({@link WriteSeat}: the directory entry, or where the
7
7
  * path lands). The establisher (`shell-read-establish.ts`) places what this module names; the judge reads the result
8
- * on the deny table's write face. No table of programs or options lives here: what a program writes is its row's.
8
+ * on the write face (the write deny rows, then the write roots). No table of programs or options lives here: what a
9
+ * program writes is its row's.
9
10
  */
10
11
  import type { ReadCandidate, ShellReadSegment } from "./shell-read-plan.js";
11
12
  import { type WriteSeat } from "./program-read-model.js";
@@ -47,5 +48,7 @@ export interface JudgedCandidate {
47
48
  }
48
49
  /** Every candidate a segment hands the judge: its reads minus the write targets, plus its `cd` target (the plan already
49
50
  * lists it among the reads), plus its WRITE targets for the write face ({@link writeTargetsOf}), plus the deny-floor
50
- * shadow of every unplaced home word ({@link denyFloorShadowsOf}) on both faces. */
51
+ * shadow of every unplaced home word ({@link denyFloorShadowsOf}) on both faces. A word the program only writes keeps
52
+ * its read copy for the read deny rows alone (`denyOnly`): whether it lands inside the write roots — or cannot be placed
53
+ * at all — is the write face's question, never a read's. */
51
54
  export declare function judgedCandidatesOf(segment: ShellReadSegment): readonly JudgedCandidate[];
@@ -29,6 +29,7 @@ function writeOwnersOf(segment) {
29
29
  }
30
30
  function writeTargetsOf(segment) {
31
31
  const out = [];
32
+ const writeOnly = new Set();
32
33
  const write = (c, seats, written, child, onlyIfExists) => void out.push({ candidate: { ...c, face: "write" }, ...(seats !== undefined ? { seats } : {}), ...(written !== undefined ? { written } : {}), ...(child === true ? { child } : {}), ...(onlyIfExists !== undefined ? { onlyIfExists } : {}) });
33
34
  for (const r of segment.redirects)
34
35
  if (r.direction === "out" && r.target !== undefined)
@@ -48,9 +49,12 @@ function writeTargetsOf(segment) {
48
49
  continue;
49
50
  const placed = owners.filter((o) => o.words.some((w) => w.raw === c.raw));
50
51
  const fallback = placed.length === 0 ? owners.filter((o) => o.program) : [];
52
+ let only = placed.length > 0;
51
53
  for (const o of [...placed, ...fallback]) {
52
- if (o.readings.length === 0)
54
+ if (o.readings.length === 0) {
55
+ only = false;
53
56
  continue;
57
+ }
54
58
  const at = new Set(o.words.flatMap((w, i) => (w.raw === c.raw ? [i] : [])));
55
59
  const roles = [];
56
60
  let readings = 0;
@@ -64,8 +68,11 @@ function writeTargetsOf(segment) {
64
68
  readings += 1;
65
69
  unexplained ||= unplaced;
66
70
  }
67
- if (roles.length === 0)
71
+ if (roles.length === 0) {
72
+ only = false;
68
73
  continue;
74
+ }
75
+ only &&= !unexplained && readings === o.all.length && roles.every((role) => role.effect !== "edit-in-place" && role.writtenAt === undefined);
69
76
  const stated = roles.some((role) => (o.override ?? role.seats) !== undefined);
70
77
  const seats = stated ? [...new Set(roles.flatMap((role) => o.override ?? role.seats ?? ["landing"]))] : undefined;
71
78
  const written = unexplained || roles.some((role) => role.writtenAt === undefined) ? undefined : [...new Set(roles.flatMap((role) => role.writtenAt ?? []))];
@@ -74,13 +81,15 @@ function writeTargetsOf(segment) {
74
81
  if (roles.some((role) => role.effect === "edit-in-place") && c.expands === false)
75
82
  edited.set(o, [...(edited.get(o) ?? []), { candidate: c, ...(speculative !== undefined ? { onlyIfExists: speculative } : {}) }]);
76
83
  }
84
+ if (only)
85
+ writeOnly.add(c);
77
86
  }
78
87
  for (const o of owners) {
79
88
  for (const c of copyDestinationChildren(segment, o.words, o.readings))
80
89
  write(c, ["landing", "entry"], undefined, true);
81
90
  out.push(...backupTargetsOf(edited.get(o) ?? [], o.readings, o.override));
82
91
  }
83
- return out;
92
+ return { targets: out, writeOnly };
84
93
  }
85
94
  function backupTargetsOf(edited, readings, override) {
86
95
  const suffixes = [...new Set(readings.flatMap((r) => r.suffixes))];
@@ -114,8 +123,8 @@ function copyDestinationChildren(segment, words, readings) {
114
123
  return [...children.values()];
115
124
  }
116
125
  export function judgedCandidatesOf(segment) {
117
- const reads = segment.reads.filter((c) => c.provenance !== "write_redirect_target");
118
- const writes = writeTargetsOf(segment);
126
+ const { targets: writes, writeOnly } = writeTargetsOf(segment);
127
+ const reads = segment.reads.flatMap((c) => (c.provenance === "write_redirect_target" ? [] : [writeOnly.has(c) ? { ...c, denyOnly: true } : c]));
119
128
  const plain = (cs) => cs.map((candidate) => ({ candidate }));
120
129
  return [...plain(reads), ...plain(denyFloorShadowsOf(reads)), ...writes, ...plain(denyFloorShadowsOf(writes.map((w) => w.candidate)))];
121
130
  }
@@ -6,6 +6,7 @@
6
6
  */
7
7
  import { type LexedSegment, type LexedWord } from "../../shell/lex.js";
8
8
  import { type ProgramPosition } from "./bash-program-position.js";
9
+ import { type TargetUser } from "./program-read-model.js";
9
10
  import type { BoundValue } from "./shell-read-bindings.js";
10
11
  /**
11
12
  * The code bodies a builtin keeps among its operands, one per body; empty for every other program. The program read
@@ -52,6 +53,8 @@ export interface LaunchedCommand {
52
53
  readonly spelled: string;
53
54
  };
54
55
  readonly args: readonly LaunchedArg[];
56
+ /** The user the launcher runs it as, where its row says it runs another ({@link targetUserOf}). */
57
+ readonly as?: TargetUser;
55
58
  }
56
59
  /**
57
60
  * What a launcher that runs a program named by no word of its own runs ({@link readProgramPosition}'s `runsShell`: the
@@ -79,11 +82,11 @@ export declare function launchedReadings(argv: readonly LexedWord[], command: La
79
82
  readonly shell?: string;
80
83
  readonly line?: string;
81
84
  };
82
- /** What a launcher runs ({@link launchedCommands}, {@link launchedReadings}), as a reader of the command line reads it:
83
- * each shell's argv in two spellings — `texts` (a word's literal value, else `spell.text`) and `args` (`spell.folded`) —
84
- * with the argv index each position stands for (`words`), one argv per reading of the values its words may take
85
- * (`spell.values`, {@link spellLaunched}); the word naming a shell (`su -s /bin/bash`, `programWords`); and each command
86
- * line a program that is no shell runs (`lines`, once each). */
85
+ /** What a launcher runs ({@link launchedCommands}, {@link launchedReadings}), as a reader of the command line reads it in
86
+ * one reading of its names: each shell's argv in two spellings — `texts` (a word's literal value, else `spell.text`) and
87
+ * `args` (`spell.folded`) — with the argv index each position stands for (`words`), its words' fields read off
88
+ * `spell.values` ({@link spellLaunched}) and the user it runs as (`as`); the word naming a shell (`su -s /bin/bash`,
89
+ * `programWords`); and each command line a program that is no shell runs (`lines`, once each). */
87
90
  export declare function launchedInput(argv: readonly LexedWord[], pos: ProgramPosition, spell: {
88
91
  readonly text: (k: number) => string;
89
92
  readonly folded: (k: number) => string;
@@ -94,6 +97,7 @@ export declare function launchedInput(argv: readonly LexedWord[], pos: ProgramPo
94
97
  readonly texts: readonly string[];
95
98
  readonly args: readonly string[];
96
99
  readonly words: readonly (number | undefined)[];
100
+ readonly as?: TargetUser;
97
101
  }[];
98
102
  readonly programWords: readonly number[];
99
103
  readonly lines: readonly string[];
@@ -107,34 +111,30 @@ export interface LaunchedSpelling {
107
111
  readonly values?: (at: number) => readonly BoundValue[] | undefined;
108
112
  }
109
113
  /**
110
- * The argv a launched shell is handed ({@link launchedCommands}), spelled as `spell` spells the command line's words — one
111
- * argv per reading of the values its words may take. A word an escaping launcher joins (`sudo -s CMD…`) is handed as the
112
- * launcher hands it: each FIELD the command line's shell gives the launcher, escaped ({@link sudoEscaped}) — the field a
113
- * literal word spells, or each field the shell established for a word it rewrites first (`X='#'; sudo -s rm -r "$X" d`
114
- * hands `rm -r \# d`: the value is an operand, never a comment), a pattern's literal characters escaped and its pattern
115
- * characters bare ({@link launchedSpellingOf}). A word whose fields the reader does not know is handed AS WRITTEN: the
116
- * launched shell re-reads the expansion with the command line's quoting, so the word stays one argument (an unknown there)
117
- * and its neighbours stay theirs (`"#$Y" d` is never `#$Y d`). A reading gives each distinct word spelling one value — the
118
- * same word spelled twice expands alike — and words with several values are read in every combination of them (a value in
119
- * the program's position meets each operand); past {@link LAUNCHED_READINGS_MAX}
120
- * combinations reading `i` hands each word its `i`-th value (its last where it holds fewer) — every value of every word is
121
- * still read, the same word spelled twice takes one value per reading as the shell expands it, and the readings stay as
122
- * many as one word's values: their cost is linear in the command, whatever its length.
114
+ * The argv a launched shell is handed ({@link launchedCommands}), spelled as `spell` spells the command line's words in ONE
115
+ * reading of their names (the plan reads a segment once per combination of its names' values, `segmentReadingsOf` in
116
+ * shell-read-word.ts — a word's value here is its value in that reading). A word an escaping launcher joins (`sudo -s
117
+ * CMD…`) is handed as the launcher hands it: the FIELD the command line's shell gives the launcher, escaped
118
+ * ({@link sudoEscaped}) — the field a literal word spells, or the field the shell established for a word it rewrites first
119
+ * (`X='#'; sudo -s rm -r "$X" d` hands `rm -r \# d`: the value is an operand, never a comment), a pattern's literal
120
+ * characters escaped and its pattern characters bare ({@link launchedSpellingOf}). A word whose field the reader does not
121
+ * know is handed AS WRITTEN: the launched shell re-reads the expansion with the command line's quoting, so the word stays
122
+ * one argument (an unknown there) and its neighbours stay theirs (`"#$Y" d` is never `#$Y d`). Any other launcher hands a
123
+ * word's text as `spell.word` spells it.
123
124
  */
124
- export declare function spellLaunched(argv: readonly LexedWord[], args: readonly LaunchedArg[], spell: LaunchedSpelling): string[][];
125
+ export declare function spellLaunched(argv: readonly LexedWord[], args: readonly LaunchedArg[], spell: LaunchedSpelling): string[];
125
126
  /** The argv index of the SCRIPT FILE a shell runs where its argv carries no text ({@link scriptSourceOf}). */
126
127
  export declare function scriptFileAt(basename: string, args: readonly string[]): number | undefined;
127
128
  /** One text that may arrive on a segment's standard input: `from` = its source as written (a here-document's body,
128
- * `<<<WORD`, `<FILE`, `<&N`, the segment the pipe comes from); `literal` = the text, where the command spells it. */
129
+ * `<<<WORD`, `<FILE`, `<&N`, the segment the pipe comes from); `literal` = the text, where the command spells it — a
130
+ * here-document or here-string written in the command; never a pipe's text, which a program PRODUCES. */
129
131
  export interface StdinText {
130
132
  readonly from: string;
131
133
  readonly literal?: string;
132
134
  }
133
135
  /** What may arrive on a segment's standard input: each here-document (its descriptor is not read: every one counts) —
134
136
  * its body, literal when quoted or when nothing in it expands — each here-string (literal when its word is), `<` file
135
- * or `<&` descriptor written to no other descriptor, and the pipe it is reached through (`piped`) unless one of those
136
- * three replaces it. */
137
- export declare function stdinTextsOf(segment: LexedSegment, piped: StdinText | undefined): StdinText[];
138
- /** What one segment (its argv) writes into the pipe after it: the text a printer spells ({@link printedText}) when its
139
- * program word and every argument are literal, else only the segment as written. */
140
- export declare function pipedTextOf(segment: LexedSegment, argv: readonly LexedWord[]): StdinText;
137
+ * or `<&` descriptor written to no other descriptor, and what it inherits (`fed`: the pipe it is reached through, the
138
+ * pipe or the input of the group it stands in, the input of the shell running its text) unless one of those three
139
+ * replaces it. */
140
+ export declare function stdinTextsOf(segment: LexedSegment, fed: readonly StdinText[]): StdinText[];
@@ -1,6 +1,6 @@
1
1
  import { literalHeredocBody, literalTextOf } from "../../shell/lex.js";
2
2
  import { programBasename, readProgramPosition } from "./bash-program-position.js";
3
- import { implementationsOf, printedText, programRow, readArgRoles, selectedOptions } from "./program-read-model.js";
3
+ import { implementationRejects, implementationsOf, programRow, readArgRoles, selectedOptions, targetUserOf } from "./program-read-model.js";
4
4
  import { namesStandardInput } from "./safety.js";
5
5
  export function codeBodies(basename, args) {
6
6
  const row = programRow(basename);
@@ -77,17 +77,27 @@ export function launchedCommands(argv, pos = readProgramPosition(argv)) {
77
77
  const row = programRow(programBasename(argv[runs.launcher].folded));
78
78
  const words = argv.slice(runs.from).map((w) => w.folded);
79
79
  const at = (k) => runs.from + k;
80
- if (words.length === 0 || row?.launcher === undefined)
81
- return [{ args: [] }];
82
- if (row.launcher.shellText === "user")
80
+ if (row?.launcher?.shellText === "user")
83
81
  return userCommands(row, words, at);
82
+ const user = row === undefined ? undefined : targetUserOf(row, argv.slice(runs.launcher + 1, runs.from).map((w) => w.folded));
83
+ const as = user !== undefined ? { as: user } : {};
84
+ if (words.length === 0 || row?.launcher === undefined)
85
+ return [{ args: [], ...as }];
84
86
  if (row.launcher.shellText === "joined") {
85
- const joined = words.flatMap((w, k) => (w.startsWith("-") ? [] : [at(k)]));
86
- const attached = readArgRoles(row, words).flatMap((e) => (e.kind === "option" ? roleValue(e, "shell-text", words, at) ?? [] : []));
87
- const texts = [...(joined.length === 0 ? [] : [{ joined }]), ...attached];
88
- return texts.length === 0 ? [{ args: [] }] : texts.map((t) => ({ args: [{ fixed: "-c" }, t] }));
87
+ const texts = new Map();
88
+ for (const view of implementationsOf(row)) {
89
+ const events = readArgRoles(view, words);
90
+ const first = events.find((e) => e.kind === "operand" || e.kind === "dash-word-operand")?.at ?? words.length;
91
+ if (implementationRejects(row, view, words.slice(0, first)))
92
+ continue;
93
+ const joined = words.slice(first).map((_, k) => at(first + k));
94
+ const values = events.flatMap((e) => (e.kind === "option" || (e.kind === "value" && e.at < first) ? roleValue(e, "shell-text", words, at) ?? [] : []));
95
+ for (const t of [...(joined.length === 0 ? [] : [{ joined }]), ...values])
96
+ texts.set(JSON.stringify(t), t);
97
+ }
98
+ return texts.size === 0 ? [{ args: [], ...as }] : [...texts.values()].map((t) => ({ args: [{ fixed: "-c" }, t], ...as }));
89
99
  }
90
- return [{ args: [{ fixed: "-c" }, { joined: words.map((_, k) => at(k)), escaped: true }] }];
100
+ return [{ args: [{ fixed: "-c" }, { joined: words.map((_, k) => at(k)), escaped: true }], ...as }];
91
101
  }
92
102
  function roleValue(e, kind, words, at) {
93
103
  if (e.kind === "value" && e.role?.kind === kind)
@@ -109,16 +119,18 @@ function userCommands(row, words, at) {
109
119
  const named = own.flatMap((e) => valued(e, "command") ?? []).at(-1);
110
120
  const fromEnvironment = selectedOptions(view, stops ? words.slice(0, end) : words, "one-implementation").some((o) => o.mode === "names-program");
111
121
  const program = named !== undefined ? { program: named } : fromEnvironment ? { program: { spelled: "\"$SHELL\"" } } : {};
122
+ const target = targetUserOf(view, stops ? words.slice(0, end) : words.filter((_, k) => k !== user), { name: user === undefined ? "root" : words[user], dash: operands[0]?.dash !== undefined });
123
+ const runs = { ...program, ...(target !== undefined ? { as: target } : {}) };
112
124
  if (stops) {
113
- out.push({ ...program, args: user === undefined ? [] : words.slice(user + 1).map((_, k) => ({ at: at(user + 1 + k) })) });
125
+ out.push({ ...runs, args: user === undefined ? [] : words.slice(user + 1).map((_, k) => ({ at: at(user + 1 + k) })) });
114
126
  continue;
115
127
  }
116
128
  const rest = operands.filter((e) => user !== undefined && e.at > user).map((e) => ({ at: at(e.at) }));
117
129
  const texts = own.flatMap((e) => valued(e, "shell-text") ?? []);
118
130
  if (texts.length === 0)
119
- out.push({ ...program, args: rest });
131
+ out.push({ ...runs, args: rest });
120
132
  for (const text of texts)
121
- out.push({ ...program, args: [{ fixed: "-c" }, text, ...rest] });
133
+ out.push({ ...runs, args: [{ fixed: "-c" }, text, ...rest] });
122
134
  }
123
135
  return out;
124
136
  }
@@ -155,12 +167,10 @@ export function launchedInput(argv, pos, spell) {
155
167
  if (line === undefined && c.program !== undefined && "at" in c.program && c.program.from === undefined)
156
168
  programWords.push(c.program.at);
157
169
  const words = c.args.map((x) => ("at" in x && x.from === undefined ? x.at : undefined));
158
- const args = asArgs(c.args);
159
- return asTexts(c.args).map((texts, i) => ({ shell, texts, args: args[i], words }));
170
+ return [{ shell, texts: asTexts(c.args), args: asArgs(c.args), words, ...(c.as !== undefined ? { as: c.as } : {}) }];
160
171
  });
161
172
  return { shells, programWords, lines: [...lines] };
162
173
  }
163
- const LAUNCHED_READINGS_MAX = 64;
164
174
  function sudoEscaped(field) {
165
175
  return field.replace(/[^A-Za-z0-9_$-]/gu, (c) => `\\${c}`);
166
176
  }
@@ -168,20 +178,14 @@ function launchedSpellingOf(v) {
168
178
  return v.glob === true ? v.parts.map((p) => (p.pattern ? p.text : sudoEscaped(p.text))).join("") : sudoEscaped(v.spelled);
169
179
  }
170
180
  export function spellLaunched(argv, args, spell) {
171
- const choicesOf = (k) => {
181
+ const field = (k) => {
172
182
  const literal = literalTextOf(argv[k].pieces);
173
183
  if (literal !== undefined)
174
- return [sudoEscaped(literal)];
184
+ return sudoEscaped(literal);
175
185
  const values = spell.values?.(k);
176
- return values === undefined ? [argv[k].raw] : values.map(launchedSpellingOf);
186
+ return values?.length === 1 ? launchedSpellingOf(values[0]) : argv[k].raw;
177
187
  };
178
- const choices = new Map(args.flatMap((a) => ("joined" in a && a.escaped === true ? a.joined : [])).map((k) => [k, choicesOf(k)]));
179
- const distinct = new Map([...choices].map(([k, c]) => [argv[k].raw, c]));
180
- const combinations = [...distinct.values()].reduce((n, c) => n * c.length, 1);
181
- const readings = combinations <= LAUNCHED_READINGS_MAX
182
- ? [...distinct].reduce((acc, [w, c]) => acc.flatMap((r) => c.map((x) => new Map(r).set(w, x))), [new Map()]).map((r) => new Map([...choices.keys()].map((k) => [k, r.get(argv[k].raw)])))
183
- : Array.from({ length: [...choices.values()].reduce((n, c) => Math.max(n, c.length), 1) }, (_, i) => new Map([...choices].map(([k, c]) => [k, c[Math.min(i, c.length - 1)]])));
184
- return readings.map((reading) => args.map((a) => ("fixed" in a ? a.fixed : "at" in a ? spell.word(a.at, a.from ?? 0) : a.joined.map((k) => (a.escaped === true ? reading.get(k) : spell.word(k, 0))).join(" "))));
188
+ return args.map((a) => ("fixed" in a ? a.fixed : "at" in a ? spell.word(a.at, a.from ?? 0) : a.joined.map((k) => (a.escaped === true ? field(k) : spell.word(k, 0))).join(" ")));
185
189
  }
186
190
  export function scriptFileAt(basename, args) {
187
191
  const row = programRow(basename);
@@ -198,7 +202,7 @@ function scriptSourceOf(row, args) {
198
202
  return { stdin: true };
199
203
  return { file: first.at, stdin: options.some((e) => e.kind === "option" && e.reading === "speculative") };
200
204
  }
201
- export function stdinTextsOf(segment, piped) {
205
+ export function stdinTextsOf(segment, fed) {
202
206
  const out = [];
203
207
  let replacesPipe = false;
204
208
  for (const t of segment.tokens) {
@@ -212,12 +216,5 @@ export function stdinTextsOf(segment, piped) {
212
216
  replacesPipe = true;
213
217
  }
214
218
  }
215
- return piped === undefined || replacesPipe ? out : [piped, ...out];
216
- }
217
- export function pipedTextOf(segment, argv) {
218
- const from = `${segment.text.trim()} |`;
219
- const pos = readProgramPosition(argv);
220
- const program = pos.program;
221
- const literal = program === undefined || pos.refusal !== undefined || literalTextOf(argv[program.index].pieces) === undefined ? undefined : printedText(programRow(program.basename), argv.slice(program.index + 1).map((w) => literalTextOf(w.pieces)));
222
- return literal === undefined ? { from } : { from, literal };
219
+ return replacesPipe ? out : [...fed, ...out];
223
220
  }
@@ -96,8 +96,7 @@ export interface TaskListStore {
96
96
  export declare function normalizeTaskShape<T>(item: T): T;
97
97
  export declare function assertJsonMetadata(value: unknown, path?: string): void;
98
98
  /**
99
- * RB-274 — the contract's `list` order, mirroring the CC-compat backend's `orderIds`
100
- * (`stores/cc/task-list-store.ts`): numeric ids ascending (CC's own task order), any non-numeric id
99
+ * RB-274 — the contract's `list` order: numeric ids ascending (CC's own task order), any non-numeric id
101
100
  * after them, lexicographically. Ties broken lexicographically so the comparator is total (and the
102
101
  * order therefore stable across repeated calls, which the contract also requires).
103
102
  */
package/dist/tools/web.js CHANGED
@@ -67,7 +67,7 @@ function assessGrounding(text, bytes) {
67
67
  return { level: low ? "low" : "ok", textChars, bytes, textRatio: Math.round(textRatio * 1000) / 1000 };
68
68
  }
69
69
  function recoveryToolRuledOut(ctx, toolName) {
70
- if (ctx.excludeTools?.includes(toolName) ?? false)
70
+ if (ctx.toolSelector !== undefined && !ctx.toolSelector.admits({ name: toolName }))
71
71
  return true;
72
72
  const deferred = ctx.deferTools?.includes(toolName) ?? false;
73
73
  const pinnedInline = ctx.alwaysLoadTools?.includes(toolName) ?? false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sema-agent/core",
3
- "version": "7.47.0",
3
+ "version": "7.49.0",
4
4
  "description": "Stateless, task-oriented AI agent core",
5
5
  "type": "module",
6
6
  "license": "BUSL-1.1",
@@ -72,6 +72,7 @@
72
72
  "handoff:diff": "node scripts/dist-handoff-diff.mjs",
73
73
  "post-ship": "node scripts/post-ship.mjs",
74
74
  "gate:debts:rc": "node scripts/verify-debts.mjs --rc-gate",
75
+ "gate:rulings": "node scripts/rulings-gate.mjs --require-comms",
75
76
  "gate:error-surface": "node scripts/verify-error-surface.mjs",
76
77
  "gate:criteria": "node scripts/criteria-lint.mjs",
77
78
  "gate:reminder-literal": "node scripts/verify-reminder-literal.mjs",
@@ -89,7 +90,9 @@
89
90
  "gate:child-clamp-seats": "node scripts/verify-child-clamp-seats.mjs",
90
91
  "gate:spawn-sites": "node scripts/verify-spawn-sites.mjs",
91
92
  "gate:point-free-callbacks": "node scripts/verify-point-free-callbacks.mjs",
93
+ "gate:weak-identity": "node scripts/gate-weak-identity.mjs",
92
94
  "gate:docs-tool-names": "node scripts/verify-docs-tool-names.mjs",
95
+ "gate:credential-vocabulary": "node scripts/verify-credential-vocabulary.mjs",
93
96
  "gate:comment-ratio": "vitest run test/comment-ratio-ratchet.test.ts",
94
97
  "gate:negative-controls": "vitest run test/gate-negative-controls.test.ts",
95
98
  "gate:memory-ga": "node scripts/gate-memory-distillation-ga.mjs",