@sema-agent/core 7.16.0 → 7.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (207) hide show
  1. package/CHANGELOG.md +209 -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-engine/engine.js +2 -1
  49. package/dist/core/memory-engine/layout.d.ts +18 -6
  50. package/dist/core/memory-engine/layout.js +40 -21
  51. package/dist/core/memory-recall.d.ts +0 -8
  52. package/dist/core/memory.d.ts +1 -1
  53. package/dist/core/oracle-isolation.js +2 -2
  54. package/dist/core/parent-spec-seat.d.ts +66 -0
  55. package/dist/core/parent-spec-seat.js +47 -0
  56. package/dist/core/permission-rule-model.d.ts +11 -6
  57. package/dist/core/permission-rule-model.js +53 -37
  58. package/dist/core/permission-rules.js +8 -3
  59. package/dist/core/physical-path.d.ts +37 -0
  60. package/dist/core/physical-path.js +30 -0
  61. package/dist/core/protocol-naming.d.ts +2 -2
  62. package/dist/core/remote-env.d.ts +1 -1
  63. package/dist/core/retired-keys.d.ts +19 -0
  64. package/dist/core/retired-keys.js +15 -0
  65. package/dist/core/runner/active-skill-scope.js +3 -3
  66. package/dist/core/runner/assemble-result.d.ts +15 -13
  67. package/dist/core/runner/assemble-result.js +5 -4
  68. package/dist/core/runner/compaction-call-options.d.ts +25 -89
  69. package/dist/core/runner/contracts.d.ts +11 -10
  70. package/dist/core/runner/gate-exit.js +15 -1
  71. package/dist/core/runner/halt-attribution.d.ts +35 -0
  72. package/dist/core/runner/halt-attribution.js +16 -0
  73. package/dist/core/runner/memory-consolidation.d.ts +0 -2
  74. package/dist/core/runner/memory-consolidation.js +0 -1
  75. package/dist/core/runner/prepare-artifact.d.ts +52 -0
  76. package/dist/core/runner/prepare-artifact.js +63 -0
  77. package/dist/core/runner/prepare-caps-and-workflow.d.ts +4 -2
  78. package/dist/core/runner/prepare-caps-and-workflow.js +2 -3
  79. package/dist/core/runner/prepare-config-doors.d.ts +3 -3
  80. package/dist/core/runner/prepare-config-doors.js +5 -2
  81. package/dist/core/runner/prepare-context-lane.d.ts +2 -2
  82. package/dist/core/runner/prepare-context-lane.js +2 -13
  83. package/dist/core/runner/prepare-file-history.d.ts +1 -1
  84. package/dist/core/runner/prepare-file-history.js +3 -52
  85. package/dist/core/runner/prepare-hands-readface.d.ts +4 -7
  86. package/dist/core/runner/prepare-hands-readface.js +3 -2
  87. package/dist/core/runner/prepare-inherited-gate.d.ts +5 -2
  88. package/dist/core/runner/prepare-inherited-gate.js +7 -8
  89. package/dist/core/runner/prepare-memory.d.ts +4 -6
  90. package/dist/core/runner/prepare-memory.js +4 -2
  91. package/dist/core/runner/prepare-policy-chain.d.ts +3 -3
  92. package/dist/core/runner/prepare-policy-chain.js +15 -30
  93. package/dist/core/runner/prepare-prompt-assembly.js +1 -1
  94. package/dist/core/runner/prepare-question-face.js +2 -1
  95. package/dist/core/runner/prepare-safety-scan.d.ts +1 -1
  96. package/dist/core/runner/prepare-suspend-saga.js +0 -2
  97. package/dist/core/runner/prepare-task.js +12 -11
  98. package/dist/core/runner/prepare-wiring-manifest.js +9 -7
  99. package/dist/core/runner/resume-admission.js +2 -1
  100. package/dist/core/runner/resume-internals-and-config.js +4 -0
  101. package/dist/core/runner/retired-runner-deps.d.ts +3 -0
  102. package/dist/core/runner/retired-runner-deps.js +7 -0
  103. package/dist/core/runner/run-harness-handlers.js +5 -3
  104. package/dist/core/runner/run-settle-and-teardown.d.ts +1 -1
  105. package/dist/core/runner/run-settle-and-teardown.js +3 -1
  106. package/dist/core/runner/session-file-state-replay.js +3 -3
  107. package/dist/core/runner/session-rule-policy.js +3 -4
  108. package/dist/core/runner/stream-halt-verbs.js +1 -1
  109. package/dist/core/runner/stream-steer-verb.js +1 -4
  110. package/dist/core/runner/workspace-path.js +3 -0
  111. package/dist/core/runner-deps.d.ts +30 -49
  112. package/dist/core/safe-notify.d.ts +1 -1
  113. package/dist/core/sensitive-path-policy.d.ts +1 -1
  114. package/dist/core/sensitive-path-policy.js +11 -12
  115. package/dist/core/session.d.ts +2 -2
  116. package/dist/core/skill-tool-specifier.d.ts +1 -1
  117. package/dist/core/skills-directory.d.ts +1 -1
  118. package/dist/core/skills-directory.js +4 -3
  119. package/dist/core/spec-contract.js +5 -4
  120. package/dist/core/store-contracts/checkpoint-store-contract.js +1 -1
  121. package/dist/core/strategy-store.d.ts +8 -11
  122. package/dist/core/task-event.d.ts +20 -17
  123. package/dist/core/task-limits.d.ts +1 -1
  124. package/dist/core/task-notification.d.ts +5 -5
  125. package/dist/core/task-registry-agent.d.ts +5 -5
  126. package/dist/core/task-registry-monitor.d.ts +2 -2
  127. package/dist/core/task-registry-shared.d.ts +32 -28
  128. package/dist/core/task-registry-shared.js +4 -13
  129. package/dist/core/task-registry.d.ts +8 -8
  130. package/dist/core/task-result.d.ts +37 -37
  131. package/dist/core/task-spec.d.ts +5 -5
  132. package/dist/core/task-stream.d.ts +16 -11
  133. package/dist/core/tool-catalog-entries.d.ts +1 -0
  134. package/dist/core/tool-catalog-entries.js +6 -1
  135. package/dist/core/tool-conformance.d.ts +0 -2
  136. package/dist/core/tool-conformance.js +1 -3
  137. package/dist/core/tool-errors.d.ts +5 -0
  138. package/dist/core/tool-errors.js +1 -0
  139. package/dist/core/tool-policy.d.ts +66 -22
  140. package/dist/core/tool-policy.js +31 -5
  141. package/dist/core/tool-result-budget.d.ts +1 -1
  142. package/dist/core/tool-result-store.d.ts +11 -11
  143. package/dist/core/tool-spec.d.ts +34 -38
  144. package/dist/core/tools.d.ts +2 -2
  145. package/dist/core/trace.d.ts +12 -15
  146. package/dist/core/untrusted-text.d.ts +1 -1
  147. package/dist/core/wiring-manifest.d.ts +4 -3
  148. package/dist/core/workflow-journal-store.d.ts +11 -11
  149. package/dist/engine/execution-env/node-execution-env.d.ts +3 -2
  150. package/dist/engine/execution-env/node-execution-env.js +8 -5
  151. package/dist/engine/harness/agent-harness.d.ts +47 -4
  152. package/dist/engine/harness/agent-harness.js +52 -9
  153. package/dist/engine/loop/agent-loop.js +15 -8
  154. package/dist/engine/loop/types.d.ts +5 -0
  155. package/dist/index.d.ts +20 -14
  156. package/dist/index.js +16 -10
  157. package/dist/internal/harness.d.ts +1 -0
  158. package/dist/orchestration/run-spec.d.ts +3 -0
  159. package/dist/orchestration/run-spec.js +3 -3
  160. package/dist/orchestration/run-workflow-tool.d.ts +12 -6
  161. package/dist/orchestration/run-workflow-tool.js +23 -5
  162. package/dist/orchestration/workflow-primitives.d.ts +4 -2
  163. package/dist/orchestration/workflow-primitives.js +1 -4
  164. package/dist/orchestration/workflow-script-store.js +9 -25
  165. package/dist/orchestration/workflow-types.d.ts +34 -4
  166. package/dist/orchestration/workflow-types.js +2 -0
  167. package/dist/orchestration/workflow.d.ts +39 -7
  168. package/dist/orchestration/workflow.js +237 -113
  169. package/dist/prompt-assembly/assemble.d.ts +2 -2
  170. package/dist/prompt-assembly/assemble.js +9 -9
  171. package/dist/prompt-assembly/composer.d.ts +6 -7
  172. package/dist/prompt-assembly/composer.js +10 -10
  173. package/dist/prompt-assembly/epoch.js +1 -1
  174. package/dist/prompt-assembly/event-registry.d.ts +0 -21
  175. package/dist/prompt-assembly/packs/sema-default.js +30 -30
  176. package/dist/prompt-assembly/types.d.ts +14 -14
  177. package/dist/prompts/coordinator.d.ts +0 -13
  178. package/dist/prompts/coordinator.js +0 -3
  179. package/dist/stores/cc/task-list-store.js +2 -10
  180. package/dist/stores/file/checkpoint-store.js +1 -5
  181. package/dist/stores/file/file-history-store.js +2 -2
  182. package/dist/stores/file/fs-atomic.d.ts +15 -18
  183. package/dist/stores/file/fs-atomic.js +4 -14
  184. package/dist/stores/file/mailbox-store.d.ts +7 -11
  185. package/dist/stores/file/mailbox-store.js +4 -11
  186. package/dist/stores/file/permission-rule-store.d.ts +4 -35
  187. package/dist/stores/file/permission-rule-store.js +4 -148
  188. package/dist/tools/artifact/artifact-text.d.ts +62 -0
  189. package/dist/tools/artifact/artifact-text.js +68 -0
  190. package/dist/tools/artifact/artifact-tool.d.ts +52 -0
  191. package/dist/tools/artifact/artifact-tool.js +351 -0
  192. package/dist/tools/artifact/local-stub.d.ts +26 -0
  193. package/dist/tools/artifact/local-stub.js +297 -0
  194. package/dist/tools/fs/bash-readonly-classifier.d.ts +90 -8
  195. package/dist/tools/fs/bash-readonly-classifier.js +294 -70
  196. package/dist/tools/fs/fs-bash.d.ts +14 -10
  197. package/dist/tools/fs/fs-bash.js +50 -33
  198. package/dist/tools/fs/fs-search-tools.js +5 -2
  199. package/dist/tools/fs/fs-shared.d.ts +2 -0
  200. package/dist/tools/fs/fs-shared.js +3 -11
  201. package/dist/tools/fs/index.d.ts +4 -0
  202. package/dist/tools/fs/index.js +4 -1
  203. package/dist/tools/fs/safety.d.ts +117 -1
  204. package/dist/tools/fs/safety.js +131 -31
  205. package/dist/tools/fs/search.js +8 -6
  206. package/package.json +2 -1
  207. package/test/export-surface.snapshot.json +119 -39
@@ -19,7 +19,7 @@ export function streamHaltVerbs(input) {
19
19
  if (receipt.accepted && !abortOwnedBeforeHalt) {
20
20
  h.loop.userHalted = true;
21
21
  }
22
- else {
22
+ else if (!h.loop.userHalted) {
23
23
  deliverEngineNotice(runner.deps.onNotice, {
24
24
  code: "task.halt_unconsumed",
25
25
  message: "a user halt arrived while the run was already ending for its own reason: nothing was cut or stopped " +
@@ -1,6 +1,6 @@
1
1
  import { uuidv7 } from "../../internal/harness.js";
2
2
  import { snapshotActorAssertion } from "../../internal/llm.js";
3
- import { LEGACY_PENDING_STEER_INPUT_ID, MAX_STEER_INPUT_ID_CHARS } from "../checkpoint-store.js";
3
+ import { MAX_STEER_INPUT_ID_CHARS } from "../checkpoint-store.js";
4
4
  import { formatHookFeedback, hookSeatExpiredError, runHookSeat } from "../hooks.js";
5
5
  import { buildHumanInputEvent, frameMidTurnUserInput, projectHumanInput } from "../human-input-projection.js";
6
6
  import { isSystemInjectionPriority, SYSTEM_INJECTION_PRIORITIES } from "../task-notification.js";
@@ -23,9 +23,6 @@ export function streamSteerVerb(input) {
23
23
  if (inputId === "" || inputId.length > MAX_STEER_INPUT_ID_CHARS) {
24
24
  throw steeringError(`inputId must be a non-empty string of at most ${MAX_STEER_INPUT_ID_CHARS} characters`, "steering.invalid_content");
25
25
  }
26
- if (inputId === LEGACY_PENDING_STEER_INPUT_ID) {
27
- throw steeringError(`inputId "${LEGACY_PENDING_STEER_INPUT_ID}" is reserved for a pre-queue parked steer and cannot be supplied by a caller`, "steering.invalid_content");
28
- }
29
26
  }
30
27
  const priorityIn = options?.priority;
31
28
  if (priorityIn !== undefined && !isSystemInjectionPriority(priorityIn)) {
@@ -1,6 +1,9 @@
1
+ import { isWinFormPath, pathFamilyOf } from "../../tools/fs/safety.js";
1
2
  export function rebaseWorkspacePath(p, fromRaw, toRaw) {
2
3
  if (p.includes("\\") || fromRaw.includes("\\") || toRaw.includes("\\"))
3
4
  return p;
5
+ if (pathFamilyOf({ root: fromRaw }) !== "posix" || pathFamilyOf({ root: toRaw }) !== "posix" || isWinFormPath(p))
6
+ return p;
4
7
  const stripTrail = (s) => (s.length > 1 && s.endsWith("/") ? stripTrail(s.slice(0, -1)) : s);
5
8
  const from = stripTrail(fromRaw);
6
9
  const to = stripTrail(toRaw);
@@ -187,7 +187,7 @@ export interface RunnerDeps {
187
187
  */
188
188
  readDenyPatterns?: readonly import("../tools/fs/read-deny.js").ReadDenyEntry[];
189
189
  /**
190
- * #245 (revises the D-4 zero-shrink ruling) — the deployment's built-in deny-table TIER selection:
190
+ * The deployment's built-in deny-table TIER selection:
191
191
  * EXACTLY the listed tiers of
192
192
  * {@link import("../tools/fs/read-deny.js").READ_FACE_BUILTIN_DENY_TABLE} are active (`[]` = none —
193
193
  * explicit and legal); absent = the default selection
@@ -203,7 +203,7 @@ export interface RunnerDeps {
203
203
  */
204
204
  readDenyBuiltinTiers?: readonly string[];
205
205
  /**
206
- * #245 — per-row removal from the built-in deny table by STABLE NAME (= the row's canonical
206
+ * Per-row removal from the built-in deny table by STABLE NAME (= the row's canonical
207
207
  * pattern text, e.g. `".ssh"`, `".config/gcloud"`; the admin delete channel), applied after
208
208
  * {@link readDenyBuiltinTiers} selection. Naming a row of an inactive tier is a satisfied intent
209
209
  * (no-op); a name matching NO table row refuses loudly at prepare (#123 — never silently
@@ -490,30 +490,6 @@ export interface RunnerDeps {
490
490
  * in its own audit surface. Values outside the two-member set refuse prepare loudly.
491
491
  */
492
492
  onTrackFailure?: "refuse" | "proceed-unprotected";
493
- /**
494
- * design/381 §5.3① / §10 S-1 — the ADDITIVE discriminant for the rewind refusal that this engine
495
- * cannot decide on its own. When a restore finds no boundary for the requested entry, there are
496
- * two very different worlds: the boundary NEVER existed (those turns ran with no history store, or
497
- * it was reaped), or it exists in the RETIRED whole-tree snapshot epoch, which the per-edited-file
498
- * seat deliberately does not restore. The engine holds no whole-tree state, so absent this probe
499
- * the refusal honestly names BOTH possibilities rather than picking one — the default, and the
500
- * only honest wording for a deployment that never had a whole-tree epoch at all.
501
- *
502
- * A deployment that DOES hold the retired epoch (its assembly layer can ask the old table whether
503
- * that entry has a legacy row) supplies the bit here, and the refusal splits into the two precise
504
- * messages. `true` = a whole-tree-era boundary exists for that entry; `false` = it definitively
505
- * does not; `undefined` = the deployment cannot tell, which reads exactly like an absent probe.
506
- *
507
- * Consulted ONLY on the refusal path (never on a successful restore), so a slow probe costs
508
- * nothing in the ordinary case. It is a DIAGNOSTIC input, never a control input: a probe that
509
- * throws, hangs past the caller's own patience, or answers a non-boolean cannot change the outcome
510
- * — the refusal still happens, the wording falls back to the honest both-possibilities form, and
511
- * the bad value is disclosed through `onError` (phase "rewind") rather than silently absorbed.
512
- */
513
- legacyRewindBoundaryProbe?: (query: {
514
- sessionId: string;
515
- entryId: string;
516
- }) => boolean | undefined | Promise<boolean | undefined>;
517
493
  /**
518
494
  * design/99 §E6 — DURABLE per-session permission rules (a deny-narrowing folded into the task-time tool
519
495
  * policy). Omitted ⇒ the feature is OFF (no rules read, zero behavior change). A deployment supplies a
@@ -713,7 +689,7 @@ export interface RunnerDeps {
713
689
  */
714
690
  denialLimit?: import("./auto-mode.js").AutoModeDenialLimitOptions;
715
691
  /**
716
- * #503 — OPT IN to recording this arming's serializable criteria (an
692
+ * OPT IN to recording this arming's serializable criteria (an
717
693
  * {@link import("./auto-mode-arming.js").AutoModeArmingRecipe}) on the constraint-chain entries a
718
694
  * durable park freezes, so a CROSS-PROCESS redemption can rebuild an equivalent classifier over its
719
695
  * own model leg ({@link import("./auto-mode-rebuild.js").rebuildAutoModeDecider}) instead of
@@ -733,7 +709,7 @@ export interface RunnerDeps {
733
709
  */
734
710
  persistArming?: boolean;
735
711
  /**
736
- * #503 — the deployment's auto-mode SETTINGS GENERATION (a config revision, a settings hash, a
712
+ * The deployment's auto-mode SETTINGS GENERATION (a config revision, a settings hash, a
737
713
  * publish id — the string is opaque to the engine). Recorded in the arming recipe and compared at
738
714
  * rebuild time against the REDEEMING deployment's own: it is a declaration axis that can only make
739
715
  * the rebuild stricter (see {@link import("./auto-mode-arming.js").foldAutoModeArming}). Absent =
@@ -947,7 +923,7 @@ export interface RunnerDeps {
947
923
  /** design/72 §2.2 (B): deployment default for the suspend-loop cap (see `TaskSpec.maxSuspends`).
948
924
  * Default 5 (loose — human-approval flows re-suspend rarely). A task's own `maxSuspends` overrides. */
949
925
  maxSuspends?: number;
950
- /** RB-458 (ruled 2026-08-03): deployment default for the outer per-brain-call guardrail — see
926
+ /** Deployment default for the outer per-brain-call guardrail — see
951
927
  * `TaskSpec.limits.brainCallGuardrailMs` for the semantics (default one hour; `false`/`0` = off;
952
928
  * an invalid value is a fail-loud config error). A task's own `limits.brainCallGuardrailMs`
953
929
  * overrides it. Set it here to cover EVERY run of this Runner, delegated children included — a
@@ -1156,6 +1132,18 @@ export interface RunnerDeps {
1156
1132
  * `undefined` for a file whose language has no server, and the tool degrades to "fall back to grep". A
1157
1133
  * task's own `lspManager` overrides this. Unset ⇒ no `lsp` tool. */
1158
1134
  lspManager?: import("./lsp.js").LspServerManager;
1135
+ /**
1136
+ * The Artifacts hosting seat — a storage/service-tier seam of the same family as
1137
+ * {@link checkpointStore} and {@link rosterStore}. Three states, judged once at prepare: ABSENT ⇒ no
1138
+ * `Artifact` tool and no announcement (the default: a library deployment has no hosting); a host
1139
+ * whose `capabilities()` satisfies the declaration invariants ⇒ ONE `Artifact` tool assembled from
1140
+ * that declaration (`plane: "hosted"` mounts the hosted face over the declared action subset,
1141
+ * `plane: "local-stub"` — `localArtifactStub({ dir })` — mounts the publish-only local face with
1142
+ * `eval-stub://` links); a host whose declaration fails an invariant ⇒ no tool and a loud
1143
+ * `config.artifact_host_invalid` notice. Filling the seat IS the authorization to publish: there is
1144
+ * no second switch. `TaskSpec.excludeTools` unmounts the tool as it does any other.
1145
+ */
1146
+ artifactHost?: import("./artifact-host.js").ArtifactHost;
1159
1147
  /**
1160
1148
  * Default in-process hooks for all tasks (design/37) — the FULL lifecycle seam of the `Hooks`
1161
1149
  * interface, not just the tool-call trio: `preToolUse` (rewrite/restrict args + inject context),
@@ -1309,27 +1297,20 @@ export interface RunnerDeps {
1309
1297
  */
1310
1298
  toolResultThresholdChars?: number;
1311
1299
  /**
1312
- * design/374 — microCompact machine-alignment knobs. Since the slice-3 default flip BOTH knobs
1313
- * default ON (`machine: "cc"`, `clearOnRejection: true`); the pre-374 behavior is the explicit
1314
- * opt-out `{ machine: "legacy", clearOnRejection: false }`.
1300
+ * design/374 — the microCompact knobs. Both default ON (`machine: "cc"`, `clearOnRejection: true`).
1315
1301
  *
1316
- * - `machine`: which stale-tool-result clearing machine the request pipeline runs —
1317
- * `"cc"` (default: the CC 2.1.223 rejection-leg form — keep 5, ≥20k minimum-savings gate, one
1318
- * deep clear beyond the keep window, CC marker bytes), `"legacy"` (the historical keep-3 /
1319
- * clear-to-budget machine, kept as the compatibility opt-out; it also keeps the pre-374
1320
- * backstop order guard trim as the ordinary second line), or `"off"` (no proactive frontier
1321
- * clearing at all the D-2 off switch; the unified machine then gets its ONE shot at the
1322
- * blocking point instead, the slice-3 arm A, trace trigger `"blocking"`). The pre-flip P-form
1323
- * warning on {@link import("./context-edit.js").ContextEditMachine} is resolved: the slice-3
1324
- * fallback re-ordering shipped with this default (blocking-point re-run → in-turn forced
1325
- * compaction behind the adopt seam → trim demoted to the disaster-only last resort), so an
1326
- * under-20k refusal no longer falls straight into a message-dropping trim.
1302
+ * - `machine`: `"cc"` (default: the CC 2.1.223 rejection-leg form keep 5, ≥20k minimum-savings
1303
+ * gate, one deep clear beyond the keep window, CC marker bytes) or `"off"` (no proactive
1304
+ * frontier clearing at all — the D-2 off switch; the machine then gets its ONE shot at the
1305
+ * blocking point instead, the slice-3 arm A, trace trigger `"blocking"`). The vocabulary is
1306
+ * {@link import("./context-edit.js").MICRO_COMPACT_MACHINES}; the guard chain behind either
1307
+ * value is the same (blocking-point run in-turn forced compaction behind the adopt seam
1308
+ * trim demoted to the disaster-only last resort), so an under-20k refusal never falls straight
1309
+ * into a message-dropping trim.
1327
1310
  * - `clearOnRejection` (MC-R, slice 2): on a provider input-too-long rejection, run ONE cheap
1328
- * deterministic clear over the rejected projection (same cc machine, savings ≥20k or nothing)
1329
- * and retry inside the turn BEFORE the forced-compaction recovery. Default true (flipped with
1330
- * the machine default in slice 3; X2's dark-landing clause is spent). Independent of
1331
- * `machine` — an enabled MC-R always clears in the cc form (the rejection arm has no
1332
- * budget coordinate for the legacy incremental form to stop at). BUDGET ACCOUNTING (design/374
1311
+ * deterministic clear over the rejected projection (the same machine, savings ≥20k or nothing)
1312
+ * and retry inside the turn BEFORE the forced-compaction recovery. Default true. Independent of
1313
+ * `machine` an enabled MC-R clears even with the frontier pass `"off"`. BUDGET ACCOUNTING (design/374
1333
1314
  * §3.2.1, stated here because it is otherwise invisible to a deployment): a successful MC-R
1334
1315
  * clear-and-retry SPENDS one attempt of the shared prompt-too-long recovery budget (default 2
1335
1316
  * attempts per chain), so a chain that clears and is rejected AGAIN has one forced-compaction
@@ -1344,7 +1325,7 @@ export interface RunnerDeps {
1344
1325
  * effect.
1345
1326
  */
1346
1327
  microCompact?: {
1347
- machine?: "off" | "legacy" | "cc";
1328
+ machine?: import("./context-edit.js").MicroCompactMachine;
1348
1329
  clearOnRejection?: boolean;
1349
1330
  };
1350
1331
  /**
@@ -1,5 +1,5 @@
1
1
  /**
2
- * RB-463 — host-callback isolation, one primitive.
2
+ * Host-callback isolation, one primitive.
3
3
  *
4
4
  * The invariant "a callback the HOST handed us must never take the engine down" was implemented by hand at
5
5
  * ~20 sites across 10 modules (observer taps, cascade/verify observability hooks, roster eviction sinks, the
@@ -60,7 +60,7 @@ export declare function dataRootSpellings(explicit: string | undefined): string[
60
60
  * `env` is the same ExecutionEnv the hands run against (inject the one you pass to the Runner), so
61
61
  * canonicalization sees the task's real filesystem (a remote/E2B task resolves in its container).
62
62
  * `rootPath` is the FALLBACK base a relative path resolves against (omit = paths resolve as given).
63
- * RB-108: when the engine stamps a live cwd onto the request (`ToolCallRequest.cwd` — the tracked
63
+ * When the engine stamps a live cwd onto the request (`ToolCallRequest.cwd` — the tracked
64
64
  * directory the shell's `cd` moves and the fs tools resolve with), THAT wins for the call's target, so
65
65
  * the guard judges the file the tool will actually write. `rootPath` still serves every deployment that
66
66
  * calls this policy outside a Runner.
@@ -1,6 +1,6 @@
1
1
  import { homedir } from "node:os";
2
2
  import { isAbsolute, join, resolve } from "node:path";
3
- import { canonicalizeTarget, expandHomeTilde, isAbsolutePathForm, isWinFormPath, writeTargetPath } from "../tools/fs/safety.js";
3
+ import { canonicalizeTarget, expandHomeTilde, isAbsoluteForFamily, isWinFormPath, pathFamilyOf, writeTargetPath } from "../tools/fs/safety.js";
4
4
  import { compileSegmentPattern, matchSegmentPatterns } from "../tools/fs/read-deny.js";
5
5
  import { isProtectedWrite, protectivePathTargetOf } from "./tool-registry.js";
6
6
  import { pathTargetBaseOf } from "./effective-path-target.js";
@@ -40,7 +40,7 @@ export function dataRootSpellings(explicit) {
40
40
  const engineForm = isAbsolute(raw) ? raw : resolve(raw);
41
41
  const out = [];
42
42
  for (const v of [raw, tilde, engineForm]) {
43
- const anchored = isAbsolutePathForm(v) ? v : resolve(v);
43
+ const anchored = isAbsoluteForFamily(pathFamilyOf({ root: v }), v) ? v : resolve(v);
44
44
  if (!out.includes(anchored))
45
45
  out.push(anchored);
46
46
  }
@@ -82,7 +82,7 @@ export function createSensitivePathPolicy(opts) {
82
82
  const keys = [];
83
83
  for (const spelling of dataRootPaths) {
84
84
  try {
85
- const r = await canonicalizeTarget(opts.env, spelling, signal);
85
+ const r = await canonicalizeTarget(opts.env, spelling, signal, pathFamilyOf({ root: spelling }));
86
86
  if (r.ok && !keys.includes(r.key))
87
87
  keys.push(r.key);
88
88
  }
@@ -102,16 +102,15 @@ export function createSensitivePathPolicy(opts) {
102
102
  const path = writeTargetPath(req, protective);
103
103
  if (typeof path !== "string" || path.length === 0)
104
104
  return { action: "allow" };
105
- const canon = await canonicalizeTarget(opts.env, path, signal, pathTargetBaseOf(protective, { root: opts.rootPath, cwd: req.cwd }));
105
+ const canon = await canonicalizeTarget(opts.env, path, signal, pathFamilyOf({ root: opts.rootPath, cwd: req.cwd ?? opts.env.cwd }), pathTargetBaseOf(protective, { root: opts.rootPath, cwd: req.cwd }));
106
106
  if (!canon.ok) {
107
- if (canon.unresolvedSymlink) {
108
- return {
109
- action: "deny",
110
- message: `write to "${path}" is blocked: it is a symlink whose real target could not be resolved (it could point onto a guarded sensitive path)`,
111
- decisionReason: "safety",
112
- };
113
- }
114
- return { action: "allow" };
107
+ return {
108
+ action: "deny",
109
+ message: canon.unresolvedSymlink
110
+ ? `write to "${path}" is blocked: it is a symlink whose real target could not be resolved (it could point onto a guarded sensitive path)`
111
+ : `write to "${path}" is blocked: its target could not be resolved on this tree (${canon.refused ?? canon.message}), so the sensitive-path guard cannot judge it`,
112
+ decisionReason: "safety",
113
+ };
115
114
  }
116
115
  let relative = null;
117
116
  for (const rootKey of await dataRootKeys(signal)) {
@@ -74,7 +74,7 @@ export interface SessionStoreSummary {
74
74
  * Absent until a task has run on the session (recorded via {@link SessionStore.noteTaskRun}). */
75
75
  lastTaskId?: string;
76
76
  /**
77
- * #499 — an ENGINE-minted run identity for this session ({@link import("./types.js").TaskResult.runId}),
77
+ * An ENGINE-minted run identity for this session ({@link import("./types.js").TaskResult.runId}),
78
78
  * recorded by the most recent {@link SessionStore.noteTaskRun} write to LAND.
79
79
  * {@link lastTaskId} above is `spec.taskId ?? sessionId`, so on the ordinary deployment that supplies no
80
80
  * host task id it answers the SESSION's own id: a "last run" handle that names the session it hangs off
@@ -317,7 +317,7 @@ export declare function boundedTail(pathEntries: readonly SessionTreeEntry[]): {
317
317
  * times in one prepare (project-memory phase, design/148 center adoption, the epoch-pin
318
318
  * discriminator), and an entry-COUNT proxy at ANY of them re-creates the same lie: a host may write
319
319
  * session_info / model_change / … rows before the first turn (naming a new chat, recording a model
320
- * pick), and none of that is evidence of a prior session (5.29 merge-rescan: the count proxy
320
+ * pick), and none of that is evidence of a prior session (the count proxy
321
321
  * survived at the adoption arm after the pin arm was fixed, silently costing a pre-named session
322
322
  * its published center prompt for life). Conversation content — and only that — is the evidence.
323
323
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * RB-428-B — pattern specifiers inside a {@link import("./types.js").SkillManifest}'s `allowTools`.
2
+ * Pattern specifiers inside a {@link import("./types.js").SkillManifest}'s `allowTools`.
3
3
  *
4
4
  * An entry may be a bare tool name (`Bash`) or a name carrying a specifier (`Bash(git:*)`). A bare name
5
5
  * claims the whole tool; a specifier claims a NARROWER slice of it. Both directions of that sentence are
@@ -42,7 +42,7 @@ export type SkillsDirectoryWarningCode =
42
42
  | "name_mismatch"
43
43
  /** Required `description` absent. */
44
44
  | "missing_description"
45
- /** RB-428-A: an `allowed-tools` entry carries a pattern specifier (`Bash(git:*)`) — the scope policy
45
+ /** An `allowed-tools` entry carries a pattern specifier (`Bash(git:*)`) — the scope policy
46
46
  * matches names, not patterns, so the entry cannot match and the tool is DISABLED in this skill
47
47
  * frame. Disclosed loudly until pattern enforcement lands (the entry is deliberately NOT widened to
48
48
  * its base name: that would turn "only git" into "all of Bash"). */
@@ -1,5 +1,6 @@
1
- import { readFileSync, readdirSync, realpathSync, statSync } from "node:fs";
1
+ import { readFileSync, readdirSync, statSync } from "node:fs";
2
2
  import { isAbsolute, join, relative } from "node:path";
3
+ import { physicalPathOf } from "./physical-path.js";
3
4
  import { isSkillSpecifierEnforced, parseSkillToolEntry } from "./skill-tool-specifier.js";
4
5
  const SKILL_FILE = "SKILL.md";
5
6
  const RESOURCE_DIRS = ["assets", "references", "scripts"];
@@ -200,7 +201,7 @@ function resolveInsideSkill(abs, rel, walk) {
200
201
  let real;
201
202
  let stats;
202
203
  try {
203
- real = realpathSync(abs);
204
+ real = physicalPathOf(abs);
204
205
  stats = statSync(abs);
205
206
  }
206
207
  catch (err) {
@@ -220,7 +221,7 @@ function resolveInsideSkill(abs, rel, walk) {
220
221
  function readAttachments(skillDir, skillName, budgetBytes, warn) {
221
222
  let realRoot;
222
223
  try {
223
- realRoot = realpathSync(skillDir);
224
+ realRoot = physicalPathOf(skillDir);
224
225
  }
225
226
  catch (err) {
226
227
  warn({ code: "read_failed", skill: skillName, detail: `the skill directory could not be resolved (${errText(err)}) — attachments skipped` });
@@ -1,7 +1,8 @@
1
1
  import { execFile } from "node:child_process";
2
2
  import { randomBytes } from "node:crypto";
3
- import { lstatSync, readFileSync, realpathSync, renameSync, rmSync, writeFileSync } from "node:fs";
3
+ import { lstatSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
4
4
  import { dirname, isAbsolute, resolve, sep } from "node:path";
5
+ import { physicalPathOf } from "./physical-path.js";
5
6
  const DEFAULT_GATE_TIMEOUT_MS = 60_000;
6
7
  const GATE_MAX_BUFFER = 16 * 1024 * 1024;
7
8
  const OUTPUT_TAIL_CHARS = 1500;
@@ -139,8 +140,8 @@ export async function runOracle(gates, cwdRoot, opts) {
139
140
  continue;
140
141
  }
141
142
  try {
142
- const physRoot = realpathSync(root);
143
- const phys = realpathSync(candidate);
143
+ const physRoot = physicalPathOf(root);
144
+ const phys = physicalPathOf(candidate);
144
145
  if (phys !== physRoot && !phys.startsWith(physRoot + sep)) {
145
146
  results.push(err(gate, `gate cwd physically escapes the spec root (symlink): ${gate.cwd}`));
146
147
  continue;
@@ -247,7 +248,7 @@ function restoreOneAtomic(p, bytes) {
247
248
  }
248
249
  function safeRealpath(p) {
249
250
  try {
250
- return realpathSync(p);
251
+ return physicalPathOf(p);
251
252
  }
252
253
  catch {
253
254
  return undefined;
@@ -185,7 +185,7 @@ export async function checkpointStoreContract(make, runAssertion) {
185
185
  assert.equal(q[0].text, "go");
186
186
  assert.equal(q[0].trusted, false);
187
187
  assert.equal(q[0].seq, 1);
188
- assert.equal((await store.get(cp.token)).state.pendingSteer, undefined);
188
+ assert.equal("pendingSteer" in (await store.get(cp.token)).state, false);
189
189
  });
190
190
  run("setPendingSteer APPENDS: two steers both survive in issue order, each keeping its frozen trust", async () => {
191
191
  const store = make();
@@ -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". */