@sema-agent/core 7.16.0 → 7.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (193) hide show
  1. package/CHANGELOG.md +173 -0
  2. package/dist/agents/builtin-agents.d.ts +3 -3
  3. package/dist/agents/cross-session-envelope.d.ts +0 -1
  4. package/dist/agents/cross-session-envelope.js +0 -1
  5. package/dist/agents/peer-notices.d.ts +0 -9
  6. package/dist/agents/peer-notices.js +0 -63
  7. package/dist/agents/subagent.js +7 -15
  8. package/dist/brain/request-params.d.ts +2 -2
  9. package/dist/config/defaults.d.ts +0 -7
  10. package/dist/config/defaults.js +0 -2
  11. package/dist/core/artifact-host.d.ts +218 -0
  12. package/dist/core/artifact-host.js +92 -0
  13. package/dist/core/ask-origin.d.ts +29 -3
  14. package/dist/core/ask-origin.js +17 -9
  15. package/dist/core/ask-question.d.ts +25 -0
  16. package/dist/core/ask-question.js +4 -0
  17. package/dist/core/ask-unresolvable-notice.d.ts +30 -21
  18. package/dist/core/ask-unresolvable-notice.js +16 -8
  19. package/dist/core/auto-compaction.d.ts +10 -10
  20. package/dist/core/auto-mode-arming.d.ts +2 -2
  21. package/dist/core/background-agent-store.d.ts +5 -5
  22. package/dist/core/background-shell.d.ts +1 -1
  23. package/dist/core/checkpoint-execution-record.d.ts +0 -3
  24. package/dist/core/checkpoint-execution-record.js +0 -4
  25. package/dist/core/checkpoint-store.d.ts +71 -99
  26. package/dist/core/checkpoint-store.js +9 -16
  27. package/dist/core/context-edit.d.ts +36 -104
  28. package/dist/core/context-edit.js +37 -60
  29. package/dist/core/effective-path-target.d.ts +68 -8
  30. package/dist/core/effective-path-target.js +42 -30
  31. package/dist/core/engine-notice.d.ts +46 -32
  32. package/dist/core/env-budget.d.ts +31 -0
  33. package/dist/core/env-budget.js +39 -0
  34. package/dist/core/exec-output-tail.d.ts +5 -5
  35. package/dist/core/file-history-store.js +3 -6
  36. package/dist/core/fs-write-gate-policy.d.ts +1 -1
  37. package/dist/core/fs-write-gate-policy.js +3 -3
  38. package/dist/core/gate-lanes.js +9 -15
  39. package/dist/core/governance-codes.d.ts +1 -1
  40. package/dist/core/governance-codes.js +2 -0
  41. package/dist/core/hands-band.d.ts +1 -1
  42. package/dist/core/hooks.d.ts +18 -17
  43. package/dist/core/lsp-session.d.ts +1 -1
  44. package/dist/core/lsp.d.ts +1 -1
  45. package/dist/core/lsp.js +5 -4
  46. package/dist/core/mcp.d.ts +5 -5
  47. package/dist/core/mcp.js +4 -48
  48. package/dist/core/memory-recall.d.ts +0 -8
  49. package/dist/core/memory.d.ts +1 -1
  50. package/dist/core/oracle-isolation.js +2 -2
  51. package/dist/core/parent-spec-seat.d.ts +66 -0
  52. package/dist/core/parent-spec-seat.js +47 -0
  53. package/dist/core/permission-rule-model.d.ts +11 -6
  54. package/dist/core/permission-rule-model.js +53 -37
  55. package/dist/core/permission-rules.js +8 -3
  56. package/dist/core/protocol-naming.d.ts +2 -2
  57. package/dist/core/remote-env.d.ts +1 -1
  58. package/dist/core/retired-keys.d.ts +19 -0
  59. package/dist/core/retired-keys.js +15 -0
  60. package/dist/core/runner/active-skill-scope.js +3 -3
  61. package/dist/core/runner/assemble-result.d.ts +15 -13
  62. package/dist/core/runner/assemble-result.js +5 -4
  63. package/dist/core/runner/compaction-call-options.d.ts +25 -89
  64. package/dist/core/runner/contracts.d.ts +10 -9
  65. package/dist/core/runner/gate-exit.js +15 -1
  66. package/dist/core/runner/halt-attribution.d.ts +35 -0
  67. package/dist/core/runner/halt-attribution.js +16 -0
  68. package/dist/core/runner/memory-consolidation.d.ts +0 -2
  69. package/dist/core/runner/memory-consolidation.js +0 -1
  70. package/dist/core/runner/prepare-artifact.d.ts +53 -0
  71. package/dist/core/runner/prepare-artifact.js +77 -0
  72. package/dist/core/runner/prepare-caps-and-workflow.d.ts +4 -2
  73. package/dist/core/runner/prepare-caps-and-workflow.js +2 -3
  74. package/dist/core/runner/prepare-config-doors.d.ts +3 -3
  75. package/dist/core/runner/prepare-config-doors.js +5 -2
  76. package/dist/core/runner/prepare-context-lane.d.ts +2 -2
  77. package/dist/core/runner/prepare-context-lane.js +2 -13
  78. package/dist/core/runner/prepare-file-history.d.ts +1 -1
  79. package/dist/core/runner/prepare-file-history.js +3 -52
  80. package/dist/core/runner/prepare-hands-readface.d.ts +4 -7
  81. package/dist/core/runner/prepare-hands-readface.js +3 -2
  82. package/dist/core/runner/prepare-inherited-gate.d.ts +5 -2
  83. package/dist/core/runner/prepare-inherited-gate.js +7 -8
  84. package/dist/core/runner/prepare-memory.d.ts +4 -6
  85. package/dist/core/runner/prepare-memory.js +4 -2
  86. package/dist/core/runner/prepare-policy-chain.d.ts +3 -3
  87. package/dist/core/runner/prepare-policy-chain.js +15 -30
  88. package/dist/core/runner/prepare-prompt-assembly.js +1 -1
  89. package/dist/core/runner/prepare-safety-scan.d.ts +1 -1
  90. package/dist/core/runner/prepare-suspend-saga.js +0 -2
  91. package/dist/core/runner/prepare-task.js +10 -9
  92. package/dist/core/runner/prepare-wiring-manifest.js +9 -7
  93. package/dist/core/runner/resume-admission.js +2 -1
  94. package/dist/core/runner/resume-internals-and-config.js +4 -0
  95. package/dist/core/runner/retired-runner-deps.d.ts +3 -0
  96. package/dist/core/runner/retired-runner-deps.js +7 -0
  97. package/dist/core/runner/run-harness-handlers.js +2 -3
  98. package/dist/core/runner/run-settle-and-teardown.d.ts +1 -1
  99. package/dist/core/runner/run-settle-and-teardown.js +3 -1
  100. package/dist/core/runner/session-file-state-replay.js +3 -3
  101. package/dist/core/runner/session-rule-policy.js +3 -4
  102. package/dist/core/runner/stream-halt-verbs.js +1 -1
  103. package/dist/core/runner/stream-steer-verb.js +1 -4
  104. package/dist/core/runner/workspace-path.js +3 -0
  105. package/dist/core/runner-deps.d.ts +30 -49
  106. package/dist/core/safe-notify.d.ts +1 -1
  107. package/dist/core/sensitive-path-policy.d.ts +1 -1
  108. package/dist/core/sensitive-path-policy.js +4 -4
  109. package/dist/core/session.d.ts +2 -2
  110. package/dist/core/skill-tool-specifier.d.ts +1 -1
  111. package/dist/core/skills-directory.d.ts +1 -1
  112. package/dist/core/store-contracts/checkpoint-store-contract.js +1 -1
  113. package/dist/core/strategy-store.d.ts +8 -11
  114. package/dist/core/task-event.d.ts +20 -17
  115. package/dist/core/task-limits.d.ts +1 -1
  116. package/dist/core/task-notification.d.ts +5 -5
  117. package/dist/core/task-registry-agent.d.ts +5 -5
  118. package/dist/core/task-registry-monitor.d.ts +2 -2
  119. package/dist/core/task-registry-shared.d.ts +27 -27
  120. package/dist/core/task-registry-shared.js +3 -13
  121. package/dist/core/task-registry.d.ts +8 -8
  122. package/dist/core/task-result.d.ts +37 -37
  123. package/dist/core/task-spec.d.ts +5 -5
  124. package/dist/core/task-stream.d.ts +16 -11
  125. package/dist/core/tool-catalog-entries.d.ts +1 -0
  126. package/dist/core/tool-catalog-entries.js +5 -0
  127. package/dist/core/tool-conformance.d.ts +0 -2
  128. package/dist/core/tool-conformance.js +1 -3
  129. package/dist/core/tool-errors.d.ts +5 -0
  130. package/dist/core/tool-errors.js +1 -0
  131. package/dist/core/tool-policy.d.ts +51 -22
  132. package/dist/core/tool-policy.js +28 -5
  133. package/dist/core/tool-result-budget.d.ts +1 -1
  134. package/dist/core/tool-result-store.d.ts +11 -11
  135. package/dist/core/tool-spec.d.ts +34 -38
  136. package/dist/core/tools.d.ts +2 -2
  137. package/dist/core/trace.d.ts +12 -15
  138. package/dist/core/untrusted-text.d.ts +1 -1
  139. package/dist/core/wiring-manifest.d.ts +4 -3
  140. package/dist/core/workflow-journal-store.d.ts +11 -11
  141. package/dist/engine/execution-env/node-execution-env.d.ts +3 -2
  142. package/dist/engine/execution-env/node-execution-env.js +4 -2
  143. package/dist/engine/harness/agent-harness.d.ts +47 -4
  144. package/dist/engine/harness/agent-harness.js +52 -9
  145. package/dist/engine/loop/agent-loop.js +15 -8
  146. package/dist/engine/loop/types.d.ts +5 -0
  147. package/dist/index.d.ts +19 -14
  148. package/dist/index.js +15 -10
  149. package/dist/internal/harness.d.ts +1 -0
  150. package/dist/orchestration/run-spec.d.ts +3 -0
  151. package/dist/orchestration/run-spec.js +3 -3
  152. package/dist/orchestration/run-workflow-tool.d.ts +12 -6
  153. package/dist/orchestration/run-workflow-tool.js +23 -5
  154. package/dist/orchestration/workflow-primitives.d.ts +4 -2
  155. package/dist/orchestration/workflow-primitives.js +1 -4
  156. package/dist/orchestration/workflow-types.d.ts +34 -4
  157. package/dist/orchestration/workflow-types.js +2 -0
  158. package/dist/orchestration/workflow.d.ts +39 -7
  159. package/dist/orchestration/workflow.js +234 -113
  160. package/dist/prompt-assembly/assemble.d.ts +2 -2
  161. package/dist/prompt-assembly/assemble.js +9 -9
  162. package/dist/prompt-assembly/composer.d.ts +6 -7
  163. package/dist/prompt-assembly/composer.js +10 -10
  164. package/dist/prompt-assembly/epoch.js +1 -1
  165. package/dist/prompt-assembly/event-registry.d.ts +0 -21
  166. package/dist/prompt-assembly/packs/sema-default.js +30 -30
  167. package/dist/prompt-assembly/types.d.ts +14 -14
  168. package/dist/prompts/coordinator.d.ts +0 -13
  169. package/dist/prompts/coordinator.js +0 -3
  170. package/dist/stores/file/checkpoint-store.js +1 -5
  171. package/dist/stores/file/file-history-store.js +2 -2
  172. package/dist/stores/file/permission-rule-store.d.ts +4 -35
  173. package/dist/stores/file/permission-rule-store.js +4 -148
  174. package/dist/tools/artifact/artifact-text.d.ts +62 -0
  175. package/dist/tools/artifact/artifact-text.js +68 -0
  176. package/dist/tools/artifact/artifact-tool.d.ts +52 -0
  177. package/dist/tools/artifact/artifact-tool.js +351 -0
  178. package/dist/tools/artifact/local-stub.d.ts +26 -0
  179. package/dist/tools/artifact/local-stub.js +296 -0
  180. package/dist/tools/fs/bash-readonly-classifier.d.ts +74 -8
  181. package/dist/tools/fs/bash-readonly-classifier.js +171 -60
  182. package/dist/tools/fs/fs-bash.d.ts +14 -10
  183. package/dist/tools/fs/fs-bash.js +19 -27
  184. package/dist/tools/fs/fs-search-tools.js +5 -2
  185. package/dist/tools/fs/fs-shared.d.ts +2 -0
  186. package/dist/tools/fs/fs-shared.js +3 -11
  187. package/dist/tools/fs/index.d.ts +4 -0
  188. package/dist/tools/fs/index.js +4 -1
  189. package/dist/tools/fs/safety.d.ts +117 -1
  190. package/dist/tools/fs/safety.js +131 -31
  191. package/dist/tools/fs/search.js +8 -6
  192. package/package.json +2 -1
  193. package/test/export-surface.snapshot.json +115 -39
@@ -156,19 +156,16 @@ export declare function validateStrategyForWrite(s: StoredStrategy): void;
156
156
  * source for the in-memory and file-backed stores, so retrieval semantics cannot fork between
157
157
  * backends.
158
158
  *
159
- * TWO acceptance arms, OR-combined, so the CJK upgrade can only ADD hits, never lose one:
159
+ * TWO acceptance arms, OR-combined (retrieval semantics, pinned):
160
160
  * - full arm — every significant term (alphanumeric AND CJK) present in the problem;
161
- * - legacy arm — every significant ALPHANUMERIC term present (and there is ≥1). This is exactly the
162
- * pre-CJK predicate: it used to DISCARD CJK from the query, so "请帮我 extract tables from
163
- * report.pdf" matched an English-only stored problem. Requiring the CJK boilerplate too would
164
- * have silently un-matched that pair — a recall regression hiding inside a recall fix. Keeping
165
- * the legacy arm costs precision only relative to a strictness nobody ever had.
161
+ * - alphanumeric arm — every significant ALPHANUMERIC term present (and there is ≥1), so a mixed
162
+ * query ("请帮我 extract tables from report.pdf") still matches an English-only stored problem
163
+ * requiring the CJK boilerplate too would un-match that pair.
166
164
  *
167
- * ACCEPTED COST (documented, pinned): via the legacy arm, a mixed query whose alphanumeric terms all
168
- * match can hit a problem whose CJK terms CONFLICT (提取 X vs 删除 X) exactly what the pre-CJK
169
- * predicate always did, retained because losing old hits is the one regression this upgrade must not
170
- * make. The mitigation is the surrounding depth (negation preamble, verify-before-use instruction,
171
- * injection audit); tightening precision is a measured-recalibration change, not a retrieval patch.
165
+ * ACCEPTED COST (documented, pinned): via the alphanumeric arm, a mixed query whose alphanumeric
166
+ * terms all match can hit a problem whose CJK terms CONFLICT (提取 X vs 删除 X). The mitigation is
167
+ * the surrounding depth (negation preamble, verify-before-use instruction, injection audit);
168
+ * tightening precision is a measured-recalibration change, not a retrieval patch.
172
169
  */
173
170
  export declare function compileStrategyQuery(query: string): ((problem: string) => boolean) | null;
174
171
  export declare function normalizeStrategyText(s: string): string;
@@ -64,7 +64,7 @@ export interface TaskEventIdentity {
64
64
  */
65
65
  export type BrainStatusPhase = "rate_limited" | "retrying" | "reconnecting" | "circuit_open"
66
66
  /**
67
- * RB-420-c — TERMINAL frames closing a retry sequence. Without them a consumer that rendered a
67
+ * TERMINAL frames closing a retry sequence. Without them a consumer that rendered a
68
68
  * `rate_limited`/`retrying`/`reconnecting` frame has nothing telling it the wait is over, so the
69
69
  * warning row stays pinned until the next unrelated event. Exactly one terminal frame is emitted,
70
70
  * and only for a call that actually waited (a retry wait, or a `waiting_first_token` trail —
@@ -75,7 +75,7 @@ export type BrainStatusPhase = "rate_limited" | "retrying" | "reconnecting" | "c
75
75
  */
76
76
  | "recovered" | "gave_up"
77
77
  /**
78
- * #530 — the first-token WAIT, before any failure: a first-token watchdog is armed
78
+ * The first-token WAIT, before any failure: a first-token watchdog is armed
79
79
  * (`firstTokenTimeoutMs > 0`) and nothing has arrived yet. Emitted once the wait has lasted
80
80
  * `WAITING_FIRST_TOKEN_AFTER_MS` and re-emitted every `WAITING_FIRST_TOKEN_EVERY_MS` while it goes
81
81
  * on, carrying {@link BrainStatus.elapsedMs} and {@link BrainStatus.timeoutMs}; never carries a
@@ -126,7 +126,7 @@ export interface BrainStatus {
126
126
  detail?: string;
127
127
  /** Seconds until the brain's next retry attempt (from the honored backoff / `Retry-After`), when known. */
128
128
  retryInSec?: number;
129
- /** RB-420-c — millisecond precision of {@link retryInSec}, for a client that renders a countdown.
129
+ /** Millisecond precision of {@link retryInSec}, for a client that renders a countdown.
130
130
  * A wait longer than the re-announce slice is re-emitted with the REMAINING time, so a consumer
131
131
  * that simply overwrites its row always shows a live number instead of a stale one. */
132
132
  retryInMs?: number;
@@ -149,17 +149,17 @@ export interface BrainStatus {
149
149
  * the authoritative RELATIVE quantity, and this seat is the absolute convenience derived from it.
150
150
  */
151
151
  retryAtMs?: number;
152
- /** #530 — on a `waiting_first_token` frame: how long the first token has been awaited, ms, at the
152
+ /** On a `waiting_first_token` frame: how long the first token has been awaited, ms, at the
153
153
  * moment the frame is emitted (the emitting process's clock; approximate across a hop). Absent on
154
154
  * every other phase. */
155
155
  elapsedMs?: number;
156
- /** #530 — on a `waiting_first_token` frame: the armed first-token watchdog, ms — the wait's ceiling,
156
+ /** On a `waiting_first_token` frame: the armed first-token watchdog, ms — the wait's ceiling,
157
157
  * so a consumer can render "45s of 120s". Absent on every other phase. */
158
158
  timeoutMs?: number;
159
- /** RB-420-c — 1-based index of the attempt that just failed (the wait precedes attempt `attempt + 1`);
159
+ /** 1-based index of the attempt that just failed (the wait precedes attempt `attempt + 1`);
160
160
  * same numbering as the `brain.retry` telemetry frame. Absent on frames that are not a retry wait. */
161
161
  attempt?: number;
162
- /** RB-420-c — the retry budget of THIS lane, so a consumer can render "attempt 3 of 10". Lane, not
162
+ /** The retry budget of THIS lane, so a consumer can render "attempt 3 of 10". Lane, not
163
163
  * engine: a failure class served by a shorter ladder reports that ladder's budget, so the fraction a
164
164
  * consumer renders is the one actually in force rather than the engine-wide ceiling. */
165
165
  maxRetries?: number;
@@ -259,7 +259,7 @@ export type TaskEvent = ({
259
259
  delta: string;
260
260
  } & TaskEventIdentity) | ({
261
261
  /**
262
- * #447 — the assistant's streaming PROSE SEGMENT is COMPLETE: the model closed the text content
262
+ * The assistant's streaming PROSE SEGMENT is COMPLETE: the model closed the text content
263
263
  * block whose bytes just streamed as `text_delta`s. This is the explicit segment boundary a
264
264
  * REMOTE consumer needs so it never has to guess segment ends from wire silence (the idle-flush
265
265
  * heuristic this retires cut one slow-model reply into N fragments). CC-aligned: CC's agent
@@ -449,7 +449,7 @@ export type TaskEvent = ({
449
449
  */
450
450
  truncated?: boolean;
451
451
  /**
452
- * RB-210 — present iff {@link truncated}: the TRUE original size (characters) of
452
+ * Present iff {@link truncated}: the TRUE original size (characters) of
453
453
  * the content this event's {@link output} was degraded from — for a string result, the string's own
454
454
  * length; for a non-string result (a blocks array), the SUM of each block's own true size (a text
455
455
  * block's `.text.length`; an image/document block's `.data.length`, i.e. its base64 payload) — never
@@ -469,7 +469,7 @@ export type TaskEvent = ({
469
469
  totalChars?: number;
470
470
  } & TaskEventIdentity) | ({
471
471
  /**
472
- * RB-126 — context occupancy at a compaction boundary, emitted on EVERY
472
+ * Context occupancy at a compaction boundary, emitted on EVERY
473
473
  * boundary (not only when a compaction fires). The three numbers are the engine's own trigger
474
474
  * inputs, verbatim: `usedTokens > compactAtTokens` IS the predicate `shouldCompact` evaluates, so a
475
475
  * consumer's "context is N% full" indicator and the moment compaction actually fires can never
@@ -490,15 +490,17 @@ export type TaskEvent = ({
490
490
  /**
491
491
  * Per-turn token usage + cost (the turn that just ended), for live per-turn accounting / a trace UI
492
492
  * (service [41]). Re-priced in core from injected pricing (authoritative, like `TaskResult.stats`).
493
- * Absent only if the turn produced no assistant usage.
493
+ * ALWAYS present: a turn that produced no provider usage frame carries the counted ZEROS beside
494
+ * `usageMissing: true` — zero is unknown, not free, the one law `TaskResult.stats` states (numbers
495
+ * always present, the flag says they under-count), so a consumer handles ONE frame shape.
494
496
  *
495
- * RB-457-a: `inputTokens` is the cache-MISS count (Anthropic-protocol shape, matches
497
+ * `inputTokens` is the cache-MISS count (Anthropic-protocol shape, matches
496
498
  * `stats.promptTokens` / the tracer's `brain.call.promptTokens`); `totalInputTokens` is the
497
499
  * cache-INCLUSIVE total (`inputTokens + cacheReadTokens + cacheWriteTokens`) that cost is computed
498
500
  * from. Sum `totalInputTokens` for context/window/spend views; read `inputTokens` only where the
499
501
  * protocol's `input_tokens` is meant. Up to 2.13.x `inputTokens` carried the total.
500
502
  */
501
- usage?: {
503
+ usage: {
502
504
  /** Cache-MISS input tokens for this turn (the Anthropic protocol's `input_tokens` meaning;
503
505
  * matches `stats.promptTokens` / `brain.call.promptTokens`). **Up to 2.13.x this field
504
506
  * carried the cache-INCLUSIVE total** (RB-457-a, BREAKING at 3.0.0) — that value now lives
@@ -514,9 +516,10 @@ export type TaskEvent = ({
514
516
  costMicroUsd: number;
515
517
  };
516
518
  /** TB 尸检 T1-5: set when the turn ended WITHOUT a provider usage frame (e.g. a degenerate-repetition
517
- * cutoff cancelled the stream before usage arrived). Consumers must treat the missing usage as
518
- * UNKNOWN — not zero (the provider still served the request; `stats` under-counts it honestly rather
519
- * than polluting the single-source accounting with an estimate). */
519
+ * cutoff cancelled the stream before usage arrived) or the brain flagged its frame unknown. Consumers
520
+ * must treat `usage` as UNKNOWN — its zeros are not a measured 0 (the provider still served the
521
+ * request; `stats` under-counts it honestly rather than polluting the single-source accounting
522
+ * with an estimate). Absent on a measured turn (never `false`). */
520
523
  usageMissing?: true;
521
524
  /** TB telemetry B1: the NORMALIZED finish reason of the turn's LAST model call —
522
525
  * the engine's `AssistantMessage.stopReason` (`StopReason`: `"stop"`/`"length"`/`"toolUse"`/
@@ -789,7 +792,7 @@ export type TaskEvent = ({
789
792
  */
790
793
  taskType?: DelegationTaskType;
791
794
  /**
792
- * #258 — the registry row's STOP-CYCLE generation this tick reports from (fresh
795
+ * The registry row's STOP-CYCLE generation this tick reports from (fresh
793
796
  * spawn = 1, every launched revival bumps it), the same counter `TaskNotificationPayload.seq`
794
797
  * and `BackgroundChildEvent.seq` already speak — one axis, not a third spelling. It answers
795
798
  * the one question a fleet consumer cannot otherwise decide when a frame arrives late: "late
@@ -92,7 +92,7 @@ export interface TaskLimits {
92
92
  atCostFraction: number;
93
93
  };
94
94
  /**
95
- * RB-458 (ruled 2026-08-03) — the OUTER wall on how long the engine waits for a single brain
95
+ * The OUTER wall on how long the engine waits for a single brain
96
96
  * call, in ms. Default {@link import("../brain/timeout.js").BRAIN_CALL_GUARDRAIL_DEFAULT_MS}
97
97
  * (one hour); `false` or `0` switches it off; any other non-positive / non-finite value is a
98
98
  * config error (fail-loud, never folded to a default). Overrides `RunnerDeps.brainCallGuardrailMs`.
@@ -279,7 +279,7 @@ export interface SystemInjection<TPayload = unknown> {
279
279
  * repeat, or refusing the repeat typed, would each turn a dedup fold into a delivery mutation. */
280
280
  export declare function taskNotificationDedupKey(n: Pick<TaskNotificationPayload, "task_id" | "task_type" | "status" | "seq">): string;
281
281
  /**
282
- * RB-142 — the lane-scoped identity of a task, extracted from {@link taskNotificationDedupKey} so every
282
+ * The lane-scoped identity of a task, extracted from {@link taskNotificationDedupKey} so every
283
283
  * place that treats "same task" as one bucket applies the SAME lane rule.
284
284
  *
285
285
  * The dedup key had the lane segment from the start; three other sites did not — the pending store's
@@ -397,7 +397,7 @@ export interface DrainedPendingNotifications {
397
397
  priorities?: Map<TaskNotificationPayload, SystemInjectionPriority>;
398
398
  /** task_id → notifications evicted by the bounds while pending (never delivered). `taskType` remembers
399
399
  * the victim's lane so a survivors-none disclosure can still render an honest synthetic payload. */
400
- /** RB-142: keyed by {@link taskNotificationLaneKey}, NOT the bare `task_id` — the external lane's ids are
400
+ /** Keyed by {@link taskNotificationLaneKey}, NOT the bare `task_id` — the external lane's ids are
401
401
  * caller-supplied, so one bare-id row could cover two lanes and name only one of their types. `taskId`
402
402
  * carries the victim's real id back out (the lane key is process-internal and must never be rendered). */
403
403
  dropped: Map<string, {
@@ -406,7 +406,7 @@ export interface DrainedPendingNotifications {
406
406
  taskId: string;
407
407
  }>;
408
408
  /**
409
- * RB-114 (2026-07-25, defect probe): notifications lost when this whole SESSION was evicted by the
409
+ * Notifications lost when this whole SESSION was evicted by the
410
410
  * session-count cap, kept OUT of `dropped`. RB-91 folded them in under a `"(evicted-session)"` string
411
411
  * key, which put a session-level fact into a per-task ledger and broke twice for it: the key could
412
412
  * collide with a real, free-form external `task_id` (merging two unrelated counts and mislabelling the
@@ -421,7 +421,7 @@ export declare class PendingSessionNotifications {
421
421
  /** Whole sessions evicted by {@link MAX_PENDING_SESSIONS} (their pendings were never delivered). */
422
422
  droppedSessions: number;
423
423
  /**
424
- * RB-91 (2026-07-25, red probe): a TOMBSTONE per whole-session eviction, so that session's next drain
424
+ * A TOMBSTONE per whole-session eviction, so that session's next drain
425
425
  * can still say what it lost. The two item-level caps disclose their drops per task (they mutate a
426
426
  * surviving session's `dropped` map), but the session-count cap deleted the whole record and only
427
427
  * bumped a global, unattributed counter — from the evicted session's point of view its next drain
@@ -430,7 +430,7 @@ export declare class PendingSessionNotifications {
430
430
  * Bounded like the sessions map itself (a tombstone is two numbers and a lane tag).
431
431
  */
432
432
  private readonly evictedSessions;
433
- /** RB-143: whole-session losses whose tombstone was itself evicted — the count survives, the attribution
433
+ /** Whole-session losses whose tombstone was itself evicted — the count survives, the attribution
434
434
  * does not. Surfaced on the next session-level disclosure so it is never simply forgotten. */
435
435
  private unattributedDrops;
436
436
  pend(sessionId: string, n: TaskNotificationPayload, priority?: SystemInjectionPriority): void;
@@ -173,7 +173,7 @@ export declare function parkBackgroundAgentLane(core: DurableAgentCore, id: stri
173
173
  * `excludeWriterId` = this instance's writerId, so foreign (dead-process) rows are cleaned
174
174
  * without ever touching a row this process is live-managing.
175
175
  *
176
- * backlog #400 — the live half used to skip EVERY non-expired/missing state, `resolved` included, and
176
+ * The live half used to skip EVERY non-expired/missing state, `resolved` included, and
177
177
  * that was the whole zombie: a parked row whose checkpoint was decided by the task-level
178
178
  * `resumeCheckpoint` leg (a serving layer's documented fallback when its parked-row discriminator
179
179
  * misses) is decided but still says `parked`, its side effects already executed by a path that never
@@ -321,7 +321,7 @@ export declare function resolveBackgroundAgentByNameLane(core: DurableAgentCore,
321
321
  * a capacity/pin failure (or plain session-scope) could never drain. No-op on unknown ids. */
322
322
  export declare function markRetainedContinuationLane(core: DurableAgentCore, id: string): void;
323
323
  /**
324
- * #258 — the stop-cycle generation of the RUN BEING SPAWNED under this row (the same counter the
324
+ * The stop-cycle generation of the RUN BEING SPAWNED under this row (the same counter the
325
325
  * register/revive lanes keep on the handle: fresh spawn = 1, durable-seeded revive = the claimed
326
326
  * row's seq, in-memory wake = the bump). The spawn lanes read it ONCE, right after registering, to
327
327
  * thread into the child's `RunInternals.cycleSeq` — one authoritative source instead of each lane
@@ -444,7 +444,7 @@ export declare function deliverToRunningAgentLane(core: DurableAgentCore, id: st
444
444
  * very rows a retry needs. The task faces' split lives in `runningAgentFooterLane` (RB-332). */
445
445
  export declare function runningBackgroundAgentLabelsLane(core: DurableAgentCore, access: TaskAccess): string[];
446
446
  /**
447
- * RB-332 — the not-found FOOTER's two rows, split the way CC 220 assembles them:
447
+ * The not-found FOOTER's two rows, split the way CC 220 assembles them:
448
448
  * - `named` = CC `uG_` (220:467941-467953): the agentNameRegistry's KEYS whose task is a running local
449
449
  * agent, listed as BARE NAMES — the string a retry should pass verbatim. sema's counterpart
450
450
  * of "has a registry entry" is the handle carrying an explicit `name` (spawn-time label),
@@ -461,7 +461,7 @@ export declare function runningAgentFooterLane(core: DurableAgentCore, access: T
461
461
  named: string[];
462
462
  background: string[];
463
463
  };
464
- /** RB-332/RB-333 — the not-found TAIL both task faces share (CC `rxo`, appended by `uMs` for TaskStop
464
+ /** The not-found TAIL both task faces share (CC `rxo`, appended by `uMs` for TaskStop
465
465
  * and by `xwd` 220:472095-472097 for TaskOutput). Empty string when the caller has nothing running. */
466
466
  export declare function notFoundRunningAgentsTail(footer: {
467
467
  named: string[];
@@ -543,7 +543,7 @@ export declare function serveDurableAgentRowLane(row: BackgroundAgentRecord): Un
543
543
  */
544
544
  export declare function spillClippedAgentResult(handle: BackgroundAgentTaskHandle, full: string, clipped: string, store: ToolResultStore | undefined, sessionId: string | undefined): Promise<string>;
545
545
  export declare function pollBackgroundAgentLane(handle: BackgroundAgentTaskHandle, deadline?: number, signal?: AbortSignal,
546
- /** RB-220 — mirrors {@link import("./types.js").TaskSpec.oneShot} (see
546
+ /** Mirrors {@link import("./types.js").TaskSpec.oneShot} (see
547
547
  * {@link import("./task-registry.js").TaskToolOptions.oneShot} for the full contract): this run has
548
548
  * no later turn for an async background notification to land in, so the still-running body must
549
549
  * not teach "you will be notified when it completes". */
@@ -1,7 +1,7 @@
1
1
  import type { TaskNotificationPayload } from "./task-notification.js";
2
2
  import { type RegistryCore, type RegisterMonitorInput, type MonitorTaskHandle, type UnifiedTaskResult } from "./task-registry-shared.js";
3
3
  export declare function registerMonitorLane(core: RegistryCore, input: RegisterMonitorInput): string;
4
- /** RB-239: ONE absorption arithmetic for a monitor poll — env-side-loss accounting
4
+ /** ONE absorption arithmetic for a monitor poll — env-side-loss accounting
5
5
  * (RB-238), the spool roll (registry memory bound) and the completed-line split — shared by the
6
6
  * watcher tick and the stop-time final drain. A hand-copied twin in stopMonitor is how half-fixes
7
7
  * happen: any change to the roll/line rules must reach both consumers through this method. Returns
@@ -12,7 +12,7 @@ export declare function absorbMonitorPollLane(handle: MonitorTaskHandle, v: {
12
12
  truncated?: boolean;
13
13
  bytesDroppedBeforeCursor?: number;
14
14
  }): string[];
15
- /** RB-239: the swallow-guarded event sink, shared by the watcher's emits and the stop-time drain. */
15
+ /** The swallow-guarded event sink, shared by the watcher's emits and the stop-time drain. */
16
16
  export declare function emitMonitorEventLane(handle: MonitorTaskHandle, n: TaskNotificationPayload): void;
17
17
  /** The monitor watcher tick loop. Same zombie-proofing discipline as {@link startBashWatcher}
18
18
  * (re-entrancy guard / stop on eviction / stop on vanished shell / stop on a throwing adapter),
@@ -22,7 +22,7 @@ export type SemaTaskStatus = "pending" | "running" | "parked" | "completed" | "f
22
22
  export type TaskRetrievalStatus = "success" | "not_ready" | "timeout";
23
23
  export interface UnifiedTaskOutput {
24
24
  task_id: string;
25
- /** RB-92 (2026-07-25, red probe): `"unknown"` is a DECLARED member here, not a stray literal. A
25
+ /** `"unknown"` is a DECLARED member here, not a stray literal. A
26
26
  * not-found lookup has no task kind to report, and the TaskStop envelope's `task_type` is required by
27
27
  * the client schema — so the wrapper was already emitting `"unknown"` while the type said it could
28
28
  * only be a `SemaTaskType`. Declaring it keeps the two honest with each other, and keeps `SemaTaskType`
@@ -146,7 +146,7 @@ export interface BackgroundBashTaskHandle extends SemaTaskHandle {
146
146
  * `mirrorFailed` records that at least one append to the advertised output FILE failed — the terminal
147
147
  * frame then discloses the file as incomplete instead of letting the launch receipt's "full output is
148
148
  * appended there" promise stand over a silently partial file. */
149
- /** RB-238: `droppedBytes`/`dropUnknown` account ENV-SIDE tail-buffer eviction disclosed by
149
+ /** `droppedBytes`/`dropUnknown` account ENV-SIDE tail-buffer eviction disclosed by
150
150
  * the poll (`bytesDroppedBeforeCursor`/`truncated`) — a loss upstream of (and distinct from) the
151
151
  * registry's own `rolledChars` memory bound. Bytes counted here never reached the spool at all. */
152
152
  spool?: {
@@ -182,7 +182,7 @@ export interface WorkflowTaskHandle extends SemaTaskHandle {
182
182
  store?: WorkflowRunStore;
183
183
  /** B-1 (live leg) — see {@link RegisterWorkflowInput.originatingSessionId}. */
184
184
  originatingSessionId?: string;
185
- /** RB-215: design/129 session-lifetime discipline, extended to workflow — the
185
+ /** Design/129 session-lifetime discipline, extended to workflow — the
186
186
  * ONE background kind that never had it (`background_bash`/`monitor`/`background_agent` all do).
187
187
  * Unlike those three (task-scoped BY DEFAULT, `sessionScoped` an explicit opt-in via
188
188
  * `TaskSpec.backgroundScope`), a workflow is unconditionally session-anchored — `originatingSessionId`
@@ -198,7 +198,7 @@ export interface WorkflowTaskHandle extends SemaTaskHandle {
198
198
  sessionScoped?: true;
199
199
  /** See {@link RegisterWorkflowInput.onServedTerminal}. Cleared after the single fire. */
200
200
  onServedTerminal?: () => void;
201
- /** 复审 r2 MAJOR: the bounded return value, captured on the done-hook so the STORE-LESS in-memory lane's
201
+ /** The bounded return value, captured on the done-hook so the STORE-LESS in-memory lane's
202
202
  * terminal poll can hand it over too (the launch note promises it; without a store there was no result). */
203
203
  result?: string;
204
204
  /** T2A-8: the failure reason (bounded + redacted), captured on the done-hook's rejection so a store-less
@@ -232,7 +232,7 @@ export interface BackgroundAgentTaskHandle extends SemaTaskHandle {
232
232
  type: "background_agent";
233
233
  /** design/115 P3: aborting this cancels the child run (TaskStop / parent teardown). */
234
234
  abort: AbortController;
235
- /** RB-236 — lineage axes, declared (registration always spread them into the handle; readers used
235
+ /** Lineage axes, declared (registration always spread them into the handle; readers used
236
236
  * to cast). `rootSessionId` feeds {@link canAccess}'s root-session arm; the other two stay
237
237
  * read-only lineage metadata on the live face (no parentSessionId access arm — see the arm's
238
238
  * comment for why). The register side clamps `parentTaskId`. */
@@ -313,7 +313,7 @@ export interface BackgroundAgentTaskHandle extends SemaTaskHandle {
313
313
  /** Terminal snapshot (bounded, {@link BG_AGENT_RESULT_MAX} in subagent.ts) — served by TaskOutput
314
314
  * once the child finishes. */
315
315
  result?: string;
316
- /** RB-205-B: the FULL result (bounded only by the defensive {@link BG_AGENT_RESULT_FULL_MAX} ceiling
316
+ /** The FULL result (bounded only by the defensive {@link BG_AGENT_RESULT_FULL_MAX} ceiling
317
317
  * in subagent.ts), set ONLY when it differs from `result` — same shape as {@link WorkflowRun.resultFull}
318
318
  * (workflow.ts NH-1). Before this field existed, the settle call sites pre-sliced `child.result` to
319
319
  * ~2-4K chars with no disclosure — clipTaskOutput's own file-pointer/offload-friendly design at the
@@ -350,7 +350,7 @@ export interface BackgroundAgentTaskHandle extends SemaTaskHandle {
350
350
  * overloaded/timeout/network ⇒ true, logic ⇒ false). Stored rather than re-derived so the core
351
351
  * poll lane never has to import the agents-domain classifier (no new domain cycle). */
352
352
  errorRetryable?: boolean;
353
- /** RB-405 — the coarse classification KIND beside `errorRetryable`
353
+ /** The coarse classification KIND beside `errorRetryable`
354
354
  * (classifySubagentError's error_kind ∈ rate_limit/overloaded/timeout/network/logic), threaded
355
355
  * from the same settle mint point and stored for the same no-domain-cycle reason as its sibling.
356
356
  * Rendered on the FAILED row's poll TEXT face as the `(error_kind: …, retryable: …)` clause —
@@ -421,7 +421,7 @@ export interface MonitorTaskHandle extends SemaTaskHandle {
421
421
  lineBuf: string;
422
422
  /** Per-batch monotonic counter → unique notification dedup keys (see task-notification.ts). */
423
423
  seq: number;
424
- /** RB-334 (CC `PCo`/`TIs` 220:403278-403321): the TWO-LEVEL event-storm control's state.
424
+ /** The TWO-LEVEL event-storm control's state.
425
425
  * Level 1 = a token bucket (`stormTokens` out of `stormBurst`, refilled one per
426
426
  * `stormRefillIntervalMs`): a batch that cannot consume a token is SUPPRESSED (its lines stay in the
427
427
  * re-readable spool) and counted in `suppressedBatches`; the next batch that DOES consume one first
@@ -452,7 +452,7 @@ export interface MonitorTaskHandle extends SemaTaskHandle {
452
452
  deadlineAt?: number;
453
453
  timeoutMs?: number;
454
454
  watcher?: unknown;
455
- /** RB-239: a watcher tick is suspended on its pollBackground await RIGHT NOW. The stop-time
455
+ /** A watcher tick is suspended on its pollBackground await RIGHT NOW. The stop-time
456
456
  * final drain must skip its own poll then (that in-flight tick already consumed the env cursor — and a
457
457
  * never-resolving adapter must not pin TaskStop). Set/cleared in lockstep with the tick's re-entrancy
458
458
  * guard. */
@@ -486,7 +486,7 @@ export interface MonitorTaskHandle extends SemaTaskHandle {
486
486
  /** design/158 S2 — cumulative chars (UTF-16 code units, `string.length`) handed to `store.put`
487
487
  * across every segment this handle has spilled so far (both streams combined) — the per-handle
488
488
  * disk-cap accounting ({@link import("./task-registry-monitor.js")} reads `MONITOR_SPILL_CAP_CHARS`
489
- * against this). RB-396-b: the field used to be named `spillBytesUsed` while the ledger counted
489
+ * against this). The field used to be named `spillBytesUsed` while the ledger counted
490
490
  * chars — renamed to the axis it really measures (see the constant's own doc for why chars). */
491
491
  spillCharsUsed?: number;
492
492
  /** design/158 S2 — the per-handle spill cap (`MONITOR_SPILL_CAP_CHARS`) was reached; further
@@ -518,10 +518,10 @@ export interface RegisterMonitorInput extends TaskAccess {
518
518
  timers?: MonitorTimers;
519
519
  /** Batch window (ms, default 200): lines arriving within one tick coalesce into one notification. */
520
520
  batchWindowMs?: number;
521
- /** RB-334: the SUSTAINED batch rate the storm bucket refills at (default 50/min). Exceeding it is
521
+ /** The SUSTAINED batch rate the storm bucket refills at (default 50/min). Exceeding it is
522
522
  * suppression, not death — see `stormBurst` and MONITOR_STORM_KILL_AFTER_MS. */
523
523
  maxBatchesPerMinute?: number;
524
- /** RB-334: burst capacity of the storm bucket (default MONITOR_STORM_BURST = CC's 10). */
524
+ /** Burst capacity of the storm bucket (default MONITOR_STORM_BURST = CC's 10). */
525
525
  stormBurst?: number;
526
526
  now?: number;
527
527
  /** design/158 S2 (RB-364 半) — the offload store a rolled-off spool middle spills to (see
@@ -563,23 +563,23 @@ export declare const MONITOR_BATCH_WINDOW_MS = 200;
563
563
  export declare const MONITOR_DEFAULT_TIMEOUT_MS = 300000;
564
564
  export declare const MONITOR_MAX_TIMEOUT_MS = 3600000;
565
565
  export declare const MONITOR_MAX_BATCHES_PER_MINUTE = 50;
566
- /** RB-334 (CC `bIs` 220:403421): burst capacity of the storm token bucket — how many batches may fire
566
+ /** Burst capacity of the storm token bucket — how many batches may fire
567
567
  * back-to-back before the SUPPRESSION level engages. CC value, adopted verbatim. */
568
568
  export declare const MONITOR_STORM_BURST = 10;
569
- /** RB-334 (CC `FN_` 220:403423): how long a monitor must stay CONTINUOUSLY over budget before the
569
+ /** How long a monitor must stay CONTINUOUSLY over budget before the
570
570
  * second level (kill) fires. CC value, adopted verbatim. */
571
571
  export declare const MONITOR_STORM_KILL_AFTER_MS = 30000;
572
- /** RB-334 (CC `bdd` 220:403427): the partial-line accumulator bound. sema's `lineBuf` had NO bound —
572
+ /** The partial-line accumulator bound. sema's `lineBuf` had NO bound —
573
573
  * a monitored process emitting megabytes without a single newline grew it without limit (the spool's
574
574
  * own roll never covered it). Keep the TAIL (the newest bytes are the ones a watch is about). */
575
575
  export declare const MONITOR_LINE_BUF_CAP = 1048576;
576
- /** RB-239: the monitor event-result clip, shared by the watcher's batch/terminal emits and
576
+ /** The monitor event-result clip, shared by the watcher's batch/terminal emits and
577
577
  * the stop-time drain emit (one clip, one truncation wording). */
578
578
  export declare function clipMonitorEvent(s: string): string;
579
- /** RB-334 (CC `DCo` leg): per-line clip applied to the `lines[]` a batch carries. Spool untouched. */
579
+ /** Per-line clip applied to the `lines[]` a batch carries. Spool untouched. */
580
580
  export declare function clipMonitorLine(s: string): string;
581
581
  /**
582
- * RB-335 (CC `rFs` 220:507725-507743, all six branches verbatim): the ONE terminal-notification summary
582
+ * The ONE terminal-notification summary
583
583
  * HEAD for a background command / monitor watch. Every terminal frame in the bash and monitor lanes
584
584
  * composes its summary as `terminalTaskSummary(...)` plus this lane's own honest detail clause — the
585
585
  * pre-RB-335 code had six hand-written phrasings whose comment claimed "no CC sample for those faces"
@@ -619,14 +619,14 @@ export declare function rollSpoolText(spool: {
619
619
  * matching the pre-S2 loss shape for whatever is dropped PAST the cap. Exported so the boundary is a
620
620
  * testable contract, not a buried literal.
621
621
  *
622
- * RB-396-b (回溯复查批, [c209-C] R2 C4① char/byte 同名异轴族): the constant used to be named
622
+ * The constant used to be named
623
623
  * `..._BYTES` while the ledger added `dropped.length` — chars, up to ~3× fewer than UTF-8 bytes on
624
624
  * multibyte content. CHARS is the axis kept (name changed, arithmetic untouched) because it is the
625
625
  * offload store family's own coordinate (`InMemoryToolResultStore.maxTotalChars` evicts by
626
626
  * `content.length`; `ToolResultSlice.totalChars`) and the spool's `rolledChars` axis — one unit
627
627
  * end-to-end; a `Buffer.byteLength` ledger here would sit crosswise to the store's own cap. */
628
628
  export declare const MONITOR_SPILL_CAP_CHARS: number;
629
- /** RB-238: fold one poll's env-side-loss disclosure into the spool's account. The env's
629
+ /** Fold one poll's env-side-loss disclosure into the spool's account. The env's
630
630
  * tail buffer evicts its HEAD under pressure (node-execution-env 8MB bound) — those bytes are gone
631
631
  * before any watcher ever saw them, which is a different loss than the registry-side `rolledChars`
632
632
  * middle-drop. `bytesDroppedBeforeCursor` only counts bytes dropped before an unconsumed cursor, so
@@ -645,7 +645,7 @@ export declare function accountDroppedBytes(spool: {
645
645
  truncated?: boolean;
646
646
  bytesDroppedBeforeCursor?: number;
647
647
  }): void;
648
- /** RB-238 — the POLL-FACE wording for env-side loss (the terminal/event-frame wording is
648
+ /** The POLL-FACE wording for env-side loss (the terminal/event-frame wording is
649
649
  * {@link droppedGapNote}'s; the two faces differ by design and always have). One function so the two
650
650
  * quantified/unquantified branches cannot drift between the three legs that render it: the monitor
651
651
  * re-readable spool, the bash re-readable spool, and the bash blocked wait. Trailing newline included
@@ -686,7 +686,7 @@ export interface SpoolBodyOptions {
686
686
  /** A full banner line (own trailing newline) rendered after the drop note, or "". */
687
687
  drainNote: string;
688
688
  }
689
- /** RB-238/RB-239/RB-240 — the ONE renderer for a re-readable spool's TaskOutput body,
689
+ /** The ONE renderer for a re-readable spool's TaskOutput body,
690
690
  * shared by the monitor lane (pollMonitorLane) and the bash spool lane (pollBackgroundBash).
691
691
  *
692
692
  * Both faces were hand-copied twins carrying three real disclosure bugs' worth of wording (env-side
@@ -700,19 +700,19 @@ export interface SpoolBodyOptions {
700
700
  * wording ("accumulated char(s) dropped from the middle during the blocked wait"), an intentional
701
701
  * divergence — it shares {@link accountDroppedBytes} + {@link spoolDropNote}, not this. */
702
702
  export declare function renderSpoolBody(spool: RenderableSpool, opts: SpoolBodyOptions): string;
703
- /** RB-238: the honesty suffix for frames over a spool with env-side loss. Empty when nothing dropped. */
703
+ /** The honesty suffix for frames over a spool with env-side loss. Empty when nothing dropped. */
704
704
  export declare function droppedGapNote(spool: {
705
705
  droppedBytes?: number;
706
706
  dropUnknown?: true;
707
707
  }): string;
708
- /** RB-238: the event-stream disclosure rides the FIRST batch after a loss is observed (once-latch —
708
+ /** The event-stream disclosure rides the FIRST batch after a loss is observed (once-latch —
709
709
  * a chatty watch must not repeat the note on every batch; terminal frames disclose unconditionally). */
710
710
  export declare function firstDropNote(spool: {
711
711
  droppedBytes?: number;
712
712
  dropUnknown?: true;
713
713
  dropNotified?: true;
714
714
  }): string;
715
- /** RB-244: ONE wording for "you stopped nothing" across every already-terminal stop face —
715
+ /** ONE wording for "you stopped nothing" across every already-terminal stop face —
716
716
  * the in-process bash/monitor/agent arms and the durable-row fallback previously split: the durable
717
717
  * arm answered honestly while the in-process arms claimed `Terminated <id>.` over work that finished
718
718
  * (or was killed) on its own. CC 220 refuses the call outright (`Task X is not running (status: …)`,
@@ -781,7 +781,7 @@ export declare function editDistance(a: string, b: string): number;
781
781
  /** CC `htr` shape (206:519814-519827): candidates within Levenshtein ≤2 (length-diff ≤2 pre-filter),
782
782
  * best-first; the single best is the "Did you mean" suggestion (`htr(e, keys, 1)[0]`, 206:575196). */
783
783
  export declare function closestName(query: string, candidates: Iterable<string>): string | undefined;
784
- /** Ruled 2026-07-22: DEFAULT-DENY on BOTH axes — the old predicate skipped
784
+ /** DEFAULT-DENY on BOTH axes — the old predicate skipped
785
785
  * a missing axis (owner-less handle = readable by everyone in scope; scope-less handle = readable
786
786
  * across scopes), splitting polarity with `canAccessAgentRecord` and re-opening the session-axis
787
787
  * class cli/server just swept. Registration now REQUIRES both axes ({@link assertOwnership}), so a
@@ -822,7 +822,7 @@ export interface ParkedClaimTicket {
822
822
  reservedRev: number;
823
823
  row: import("./background-agent-store.js").BackgroundAgentRecord;
824
824
  }
825
- /** P1-3 独立复审第三轮(已修) — sibling of {@link mintCompletionId} for a caller that must compute the
825
+ /** Sibling of {@link mintCompletionId} for a caller that must compute the
826
826
  * value BEFORE it is safe to commit (a CAS not yet known to win): fill-once with an EXTERNALLY-chosen
827
827
  * value instead of generating a fresh one. Exists because `rollbackParkedClaim`'s original fix minted
828
828
  * directly onto the live handle before its durable CAS was confirmed — a losing CAS then left a
@@ -2,8 +2,8 @@ import { uuidv7 } from "../internal/harness.js";
2
2
  import { summarizeWorkflowRun } from "./workflow-run-store.js";
3
3
  import { delimitUntrusted } from "./untrusted-text.js";
4
4
  import { boundedRedactedSummary } from "./untrusted-egress.js";
5
- import { clipWithFilePointer } from "./tool-errors.js";
6
- import { announceEnvKnob } from "./env-knob-announce.js";
5
+ import { clipWithFilePointer, OUTPUT_BUDGET_MIN_CHARS } from "./tool-errors.js";
6
+ import { resolveEnvBudget } from "./env-budget.js";
7
7
  export function mintCompletionId(target) {
8
8
  if (target.completionId === undefined)
9
9
  target.completionId = uuidv7();
@@ -60,18 +60,8 @@ export function terminalTaskSummary(kind, label, status, exitCode) {
60
60
  }
61
61
  const TASK_OUTPUT_DEFAULT_CHARS = 32_000;
62
62
  export const TASK_OUTPUT_MAX_CHARS = 160_000;
63
- const TASK_OUTPUT_MIN_CHARS = 512;
64
63
  function taskMaxOutputChars() {
65
- const rawEnv = process.env.TASK_MAX_OUTPUT_LENGTH;
66
- if (rawEnv === undefined || rawEnv.trim() === "")
67
- return TASK_OUTPUT_DEFAULT_CHARS;
68
- const raw = rawEnv.trim();
69
- const n = /^\d+$/.test(raw) ? parseInt(raw, 10) : Number.NaN;
70
- if (!Number.isFinite(n) || n <= 0) {
71
- announceEnvKnob(`TASK_MAX_OUTPUT_LENGTH=${rawEnv} was ignored — it is not a positive whole number of characters. Using ${TASK_OUTPUT_DEFAULT_CHARS} instead.`);
72
- return TASK_OUTPUT_DEFAULT_CHARS;
73
- }
74
- return Math.min(Math.max(n, TASK_OUTPUT_MIN_CHARS), TASK_OUTPUT_MAX_CHARS);
64
+ return resolveEnvBudget(process.env.TASK_MAX_OUTPUT_LENGTH, { name: "TASK_MAX_OUTPUT_LENGTH", unit: "characters", default: TASK_OUTPUT_DEFAULT_CHARS, min: OUTPUT_BUDGET_MIN_CHARS, max: TASK_OUTPUT_MAX_CHARS });
75
65
  }
76
66
  export function clipTaskOutput(s, fullOutputPath) {
77
67
  return clipWithFilePointer(s, taskMaxOutputChars(), fullOutputPath);
@@ -53,7 +53,7 @@ export interface TaskPollOptions {
53
53
  timeoutMs?: number;
54
54
  /** Abort signal — a blocked wait must stop when the tool call is cancelled. */
55
55
  signal?: AbortSignal;
56
- /** RB-220 — mirrors {@link import("./types.js").TaskSpec.oneShot} (see {@link TaskToolOptions.oneShot}
56
+ /** Mirrors {@link import("./types.js").TaskSpec.oneShot} (see {@link TaskToolOptions.oneShot}
57
57
  * for the full contract): forwarded to the background_agent lane's still-running poll body so it
58
58
  * does not teach "you will be notified" when this run has no later turn to receive one. */
59
59
  oneShot?: boolean;
@@ -88,7 +88,7 @@ export interface TaskToolOptions extends TaskAccess {
88
88
  * historical wording); prepare-task passes the real wiring state. */
89
89
  notificationWired?: boolean;
90
90
  /**
91
- * RB-220 — mirrors {@link import("./types.js").TaskSpec.oneShot}: this run has no later turn for an
91
+ * Mirrors {@link import("./types.js").TaskSpec.oneShot}: this run has no later turn for an
92
92
  * async background notification to land in (a headless `-p` process exits once the turn ends).
93
93
  * Threaded into the background_agent lane's non-blocking/blocked-timeout "still running" poll body
94
94
  * (see {@link import("./task-registry-agent.js").pollBackgroundAgentLane}), which otherwise taught
@@ -122,7 +122,7 @@ export interface AccessibleTaskRow {
122
122
  parentTaskId?: string;
123
123
  parentSessionId?: string;
124
124
  rootSessionId?: string;
125
- /** RB-478 — the row's registration instant (the original spawn time for a first-cycle row): the
125
+ /** The row's registration instant (the original spawn time for a first-cycle row): the
126
126
  * revive projection needs it so a revive frame's `startedAt` anchors the ROW, not the wake call. */
127
127
  createdAt?: number;
128
128
  }
@@ -139,11 +139,11 @@ export declare class TaskRegistry {
139
139
  * (cap overflow dropped the watcher; the owner's tasks may still be running — the subscriber must
140
140
  * NOT treat this as quiescence). */
141
141
  private bgQuiescenceWatchers;
142
- /** RB-463 — one host-callback isolation scope for this registry's five notification seams (reap terminal
142
+ /** One host-callback isolation scope for this registry's five notification seams (reap terminal
143
143
  * notifier, session-reap hooks, quiescence fire + cap-overflow eviction, terminal-once send). Same swallow
144
144
  * as the five hand-written try/catches it replaced, now counted per site and readable for diagnostics. */
145
145
  private readonly notifier;
146
- /** RB-473 — the read face for this registry's CONTAINED host-callback failures (site → count).
146
+ /** The read face for this registry's CONTAINED host-callback failures (site → count).
147
147
  * The registry has no deployment error sink of its own to disclose to (it is process-global,
148
148
  * constructed before any RunnerDeps exists), so readability IS its disclosure grade: a deployment
149
149
  * that suspects a broken observer polls this instead of grepping for silence. Empty on the
@@ -241,7 +241,7 @@ export declare class TaskRegistry {
241
241
  agentStore: import("./background-agent-store.js").BackgroundAgentStore;
242
242
  }, ticket: ParkedClaimTicket): Promise<boolean>;
243
243
  finalizeParkedResume(id: string): void;
244
- /** RB-425: `outcome.cycle` names the revive cycle this settle speaks for (absent = 0 = the original
244
+ /** `outcome.cycle` names the revive cycle this settle speaks for (absent = 0 = the original
245
245
  * spawn cycle). A spawn leg never passes it; a caller that settles by LIFECYCLE AUTHORITY (reap /
246
246
  * session release — "whatever is running under this row dies") passes the row's current cycle. See
247
247
  * {@link settleBackgroundAgentLane} for why a stale stamp must be a no-op. */
@@ -283,7 +283,7 @@ export declare class TaskRegistry {
283
283
  suggestion?: string;
284
284
  };
285
285
  markRetainedContinuation(id: string): void;
286
- /** #258 — the row's current stop-cycle counter, read by the spawn lanes right after registering to
286
+ /** The row's current stop-cycle counter, read by the spawn lanes right after registering to
287
287
  * thread into the child's `RunInternals.cycleSeq`; see {@link backgroundAgentCycleSeqLane}. */
288
288
  backgroundAgentCycleSeq(id: string): number | undefined;
289
289
  /** Subagent transcript persistence (delegation entry caps) — one delegation tree's ACTIVE
@@ -399,7 +399,7 @@ export declare class TaskRegistry {
399
399
  * watcher/stop lanes mark and read it too); workflow cancellation is out of scope. */
400
400
  markStopSource(id: string, source: StopSource): void;
401
401
  /**
402
- * RB-164 — attribute an ENV-LEVEL blanket sweep before it runs.
402
+ * Attribute an ENV-LEVEL blanket sweep before it runs.
403
403
  *
404
404
  * The incident: a user's `run_in_background` Bash died mid-run reporting `stopped-by:"system"` with a
405
405
  * zero-byte output file, and diagnosing it took a cross-repo investigation with a timeline argument.