@sema-agent/core 7.29.0 → 7.30.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/CHANGELOG.md +393 -0
  2. package/dist/agents/child-model-seat.d.ts +59 -7
  3. package/dist/agents/child-model-seat.js +33 -7
  4. package/dist/agents/cross-session-judge.d.ts +27 -5
  5. package/dist/agents/cross-session-judge.js +23 -12
  6. package/dist/agents/list-agents-tool.d.ts +31 -6
  7. package/dist/agents/list-agents-tool.js +66 -14
  8. package/dist/agents/peer-admission.d.ts +20 -8
  9. package/dist/agents/peer-admission.js +21 -12
  10. package/dist/agents/peer-directory.d.ts +29 -0
  11. package/dist/agents/peer-directory.js +20 -0
  12. package/dist/agents/peer-held-queue.d.ts +31 -4
  13. package/dist/agents/peer-held-queue.js +32 -1
  14. package/dist/agents/peer-session-drain.d.ts +91 -13
  15. package/dist/agents/peer-session-drain.js +409 -102
  16. package/dist/agents/read-inbox-tool.d.ts +22 -0
  17. package/dist/agents/read-inbox-tool.js +39 -0
  18. package/dist/agents/roster-store.d.ts +2 -4
  19. package/dist/agents/roster-store.js +1 -1
  20. package/dist/agents/send-message-tool.d.ts +4 -4
  21. package/dist/agents/send-message-tool.js +22 -2
  22. package/dist/agents/subagent.js +62 -44
  23. package/dist/agents/team-role.d.ts +34 -0
  24. package/dist/agents/team-role.js +17 -0
  25. package/dist/agents/verify.js +2 -2
  26. package/dist/core/auto-compaction.d.ts +42 -0
  27. package/dist/core/auto-compaction.js +35 -2
  28. package/dist/core/child-clamp-seats.d.ts +11 -0
  29. package/dist/core/child-clamp-seats.js +3 -0
  30. package/dist/core/context-edit.d.ts +3 -2
  31. package/dist/core/context-edit.js +6 -5
  32. package/dist/core/context-guard.d.ts +2 -1
  33. package/dist/core/context-guard.js +3 -2
  34. package/dist/core/context-settings.d.ts +103 -0
  35. package/dist/core/context-settings.js +60 -0
  36. package/dist/core/engine-notice.d.ts +11 -1
  37. package/dist/core/frame-settlement.d.ts +97 -0
  38. package/dist/core/frame-settlement.js +36 -0
  39. package/dist/core/governance-codes.d.ts +1 -1
  40. package/dist/core/governance-codes.js +2 -0
  41. package/dist/core/hooks.d.ts +10 -10
  42. package/dist/core/mailbox-store.d.ts +41 -7
  43. package/dist/core/mailbox-store.js +9 -3
  44. package/dist/core/parent-spec-seat.d.ts +14 -1
  45. package/dist/core/parent-spec-seat.js +6 -0
  46. package/dist/core/permission-rule-model.js +1 -1
  47. package/dist/core/roles.d.ts +20 -0
  48. package/dist/core/roles.js +35 -16
  49. package/dist/core/runner/assemble-result.d.ts +2 -0
  50. package/dist/core/runner/assemble-result.js +1 -1
  51. package/dist/core/runner/compaction-call-options.d.ts +26 -2
  52. package/dist/core/runner/compaction-call-options.js +9 -0
  53. package/dist/core/runner/compaction-seams.d.ts +4 -3
  54. package/dist/core/runner/compaction-seams.js +13 -6
  55. package/dist/core/runner/contracts.d.ts +56 -7
  56. package/dist/core/runner/decide-continuation.d.ts +2 -1
  57. package/dist/core/runner/decide-continuation.js +11 -10
  58. package/dist/core/runner/initial-run-state.js +1 -1
  59. package/dist/core/runner/prepare-caps-and-workflow.js +9 -1
  60. package/dist/core/runner/prepare-config-doors.js +4 -1
  61. package/dist/core/runner/prepare-context-lane.d.ts +9 -2
  62. package/dist/core/runner/prepare-context-lane.js +15 -10
  63. package/dist/core/runner/prepare-delegation-surface.d.ts +3 -2
  64. package/dist/core/runner/prepare-delegation-surface.js +9 -3
  65. package/dist/core/runner/prepare-file-history.js +10 -8
  66. package/dist/core/runner/prepare-gate-stations.d.ts +4 -0
  67. package/dist/core/runner/prepare-gate-stations.js +3 -1
  68. package/dist/core/runner/prepare-inherited-gate.js +1 -0
  69. package/dist/core/runner/prepare-prompt-inputs.d.ts +6 -0
  70. package/dist/core/runner/prepare-prompt-inputs.js +2 -1
  71. package/dist/core/runner/prepare-task.js +22 -9
  72. package/dist/core/runner/prepare-wiring-manifest.d.ts +6 -1
  73. package/dist/core/runner/prepare-wiring-manifest.js +6 -1
  74. package/dist/core/runner/retired-runner-deps.d.ts +3 -1
  75. package/dist/core/runner/retired-runner-deps.js +1 -0
  76. package/dist/core/runner/run-compaction-machinery.d.ts +4 -2
  77. package/dist/core/runner/run-compaction-machinery.js +5 -3
  78. package/dist/core/runner/run-harness-handlers.js +1 -1
  79. package/dist/core/runner/run-identity-wiring.js +19 -1
  80. package/dist/core/runner/run-leg.js +1 -1
  81. package/dist/core/runner/run-notification-lane.js +8 -2
  82. package/dist/core/runner/run-recovery-lanes.js +9 -5
  83. package/dist/core/runner/run-settle-and-teardown.d.ts +4 -22
  84. package/dist/core/runner/run-settle-and-teardown.js +6 -10
  85. package/dist/core/runner/run-stop-and-final-verify.js +1 -0
  86. package/dist/core/runner/run-terminal-adoption.js +5 -5
  87. package/dist/core/runner/run-turn-boundary.js +32 -5
  88. package/dist/core/runner/runtask.d.ts +8 -1
  89. package/dist/core/runner/runtask.js +32 -1
  90. package/dist/core/runner-deps.d.ts +44 -13
  91. package/dist/core/secret-env.js +2 -1
  92. package/dist/core/swappable-deps.d.ts +20 -4
  93. package/dist/core/swappable-deps.js +6 -1
  94. package/dist/core/task-event.d.ts +5 -0
  95. package/dist/core/task-notification.d.ts +144 -2
  96. package/dist/core/task-notification.js +154 -5
  97. package/dist/core/task-result.d.ts +14 -0
  98. package/dist/core/task-spec.d.ts +7 -0
  99. package/dist/core/tool-catalog-entries.js +2 -1
  100. package/dist/core/tool-conformance.js +1 -0
  101. package/dist/core/tool-policy.d.ts +9 -4
  102. package/dist/core/tool-spec.d.ts +14 -0
  103. package/dist/core/wiring-manifest.d.ts +12 -0
  104. package/dist/core/wiring-manifest.js +5 -1
  105. package/dist/engine/harness/agent-harness.d.ts +14 -1
  106. package/dist/engine/harness/agent-harness.js +28 -3
  107. package/dist/engine/harness/types.d.ts +3 -1
  108. package/dist/engine/llm/types.d.ts +8 -7
  109. package/dist/engine/llm/types.js +1 -1
  110. package/dist/engine/lsp/node-lsp-manager.d.ts +3 -0
  111. package/dist/engine/lsp/node-lsp-manager.js +5 -3
  112. package/dist/engine/session/import-validate.js +4 -0
  113. package/dist/index.d.ts +10 -7
  114. package/dist/index.js +7 -5
  115. package/dist/orchestration/run-workflow-tool.d.ts +4 -4
  116. package/dist/orchestration/workflow.d.ts +1 -1
  117. package/dist/orchestration/workflow.js +8 -5
  118. package/dist/shell/lex.d.ts +38 -54
  119. package/dist/shell/lex.js +239 -286
  120. package/dist/stores/cc/mailbox-store.js +3 -2
  121. package/dist/stores/file/corrupt-read-sink.d.ts +28 -2
  122. package/dist/stores/file/file-history-store.d.ts +2 -4
  123. package/dist/stores/file/file-history-store.js +1 -1
  124. package/dist/stores/file/fs-atomic.d.ts +16 -11
  125. package/dist/stores/file/fs-atomic.js +17 -6
  126. package/dist/stores/file/index.d.ts +5 -6
  127. package/dist/stores/file/index.js +1 -1
  128. package/dist/stores/file/mailbox-store.d.ts +4 -9
  129. package/dist/stores/file/mailbox-store.js +29 -30
  130. package/dist/stores/file/session-policy-store.d.ts +2 -0
  131. package/dist/stores/file/session-policy-store.js +1 -1
  132. package/dist/stores/file/session-store.d.ts +11 -7
  133. package/dist/stores/file/session-store.js +23 -16
  134. package/dist/stores/file/shared-ledger.js +3 -14
  135. package/dist/stores/file/tool-result-store.d.ts +2 -0
  136. package/dist/stores/file/tool-result-store.js +5 -2
  137. package/dist/stores/file/workflow-journal-store.js +14 -9
  138. package/dist/tools/fs/bash-program-position.d.ts +15 -24
  139. package/dist/tools/fs/bash-program-position.js +11 -29
  140. package/dist/tools/fs/bash-readonly-classifier.d.ts +131 -117
  141. package/dist/tools/fs/bash-readonly-classifier.js +404 -272
  142. package/dist/tools/fs/shell-read-check.js +3 -3
  143. package/dist/tools/fs/shell-read-establish.d.ts +1 -1
  144. package/dist/tools/fs/shell-read-establish.js +5 -33
  145. package/dist/tools/fs/shell-read-identity.d.ts +13 -0
  146. package/dist/tools/fs/shell-read-identity.js +39 -0
  147. package/dist/tools/fs/shell-read-judge.d.ts +8 -0
  148. package/dist/tools/fs/shell-read-judge.js +7 -0
  149. package/dist/tools/fs/shell-read-plan.d.ts +15 -6
  150. package/dist/tools/fs/shell-read-plan.js +171 -195
  151. package/dist/tools/fs/shell-read-word.d.ts +64 -0
  152. package/dist/tools/fs/shell-read-word.js +94 -0
  153. package/dist/tools/fs/shell-reentry-text.d.ts +10 -0
  154. package/dist/tools/fs/shell-reentry-text.js +73 -0
  155. package/package.json +1 -1
  156. package/test/export-surface.snapshot.json +58 -8
  157. package/wire-changes/core@7.30.0.json +1821 -0
  158. package/wire-changes/core@7.30.1.json +154 -0
@@ -1291,16 +1291,17 @@ export function startWorkflow(runner, fn, opts = {}, internals) {
1291
1291
  const groupId = currentGroup;
1292
1292
  const typeDef = agentOpts.agentType !== undefined ? agentRegistry.find((d) => d.name === agentOpts.agentType) : undefined;
1293
1293
  const typeDefModel = typeDef?.model;
1294
- let inheritedModelSnap;
1294
+ let inheritedModelPick;
1295
1295
  let inheritedModelError;
1296
1296
  if (spec.model === undefined && typeDefModel === undefined) {
1297
1297
  try {
1298
- inheritedModelSnap = opts.defaultModel?.();
1298
+ inheritedModelPick = opts.defaultModel?.();
1299
1299
  }
1300
1300
  catch (err) {
1301
1301
  inheritedModelError = asThrownError(err);
1302
1302
  }
1303
1303
  }
1304
+ const inheritedModelSnap = inheritedModelPick?.model;
1304
1305
  const inheritedThinkingSnap = spec.thinking === undefined ? opts.defaultThinking?.() : undefined;
1305
1306
  const inheritedPrincipal = spec.principal === undefined ? opts.parentSpecSeat?.principal : undefined;
1306
1307
  const specForIdentity = {
@@ -1313,7 +1314,7 @@ export function startWorkflow(runner, fn, opts = {}, internals) {
1313
1314
  const prompt = boundedRedactedSummary(spec.systemPrompt ? `${spec.systemPrompt}\n\n${spec.objective}` : spec.objective, MAX_TRANSCRIPT_CHARS);
1314
1315
  const specForLabel = spec.model === undefined && typeDefModel !== undefined ? { ...spec, model: typeDefModel } : specForIdentity;
1315
1316
  const model = workflowModelLabel(specForLabel, modelCatalog);
1316
- return { label, phase, phaseInstance, groupId, inheritedModelSnap, inheritedModelError, inheritedThinkingSnap, callKey, prompt, model };
1317
+ return { label, phase, phaseInstance, groupId, inheritedModelSnap, inheritedModelRef: inheritedModelPick?.modelRef, inheritedModelError, inheritedThinkingSnap, callKey, prompt, model };
1317
1318
  };
1318
1319
  const reviewSpawnBeforeLaunch = async (lane, label, callKey, runSpec, effectiveSignal) => {
1319
1320
  const review = opts.autoModeReview;
@@ -1460,7 +1461,7 @@ export function startWorkflow(runner, fn, opts = {}, internals) {
1460
1461
  },
1461
1462
  async agent(spec, agentOpts = {}) {
1462
1463
  const effectiveSignal = assertAgentSpawnAllowed("ctx.agent", spec, agentOpts);
1463
- const { label, phase, phaseInstance, groupId, inheritedModelSnap, inheritedModelError, inheritedThinkingSnap, callKey, prompt, model } = prepareAgentCall(spec, agentOpts);
1464
+ const { label, phase, phaseInstance, groupId, inheritedModelSnap, inheritedModelRef, inheritedModelError, inheritedThinkingSnap, callKey, prompt, model } = prepareAgentCall(spec, agentOpts);
1464
1465
  let drive;
1465
1466
  const cached = opts.resumeFromRunId !== undefined ? replayByOrdinal[run.agents.length] : undefined;
1466
1467
  const truth = opts.resumeFromRunId !== undefined ? parkedByOrdinal[run.agents.length] : undefined;
@@ -1616,6 +1617,7 @@ export function startWorkflow(runner, fn, opts = {}, internals) {
1616
1617
  }
1617
1618
  const attemptInternals = {
1618
1619
  ...baseInternals,
1620
+ ...(inheritedModelRef !== undefined ? { inheritedModelRef } : {}),
1619
1621
  ...(bceSink !== undefined
1620
1622
  ? {
1621
1623
  onForwardEvent: (e) => {
@@ -1845,7 +1847,7 @@ export function startWorkflow(runner, fn, opts = {}, internals) {
1845
1847
  if (budgetTotal !== null && spent() >= budgetTotal) {
1846
1848
  throw new WorkflowBudgetExceededError(spent(), budgetTotal);
1847
1849
  }
1848
- const { label, phase, phaseInstance, groupId, inheritedModelSnap, inheritedModelError, inheritedThinkingSnap, callKey, prompt, model } = prepareAgentCall(spec, agentOpts);
1850
+ const { label, phase, phaseInstance, groupId, inheritedModelSnap, inheritedModelRef, inheritedModelError, inheritedThinkingSnap, callKey, prompt, model } = prepareAgentCall(spec, agentOpts);
1849
1851
  let drive;
1850
1852
  const truth = opts.resumeFromRunId !== undefined ? parkedByOrdinal[run.agents.length] : undefined;
1851
1853
  if (truth !== undefined) {
@@ -1946,6 +1948,7 @@ export function startWorkflow(runner, fn, opts = {}, internals) {
1946
1948
  }
1947
1949
  : undefined;
1948
1950
  const runInternals = {
1951
+ ...(inheritedModelRef !== undefined ? { inheritedModelRef } : {}),
1949
1952
  ...(agentOpts.isolation ? { isolation: agentOpts.isolation } : {}),
1950
1953
  ...(opts.parentCwd !== undefined ? { parentCwd: opts.parentCwd } : {}),
1951
1954
  ...spawnAttribution,
@@ -5,13 +5,11 @@
5
5
  * environment's last-resort `sh` reads `$'…'`, `+=`, a subscript, `<<<`, `<(…)` and `&>` differently; see
6
6
  * {@link bashOnlyConstructsOf}).
7
7
  *
8
- * Two modes remain. STRICT is the residual space the classify faces live in: the caller has hard-rejected
9
- * `< > $ ( ) \` \n \r \\` (or passes `<`/`>` through as text under the rule lane's tolerate option), so the whole of
10
- * bash's word grammar left to model there is quote pairing, the four connectors and whitespace. LENIENT is the space
11
- * the read faces read — everything the strict gate refused, RECORDED instead of refused. The lenient-only
12
- * constructs are branches the strict caller can never reach, so for every strict-accepted input the two modes
13
- * produce the same words and connectors, up to the strict mode's two residuals (a `#` is a word there, and JS
14
- * whitespace rather than bash's blanks bounds a word).
8
+ * ONE walk, ONE reading: every construct bash reads is RECORDED — a redirection, a substitution, an escape, a
9
+ * comment, a line break, a backgrounding `&` — never refused here. Which of them a face refuses is that face's
10
+ * predicate over the result (the classify faces' residual predicate in the read-only classifier); the lexer has
11
+ * no modes. Bash's own word rules hold throughout: an unquoted word-start `#` begins a comment, and only a blank
12
+ * (space or tab) bounds a word — a non-breaking space or a vertical tab is a word character.
15
13
  *
16
14
  * A command bash cannot parse is a {@link LexParseFailure}, never a guessed reading: an unterminated quote,
17
15
  * substitution, subscript or here-document yields NO segments. A word bash reads but whose VALUE the text does not
@@ -21,39 +19,25 @@
21
19
  * a comment and a QUOTED here-document body. Every lookahead below reads the next LOGICAL character past any
22
20
  * continuation, so a pair can stand inside a construct's spelling and never inside the three places bash keeps it.
23
21
  */
24
- export type LexMode = "strict" | "lenient";
25
- export interface LexOptions {
26
- readonly mode: LexMode;
27
- /** `"split"` (default): the connectors bound segments. `"text"`: a single segment is being tokenized and an
28
- * unquoted connector character is a word character. */
29
- readonly connectors?: "split" | "text";
30
- }
31
22
  /** The dialect this lexer reads. The execution environment falls back to `sh` when no bash is found; a reader on
32
23
  * that path must degrade every word carrying a {@link BashOnlyConstruct} to the conservative reading. */
33
24
  export declare const SHELL_LEX_DIALECT = "bash";
34
25
  /** What holds a character quoted: the four quote forms and the backslash escape, one reason each. */
35
26
  export declare const QUOTE_KINDS: readonly ["'", "\"", "$'", "$\"", "\\"];
36
27
  export type QuoteKind = (typeof QUOTE_KINDS)[number];
37
- /** The expansions this lexer names. Extended globs are absent on purpose: `bash -c` runs with `extglob` off, so
38
- * `?(…)` is a syntax error there and `(` is a group token here. */
28
+ /** The expansions this lexer names. Extended globs are not among them: `extglob` is off when `bash -c` starts, where
29
+ * `?(…)` is a syntax error and `(` is a group token here — but a text may turn it on (`shopt -s extglob` on an earlier
30
+ * line), after which bash reads `pack@(age.json)` as one pattern. A reader that plans reads treats an unquoted opener
31
+ * as a pattern it does not expand (`extglobOpenerIn`, the read station's `unreadable` floor). */
39
32
  export declare const EXPANSION_KINDS: readonly ["parameter", "command", "process", "arithmetic", "tilde", "brace", "glob"];
40
33
  export type ExpansionKind = (typeof EXPANSION_KINDS)[number];
41
34
  /** Why a word's value cannot be read off the text. Each member is a spelling whose value the text does not
42
35
  * contain — never "the lexer did not look". */
43
36
  export declare const UNRESOLVED_REASONS: readonly ["ansi_c_escape", "locale_string", "parameter_text", "subscript_text", "compound_array_value"];
44
37
  export type UnresolvedReason = (typeof UNRESOLVED_REASONS)[number];
45
- /** What the {@link lexShellText} view does with an unresolved word: `refuse` hands the consumer the reason's
46
- * sentence; `fold` hands it the folded spelling as the pre-fact readers judged it. The locale string folds:
47
- * refusing it would turn a deny row's HIT (judged on the untranslated spelling) into a mere question, and a
48
- * reader that asks on both faces AND keeps the deny judgment reads the fact, not this view. */
49
- export declare const UNRESOLVED_VIEW: {
50
- readonly ansi_c_escape: "refuse";
51
- readonly locale_string: "fold";
52
- readonly parameter_text: "refuse";
53
- readonly subscript_text: "refuse";
54
- readonly compound_array_value: "refuse";
55
- };
56
- /** The sentence the {@link lexShellText} view hands a consumer for an unresolved word it refuses. */
38
+ /** The sentence a consumer hands on for an unresolved word: every reason is one a face ASKS about (the locale
39
+ * string included — its translation is not in the text), and a deny row is still judged on the written spelling
40
+ * by the readers that keep the word beside the reason. */
57
41
  export declare const UNRESOLVED_SENTENCE: {
58
42
  readonly ansi_c_escape: "an ANSI-C quoted word carries an escape this lexer does not fold";
59
43
  readonly locale_string: "a locale-translated string carries text this lexer does not read";
@@ -61,9 +45,8 @@ export declare const UNRESOLVED_SENTENCE: {
61
45
  readonly subscript_text: "a subscript carries text this lexer does not read";
62
46
  readonly compound_array_value: "a compound assignment value is a list this lexer does not read";
63
47
  };
64
- /** Why a command yields no segments: bash's own syntax errors, the two constructs this lexer cannot delimit, and
65
- * the strict mode's backgrounding refusal. */
66
- export declare const PARSE_FAILURE_REASONS: readonly ["unterminated_single_quote", "unterminated_double_quote", "unterminated_ansi_c", "unterminated_subscript", "unterminated_compound_value", "unterminated_command_substitution", "unterminated_process_substitution", "unterminated_parameter_expansion", "unterminated_heredoc", "undelimited_substitution", "redirect_without_target", "heredoc_without_delimiter", "heredoc_delimiter_expands", "background_operator"];
48
+ /** Why a command yields no segments: bash's own syntax errors and the two constructs this lexer cannot delimit. */
49
+ export declare const PARSE_FAILURE_REASONS: readonly ["unterminated_single_quote", "unterminated_double_quote", "unterminated_ansi_c", "unterminated_subscript", "unterminated_compound_value", "unterminated_command_substitution", "unterminated_process_substitution", "unterminated_parameter_expansion", "unterminated_heredoc", "undelimited_substitution", "redirect_without_target", "heredoc_without_delimiter", "heredoc_delimiter_expands"];
67
50
  export type ParseFailureReason = (typeof PARSE_FAILURE_REASONS)[number];
68
51
  export declare const PARSE_FAILURE_SENTENCE: {
69
52
  readonly unterminated_single_quote: "a single-quoted word never closes";
@@ -79,10 +62,9 @@ export declare const PARSE_FAILURE_SENTENCE: {
79
62
  readonly redirect_without_target: "a redirection names no target";
80
63
  readonly heredoc_without_delimiter: "a here-document operator names no delimiter";
81
64
  readonly heredoc_delimiter_expands: "a here-document delimiter is not a plain word";
82
- readonly background_operator: "`&` backgrounding is not allowed — a backgrounded process outlives the command";
83
65
  };
84
66
  /** The constructs of this dialect a POSIX `sh` reads as something else. */
85
- export declare const BASH_ONLY_CONSTRUCTS: readonly ["ansi_c_quoting", "locale_string", "append_assignment", "subscript_assignment", "compound_assignment", "here_string", "process_substitution", "redirect_both", "brace_expansion"];
67
+ export declare const BASH_ONLY_CONSTRUCTS: readonly ["ansi_c_quoting", "locale_string", "append_assignment", "subscript_assignment", "compound_assignment", "here_string", "process_substitution", "redirect_both", "pipe_both", "brace_expansion"];
86
68
  export type BashOnlyConstruct = (typeof BASH_ONLY_CONSTRUCTS)[number];
87
69
  /**
88
70
  * The ANSI-C escapes this lexer folds: the thirteen single-letter ones, whose byte is the same in every bash and
@@ -172,11 +154,16 @@ export interface LexedWord {
172
154
  * assignment word, after a bare control-prefix word, or after a leading redirection list. */
173
155
  readonly atCommandPosition: boolean;
174
156
  }
175
- /** A redirection and the word it takes. A descriptor duplication (`>&2`, `<&0`, `>&-`, `>&1-`) takes none. */
157
+ /** A redirection and the word it takes. A descriptor duplication (`>&2`, `<&0`, `>&-`, `>&1-`) takes none: its
158
+ * operand is `dup`, the descriptor (or `-`, or a descriptor followed by `-`) as written. `fd` is the descriptor
159
+ * number written in front of the operator (`2>f`, `3>&0`); absent when none was (bash's default, `1` for an
160
+ * output form and `0` for an input form, is the reader's to apply). */
176
161
  export interface LexedRedirect {
177
162
  readonly kind: "redirect";
178
163
  readonly op: "<" | ">" | ">>" | "<<<" | "&>" | "&>>" | ">&" | "<&";
164
+ readonly fd?: number;
179
165
  readonly target?: LexedWord;
166
+ readonly dup?: string;
180
167
  }
181
168
  /** A here-document: the body is DATA the program reads on stdin, never command text. `quoted` records whether
182
169
  * the delimiter word carried a quote or an escape, which is bash's rule for "the body does not expand". */
@@ -197,13 +184,17 @@ export type LexedToken = LexedWord | LexedRedirect | LexedHeredoc | LexedGroup;
197
184
  * exited ZERO, `||` is the only one under which the previous segment may have been SKIPPED ENTIRELY, `|`
198
185
  * puts the segment in a subshell whose directory changes never reach the parent, and `;` is plain sequence. */
199
186
  export type ShellSegmentConnector = "start" | ";" | "&&" | "||" | "|";
200
- /** The lenient mode's two extra boundaries: a backgrounding `&` and a line break. */
187
+ /** The two boundaries the read boundary does not distinguish from a plain sequence: a backgrounding `&` and a
188
+ * line break. */
201
189
  export type LenientConnector = ShellSegmentConnector | "&" | "\n";
202
190
  export interface LexedSegment {
203
191
  /** The segment's text exactly as written (surrounding whitespace included). Here-document bodies are not part
204
192
  * of any segment's text. */
205
193
  readonly text: string;
206
194
  readonly connector: LenientConnector;
195
+ /** The `|` was spelled `|&`: the previous segment's standard error is piped too (bash 4+; a syntax error on
196
+ * bash 3.2, so a reader on the fail-closed side treats the pipe as real). */
197
+ readonly pipesStderr?: true;
207
198
  readonly tokens: readonly LexedToken[];
208
199
  /** The bodies of the substitutions found in THIS segment (its words and its redirection targets), in order. */
209
200
  readonly substitutions: readonly string[];
@@ -233,7 +224,6 @@ export declare const SUBSTITUTION_PLACEHOLDER = " subst";
233
224
  /** Shell control words that stand BEFORE a command: transparent for the boundary walk (the command behind them is
234
225
  * judged), and a position after which bash still accepts an assignment word. */
235
226
  export declare const SHELL_CONTROL_PREFIXES: ReadonlySet<string>;
236
- export type QuoteOpen = '"' | "'" | undefined;
237
227
  /**
238
228
  * Does the `$` at `at` OPEN a quote form (`$'…'` / `$"…"`)? ONE question, asked by every walker that has to
239
229
  * answer it. Escaped means an ODD run of backslashes in front of it: `\$'y'` is a literal `$`, while `x\\$'y'`
@@ -244,34 +234,28 @@ export declare function dollarOpensQuote(text: string, at: number): boolean;
244
234
  /** The `'` that CLOSES the ANSI-C quote opened at `open`, or `undefined` when none does. `\'` does not close
245
235
  * one — the single place a quote region honours a backslash. */
246
236
  export declare function ansiCQuoteClose(source: string, open: number): number | undefined;
247
- /**
248
- * Which QUOTE holds each character of `s`, by the same pairing rule the lexer walks with, and the boolean view of
249
- * it. The pairing quote characters belong to the region they bound. `balanced` is false when a region is still
250
- * open at the end of the string; callers must then NOT use the mask. This models bash only for the residual
251
- * character space the strict faces operate in, where backslash escapes are rejected outright.
252
- */
253
- export declare function quoteMask(s: string): {
254
- openedBy: readonly QuoteOpen[];
255
- quoted: readonly boolean[];
256
- balanced: boolean;
257
- };
258
237
  /** The ONE spelling of a LITERAL leading tilde — `./~…`, the relative path it is — for every position bash does not
259
238
  * expand it in; a word without a leading tilde is returned as is. */
260
239
  export declare function literalTildeSpelling(word: string): string;
261
- /** The argv-word projection of a segment: redirections, here-documents and groups are not words the program
262
- * receives (bash removes them before exec). */
240
+ /** The argv words of a segment: redirections, here-documents and groups are not words the program receives (bash
241
+ * removes them before exec). */
242
+ export declare function argvOf(segment: LexedSegment): readonly LexedWord[];
243
+ /** The two-spelling view of {@link argvOf}, for the readers that compare spellings. */
263
244
  export declare function wordsOf(segment: LexedSegment): SegmentTokens;
264
245
  /** The substitution bodies of an UNQUOTED here-document body: `$(…)` and backticks are live there, quotes are
265
246
  * ordinary characters, a backslash protects the next character. `undefined` when a substitution never closes. */
266
- export declare function substitutionsInHeredocBody(body: string): string[] | undefined;
247
+ export declare function substitutionsInHeredocBody(body: string): {
248
+ readonly body: string;
249
+ readonly kind: "command" | "arithmetic";
250
+ }[] | undefined;
267
251
  /** Lex a command: its segments, or the one reason bash (or this lexer) cannot delimit them. */
268
- export declare function lexShell(source: string, opts: LexOptions): ShellLex;
252
+ export declare function lexShell(source: string): ShellLex;
269
253
  /**
270
254
  * The refused-reading view of {@link lexShell}: a parse failure, and any word whose value cannot be read off the
271
- * text and whose reason {@link UNRESOLVED_VIEW} refuses, become the one `{ reject }` sentence a consumer's
272
- * unreadable arm already takes.
255
+ * text, become the one `{ reject }` sentence a consumer's unreadable arm already takes. A reader that keeps the
256
+ * other words (the read station) reads {@link lexShell} and the word's {@link LexedWord.unresolved} instead.
273
257
  */
274
- export declare function lexShellText(source: string, opts: LexOptions): LexedCommand | {
258
+ export declare function lexShellText(source: string): LexedCommand | {
275
259
  reject: string;
276
260
  };
277
261
  /** The constructs of this dialect the command leans on — what a POSIX `sh` would read as something else. Empty