@sema-agent/core 7.48.0 → 7.49.1

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 (421) hide show
  1. package/CHANGELOG.md +457 -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 +38 -31
  51. package/dist/core/arg-summary.d.ts +21 -28
  52. package/dist/core/arg-summary.js +235 -88
  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 +94 -65
  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 +43 -11
  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 +21 -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.d.ts +4 -0
  101. package/dist/core/mcp.js +70 -43
  102. package/dist/core/memory-engine/content-origin.js +2 -14
  103. package/dist/core/memory-engine/engine.d.ts +32 -22
  104. package/dist/core/memory-engine/engine.js +103 -55
  105. package/dist/core/memory-engine/file-backend.d.ts +13 -30
  106. package/dist/core/memory-engine/file-backend.js +37 -252
  107. package/dist/core/memory-engine/index.d.ts +1 -1
  108. package/dist/core/memory-engine/index.js +1 -1
  109. package/dist/core/memory-engine/layout.d.ts +139 -9
  110. package/dist/core/memory-engine/layout.js +350 -7
  111. package/dist/core/memory-engine/scope-contract.d.ts +10 -0
  112. package/dist/core/memory-engine/scope-contract.js +8 -0
  113. package/dist/core/memory-engine/session-incarnation.d.ts +14 -4
  114. package/dist/core/memory-engine/session-incarnation.js +5 -2
  115. package/dist/core/memory-engine/types.d.ts +10 -1
  116. package/dist/core/memory.js +5 -17
  117. package/dist/core/model-seat.d.ts +4 -4
  118. package/dist/core/model-seat.js +1 -1
  119. package/dist/core/mounted-mcp.d.ts +57 -0
  120. package/dist/core/mounted-mcp.js +19 -0
  121. package/dist/core/namespaced-rule-name.d.ts +29 -0
  122. package/dist/core/namespaced-rule-name.js +52 -0
  123. package/dist/core/park-selfcheck.d.ts +1 -1
  124. package/dist/core/park-selfcheck.js +16 -6
  125. package/dist/core/path-guard-rows.d.ts +99 -0
  126. package/dist/core/path-guard-rows.js +45 -0
  127. package/dist/core/path-identity.d.ts +22 -16
  128. package/dist/core/path-identity.js +10 -10
  129. package/dist/core/path-rule-binding.d.ts +2 -1
  130. package/dist/core/path-rule-binding.js +3 -1
  131. package/dist/core/pause-registry.d.ts +16 -2
  132. package/dist/core/pause-registry.js +6 -0
  133. package/dist/core/permission-rule-consent.js +0 -7
  134. package/dist/core/permission-rule-model.d.ts +68 -24
  135. package/dist/core/permission-rule-model.js +105 -24
  136. package/dist/core/permission-rule-store.js +2 -2
  137. package/dist/core/permission-rules.d.ts +3 -30
  138. package/dist/core/permission-rules.js +4 -54
  139. package/dist/core/read-root-candidate.d.ts +1 -3
  140. package/dist/core/read-root-candidate.js +4 -15
  141. package/dist/core/real-approval.d.ts +4 -3
  142. package/dist/core/retired-keys.d.ts +13 -0
  143. package/dist/core/retired-keys.js +14 -0
  144. package/dist/core/roles.d.ts +2 -3
  145. package/dist/core/roles.js +15 -6
  146. package/dist/core/runner/assemble-result.d.ts +0 -7
  147. package/dist/core/runner/assemble-result.js +19 -31
  148. package/dist/core/runner/caller-roster.d.ts +78 -0
  149. package/dist/core/runner/caller-roster.js +219 -0
  150. package/dist/core/runner/checkpoint-scope.d.ts +16 -16
  151. package/dist/core/runner/checkpoint-scope.js +2 -2
  152. package/dist/core/runner/child-tree.js +2 -2
  153. package/dist/core/runner/contracts.d.ts +68 -35
  154. package/dist/core/runner/decide-continuation.d.ts +51 -3
  155. package/dist/core/runner/decide-continuation.js +76 -21
  156. package/dist/core/runner/denial-limit-arms.d.ts +17 -5
  157. package/dist/core/runner/denial-limit-arms.js +11 -9
  158. package/dist/core/runner/extra-body-dropped-seat.d.ts +8 -0
  159. package/dist/core/runner/extra-body-dropped-seat.js +22 -0
  160. package/dist/core/runner/finish-reason-seat.d.ts +9 -0
  161. package/dist/core/runner/finish-reason-seat.js +40 -0
  162. package/dist/core/runner/gate-exit.d.ts +44 -32
  163. package/dist/core/runner/gate-exit.js +112 -25
  164. package/dist/core/runner/inherited-ask-grants.js +6 -4
  165. package/dist/core/runner/mcp-redial.d.ts +3 -3
  166. package/dist/core/runner/mcp-redial.js +3 -4
  167. package/dist/core/runner/permission-rule-lanes.d.ts +1 -2
  168. package/dist/core/runner/permission-rule-lanes.js +5 -4
  169. package/dist/core/runner/prepare-artifact.d.ts +4 -0
  170. package/dist/core/runner/prepare-artifact.js +2 -1
  171. package/dist/core/runner/prepare-ask-lane.d.ts +2 -0
  172. package/dist/core/runner/prepare-ask-lane.js +12 -6
  173. package/dist/core/runner/prepare-boundary-parks.d.ts +5 -8
  174. package/dist/core/runner/prepare-boundary-parks.js +4 -7
  175. package/dist/core/runner/prepare-caps-and-workflow.d.ts +11 -15
  176. package/dist/core/runner/prepare-caps-and-workflow.js +19 -27
  177. package/dist/core/runner/prepare-config-doors.d.ts +9 -9
  178. package/dist/core/runner/prepare-config-doors.js +10 -5
  179. package/dist/core/runner/prepare-defer-classify.d.ts +2 -2
  180. package/dist/core/runner/prepare-defer-classify.js +5 -3
  181. package/dist/core/runner/prepare-delegation-surface.d.ts +1 -1
  182. package/dist/core/runner/prepare-delegation-surface.js +3 -3
  183. package/dist/core/runner/prepare-gate-stations.d.ts +4 -4
  184. package/dist/core/runner/prepare-gate-stations.js +9 -7
  185. package/dist/core/runner/prepare-hands-readface.d.ts +7 -7
  186. package/dist/core/runner/prepare-hands-readface.js +7 -7
  187. package/dist/core/runner/prepare-inherited-gate.d.ts +7 -6
  188. package/dist/core/runner/prepare-inherited-gate.js +14 -15
  189. package/dist/core/runner/prepare-listings.d.ts +7 -24
  190. package/dist/core/runner/prepare-listings.js +4 -5
  191. package/dist/core/runner/prepare-memory-engine-session.d.ts +2 -0
  192. package/dist/core/runner/prepare-memory-engine-session.js +4 -3
  193. package/dist/core/runner/prepare-memory.d.ts +6 -0
  194. package/dist/core/runner/prepare-memory.js +13 -13
  195. package/dist/core/runner/prepare-offload-wrappers.d.ts +5 -0
  196. package/dist/core/runner/prepare-offload-wrappers.js +3 -3
  197. package/dist/core/runner/prepare-park-ask.d.ts +7 -8
  198. package/dist/core/runner/prepare-park-ask.js +17 -10
  199. package/dist/core/runner/prepare-policy-chain.js +24 -44
  200. package/dist/core/runner/prepare-project-context.d.ts +1 -1
  201. package/dist/core/runner/prepare-project-context.js +3 -4
  202. package/dist/core/runner/prepare-protocol-tools.d.ts +9 -3
  203. package/dist/core/runner/prepare-protocol-tools.js +3 -4
  204. package/dist/core/runner/prepare-run-refs.d.ts +3 -0
  205. package/dist/core/runner/prepare-run-refs.js +2 -1
  206. package/dist/core/runner/prepare-safety-scan.d.ts +4 -8
  207. package/dist/core/runner/prepare-safety-scan.js +1 -2
  208. package/dist/core/runner/prepare-suspend-saga.d.ts +7 -1
  209. package/dist/core/runner/prepare-suspend-saga.js +28 -12
  210. package/dist/core/runner/prepare-task.d.ts +1 -1
  211. package/dist/core/runner/prepare-task.js +67 -56
  212. package/dist/core/runner/prepare-wiring-manifest.d.ts +11 -10
  213. package/dist/core/runner/prepare-wiring-manifest.js +5 -8
  214. package/dist/core/runner/resume-apply.js +7 -14
  215. package/dist/core/runner/resume-checkpoint-screen.js +11 -4
  216. package/dist/core/runner/resume-internals-and-config.js +2 -2
  217. package/dist/core/runner/resume-policy-outcome.js +5 -32
  218. package/dist/core/runner/resume-review-outcome.js +4 -1
  219. package/dist/core/runner/retired-runner-deps.d.ts +6 -0
  220. package/dist/core/runner/retired-runner-deps.js +10 -1
  221. package/dist/core/runner/run-brain-sinks.d.ts +4 -0
  222. package/dist/core/runner/run-brain-sinks.js +5 -2
  223. package/dist/core/runner/run-harness-handlers.js +29 -36
  224. package/dist/core/runner/run-leg.d.ts +0 -2
  225. package/dist/core/runner/run-leg.js +32 -33
  226. package/dist/core/runner/run-terminal-adoption.js +4 -3
  227. package/dist/core/runner/runtask.js +8 -8
  228. package/dist/core/runner/session-rule-policy.js +5 -5
  229. package/dist/core/runner/stream-settle-backstop.js +7 -4
  230. package/dist/core/runner/sub-agent-deny-lists.d.ts +51 -12
  231. package/dist/core/runner/sub-agent-deny-lists.js +111 -80
  232. package/dist/core/runner/terminal-account.d.ts +48 -0
  233. package/dist/core/runner/terminal-account.js +186 -0
  234. package/dist/core/runner/tool-end-body.d.ts +54 -17
  235. package/dist/core/runner/tool-end-body.js +27 -2
  236. package/dist/core/runner/tool-face-overlay.d.ts +3 -1
  237. package/dist/core/runner/tool-face-overlay.js +6 -4
  238. package/dist/core/runner/tool-occurrence.d.ts +106 -0
  239. package/dist/core/runner/tool-occurrence.js +123 -0
  240. package/dist/core/runner/tool-progress-lane.d.ts +16 -8
  241. package/dist/core/runner/tool-progress-lane.js +25 -34
  242. package/dist/core/runner/tool-turn-repair-seat.d.ts +28 -4
  243. package/dist/core/runner/tool-turn-repair-seat.js +36 -13
  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/secret-env.d.ts +16 -5
  249. package/dist/core/secret-env.js +23 -63
  250. package/dist/core/sensitive-path-policy.d.ts +19 -18
  251. package/dist/core/sensitive-path-policy.js +73 -49
  252. package/dist/core/session-reconcile.d.ts +3 -0
  253. package/dist/core/session-reconcile.js +5 -4
  254. package/dist/core/session-store.d.ts +5 -0
  255. package/dist/core/session-store.js +12 -0
  256. package/dist/core/session.d.ts +13 -0
  257. package/dist/core/shared-memory/normalize.d.ts +17 -4
  258. package/dist/core/shared-memory/normalize.js +7 -7
  259. package/dist/core/shell-lexer.js +5 -4
  260. package/dist/core/shell-wrapper-projection.js +1 -1
  261. package/dist/core/skill-grant.js +1 -1
  262. package/dist/core/store-contracts/checkpoint-store-contract.js +13 -0
  263. package/dist/core/store-contracts/mailbox-store-contract.d.ts +7 -14
  264. package/dist/core/store-contracts/session-store-incarnation-contract.d.ts +27 -0
  265. package/dist/core/store-contracts/session-store-incarnation-contract.js +92 -0
  266. package/dist/core/stub-env.d.ts +2 -0
  267. package/dist/core/stub-env.js +1 -0
  268. package/dist/core/synthetic-read-verdict.js +2 -2
  269. package/dist/core/task-event.d.ts +59 -5
  270. package/dist/core/task-result.d.ts +1 -1
  271. package/dist/core/task-spec.d.ts +42 -9
  272. package/dist/core/terminal-cause.d.ts +94 -11
  273. package/dist/core/tighten-task-spec.d.ts +5 -4
  274. package/dist/core/tighten-task-spec.js +20 -25
  275. package/dist/core/tool-catalog-entries.d.ts +5 -7
  276. package/dist/core/tool-catalog-entries.js +14 -15
  277. package/dist/core/tool-face.d.ts +47 -0
  278. package/dist/core/tool-face.js +5 -0
  279. package/dist/core/tool-model-gate.d.ts +5 -5
  280. package/dist/core/tool-name-aliases.d.ts +26 -2
  281. package/dist/core/tool-name-aliases.js +13 -0
  282. package/dist/core/tool-name-list.d.ts +30 -0
  283. package/dist/core/tool-name-list.js +55 -0
  284. package/dist/core/tool-name-readings.d.ts +1 -9
  285. package/dist/core/tool-name-readings.js +1 -3
  286. package/dist/core/tool-policy.d.ts +195 -85
  287. package/dist/core/tool-policy.js +165 -380
  288. package/dist/core/tool-registry.d.ts +44 -1
  289. package/dist/core/tool-registry.js +26 -0
  290. package/dist/core/tool-roster.d.ts +19 -1
  291. package/dist/core/tool-roster.js +21 -2
  292. package/dist/core/tool-spec-members.d.ts +45 -0
  293. package/dist/core/tool-spec-members.js +169 -0
  294. package/dist/core/tool-spec.d.ts +46 -8
  295. package/dist/core/tools.d.ts +6 -2
  296. package/dist/core/tools.js +8 -4
  297. package/dist/core/untrusted-egress.js +29 -26
  298. package/dist/core/untrusted-text.d.ts +13 -10
  299. package/dist/core/untrusted-text.js +6 -44
  300. package/dist/core/workflow-journal-store.d.ts +4 -1
  301. package/dist/core/write-protect.d.ts +65 -29
  302. package/dist/core/write-protect.js +235 -177
  303. package/dist/engine/compaction/compaction.d.ts +2 -2
  304. package/dist/engine/execution-env/node-execution-env.d.ts +5 -23
  305. package/dist/engine/execution-env/node-execution-env.js +16 -38
  306. package/dist/engine/execution-env/symlink-chain.d.ts +23 -0
  307. package/dist/engine/execution-env/symlink-chain.js +32 -0
  308. package/dist/engine/harness/types.d.ts +7 -0
  309. package/dist/engine/llm/tool-turns.d.ts +3 -0
  310. package/dist/engine/llm/tool-turns.js +1 -0
  311. package/dist/engine/llm/types.d.ts +59 -23
  312. package/dist/engine/loop/agent-loop.js +16 -2
  313. package/dist/engine/session/memory-repo.js +11 -3
  314. package/dist/engine/session/repo-utils.d.ts +8 -0
  315. package/dist/engine/session/repo-utils.js +13 -0
  316. package/dist/index.d.ts +20 -23
  317. package/dist/index.js +17 -20
  318. package/dist/internal/harness.d.ts +1 -1
  319. package/dist/internal/harness.js +1 -1
  320. package/dist/internal/llm.d.ts +2 -2
  321. package/dist/internal/llm.js +1 -1
  322. package/dist/orchestration/governance-baseline-validity.js +1 -1
  323. package/dist/orchestration/run-spec.js +3 -3
  324. package/dist/orchestration/run-workflow-tool.d.ts +16 -35
  325. package/dist/orchestration/run-workflow-tool.js +38 -78
  326. package/dist/orchestration/workflow-governance.d.ts +21 -25
  327. package/dist/orchestration/workflow-governance.js +38 -78
  328. package/dist/orchestration/workflow-primitives.d.ts +7 -22
  329. package/dist/orchestration/workflow-primitives.js +5 -12
  330. package/dist/orchestration/workflow-types.d.ts +1 -1
  331. package/dist/orchestration/workflow.d.ts +61 -11
  332. package/dist/orchestration/workflow.js +189 -117
  333. package/dist/scenarios/full-body.d.ts +1 -1
  334. package/dist/shell/lex.d.ts +0 -21
  335. package/dist/shell/lex.js +250 -68
  336. package/dist/shell/shell-words.d.ts +35 -0
  337. package/dist/shell/shell-words.js +65 -0
  338. package/dist/stores/file/checkpoint-store.d.ts +5 -5
  339. package/dist/stores/file/checkpoint-store.js +5 -2
  340. package/dist/stores/file/index.d.ts +0 -8
  341. package/dist/stores/file/index.js +0 -12
  342. package/dist/stores/file/session-store.d.ts +3 -0
  343. package/dist/stores/file/session-store.js +44 -19
  344. package/dist/tools/artifact/artifact-tool.js +2 -0
  345. package/dist/tools/fs/bash-program-position.d.ts +12 -4
  346. package/dist/tools/fs/bash-program-position.js +32 -9
  347. package/dist/tools/fs/bash-readonly-classifier.d.ts +1 -1
  348. package/dist/tools/fs/bash-readonly-classifier.js +8 -7
  349. package/dist/tools/fs/containment-face.d.ts +4 -0
  350. package/dist/tools/fs/containment-face.js +3 -0
  351. package/dist/tools/fs/fs-shared.d.ts +10 -0
  352. package/dist/tools/fs/fs-shared.js +18 -0
  353. package/dist/tools/fs/fs-write.js +4 -2
  354. package/dist/tools/fs/index.d.ts +1 -1
  355. package/dist/tools/fs/program-read-model.d.ts +46 -20
  356. package/dist/tools/fs/program-read-model.js +50 -20
  357. package/dist/tools/fs/program-read-model.rows.d.ts +0 -14
  358. package/dist/tools/fs/program-read-model.rows.js +16 -15
  359. package/dist/tools/fs/read-deny-home.d.ts +33 -47
  360. package/dist/tools/fs/read-deny-home.js +35 -49
  361. package/dist/tools/fs/read-deny.d.ts +23 -22
  362. package/dist/tools/fs/read-deny.js +114 -89
  363. package/dist/tools/fs/removal-targets.d.ts +56 -23
  364. package/dist/tools/fs/removal-targets.js +65 -87
  365. package/dist/tools/fs/safety.d.ts +29 -22
  366. package/dist/tools/fs/safety.js +17 -11
  367. package/dist/tools/fs/search.js +10 -8
  368. package/dist/tools/fs/shell-read-argv.js +1 -1
  369. package/dist/tools/fs/shell-read-bindings.d.ts +169 -37
  370. package/dist/tools/fs/shell-read-bindings.js +324 -86
  371. package/dist/tools/fs/shell-read-builtins.d.ts +35 -0
  372. package/dist/tools/fs/shell-read-builtins.js +43 -0
  373. package/dist/tools/fs/shell-read-check.d.ts +15 -1
  374. package/dist/tools/fs/shell-read-check.js +67 -43
  375. package/dist/tools/fs/shell-read-establish.js +6 -6
  376. package/dist/tools/fs/shell-read-functions.d.ts +22 -0
  377. package/dist/tools/fs/shell-read-functions.js +29 -0
  378. package/dist/tools/fs/shell-read-judge.d.ts +51 -18
  379. package/dist/tools/fs/shell-read-judge.js +40 -4
  380. package/dist/tools/fs/shell-read-plan.d.ts +12 -6
  381. package/dist/tools/fs/shell-read-plan.js +118 -113
  382. package/dist/tools/fs/shell-read-start.d.ts +29 -6
  383. package/dist/tools/fs/shell-read-start.js +16 -9
  384. package/dist/tools/fs/shell-read-word.js +4 -0
  385. package/dist/tools/fs/shell-read-workdir.d.ts +156 -0
  386. package/dist/tools/fs/shell-read-workdir.js +281 -0
  387. package/dist/tools/fs/shell-read-write-targets.d.ts +5 -2
  388. package/dist/tools/fs/shell-read-write-targets.js +14 -5
  389. package/dist/tools/fs/shell-reentry-text.d.ts +4 -6
  390. package/dist/tools/fs/shell-reentry-text.js +3 -11
  391. package/dist/tools/task-list.d.ts +1 -2
  392. package/dist/tools/web.js +1 -1
  393. package/package.json +4 -1
  394. package/test/export-surface.snapshot.json +107 -143
  395. package/wire-changes/core@7.49.0.json +4765 -0
  396. package/dist/agents/teacher.d.ts +0 -159
  397. package/dist/agents/teacher.js +0 -577
  398. package/dist/agents/team.d.ts +0 -226
  399. package/dist/agents/team.js +0 -257
  400. package/dist/core/strategy-store.d.ts +0 -238
  401. package/dist/core/strategy-store.js +0 -253
  402. package/dist/orchestration/builtin-workflows.d.ts +0 -133
  403. package/dist/orchestration/builtin-workflows.js +0 -159
  404. package/dist/scenarios/env.d.ts +0 -40
  405. package/dist/scenarios/env.js +0 -39
  406. package/dist/scenarios/scenario-registry.d.ts +0 -110
  407. package/dist/scenarios/scenario-registry.js +0 -140
  408. package/dist/scenarios/teacher-quickstart.d.ts +0 -40
  409. package/dist/scenarios/teacher-quickstart.js +0 -12
  410. package/dist/stores/cc/lockfile.d.ts +0 -10
  411. package/dist/stores/cc/lockfile.js +0 -98
  412. package/dist/stores/cc/mailbox-store.d.ts +0 -20
  413. package/dist/stores/cc/mailbox-store.js +0 -255
  414. package/dist/stores/cc/roster-adapter.d.ts +0 -12
  415. package/dist/stores/cc/roster-adapter.js +0 -117
  416. package/dist/stores/cc/sidecar-transcript.d.ts +0 -97
  417. package/dist/stores/cc/sidecar-transcript.js +0 -264
  418. package/dist/stores/cc/task-list-store.d.ts +0 -2
  419. package/dist/stores/cc/task-list-store.js +0 -125
  420. package/dist/stores/file/strategy-store.d.ts +0 -97
  421. package/dist/stores/file/strategy-store.js +0 -341
@@ -0,0 +1,156 @@
1
+ /**
2
+ * THE WORKING-DIRECTORY THREAD — where a command stands at each of its segments, and what `PWD` / `OLDPWD` hold there.
3
+ * ONE walk (`shell-read-plan.ts` drives it, segment by segment, beside the binding thread) over a CLOSED word set that
4
+ * moves the base ({@link BaseShift}): `cd` in its forms — a bare relative target searched through `CDPATH` first, `cd -`
5
+ * going to `OLDPWD`, a bare `cd` to `HOME`, `-P` / `set -P` leaving `PWD` a spelling the text does not hold — `pushd` /
6
+ * `popd` with the stack the text pushed, and a literal `eval` text read as the text it is, in this shell. Any other text
7
+ * that may move the base where the plan cannot follow it (`source`, a non-literal `eval`, a computed program word, a
8
+ * call into a function body or a code body that may move, an option the stack reading does not follow) LOSES it: what
9
+ * stands after it cannot be placed. A move inside a subshell, a pipeline member or a function body nobody called is read
10
+ * as a move too — a candidate SET, more places, never fewer (a move may also fail: the unmoved place stays a candidate
11
+ * unless an `&&` run proves the move ran).
12
+ */
13
+ import type { Bare } from "./shell-read-argv.js";
14
+ import type { BindingTable, WorkingDirectoryState } from "./shell-read-bindings.js";
15
+ import type { Read } from "./shell-read-word.js";
16
+ import { type LexedWord } from "../../shell/lex.js";
17
+ import { type FunctionCall } from "./shell-read-functions.js";
18
+ /** A working directory the shell could be standing in, with the latest move this candidate assumes did NOT run
19
+ * (`skippedCd`), and what the shell holds there: `pwd` — what `PWD` spells (absent: not the base's spelling — a physical
20
+ * move, or a start the plan does not place), `old` — what `OLDPWD` holds (absent: what the shell inherited, unknown),
21
+ * `stack` — the directories the text pushed and has not popped, top first (absent: the text changed the stack in a way
22
+ * this walk does not follow; what lies below the text's own entries is the shell's, unknown). */
23
+ export interface BaseCandidate {
24
+ readonly base: string;
25
+ readonly skippedCd: number;
26
+ readonly pwd?: string;
27
+ readonly old?: string;
28
+ readonly dirStack?: readonly string[];
29
+ }
30
+ /** How one segment moves the base — the closed word set. `cd`: a `cd` (`push`: a `pushd DIR`) to a target, the
31
+ * declared-home spelling of an unsettled target for the deny floor; `swap`: `pushd` with no directory; `pop`: `popd`;
32
+ * `stack`: the stack changes and the base does not (`pushd -n`, `popd -n`, `dirs -c`); `eval`: a literal `eval` text;
33
+ * `lost`: a move this walk does not follow. */
34
+ export type BaseShift = {
35
+ readonly kind: "cd";
36
+ readonly target: Bare | "home" | "previous";
37
+ readonly physical: boolean;
38
+ readonly push?: true;
39
+ } | {
40
+ readonly kind: "swap" | "pop" | "stack" | "lost";
41
+ } | {
42
+ readonly kind: "eval";
43
+ readonly text: string;
44
+ };
45
+ /** What the walk asks of the plan around it: the declared home (a `~` target), whether the text binds a name anywhere
46
+ * (`OLDPWD` — then `cd -` reads the table's value; `PWD` — then a move's `OLDPWD` is not the base the candidate stood
47
+ * in), and where a literal `eval` text started at a candidate ends ({@link WorkdirThread.end}). */
48
+ export interface WorkdirContext {
49
+ readonly homeDir?: string;
50
+ readonly textBinds: (name: string) => boolean;
51
+ readonly evalEnd: (text: string, from: BaseCandidate, table: BindingTable) => {
52
+ readonly end: readonly BaseCandidate[] | "unmodelled";
53
+ readonly physical: boolean;
54
+ };
55
+ }
56
+ /** One segment's move as the walk applies it: the shift, whether an `&&` run proves it ran, the first segment of the
57
+ * reader's `&&` run, the names there, and whether `cdable_vars` may be on (a bare name may be a variable's value). */
58
+ export interface ShiftAt {
59
+ readonly shift: BaseShift;
60
+ readonly provable: boolean;
61
+ readonly andRunStart: number;
62
+ readonly table: CommandTable;
63
+ readonly cdable: boolean;
64
+ }
65
+ /** The names at a `cd` segment with the command's own prefix assignments in force (`HOME=/ cd`), and which names those are. */
66
+ export interface CommandTable extends BindingTable {
67
+ readonly commandSets: ReadonlySet<string>;
68
+ }
69
+ export declare class WorkdirThread {
70
+ /** The start is where the shell stands (not a placeholder a nested plan is re-based from): `PWD` reads it. */
71
+ private readonly readable;
72
+ private candidates;
73
+ private lostAt;
74
+ /** The reachable bases at the moment the walk lost track — the deny floor of a word it cannot place. */
75
+ private floors;
76
+ /** `set -P` (or `-o physical`) may be on — a text it began in, an `eval` text that set it — : a later move leaves `PWD` a physical
77
+ * spelling the text does not hold, and a `..` in a target resolves links the plan cannot see. */
78
+ private physical;
79
+ /** The last segment whose move was applied or lost track ({@link WorkingDirectoryState.movedAt}). */
80
+ private movedAt;
81
+ constructor(start: readonly BaseCandidate[] | readonly string[] | "unmodelled",
82
+ /** The start is where the shell stands (not a placeholder a nested plan is re-based from): `PWD` reads it. */
83
+ readable: boolean,
84
+ /** The physical mode may already be on where the text starts (an `eval` text run in a shell that set it). */
85
+ startsPhysical?: boolean);
86
+ get lost(): boolean;
87
+ get floorBases(): readonly string[] | undefined;
88
+ /** The candidates a reader whose `&&` run starts at `andRunStart` may stand in. */
89
+ reachable(andRunStart: number): readonly BaseCandidate[];
90
+ /** Where the text ends: every candidate, or `unmodelled`. */
91
+ end(): readonly BaseCandidate[] | "unmodelled";
92
+ /** What `PWD` / `OLDPWD` hold for a reader whose `&&` run starts at `andRunStart`. */
93
+ where(andRunStart: number): WorkingDirectoryState;
94
+ /** `set -P` / `set -o physical`: from here on a move's `PWD` is a physical spelling. */
95
+ setPhysical(): void;
96
+ /** Where the text ends the physical mode may be on (an `eval` text hands it back to the shell that ran it). */
97
+ get mayBePhysical(): boolean;
98
+ /** Stop placing anything from segment `at` on: the reachable bases (and a target's floor spellings) become the deny floor. */
99
+ lose(at: number, reachable: readonly BaseCandidate[], floorTargets?: readonly string[]): void;
100
+ /** Apply segment `si`'s move. */
101
+ shift(si: number, at: ShiftAt, ctx: WorkdirContext): void;
102
+ /** Where one candidate goes: the places (the CDPATH entries a bare target is searched through, then the target itself),
103
+ * each with the `PWD`, `OLDPWD` and stack the move leaves — or `lost`. */
104
+ private movedFrom;
105
+ }
106
+ /** Does bash search `CDPATH` for this `cd` target: not an absolute one, not `.` / `..`, not one starting `./` / `../`? */
107
+ export declare function searchesCdPath(dir: string): boolean;
108
+ /** The base shift of a `cd` / `pushd` / `popd` / `dirs` segment, read off its arguments as the program receives them (and
109
+ * the move the plan reports for it: a `cd` target, or `unmodelled` for a stack move it cannot name), or `undefined` for
110
+ * another program. `targetOf` turns the target word into its candidate (and records it as a read where the caller does). */
111
+ export declare function baseShiftOf(program: string, args: readonly Read[], targetOf: (r: Read) => Bare): {
112
+ shift: BaseShift;
113
+ reported?: Bare | "home" | "previous" | "unmodelled";
114
+ } | undefined;
115
+ /** May this text move the base of the shell that runs it: a program of the closed set or one running text in this shell,
116
+ * a computed program word, a call into one of `functions` — or text the lexer cannot read? */
117
+ export declare function textMayMove(text: string, functions: ReadonlySet<string>): boolean;
118
+ /** Does this text turn the physical mode on in the shell that runs it? An `eval` text that does is no text to skip. */
119
+ export declare function textSetsPhysical(text: string): boolean;
120
+ /** The table a `cd` / `pushd` reads `HOME`, `CDPATH` and `OLDPWD` from: the segment's own, with each prefix assignment in
121
+ * front of the builtin (`HOME=/ cd`, `CDPATH=/ cd usr`) holding its value there — it is in the builtin's environment. A
122
+ * prefix value naming an earlier prefix's name (`HOME=/ CDPATH=$HOME cd usr`) reads it as bash 5 does (the earlier
123
+ * assignment applied) and as bash 3.2 does (the value before the command): both. */
124
+ export declare function withCommandEnvironment(table: BindingTable, argv: readonly LexedWord[]): CommandTable;
125
+ /** Does this text call one of `functions` (a program word naming one) — or is it text the lexer cannot read? */
126
+ export declare function textCalls(text: string, functions: ReadonlySet<string>): boolean;
127
+ /** May a segment with these words move the base ({@link textMayMove})? */
128
+ export declare function segmentMayMove(argv: readonly LexedWord[], functions: ReadonlySet<string>): boolean;
129
+ /** What the walk reads of a whole text before it walks it: the text's functions (the names a program word can be one of;
130
+ * whether it IS one at a segment is the binding thread's answer, `callAt`); per segment whether it may move the base
131
+ * ({@link segmentMayMove}), may call a function, runs code bodies later (`trap`, `alias`, …), turns on the physical mode
132
+ * (`set -P`, `set -o physical`); whether a function body may move the base; where `cdable_vars` goes on. */
133
+ export interface TextMoves {
134
+ readonly functions: ReadonlySet<string>;
135
+ /** The names whose bodies the plan has not read (an `eval` text defined them). */
136
+ readonly unread: ReadonlySet<string>;
137
+ readonly mayMove: readonly boolean[];
138
+ /** Segment `si` may call a function (read before the walk, to bound where bodies run). */
139
+ readonly mayCallAt: readonly boolean[];
140
+ /** Segment `si` may run a function body: it may call one, hands a code body to run later, or runs text the plan does not read. */
141
+ readonly runsBodyAt: readonly boolean[];
142
+ readonly bodiesAt: readonly (readonly string[])[];
143
+ readonly physicalAt: readonly boolean[];
144
+ readonly cdableFrom: number;
145
+ readonly bodyMoves: boolean;
146
+ /** The function segment `si`'s program word names where the walk stands (`table`) — {@link functionCallOf}. */
147
+ callAt(si: number, table: BindingTable): FunctionCall | undefined;
148
+ /** The segment may call a function a literal `eval` text defined: its body is not read — it may move the base and bind any name. */
149
+ callsUnread(si: number, table: BindingTable): boolean;
150
+ /** The segment runs a body that may move the base where the walk cannot follow it: a call when a body may move or whose body is not read, a code body that may move or call one. */
151
+ losesBaseAt(si: number, table: BindingTable): boolean;
152
+ }
153
+ export declare function textMovesOf(defined: ReadonlySet<string>, argvs: readonly (readonly LexedWord[])[], inFunctionBody: (si: number) => boolean, inherited?: {
154
+ readonly functions: ReadonlySet<string>;
155
+ readonly unread: ReadonlySet<string>;
156
+ }): TextMoves;
@@ -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
  }
@@ -120,13 +120,14 @@ export interface LaunchedSpelling {
120
120
  * characters escaped and its pattern characters bare ({@link launchedSpellingOf}). A word whose field the reader does not
121
121
  * know is handed AS WRITTEN: the launched shell re-reads the expansion with the command line's quoting, so the word stays
122
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. One argv, as a list of the one.
123
+ * word's text as `spell.word` spells it.
124
124
  */
125
- 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[];
126
126
  /** The argv index of the SCRIPT FILE a shell runs where its argv carries no text ({@link scriptSourceOf}). */
127
127
  export declare function scriptFileAt(basename: string, args: readonly string[]): number | undefined;
128
128
  /** One text that may arrive on a segment's standard input: `from` = its source as written (a here-document's body,
129
- * `<<<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. */
130
131
  export interface StdinText {
131
132
  readonly from: string;
132
133
  readonly literal?: string;
@@ -137,6 +138,3 @@ export interface StdinText {
137
138
  * pipe or the input of the group it stands in, the input of the shell running its text) unless one of those three
138
139
  * replaces it. */
139
140
  export declare function stdinTextsOf(segment: LexedSegment, fed: readonly StdinText[]): StdinText[];
140
- /** What one segment (its argv) writes into the pipe after it: the text a printer spells ({@link printedText}) when its
141
- * program word and every argument are literal, else only the segment as written. */
142
- export declare function pipedTextOf(segment: LexedSegment, argv: readonly LexedWord[]): 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 { implementationRejects, implementationsOf, printedText, programRow, readArgRoles, selectedOptions, targetUserOf } 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);
@@ -167,8 +167,7 @@ export function launchedInput(argv, pos, spell) {
167
167
  if (line === undefined && c.program !== undefined && "at" in c.program && c.program.from === undefined)
168
168
  programWords.push(c.program.at);
169
169
  const words = c.args.map((x) => ("at" in x && x.from === undefined ? x.at : undefined));
170
- const args = asArgs(c.args);
171
- return asTexts(c.args).map((texts, i) => ({ shell, texts, args: args[i], words, ...(c.as !== undefined ? { as: c.as } : {}) }));
170
+ return [{ shell, texts: asTexts(c.args), args: asArgs(c.args), words, ...(c.as !== undefined ? { as: c.as } : {}) }];
172
171
  });
173
172
  return { shells, programWords, lines: [...lines] };
174
173
  }
@@ -186,7 +185,7 @@ export function spellLaunched(argv, args, spell) {
186
185
  const values = spell.values?.(k);
187
186
  return values?.length === 1 ? launchedSpellingOf(values[0]) : argv[k].raw;
188
187
  };
189
- 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(" ")))];
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(" ")));
190
189
  }
191
190
  export function scriptFileAt(basename, args) {
192
191
  const row = programRow(basename);
@@ -219,10 +218,3 @@ export function stdinTextsOf(segment, fed) {
219
218
  }
220
219
  return replacesPipe ? out : [...fed, ...out];
221
220
  }
222
- export function pipedTextOf(segment, argv) {
223
- const from = `${segment.text.trim()} |`;
224
- const pos = readProgramPosition(argv);
225
- const program = pos.program;
226
- 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)));
227
- return literal === undefined ? { from } : { from, literal };
228
- }
@@ -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.48.0",
3
+ "version": "7.49.1",
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",