@sema-agent/core 7.28.1 → 7.30.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 (162) hide show
  1. package/CHANGELOG.md +473 -1
  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/brain/anthropic.js +4 -2
  27. package/dist/brain/open-responses.js +4 -3
  28. package/dist/brain/openai.js +2 -1
  29. package/dist/brain/stream-engine.js +6 -0
  30. package/dist/brain/stream-shared.d.ts +8 -0
  31. package/dist/brain/stream-shared.js +8 -0
  32. package/dist/core/auto-compaction.d.ts +42 -0
  33. package/dist/core/auto-compaction.js +35 -2
  34. package/dist/core/child-clamp-seats.d.ts +11 -0
  35. package/dist/core/child-clamp-seats.js +3 -0
  36. package/dist/core/context-edit.d.ts +3 -2
  37. package/dist/core/context-edit.js +6 -5
  38. package/dist/core/context-guard.d.ts +2 -1
  39. package/dist/core/context-guard.js +3 -2
  40. package/dist/core/context-settings.d.ts +103 -0
  41. package/dist/core/context-settings.js +60 -0
  42. package/dist/core/engine-notice.d.ts +18 -1
  43. package/dist/core/frame-settlement.d.ts +97 -0
  44. package/dist/core/frame-settlement.js +36 -0
  45. package/dist/core/governance-codes.d.ts +1 -1
  46. package/dist/core/governance-codes.js +4 -0
  47. package/dist/core/hooks.d.ts +10 -10
  48. package/dist/core/mailbox-store.d.ts +41 -7
  49. package/dist/core/mailbox-store.js +9 -3
  50. package/dist/core/message-utils.d.ts +13 -0
  51. package/dist/core/message-utils.js +6 -0
  52. package/dist/core/parent-spec-seat.d.ts +14 -1
  53. package/dist/core/parent-spec-seat.js +6 -0
  54. package/dist/core/permission-rule-model.js +1 -1
  55. package/dist/core/roles.d.ts +20 -0
  56. package/dist/core/roles.js +35 -16
  57. package/dist/core/runner/assemble-result.d.ts +2 -0
  58. package/dist/core/runner/assemble-result.js +3 -1
  59. package/dist/core/runner/compaction-call-options.d.ts +26 -2
  60. package/dist/core/runner/compaction-call-options.js +9 -0
  61. package/dist/core/runner/compaction-seams.d.ts +4 -3
  62. package/dist/core/runner/compaction-seams.js +13 -6
  63. package/dist/core/runner/contracts.d.ts +61 -7
  64. package/dist/core/runner/decide-continuation.d.ts +2 -1
  65. package/dist/core/runner/decide-continuation.js +11 -10
  66. package/dist/core/runner/initial-run-state.js +2 -2
  67. package/dist/core/runner/prepare-caps-and-workflow.js +9 -1
  68. package/dist/core/runner/prepare-config-doors.js +4 -1
  69. package/dist/core/runner/prepare-context-lane.d.ts +9 -2
  70. package/dist/core/runner/prepare-context-lane.js +15 -10
  71. package/dist/core/runner/prepare-delegation-surface.d.ts +3 -2
  72. package/dist/core/runner/prepare-delegation-surface.js +9 -3
  73. package/dist/core/runner/prepare-file-history.js +10 -8
  74. package/dist/core/runner/prepare-gate-stations.d.ts +4 -0
  75. package/dist/core/runner/prepare-gate-stations.js +3 -1
  76. package/dist/core/runner/prepare-inherited-gate.js +1 -0
  77. package/dist/core/runner/prepare-prompt-inputs.d.ts +6 -0
  78. package/dist/core/runner/prepare-prompt-inputs.js +2 -1
  79. package/dist/core/runner/prepare-task.js +22 -9
  80. package/dist/core/runner/prepare-wiring-manifest.d.ts +6 -1
  81. package/dist/core/runner/prepare-wiring-manifest.js +6 -1
  82. package/dist/core/runner/response-model-seat.d.ts +16 -0
  83. package/dist/core/runner/response-model-seat.js +27 -0
  84. package/dist/core/runner/retired-runner-deps.d.ts +3 -1
  85. package/dist/core/runner/retired-runner-deps.js +1 -0
  86. package/dist/core/runner/run-compaction-machinery.d.ts +4 -2
  87. package/dist/core/runner/run-compaction-machinery.js +5 -3
  88. package/dist/core/runner/run-harness-handlers.js +9 -2
  89. package/dist/core/runner/run-identity-wiring.js +19 -1
  90. package/dist/core/runner/run-leg.js +1 -1
  91. package/dist/core/runner/run-notification-lane.js +8 -2
  92. package/dist/core/runner/run-recovery-lanes.js +9 -5
  93. package/dist/core/runner/run-settle-and-teardown.d.ts +4 -22
  94. package/dist/core/runner/run-settle-and-teardown.js +6 -10
  95. package/dist/core/runner/run-stop-and-final-verify.js +1 -0
  96. package/dist/core/runner/run-terminal-adoption.js +5 -5
  97. package/dist/core/runner/run-turn-boundary.js +32 -5
  98. package/dist/core/runner/runtask.d.ts +8 -1
  99. package/dist/core/runner/runtask.js +33 -2
  100. package/dist/core/runner-deps.d.ts +44 -13
  101. package/dist/core/side-query.d.ts +6 -5
  102. package/dist/core/side-query.js +3 -1
  103. package/dist/core/swappable-deps.d.ts +20 -4
  104. package/dist/core/swappable-deps.js +6 -1
  105. package/dist/core/task-event.d.ts +13 -0
  106. package/dist/core/task-notification.d.ts +144 -2
  107. package/dist/core/task-notification.js +154 -5
  108. package/dist/core/task-result.d.ts +27 -3
  109. package/dist/core/task-spec.d.ts +7 -0
  110. package/dist/core/tool-catalog-entries.js +2 -1
  111. package/dist/core/tool-conformance.js +1 -0
  112. package/dist/core/tool-policy.d.ts +9 -4
  113. package/dist/core/tool-spec.d.ts +14 -0
  114. package/dist/core/wiring-manifest.d.ts +12 -0
  115. package/dist/core/wiring-manifest.js +5 -1
  116. package/dist/engine/harness/agent-harness.d.ts +14 -1
  117. package/dist/engine/harness/agent-harness.js +28 -3
  118. package/dist/engine/harness/types.d.ts +3 -1
  119. package/dist/engine/llm/types.d.ts +8 -7
  120. package/dist/engine/llm/types.js +1 -1
  121. package/dist/engine/session/import-validate.js +4 -0
  122. package/dist/index.d.ts +10 -7
  123. package/dist/index.js +7 -5
  124. package/dist/orchestration/run-workflow-tool.d.ts +4 -4
  125. package/dist/orchestration/workflow.d.ts +1 -1
  126. package/dist/orchestration/workflow.js +8 -5
  127. package/dist/shell/lex.d.ts +30 -51
  128. package/dist/shell/lex.js +237 -284
  129. package/dist/stores/cc/mailbox-store.js +3 -2
  130. package/dist/stores/file/corrupt-read-sink.d.ts +28 -2
  131. package/dist/stores/file/file-history-store.d.ts +2 -4
  132. package/dist/stores/file/file-history-store.js +1 -1
  133. package/dist/stores/file/fs-atomic.d.ts +16 -11
  134. package/dist/stores/file/fs-atomic.js +17 -6
  135. package/dist/stores/file/index.d.ts +5 -6
  136. package/dist/stores/file/index.js +1 -1
  137. package/dist/stores/file/mailbox-store.d.ts +4 -9
  138. package/dist/stores/file/mailbox-store.js +29 -30
  139. package/dist/stores/file/session-policy-store.d.ts +2 -0
  140. package/dist/stores/file/session-policy-store.js +1 -1
  141. package/dist/stores/file/session-store.d.ts +11 -7
  142. package/dist/stores/file/session-store.js +23 -16
  143. package/dist/stores/file/shared-ledger.js +3 -14
  144. package/dist/stores/file/tool-result-store.d.ts +2 -0
  145. package/dist/stores/file/tool-result-store.js +5 -2
  146. package/dist/stores/file/workflow-journal-store.js +14 -9
  147. package/dist/tools/fs/bash-program-position.d.ts +15 -24
  148. package/dist/tools/fs/bash-program-position.js +11 -29
  149. package/dist/tools/fs/bash-readonly-classifier.d.ts +125 -117
  150. package/dist/tools/fs/bash-readonly-classifier.js +400 -272
  151. package/dist/tools/fs/shell-read-check.js +3 -3
  152. package/dist/tools/fs/shell-read-establish.js +1 -1
  153. package/dist/tools/fs/shell-read-plan.d.ts +11 -6
  154. package/dist/tools/fs/shell-read-plan.js +167 -183
  155. package/dist/tools/fs/shell-read-word.d.ts +50 -0
  156. package/dist/tools/fs/shell-read-word.js +59 -0
  157. package/dist/tools/fs/shell-reentry-text.d.ts +10 -0
  158. package/dist/tools/fs/shell-reentry-text.js +73 -0
  159. package/package.json +1 -1
  160. package/test/export-surface.snapshot.json +58 -8
  161. package/wire-changes/core@7.29.0.json +185 -0
  162. package/wire-changes/core@7.30.0.json +1821 -0
@@ -2,6 +2,7 @@ import type { ActorAssertion, AssistantMessage, ImageContent, Model, UserMessage
2
2
  import type { HaltRemainingDirective } from "../loop/types.js";
3
3
  import type { AgentMessage, AgentTool, LoopMalformedToolUseRecovery, LoopThinkingOnlyRecovery, LoopTruncatedOutputRecovery, QueueMode, ThinkingLevel } from "../loop/types.js";
4
4
  import { type EngineSegment } from "../../core/untrusted-text.js";
5
+ import type { CommittedFrameCarrier } from "../../core/frame-settlement.js";
5
6
  import type { AbortResult, AgentHarnessEvent, AgentHarnessEventResultMap, AgentHarnessOptions, AgentHarnessOwnEvent, AgentHarnessResources, AgentHarnessStreamOptions, ExecutionEnv, PromptTemplate, Skill } from "./types.js";
6
7
  /** [c209-C] 收口 C1/C2 — engine-provenance metadata a caller can stamp on the user message it
7
8
  * mints (see the field docs on {@link UserMessage}). Threaded from `prompt`/`steer`/`followUp`/
@@ -56,6 +57,10 @@ export interface UserMessageProvenance {
56
57
  * while an engine-authored one is held. Minter-stated at the single relay seam that mints such
57
58
  * frames — never inferred from text. Metadata only; not persisted on the message. */
58
59
  callerAuthored?: true;
60
+ /** #1036 — the frame's injection-queue dedup key, persisted on the message it becomes
61
+ * ({@link UserMessage.engineNoteKey}) so a reader of the TRANSCRIPT alone can join an entry back
62
+ * to its frame. Rides only WITH `provenance:"engine-note"`. */
63
+ engineNoteKey?: string;
59
64
  /** RB-30 terminal fix — an OPAQUE payload the engine rides on this queued message (the runner's
60
65
  * task-notification frame). Never serialized, never interpreted by the harness: if the message is
61
66
  * still undrained at agent_end, the payload is handed back through `onUndrainedEngineNotes` so
@@ -178,6 +183,8 @@ export declare class AgentHarness<TSkill extends Skill = Skill, TPromptTemplate
178
183
  private runPromise?;
179
184
  private pendingSessionWrites;
180
185
  private model;
186
+ /** The ref that chose {@link model}, moved by the SAME assignment (one value, never two answers). */
187
+ private modelRef;
181
188
  /** The run's thinking level; `undefined` = undeclared (provider default, no wire key) — distinct from "off". */
182
189
  private thinkingLevel;
183
190
  /** RB-30 terminal fix — runner-set sink for engine-note payloads left undrained at agent_end. */
@@ -200,6 +207,9 @@ export declare class AgentHarness<TSkill extends Skill = Skill, TPromptTemplate
200
207
  * Advisory (swallow-guarded at the call sites via the runner's own closure); never re-entered
201
208
  * for the same payload — consumption deletes the sidecar entry in the same step. */
202
209
  onEngineNoteConsumed?: (payload: unknown) => void;
210
+ /** #1036 — THE RECEIPT SINK: a frame reached the TRANSCRIPT, reported at the `message_end` append
211
+ * that proves it, with its carrier and entry id. Advisory. */
212
+ onFrameCommitted?: (carrier: CommittedFrameCarrier, entryId: string) => void;
203
213
  /** Runner-set HOLD — the single gate for every engine-authored injection against the run's live
204
214
  * human-halt fact. When it reports true (a person's bare rejection halted the run at this
205
215
  * boundary, and only that person's own input may continue it):
@@ -496,9 +506,12 @@ export declare class AgentHarness<TSkill extends Skill = Skill, TPromptTemplate
496
506
  } & UserMessageProvenance): Promise<void>;
497
507
  appendMessage(message: AgentMessage): Promise<void>;
498
508
  getModel(): Model;
509
+ /** The ref that chose the CURRENT model — {@link getModel}'s companion (a word re-resolves, an object pins). */
510
+ getModelRef(): import("../../core/model-seat.js").ModelRef;
499
511
  /** The current level, or `undefined` when none was declared (provider default — no wire key). */
500
512
  getThinkingLevel(): ThinkingLevel | undefined;
501
- setModel(model: Model): Promise<void>;
513
+ /** `ref` = the word that chose `model`; omitted ⇒ the object pins itself. The pair moves together. */
514
+ setModel(model: Model, ref?: import("../../core/model-seat.js").ModelRef): Promise<void>;
502
515
  setThinkingLevel(level: ThinkingLevel): Promise<void>;
503
516
  setActiveTools(toolNames: string[]): Promise<void>;
504
517
  getSteeringMode(): QueueMode;
@@ -28,6 +28,7 @@ function createUserMessage(text, images, provenance) {
28
28
  : {}),
29
29
  ...(provenance?.engineMinted === true && !engineNote ? { engineMinted: true } : {}),
30
30
  ...(engineNote ? { provenance: "engine-note" } : {}),
31
+ ...(engineNote && typeof provenance?.engineNoteKey === "string" && provenance.engineNoteKey.length > 0 ? { engineNoteKey: provenance.engineNoteKey } : {}),
31
32
  ...(provenance?.actor !== undefined &&
32
33
  typeof provenance.actor.id === "string" &&
33
34
  provenance.actor.id.length > 0 &&
@@ -206,10 +207,12 @@ export class AgentHarness {
206
207
  runPromise;
207
208
  pendingSessionWrites = [];
208
209
  model;
210
+ modelRef;
209
211
  thinkingLevel;
210
212
  onUndrainedEngineNotes;
211
213
  onUndrainedUserInputs;
212
214
  onEngineNoteConsumed;
215
+ onFrameCommitted;
213
216
  engineInjectionsHeld;
214
217
  recoverUndrainedEngineNotes() {
215
218
  this.sweepUndrainedEngineNotes([this.drainedPendingInjection, this.nextTurnQueue, this.steerQueue, this.followUpQueue]);
@@ -297,6 +300,7 @@ export class AgentHarness {
297
300
  this.tools.set(tool.name, tool);
298
301
  }
299
302
  this.model = options.model;
303
+ this.modelRef = options.modelRef ?? options.model;
300
304
  this.thinkingLevel = options.thinkingLevel;
301
305
  this.activeToolNames =
302
306
  options.activeToolNames ?? (options.tools ?? []).map((tool) => tool.name);
@@ -582,11 +586,21 @@ export class AgentHarness {
582
586
  const gone = new Set(messages);
583
587
  this.drainedPendingInjection = this.drainedPendingInjection.filter((m) => !gone.has(m));
584
588
  }
585
- settleInjectedFrame(message) {
589
+ settleInjectedFrame(message, entryId) {
586
590
  if (!this.drainedPendingInjection.includes(message))
587
591
  return;
588
592
  this.unbookInFlight([message]);
589
593
  userInputParkRecords.delete(message);
594
+ if (entryId !== undefined) {
595
+ const payload = engineNotePayloads.get(message);
596
+ if (payload !== undefined) {
597
+ try {
598
+ this.onFrameCommitted?.({ kind: "engine_note", payload }, entryId);
599
+ }
600
+ catch {
601
+ }
602
+ }
603
+ }
590
604
  engineNotePayloads.delete(message);
591
605
  }
592
606
  createLoopConfig(getTurnState, setTurnState, runPromptOverride) {
@@ -788,7 +802,14 @@ export class AgentHarness {
788
802
  let entryId;
789
803
  if (!isEmptyFailureAssistant(event.message)) {
790
804
  entryId = await this.session.appendMessage(event.message);
791
- this.settleInjectedFrame(event.message);
805
+ this.settleInjectedFrame(event.message, entryId);
806
+ if (entryId !== undefined && event.message.role === "toolResult" && typeof event.message.toolCallId === "string") {
807
+ try {
808
+ this.onFrameCommitted?.({ kind: "tool_result", toolCallId: event.message.toolCallId, content: event.message.content }, entryId);
809
+ }
810
+ catch {
811
+ }
812
+ }
792
813
  }
793
814
  else if (event.message.isApiErrorMessage === true) {
794
815
  await this.recordApiFailure(event.message);
@@ -1169,10 +1190,13 @@ export class AgentHarness {
1169
1190
  getModel() {
1170
1191
  return this.model;
1171
1192
  }
1193
+ getModelRef() {
1194
+ return this.modelRef;
1195
+ }
1172
1196
  getThinkingLevel() {
1173
1197
  return this.thinkingLevel;
1174
1198
  }
1175
- async setModel(model) {
1199
+ async setModel(model, ref) {
1176
1200
  try {
1177
1201
  const previousModel = this.model;
1178
1202
  if (this.phase === "idle") {
@@ -1186,6 +1210,7 @@ export class AgentHarness {
1186
1210
  });
1187
1211
  }
1188
1212
  this.model = model;
1213
+ this.modelRef = ref ?? model;
1189
1214
  await this.emitOwn({ type: "model_select", model, previousModel, source: "set" });
1190
1215
  }
1191
1216
  catch (error) {
@@ -210,7 +210,7 @@ export declare class CompactionError extends Error {
210
210
  code: CompactionErrorCode;
211
211
  constructor(code: CompactionErrorCode, message: string, cause?: Error);
212
212
  }
213
- export type SessionErrorCode = "not_found" | "invalid_session" | "invalid_entry" | "invalid_fork_target" | "storage" | "conflict" | "placement_refused" | "unknown";
213
+ export type SessionErrorCode = "not_found" | "invalid_session" | "invalid_entry" | "invalid_fork_target" | "storage" | "conflict" | "placement_refused" | "corrupt_session" | "unknown";
214
214
  /** Error thrown by session storage, repositories, and session tree operations. */
215
215
  export declare class SessionError extends Error {
216
216
  /** Session subsystem error code. */
@@ -1380,6 +1380,8 @@ export interface AgentHarnessOptions<TSkill extends Skill = Skill, TPromptTempla
1380
1380
  /** Curated stream/provider request options. Snapshotted at turn start. */
1381
1381
  streamOptions?: AgentHarnessStreamOptions;
1382
1382
  model: Model;
1383
+ /** WHICH REF chose {@link AgentHarnessOptions.model} — the word, else the object. Omitted ⇒ pinned. */
1384
+ modelRef?: import("../../core/model-seat.js").ModelRef;
1383
1385
  thinkingLevel?: ThinkingLevel;
1384
1386
  activeToolNames?: string[];
1385
1387
  steeringMode?: QueueMode;
@@ -348,6 +348,8 @@ export interface UserMessage {
348
348
  * invariant outranks the may-skip one (dropping visible content is the unrecoverable direction).
349
349
  */
350
350
  engineMinted?: true;
351
+ /** #1036 — this frame's injection-queue dedup key, with `provenance:"engine-note"`; OPAQUE (equality only), the DURABLE half of frame identity. */
352
+ engineNoteKey?: string;
351
353
  /**
352
354
  * [c209-C] R3 收口 — the "visible but not the user" THIRD state. This message is an
353
355
  * ENGINE-INJECTED note whose CONTENT the model must read (LSP `<new-diagnostics>` blocks,
@@ -524,13 +526,12 @@ export interface ToolResultMessage<TDetails = unknown> {
524
526
  export type Message = UserMessage | AssistantMessage | ToolResultMessage;
525
527
  /**
526
528
  * RB-3 (stage S4 carry): strip the engine-provenance metadata fields from user messages before
527
- * serializing a Context to an external wire. The five fields (`enginePrefixChars`/`engineSegments`/
528
- * `engineMinted`/`provenance`/`actor`, the last per design/171 §5.2) are INTERNAL coordination
529
- * between the engine's minting side and its consumers (permission classifier, compaction summarizer,
530
- * prompt suggestions, multiplayer attribution) — they must never reach a provider payload. The
531
- * built-in brains construct their own wire shapes and are immune; a CUSTOM Brain that
532
- * whole-object-serializes messages (`JSON.stringify(context.messages)`) would leak them — run the
533
- * array through this projection first.
529
+ * serializing a Context to an external wire. The six fields (`enginePrefixChars`/`engineSegments`/
530
+ * `engineMinted`/`provenance`/`actor`/`engineNoteKey`) are INTERNAL coordination between the engine's
531
+ * minting side and its consumers (permission classifier, compaction summarizer, prompt suggestions,
532
+ * multiplayer attribution) — they must never reach a provider payload. The built-in brains construct
533
+ * their own wire shapes and are immune; a CUSTOM Brain that whole-object-serializes messages
534
+ * (`JSON.stringify(context.messages)`) would leak them — run the array through this projection first.
534
535
  */
535
536
  export declare function stripEngineMetadata(messages: Message[]): Message[];
536
537
  export type ImagesInputContent = TextContent | ImageContent;
@@ -9,7 +9,7 @@ export function stripEngineMetadata(messages) {
9
9
  return messages.map((m) => {
10
10
  if (m.role !== "user")
11
11
  return m;
12
- const { enginePrefixChars: _a, engineSegments: _b, engineMinted: _c, provenance: _d, actor: _e, ...rest } = m;
12
+ const { enginePrefixChars: _a, engineSegments: _b, engineMinted: _c, provenance: _d, actor: _e, engineNoteKey: _f, ...rest } = m;
13
13
  return rest;
14
14
  });
15
15
  }
@@ -293,6 +293,10 @@ function normalizeEngineProvenanceStamp(message, preserveActorAssertions = false
293
293
  delete m.engineMinted;
294
294
  if (m.provenance !== undefined && m.provenance !== "engine-note")
295
295
  delete m.provenance;
296
+ if (m.engineNoteKey !== undefined && !(typeof m.engineNoteKey === "string" && m.engineNoteKey.length > 0))
297
+ delete m.engineNoteKey;
298
+ if (m.engineNoteKey !== undefined && m.provenance !== "engine-note")
299
+ delete m.engineNoteKey;
296
300
  if (m.engineMinted === true && m.provenance === "engine-note") {
297
301
  delete m.engineMinted;
298
302
  }
package/dist/index.d.ts CHANGED
@@ -128,14 +128,15 @@ export type { FileHistoryRetentionPolicy } from "./core/file-history-retention.j
128
128
  export { FileStorageBackend, FileSessionRepo, FileCheckpointStore, FileMemoryStore, FileToolResultStore, FileSessionPolicyStore, FileStrategyStore, FileFileHistoryStore, FileWorkflowJournalStore, MAX_JOURNAL_RESULT_BYTES, oversizeJournalResult, resolveDataRoot, sanitizeScope, sanitizePathComponent, createFileConsolidationLock, atomicWriteFile, writeThenLink, ensureDir, readJsonlRecords, AppendLog, FileStoreLockError, type FileStoreLockErrorCode, processFingerprint, isProcessLive, type ProcessFingerprint, type FileStorageBackendOptions, type FileStorageCorruptReadInfo, type FileStrategyStoreOptions, type FileFileHistoryStoreOptions, type FileSessionRepoOptions, type FileCheckpointStoreOptions, } from "./stores/file/index.js";
129
129
  export { CacheBreakDetector, type CacheBreakFinding, type ToolFingerprintInput } from "./core/cache-break-detector.js";
130
130
  export { maybeCompact, type MaybeCompactOptions, type CompactionWindowSafetyInfo } from "./core/auto-compaction.js";
131
+ export type { CompactionEffect } from "./core/frame-settlement.js";
131
132
  export { brainToRuntime } from "./core/runtime.js";
132
133
  export { createSensitivePathPolicy, RECOMMENDED_SENSITIVE_PATTERNS } from "./core/sensitive-path-policy.js";
133
134
  export { createFsWriteGatePolicy, WRITE_EXEMPT_DIR_COVERS_ROOT_CODE, type FsWriteGatePolicyOptions } from "./core/fs-write-gate-policy.js";
134
135
  export { RETIRED_TOOL_NAMES } from "./core/tool-name-aliases.js";
135
136
  export { DEFAULT_SUBAGENT_TOOL_NAME } from "./agents/subagent.js";
136
- export { renderTaskNotificationXml, taskNotificationDedupKey, isDelegatedAgentTerminal, isTerminalTaskNotification, SystemInjectionQueue, type TaskNotificationPayload, type TaskNotificationStatus, type ExternalNotificationInput, type SystemInjection, type SystemInjectionPriority, type NotificationInjectionOutcome, // the injector's outcome words (`parked_durably` = the session's durable box took the frame)
137
+ export { renderTaskNotificationXml, RESUPPLIED_FRAME_PREAMBLE, taskNotificationDedupKey, isDelegatedAgentTerminal, isTerminalTaskNotification, SystemInjectionQueue, type TaskNotificationPayload, type TaskNotificationStatus, type ExternalNotificationInput, type SystemInjection, type SystemInjectionPriority, type NotificationInjectionOutcome, // the injector's outcome words (`parked_durably` = the session's durable box took the frame)
137
138
  NOTIFICATION_INJECTION_OUTCOMES, // …and their value half + guard, so a host wiring its own uplink validates a reported outcome without duplicating the vocabulary
138
- isNotificationInjectionOutcome, SYSTEM_INJECTION_PRIORITIES, isSystemInjectionPriority, AGENT_MESSAGE_TAG, renderAgentMessageFrame, type SemaProvenance, } from "./core/task-notification.js";
139
+ isNotificationInjectionOutcome, SYSTEM_INJECTION_PRIORITIES, isSystemInjectionPriority, AGENT_MESSAGE_TAG, renderAgentMessageFrame, type SemaProvenance, HANDBACK_STATES, type HandbackState, COMPACTION_KINDS, type CompactionKind, handbackStateOf, terminalFrameFacets, } from "./core/task-notification.js";
139
140
  export { TOOL_FAMILIES, TOOL_MOUNT_TAGS, TOOL_APPROVAL_CARDS, TOOL_PATH_ACCESSES, TOOL_PATH_BASES, TOOL_PATH_ABSENCES, TOOL_WIRE_NAME_MAX_CHARS, TOOL_CONTRACT_MAX_CHARS, TOOL_CARD_ID_MAX_CHARS, TOOL_KEY_MAX_CHARS, TOOL_KEYS_MAX, RENDER_HINT_MAX_CHARS, RENDER_HINT_ACTIVITY_MAX_CHARS, RENDER_HINT_MAX_LIST, type ToolFamily, type ToolMountTag, type ToolApprovalCard, type ToolPathAccess, type ToolPathBase, type ToolPathAbsence, type ToolPathTarget, type ToolCallPathTarget, type ToolRosterPathTarget, pathTargetSlotOnly, type ToolRuleFace, type ToolRenderHints, type ToolFaceDeclaration, type ToolCatalogEntry, } from "./core/tool-face.js";
140
141
  export { describeToolCatalog, catalogEntriesNamed, catalogToolNames, catalogRuleFaceOf, pathTargetOf, pathTargetValue, protectivePathTargetOf, declaredPathTargetOf, BARE_REQUEST_CODE, isProtectedWrite, isDeclaredWrite, fileOpAccessOf, type ToolCallLike, pathConfinableWriteToolNames, skillScopeWriteToolNames, pathTargetingToolNames, compactableToolNames, budgetExemptToolNames, handBandEffects, engineCardTypes, predictMountedToolNames, HANDS_BAND_TAGS, MOUNT_TAG_IN_HANDS_BAND, } from "./core/tool-registry.js";
141
142
  export { ToolRosterEntry, ToolRoster, ToolRosterDelta, ToolRosterRenderHints, ROSTER_SOURCES, type RosterSource, type ToolIdentity, toolIdentityOf, mintCapabilityId, diffToolRoster, judgeParkedToolIdentity, ruleFacesFromRoster, toolCallFaceOf, inputKeysOf, ruleFaceOfInstance, rosterMemberBoundProblem, type RosterBoundMembers, type RosterBoundCode, ToolRosterDeltaSeat, } from "./core/tool-roster.js";
@@ -158,7 +159,7 @@ export { type StoreDurability } from "./core/checkpoint-store.js";
158
159
  export { type StoreFidelity } from "./core/checkpoint-store.js";
159
160
  export { projectHumanInput, buildHumanInputEvent, type HumanInputSource, type HumanInputFrame, type HumanInputEvent, type HumanInputDelivery, } from "./core/human-input-projection.js";
160
161
  export { TaskRegistry, defaultTaskRegistry, createTaskOutputTool, createTaskStopTool, type SemaTaskType, type SemaTaskStatus, type SemaTaskHandle, type ParkedClaimTicket, type TaskAccess, type UnifiedTaskOutput, type TaskRetrievalStatus, type StopSource, type RegisterMonitorInput, type MonitorTimers, MONITOR_BATCH_WINDOW_MS, MONITOR_DEFAULT_TIMEOUT_MS, MONITOR_MAX_TIMEOUT_MS, MONITOR_MAX_BATCHES_PER_MINUTE, canAccessWorkflowRun, DURABLE_AGENT_HANDLE_RE, } from "./core/task-registry.js";
161
- export { InMemoryMailboxStore, type MailboxStore, type MailboxMessage, type MailboxLease, MailboxStoreError, type MailboxStoreErrorCode, MAILBOX_TOMBSTONED_RECIPIENT_CODE, type MailboxAppendMessage, type MailboxPeerMeta, type MailboxPeerFromMode, type MailboxPeerRecordKind, type MailboxPeerNoticeMeta, type MailboxPeerNoticeState, MAILBOX_PEER_NOTICE_STATES, MAILBOX_PEER_FROM_MODES, MAILBOX_PEER_RECORD_KINDS, MAILBOX_INVALID_PEER_META_CODE, MAILBOX_CROSS_PROCESS_UNSAFE_CODE, readMailboxPeerMeta, mailboxCrossProcessMountVerdict, type MailboxCrossProcessVerdict, } from "./core/mailbox-store.js";
162
+ export { InMemoryMailboxStore, type MailboxStore, type MailboxMessage, type MailboxLease, MailboxStoreError, type MailboxStoreErrorCode, MAILBOX_TOMBSTONED_RECIPIENT_CODE, type MailboxAppendMessage, type MailboxPeerMeta, type MailboxPeerFromMode, type MailboxPeerRecordKind, type MailboxPeerNoticeMeta, type MailboxPeerNoticeState, MAILBOX_PEER_NOTICE_STATES, MAILBOX_PEER_FROM_MODES, MAILBOX_PEER_RECORD_KINDS, MAILBOX_INVALID_PEER_META_CODE, MAILBOX_CROSS_PROCESS_UNSAFE_CODE, readMailboxPeerMeta, mailboxCrossProcessMountVerdict, type MailboxCrossProcessVerdict, type MailboxAckResult, } from "./core/mailbox-store.js";
162
163
  export { FileMailboxStore, type FileMailboxStoreOptions } from "./stores/file/mailbox-store.js";
163
164
  export { createFileTaskListStore } from "./stores/file/task-list-store.js";
164
165
  export { createCcFileTaskListStore } from "./stores/cc/task-list-store.js";
@@ -311,14 +312,16 @@ export { COORDINATOR_ROLE_PROMPT, TEAMMATE_COMMUNICATION_ADDENDUM } from "./prom
311
312
  export { createSubagentTool, FORK_SUBAGENT_TYPE, GENERAL_PURPOSE_SUBAGENT_TYPE, agentWhenToUseText, FORK_DIRECTIVE_FRAME, SUBAGENT_SYSTEM_NOTE, type SubagentToolOptions, resolveDelegationEntryCaps, type ResolvedDelegationEntryCaps, type SubagentSpawnContext, type SubagentSteerHandle, type SubagentStep, type SubagentEditedFile, } from "./agents/subagent.js";
312
313
  export { getSessionRetainLedger, releaseSessionRetainLedger, } from "./agents/retain-ledger.js";
313
314
  export { createSendMessageTool, createAgentContinuationVerb, SEND_MESSAGE_TOOL_NAME, type SendMessageToolOptions, type AgentContinuationReceipt } from "./agents/send-message-tool.js";
314
- export { createPeerAdmission, peerAdmissionFor, judgePeerAdmission, resolvePeerAdmissionConfig, PEER_ADMISSION_DEFAULTS, PEER_HOP_CHAIN_WINDOW, PEER_MESSAGE_NOTICE, createPeerSelfRef, createPeerInboundChainRef, peerAxisToken, appendHopToken, type PeerAdmission, type PeerAdmissionConfig, type PeerAdmissionOptions, type PeerAdmissionRequest, type PeerAdmissionVerdict, type PeerAdmissionRefusal, type PeerRefusalCode, type PeerAxisTag, type PeerIdentity, type PeerSelfRef, type PeerInboundChainRef, } from "./agents/peer-admission.js";
315
+ export { createPeerAdmission, peerAdmissionFor, judgePeerAdmission, resolvePeerLaneConfig, PEER_LANE_DEFAULTS, PEER_HOP_CHAIN_WINDOW, PEER_MESSAGE_NOTICE, createPeerSelfRef, createPeerInboundChainRef, peerAxisToken, appendHopToken, type PeerAdmission, type PeerLaneConfig, type PeerAdmissionOptions, type PeerAdmissionRequest, type PeerAdmissionVerdict, type PeerAdmissionRefusal, type PeerRefusalCode, type PeerAxisTag, type PeerIdentity, type PeerSelfRef, type PeerInboundChainRef, } from "./agents/peer-admission.js";
315
316
  export { CROSS_SESSION_MESSAGE_TAG, CROSS_SESSION_MESSAGE_NOTICE, PERMISSION_MODE_CLASSES, isPermissionModeClass, CrossSessionCodecError, PEER_HOP_CHAIN_CARRY_WINDOW, encodePeerAddress, isCanonicalPeerAddress, encodeScopeAttribute, decodeScopeAttribute, canonicalPeerDisplayName, buildCrossSessionEnvelope, parseCrossSessionEnvelope, clampHopChain, encodeCcPeerFrame, decodeCcPeerFrame, type PermissionModeClass, type CrossSessionEnvelopeFields, type CrossSessionEnvelopeParse, type CrossSessionEnvelopeRefusal, type CcPeerFrameFields, type CcPeerFrameParse, } from "./agents/cross-session-envelope.js";
316
317
  export { CROSS_SESSION_INBOUND_SETTINGS, isCrossSessionInboundSetting, resolveCrossSessionInboundSetting, CROSS_SESSION_HOLD_CAUSES, describeCrossSessionHoldCause, judgeCrossSessionInbound, foldPermissionModeClass, PEER_SEND_VERDICT_CODES, peerSendVerdictSeverity, type CrossSessionInboundSetting, type CrossSessionSettingSource, type CrossSessionInboundSettingLayers, type ResolvedCrossSessionInboundSetting, type CrossSessionHoldCause, type CrossSessionInboundVerdict, type CrossSessionInboundInput, type PeerSendVerdictCode, type PeerSendVerdict, } from "./agents/cross-session-judge.js";
317
318
  export { PEER_REF_MIN, PEER_REF_MAX, PEER_REF_RE, mintPeerRef, formatPeerNameRef, parsePeerNameRef, normalizePeerName, PEER_ADDRESS_PREFIXES, reservedPeerNameReason, type PeerRefEntry, } from "./agents/cross-session-ref.js";
318
- export { PEER_SESSION_RECORD_SCHEMA_VERSION, PEER_SESSION_RECORD_MAX_BYTES, SESSION_BOX_PREFIX, peerSessionBoxHandle, isPeerSessionId, PEER_SESSION_ID_GRAMMAR, parsePeerSessionAddress, readPeerSessionRecord, defaultPeerLivenessProbe, isPeerSessionProcessAlive, mintPeerSessionCandidates, resolvePeerSessions, createInMemoryPeerDirectory, vetPeerRegistryDirectory, judgePeerRecordFile, type PeerSessionRecord, type PeerSessionLiveness, type PeerSessionTempo, type PeerSessionRecordRefusal, type PeerSessionRecordRead, type PeerLivenessProbe, type PeerDirectory, type PeerDirectoryAccess, type PeerSessionCandidate, type PeerSessionResolution, type InMemoryPeerDirectory, type PeerRegistryDirectoryRefusal, type PeerRegistryDirectoryVerdict, } from "./agents/peer-directory.js";
319
- export { createListAgentsTool, LIST_AGENTS_TOOL_NAME, LIST_AGENTS_TOOL_ALIAS, LIST_AGENTS_MAX_RESULT_CHARS, type ListAgentsToolOptions, type ListAgentsRow } from "./agents/list-agents-tool.js";
319
+ export { PEER_SESSION_RECORD_SCHEMA_VERSION, PEER_SESSION_RECORD_MAX_BYTES, SESSION_BOX_PREFIX, peerSessionBoxHandle, isPeerSessionId, PEER_SESSION_ID_GRAMMAR, parsePeerSessionAddress, readPeerSessionRecord, defaultPeerLivenessProbe, isPeerSessionProcessAlive, mintPeerSessionCandidates, resolvePeerSessions, createInMemoryPeerDirectory, vetPeerRegistryDirectory, judgePeerRecordFile, type PeerSessionRecord, type PeerPresence, PEER_PRESENCE_MAX_CHARS, type PeerSessionLiveness, type PeerSessionTempo, type PeerSessionRecordRefusal, type PeerSessionRecordRead, type PeerLivenessProbe, type PeerDirectory, type PeerDirectoryAccess, type PeerSessionCandidate, type PeerSessionResolution, type InMemoryPeerDirectory, type PeerRegistryDirectoryRefusal, type PeerRegistryDirectoryVerdict, } from "./agents/peer-directory.js";
320
+ export { createReadInboxTool, READ_INBOX_TOOL_NAME, READ_INBOX_MAX_LIMIT, READ_INBOX_RESULT_BUDGET_CHARS, type ReadInboxToolOptions } from "./agents/read-inbox-tool.js";
321
+ export { TEAM_ROLES, DIRECTION_RELATIONS, teamRoleOf, mayDirect, type TeamRole, type DirectionRelation } from "./agents/team-role.js";
322
+ export { createListAgentsTool, LIST_AGENTS_TOOL_NAME, LIST_AGENTS_TOOL_ALIAS, LIST_AGENTS_MAX_RESULT_CHARS, PEER_LISTING_FRESH_WINDOW_MS, isFreshPeerRow, type ListAgentsToolOptions, type ListAgentsRow } from "./agents/list-agents-tool.js";
320
323
  export { CROSS_SESSION_CLASSIFIER_RULE } from "./agents/cross-session-envelope.js";
321
- export { PEER_SESSION_ID_UNGRAMMATICAL_CODE, type PeerLaneMountVerdict, type PeerInboundDisposition } from "./agents/peer-session-drain.js";
324
+ export { PEER_SESSION_ID_UNGRAMMATICAL_CODE, PEER_RESUPPLY_CAP, type PeerLaneMountVerdict, type PeerInboundDisposition } from "./agents/peer-session-drain.js";
322
325
  export { renderCrossSessionMessageFrame, renderCrossSessionNoticeLine } from "./core/task-notification.js";
323
326
  export { PEER_HELD_QUEUE_CAP, PEER_IDLE_SUBSCRIPTION_TTL_MS, PEER_IDLE_SUBSCRIBER_TABLE_CAP, PEER_IDLE_OUTSTANDING_CAP, PEER_IDLE_PRIORS_KEPT, PEER_IDLE_FIRE_DEBOUNCE_MS, PEER_IDLE_HELD_BACKOFF_MS, PEER_IDLE_LABEL_MAX, CROSS_SESSION_DIALOG_EXPIRY_VALUES, CROSS_SESSION_DIALOG_EXPIRY_DEFAULT, resolveCrossSessionDialogExpiry, PEER_HELD_REVIEW_CAUSES, PEER_DELIVERY_RECEIPT_STATES, isPeerDeliveryReceiptState, PEER_DROP_REASONS, peerRecipientSuffix, renderCrossSessionDeliveryNotice, describePeerDropReasons, renderCrossSessionDroppedNotice, PEER_IDLE_NOTICE_KINDS, isPeerIdleNoticeKind, PEER_IDLE_UNAVAILABLE_CAUSES, peerIdleNoticeLabel, formatPeerNoticeClock, renderCrossSessionIdleNotice, describePeerIdleSubscription, type CrossSessionDialogExpiry, type ResolvedCrossSessionDialogExpiry, type PeerDeliveryReceiptState, type PeerDropReason, type PeerIdleNoticeKind, type PeerIdleNoticeFields, } from "./agents/peer-notices.js";
324
327
  export { createPeerHeldQueue, peerHeldQueueFor, peerHeldQueueIfAny, peerHeldQueueKey, realPeerClock, type PeerInboundHoldCause, type PeerHeldEntry, type PeerHeldSettlement, type PeerHeldSettleReason, type PeerHeldSettleOutcome, type PeerClock, type PeerHeldQueueSink, type PeerHeldQueueConfig, type PeerHeldQueue, } from "./agents/peer-held-queue.js";
package/dist/index.js CHANGED
@@ -108,7 +108,7 @@ export { createSensitivePathPolicy, RECOMMENDED_SENSITIVE_PATTERNS } from "./cor
108
108
  export { createFsWriteGatePolicy, WRITE_EXEMPT_DIR_COVERS_ROOT_CODE } from "./core/fs-write-gate-policy.js";
109
109
  export { RETIRED_TOOL_NAMES } from "./core/tool-name-aliases.js";
110
110
  export { DEFAULT_SUBAGENT_TOOL_NAME } from "./agents/subagent.js";
111
- export { renderTaskNotificationXml, taskNotificationDedupKey, isDelegatedAgentTerminal, isTerminalTaskNotification, SystemInjectionQueue, NOTIFICATION_INJECTION_OUTCOMES, isNotificationInjectionOutcome, SYSTEM_INJECTION_PRIORITIES, isSystemInjectionPriority, AGENT_MESSAGE_TAG, renderAgentMessageFrame, } from "./core/task-notification.js";
111
+ export { renderTaskNotificationXml, RESUPPLIED_FRAME_PREAMBLE, taskNotificationDedupKey, isDelegatedAgentTerminal, isTerminalTaskNotification, SystemInjectionQueue, NOTIFICATION_INJECTION_OUTCOMES, isNotificationInjectionOutcome, SYSTEM_INJECTION_PRIORITIES, isSystemInjectionPriority, AGENT_MESSAGE_TAG, renderAgentMessageFrame, HANDBACK_STATES, COMPACTION_KINDS, handbackStateOf, terminalFrameFacets, } from "./core/task-notification.js";
112
112
  export { TOOL_FAMILIES, TOOL_MOUNT_TAGS, TOOL_APPROVAL_CARDS, TOOL_PATH_ACCESSES, TOOL_PATH_BASES, TOOL_PATH_ABSENCES, TOOL_WIRE_NAME_MAX_CHARS, TOOL_CONTRACT_MAX_CHARS, TOOL_CARD_ID_MAX_CHARS, TOOL_KEY_MAX_CHARS, TOOL_KEYS_MAX, RENDER_HINT_MAX_CHARS, RENDER_HINT_ACTIVITY_MAX_CHARS, RENDER_HINT_MAX_LIST, pathTargetSlotOnly, } from "./core/tool-face.js";
113
113
  export { describeToolCatalog, catalogEntriesNamed, catalogToolNames, catalogRuleFaceOf, pathTargetOf, pathTargetValue, protectivePathTargetOf, declaredPathTargetOf, BARE_REQUEST_CODE, isProtectedWrite, isDeclaredWrite, fileOpAccessOf, pathConfinableWriteToolNames, skillScopeWriteToolNames, pathTargetingToolNames, compactableToolNames, budgetExemptToolNames, handBandEffects, engineCardTypes, predictMountedToolNames, HANDS_BAND_TAGS, MOUNT_TAG_IN_HANDS_BAND, } from "./core/tool-registry.js";
114
114
  export { ToolRosterEntry, ToolRoster, ToolRosterDelta, ToolRosterRenderHints, ROSTER_SOURCES, toolIdentityOf, mintCapabilityId, diffToolRoster, judgeParkedToolIdentity, ruleFacesFromRoster, toolCallFaceOf, inputKeysOf, ruleFaceOfInstance, rosterMemberBoundProblem, ToolRosterDeltaSeat, } from "./core/tool-roster.js";
@@ -258,14 +258,16 @@ export { COORDINATOR_ROLE_PROMPT, TEAMMATE_COMMUNICATION_ADDENDUM } from "./prom
258
258
  export { createSubagentTool, FORK_SUBAGENT_TYPE, GENERAL_PURPOSE_SUBAGENT_TYPE, agentWhenToUseText, FORK_DIRECTIVE_FRAME, SUBAGENT_SYSTEM_NOTE, resolveDelegationEntryCaps, } from "./agents/subagent.js";
259
259
  export { getSessionRetainLedger, releaseSessionRetainLedger, } from "./agents/retain-ledger.js";
260
260
  export { createSendMessageTool, createAgentContinuationVerb, SEND_MESSAGE_TOOL_NAME } from "./agents/send-message-tool.js";
261
- export { createPeerAdmission, peerAdmissionFor, judgePeerAdmission, resolvePeerAdmissionConfig, PEER_ADMISSION_DEFAULTS, PEER_HOP_CHAIN_WINDOW, PEER_MESSAGE_NOTICE, createPeerSelfRef, createPeerInboundChainRef, peerAxisToken, appendHopToken, } from "./agents/peer-admission.js";
261
+ export { createPeerAdmission, peerAdmissionFor, judgePeerAdmission, resolvePeerLaneConfig, PEER_LANE_DEFAULTS, PEER_HOP_CHAIN_WINDOW, PEER_MESSAGE_NOTICE, createPeerSelfRef, createPeerInboundChainRef, peerAxisToken, appendHopToken, } from "./agents/peer-admission.js";
262
262
  export { CROSS_SESSION_MESSAGE_TAG, CROSS_SESSION_MESSAGE_NOTICE, PERMISSION_MODE_CLASSES, isPermissionModeClass, CrossSessionCodecError, PEER_HOP_CHAIN_CARRY_WINDOW, encodePeerAddress, isCanonicalPeerAddress, encodeScopeAttribute, decodeScopeAttribute, canonicalPeerDisplayName, buildCrossSessionEnvelope, parseCrossSessionEnvelope, clampHopChain, encodeCcPeerFrame, decodeCcPeerFrame, } from "./agents/cross-session-envelope.js";
263
263
  export { CROSS_SESSION_INBOUND_SETTINGS, isCrossSessionInboundSetting, resolveCrossSessionInboundSetting, CROSS_SESSION_HOLD_CAUSES, describeCrossSessionHoldCause, judgeCrossSessionInbound, foldPermissionModeClass, PEER_SEND_VERDICT_CODES, peerSendVerdictSeverity, } from "./agents/cross-session-judge.js";
264
264
  export { PEER_REF_MIN, PEER_REF_MAX, PEER_REF_RE, mintPeerRef, formatPeerNameRef, parsePeerNameRef, normalizePeerName, PEER_ADDRESS_PREFIXES, reservedPeerNameReason, } from "./agents/cross-session-ref.js";
265
- export { PEER_SESSION_RECORD_SCHEMA_VERSION, PEER_SESSION_RECORD_MAX_BYTES, SESSION_BOX_PREFIX, peerSessionBoxHandle, isPeerSessionId, PEER_SESSION_ID_GRAMMAR, parsePeerSessionAddress, readPeerSessionRecord, defaultPeerLivenessProbe, isPeerSessionProcessAlive, mintPeerSessionCandidates, resolvePeerSessions, createInMemoryPeerDirectory, vetPeerRegistryDirectory, judgePeerRecordFile, } from "./agents/peer-directory.js";
266
- export { createListAgentsTool, LIST_AGENTS_TOOL_NAME, LIST_AGENTS_TOOL_ALIAS, LIST_AGENTS_MAX_RESULT_CHARS } from "./agents/list-agents-tool.js";
265
+ export { PEER_SESSION_RECORD_SCHEMA_VERSION, PEER_SESSION_RECORD_MAX_BYTES, SESSION_BOX_PREFIX, peerSessionBoxHandle, isPeerSessionId, PEER_SESSION_ID_GRAMMAR, parsePeerSessionAddress, readPeerSessionRecord, defaultPeerLivenessProbe, isPeerSessionProcessAlive, mintPeerSessionCandidates, resolvePeerSessions, createInMemoryPeerDirectory, vetPeerRegistryDirectory, judgePeerRecordFile, PEER_PRESENCE_MAX_CHARS, } from "./agents/peer-directory.js";
266
+ export { createReadInboxTool, READ_INBOX_TOOL_NAME, READ_INBOX_MAX_LIMIT, READ_INBOX_RESULT_BUDGET_CHARS } from "./agents/read-inbox-tool.js";
267
+ export { TEAM_ROLES, DIRECTION_RELATIONS, teamRoleOf, mayDirect } from "./agents/team-role.js";
268
+ export { createListAgentsTool, LIST_AGENTS_TOOL_NAME, LIST_AGENTS_TOOL_ALIAS, LIST_AGENTS_MAX_RESULT_CHARS, PEER_LISTING_FRESH_WINDOW_MS, isFreshPeerRow } from "./agents/list-agents-tool.js";
267
269
  export { CROSS_SESSION_CLASSIFIER_RULE } from "./agents/cross-session-envelope.js";
268
- export { PEER_SESSION_ID_UNGRAMMATICAL_CODE } from "./agents/peer-session-drain.js";
270
+ export { PEER_SESSION_ID_UNGRAMMATICAL_CODE, PEER_RESUPPLY_CAP } from "./agents/peer-session-drain.js";
269
271
  export { renderCrossSessionMessageFrame, renderCrossSessionNoticeLine } from "./core/task-notification.js";
270
272
  export { PEER_HELD_QUEUE_CAP, PEER_IDLE_SUBSCRIPTION_TTL_MS, PEER_IDLE_SUBSCRIBER_TABLE_CAP, PEER_IDLE_OUTSTANDING_CAP, PEER_IDLE_PRIORS_KEPT, PEER_IDLE_FIRE_DEBOUNCE_MS, PEER_IDLE_HELD_BACKOFF_MS, PEER_IDLE_LABEL_MAX, CROSS_SESSION_DIALOG_EXPIRY_VALUES, CROSS_SESSION_DIALOG_EXPIRY_DEFAULT, resolveCrossSessionDialogExpiry, PEER_HELD_REVIEW_CAUSES, PEER_DELIVERY_RECEIPT_STATES, isPeerDeliveryReceiptState, PEER_DROP_REASONS, peerRecipientSuffix, renderCrossSessionDeliveryNotice, describePeerDropReasons, renderCrossSessionDroppedNotice, PEER_IDLE_NOTICE_KINDS, isPeerIdleNoticeKind, PEER_IDLE_UNAVAILABLE_CAUSES, peerIdleNoticeLabel, formatPeerNoticeClock, renderCrossSessionIdleNotice, describePeerIdleSubscription, } from "./agents/peer-notices.js";
271
273
  export { createPeerHeldQueue, peerHeldQueueFor, peerHeldQueueIfAny, peerHeldQueueKey, realPeerClock, } from "./agents/peer-held-queue.js";
@@ -293,10 +293,10 @@ export interface RunWorkflowToolDeps {
293
293
  * `ToolExecuteContext.interactiveTools` seat — without it a headless-clamped host's workflow
294
294
  * children could re-mount the interactive tool the host run disabled. */
295
295
  parentInteractiveTools?: false;
296
- /** Call-time getter for the HOST task's RESOLVED Model object: a spawned agent whose
297
- * fold chain produced no model inherits the parent's full object (baseUrl/key routing included),
298
- * mirroring the subagent lane's ctx.model semantics. */
299
- parentModel?: () => import("../internal/llm.js").Model | undefined;
296
+ /** Call-time getter for the HOST task's RESOLVED model AND the word that chose it: a spawned agent whose
297
+ * fold chain produced no model inherits the object on its spec and the word on its trusted channel
298
+ * (the subagent lane's `ctx.model` / `ctx.modelRef` pair). Word-less ⇒ the object alone, i.e. a pin. */
299
+ parentModel?: () => import("../agents/child-model-seat.js").InheritedModelPick | undefined;
300
300
  /** The HOST task's per-model auth hook: the CREDENTIAL half of model
301
301
  * inheritance. The Model object fixed the URL routing but the child brain still authenticated
302
302
  * with the boot env token (rerun: 7/7 kimi-route 401s with the qwen key). The subagent lane
@@ -451,7 +451,7 @@ export interface RunWorkflowOptions {
451
451
  * parent's full object — baseUrl/key routing included — instead of falling to a string/role
452
452
  * re-resolution that loses per-model routing (the 4/4-agents-404 incident: session model id
453
453
  * re-resolved against the base gateway). Mirrors the subagent lane's `ctx.model` semantics. */
454
- defaultModel?: () => import("../internal/llm.js").Model | undefined;
454
+ defaultModel?: () => import("../agents/child-model-seat.js").InheritedModelPick | undefined;
455
455
  /** Call-time getter for the thinking level a spawned agent runs at when neither the script, the
456
456
  * agentType definition nor the governance baseline set `thinking` — the child thinking seat's lower rungs
457
457
  * (the deployment's STATED `roles.subagent.thinking`, else the host's current level), as the run-workflow
@@ -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,13 +19,6 @@
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";
@@ -42,18 +33,9 @@ export type ExpansionKind = (typeof EXPANSION_KINDS)[number];
42
33
  * contain — never "the lexer did not look". */
43
34
  export declare const UNRESOLVED_REASONS: readonly ["ansi_c_escape", "locale_string", "parameter_text", "subscript_text", "compound_array_value"];
44
35
  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. */
36
+ /** The sentence a consumer hands on for an unresolved word: every reason is one a face ASKS about (the locale
37
+ * string included — its translation is not in the text), and a deny row is still judged on the written spelling
38
+ * by the readers that keep the word beside the reason. */
57
39
  export declare const UNRESOLVED_SENTENCE: {
58
40
  readonly ansi_c_escape: "an ANSI-C quoted word carries an escape this lexer does not fold";
59
41
  readonly locale_string: "a locale-translated string carries text this lexer does not read";
@@ -61,9 +43,8 @@ export declare const UNRESOLVED_SENTENCE: {
61
43
  readonly subscript_text: "a subscript carries text this lexer does not read";
62
44
  readonly compound_array_value: "a compound assignment value is a list this lexer does not read";
63
45
  };
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"];
46
+ /** Why a command yields no segments: bash's own syntax errors and the two constructs this lexer cannot delimit. */
47
+ 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
48
  export type ParseFailureReason = (typeof PARSE_FAILURE_REASONS)[number];
68
49
  export declare const PARSE_FAILURE_SENTENCE: {
69
50
  readonly unterminated_single_quote: "a single-quoted word never closes";
@@ -79,10 +60,9 @@ export declare const PARSE_FAILURE_SENTENCE: {
79
60
  readonly redirect_without_target: "a redirection names no target";
80
61
  readonly heredoc_without_delimiter: "a here-document operator names no delimiter";
81
62
  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
63
  };
84
64
  /** 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"];
65
+ 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
66
  export type BashOnlyConstruct = (typeof BASH_ONLY_CONSTRUCTS)[number];
87
67
  /**
88
68
  * The ANSI-C escapes this lexer folds: the thirteen single-letter ones, whose byte is the same in every bash and
@@ -172,11 +152,16 @@ export interface LexedWord {
172
152
  * assignment word, after a bare control-prefix word, or after a leading redirection list. */
173
153
  readonly atCommandPosition: boolean;
174
154
  }
175
- /** A redirection and the word it takes. A descriptor duplication (`>&2`, `<&0`, `>&-`, `>&1-`) takes none. */
155
+ /** A redirection and the word it takes. A descriptor duplication (`>&2`, `<&0`, `>&-`, `>&1-`) takes none: its
156
+ * operand is `dup`, the descriptor (or `-`, or a descriptor followed by `-`) as written. `fd` is the descriptor
157
+ * number written in front of the operator (`2>f`, `3>&0`); absent when none was (bash's default, `1` for an
158
+ * output form and `0` for an input form, is the reader's to apply). */
176
159
  export interface LexedRedirect {
177
160
  readonly kind: "redirect";
178
161
  readonly op: "<" | ">" | ">>" | "<<<" | "&>" | "&>>" | ">&" | "<&";
162
+ readonly fd?: number;
179
163
  readonly target?: LexedWord;
164
+ readonly dup?: string;
180
165
  }
181
166
  /** A here-document: the body is DATA the program reads on stdin, never command text. `quoted` records whether
182
167
  * the delimiter word carried a quote or an escape, which is bash's rule for "the body does not expand". */
@@ -197,13 +182,17 @@ export type LexedToken = LexedWord | LexedRedirect | LexedHeredoc | LexedGroup;
197
182
  * exited ZERO, `||` is the only one under which the previous segment may have been SKIPPED ENTIRELY, `|`
198
183
  * puts the segment in a subshell whose directory changes never reach the parent, and `;` is plain sequence. */
199
184
  export type ShellSegmentConnector = "start" | ";" | "&&" | "||" | "|";
200
- /** The lenient mode's two extra boundaries: a backgrounding `&` and a line break. */
185
+ /** The two boundaries the read boundary does not distinguish from a plain sequence: a backgrounding `&` and a
186
+ * line break. */
201
187
  export type LenientConnector = ShellSegmentConnector | "&" | "\n";
202
188
  export interface LexedSegment {
203
189
  /** The segment's text exactly as written (surrounding whitespace included). Here-document bodies are not part
204
190
  * of any segment's text. */
205
191
  readonly text: string;
206
192
  readonly connector: LenientConnector;
193
+ /** The `|` was spelled `|&`: the previous segment's standard error is piped too (bash 4+; a syntax error on
194
+ * bash 3.2, so a reader on the fail-closed side treats the pipe as real). */
195
+ readonly pipesStderr?: true;
207
196
  readonly tokens: readonly LexedToken[];
208
197
  /** The bodies of the substitutions found in THIS segment (its words and its redirection targets), in order. */
209
198
  readonly substitutions: readonly string[];
@@ -233,7 +222,6 @@ export declare const SUBSTITUTION_PLACEHOLDER = " subst";
233
222
  /** Shell control words that stand BEFORE a command: transparent for the boundary walk (the command behind them is
234
223
  * judged), and a position after which bash still accepts an assignment word. */
235
224
  export declare const SHELL_CONTROL_PREFIXES: ReadonlySet<string>;
236
- export type QuoteOpen = '"' | "'" | undefined;
237
225
  /**
238
226
  * Does the `$` at `at` OPEN a quote form (`$'…'` / `$"…"`)? ONE question, asked by every walker that has to
239
227
  * answer it. Escaped means an ODD run of backslashes in front of it: `\$'y'` is a literal `$`, while `x\\$'y'`
@@ -244,34 +232,25 @@ export declare function dollarOpensQuote(text: string, at: number): boolean;
244
232
  /** The `'` that CLOSES the ANSI-C quote opened at `open`, or `undefined` when none does. `\'` does not close
245
233
  * one — the single place a quote region honours a backslash. */
246
234
  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
235
  /** The ONE spelling of a LITERAL leading tilde — `./~…`, the relative path it is — for every position bash does not
259
236
  * expand it in; a word without a leading tilde is returned as is. */
260
237
  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). */
238
+ /** The argv words of a segment: redirections, here-documents and groups are not words the program receives (bash
239
+ * removes them before exec). */
240
+ export declare function argvOf(segment: LexedSegment): readonly LexedWord[];
241
+ /** The two-spelling view of {@link argvOf}, for the readers that compare spellings. */
263
242
  export declare function wordsOf(segment: LexedSegment): SegmentTokens;
264
243
  /** The substitution bodies of an UNQUOTED here-document body: `$(…)` and backticks are live there, quotes are
265
244
  * ordinary characters, a backslash protects the next character. `undefined` when a substitution never closes. */
266
245
  export declare function substitutionsInHeredocBody(body: string): string[] | undefined;
267
246
  /** 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;
247
+ export declare function lexShell(source: string): ShellLex;
269
248
  /**
270
249
  * 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.
250
+ * text, become the one `{ reject }` sentence a consumer's unreadable arm already takes. A reader that keeps the
251
+ * other words (the read station) reads {@link lexShell} and the word's {@link LexedWord.unresolved} instead.
273
252
  */
274
- export declare function lexShellText(source: string, opts: LexOptions): LexedCommand | {
253
+ export declare function lexShellText(source: string): LexedCommand | {
275
254
  reject: string;
276
255
  };
277
256
  /** The constructs of this dialect the command leans on — what a POSIX `sh` would read as something else. Empty