@sema-agent/core 7.15.0 → 7.17.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 (287) hide show
  1. package/CHANGELOG.md +202 -0
  2. package/dist/agents/builtin-agents.d.ts +3 -3
  3. package/dist/agents/cross-session-envelope.d.ts +0 -1
  4. package/dist/agents/cross-session-envelope.js +0 -1
  5. package/dist/agents/peer-notices.d.ts +0 -9
  6. package/dist/agents/peer-notices.js +0 -63
  7. package/dist/agents/subagent.js +7 -15
  8. package/dist/brain/request-params.d.ts +2 -2
  9. package/dist/config/defaults.d.ts +0 -7
  10. package/dist/config/defaults.js +0 -2
  11. package/dist/core/artifact-host.d.ts +218 -0
  12. package/dist/core/artifact-host.js +92 -0
  13. package/dist/core/ask-origin.d.ts +29 -3
  14. package/dist/core/ask-origin.js +17 -9
  15. package/dist/core/ask-question.d.ts +25 -0
  16. package/dist/core/ask-question.js +4 -0
  17. package/dist/core/ask-unresolvable-notice.d.ts +30 -21
  18. package/dist/core/ask-unresolvable-notice.js +16 -8
  19. package/dist/core/auto-compaction.d.ts +10 -10
  20. package/dist/core/auto-mode-arming.d.ts +2 -2
  21. package/dist/core/background-agent-store.d.ts +5 -5
  22. package/dist/core/background-shell.d.ts +1 -1
  23. package/dist/core/checkpoint-execution-record.d.ts +0 -3
  24. package/dist/core/checkpoint-execution-record.js +0 -4
  25. package/dist/core/checkpoint-store.d.ts +71 -99
  26. package/dist/core/checkpoint-store.js +9 -16
  27. package/dist/core/context-edit.d.ts +36 -104
  28. package/dist/core/context-edit.js +37 -60
  29. package/dist/core/effective-path-target.d.ts +68 -8
  30. package/dist/core/effective-path-target.js +42 -30
  31. package/dist/core/engine-notice.d.ts +46 -32
  32. package/dist/core/env-budget.d.ts +31 -0
  33. package/dist/core/env-budget.js +39 -0
  34. package/dist/core/exec-output-tail.d.ts +5 -5
  35. package/dist/core/file-history-store.js +3 -6
  36. package/dist/core/fs-write-gate-policy.d.ts +1 -1
  37. package/dist/core/fs-write-gate-policy.js +3 -3
  38. package/dist/core/gate-lanes.js +9 -15
  39. package/dist/core/governance-codes.d.ts +1 -1
  40. package/dist/core/governance-codes.js +4 -0
  41. package/dist/core/hands-band.d.ts +1 -1
  42. package/dist/core/hooks.d.ts +18 -17
  43. package/dist/core/lsp-session.d.ts +1 -1
  44. package/dist/core/lsp.d.ts +1 -1
  45. package/dist/core/lsp.js +5 -4
  46. package/dist/core/mcp.d.ts +5 -5
  47. package/dist/core/mcp.js +4 -48
  48. package/dist/core/memory-engine/delegation-settlement.d.ts +37 -12
  49. package/dist/core/memory-engine/delegation-settlement.js +128 -39
  50. package/dist/core/memory-engine/engine.d.ts +9 -8
  51. package/dist/core/memory-engine/engine.js +115 -120
  52. package/dist/core/memory-engine/file-backend.d.ts +17 -5
  53. package/dist/core/memory-engine/file-backend.js +78 -34
  54. package/dist/core/memory-engine/index.d.ts +2 -2
  55. package/dist/core/memory-engine/index.js +2 -2
  56. package/dist/core/memory-engine/layout.d.ts +152 -54
  57. package/dist/core/memory-engine/layout.js +441 -104
  58. package/dist/core/memory-engine/types.d.ts +8 -3
  59. package/dist/core/memory-engine/types.js +5 -0
  60. package/dist/core/memory-recall.d.ts +0 -8
  61. package/dist/core/memory.d.ts +1 -1
  62. package/dist/core/oracle-isolation.js +2 -2
  63. package/dist/core/parent-spec-seat.d.ts +66 -0
  64. package/dist/core/parent-spec-seat.js +47 -0
  65. package/dist/core/permission-rule-model.d.ts +11 -6
  66. package/dist/core/permission-rule-model.js +53 -37
  67. package/dist/core/permission-rules.js +8 -3
  68. package/dist/core/protocol-naming.d.ts +2 -2
  69. package/dist/core/remote-env.d.ts +1 -1
  70. package/dist/core/retired-keys.d.ts +19 -0
  71. package/dist/core/retired-keys.js +15 -0
  72. package/dist/core/runner/abort-race.d.ts +3 -3
  73. package/dist/core/runner/active-skill-scope.d.ts +2 -2
  74. package/dist/core/runner/active-skill-scope.js +3 -3
  75. package/dist/core/runner/assemble-result.d.ts +42 -40
  76. package/dist/core/runner/assemble-result.js +5 -4
  77. package/dist/core/runner/checkpoint-scope.d.ts +4 -4
  78. package/dist/core/runner/clock-and-limits.d.ts +3 -3
  79. package/dist/core/runner/compaction-call-options.d.ts +35 -99
  80. package/dist/core/runner/compaction-knobs.d.ts +4 -4
  81. package/dist/core/runner/compaction-seams.d.ts +5 -5
  82. package/dist/core/runner/contracts.d.ts +232 -233
  83. package/dist/core/runner/decide-continuation.d.ts +6 -6
  84. package/dist/core/runner/denial-limit-arms.d.ts +8 -8
  85. package/dist/core/runner/derived-route-fallback.d.ts +2 -2
  86. package/dist/core/runner/gate-exit.d.ts +6 -6
  87. package/dist/core/runner/gate-exit.js +15 -1
  88. package/dist/core/runner/git-status-frame.d.ts +7 -7
  89. package/dist/core/runner/halt-attribution.d.ts +35 -0
  90. package/dist/core/runner/halt-attribution.js +16 -0
  91. package/dist/core/runner/inherited-ask-grants.d.ts +6 -6
  92. package/dist/core/runner/memory-capture-optout.d.ts +1 -1
  93. package/dist/core/runner/memory-consolidation-driver.d.ts +4 -4
  94. package/dist/core/runner/memory-consolidation.d.ts +6 -8
  95. package/dist/core/runner/memory-consolidation.js +0 -1
  96. package/dist/core/runner/park-commit.d.ts +6 -6
  97. package/dist/core/runner/permission-rule-lanes.d.ts +19 -19
  98. package/dist/core/runner/prepare-acquire-reconcile.d.ts +4 -4
  99. package/dist/core/runner/prepare-artifact.d.ts +53 -0
  100. package/dist/core/runner/prepare-artifact.js +77 -0
  101. package/dist/core/runner/prepare-ask-lane.d.ts +3 -3
  102. package/dist/core/runner/prepare-boundary-parks.d.ts +3 -3
  103. package/dist/core/runner/prepare-caps-and-workflow.d.ts +9 -7
  104. package/dist/core/runner/prepare-caps-and-workflow.js +2 -3
  105. package/dist/core/runner/prepare-config-doors.d.ts +24 -24
  106. package/dist/core/runner/prepare-config-doors.js +5 -2
  107. package/dist/core/runner/prepare-context-lane.d.ts +8 -8
  108. package/dist/core/runner/prepare-context-lane.js +2 -13
  109. package/dist/core/runner/prepare-defer-classify.d.ts +2 -2
  110. package/dist/core/runner/prepare-delegation-surface.d.ts +1 -1
  111. package/dist/core/runner/prepare-file-history.d.ts +3 -3
  112. package/dist/core/runner/prepare-file-history.js +3 -52
  113. package/dist/core/runner/prepare-gate-stations.d.ts +5 -5
  114. package/dist/core/runner/prepare-hands-readface.d.ts +35 -38
  115. package/dist/core/runner/prepare-hands-readface.js +3 -2
  116. package/dist/core/runner/prepare-inherited-gate.d.ts +9 -6
  117. package/dist/core/runner/prepare-inherited-gate.js +7 -8
  118. package/dist/core/runner/prepare-listings.d.ts +3 -3
  119. package/dist/core/runner/prepare-lsp.d.ts +3 -3
  120. package/dist/core/runner/prepare-memory-engine-session.d.ts +5 -5
  121. package/dist/core/runner/prepare-memory.d.ts +4 -6
  122. package/dist/core/runner/prepare-memory.js +10 -9
  123. package/dist/core/runner/prepare-offload-wrappers.d.ts +2 -2
  124. package/dist/core/runner/prepare-park-ask.d.ts +6 -6
  125. package/dist/core/runner/prepare-policy-chain.d.ts +7 -7
  126. package/dist/core/runner/prepare-policy-chain.js +15 -30
  127. package/dist/core/runner/prepare-prompt-assembly.js +1 -1
  128. package/dist/core/runner/prepare-prompt-inputs.d.ts +5 -5
  129. package/dist/core/runner/prepare-protocol-tools.d.ts +1 -1
  130. package/dist/core/runner/prepare-question-face.d.ts +4 -4
  131. package/dist/core/runner/prepare-run-refs.d.ts +11 -11
  132. package/dist/core/runner/prepare-safety-scan.d.ts +2 -2
  133. package/dist/core/runner/prepare-suspend-saga.d.ts +4 -4
  134. package/dist/core/runner/prepare-suspend-saga.js +0 -2
  135. package/dist/core/runner/prepare-task.d.ts +12 -12
  136. package/dist/core/runner/prepare-task.js +10 -9
  137. package/dist/core/runner/prepare-tool-disclosure-mount.d.ts +2 -3
  138. package/dist/core/runner/prepare-wiring-manifest.d.ts +4 -4
  139. package/dist/core/runner/prepare-wiring-manifest.js +9 -7
  140. package/dist/core/runner/prepare-workspace-restore.d.ts +1 -1
  141. package/dist/core/runner/remote-env-retry.d.ts +3 -3
  142. package/dist/core/runner/resume-admission.d.ts +1 -1
  143. package/dist/core/runner/resume-admission.js +2 -1
  144. package/dist/core/runner/resume-claim.d.ts +1 -1
  145. package/dist/core/runner/resume-internals-and-config.d.ts +1 -1
  146. package/dist/core/runner/resume-internals-and-config.js +4 -0
  147. package/dist/core/runner/resume-policy-outcome.d.ts +1 -1
  148. package/dist/core/runner/resume-preflight.d.ts +1 -1
  149. package/dist/core/runner/resume-review-outcome.d.ts +1 -1
  150. package/dist/core/runner/retired-runner-deps.d.ts +3 -0
  151. package/dist/core/runner/retired-runner-deps.js +7 -0
  152. package/dist/core/runner/run-brain-sinks.d.ts +1 -1
  153. package/dist/core/runner/run-clock-and-content.d.ts +4 -4
  154. package/dist/core/runner/run-compaction-machinery.d.ts +3 -3
  155. package/dist/core/runner/run-git-lane.d.ts +1 -1
  156. package/dist/core/runner/run-harness-handlers.d.ts +2 -2
  157. package/dist/core/runner/run-harness-handlers.js +2 -3
  158. package/dist/core/runner/run-identity-wiring.d.ts +4 -4
  159. package/dist/core/runner/run-leg.d.ts +3 -3
  160. package/dist/core/runner/run-notification-lane.d.ts +2 -2
  161. package/dist/core/runner/run-reasoning-seat.d.ts +2 -2
  162. package/dist/core/runner/run-settle-and-teardown.d.ts +5 -5
  163. package/dist/core/runner/run-settle-and-teardown.js +3 -1
  164. package/dist/core/runner/run-telemetry-and-budget-seats.d.ts +2 -2
  165. package/dist/core/runner/run-terminal-adoption.d.ts +5 -5
  166. package/dist/core/runner/runtask.d.ts +14 -14
  167. package/dist/core/runner/session-file-state-replay.d.ts +3 -3
  168. package/dist/core/runner/session-file-state-replay.js +3 -3
  169. package/dist/core/runner/session-rule-policy.d.ts +2 -2
  170. package/dist/core/runner/session-rule-policy.js +3 -4
  171. package/dist/core/runner/steer-admission.d.ts +2 -2
  172. package/dist/core/runner/stream-halt-verbs.d.ts +1 -1
  173. package/dist/core/runner/stream-halt-verbs.js +1 -1
  174. package/dist/core/runner/stream-reap.d.ts +1 -1
  175. package/dist/core/runner/stream-steer-verb.js +1 -4
  176. package/dist/core/runner/synthetic-tools.d.ts +8 -8
  177. package/dist/core/runner/teardown-bounded.d.ts +2 -2
  178. package/dist/core/runner/tool-defer-gate.d.ts +1 -1
  179. package/dist/core/runner/tool-disclosure.d.ts +33 -33
  180. package/dist/core/runner/tool-end-body.d.ts +3 -3
  181. package/dist/core/runner/tool-face-overlay.d.ts +2 -2
  182. package/dist/core/runner/tool-output-projection.d.ts +2 -2
  183. package/dist/core/runner/turn-attachments.d.ts +53 -53
  184. package/dist/core/runner/usage-accounting.d.ts +4 -4
  185. package/dist/core/runner/workspace-path.d.ts +1 -1
  186. package/dist/core/runner/workspace-path.js +3 -0
  187. package/dist/core/runner-deps.d.ts +30 -49
  188. package/dist/core/safe-notify.d.ts +1 -1
  189. package/dist/core/sensitive-path-policy.d.ts +1 -1
  190. package/dist/core/sensitive-path-policy.js +4 -4
  191. package/dist/core/session.d.ts +2 -2
  192. package/dist/core/skill-tool-specifier.d.ts +1 -1
  193. package/dist/core/skills-directory.d.ts +1 -1
  194. package/dist/core/store-contracts/checkpoint-store-contract.js +1 -1
  195. package/dist/core/strategy-store.d.ts +8 -11
  196. package/dist/core/task-event.d.ts +20 -17
  197. package/dist/core/task-limits.d.ts +1 -1
  198. package/dist/core/task-notification.d.ts +5 -5
  199. package/dist/core/task-registry-agent.d.ts +5 -5
  200. package/dist/core/task-registry-monitor.d.ts +2 -2
  201. package/dist/core/task-registry-shared.d.ts +27 -27
  202. package/dist/core/task-registry-shared.js +3 -13
  203. package/dist/core/task-registry.d.ts +8 -8
  204. package/dist/core/task-result.d.ts +37 -37
  205. package/dist/core/task-spec.d.ts +5 -5
  206. package/dist/core/task-stream.d.ts +16 -11
  207. package/dist/core/tool-catalog-entries.d.ts +1 -0
  208. package/dist/core/tool-catalog-entries.js +5 -0
  209. package/dist/core/tool-conformance.d.ts +0 -2
  210. package/dist/core/tool-conformance.js +1 -3
  211. package/dist/core/tool-errors.d.ts +5 -0
  212. package/dist/core/tool-errors.js +1 -0
  213. package/dist/core/tool-policy.d.ts +51 -22
  214. package/dist/core/tool-policy.js +28 -5
  215. package/dist/core/tool-result-budget.d.ts +1 -1
  216. package/dist/core/tool-result-store.d.ts +11 -11
  217. package/dist/core/tool-spec.d.ts +34 -38
  218. package/dist/core/tools.d.ts +2 -2
  219. package/dist/core/trace.d.ts +12 -15
  220. package/dist/core/untrusted-text.d.ts +1 -1
  221. package/dist/core/wiring-manifest.d.ts +4 -3
  222. package/dist/core/workflow-journal-store.d.ts +11 -11
  223. package/dist/engine/execution-env/node-execution-env.d.ts +3 -2
  224. package/dist/engine/execution-env/node-execution-env.js +4 -2
  225. package/dist/engine/harness/agent-harness.d.ts +47 -4
  226. package/dist/engine/harness/agent-harness.js +52 -9
  227. package/dist/engine/llm/types.d.ts +1 -1
  228. package/dist/engine/loop/agent-loop.js +15 -8
  229. package/dist/engine/loop/types.d.ts +5 -0
  230. package/dist/index.d.ts +21 -16
  231. package/dist/index.js +17 -12
  232. package/dist/internal/harness.d.ts +1 -0
  233. package/dist/orchestration/run-spec.d.ts +3 -0
  234. package/dist/orchestration/run-spec.js +3 -3
  235. package/dist/orchestration/run-workflow-tool.d.ts +12 -6
  236. package/dist/orchestration/run-workflow-tool.js +23 -5
  237. package/dist/orchestration/workflow-primitives.d.ts +4 -2
  238. package/dist/orchestration/workflow-primitives.js +1 -4
  239. package/dist/orchestration/workflow-types.d.ts +34 -4
  240. package/dist/orchestration/workflow-types.js +2 -0
  241. package/dist/orchestration/workflow.d.ts +39 -7
  242. package/dist/orchestration/workflow.js +234 -113
  243. package/dist/prompt-assembly/assemble.d.ts +2 -2
  244. package/dist/prompt-assembly/assemble.js +9 -9
  245. package/dist/prompt-assembly/composer.d.ts +6 -7
  246. package/dist/prompt-assembly/composer.js +10 -10
  247. package/dist/prompt-assembly/epoch.js +1 -1
  248. package/dist/prompt-assembly/event-registry.d.ts +0 -21
  249. package/dist/prompt-assembly/packs/sema-default.js +30 -30
  250. package/dist/prompt-assembly/types.d.ts +14 -14
  251. package/dist/prompts/coordinator.d.ts +0 -13
  252. package/dist/prompts/coordinator.js +0 -3
  253. package/dist/stores/file/checkpoint-store.js +1 -5
  254. package/dist/stores/file/file-history-store.js +2 -2
  255. package/dist/stores/file/permission-rule-store.d.ts +4 -35
  256. package/dist/stores/file/permission-rule-store.js +4 -148
  257. package/dist/tools/artifact/artifact-text.d.ts +62 -0
  258. package/dist/tools/artifact/artifact-text.js +68 -0
  259. package/dist/tools/artifact/artifact-tool.d.ts +52 -0
  260. package/dist/tools/artifact/artifact-tool.js +351 -0
  261. package/dist/tools/artifact/local-stub.d.ts +26 -0
  262. package/dist/tools/artifact/local-stub.js +296 -0
  263. package/dist/tools/fs/bash-readonly-classifier.d.ts +114 -48
  264. package/dist/tools/fs/bash-readonly-classifier.js +171 -60
  265. package/dist/tools/fs/encoding.d.ts +31 -40
  266. package/dist/tools/fs/fs-bash.d.ts +49 -45
  267. package/dist/tools/fs/fs-bash.js +19 -27
  268. package/dist/tools/fs/fs-pdf.d.ts +8 -8
  269. package/dist/tools/fs/fs-search-tools.d.ts +4 -4
  270. package/dist/tools/fs/fs-search-tools.js +5 -2
  271. package/dist/tools/fs/fs-shared.d.ts +146 -158
  272. package/dist/tools/fs/fs-shared.js +3 -11
  273. package/dist/tools/fs/fs-write.d.ts +8 -8
  274. package/dist/tools/fs/gh-rate-limit.d.ts +13 -14
  275. package/dist/tools/fs/index.d.ts +78 -78
  276. package/dist/tools/fs/index.js +4 -1
  277. package/dist/tools/fs/notebook.d.ts +24 -25
  278. package/dist/tools/fs/pdf.d.ts +3 -3
  279. package/dist/tools/fs/read-deny.d.ts +22 -22
  280. package/dist/tools/fs/read-face.d.ts +21 -24
  281. package/dist/tools/fs/repo-map.d.ts +8 -8
  282. package/dist/tools/fs/safety.d.ts +233 -130
  283. package/dist/tools/fs/safety.js +131 -31
  284. package/dist/tools/fs/search.d.ts +63 -71
  285. package/dist/tools/fs/search.js +8 -6
  286. package/package.json +6 -2
  287. package/test/export-surface.snapshot.json +119 -39
@@ -1,22 +1,22 @@
1
1
  /**
2
2
  * Bare command names `bash_readonly` permits out of the box, ALSO the default reversible set for the
3
- * design/80 D-2 {@link import("./fs-bash.js").bashReversibilityProbe} classifier. **Coarse first filter, NOT a security
3
+ * The {@link import("./fs-bash.js").bashReversibilityProbe} classifier. **Coarse first filter, NOT a security
4
4
  * boundary**: {@link coarseReadonlyCheck} matches only the command NAME, so a listed command with a
5
5
  * writing flag (e.g. `find -delete`, `sort -o`, `tee`) would still write. Such commands are therefore
6
6
  * kept OFF this default — the list is curated to commands with NO write/mutation mode under ANY args, so
7
7
  * the `effect:"read"` declaration (relied on by wake/resume reconcile + the verifier read-only boundary)
8
8
  * AND the classifier's "reversible" promise both stay truthful. The deployment's tool-policy gate is the
9
- * authoritative control (design/44 §5, council blocker #1); anything that can mutate state or run arbitrary
9
+ * authoritative control (council blocker #1); anything that can mutate state or run arbitrary
10
10
  * code belongs on the full `bash` (effect:write, gated), not here. A deployment may widen this list,
11
11
  * accepting that responsibility.
12
12
  *
13
- * design/80 D-2 final-council MAJOR: `date` (`-s`/`--set` → CLOCK_SETTIME), `hostname` (`<name>` → kernel
13
+ * Deliberately ABSENT: `date` (`-s`/`--set` → CLOCK_SETTIME), `hostname` (`<name>` → kernel
14
14
  * hostname), and `file` (`-C -m` → compiles/writes a magic file) were REMOVED — each is read-only by NAME
15
15
  * but state-MUTATING with args, which an argv[0]-only filter cannot tell apart. Leaving them in defeated
16
16
  * both the `effect:read` truthfulness here and the classifier's irreversibility promise (a `date -s` would
17
17
  * auto-allow an irreversible clock jump under `shellGate:"classify"`).
18
18
  *
19
- * backlog #482 (CC parity): rows 3-4 are the CC-anchored expansion — the members of CC's safe-command
19
+ * Rows 3-4 are the CC-anchored expansion — the members of CC's safe-command
20
20
  * set (pretty223.js:420513-420565 `e6s`; identical in the 220 corpus; the 220→245 campaign diff records
21
21
  * no change on this face) that satisfy THIS list's curation bar (no write/mutation mode under any args)
22
22
  * without new stdin-floor/option-value modeling: pure status/computation printers (`cal`…`sleep` — none
@@ -27,7 +27,7 @@
27
27
  * `uniq` (second positional is an OUTPUT file; CC allows a flags-only regex form this filter cannot
28
28
  * express), `printf` (builtin `-v var` assigns), `find` (CC allows only a regex excluding
29
29
  * `-delete`/`-exec`/…), and the bare-stdin text filters (`od`/`strings`/`nl`/`tsort`/`pr`/…) whose
30
- * value-taking options defeat the stdin-floor operand count without a per-verb option-value model (#109)
30
+ * value-taking options defeat the stdin-floor operand count without a per-verb option-value model
31
31
  * — those are a follow-on slice, not a silent drop.
32
32
  */
33
33
  /** The verdict every unresolvable / out-of-root / unbounded finding ends on. The findings differ in what
@@ -35,7 +35,7 @@
35
35
  export declare const NOT_AUTO_ALLOWED = "\u2014 not auto-allowed";
36
36
  export declare const BASH_READONLY_DEFAULT_ALLOW: readonly string[];
37
37
  /**
38
- * backlog #482 slice 2 — the CLASSIFY face's default allow set: the shared list PLUS the verbs that are
38
+ * The CLASSIFY face's default allow set: the shared list PLUS the verbs that are
39
39
  * admissible only where the compound classifier's per-verb judgment runs, and NOT on the shared list's
40
40
  * other consumer faces:
41
41
  * · `find` — read-only only when no CC `aCy` dangerous predicate token is present (guard arm);
@@ -123,13 +123,13 @@ export declare function parseLeadingCommandName(command: string, options?: Leadi
123
123
  * with no shell operators. It validates the NAME only (+ blocks operators/path-prefix/env-assignment); it
124
124
  * does NOT inspect arguments for write flags — keeping the allowlist free of write-capable commands and
125
125
  * the policy gate are what make `effect:"read"` truthful. Returns a reason when rejected, else undefined.
126
- * design/154: this `effect:"read"` DECLARATION face deliberately stays strict-single-command; only the
126
+ * This `effect:"read"` DECLARATION face deliberately stays strict-single-command; only the
127
127
  * classify face ({@link classifyCompoundReadonly} via {@link import("./fs-bash.js").bashReversibilityProbe}) segments compounds. */
128
128
  export declare function coarseReadonlyCheck(command: string, allow: ReadonlySet<string>, options?: LeadingCommandNameOptions): string | undefined;
129
129
  /**
130
130
  * Does this text carry a bare redirection operator — the ONE metacharacter family
131
- * {@link splitShellCompoundSegments} can be asked to tolerate at its whole-string gate (#490 修①,
132
- * `redirection: "tolerate"`)?
131
+ * {@link splitShellCompoundSegments} can be asked to tolerate at its whole-string gate
132
+ * (`redirection: "tolerate"`)?
133
133
  *
134
134
  * Exported because the tolerating caller owes a PER-SEGMENT judgement in its place, and that judgement
135
135
  * must read the same character class this module tolerated — two hand-kept lists would drift, and a
@@ -162,7 +162,7 @@ export interface ShellCompoundSegments {
162
162
  * bash's quoted regions and the unquoted connectors are exactly bash's command boundaries. Callers
163
163
  * that tolerate a narrow redirection subset (the read-only classify face and its two data-free
164
164
  * spellings) remove those words BEFORE calling; nothing here restores them. `redirection:
165
- * "tolerate"` (#490 修①) narrows this step to {@link rejectedSansRedirection} — the mask argument
165
+ * "tolerate"` narrows this step to {@link rejectedSansRedirection} — the mask argument
166
166
  * is untouched (`<`/`>` neither quote nor bound) and the refusal moves to the caller's per-segment
167
167
  * vetting via {@link carriesShellRedirection}. The default refuses the whole string as it always did.
168
168
  * 2. one trailing `;` is stripped — a no-op terminator, not an empty command. OPTIONAL, because it is
@@ -189,7 +189,7 @@ export declare function splitShellCompoundSegments(source: string, options?: {
189
189
  reject: string;
190
190
  };
191
191
  /**
192
- * RB-412 — the READ-BOUNDARY face of the read-only classification (opt-in).
192
+ * The READ-BOUNDARY face of the read-only classification (opt-in).
193
193
  *
194
194
  * The allowlist vets `argv[0]` only, so until this face existed every listed reader could name ANY
195
195
  * path: `ls /etc` and `cat /etc/passwd` classified read-only, and a deployment whose manual-mode shell
@@ -198,7 +198,7 @@ export declare function splitShellCompoundSegments(source: string, options?: {
198
198
  * pretty220 @457568) and renders an approval option naming the directory (@905642 (cli250.js:66007)).
199
199
  *
200
200
  * Supplying this object turns the check ON; omitting it leaves the classifier byte-identical to its
201
- * pre-RB-412 behaviour, so a consumer pinned to an older calling convention is unaffected.
201
+ * name-only behaviour, so a consumer pinned to an older calling convention is unaffected.
202
202
  */
203
203
  export interface BashReadonlyRootBoundary {
204
204
  /** Canonical containment roots — the primary root plus any additional allowed directories. An EMPTY
@@ -209,17 +209,18 @@ export interface BashReadonlyRootBoundary {
209
209
  /** Base for resolving relative operands. Defaults to `roots[0]`. Callers tracking an observable `cd`
210
210
  * should pass the LIVE working directory, or a `..` operand will be judged against the wrong base. */
211
211
  cwd?: string;
212
- /** Expansion for a leading `~`. Without it a `~`-rooted operand is unresolvable and demotes (with no
213
- * out-of-root signal the classifier does not know where it points, which is a different verdict
214
- * from knowing it points outside). */
212
+ /** Expansion for a leading `~` and the value the read faces substitute for the `$HOME` / `${HOME}` word
213
+ * spellings before segmenting ({@link foldHomeVariableSpelling}). Without it a `~`-rooted operand is unresolvable
214
+ * and demotes (with no out-of-root signal — the classifier does not know where it points, which is a
215
+ * different verdict from knowing it points outside). */
215
216
  homeDir?: string;
216
- /** design/199 件B — the sensitive-path read deny judge over LEXICALLY RESOLVED operands: a hit
217
+ /** The sensitive-path read deny judge over LEXICALLY RESOLVED operands: a hit
217
218
  * demotes the command (ask, never auto-allow), independently of the roots — in-root operands are
218
219
  * judged too. Returns the matched pattern, or null. TWO named residuals, both inherited from this
219
- * classifier's declared purity (synchronous, zero I/O — RB-448/RB-451 state the same scope for the
220
+ * classifier's declared purity (synchronous, zero I/O — the same scope stated for the
220
221
  * containment half): ① operand TARGET matching only — no ancestor intersection: the judge sees
221
222
  * the operand's own resolved spelling, never its subtree. The RECURSIVE-reach half of that
222
- * residual has since been narrowed (backlog #222): a listed recursive/expanding verb's path
223
+ * residual has since been narrowed: a listed recursive/expanding verb's path
223
224
  * operand under this wired seat rides {@link CompoundReadonlyVerdict.recursiveReadPaths}
224
225
  * (⊂ undecidedPaths), so `grep -r x ~/` no longer auto-allows — it demotes to ask through the
225
226
  * undecided contract. What REMAINS of ① is the form table's stated open set (see the KNOWN OPEN
@@ -230,29 +231,31 @@ export interface BashReadonlyRootBoundary {
230
231
  * (the enforcing/canonicalizing recheck is the bash_readonly leg's job via checkedPaths; the
231
232
  * classify auto-allow lane has no I/O seat by contract). The structured read faces judge BOTH
232
233
  * views (canonical + lexical) — this seat is the shell lane's honest-friction floor, not its
233
- * security boundary (§3.0). The `bash_readonly` face deliberately does NOT wire this seat (its
234
+ * security boundary. The `bash_readonly` face deliberately does NOT wire this seat (its
234
235
  * roots containment + command allowlist double gate is the deployment's own read-safety
235
236
  * declaration — v1 ruling). */
236
237
  denyMatch?: (resolvedPath: string) => string | null;
237
- /** design/199 件A — the resolved read-face containment state. Under "open" the CONTAINMENT half of
238
+ /** The resolved read-face containment state. Under "open" the CONTAINMENT half of
238
239
  * this boundary is structurally satisfied (an out-of-roots operand is not a demotion; it reports
239
- * as a checked candidate instead), while the deny half above keeps judging in both faces (§2.0).
240
+ * as a checked candidate instead), while the deny half above keeps judging in both faces.
240
241
  * Absent ⇒ "roots" (byte-compat). The `bash_readonly` face never passes this seat — its
241
242
  * containment is load-bearing and never opens. */
242
243
  face?: "open" | "roots";
243
244
  }
244
245
  /**
245
- * RB-412 — the structured verdict of {@link classifyCompoundReadonlyDetailed}. `reason === undefined`
246
+ * The structured verdict of {@link classifyCompoundReadonlyDetailed}. `reason === undefined`
246
247
  * is the read-only verdict; everything else is a demotion.
247
248
  */
248
249
  export interface CompoundReadonlyVerdict {
249
250
  /** Demotion reason (the same string {@link classifyCompoundReadonly} returns), or undefined. */
250
251
  reason?: string;
251
- /** Set only when the SOLE obstacle to the read-only verdict was the root boundary: every segment is
252
- * an allowlisted reader, no blocking/device/backgrounding arm fired, and the offending arguments are
253
- * statically resolved paths outside the roots. A gate can therefore offer the narrow "allow reading
254
- * from <dir>" approval instead of a generic shell prompt. Absent for every other demotion an
255
- * unresolvable path deliberately does NOT carry it (nothing concrete to grant). */
252
+ /** Set when a listed reader's statically resolved path operand lies outside the roots. With `reason` the
253
+ * containment sentence itself, the roots were the SOLE obstacle (every segment a listed reader, no
254
+ * blocking/device/guarded-form arm fired, every operand resolved) and the narrow "allow reading from <dir>"
255
+ * approval would make the command auto-allowable; with `reason` a SHAPE refusal (follow mode, a device, a
256
+ * blocking stdin read, a guarded verb form, multi-cd) or an UNRESOLVABLE-operand refusal (another operand
257
+ * the walk could not read) the finding rides beside the sentence — the read of that path is the same read,
258
+ * so the boundary's objection is stated either way, while the command stays refused after any grant. */
256
259
  outOfRootRead?: true;
257
260
  /** The resolved out-of-root paths, de-duplicated, in first-seen order. Present iff `outOfRootRead`. */
258
261
  outOfRootPaths?: readonly string[];
@@ -262,7 +265,7 @@ export interface CompoundReadonlyVerdict {
262
265
  * tier question, never one the read face itself asked. Structural sibling of `outOfRootRead`. */
263
266
  readDenied?: true;
264
267
  /**
265
- * RB-451 — the paths this scan resolved INSIDE the roots (de-duplicated, first-seen order), i.e. the
268
+ * The paths this scan resolved INSIDE the roots (de-duplicated, first-seen order), i.e. the
266
269
  * candidates a caller holding a filesystem should re-check with symlinks resolved. Absent when there
267
270
  * are none.
268
271
  *
@@ -287,7 +290,7 @@ export interface CompoundReadonlyVerdict {
287
290
  */
288
291
  checkedPaths?: readonly string[];
289
292
  /**
290
- * RB-474 — operands whose spelling carries an UNEXPANDED glob (`*`, `?`, `[…]`, unquoted). Lexical
293
+ * Operands whose spelling carries an UNEXPANDED glob (`*`, `?`, `[…]`, unquoted). Lexical
291
294
  * containment is not decidable for them: the shell expands the pattern AFTER this verdict is made, and
292
295
  * inside a root an expansion can land on a symlink that points out of it (`cat *` where the directory
293
296
  * holds a link to an out-of-root file — reproduced end-to-end, not a theoretical shape).
@@ -312,6 +315,15 @@ export interface CompoundReadonlyVerdict {
312
315
  * and miss the other.
313
316
  */
314
317
  undecidedPaths?: readonly string[];
318
+ /**
319
+ * Operands (written spellings) the walk could NOT resolve at all — a `~user` form, a `~` under no declared
320
+ * home, an argument the shell rewrites (brace/variable/command expansion), a `cd` target it cannot follow
321
+ * (`cd -`, bare `cd`, a pattern). The STRUCTURAL form of the unresolvable sentence: `reason` carries the
322
+ * first one's sentence, this member every one of them, and both survive whatever other sentence (a shape
323
+ * refusal) takes precedence. CONSUMER CONTRACT: non-empty ⇒ the boundary could not read where the command
324
+ * reads — a fail-closed ask (plain: nothing was declared), never a vouch.
325
+ */
326
+ unresolvedOperands?: readonly string[];
315
327
  /**
316
328
  * Operands of a RECURSIVE/EXPANDING read form (`grep -r`, `ls -R`, `du`, … — see
317
329
  * {@link RECURSIVE_READ_FORMS}) judged with a {@link BashReadonlyRootBoundary.denyMatch} seat wired.
@@ -333,8 +345,8 @@ export interface CompoundReadonlyVerdict {
333
345
  recursiveReadPaths?: readonly string[];
334
346
  }
335
347
  /**
336
- * RB-412 — the single minting point for the out-of-root-read approval option text, so a gate rendering
337
- * the prompt and any other consumer cannot drift apart. Shape follows CC 2.1.220 (@905642 (cli250.js:66007)): the option
348
+ * The single minting point for the out-of-root-read approval option text, so a gate rendering
349
+ * the prompt and any other consumer cannot drift apart. Shape follows CC: the option
338
350
  * shows the LAST segment of the grantable directory followed by a separator, not the full path.
339
351
  *
340
352
  * `directory` is the directory to be granted — a caller holding a filesystem (this classifier does not)
@@ -343,14 +355,59 @@ export interface CompoundReadonlyVerdict {
343
355
  * uses the host's native separator.
344
356
  */
345
357
  export declare function formatOutOfRootReadApprovalOption(directory: string): string;
358
+ /** Resolve one operand against the boundary's base, WITHOUT touching the filesystem. Returns undefined
359
+ * when the token cannot be resolved statically — the fail-closed direction, reported as its own
360
+ * demotion rather than silently treated as in-root.
361
+ *
362
+ * The resolution is TEXTUAL, and its limitation runs in BOTH directions (only the first shows up as
363
+ * a refusal, so only that half tends to get reported):
364
+ * · false REFUSAL — a non-canonical spelling of an in-root path (a symlinked `/tmp` → `/private/tmp`
365
+ * prefix) does not textually match the canonical roots and is refused;
366
+ * · false ALLOW — a symlink INSIDE a root that points outside it (`<root>/vendor` → `/etc`) resolves
367
+ * to a textual prefix match, so `cat vendor/passwd` is judged in-root and the real command follows
368
+ * the link. This face is therefore lexical containment, NOT filesystem containment: it is weaker
369
+ * than the structured Read/Grep tools, which canonicalize through `realpath` before comparing
370
+ * (see safety.ts's `canonicalizeAndEnforceRoot`). Closing it means resolving each candidate against
371
+ * the live filesystem, which this function deliberately cannot do (it is synchronous, pure, and
372
+ * shared with the approval-gate face); the seam for it is the ENFORCING caller, which holds the
373
+ * ExecutionEnv.
374
+ *
375
+ * The verdict now carries {@link CompoundReadonlyVerdict.checkedPaths} (the
376
+ * candidates that landed inside), and `createBashReadonlyTool` canonicalizes them on a LOCAL env
377
+ * before running — closing BOTH directions above for that face (an escaping symlink is refused; a
378
+ * non-canonical spelling that resolves back inside is no longer refused). Two residuals stay here by
379
+ * construction, and belong to the caller rather than to this function: the compound/approval-gate face
380
+ * has no filesystem and stays lexical, and a REMOTE env keeps the lexical behaviour (its
381
+ * `canonicalPath` is an RPC per candidate). */
382
+ export declare function resolveOperandLexically(base: string | undefined, operand: string, homeDir: string | undefined): string | undefined;
346
383
  /**
347
- * RB-412 {@link classifyCompoundReadonly} with the structured verdict. The name/operator/blocking arms
384
+ * The home directory's VARIABLE spellings, SUBSTITUTED with the declared value before a read face segments the
385
+ * command: `$HOME` / `${HOME}` at the START of a word (an empty quote pair before it included), unquoted or
386
+ * double-quoted, followed by `/` or by the word's end. Those are exactly the words whose expansion is the home
387
+ * directory and nothing else, so the word is rewritten to what bash hands the program — the value itself, in
388
+ * place, with the word's quote structure untouched (`"$HOME/x"` → `"/home/u/x"`, `$HOME"/x"` → `/home/u"/x"`)
389
+ * — and every arm reads an ordinary absolute path; no tilde is minted, so the tilde-prefix rule of
390
+ * {@link tokenizeSegment} judges only tildes the command actually wrote. Substituted only against a DECLARED
391
+ * home (`homeDir`): with none declared the child's `$HOME` may differ from what `~` falls back to, so the
392
+ * spelling is left as written and meets the substitution hard-reject. The value must survive this file's own
393
+ * reading of the rewritten word: the UNQUOTED spelling only for a value with no `$IFS` whitespace, glob or
394
+ * shell metacharacter (word splitting / pathname expansion / a connector this file would then split on — none
395
+ * of which a real expansion is subject to here), the double-quoted one for any value carrying no `"`, `$`,
396
+ * backtick, backslash or line break (the characters that would change the quote structure or meet the
397
+ * hard-reject). Everything else is left as written: a single-quoted spelling does not expand, and a mid-word
398
+ * or suffixed one (`x$HOME`, `$HOME.bak`, `$HOMES`) still meets the substitution hard-reject. Bails whole on
399
+ * an escape or a backtick in the command (the hard-reject refuses those strings regardless, and the quote
400
+ * walk below is exact only without them) and on unbalanced quoting.
401
+ */
402
+ export declare function foldHomeVariableSpelling(command: string, homeDir: string | undefined): string;
403
+ /**
404
+ * {@link classifyCompoundReadonly} with the structured verdict. The name/operator/blocking arms
348
405
  * run FIRST and unchanged, so an existing demotion keeps its exact reason and never acquires the
349
406
  * out-of-root signal; the boundary scan below only ever converts a would-be READ-ONLY verdict into a
350
- * demotion, which is why omitting `boundary` reproduces the pre-RB-412 behaviour exactly.
407
+ * demotion, which is why omitting `boundary` reproduces the name-only behaviour exactly.
351
408
  */
352
409
  export declare function classifyCompoundReadonlyDetailed(command: string, allow: ReadonlySet<string>, boundary?: BashReadonlyRootBoundary,
353
- /** backlog #482 slice 3 (C4): the poll-loop face passes `iterated:true` over a body REPLICATED
410
+ /** The poll-loop face passes `iterated:true` over a body REPLICATED
354
411
  * `beats` times — a single cd repeated per iteration is a legitimate accumulating shift, not the
355
412
  * ">1 cd = ask for clarity" compound CC refuses (a `for` loop is a sema-only face; CC asks for any
356
413
  * loop). It suppresses ONLY that multi-cd refuse; every read is still threaded + boundary-judged
@@ -359,7 +416,7 @@ opts?: {
359
416
  readonly iterated?: boolean;
360
417
  }): CompoundReadonlyVerdict;
361
418
  /**
362
- * RB-413 — the read boundary ALONE, for the `bash_readonly` face.
419
+ * The read boundary ALONE, for the `bash_readonly` face.
363
420
  *
364
421
  * `bash_readonly` declares `effect:"read"` and is admitted by {@link coarseReadonlyCheck}, an argv[0]-NAME
365
422
  * filter: path operands were invisible to it, so an allowlisted reader could name any file on the host
@@ -379,16 +436,16 @@ opts?: {
379
436
  * kinds — resolved-and-outside (`outOfRootRead`, with `outOfRootPaths`) and could-not-resolve (reason
380
437
  * only) — as a refusal; there is nowhere to degrade to.
381
438
  *
382
- * SCOPE OF THE GUARANTEE (RB-448, both directions): "inside the roots" is LEXICAL containment — see
439
+ * SCOPE OF THE GUARANTEE (both directions): "inside the roots" is LEXICAL containment — see
383
440
  * {@link resolveOperandLexically}. A symlink inside a root that points out of it reads as in-root here,
384
441
  * so this face bounds where a command may NAME a file, not where the kernel will ultimately take it.
385
- * RB-451 — a deployment that needs filesystem-true containment resolves the operands itself, and this
442
+ * A deployment that needs filesystem-true containment resolves the operands itself, and this
386
443
  * verdict hands it the list to resolve ({@link CompoundReadonlyVerdict.checkedPaths}, on both arms).
387
444
  * `createBashReadonlyTool` is that caller for the `bash_readonly` leg and does it on a local env.
388
445
  */
389
446
  export declare function classifySimpleCommandReadBoundary(command: string, boundary: BashReadonlyRootBoundary): CompoundReadonlyVerdict;
390
447
  /**
391
- * #502 — what {@link classifyOutOfRootReadGate} answers. Two members and one rule between them:
448
+ * What {@link classifyOutOfRootReadGate} answers. Two members and one rule between them:
392
449
  * `paths` is EVIDENCE for a `gated` answer, never the answer itself. A caller decides on `gated`.
393
450
  */
394
451
  export interface OutOfRootReadGateVerdict {
@@ -404,7 +461,7 @@ export interface OutOfRootReadGateVerdict {
404
461
  * Exported for that one assertion — production code reads the constant directly. */
405
462
  export declare const COMMAND_LAUNCHERS_FOR_TEST: ReadonlySet<string>;
406
463
  /**
407
- * #502 — the OUT-OF-ROOT READ GATE asked as its OWN question: does any listed reader in this command
464
+ * The OUT-OF-ROOT READ GATE asked as its OWN question: does any listed reader in this command
408
465
  * name a path outside the allowed directories?
409
466
  *
410
467
  * {@link classifyCompoundReadonlyDetailed} answers a different question — "is this whole command
@@ -435,7 +492,7 @@ export declare const COMMAND_LAUNCHERS_FOR_TEST: ReadonlySet<string>;
435
492
  * unchanged on the full face, and this one keeps answering its own question underneath it.
436
493
  * · `face: "open"` is honoured: under the open read face containment is structurally satisfied, an
437
494
  * out-of-roots operand is not a finding, and this gate is silent — a full-read deployment sees no
438
- * gate here, by the same one mechanism §2.0 already defines.
495
+ * gate here, by the same one mechanism the face already defines.
439
496
  *
440
497
  * Answers `gated` with the resolved paths behind it, and NOT gated for every whole-string refusal (an
441
498
  * unparseable grammar, a substitution, a redirection) and for an operand that cannot be resolved
@@ -456,12 +513,12 @@ export declare const COMMAND_LAUNCHERS_FOR_TEST: ReadonlySet<string>;
456
513
  */
457
514
  export declare function classifyOutOfRootReadGate(command: string, allow: ReadonlySet<string>, boundary: BashReadonlyRootBoundary): OutOfRootReadGateVerdict;
458
515
  /**
459
- * design/154 — compound read-only classification, reason-only face. Returns the demotion reason, or
516
+ * Compound read-only classification, reason-only face. Returns the demotion reason, or
460
517
  * undefined when the command classifies read-only. ⚠️ `undefined` is NOT "safe to auto-execute":
461
518
  * the detailed verdict may still carry `undecidedPaths` (operands whose unexpanded spelling — a
462
519
  * glob — is what got checked), and this face discards that field. An auto-allow decision must read
463
520
  * {@link classifyCompoundReadonlyDetailed} and treat a non-empty `undecidedPaths` as ask — the
464
- * engine's own probe does exactly that (fs-bash.ts). RB-412 added the optional `boundary`: with it,
521
+ * engine's own probe does exactly that (fs-bash.ts). The optional `boundary`: with it,
465
522
  * an allowlisted reader whose path arguments leave the allowed directories is demoted too (use the
466
523
  * detailed face when the caller wants to know WHY, e.g. to offer the narrow "allow reading from
467
524
  * <dir>" approval); without it the verdict is exactly what it always was.
@@ -477,7 +534,7 @@ export declare function classifyCompoundReadonly(command: string, allow: Readonl
477
534
  export declare const POLL_LOOP_MAX_BEATS = 120;
478
535
  /**
479
536
  * Per-`sleep` cap (seconds) for {@link classifyBoundedReadonlyPollLoop}. A literal `sleep 99999999`
480
- * is technically bounded but practically a hang — the same hazard class the RB-41 availability arms
537
+ * is technically bounded but practically a hang — the same hazard class the availability arms
481
538
  * demote (a green verdict that blocks until the tool timeout is green in name only).
482
539
  */
483
540
  export declare const POLL_LOOP_MAX_SLEEP_SECONDS = 600;
@@ -497,7 +554,7 @@ export declare const POLL_LOOP_MAX_SLEEP_SECONDS = 600;
497
554
  * maps to a test group in test/poll-loop-classifier.test.ts (G1-G6):
498
555
  * G1 BOUNDED TERMINATION. The loop head must be one of three LITERAL forms with a computable
499
556
  * iteration count ≤ {@link POLL_LOOP_MAX_BEATS} ({@link pollLoopBeatsOf}); `while`/`until` never
500
- * match the skeleton. Every body command terminates: non-`sleep` segments inherit the RB-41/84/
557
+ * match the skeleton. Every body command terminates: non-`sleep` segments inherit the availability/
501
558
  * 108/153 availability arms via {@link classifyCompoundReadonlyDetailed} (blocking stdin, `tail
502
559
  * -f`, unbounded devices all reject), and `sleep` must be a literal ≤
503
560
  * {@link POLL_LOOP_MAX_SLEEP_SECONDS}. Bounded beats × terminating body ⇒ the loop halts.
@@ -512,7 +569,7 @@ export declare const POLL_LOOP_MAX_SLEEP_SECONDS = 600;
512
569
  * the allowlist. Nothing can chain past the vetted segment heads.
513
570
  * G4 READ BOUNDARY UNCHANGED. The reassembled body goes through the boundary scan of
514
571
  * {@link classifyCompoundReadonlyDetailed} with the caller's boundary — out-of-root operands
515
- * reject exactly as on the plain face (RB-412/413, not relaxed by one rule). STRICTER here: a
572
+ * reject exactly as on the plain face (not relaxed by one rule). STRICTER here: a
516
573
  * verdict carrying {@link CompoundReadonlyVerdict.undecidedPaths} (an unexpanded glob) rejects,
517
574
  * because the probe face is reason-only and a repeated read of a runtime-decided target must not
518
575
  * auto-allow.
@@ -534,7 +591,7 @@ export declare const POLL_LOOP_MAX_SLEEP_SECONDS = 600;
534
591
  * so the counter is write-only and inert.
535
592
  *
536
593
  * ACCEPTED-COST NOTES (the residuals, recorded rather than silently tolerated — same posture as the
537
- * RB-84 `head` note above):
594
+ * `head` note above):
538
595
  * · `$(seq …)` RESOLVES A COMMAND. This is the ONE command-substitution form the ruling exempts, and
539
596
  * it does run whatever `seq` resolves to on PATH (or a shell function/alias of that name). Two
540
597
  * facts bound the exposure. FIRST, the trust assumption is ISOMORPHIC to the allowlist itself:
@@ -547,8 +604,8 @@ export declare const POLL_LOOP_MAX_SLEEP_SECONDS = 600;
547
604
  * no-egress envelope — every beat still runs allowlisted readers + literal `sleep`), and the
548
605
  * walltime axis cascades a hard kill regardless. A deployment wanting NO command-substitution at
549
606
  * all can prefer `{<lo>..<hi>}` or a literal list, which bash expands internally with no command
550
- * run. (falsification review flagged the substitution as [high] and recommended dropping it;
551
- * kept per the ruling that names `$(seq <int> <int>)` as the one exemption — recorded for a
607
+ * run. (The substitution is a flagged, high-severity shape kept per the ruling that names
608
+ * `$(seq <int> <int>)` as the one exemption — recorded for a
552
609
  * tightening decision, since the brace form is a drop-in equivalent.)
553
610
  * · STDIN-BLOCKING BODY (an availability residual, not a safety one). CLOSED for the shape this note
554
611
  * used to record: a quoted multiword operand like `grep "x y"` read, to the then whitespace-blind
@@ -568,3 +625,12 @@ export declare const POLL_LOOP_MAX_SLEEP_SECONDS = 600;
568
625
  * ({@link NON_ASCII_WHITESPACE}), so the grammar's tokenization and bash's stay identical.
569
626
  */
570
627
  export declare function classifyBoundedReadonlyPollLoop(command: string, allow: ReadonlySet<string>, boundary?: BashReadonlyRootBoundary): string | undefined;
628
+ /**
629
+ * The poll-loop face's STRUCTURED verdict — the same {@link CompoundReadonlyVerdict} the compound face
630
+ * returns, so a consumer reads the boundary's structural findings (deny row, containment, recursive or
631
+ * undecided operands) off the loop body exactly as off a plain compound, beside whatever sentence the
632
+ * loop grammar or the body's shape produced. {@link classifyBoundedReadonlyPollLoop} is its `reason`
633
+ * projection. A refusal of the LOOP GRAMMAR itself (not a bounded loop, an unlisted body program, an
634
+ * unvetted sleep) carries no structure: no reader segment was walked.
635
+ */
636
+ export declare function classifyBoundedReadonlyPollLoopDetailed(command: string, allow: ReadonlySet<string>, boundary?: BashReadonlyRootBoundary): CompoundReadonlyVerdict;