@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
@@ -1,12 +1,15 @@
1
1
  import { lexShell, PARSE_FAILURE_SENTENCE, substitutionsInHeredocBody, literalTextOf, literalTildeSpelling, } from "../../shell/lex.js";
2
- import { programTextOf, readOfText, readsOf, renamed, rewritten, settledFieldsOf, spelledWithHome, isArithmeticBody, unreadableSentenceOf } from "./shell-read-word.js";
2
+ import { programTextOf, readOfText, readsOf, rewritten, segmentReadingsOf, settledFieldsOf, spelledWithHome, isArithmeticBody, unreadableSentenceOf } from "./shell-read-word.js";
3
3
  import { assignmentArithmetic, bare, listedVerbCandidates, pathSubcommandOf, programTextSentence, pushAssignment, roleReads, subscriptOnly, unlistedWords } from "./shell-read-argv.js";
4
- import { ARITHMETIC_TEST_OPERATORS, BindingThread, arithmeticSubstitutions, isArithmeticCommand, bindingEffectOf, parameterBodySubstitutions, projectSegment, valueOf, } from "./shell-read-bindings.js";
5
- import { programBasename, programPositionRunsShell, readProgramPosition, shellScanDeclineOf, } from "./bash-program-position.js";
4
+ import { ARITHMETIC_TEST_OPERATORS, BindingThread, arithmeticSubstitutions, isArithmeticCommand, bindingEffectOf, joinRebound, loopListHeadAt, namesBoundIn, parameterBodySubstitutions, projectSegment, valueOf, } from "./shell-read-bindings.js";
5
+ import { commandEnvironmentNames, isShellSyntaxWord, programBasename, programPositionRunsShell, readProgramPosition, shellScanDeclineOf, } from "./bash-program-position.js";
6
+ import { WorkdirThread, baseShiftOf, textCalls, textMayMove, textMovesOf, textSetsPhysical, withCommandEnvironment } from "./shell-read-workdir.js";
6
7
  import { POLL_LOOP_MAX_BEATS, attachedOptionPayloads, resolveOperandLexically, isPathShapedToken, programTextSlotFiles, } from "./bash-readonly-classifier.js";
7
- import { BLOCK_WORD_NAMES, commandLineOptionSpellings, declaredAttributes, isDeclarationBuiltin, isInertBuiltin, launcherOptionPathRole, launcherOptionStep, readOptionRole, programLanguageOf, programTextOpensOf, selectedOptions, movesBaseUnfollowed, opensNoOperand, programDelivery, programRow, readArgRoles, runsShellText, } from "./program-read-model.js";
8
- import { isAbsolutePathForm } from "./safety.js";
9
- import { codeBodies, launchedInput, pipedTextOf, reentryText, scriptFileAt, stdinTextsOf } from "./shell-reentry-text.js";
8
+ import { BLOCK_WORD_NAMES, commandLineOf, commandLineOptionSpellings, declaredAttributes, isDeclarationBuiltin, isInertBuiltin, launcherOptionPathRole, launcherOptionStep, readOptionRole, programLanguageOf, programTextOpensOf, selectedOptions, movesBaseByStack, opensNoOperand, programDelivery, programRow, readArgRoles, runsShellText, } from "./program-read-model.js";
9
+ import { shellWordsOf } from "../../shell/shell-words.js";
10
+ import { isAbsoluteForFamily } from "./safety.js";
11
+ import { codeBodies, launchedInput, reentryText, scriptFileAt, stdinTextsOf } from "./shell-reentry-text.js";
12
+ import { heldAt, plannedOnce, rebasePlan, startedAt, stdinFeeds } from "./shell-read-start.js";
10
13
  export const READ_CANDIDATE_PROVENANCES = Object.freeze([
11
14
  "operand",
12
15
  "option_value",
@@ -22,21 +25,26 @@ export const READ_CANDIDATE_PROVENANCES = Object.freeze([
22
25
  "object_path",
23
26
  ]);
24
27
  const NESTING_MAX = 4;
25
- const BASE_CANDIDATE_MAX = 256;
28
+ const LOOP_END = shellWordsOf("loop_end"), LOOP_CONDITION = shellWordsOf("loop_condition"), COPROC = shellWordsOf("background"), RESERVED = shellWordsOf("rule_reserved");
26
29
  export function planShellReads(command, decl, depth = 0, start) {
30
+ return planText(command, decl, depth, start).plan;
31
+ }
32
+ function planText(command, decl, depth, start, from) {
27
33
  const shape = { grouped: false, backgrounded: false, strayRedirection: false };
28
34
  if (depth > NESTING_MAX)
29
- return { segments: [], unreadable: `command text nested more than ${NESTING_MAX} levels deep`, shape };
35
+ return { plan: { segments: [], unreadable: `command text nested more than ${NESTING_MAX} levels deep`, shape }, end: "unmodelled", physical: false };
30
36
  const lexed = lexShell(command);
31
37
  if ("parseFailure" in lexed)
32
- return { segments: [], unreadable: PARSE_FAILURE_SENTENCE[lexed.parseFailure.reason], shape };
38
+ return { plan: { segments: [], unreadable: PARSE_FAILURE_SENTENCE[lexed.parseFailure.reason], shape }, end: "unmodelled", physical: false };
33
39
  const unreadable = unreadableSentenceOf(lexed, command);
34
40
  const projected = lexed.segments.map((segment) => projectSegment(segment));
35
41
  const named = projected.map((p, si) => bindingEffectOf(lexed.segments[si], p.argv, p, () => "unknown"));
36
42
  const boundHere = (name) => named.some((e) => e.all === "unknown" || e.bindings.some((b) => b.name === name));
37
43
  const boundAnywhere = (name) => boundHere(name) || start?.boundAnywhere(name) === true;
38
44
  const declaredHome = decl.homeDir !== undefined ? [{ spelled: decl.homeDir }] : "unknown";
39
- const initial = start?.initial ?? ((name) => (name === "HOME" ? declaredHome : "unknown"));
45
+ const declaredCdPath = decl.cdPath === "unknown" ? "unknown" : [{ spelled: (decl.cdPath ?? []).join(":") }];
46
+ const declared = (name, rebound) => (rebound ? "unknown" : name === "HOME" ? declaredHome : name === "CDPATH" ? declaredCdPath : "unknown");
47
+ const initial = start?.initial ?? ((name) => declared(name, false));
40
48
  const loopShapes = projected.map((p) => loopShapeOf(p));
41
49
  const loopEndOf = new Map();
42
50
  {
@@ -51,26 +59,35 @@ export function planShellReads(command, decl, depth = 0, start) {
51
59
  }
52
60
  });
53
61
  }
54
- const names = new BindingThread(lexed.segments, named, initial, boundAnywhere, loopEndOf, start?.homeTouched === true, start?.inherited);
55
- const laterStart = { initial: (name) => (name === "HOME" && !boundAnywhere("HOME") ? declaredHome : "unknown"), boundAnywhere, homeTouched: boundAnywhere("HOME"), inherited: names.inheritedAt() };
56
- const nestedPlanner = (table) => (text, kind) => planShellReads(text, decl, depth + 1, kind === "substitution" ? { initial: (name) => table.stateOf(name), boundAnywhere, homeTouched: table.homeTouched, inherited: table.inherited } : laterStart);
62
+ const names = new BindingThread(lexed.segments, named, initial, boundAnywhere, loopEndOf, start?.homeTouched === true, start?.inherited, start?.names);
63
+ const laterStart = { initial: (name) => declared(name, boundAnywhere(name)), boundAnywhere, homeTouched: boundAnywhere("HOME"), inherited: names.inheritedAt() };
64
+ const nestedPlanner = (table, si) => (text, kind, at) => planShellReads(text, decl, depth + 1, kind === "substitution" ? { initial: (name) => table.stateOf(name), boundAnywhere, homeTouched: table.homeTouched, inherited: table.inherited, thread: heldThread(moves.functions), names: heldAt(table) } : startedAt(kind === "now" ? { ...laterStart, inherited: { ...laterStart.inherited, rebound: joinRebound(table.inherited.rebound, commandEnvironmentNames(projected[si].argv)) }, ...(readProgramPosition(projected[si].argv).program?.basename === "eval" ? { thread: heldThread(moves.unread), names: heldAt(table, names.functionBound()) } : {}) } : { ...laterStart, thread: heldThread(moves.functions, workdir.mayBePhysical || moves.physicalAt.some(Boolean)), names: names.heldAnywhere() }, at));
57
65
  const empty = lexed.segments.map((segment, si) => segmentIsEmpty(segment, projected[si]));
58
66
  const facts = projected.map(() => undefined);
59
67
  const tables = projected.map(() => undefined);
68
+ const fedAt = stdinFeeds(lexed.segments, start?.stdin ?? [], (si) => [{ from: `${lexed.segments[si - 1].text.trim()} |` }]);
60
69
  const factsAt = (si, table) => {
61
70
  tables[si] ??= table;
62
- const piped = si > 0 && lexed.segments[si].connector === "|" ? pipedTextOf(lexed.segments[si - 1], projected[si - 1].argv) : undefined;
63
- return (facts[si] ??= segmentFacts(lexed.segments[si], projected[si], decl, table, nestedPlanner(table), piped));
71
+ return (facts[si] ??= segmentFacts(lexed.segments[si], projected[si], decl, table, nestedPlanner(table, si), fedAt(si)));
64
72
  };
65
73
  const basesOf = projected.map(() => new Set());
66
74
  const unmodelled = projected.map(() => false);
67
- let candidates = [{ base: decl.cwd, skippedCd: -1 }];
68
- let baseLost = false;
69
- let floorBases;
70
- const loseBase = (reachable, floorTarget) => {
71
- baseLost = true;
72
- floorBases ??= [...new Set([...reachable.map((c) => c.base), ...(floorTarget !== undefined ? [floorTarget] : [])])];
75
+ const moves = textMovesOf(new Set(projected.flatMap((p) => p.defines)), projected.map((p) => p.argv), (si) => names.inFunctionBody(si), start?.thread);
76
+ names.runsBodies(moves.runsBodyAt, moves.bodiesAt.some((b) => b.length > 0), moves.mayCallAt.map((c, si) => (c ? commandEnvironmentNames(projected[si].argv) : undefined)));
77
+ const workdir = new WorkdirThread(from ?? start?.bases ?? [decl.cwd], depth === 0 || start?.bases !== undefined || from !== undefined, start?.thread?.physical === true);
78
+ const workdirContext = {
79
+ ...(decl.homeDir !== undefined ? { homeDir: decl.homeDir } : {}),
80
+ textBinds: boundAnywhere,
81
+ evalEnd: (text, c, table) => {
82
+ if (moves.bodyMoves && textCalls(text, moves.functions))
83
+ return { end: "unmodelled", physical: false };
84
+ if (!textMayMove(text, moves.functions) && !textSetsPhysical(text))
85
+ return { end: [c], physical: false };
86
+ const ran = planText(text, decl, depth + 1, { initial: (name) => table.stateOf(name), boundAnywhere, homeTouched: table.homeTouched, inherited: table.inherited, thread: heldThread(moves.unread), names: heldAt(table, names.functionBound()) }, [c]);
87
+ return { end: ran.end, physical: ran.physical };
88
+ },
73
89
  };
90
+ const heldThread = (unread, physical = workdir.mayBePhysical) => ({ physical, functions: moves.functions, unread });
74
91
  let andRunStart = 0;
75
92
  let crossedAllAnd = true;
76
93
  let crossedAnyOr = false;
@@ -87,55 +104,28 @@ export function planShellReads(command, decl, depth = 0, start) {
87
104
  }
88
105
  if (empty[si]) {
89
106
  if (!replay)
90
- factsAt(si, names.tableAt(si, andRunStart));
107
+ factsAt(si, names.tableAt(si, andRunStart, workdir.where(andRunStart)));
91
108
  return;
92
109
  }
93
110
  if (previousEmitted >= 0 && !crossedAllAnd)
94
111
  andRunStart = crossedAnyOr ? si + 1 : si;
95
- const f = replay ? facts[si] : factsAt(si, names.tableAt(si, andRunStart));
96
- const pipeFed = f.connector === "|" || lexed.segments[si + 1]?.connector === "|";
97
- reaches[si] ??= { andJoined: previousEmitted >= 0 && crossedAllAnd, orBroken: !crossedAllAnd && crossedAnyOr, moveProvable: f.moveProvable && !replay && !pipeFed };
112
+ const f = replay ? facts[si] : factsAt(si, names.tableAt(si, andRunStart, workdir.where(andRunStart)));
113
+ const pipeFed = f.connector === "|" || lexed.segments[si + 1]?.connector === "|", call = moves.callAt(si, tables[si]);
114
+ reaches[si] ??= { andJoined: previousEmitted >= 0 && crossedAllAnd, orBroken: !crossedAllAnd && crossedAnyOr, moveProvable: f.moveProvable && !replay && !pipeFed && !names.runsApart(si) };
98
115
  crossedAllAnd = true;
99
116
  crossedAnyOr = false;
100
117
  previousEmitted = si;
101
- const reachable = candidates.filter((c) => c.skippedCd < andRunStart);
102
- if (baseLost)
118
+ if (workdir.lost)
103
119
  unmodelled[si] = true;
104
120
  else
105
- for (const c of reachable)
121
+ for (const c of workdir.reachable(andRunStart))
106
122
  basesOf[si].add(c.base);
107
- const move = f.baseMove;
108
- if (move === undefined || baseLost)
109
- return;
110
- if (typeof move.target === "string" || move.target.expands !== false) {
111
- loseBase(reachable, typeof move.target !== "string" ? move.target.floorSpelled : move.target === "home" ? decl.homeDir : undefined);
112
- return;
113
- }
114
- const target = move.target.spelled;
115
- const provable = reaches[si].moveProvable;
116
- const branched = [];
117
- for (const c of candidates) {
118
- if (c.skippedCd < andRunStart) {
119
- const moved = joinBase(c.base, target, decl.homeDir);
120
- if (moved === undefined) {
121
- loseBase(reachable);
122
- return;
123
- }
124
- branched.push({ base: moved, skippedCd: c.skippedCd });
125
- }
126
- branched.push({ base: c.base, skippedCd: provable ? si : c.skippedCd });
127
- }
128
- const byBase = new Map();
129
- for (const c of branched) {
130
- const prior = byBase.get(c.base);
131
- if (prior === undefined || c.skippedCd < prior.skippedCd)
132
- byBase.set(c.base, c);
133
- }
134
- const next = [...byBase.values()];
135
- if (next.length > BASE_CANDIDATE_MAX)
136
- loseBase(reachable);
137
- else
138
- candidates = next;
123
+ if (moves.physicalAt[si])
124
+ workdir.setPhysical();
125
+ if (f.shift !== undefined && call !== "named")
126
+ workdir.shift(si, { shift: f.shift, provable: reaches[si].moveProvable && call === undefined, andRunStart, table: withCommandEnvironment(tables[si], projected[si].argv), cdable: moves.cdableFrom >= 0 && si > moves.cdableFrom }, workdirContext);
127
+ if (moves.losesBaseAt(si, tables[si]))
128
+ workdir.lose(si, workdir.reachable(andRunStart));
139
129
  };
140
130
  const bind = (si) => {
141
131
  const table = tables[si];
@@ -144,12 +134,16 @@ export function planShellReads(command, decl, depth = 0, start) {
144
134
  const end = loopEndOf.get(si);
145
135
  if (end !== undefined) {
146
136
  const body = named.slice(si + 1, end);
147
- names.kill(si, body.some((e) => e.all === "unknown") ? "all" : body.flatMap((e) => e.bindings.map((b) => b.name)));
137
+ names.kill(si, body.some((e) => e.all === "unknown") ? "all" : [...body.flatMap((e) => e.bindings.map((b) => b.name)), ...(moves.mayMove.slice(si + 1, end).some(Boolean) ? ["PWD", "OLDPWD"] : [])]);
148
138
  }
149
139
  const segment = lexed.segments[si];
150
- const effect = bindingEffectOf(segment, projected[si].argv, projected[si], (w, quoted, overlay) => valueOf(w, table, quoted, overlay));
140
+ const effect = bindingEffectOf(segment, projected[si].argv, projected[si], (w, quoted, overlay) => valueOf(w, table, quoted, overlay), moves.callAt(si, table), (builtin) => table.builtinState(builtin));
151
141
  const { all, ...rest } = effect;
152
142
  names.apply(si, all === "reset" ? rest : effect, segment.connector === "&&" || segment.connector === "||", end);
143
+ if (moves.callAt(si, table) !== undefined)
144
+ names.kill(si, moves.callsUnread(si, table) ? "all" : names.functionBound());
145
+ if (moves.bodiesAt[si].length > 0)
146
+ names.runsLater(si, moves.bodiesAt[si].reduce((held, b) => joinRebound(held, namesBoundIn(b)), names.functionBound()));
153
147
  };
154
148
  for (let si = 0; si < projected.length; si++) {
155
149
  const shapeOfLoop = loopShapes[si];
@@ -166,58 +160,65 @@ export function planShellReads(command, decl, depth = 0, start) {
166
160
  const frame = loops.pop();
167
161
  if (frame === undefined)
168
162
  continue;
169
- const body = facts.slice(frame.bodyStart, si);
170
- const moves = body.some((b) => b?.baseMove !== undefined);
171
- if (!moves)
163
+ if (!facts.slice(frame.bodyStart, si).some((b, k) => b?.shift !== undefined || (tables[frame.bodyStart + k] !== undefined && moves.losesBaseAt(frame.bodyStart + k, tables[frame.bodyStart + k]))))
172
164
  continue;
173
165
  if (frame.beats === undefined) {
174
166
  for (let k = frame.bodyStart; k < si; k++)
175
167
  unmodelled[k] = true;
176
- loseBase(candidates.filter((c) => c.skippedCd < andRunStart));
168
+ workdir.lose(si, workdir.reachable(andRunStart));
177
169
  continue;
178
170
  }
179
- for (let beat = 1; beat < frame.beats && !baseLost; beat++) {
171
+ for (let beat = 1; beat < frame.beats && !workdir.lost; beat++) {
180
172
  for (let k = frame.bodyStart; k < si; k++)
181
173
  thread(k, true);
182
174
  }
183
175
  }
184
176
  const planned = facts.map((f) => f);
185
- const inert = depth === 0 && unreadable === undefined && planned.every(segmentOpensNothing);
186
- const settled = inert ? planned.map((f) => ({ ...f, reads: f.reads.filter((c) => c.provenance !== "env_assignment") })) : planned;
177
+ const inert = depth === 0 && unreadable === undefined && planned.every((f) => (f.readings ?? [f]).every(segmentOpensNothing));
178
+ const settled = inert ? planned.map((f) => ({ ...f, reads: f.reads.filter((c) => c.provenance !== "env_assignment"), ...(f.readings !== undefined ? { readings: f.readings.map((g) => ({ ...g, reads: g.reads.filter((c) => c.provenance !== "env_assignment") })) } : {}) })) : planned;
187
179
  shape.grouped = projected.some((p) => p.grouped);
188
- shape.backgrounded = lexed.segments.some((s) => s.connector === "&") || settled.some((f) => f.backgrounds === true);
180
+ shape.backgrounded = lexed.segments.some((s) => s.connector === "&") || settled.some((f) => (f.readings ?? [f]).some((g) => g.backgrounds === true));
189
181
  shape.strayRedirection = projected.some((p) => p.argv.length === 0 && p.redirects.length > 0);
190
182
  const segments = [];
191
183
  for (let si = 0; si < settled.length; si++) {
192
- const f = settled[si];
193
- if (f.empty)
184
+ const threaded = settled[si];
185
+ if (threaded.empty)
194
186
  continue;
195
187
  const bases = unmodelled[si] ? "unmodelled" : [...basesOf[si]];
188
+ const floorBases = workdir.floorBases;
196
189
  const floor = unmodelled[si] && floorBases !== undefined && floorBases.length > 0 ? floorBases : undefined;
197
- const withBases = (c) => {
190
+ const placedAt = (at, atFloor) => (c) => {
198
191
  const relative = relativeSpelling(c.spelled);
199
- const here = c.provenance === "object_path" && bases !== "unmodelled" ? [...new Set(bases.flatMap(ancestorsOf))] : bases;
200
- return { ...c, bases: relative ? here : [], ...(relative && floor !== undefined ? { floorBases: floor } : {}) };
192
+ const here = c.provenance === "object_path" && at !== "unmodelled" ? [...new Set(at.flatMap(ancestorsOf))] : at;
193
+ return { ...c, bases: relative ? here : [], ...(relative && atFloor !== undefined ? { floorBases: atFloor } : {}) };
201
194
  };
202
- segments.push({
203
- text: f.text,
204
- connector: f.connector,
205
- argv: f.argv,
206
- launcherChain: f.launcherChain,
207
- ...(f.verb !== undefined ? { verb: f.verb } : {}),
208
- ...(f.reentry !== undefined ? { reentry: f.reentry } : {}),
209
- ...(f.unreadProgramText !== undefined ? { unreadProgramText: f.unreadProgramText } : {}),
210
- ...(f.stdin !== undefined ? { stdin: f.stdin } : {}),
211
- declines: f.declines,
212
- reads: dedupe(f.reads).map(withBases),
213
- redirects: f.redirects.map((r) => (r.target === undefined ? { op: r.op, direction: r.direction } : { op: r.op, direction: r.direction, target: withBases(r.target) })),
214
- ...(f.baseMove !== undefined ? { baseMove: { target: typeof f.baseMove.target === "string" ? f.baseMove.target : withBases(f.baseMove.target) } } : {}),
215
- bases,
216
- nested: f.nested.map((n) => rebasePlan(n, decl.cwd, bases)),
217
- reach: reaches[si] ?? { andJoined: false, orBroken: false, moveProvable: false },
218
- });
195
+ const withBases = placedAt(bases, floor);
196
+ const move = threaded.baseMove;
197
+ for (const f of threaded.readings ?? [threaded]) {
198
+ const moved = readProgramPosition(f.argv).launcherMovesBase;
199
+ const programPlaced = moved ? placedAt("unmodelled", bases !== "unmodelled" ? bases : floor) : withBases;
200
+ const programRead = (c) => (c.provenance === "stdin_redirect" ? withBases(c) : programPlaced(c));
201
+ segments.push({
202
+ text: f.text,
203
+ connector: f.connector,
204
+ argv: f.argv,
205
+ launcherChain: f.launcherChain,
206
+ ...(f.verb !== undefined ? { verb: f.verb } : {}),
207
+ ...(f.reentry !== undefined ? { reentry: f.reentry } : {}),
208
+ ...(f.unreadProgramText !== undefined ? { unreadProgramText: f.unreadProgramText } : {}),
209
+ ...(f.stdin !== undefined ? { stdin: f.stdin } : {}),
210
+ declines: f.declines,
211
+ reads: dedupe(f.reads).map(programRead),
212
+ redirects: f.redirects.map((r) => (r.target === undefined ? { op: r.op, direction: r.direction } : { op: r.op, direction: r.direction, target: withBases(r.target) })),
213
+ ...(move !== undefined ? { baseMove: { target: typeof move.target === "string" ? move.target : withBases(move.target) } } : {}),
214
+ bases,
215
+ nested: f.nested.map((n) => (f.elsewhere?.has(n) === true ? n : rebasePlan(n, decl.cwd, moved && f.shellSide?.has(n) !== true ? "unmodelled" : bases, bases === "unmodelled" ? floor : bases))),
216
+ reach: reaches[si] ?? { andJoined: false, orBroken: false, moveProvable: false },
217
+ rebound: tables[si]?.rebound ?? "all",
218
+ });
219
+ }
219
220
  }
220
- return { segments, shape, ...(unreadable !== undefined ? { unreadable } : {}) };
221
+ return { plan: { segments, shape, ...(unreadable !== undefined ? { unreadable } : {}) }, end: workdir.end(), physical: workdir.mayBePhysical };
221
222
  }
222
223
  function ancestorsOf(dir) {
223
224
  const out = [dir];
@@ -229,15 +230,14 @@ function parentOf(dir) {
229
230
  return resolveOperandLexically(dir, "..", undefined) ?? dir;
230
231
  }
231
232
  function loopShapeOf(p) {
232
- const head = p.argv[0];
233
- if (head === undefined)
233
+ if (p.argv[0] === undefined)
234
234
  return undefined;
235
- if (head.raw === head.folded && (head.folded === "for" || head.folded === "select") && BLOCK_WORD_NAMES.has(head.folded))
235
+ if (loopListHeadAt(p.argv) !== undefined)
236
236
  return "head";
237
- if (head.raw === head.folded && head.folded === "done" && BLOCK_WORD_NAMES.has(head.folded))
237
+ if (isShellSyntaxWord(p.argv[0], LOOP_END))
238
238
  return "end";
239
239
  const pos = readProgramPosition(p.argv);
240
- return pos.controlWords.some((i) => p.argv[i].folded === "while" || p.argv[i].folded === "until") ? "head" : undefined;
240
+ return pos.controlWords.some((i) => LOOP_CONDITION.has(p.argv[i].folded)) ? "head" : undefined;
241
241
  }
242
242
  function segmentIsEmpty(segment, p) {
243
243
  if (p.argv.length > 0 || p.redirects.length > 0 || segment.substitutions.length > 0)
@@ -252,8 +252,29 @@ function segmentOpensNothing(f) {
252
252
  const inertProgram = program === undefined || (program.name === program.basename && isInertBuiltin(program.basename) && !(isDeclarationBuiltin(program.basename) && f.argv.slice(at + 1).some((w) => /^[-+]/.test(w.folded))));
253
253
  return inertProgram && f.argv.every((w) => !/[[\]$`]/.test(w.raw)) && f.nested.length === 0 && f.reentry === undefined && f.declines.length === 0 && f.launcherChain.length === 0 && f.redirects.every((r) => r.direction !== "in") && f.reads.every((c) => c.provenance === "env_assignment");
254
254
  }
255
- function segmentFacts(segment, p, decl, table, nestedPlan, piped) {
256
- const facts = segmentFactsRead(segment, p, decl, table, nestedPlan, piped);
255
+ function segmentFacts(segment, p, decl, table, nestedPlan, fed) {
256
+ const targets = p.redirects.flatMap((r) => (r.target === undefined ? [] : [r.target]));
257
+ const readings = segmentReadingsOf(p.argv, targets, table, decl.homeDir);
258
+ if (readings.length === 1)
259
+ return readingFacts(segment, { ...p, argv: readings[0].argv }, decl, readings[0], nestedPlan, fed);
260
+ const once = plannedOnce(nestedPlan);
261
+ return readInSeveral(readings.map((reading) => readingFacts(segment, { ...p, argv: reading.argv }, decl, reading, once, fed)));
262
+ }
263
+ function readInSeveral(each) {
264
+ const first = each[0];
265
+ const move = each.find((f) => f.baseMove !== undefined)?.baseMove;
266
+ return {
267
+ ...first,
268
+ moveProvable: false,
269
+ ...(move !== undefined ? { baseMove: { target: typeof move.target === "string" ? move.target : { ...move.target, expands: "unresolvable" } } } : {}),
270
+ ...(each.some((f) => f.shift !== undefined) ? { shift: { kind: "lost" } } : {}),
271
+ readings: each.flatMap((f) => f.readings ?? [f]),
272
+ };
273
+ }
274
+ function readingFacts(segment, p, decl, reading, nestedPlan, fed) {
275
+ const table = reading.table;
276
+ const planner = (text, kind, at) => nestedPlan(text, kind, kind !== "substitution" ? { ...at, floors: reading.floors } : at);
277
+ const facts = segmentFactsRead(segment, p, decl, table, planner, fed, reading.reads);
257
278
  const unresolvedRaw = new Set();
258
279
  for (const t of segment.tokens) {
259
280
  const w = t.kind === "word" ? t : t.kind === "redirect" ? t.target : undefined;
@@ -269,20 +290,23 @@ function segmentFacts(segment, p, decl, table, nestedPlan, piped) {
269
290
  };
270
291
  const unsettle = (c) => floor((unresolvedRaw.has(c.raw) || (homeWithheld && c.spelled.startsWith("~"))) && c.expands !== "unresolvable" ? { ...c, expands: "unresolvable" } : c);
271
292
  const each = (c) => {
272
- const { alternatives, floors, ...one } = c;
273
- const shadows = (floors ?? []).map((v) => ({ spelled: v.spelled, raw: one.raw, provenance: one.provenance, expands: v.glob === true ? "glob" : false, denyOnly: true }));
274
- return [...[one, ...(alternatives ?? []).map((a) => ({ ...renamed(one, a.spelled), ...a }))].map(unsettle), ...shadows];
293
+ const { floors, ...one } = c;
294
+ const shadows = (floors ?? []).map((v) => ({ spelled: v.spelled, ...(v.pattern !== undefined ? { pattern: v.pattern } : {}), raw: one.raw, provenance: one.provenance, expands: v.glob === true ? "glob" : false, denyOnly: true }));
295
+ return [unsettle(one), ...shadows];
275
296
  };
276
297
  const move = facts.baseMove;
298
+ const shift = facts.shift;
277
299
  return {
278
300
  ...facts,
279
301
  reads: facts.reads.flatMap(each),
280
302
  redirects: facts.redirects.map((r) => (r.target === undefined ? r : { ...r, target: unsettle(r.target) })),
281
- ...(move !== undefined && typeof move.target !== "string" ? { baseMove: { target: unsettle(move.target.alternatives !== undefined ? { ...each(move.target)[0], expands: "unresolvable" } : move.target) } } : {}),
303
+ ...(move !== undefined && typeof move.target !== "string" ? { baseMove: { target: unsettle(move.target) } } : {}),
304
+ ...(shift?.kind === "cd" && typeof shift.target !== "string" ? { shift: { ...shift, target: unsettle(shift.target) } } : {}),
282
305
  };
283
306
  }
284
- function segmentFactsRead(segment, p, decl, table, nestedPlan, piped) {
307
+ function segmentFactsRead(segment, p, decl, table, nestedPlan, fed, toks) {
285
308
  const nested = [];
309
+ const elsewhere = new Set();
286
310
  const ctx = { table, reentered: [], programTextSeen: false };
287
311
  const arithmetic = segment.tokens.flatMap((t) => (t.kind === "word" ? t : t.kind === "redirect" ? t.target : undefined)?.pieces ?? []).flatMap((q) => (q.expansion?.kind === "arithmetic" && q.expansion.body !== undefined && isArithmeticBody(q.expansion.body) ? [q.expansion.body] : []));
288
312
  const count = (list, body) => list.filter((b) => b === body).length;
@@ -319,6 +343,7 @@ function segmentFactsRead(segment, p, decl, table, nestedPlan, piped) {
319
343
  }
320
344
  if (unreadableHeredoc)
321
345
  nested.push({ segments: [], unreadable: "a here-document body carries a substitution this lexer cannot delimit", shape: { grouped: false, backgrounded: false, strayRedirection: false } });
346
+ const shellSide = new Set(nested);
322
347
  if (isArithmeticCommand(segment))
323
348
  ctx.reentered.push(...arithmeticSubstitutions(p.argv.map((w) => w.folded).join(" "), table));
324
349
  for (const t of segment.tokens) {
@@ -339,33 +364,38 @@ function segmentFactsRead(segment, p, decl, table, nestedPlan, piped) {
339
364
  redirects,
340
365
  nested,
341
366
  };
342
- const toks = readsOf(p.argv, table, decl.homeDir);
343
367
  const done = (f) => {
344
368
  const reentered = [...new Set(ctx.reentered)];
345
- for (const body of reentered)
346
- nested.push(nestedPlan(body, "later"));
369
+ for (const body of reentered) {
370
+ const plan = nestedPlan(body, "later");
371
+ nested.push(plan);
372
+ shellSide.add(plan);
373
+ }
347
374
  return {
348
375
  ...base,
349
376
  ...f,
350
377
  ...(reentered.length > 0 ? { reentry: "shell" } : {}),
351
378
  ...(f.unreadProgramText === undefined && ctx.programText !== undefined ? { unreadProgramText: ctx.programText } : {}),
379
+ ...(elsewhere.size > 0 ? { elsewhere } : {}),
380
+ ...(shellSide.size > 0 ? { shellSide } : {}),
352
381
  };
353
382
  };
354
383
  const head = toks[0]?.folded;
355
- if (head === "coproc" && toks[0].raw === head && toks.length > 1) {
356
- const tail = (from) => ({ ...p, argv: p.argv.slice(from) });
357
- const first = segmentFacts(segment, tail(1), decl, table, nestedPlan, piped);
358
- if (toks.length < 3)
359
- return { ...first, backgrounds: true };
360
- const second = segmentFacts(segment, tail(2), decl, table, nestedPlan, piped);
361
- const seen = new Set(first.nested.map((n) => JSON.stringify(n.segments.map((sg) => sg.text))));
362
- const extraNested = second.nested.filter((n) => !seen.has(JSON.stringify(n.segments.map((sg) => sg.text))));
363
- return { ...first, ...(second.reentry === "shell" ? { reentry: second.reentry } : {}), reads: [...first.reads, ...second.reads], nested: [...first.nested, ...extraNested], backgrounds: true };
384
+ const pos = readProgramPosition(p.argv);
385
+ const coproc = pos.written !== undefined && isShellSyntaxWord(p.argv[pos.written], COPROC) ? pos.written : undefined;
386
+ if (coproc !== undefined && toks.length > coproc + 1) {
387
+ const once = plannedOnce(nestedPlan);
388
+ const tail = (from) => ({ ...p, argv: p.argv.slice(coproc + from) });
389
+ const background = (f) => ({ ...f, backgrounds: true, ...(f.readings !== undefined ? { readings: f.readings.map((g) => ({ ...g, backgrounds: true })) } : {}) });
390
+ const first = segmentFacts(segment, tail(1), decl, table, once, fed);
391
+ if (toks.length < coproc + 3 || isShellSyntaxWord(p.argv[coproc + 1], RESERVED) || readProgramPosition(tail(2).argv.slice(0, 1)).refusal !== undefined)
392
+ return background(first);
393
+ return background(readInSeveral([first, segmentFacts(segment, tail(2), decl, table, once, fed)]));
364
394
  }
365
395
  const loop = loopShapeOf(p);
366
- if (head !== undefined && toks[0].raw === head && BLOCK_WORD_NAMES.has(head)) {
367
- if (loop === "head")
368
- return done({ empty: false, launcherChain: [], declines: [], reads, moveProvable: false, loopHead: { beats: literalBeats(toks) } });
396
+ if (loopListHeadAt(p.argv) !== undefined)
397
+ return done({ empty: false, launcherChain: [], declines: [], reads, moveProvable: false, loopHead: { beats: literalBeats(toks) } });
398
+ if (head !== undefined && isShellSyntaxWord(p.argv[0], BLOCK_WORD_NAMES)) {
369
399
  if (head === "[[") {
370
400
  toks.forEach((r, i) => {
371
401
  if (ARITHMETIC_TEST_OPERATORS.has(toks[i - 1]?.folded ?? "") || ARITHMETIC_TEST_OPERATORS.has(toks[i + 1]?.folded ?? "") || toks[i - 1]?.folded === "-v")
@@ -374,7 +404,6 @@ function segmentFactsRead(segment, p, decl, table, nestedPlan, piped) {
374
404
  }
375
405
  return done({ empty: false, launcherChain: [], declines: [], reads, moveProvable: false });
376
406
  }
377
- const pos = readProgramPosition(p.argv);
378
407
  const written = pos.written;
379
408
  if (written === undefined)
380
409
  return done({ empty: segmentIsEmpty(segment, p), launcherChain: [], declines: [], reads, moveProvable: false });
@@ -413,7 +442,7 @@ function segmentFactsRead(segment, p, decl, table, nestedPlan, piped) {
413
442
  if (!w.startsWith("-") || w === "-")
414
443
  break;
415
444
  const step = launcherOptionStep(row, w);
416
- if (step === undefined)
445
+ if (step === undefined || (step === 2 && j + 1 >= chainEnd))
417
446
  break;
418
447
  if (step === 2) {
419
448
  const role = launcherOptionPathRole(row, w);
@@ -458,28 +487,44 @@ function segmentFactsRead(segment, p, decl, table, nestedPlan, piped) {
458
487
  }
459
488
  }
460
489
  let reentry;
490
+ let shift;
461
491
  if (pos.argvFromStdin)
462
492
  reentry = "argv";
463
493
  const reenterShell = (verb, argvs) => {
464
- const stdin = stdinTextsOf(segment, piped);
465
- const scripts = argvs.flatMap(({ shell, texts: t, args: a }) => [reentryText(shell, t), reentryText(shell, a), ...stdin.map((s) => (s.literal === undefined ? undefined : reentryText(shell, t, s.literal)))]);
466
- for (const t of new Set(scripts))
467
- if (t !== undefined)
468
- nested.push(nestedPlan(t, "later"));
494
+ const stdin = stdinTextsOf(segment, fed);
495
+ const scripts = new Map();
496
+ const script = (text, at) => { if (text !== undefined)
497
+ scripts.set(JSON.stringify([text, at]), { ...at, text }); };
498
+ for (const { shell, texts: t, args: a, as } of argvs) {
499
+ const user = as !== undefined ? { as } : {};
500
+ const argvText = [reentryText(shell, t), reentryText(shell, a)];
501
+ for (const text of argvText)
502
+ script(text, { ...user, ...(stdin.length > 0 ? { stdin } : {}) });
503
+ if (argvText.every((text) => text === undefined))
504
+ for (const s of stdin)
505
+ if (s.literal !== undefined)
506
+ script(reentryText(shell, t, s.literal), user);
507
+ }
508
+ for (const { text, ...at } of scripts.values()) {
509
+ const plan = nestedPlan(text, "now", at);
510
+ nested.push(plan);
511
+ if (at.as?.login === true)
512
+ elsewhere.add(plan);
513
+ }
469
514
  for (const { shell, args: a, words } of argvs) {
470
515
  const at = shell === "source" || shell === "." ? a.findIndex((w) => !w.startsWith("-") || w === "-") : scriptFileAt(shell, a);
471
516
  const file = at === undefined ? undefined : words[at];
472
517
  if (file !== undefined)
473
518
  reads.push(bare(file, "operand"));
474
519
  }
475
- return done({ empty: false, launcherChain, verb, reentry: "shell", declines, reads, moveProvable: false, ...(loopHead !== undefined ? { loopHead } : {}), ...(stdin.length > 0 ? { stdin } : {}) });
520
+ return done({ empty: false, launcherChain, verb, reentry: "shell", declines, reads, moveProvable: false, ...(loopHead !== undefined ? { loopHead } : {}), ...(stdin.length > 0 ? { stdin } : {}), ...(shift !== undefined ? { shift } : {}) });
476
521
  };
477
522
  if (pos.refusal !== undefined) {
478
- const commandLine = commandLineOptionSpellings(programRow(programBasename(pos.refusal.owner)));
479
- if (pos.refusal.kind === "option_at_program_position" && commandLine.length > 0) {
480
- const text = commandStringValue(commandLine, toks, pos.refusal.option);
523
+ const owner = programRow(programBasename(pos.refusal.owner));
524
+ if (pos.refusal.kind === "option_at_program_position" && owner !== undefined && commandLineOptionSpellings(owner).length > 0) {
525
+ const text = commandStringValue(owner, toks, pos.refusal.option);
481
526
  if (text !== undefined) {
482
- nested.push(nestedPlan(text.value, "later"));
527
+ nested.push(nestedPlan(text.value, "now"));
483
528
  reentry = "shell";
484
529
  unlistedWords(reads, toks, text.next, launcherIndices, "unlisted_word", ctx);
485
530
  return done({ empty: false, launcherChain, ...(verb !== undefined ? { verb } : {}), reentry, declines, reads, moveProvable: false, ...(loopHead !== undefined ? { loopHead } : {}) });
@@ -512,6 +557,12 @@ function segmentFactsRead(segment, p, decl, table, nestedPlan, piped) {
512
557
  const programRead = toks[program.index];
513
558
  if (rewritten(programRead) || isPathShapedToken(programRead.folded))
514
559
  reads.push(bare(programRead, "program_path"));
560
+ if (rewritten(programRead) && !programRead.word.pieces.some((p) => p.literal?.includes("/") === true))
561
+ shift = { kind: "lost" };
562
+ if (basename === "eval")
563
+ shift = argReads.every((r) => literalTextOf(r.word.pieces) !== undefined) && reentryText("eval", texts) !== undefined ? { kind: "eval", text: reentryText("eval", texts) } : { kind: "lost" };
564
+ if (basename === "source" || basename === ".")
565
+ shift = { kind: "lost" };
515
566
  if (runsShellText(basename))
516
567
  return reenterShell(verb, [{ shell: basename, texts, args, words: argReads }]);
517
568
  const row = programRow(basename);
@@ -520,11 +571,16 @@ function segmentFactsRead(segment, p, decl, table, nestedPlan, piped) {
520
571
  reentry = "interpreter";
521
572
  const moveProvable = pos.controlWords.length === 0 && pos.launchers.length === 0 && pos.assignments.length === 0 && program.name === basename;
522
573
  let baseMove;
574
+ const moving = baseShiftOf(basename, argReads, (r) => bare(r, "cd_target"));
575
+ if (moving !== undefined)
576
+ shift = moving.shift;
577
+ if (moving?.reported !== undefined)
578
+ baseMove = { target: moving.reported };
523
579
  if (basename === "cd") {
524
- baseMove = cdMove(argReads, reads);
580
+ if (typeof baseMove?.target === "object")
581
+ reads.push(baseMove.target);
525
582
  }
526
- else if (movesBaseUnfollowed(basename)) {
527
- baseMove = { target: "unmodelled" };
583
+ else if (movesBaseByStack(basename)) {
528
584
  unlistedWords(reads, toks, program.index, launcherIndices, "unlisted_word", ctx, program);
529
585
  }
530
586
  else if (listed) {
@@ -592,42 +648,11 @@ function segmentFactsRead(segment, p, decl, table, nestedPlan, piped) {
592
648
  declines,
593
649
  reads,
594
650
  ...(baseMove !== undefined ? { baseMove } : {}),
651
+ ...(shift !== undefined ? { shift } : {}),
595
652
  moveProvable,
596
653
  ...(loopHead !== undefined ? { loopHead } : {}),
597
654
  });
598
655
  }
599
- function rebasePlan(plan, from, to) {
600
- if (to !== "unmodelled" && to.length === 1 && to[0] === from)
601
- return plan;
602
- const fromSep = from.endsWith("/") || from.endsWith("\\") ? from : `${from}/`;
603
- const moveBase = (b) => {
604
- if (to === "unmodelled")
605
- return [];
606
- if (b === from)
607
- return [...to];
608
- if (b.startsWith(fromSep))
609
- return to.map((t) => `${t.endsWith("/") || t.endsWith("\\") ? t : `${t}/`}${b.slice(fromSep.length)}`);
610
- return [b];
611
- };
612
- const moveCandidate = (c) => {
613
- if (c.bases === "unmodelled" || c.bases.length === 0)
614
- return c;
615
- if (to === "unmodelled")
616
- return { ...c, bases: "unmodelled" };
617
- return { ...c, bases: [...new Set(c.bases.flatMap(moveBase))] };
618
- };
619
- return {
620
- ...plan,
621
- segments: plan.segments.map((s) => ({
622
- ...s,
623
- reads: s.reads.map(moveCandidate),
624
- redirects: s.redirects.map((r) => (r.target === undefined ? r : { ...r, target: moveCandidate(r.target) })),
625
- ...(s.baseMove !== undefined ? { baseMove: { target: typeof s.baseMove.target === "string" ? s.baseMove.target : moveCandidate(s.baseMove.target) } } : {}),
626
- bases: s.bases === "unmodelled" || to === "unmodelled" ? "unmodelled" : [...new Set(s.bases.flatMap(moveBase))],
627
- nested: s.nested.map((n) => rebasePlan(n, from, to)),
628
- })),
629
- };
630
- }
631
656
  function dedupe(reads) {
632
657
  const seen = new Set();
633
658
  const out = [];
@@ -641,10 +666,7 @@ function dedupe(reads) {
641
666
  return out;
642
667
  }
643
668
  function relativeSpelling(spelled) {
644
- return !(isAbsolutePathForm(spelled) || spelled.startsWith("~"));
645
- }
646
- function joinBase(base, target, homeDir) {
647
- return resolveOperandLexically(base, target, homeDir);
669
+ return !(isAbsoluteForFamily("own", spelled) || spelled.startsWith("~"));
648
670
  }
649
671
  function redirectFact(r, table, homeDir) {
650
672
  if (r.target === undefined)
@@ -655,21 +677,15 @@ function redirectFact(r, table, homeDir) {
655
677
  return { op: r.op, direction: "in" };
656
678
  return { op: r.op, direction: "out", target: bare(readsOf([r.target], table, homeDir)[0], "write_redirect_target") };
657
679
  }
658
- function commandStringValue(options, toks, option) {
680
+ function commandStringValue(row, toks, option) {
659
681
  const at = toks.findIndex((r) => r.folded === option);
660
- if (at < 0)
682
+ const line = at < 0 ? undefined : commandLineOf(row, option);
683
+ if (line === undefined)
661
684
  return undefined;
662
- for (const spelling of options) {
663
- if (option === spelling) {
664
- const value = toks[at + 1] === undefined ? undefined : programTextOf(toks[at + 1]);
665
- return value === undefined ? undefined : { value, next: at + 2 };
666
- }
667
- if (spelling.startsWith("--") && option.startsWith(`${spelling}=`))
668
- return { value: option.slice(spelling.length + 1), next: at + 1 };
669
- if (!spelling.startsWith("--") && option.startsWith(spelling) && option.length > spelling.length)
670
- return { value: option.slice(spelling.length), next: at + 1 };
671
- }
672
- return undefined;
685
+ if (line !== "next")
686
+ return { value: line.attached, next: at + 1 };
687
+ const value = toks[at + 1] === undefined ? undefined : programTextOf(toks[at + 1]);
688
+ return value === undefined ? undefined : { value, next: at + 2 };
673
689
  }
674
690
  function literalBeats(toks) {
675
691
  const at = toks.findIndex((r) => r.folded === "in");
@@ -691,13 +707,3 @@ function literalBeats(toks) {
691
707
  return undefined;
692
708
  return words.length <= POLL_LOOP_MAX_BEATS ? words.length : undefined;
693
709
  }
694
- function cdMove(args, reads) {
695
- const target = args.find((t) => !t.folded.startsWith("-") || t.folded === "-");
696
- if (target === undefined)
697
- return { target: "home" };
698
- if (target.folded === "-")
699
- return { target: "previous" };
700
- const c = bare(target, "cd_target");
701
- reads.push(c);
702
- return { target: c };
703
- }