@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,9 +1,21 @@
1
1
  import { argvOf, lexShell, literalTildeSpelling, substitutionsInHeredocBody } from "../../shell/lex.js";
2
- import { readProgramPosition } from "./bash-program-position.js";
2
+ import { shellWordsOf } from "../../shell/shell-words.js";
3
+ import { isShellSyntaxWord, LOOP_LIST_HEADS, readProgramPosition } from "./bash-program-position.js";
3
4
  import { declaredAttributes, programRow, readArgRoles } from "./program-read-model.js";
4
5
  import { codeBodies } from "./shell-reentry-text.js";
6
+ import { BUILTIN_ENABLED, BUILTINS_ALL, ENABLE_BUILTIN, builtinKey, chainAvailability, enableBindings, isBuiltinKey, isDisabledValue, speaksFor } from "./shell-read-builtins.js";
7
+ export function judgedSpellingOf(v) {
8
+ if (v.glob !== true)
9
+ return undefined;
10
+ const judged = literalTildeSpelling(v.parts.map((p) => (p.pattern ? p.judged : p.text)).join(""));
11
+ return judged === literalTildeSpelling(v.spelled) ? undefined : judged;
12
+ }
13
+ export function floorOf(v) {
14
+ const pattern = judgedSpellingOf(v);
15
+ return v.glob === true ? { spelled: v.spelled, glob: true, ...(pattern !== undefined ? { pattern } : {}) } : { spelled: v.spelled };
16
+ }
5
17
  function sameValue(a, b) {
6
- if (a.spelled !== b.spelled)
18
+ if (a.spelled !== b.spelled || a.fields?.length !== b.fields?.length)
7
19
  return false;
8
20
  if (a.glob !== true || b.glob !== true)
9
21
  return a.glob === b.glob;
@@ -15,53 +27,62 @@ export const SHELL_INTEGER_VARIABLES = new Set([
15
27
  "LISTMAX", "LOGCHECK", "PERIOD", "FUNCNEST", "UID", "EUID", "GID", "EGID", "REPORTTIME", "REPORTMEMORY", "DIRSTACKSIZE", "BAUD",
16
28
  "ZLE_RPROMPT_INDENT", "MBEGIN", "MEND", "PPID", "ARGC", "ZSH_SUBSHELL", "TTYIDLE", "status",
17
29
  ]);
18
- const SHELL_SET_VARIABLES = new Set(["PWD", "OLDPWD", "REPLY", "OPTARG", "MAPFILE", "BASH_REMATCH", "PIPESTATUS", "FUNCNAME", "BASH_COMMAND", "BASH_SUBSHELL", "COPROC", "GROUPS", "SHELLOPTS", "BASHOPTS", "BASH_VERSINFO"]);
30
+ const SHELL_SET_VARIABLES = new Set(["REPLY", "OPTARG", "MAPFILE", "BASH_REMATCH", "PIPESTATUS", "FUNCNAME", "BASH_COMMAND", "BASH_SUBSHELL", "COPROC", "GROUPS", "SHELLOPTS", "BASHOPTS", "BASH_VERSINFO"]);
19
31
  export function shellKeepsName(name) {
20
32
  return SHELL_INTEGER_VARIABLES.has(name) || SHELL_SET_VARIABLES.has(name);
21
33
  }
22
- const OPENING_WORDS = new Set(["if", "case", "for", "while", "until", "select", "{"]);
23
- const CLOSING_WORDS = new Set(["fi", "esac", "done", "}"]);
24
- const SWITCHING_WORDS = new Set(["else", "elif"]);
25
- const SPECIAL_BUILTINS = new Set([":", ".", "break", "continue", "eval", "exec", "exit", "export", "readonly", "return", "set", "shift", "source", "times", "trap", "unset"]);
34
+ export const WORKING_DIRECTORY_NAMES = Object.freeze(["PWD", "OLDPWD"]);
35
+ const isWorkingDirectoryName = (name) => name === "PWD" || name === "OLDPWD";
36
+ const OPENING_WORDS = shellWordsOf("scope_open");
37
+ const CLOSING_WORDS = shellWordsOf("scope_close");
38
+ const SWITCHING_WORDS = shellWordsOf("scope_switch");
39
+ const GROUP_WORDS = shellWordsOf("group"), DEFINITION_WORDS = shellWordsOf("definition"), ITERATING_HEADS = shellWordsOf("loop_iterates"), BACKGROUND_WORDS = shellWordsOf("background");
40
+ export const SPECIAL_BUILTINS = new Set([":", ".", "break", "continue", "eval", "exec", "exit", "export", "readonly", "return", "set", "shift", "source", "times", "trap", "unset"]);
26
41
  const IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;
42
+ const LOCAL_DECLARATION = "local";
43
+ const FUNCTION_KEY_PREFIX = "()";
44
+ export const functionKey = (name) => FUNCTION_KEY_PREFIX + name;
45
+ const isFunctionKey = (name) => name.startsWith(FUNCTION_KEY_PREFIX);
46
+ const FUNCTION_DEFINED = [{ spelled: "defined" }];
47
+ const FUNCTION_ABSENT = [{ spelled: "absent" }];
48
+ const isDefinedValue = (v) => v.spelled === "defined";
27
49
  const ATTRIBUTE_KINDS = { integer: "integer", transformed: "transformed", frozen: "frozen" };
28
50
  const EVERY_ATTRIBUTE = Object.values(ATTRIBUTE_KINDS).map((kind) => ({ kind }));
29
51
  export function projectSegment(segment) {
30
52
  const tokens = [...segment.tokens];
31
53
  let grouped = tokens.some((t) => t.kind === "group");
32
- const definesFunction = dropDefinitionHeads(tokens).some((n) => n > 0);
54
+ const defines = dropDefinitionHeads(tokens).flat();
33
55
  dropCasePattern(tokens);
34
56
  const words = tokens.filter((t) => {
35
57
  if (t.kind !== "word")
36
58
  return false;
37
- if (t.raw === t.folded && (t.folded === "{" || t.folded === "}")) {
59
+ if (t.raw === t.folded && GROUP_WORDS.has(t.folded)) {
38
60
  grouped = true;
39
61
  return false;
40
62
  }
41
63
  return true;
42
64
  });
43
- return { argv: words, redirects: tokens.filter((t) => t.kind === "redirect"), grouped, definesFunction };
65
+ return { argv: words, redirects: tokens.filter((t) => t.kind === "redirect"), grouped, defines };
44
66
  }
45
67
  function isDefinitionName(word) {
46
68
  return IDENTIFIER.test(word.folded) || (word.atCommandPosition && word.expansions.length === 0 && !/[?*+@!]$/.test(word.raw));
47
69
  }
48
70
  export function dropDefinitionHeads(tokens) {
49
- const heads = new Array(tokens.length + 1).fill(0);
50
- const drop = (k, count) => {
71
+ const heads = Array.from({ length: tokens.length + 1 }, () => []);
72
+ const drop = (k, count, name) => {
51
73
  tokens.splice(k, count);
52
74
  heads.splice(k, count);
53
- heads[k]++;
75
+ heads[k].push(name);
54
76
  };
55
77
  for (let k = 0; k + 1 < tokens.length; k++) {
56
78
  const [a, b, c, d] = [tokens[k], tokens[k + 1], tokens[k + 2], tokens[k + 3]];
57
- if (a.kind === "word" && a.raw === "function" && a.atCommandPosition && b.kind === "word") {
58
- drop(k--, c?.kind === "group" && c.op === "(" && d?.kind === "group" && d.op === ")" ? 4 : 2);
59
- }
79
+ if (a.kind === "word" && DEFINITION_WORDS.has(a.raw) && a.atCommandPosition && b.kind === "word")
80
+ drop(k--, c?.kind === "group" && c.op === "(" && d?.kind === "group" && d.op === ")" ? 4 : 2, b.folded);
60
81
  }
61
82
  for (let k = 0; k + 2 < tokens.length; k++) {
62
83
  const [a, b, c] = [tokens[k], tokens[k + 1], tokens[k + 2]];
63
84
  if (a.kind === "word" && b.kind === "group" && b.op === "(" && c.kind === "group" && c.op === ")" && isDefinitionName(a))
64
- drop(k, 3);
85
+ drop(k, 3, a.folded);
65
86
  }
66
87
  return heads;
67
88
  }
@@ -98,6 +119,8 @@ function extglobParen(tokens, at) {
98
119
  function blockStructure(segments) {
99
120
  let depth = 0;
100
121
  let bodies = 0;
122
+ let subshellIds = 0;
123
+ const subshellStack = [];
101
124
  const frames = [];
102
125
  const deeper = () => {
103
126
  depth++;
@@ -113,9 +136,13 @@ function blockStructure(segments) {
113
136
  return segments.map((segment) => {
114
137
  const tokens = [...segment.tokens];
115
138
  const heads = dropDefinitionHeads(tokens);
139
+ const defs = [];
116
140
  const startBodies = (k) => {
117
- for (let n = heads[k]; n > 0; n--)
141
+ for (const name of heads[k]) {
142
+ const enclosing = innermost();
143
+ defs.push({ name, standing: { ...(enclosing !== undefined ? { body: enclosing } : {}), subshells: [...subshellStack], depth } });
118
144
  frames.push({ body: { id: bodies++, base: depth }, opened: false });
145
+ }
119
146
  };
120
147
  const arithmetic = isArithmeticCommand(segment);
121
148
  const patternEnd = casePatternEnd(tokens);
@@ -123,6 +150,7 @@ function blockStructure(segments) {
123
150
  const open = [];
124
151
  let lowest = depth;
125
152
  let words;
153
+ let subshells;
126
154
  let body;
127
155
  const switches = [];
128
156
  const innermost = () => [...frames].reverse().find((f) => f.opened)?.body;
@@ -140,6 +168,7 @@ function blockStructure(segments) {
140
168
  if (k <= patternEnd)
141
169
  return;
142
170
  deeper();
171
+ subshellStack.push(subshellIds++);
143
172
  return;
144
173
  }
145
174
  const from = open.pop();
@@ -151,6 +180,7 @@ function blockStructure(segments) {
151
180
  return;
152
181
  }
153
182
  shallower();
183
+ subshellStack.pop();
154
184
  lowest = Math.min(lowest, depth);
155
185
  return;
156
186
  }
@@ -167,6 +197,7 @@ function blockStructure(segments) {
167
197
  switches.push(depth);
168
198
  else if (k > patternEnd) {
169
199
  words ??= depth;
200
+ subshells ??= [...subshellStack];
170
201
  body = innermost();
171
202
  }
172
203
  };
@@ -200,17 +231,54 @@ function blockStructure(segments) {
200
231
  while (frames.length > 0 && frames[frames.length - 1].flat === true)
201
232
  frames.pop();
202
233
  startBodies(tokens.length);
203
- return { words: words ?? depth, after: depth, lowest, switches, ...(body !== undefined ? { body } : {}) };
234
+ return { words: words ?? depth, after: depth, lowest, switches, subshells: subshells ?? [...subshellStack], defs, ...(body !== undefined ? { body } : {}) };
204
235
  });
205
236
  }
206
- const ONE_WORD = /^[A-Za-z0-9_./+@:%=,-]+$/;
237
+ const READABLE_VALUE = /^[^\\~()]*$/;
207
238
  const WORD_VALUES_MAX = 64;
208
- export function wordValues(word, table, quoted, overlay = new Map()) {
209
- if (!word.pieces.some((p) => p.expansion?.kind === "parameter" || p.expansion?.kind === "tilde"))
239
+ const quotedRunsOf = (v) => v.glob === true ? v.parts.map((r) => (r.pattern ? { text: r.text, mode: "set", judged: r.judged } : { text: r.text, mode: "inactive" })) : [{ text: v.spelled, mode: "inactive" }];
240
+ function formedField(f) {
241
+ const runs = f.runs;
242
+ if (!runs.some((r) => r.mode === "active" && /[[\]*?]/.test(r.text))) {
243
+ if (!runs.some((r) => r.mode === "raw" || r.mode === "set"))
244
+ return { spelled: f.text };
245
+ return { spelled: f.text, glob: true, parts: joinRuns([], runs.map((r) => (r.mode === "raw" || r.mode === "set" ? { text: r.text, pattern: true, judged: r.judged } : { text: r.text, pattern: false }))) };
246
+ }
247
+ if (runs.some((r) => r.mode === "active" && /[ \t\n\\]/.test(r.text)) || (runs.some((r) => r.mode === "set") && runs.some((r) => r.mode === "active" && /[[\]]/.test(r.text))))
248
+ return undefined;
249
+ const escaped = runs.map((r) => (r.mode === "raw" || r.mode === "set" ? r.text : r.text.replace(r.mode === "active" ? /[^A-Za-z0-9_./*?[\]!^:=,+@%-]/g : /[^A-Za-z0-9_./]/g, (c) => `\\${c}`))).join("");
250
+ const lexed = lexShell(`: ${escaped}`);
251
+ const words = "parseFailure" in lexed || lexed.segments.length !== 1 ? undefined : argvOf(lexed.segments[0]);
252
+ if (words?.length !== 2)
210
253
  return undefined;
211
- return valueOf(word, table, quoted, overlay);
254
+ let parts = [];
255
+ for (const p of words[1].pieces) {
256
+ if (p.expansion?.pattern !== undefined)
257
+ parts = joinRuns(parts, [{ text: p.expansion.pattern.written, pattern: true, judged: p.expansion.pattern.judged }]);
258
+ else if (p.expansion === undefined && p.literal !== undefined)
259
+ parts = joinRuns(parts, [{ text: p.literal, pattern: false }]);
260
+ else
261
+ return undefined;
262
+ }
263
+ return parts.some((r) => r.pattern) ? { spelled: f.text, glob: true, parts } : { spelled: f.text };
264
+ }
265
+ export function wordValues(word, table, quoted, overlay = new Map(), split = false) {
266
+ if (!word.pieces.some((p) => p.expansion?.kind === "parameter" || p.expansion?.kind === "tilde") && namesIn(word).length === 0)
267
+ return undefined;
268
+ return valueOf(word, table, quoted, overlay, split);
269
+ }
270
+ export function namesIn(word) {
271
+ return word.pieces.flatMap((p) => {
272
+ const e = p.expansion;
273
+ if (e?.kind === "parameter" && e.name !== undefined)
274
+ return e.body === undefined || e.body === e.name ? [e.name] : [];
275
+ return e?.kind === "glob" && e.pattern === undefined ? (bracketBodyOf(e.body) ?? []).flatMap((w) => namesIn(w)) : [];
276
+ });
277
+ }
278
+ function bracketBodyOf(body) {
279
+ const lexed = body === undefined ? undefined : lexShell(`""${body}`);
280
+ return lexed === undefined || "parseFailure" in lexed ? undefined : lexed.segments.flatMap((s) => argvOf(s));
212
281
  }
213
- const runsOf = (v) => (v.glob === true ? v.parts : [{ text: v.spelled, pattern: false }]);
214
282
  function joinRuns(runs, more) {
215
283
  const out = [...runs];
216
284
  for (const r of more) {
@@ -224,51 +292,96 @@ function joinRuns(runs, more) {
224
292
  }
225
293
  return out;
226
294
  }
227
- export function valueOf(word, table, quoted, overlay = new Map()) {
295
+ export function valueOf(word, table, quoted, overlay = new Map(), split = false) {
228
296
  const stateOf = (name) => (table === undefined ? "unknown" : overlay.get(name) ?? table.stateOf(name));
229
- let combos = [{ text: "", glob: false, parts: [] }];
230
- for (const p of word.pieces) {
231
- const e = p.expansion;
232
- let options;
233
- if (e === undefined) {
234
- if (p.literal === undefined)
235
- return "unknown";
236
- options = [{ spelled: p.literal }];
297
+ const EMPTY = { text: "", runs: [] };
298
+ let combos = [{ field: EMPTY, closed: [], started: false, split: false }];
299
+ const activeRun = (text) => ({ text, mode: "active" });
300
+ const splitInto = (c, value) => {
301
+ const words = value.split(/[ \t\n]+/).filter((w) => w !== "");
302
+ if (words.length === 0)
303
+ return value === "" ? { ...c, split: true } : { ...c, field: EMPTY, started: false, closed: c.started ? [...c.closed, c.field] : c.closed, split: true };
304
+ const closed = [...c.closed];
305
+ if (/^[ \t\n]/.test(value) && c.started)
306
+ closed.push(c.field);
307
+ let field = closed.length > c.closed.length ? { text: words[0], runs: [activeRun(words[0])] } : { text: c.field.text + words[0], runs: [...c.field.runs, activeRun(words[0])] };
308
+ for (let i = 1; i < words.length; i++) {
309
+ closed.push(field);
310
+ field = { text: words[i], runs: [activeRun(words[i])] };
237
311
  }
238
- else if (e.kind === "glob") {
239
- if (e.pattern === undefined)
240
- return "unknown";
241
- options = [{ spelled: e.pattern.folded, glob: true, parts: [{ text: e.pattern.written, pattern: true, judged: e.pattern.judged }] }];
242
- }
243
- else if (e.kind === "tilde") {
244
- if (e.body !== "~")
245
- return "unknown";
246
- const home = stateOf("HOME");
247
- if (home === "unknown")
248
- return "unknown";
249
- options = home;
250
- }
251
- else if (e.kind === "parameter" && e.name !== undefined && (e.body === undefined || e.body === e.name)) {
252
- const state = stateOf(e.name);
253
- if (state === "unknown")
254
- return "unknown";
255
- if (p.quotedBy === undefined && !quoted && (table?.ifsTouched === true || state.some((v) => v.glob === true || !ONE_WORD.test(v.spelled))))
256
- return "unknown";
257
- options = state;
258
- }
259
- else
260
- return "unknown";
261
- const next = [];
262
- for (const c of combos)
263
- for (const o of options)
264
- next.push({ text: c.text + o.spelled, glob: c.glob || o.glob === true, parts: joinRuns(c.parts, runsOf(o)) });
312
+ if (!/[ \t\n]$/.test(value))
313
+ return { ...c, field, started: true, closed, split: true };
314
+ closed.push(field);
315
+ return { ...c, field: EMPTY, started: false, closed, split: true };
316
+ };
317
+ const extend = (options) => {
318
+ const next = combos.flatMap((c) => options.map((o) => ({ ...c, field: { text: c.field.text + o.text, runs: [...c.field.runs, ...o.runs] }, started: true })));
265
319
  if (next.length > WORD_VALUES_MAX)
266
- return "unknown";
320
+ return false;
267
321
  combos = next;
268
- }
322
+ return true;
323
+ };
324
+ const unquotedKind = (v) => v.glob === true || !READABLE_VALUE.test(v.spelled) ? undefined : !/[ \t\n]/.test(v.spelled) && v.spelled !== "" ? "run" : split ? "split" : undefined;
325
+ const walk = (pieces, unquoted) => {
326
+ for (const p of pieces) {
327
+ const e = p.expansion;
328
+ const bare = unquoted && p.quotedBy === undefined;
329
+ if (e === undefined) {
330
+ if (p.literal === undefined || !extend([{ text: p.literal, runs: [{ text: p.literal, mode: bare ? "active" : "inactive" }] }]))
331
+ return false;
332
+ }
333
+ else if (e.kind === "glob") {
334
+ const formed = e.pattern;
335
+ if (formed !== undefined) {
336
+ if (!extend([{ text: formed.folded, runs: [{ text: formed.written, mode: "raw", judged: formed.judged }] }]))
337
+ return false;
338
+ continue;
339
+ }
340
+ const words = bracketBodyOf(e.body);
341
+ if (words?.length !== 1 || !extend([{ text: "[", runs: [activeRun("[")] }]) || !walk(words[0].pieces, true) || !extend([{ text: "]", runs: [activeRun("]")] }]))
342
+ return false;
343
+ }
344
+ else if (e.kind === "tilde") {
345
+ const home = e.body === "~" ? stateOf("HOME") : "unknown";
346
+ if (home === "unknown" || !extend(home.map((v) => ({ text: v.spelled, runs: quotedRunsOf(v) }))))
347
+ return false;
348
+ }
349
+ else if (e.kind === "parameter" && e.name !== undefined && (e.body === undefined || e.body === e.name)) {
350
+ const state = stateOf(e.name);
351
+ if (state === "unknown")
352
+ return false;
353
+ if (!bare) {
354
+ if (!extend(state.map((v) => ({ text: v.spelled, runs: quotedRunsOf(v) }))))
355
+ return false;
356
+ continue;
357
+ }
358
+ const kinds = state.map(unquotedKind);
359
+ if (table?.ifsTouched === true || kinds.includes(undefined))
360
+ return false;
361
+ if (!kinds.includes("split")) {
362
+ if (!extend(state.map((v) => ({ text: v.spelled, runs: [activeRun(v.spelled)] }))))
363
+ return false;
364
+ continue;
365
+ }
366
+ const next = combos.flatMap((c) => state.map((v) => splitInto(c, v.spelled)));
367
+ if (next.length > WORD_VALUES_MAX)
368
+ return false;
369
+ combos = next;
370
+ }
371
+ else
372
+ return false;
373
+ }
374
+ return true;
375
+ };
376
+ if (!walk(word.pieces, !quoted))
377
+ return "unknown";
269
378
  const out = [];
270
379
  for (const c of combos) {
271
- const v = c.glob ? { spelled: c.text, glob: true, parts: c.parts } : { spelled: c.text };
380
+ const fields = (c.split ? (c.started ? [...c.closed, c.field] : c.closed) : [c.field]).map(formedField);
381
+ const formed = fields.filter((f) => f !== undefined && !(c.split && f.glob === true));
382
+ if (formed.length !== fields.length)
383
+ return "unknown";
384
+ const v = !c.split ? formed[0] : formed.length !== 1 ? { spelled: formed.map((f) => f.spelled).join(" "), fields: formed.map((f) => f.spelled) } : { spelled: formed[0].spelled };
272
385
  if (!out.some((x) => sameValue(x, v)))
273
386
  out.push(v);
274
387
  }
@@ -288,25 +401,32 @@ export function wordFloorValues(word, table) {
288
401
  }
289
402
  else if (e.kind === "parameter" && e.name !== undefined) {
290
403
  const state = table.stateOf(e.name);
291
- options = state !== "unknown" && (e.body === undefined || e.body === e.name) ? state : table.floorOf(e.name);
404
+ options = state !== "unknown" && (e.body === undefined || e.body === e.name) ? state.map(floorOf) : table.floorOf(e.name);
292
405
  }
293
406
  else
294
407
  return [];
295
408
  if (options.length === 0)
296
409
  return [];
297
410
  const next = [];
298
- for (const c of combos)
299
- for (const o of options)
300
- next.push(c.glob === true || o.glob === true ? { spelled: c.spelled + o.spelled, glob: true } : { spelled: c.spelled + o.spelled });
411
+ for (const c of combos) {
412
+ for (const o of options) {
413
+ const pattern = c.pattern !== undefined || o.pattern !== undefined ? (c.pattern ?? c.spelled) + (o.pattern ?? o.spelled) : undefined;
414
+ next.push(c.glob === true || o.glob === true ? { spelled: c.spelled + o.spelled, glob: true, ...(pattern !== undefined ? { pattern } : {}) } : { spelled: c.spelled + o.spelled });
415
+ }
416
+ }
301
417
  if (next.length > WORD_VALUES_MAX)
302
418
  return [];
303
419
  combos = next;
304
420
  }
305
421
  return combos;
306
422
  }
307
- export function bindingEffectOf(segment, argv, shape, readValue) {
423
+ export function loopListHeadAt(argv) {
424
+ const at = isShellSyntaxWord(argv[0], LOOP_LIST_HEADS) ? 0 : readProgramPosition(argv).written;
425
+ return at !== undefined && isShellSyntaxWord(argv[at], LOOP_LIST_HEADS) ? at : undefined;
426
+ }
427
+ export function bindingEffectOf(segment, argv, shape, readValue, shadow, availability) {
308
428
  const bindings = [];
309
- let all = shape.definesFunction ? "reset" : undefined;
429
+ let all = shape.defines.length > 0 ? "reset" : undefined;
310
430
  const unknownAll = () => void (all = "unknown");
311
431
  const overlay = new Map();
312
432
  let scope;
@@ -316,6 +436,8 @@ export function bindingEffectOf(segment, argv, shape, readValue) {
316
436
  overlay.set(b.name, b.state);
317
437
  };
318
438
  const kill = (name) => bind({ name, state: "unknown" });
439
+ for (const name of shape.defines)
440
+ bind({ name: functionKey(name), state: FUNCTION_DEFINED });
319
441
  const nameOf = (w) => {
320
442
  if (w.pieces.some((p) => p.expansion !== undefined || p.literal === undefined))
321
443
  return "computed";
@@ -353,21 +475,21 @@ export function bindingEffectOf(segment, argv, shape, readValue) {
353
475
  kill(name);
354
476
  return { bindings, all };
355
477
  }
356
- const head = argv[0];
357
- const headWord = head !== undefined && head.raw === head.folded ? head.folded : undefined;
358
- if (headWord === "for" || headWord === "select") {
478
+ const loopAt = loopListHeadAt(argv);
479
+ if (loopAt !== undefined) {
480
+ const headWord = argv[loopAt].folded;
359
481
  if (tokens.some((t) => t.kind === "group"))
360
482
  unknownAll();
361
- const name = argv[1] !== undefined ? nameOf(argv[1]) : undefined;
483
+ const name = argv[loopAt + 1] !== undefined ? nameOf(argv[loopAt + 1]) : undefined;
362
484
  if (name === undefined || name === "computed") {
363
485
  unknownAll();
364
486
  return { bindings, all };
365
487
  }
366
- const inAt = argv.findIndex((w, i) => i >= 2 && w.raw === "in");
488
+ const inAt = argv.findIndex((w, i) => i >= loopAt + 2 && w.raw === "in");
367
489
  let state = "unknown";
368
- if (headWord === "for" && inAt === 2 && argv.length > 3) {
490
+ if (ITERATING_HEADS.has(headWord) && inAt === loopAt + 2 && argv.length > loopAt + 3) {
369
491
  const values = [];
370
- for (const w of argv.slice(3)) {
492
+ for (const w of argv.slice(loopAt + 3)) {
371
493
  const v = readValue(w, false, overlay);
372
494
  if (v === "unknown") {
373
495
  values.length = 0;
@@ -381,7 +503,7 @@ export function bindingEffectOf(segment, argv, shape, readValue) {
381
503
  bind({ name, state, loopVar: true });
382
504
  return { bindings, all };
383
505
  }
384
- if (headWord === "coproc" && argv[1] !== undefined)
506
+ if (argv[0] !== undefined && BACKGROUND_WORDS.has(argv[0].raw) && argv[1] !== undefined)
385
507
  killNamed(nameOf(argv[1]));
386
508
  const pos = readProgramPosition(argv);
387
509
  const program = pos.program;
@@ -401,9 +523,20 @@ export function bindingEffectOf(segment, argv, shape, readValue) {
401
523
  unknownAll();
402
524
  return { bindings, all, attributes: EVERY_ATTRIBUTE, references: true };
403
525
  }
404
- if (program === undefined || row === undefined)
526
+ if (program === undefined || shadow === "named")
527
+ return { bindings, all };
528
+ const settled = bindings.length;
529
+ const runsAsBuiltin = program.name === program.basename && pos.launchers.every((l, i) => (l.name === "builtin" || l.name === "command") && argv[l.index].folded === l.name && l.index + 1 === (pos.launchers[i + 1]?.index ?? program.index)) && !segment.tokens.some((t) => t.kind === "redirect" || t.kind === "heredoc");
530
+ const available = runsAsBuiltin ? chainAvailability([...pos.launchers.map((l) => l.name), program.basename], availability) : "enabled";
531
+ if (available === "disabled")
405
532
  return { bindings, all };
533
+ const mayNotRun = shadow === "maybe" || available === "maybe" || (!runsAsBuiltin && (row?.builtin === "declaration" || program.basename === ENABLE_BUILTIN));
534
+ const finish = (e) => (mayNotRun ? { ...e, bindings: e.bindings.map((b, i) => (i < settled ? b : { ...b, prefix: true })) } : e);
406
535
  const args = argv.slice(program.index + 1);
536
+ if (program.basename === ENABLE_BUILTIN)
537
+ return finish({ bindings: [...bindings, ...enableBindings(args)], all });
538
+ if (row === undefined)
539
+ return { bindings, all };
407
540
  const folded = args.map((w) => w.folded);
408
541
  if (row.reentry?.kind === "shell" && (row.reentry.text === "words" || row.reentry.text === "file-operand"))
409
542
  unknownAll();
@@ -416,7 +549,7 @@ export function bindingEffectOf(segment, argv, shape, readValue) {
416
549
  kill(name);
417
550
  }
418
551
  if (row.builtin === "declaration") {
419
- scope = args.some((w) => w.folded.startsWith("-") || w.folded.startsWith("+")) ? "unread" : program.basename === "local" ? "local" : undefined;
552
+ scope = args.some((w) => w.folded.startsWith("-") || w.folded.startsWith("+")) ? "unread" : program.basename === LOCAL_DECLARATION ? "local" : undefined;
420
553
  const assigns = declaredAttributes(row, folded);
421
554
  const kinds = [...assigns].filter((k) => k !== "reference" && k !== "unsettled");
422
555
  const storesText = [...assigns].every((k) => k === "frozen");
@@ -443,12 +576,19 @@ export function bindingEffectOf(segment, argv, shape, readValue) {
443
576
  bind({ name, state: assignedState(a, readValue, expanded) });
444
577
  attributes.push(...kinds.map((kind) => ({ name, kind })));
445
578
  }
446
- const inFunction = program.basename === "local" ? { inFunction: true } : {};
579
+ const inFunction = program.basename === LOCAL_DECLARATION ? { inFunction: true } : {};
447
580
  if (references) {
448
581
  unknownAll();
449
- return { bindings, all, attributes, references: true, ...inFunction };
582
+ return finish({ bindings, all, attributes, references: true, ...inFunction });
450
583
  }
451
- return { bindings, all, attributes, ...inFunction };
584
+ return finish({ bindings, all, attributes, ...inFunction });
585
+ }
586
+ if (program.basename === "unset") {
587
+ const { operands, variablesOnly } = unsetOperands(args);
588
+ if (!variablesOnly)
589
+ for (const w of operands)
590
+ if (w.pieces.every((p) => p.literal !== undefined && p.expansion === undefined))
591
+ bind({ name: functionKey(w.folded), state: FUNCTION_ABSENT, prefix: true });
452
592
  }
453
593
  for (const e of readArgRoles(row, folded)) {
454
594
  const role = e.kind === "value" || e.kind === "operand" ? e.role : e.kind === "option" && typeof e.reading === "object" ? e.reading.role : undefined;
@@ -468,11 +608,32 @@ export function bindingEffectOf(segment, argv, shape, readValue) {
468
608
  const nameLetters = new Set(row.grammars.flatMap((g) => Object.entries(g.short).flatMap(([letter, s]) => (s.value?.kind === "binds-name" ? [letter] : []))));
469
609
  if (nameLetters.size > 0 && readArgRoles(row, folded).some((e) => e.kind === "option" && e.reading === "speculative" && [...folded[e.at].slice(1)].some((ch) => nameLetters.has(ch))))
470
610
  unknownAll();
471
- return { bindings, all };
611
+ return finish({ bindings, all });
472
612
  }
473
613
  function nameIn(text) {
474
614
  return /^([A-Za-z_][A-Za-z0-9_]*)(?:\[.*\])?$/s.exec(text)?.[1];
475
615
  }
616
+ function unsetOperands(args) {
617
+ let variables = false;
618
+ let otherwise = false;
619
+ let at = 0;
620
+ for (; at < args.length; at++) {
621
+ const w = args[at].folded;
622
+ if (w === "--") {
623
+ at++;
624
+ break;
625
+ }
626
+ if (!/^-./.test(w))
627
+ break;
628
+ for (const letter of w.slice(1)) {
629
+ if (letter === "v" || letter === "n")
630
+ variables = true;
631
+ else
632
+ otherwise = true;
633
+ }
634
+ }
635
+ return { operands: args.slice(at), variablesOnly: variables && !otherwise };
636
+ }
476
637
  function compoundElementWords(raw) {
477
638
  const inner = /^\(([\s\S]*)\)$/.exec(raw)?.[1];
478
639
  const l = inner === undefined ? undefined : lexShell(inner);
@@ -490,7 +651,7 @@ function compoundFloor(raw, readValue, overlay) {
490
651
  return compoundElementWords(raw).flatMap((w) => {
491
652
  const v = w.tail === true ? "unknown" : readValue(w, true, overlay);
492
653
  if (v !== "unknown")
493
- return [...v];
654
+ return v.map(floorOf);
494
655
  const text = w.pieces.some((q) => q.expansion?.kind === "tilde") ? w.folded : literalTildeSpelling(w.folded);
495
656
  return [w.pieces.some((q) => q.expansion?.kind === "glob") ? { spelled: text, glob: true } : { spelled: text }];
496
657
  });
@@ -538,6 +699,11 @@ export function textBindsHome(text) {
538
699
  return names === "all" || names.has("HOME");
539
700
  }
540
701
  const NOTHING_INHERITED = { attributes: [], references: false };
702
+ export function joinRebound(a, b) {
703
+ if (a === "all" || b === "all")
704
+ return "all";
705
+ return new Set([...(a ?? []), ...(b ?? [])]);
706
+ }
541
707
  export class BindingThread {
542
708
  segments;
543
709
  named;
@@ -545,40 +711,186 @@ export class BindingThread {
545
711
  boundAnywhere;
546
712
  loops;
547
713
  homeStartsTouched;
714
+ inheritedFunctions;
548
715
  entries = [];
716
+ localDeclarations = [];
549
717
  attributesAt;
550
718
  unreadable;
551
719
  blocks;
552
- detached;
553
- constructor(segments, named, initial, boundAnywhere, loops, homeStartsTouched = false, inherited = NOTHING_INHERITED) {
720
+ ownSubshell;
721
+ startFloors;
722
+ startRebound;
723
+ bodyRuns = { limit: -1, environment: [] };
724
+ constructor(segments, named, initial, boundAnywhere, loops, homeStartsTouched = false, inherited = NOTHING_INHERITED, inheritedFunctions) {
554
725
  this.segments = segments;
555
726
  this.named = named;
556
727
  this.initial = initial;
557
728
  this.boundAnywhere = boundAnywhere;
558
729
  this.loops = loops;
559
730
  this.homeStartsTouched = homeStartsTouched;
731
+ this.inheritedFunctions = inheritedFunctions;
732
+ this.startFloors = inherited.floors ?? new Map();
733
+ this.startRebound = inherited.rebound ?? new Set();
560
734
  this.blocks = blockStructure(segments);
561
- this.detached = segments.map((s, i) => s.connector === "|" || segments[i + 1]?.connector === "|" || segments[i + 1]?.connector === "&");
735
+ this.ownSubshell = segments.map((_, i) => segments[i + 1]?.connector === "|" || segments[i + 1]?.connector === "&");
562
736
  this.unreadable = [...(inherited.references ? [{ at: -1 }] : []), ...named.flatMap((effect, at) => this.unreadableBy(effect, at))];
563
737
  this.attributesAt = [...inherited.attributes.map((a) => ({ ...a, at: -1 })), ...named.flatMap((effect, at) => (effect.attributes ?? []).map((a) => ({ ...a, at })))];
564
738
  }
565
739
  inheritedAt(j) {
566
740
  const holds = (at) => j === undefined || this.mayRunBefore(at, j);
741
+ const reaches = (e) => j === undefined || (this.mayRunBefore(e.at, j) && this.visible(e, j));
742
+ const floors = new Map(this.startFloors);
743
+ for (const e of this.entries)
744
+ if (e.name !== undefined && e.floor !== undefined && (j === undefined || e.at < j))
745
+ floors.set(e.name, [...(floors.get(e.name) ?? []), ...e.floor]);
746
+ let rebound = this.startRebound;
747
+ for (const e of this.entries)
748
+ if (e.state !== "reset" && reaches(e))
749
+ rebound = joinRebound(rebound, e.name === undefined ? "all" : [e.name]);
750
+ for (const u of this.unreadable)
751
+ if (j === undefined || this.lostAt(u, j))
752
+ rebound = joinRebound(rebound, u.name === undefined ? "all" : [u.name]);
753
+ rebound = joinRebound(rebound, this.boundLater(j));
567
754
  return {
568
755
  attributes: this.attributesAt.filter((x) => holds(x.at)).map(({ name, kind }) => (name !== undefined ? { name, kind } : { kind })),
569
756
  references: this.unreadable.some((u) => u.name === undefined && u.body === undefined && holds(u.at)),
757
+ ...(floors.size > 0 ? { floors } : {}),
758
+ rebound,
570
759
  };
571
760
  }
761
+ startOf(name) {
762
+ return isFunctionKey(name) ? this.inheritedFunctions?.start(name) ?? FUNCTION_ABSENT : isBuiltinKey(name) ? this.inheritedFunctions?.start(name) ?? BUILTIN_ENABLED : this.initial(name);
763
+ }
764
+ bindsInText(name) {
765
+ return this.named.some((effect) => effect.all === "unknown" || effect.bindings.some((b) => speaksFor(b.name, name)));
766
+ }
767
+ heldAnywhere() {
768
+ const start = (key) => {
769
+ const own = this.startOf(key);
770
+ if (own === "unknown")
771
+ return own;
772
+ const values = [...own];
773
+ for (const effect of this.named) {
774
+ if (effect.all === "unknown")
775
+ return "unknown";
776
+ for (const b of effect.bindings) {
777
+ if (!speaksFor(b.name, key))
778
+ continue;
779
+ if (b.state === "unknown")
780
+ return "unknown";
781
+ for (const v of b.state)
782
+ if (!values.some((x) => sameValue(x, v)))
783
+ values.push(v);
784
+ }
785
+ }
786
+ return values;
787
+ };
788
+ return { start, bound: new Set() };
789
+ }
790
+ runsBodies(runs, atEnd, environment) {
791
+ let limit = atEnd ? this.named.length - 1 : -1;
792
+ runs.forEach((r, si) => {
793
+ if (!r)
794
+ return;
795
+ limit = Math.max(limit, si);
796
+ for (const [head, end] of this.loops)
797
+ if (head <= si && si < end)
798
+ limit = Math.max(limit, end);
799
+ });
800
+ this.bodyRuns = { limit, environment };
801
+ const calling = new Set(runs.flatMap((r, si) => (r && this.blocks[si].body !== undefined ? [this.blocks[si].body.id] : [])));
802
+ this.named.forEach((effect, at) => {
803
+ for (const b of effect.bindings) {
804
+ const body = this.standingOf(at, b.name).body;
805
+ if (body !== undefined && calling.has(body.id))
806
+ this.unreadable.push({ at, name: b.name, body });
807
+ }
808
+ });
809
+ }
810
+ boundLater(j) {
811
+ const out = new Set();
812
+ if (j !== undefined && this.blocks[j].body === undefined)
813
+ return out;
814
+ const limit = j === undefined ? this.named.length - 1 : this.bodyRuns.limit;
815
+ for (let s = j === undefined ? 0 : j + 1; s <= limit; s++) {
816
+ const effect = this.named[s];
817
+ if (effect.all === "unknown" || effect.references === true)
818
+ return "all";
819
+ for (const b of effect.bindings)
820
+ out.add(b.name);
821
+ const environment = this.bodyRuns.environment[s];
822
+ if (environment === "all")
823
+ return "all";
824
+ for (const name of environment ?? [])
825
+ out.add(name);
826
+ }
827
+ return out;
828
+ }
829
+ ownSubshellAt(at, standing) {
830
+ return this.ownSubshell[at] === true && standing.depth >= this.blocks[at].after;
831
+ }
832
+ detachedAt(at, standing) {
833
+ return this.segments[at].connector === "|" || this.ownSubshellAt(at, standing);
834
+ }
835
+ visible(e, j) {
836
+ const reader = j === undefined ? undefined : this.blocks[j];
837
+ if (e.standing.body !== undefined && reader?.body?.id !== e.standing.body.id)
838
+ return false;
839
+ if (j !== e.at && this.ownSubshellAt(e.at, e.standing))
840
+ return false;
841
+ const around = reader?.subshells ?? [];
842
+ return e.standing.subshells.every((id) => around.includes(id));
843
+ }
844
+ standingOf(at, name) {
845
+ const own = this.blocks[at];
846
+ const head = name !== undefined && isFunctionKey(name) ? own.defs.find((d) => functionKey(d.name) === name) : undefined;
847
+ return head?.standing ?? { ...(own.body !== undefined ? { body: own.body } : {}), subshells: own.subshells, depth: own.words };
848
+ }
849
+ functionBound() {
850
+ const out = new Set();
851
+ if (this.inheritedFunctions?.bound === "all")
852
+ return "all";
853
+ for (const name of this.inheritedFunctions?.bound ?? [])
854
+ out.add(name);
855
+ for (let at = 0; at < this.named.length; at++) {
856
+ const effect = this.named[at];
857
+ if (this.blocks[at].body !== undefined && (effect.all === "unknown" || effect.references === true))
858
+ return "all";
859
+ for (const b of effect.bindings) {
860
+ const own = this.bodyBinding(b, at);
861
+ if (own !== undefined && (b.scope === "unread" || !this.declaredLocal(b.name, at, own)))
862
+ out.add(b.name);
863
+ }
864
+ }
865
+ return out;
866
+ }
867
+ bodyBinding(b, at) {
868
+ const own = this.standingOf(at, b.name).body;
869
+ return own !== undefined && b.scope !== "local" ? own : undefined;
870
+ }
871
+ inFunctionBody(at) {
872
+ return this.blocks[at].body !== undefined;
873
+ }
874
+ runsApart(at) {
875
+ return this.blocks[at].subshells.length > 0 || this.ownSubshell[at] === true || this.blocks[at].body !== undefined;
876
+ }
877
+ runsLater(at, names) {
878
+ if (names === "all")
879
+ this.unreadable.push({ at });
880
+ else
881
+ for (const name of names)
882
+ this.unreadable.push({ at, name });
883
+ }
572
884
  unreadableBy(effect, at) {
573
885
  const body = this.blocks[at].body;
574
886
  const out = [];
575
- if (body !== undefined) {
576
- for (const b of effect.bindings)
577
- if (b.scope !== "local" && (b.scope === "unread" || !this.declaredLocal(b.name, at, body)))
578
- out.push({ at, name: b.name, body });
579
- if (effect.all === "unknown")
580
- out.push({ at, body });
887
+ for (const b of effect.bindings) {
888
+ const own = this.bodyBinding(b, at);
889
+ if (own !== undefined)
890
+ out.push({ at, name: b.name, body: own });
581
891
  }
892
+ if (body !== undefined && effect.all === "unknown")
893
+ out.push({ at, body });
582
894
  if (effect.references === true)
583
895
  out.push({ at });
584
896
  return out;
@@ -589,107 +901,139 @@ export class BindingThread {
589
901
  return this.blocks[e].body !== undefined || [...this.loops].some(([head, end]) => head <= e && x < end);
590
902
  }
591
903
  declaredLocal(name, at, body) {
592
- for (let k = 0; k < at; k++) {
593
- const connector = this.segments[k].connector;
594
- if (this.blocks[k].body?.id !== body.id || this.detached[k] === true || connector === "&&" || connector === "||")
595
- continue;
596
- if (this.named[k].bindings.some((b) => b.scope === "local" && b.name === name) && this.heldThrough(k, at))
597
- return true;
598
- }
599
- return false;
904
+ return this.localDeclarations.some((d) => d.body === body.id && d.name === name && d.at < at && this.heldThrough(d, at));
600
905
  }
601
- heldThrough(at, j) {
602
- const depth = this.blocks[at].words;
603
- if (this.blocks[at].after < depth)
906
+ heldThrough(e, j) {
907
+ const depth = e.standing.depth;
908
+ if (this.blocks[e.at].after < depth)
604
909
  return false;
605
- for (let k = at + 1; k <= j; k++)
910
+ for (let k = e.at + 1; k <= j; k++)
606
911
  if (this.blocks[k].lowest < depth || this.blocks[k].switches.includes(depth))
607
912
  return false;
608
913
  return true;
609
914
  }
610
915
  apply(at, effect, andRun, loopEnd) {
611
- const detached = this.detached[at] === true;
612
- const refused = effect.inFunction === true && this.blocks[at].body === undefined;
916
+ const body = this.blocks[at].body;
917
+ const refused = effect.inFunction === true && body === undefined;
613
918
  if (effect.all !== undefined)
614
- this.entries.push({ at, state: effect.all === "reset" ? "reset" : "unknown", detached: false, andRun: false });
919
+ this.entries.push({ at, standing: this.standingOf(at), state: effect.all === "reset" ? "reset" : "unknown", detached: false, andRun: false });
615
920
  for (const b of effect.bindings) {
921
+ const standing = this.standingOf(at, b.name);
922
+ const detached = this.detachedAt(at, standing) || b.prefix === true;
616
923
  this.entries.push({
617
- at, name: b.name, state: refused ? "unknown" : b.state, detached: detached || b.prefix === true, andRun,
924
+ at, standing, name: b.name, state: refused ? "unknown" : b.state, detached, andRun,
618
925
  ...(b.loopVar === true && loopEnd !== undefined ? { certainUntil: loopEnd } : {}),
619
926
  ...(b.floor !== undefined && b.floor.length > 0 ? { floor: b.floor } : {}),
620
927
  });
928
+ if (b.scope === "local" && body !== undefined && !refused && !detached && !andRun)
929
+ this.localDeclarations.push({ at, name: b.name, body: body.id, standing });
621
930
  }
622
931
  }
623
- leftBody(at, body, j) {
624
- if (this.blocks[at].after <= body.base)
625
- return true;
626
- for (let k = at + 1; k <= j; k++)
627
- if (this.blocks[k].lowest <= body.base)
628
- return true;
629
- return false;
932
+ lostAt(u, j) {
933
+ if (u.body === undefined)
934
+ return this.mayRunBefore(u.at, j);
935
+ const readerBody = this.blocks[j].body;
936
+ return readerBody !== undefined && readerBody.id !== u.body.id;
630
937
  }
631
938
  kill(at, names) {
939
+ const standing = this.standingOf(at);
632
940
  if (names === "all") {
633
- this.entries.push({ at, state: "unknown", detached: false, andRun: false });
941
+ this.entries.push({ at, standing, state: "unknown", detached: false, andRun: false });
634
942
  return;
635
943
  }
636
944
  for (const name of names)
637
- this.entries.push({ at, name, state: "unknown", detached: false, andRun: false });
945
+ this.entries.push({ at, standing, name, state: "unknown", detached: false, andRun: false });
638
946
  }
639
- tableAt(j, andRunStart) {
947
+ tableAt(j, andRunStart, where) {
640
948
  const certain = (e) => {
641
949
  if (e.certainUntil !== undefined && j < e.certainUntil)
642
950
  return true;
643
- if (e.detached || !this.heldThrough(e.at, j))
951
+ if (e.detached || !this.heldThrough(e, j))
644
952
  return false;
645
953
  return !e.andRun || e.at >= andRunStart;
646
954
  };
647
955
  const readerBody = this.blocks[j].body;
648
- const lost = (u) => {
649
- if (u.body === undefined)
650
- return this.mayRunBefore(u.at, j);
651
- if (readerBody !== undefined && readerBody.id !== u.body.id)
652
- return true;
653
- return u.at < j && this.leftBody(u.at, u.body, j);
654
- };
655
- const before = (e) => e.at < j || (e.at === j && e.state === "reset");
956
+ const lost = (u) => this.lostAt(u, j);
957
+ const before = (e) => (e.at < j || (e.at === j && e.state === "reset")) && this.visible(e, j);
656
958
  const given = (name, at, integer) => this.attributesAt.some((x) => (x.name === undefined || x.name === name) && (integer !== true || x.kind === "integer") && x.at !== at && this.mayRunBefore(x.at, at));
657
- const stateOf = (name) => {
658
- if (shellKeepsName(name))
659
- return "unknown";
660
- if (this.unreadable.some((u) => (u.name === undefined || u.name === name) && lost(u)))
661
- return "unknown";
959
+ const walk = (name, start) => {
662
960
  const values = [];
663
961
  const add = (vs) => { for (const v of vs)
664
962
  if (!values.some((x) => sameValue(x, v)))
665
963
  values.push(v); };
666
964
  for (let i = this.entries.length - 1; i >= 0; i--) {
667
965
  const e = this.entries[i];
668
- if (!before(e) || (e.name !== undefined && e.name !== name))
966
+ if (!before(e) || (e.name !== undefined && !speaksFor(e.name, name)))
967
+ continue;
968
+ if (e.state === "reset" && isBuiltinKey(name))
669
969
  continue;
670
- const state = e.state === "reset" ? (name === "HOME" && this.boundAnywhere("HOME") ? "unknown" : this.initial(name)) : e.state;
970
+ const state = e.state === "reset" ? ((name === "HOME" && this.boundAnywhere("HOME")) || this.bindsInText(name) ? "unknown" : this.initial(name)) : e.state;
671
971
  if (state === "unknown")
672
- return "unknown";
972
+ return { state: "unknown" };
673
973
  if (e.name !== undefined && given(e.name, e.at))
674
- return "unknown";
974
+ return { state: "unknown" };
675
975
  add(state);
676
976
  if (certain(e))
677
- return values;
977
+ return { state: values, decided: e };
678
978
  }
679
- const start = this.initial(name);
680
979
  if (start === "unknown")
681
- return "unknown";
980
+ return { state: "unknown" };
682
981
  add(start);
683
- return values;
982
+ return { state: values };
983
+ };
984
+ const later = this.boundLater(j);
985
+ const boundLater = (name) => later === "all" || later.has(name) || (isBuiltinKey(name) && later.has(BUILTINS_ALL));
986
+ const stateOf = (name) => {
987
+ if (shellKeepsName(name))
988
+ return "unknown";
989
+ if (this.unreadable.some((u) => speaksFor(u.name, name) && lost(u)))
990
+ return "unknown";
991
+ if (!isWorkingDirectoryName(name)) {
992
+ const walked = walk(name, this.startOf(name));
993
+ const own = walked.decided !== undefined && walked.decided.state !== "reset" && readerBody !== undefined && walked.decided.standing.body?.id === readerBody.id;
994
+ return boundLater(name) && !own ? "unknown" : walked.state;
995
+ }
996
+ if (boundLater(name))
997
+ return "unknown";
998
+ const assigned = walk(name, []);
999
+ if (assigned.decided !== undefined && where !== undefined && readerBody === undefined && assigned.decided.at > where.movedAt)
1000
+ return assigned.state;
1001
+ const thread = readerBody === undefined ? where?.[name] ?? "unknown" : "unknown";
1002
+ if (thread === "unknown" || assigned.state === "unknown")
1003
+ return "unknown";
1004
+ const held = assigned.state;
1005
+ return [...held, ...thread.filter((v) => !held.some((x) => sameValue(x, v)))];
684
1006
  };
685
1007
  const touched = (name) => this.entries.some((e) => before(e) && (e.name === undefined || e.name === name));
1008
+ let rebound = this.startRebound;
1009
+ for (const e of this.entries)
1010
+ if (e.state !== "reset" && (readerBody !== undefined ? e.at !== j : before(e)))
1011
+ rebound = joinRebound(rebound, e.name === undefined ? "all" : [e.name]);
1012
+ for (const u of this.unreadable)
1013
+ if (lost(u))
1014
+ rebound = joinRebound(rebound, u.name === undefined ? "all" : [u.name]);
1015
+ const settled = joinRebound(rebound, later);
686
1016
  return {
687
1017
  stateOf,
688
1018
  isInteger: (name) => SHELL_INTEGER_VARIABLES.has(name) || given(name, j, true),
689
- ifsTouched: touched("IFS"),
690
- homeTouched: this.homeStartsTouched || touched("HOME"),
691
- floorOf: (name) => this.entries.filter((e) => e.at < j && e.name === name).flatMap((e) => e.floor ?? []),
1019
+ ifsTouched: touched("IFS") || boundLater("IFS"),
1020
+ homeTouched: this.homeStartsTouched || touched("HOME") || boundLater("HOME"),
1021
+ floorOf: (name) => [...(this.startFloors.get(name) ?? []), ...this.entries.filter((e) => e.at < j && e.name === name).flatMap((e) => e.floor ?? [])],
692
1022
  inherited: this.inheritedAt(j),
1023
+ rebound: settled,
1024
+ providedByShell: (name) => settled !== "all" && !settled.has(name),
1025
+ functionState: (name) => {
1026
+ const held = stateOf(functionKey(name));
1027
+ if (held === "unknown")
1028
+ return "maybe";
1029
+ return !held.some(isDefinedValue) ? "absent" : held.length > 1 ? "maybe" : "defined";
1030
+ },
1031
+ builtinState: (name) => {
1032
+ const held = stateOf(builtinKey(name));
1033
+ if (held === "unknown")
1034
+ return "maybe";
1035
+ return held.every(isDisabledValue) ? "disabled" : held.some(isDisabledValue) ? "maybe" : "enabled";
1036
+ },
693
1037
  };
694
1038
  }
695
1039
  }