@sema-agent/core 5.19.0 → 5.21.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 (329) hide show
  1. package/CHANGELOG.md +102 -4
  2. package/dist/agents/agent-definition.d.ts +7 -0
  3. package/dist/agents/agent-transcript-tool.d.ts +30 -0
  4. package/dist/agents/builtin-agents.d.ts +60 -0
  5. package/dist/agents/cascade.d.ts +107 -0
  6. package/dist/agents/cumulative-stats.d.ts +56 -0
  7. package/dist/agents/observer.d.ts +162 -0
  8. package/dist/agents/peer-admission.d.ts +95 -0
  9. package/dist/agents/repair-loop.d.ts +226 -0
  10. package/dist/agents/retain-ledger.d.ts +141 -0
  11. package/dist/agents/roster-store.d.ts +105 -0
  12. package/dist/agents/roster-store.js +3 -0
  13. package/dist/agents/send-message-tool.d.ts +92 -0
  14. package/dist/agents/session-util.d.ts +5 -0
  15. package/dist/agents/subagent-steps.d.ts +66 -0
  16. package/dist/agents/subagent.d.ts +600 -0
  17. package/dist/agents/suspend-guard.d.ts +29 -0
  18. package/dist/agents/teacher.d.ts +75 -0
  19. package/dist/agents/team.d.ts +120 -1
  20. package/dist/agents/tool-filter.d.ts +34 -0
  21. package/dist/agents/verify.d.ts +198 -0
  22. package/dist/bench/metrics.d.ts +455 -0
  23. package/dist/brain/anthropic.d.ts +30 -0
  24. package/dist/brain/circuit-breaker.d.ts +33 -0
  25. package/dist/brain/circuit-breaker.js +14 -3
  26. package/dist/brain/context-overflow.d.ts +60 -3
  27. package/dist/brain/degrading.d.ts +67 -0
  28. package/dist/brain/errors.d.ts +42 -0
  29. package/dist/brain/failover.d.ts +15 -0
  30. package/dist/brain/media-degrade.d.ts +39 -0
  31. package/dist/brain/model-presets.d.ts +31 -0
  32. package/dist/brain/open-responses.d.ts +19 -0
  33. package/dist/brain/openai.d.ts +46 -0
  34. package/dist/brain/reasoning.d.ts +106 -1
  35. package/dist/brain/repetition.d.ts +83 -0
  36. package/dist/brain/request-params.d.ts +56 -0
  37. package/dist/brain/retry.d.ts +46 -0
  38. package/dist/brain/routing.d.ts +12 -0
  39. package/dist/brain/status-sink.d.ts +30 -1
  40. package/dist/brain/stream-engine.d.ts +147 -0
  41. package/dist/brain/stream-shared.d.ts +34 -0
  42. package/dist/brain/terminal-cause.d.ts +31 -0
  43. package/dist/brain/timeout.d.ts +108 -0
  44. package/dist/brain/timeout.js +11 -0
  45. package/dist/brain/tool-call-id.d.ts +20 -0
  46. package/dist/brain/tool-call-repair.d.ts +13 -0
  47. package/dist/config/catalog.d.ts +47 -0
  48. package/dist/config/defaults.d.ts +33 -0
  49. package/dist/core/a2a-task-state.d.ts +53 -0
  50. package/dist/core/a2a.d.ts +51 -0
  51. package/dist/core/arg-summary.d.ts +62 -0
  52. package/dist/core/ask-question.d.ts +272 -2
  53. package/dist/core/auto-compaction.d.ts +467 -0
  54. package/dist/core/auto-compaction.js +20 -6
  55. package/dist/core/auto-mode-prompt-assets.d.ts +8 -0
  56. package/dist/core/auto-mode-prompt.d.ts +27 -0
  57. package/dist/core/auto-mode.d.ts +54 -3
  58. package/dist/core/auto-promote.d.ts +100 -0
  59. package/dist/core/background-agent-store.d.ts +293 -0
  60. package/dist/core/background-agent-store.js +5 -0
  61. package/dist/core/background-shell.d.ts +110 -0
  62. package/dist/core/cache-break-detector.d.ts +34 -0
  63. package/dist/core/canonical-json.d.ts +57 -0
  64. package/dist/core/checkpoint-store.d.ts +1574 -16
  65. package/dist/core/compliance.d.ts +30 -0
  66. package/dist/core/consolidate-scope.d.ts +75 -0
  67. package/dist/core/context-edit.d.ts +99 -0
  68. package/dist/core/context-guard.d.ts +46 -0
  69. package/dist/core/exec-gate.d.ts +44 -0
  70. package/dist/core/exec-output-tail.d.ts +61 -0
  71. package/dist/core/file-snapshot-store.d.ts +104 -0
  72. package/dist/core/fs-write-gate-policy.d.ts +36 -0
  73. package/dist/core/git-worktree-env.d.ts +31 -0
  74. package/dist/core/governance-codes.d.ts +19 -0
  75. package/dist/core/hooks.d.ts +609 -1
  76. package/dist/core/human-input-projection.d.ts +37 -0
  77. package/dist/core/human-input-projection.js +13 -0
  78. package/dist/core/image-downsample.d.ts +74 -0
  79. package/dist/core/locked-config.d.ts +37 -0
  80. package/dist/core/lsp-diagnostics.d.ts +77 -0
  81. package/dist/core/lsp-protocol.d.ts +29 -0
  82. package/dist/core/lsp-session.d.ts +60 -1
  83. package/dist/core/lsp.d.ts +150 -1
  84. package/dist/core/mailbox-store.d.ts +57 -0
  85. package/dist/core/mailbox-store.js +2 -0
  86. package/dist/core/mcp.d.ts +385 -0
  87. package/dist/core/mcp.js +58 -11
  88. package/dist/core/media-byte-cap.d.ts +21 -0
  89. package/dist/core/memory-admission.d.ts +71 -0
  90. package/dist/core/memory-engine/content-origin.d.ts +64 -0
  91. package/dist/core/memory-engine/data-plane.d.ts +43 -0
  92. package/dist/core/memory-engine/dual-root.d.ts +24 -0
  93. package/dist/core/memory-engine/engine.d.ts +230 -0
  94. package/dist/core/memory-engine/engine.js +103 -35
  95. package/dist/core/memory-engine/file-backend.d.ts +155 -0
  96. package/dist/core/memory-engine/frontmatter.d.ts +16 -0
  97. package/dist/core/memory-engine/layout.d.ts +217 -0
  98. package/dist/core/memory-engine/memory-backend-contract.d.ts +12 -0
  99. package/dist/core/memory-engine/migrate.d.ts +9 -0
  100. package/dist/core/memory-engine/scan.d.ts +12 -0
  101. package/dist/core/memory-engine/scope-contract.d.ts +61 -1
  102. package/dist/core/memory-engine/sync-client.d.ts +87 -0
  103. package/dist/core/memory-engine/sync.d.ts +60 -0
  104. package/dist/core/memory-engine/tools.d.ts +41 -0
  105. package/dist/core/memory-engine/types.d.ts +188 -0
  106. package/dist/core/memory-recall.d.ts +141 -0
  107. package/dist/core/memory-vector.d.ts +20 -0
  108. package/dist/core/memory.d.ts +458 -0
  109. package/dist/core/message-utils.d.ts +6 -0
  110. package/dist/core/oracle-isolation.d.ts +69 -0
  111. package/dist/core/permission-rule-consent.d.ts +138 -0
  112. package/dist/core/permission-rule-model.d.ts +122 -0
  113. package/dist/core/permission-rule-store.d.ts +119 -3
  114. package/dist/core/permission-rules.d.ts +87 -1
  115. package/dist/core/present-plan-tool.d.ts +20 -0
  116. package/dist/core/pricing.d.ts +26 -0
  117. package/dist/core/property-harness.d.ts +86 -0
  118. package/dist/core/protocol-naming.d.ts +38 -0
  119. package/dist/core/protocol-table.d.ts +61 -0
  120. package/dist/core/push-queue.d.ts +1 -0
  121. package/dist/core/remote-env.d.ts +383 -1
  122. package/dist/core/retention-policy.d.ts +40 -0
  123. package/dist/core/retention-policy.js +21 -0
  124. package/dist/core/retention.d.ts +51 -0
  125. package/dist/core/roles.d.ts +59 -0
  126. package/dist/core/runner/active-skill-scope.d.ts +34 -0
  127. package/dist/core/runner/assemble-result.d.ts +134 -0
  128. package/dist/core/runner/compaction-call-options.d.ts +97 -1
  129. package/dist/core/runner/grounding-signal.d.ts +10 -0
  130. package/dist/core/runner/image.d.ts +17 -0
  131. package/dist/core/runner/image.js +29 -15
  132. package/dist/core/runner/memory-consolidation.d.ts +60 -0
  133. package/dist/core/runner/prepare-memory.d.ts +59 -0
  134. package/dist/core/runner/prepare-task.d.ts +1011 -2
  135. package/dist/core/runner/prepare-task.js +51 -14
  136. package/dist/core/runner/prompt-suggestions.d.ts +7 -0
  137. package/dist/core/runner/runtask.d.ts +304 -3
  138. package/dist/core/runner/runtask.js +17 -2
  139. package/dist/core/runner/session-file-state-replay.d.ts +49 -0
  140. package/dist/core/runner/session-rule-policy.d.ts +58 -0
  141. package/dist/core/runner/strict-output-schema.d.ts +18 -3
  142. package/dist/core/runner/synthetic-tools.d.ts +113 -0
  143. package/dist/core/runner/teardown-bounded.d.ts +34 -0
  144. package/dist/core/runner/tool-disclosure.d.ts +227 -0
  145. package/dist/core/runner/tool-output-projection.d.ts +6 -0
  146. package/dist/core/runner/turn-attachments.d.ts +634 -0
  147. package/dist/core/runner/usage-accounting.d.ts +32 -0
  148. package/dist/core/runtime.d.ts +9 -0
  149. package/dist/core/safe-notify.d.ts +64 -0
  150. package/dist/core/safety-axis-vocab.d.ts +23 -0
  151. package/dist/core/safety-merge-corpus.d.ts +37 -0
  152. package/dist/core/scheduler.d.ts +121 -0
  153. package/dist/core/secret-env.d.ts +32 -0
  154. package/dist/core/select-model.d.ts +15 -0
  155. package/dist/core/sensitive-path-policy.d.ts +42 -0
  156. package/dist/core/session-policy-store.d.ts +94 -0
  157. package/dist/core/session-reconcile.d.ts +80 -0
  158. package/dist/core/session-store.d.ts +85 -0
  159. package/dist/core/session.d.ts +153 -0
  160. package/dist/core/shared-memory/contract.d.ts +22 -0
  161. package/dist/core/shared-memory/normalize.d.ts +123 -2
  162. package/dist/core/shared-memory/tools.d.ts +14 -0
  163. package/dist/core/shared-memory/types.d.ts +105 -0
  164. package/dist/core/shutdown-debug.d.ts +6 -0
  165. package/dist/core/side-query.d.ts +38 -0
  166. package/dist/core/side-query.js +6 -1
  167. package/dist/core/skill-tool-specifier.d.ts +72 -0
  168. package/dist/core/skills-directory.d.ts +100 -1
  169. package/dist/core/spec-contract.d.ts +89 -0
  170. package/dist/core/store-contracts/background-agent-store-contract.d.ts +31 -0
  171. package/dist/core/store-contracts/checkpoint-store-contract.d.ts +26 -0
  172. package/dist/core/store-contracts/contract-harness.d.ts +20 -0
  173. package/dist/core/store-contracts/contract-kit-version.d.ts +27 -0
  174. package/dist/core/store-contracts/file-snapshot-store-contract.d.ts +8 -0
  175. package/dist/core/store-contracts/mailbox-store-contract.d.ts +42 -0
  176. package/dist/core/store-contracts/tool-result-store-contract.d.ts +13 -0
  177. package/dist/core/strategy-store.d.ts +37 -0
  178. package/dist/core/stub-env.d.ts +7 -0
  179. package/dist/core/surrogate-safe-slice.d.ts +35 -0
  180. package/dist/core/task-notification.d.ts +202 -0
  181. package/dist/core/task-outcome.d.ts +53 -0
  182. package/dist/core/task-registry-agent.d.ts +337 -1
  183. package/dist/core/task-registry-agent.js +2 -0
  184. package/dist/core/task-registry-monitor.d.ts +12 -0
  185. package/dist/core/task-registry-shared.d.ts +540 -0
  186. package/dist/core/task-registry.d.ts +343 -0
  187. package/dist/core/task-registry.js +13 -2
  188. package/dist/core/task-tool-shape.d.ts +44 -0
  189. package/dist/core/tighten-task-spec.d.ts +21 -0
  190. package/dist/core/tool-detach.d.ts +21 -0
  191. package/dist/core/tool-errors.d.ts +131 -0
  192. package/dist/core/tool-errors.js +4 -0
  193. package/dist/core/tool-name-aliases.d.ts +27 -0
  194. package/dist/core/tool-policy.d.ts +555 -0
  195. package/dist/core/tool-policy.js +3 -0
  196. package/dist/core/tool-result-budget.d.ts +32 -0
  197. package/dist/core/tool-result-store.d.ts +174 -1
  198. package/dist/core/tools.d.ts +45 -0
  199. package/dist/core/trace.d.ts +323 -0
  200. package/dist/core/types.d.ts +3859 -2
  201. package/dist/core/untrusted-egress.d.ts +8 -0
  202. package/dist/core/untrusted-text.d.ts +156 -0
  203. package/dist/core/usage-window-store.d.ts +95 -0
  204. package/dist/core/version.d.ts +1 -0
  205. package/dist/core/warm-resume.d.ts +17 -0
  206. package/dist/core/wiring-manifest.d.ts +169 -0
  207. package/dist/core/with-retry.d.ts +24 -0
  208. package/dist/core/workflow-journal-store.d.ts +160 -0
  209. package/dist/core/workflow-run-store-contract.d.ts +25 -0
  210. package/dist/core/workflow-run-store.d.ts +119 -0
  211. package/dist/core/workflow-run-store.js +2 -0
  212. package/dist/engine/compaction/compaction.d.ts +256 -1
  213. package/dist/engine/compaction/utils.d.ts +94 -0
  214. package/dist/engine/execution-env/kill-tree.d.ts +29 -0
  215. package/dist/engine/execution-env/node-execution-env.d.ts +94 -0
  216. package/dist/engine/harness/agent-harness.d.ts +116 -0
  217. package/dist/engine/harness/agent-harness.js +3 -14
  218. package/dist/engine/harness/messages.d.ts +15 -0
  219. package/dist/engine/harness/types.d.ts +464 -2
  220. package/dist/engine/llm/diagnostics.d.ts +4 -0
  221. package/dist/engine/llm/event-stream.d.ts +3 -0
  222. package/dist/engine/llm/index.d.ts +7 -0
  223. package/dist/engine/llm/types.d.ts +500 -3
  224. package/dist/engine/llm/validation.d.ts +3 -0
  225. package/dist/engine/loop/agent-loop.d.ts +87 -2
  226. package/dist/engine/loop/runtime-deps.d.ts +7 -0
  227. package/dist/engine/loop/types.d.ts +424 -0
  228. package/dist/engine/lsp/frame-decoder.d.ts +13 -0
  229. package/dist/engine/lsp/node-lsp-manager.d.ts +107 -0
  230. package/dist/engine/lsp/stdio-lsp-transport.d.ts +7 -0
  231. package/dist/engine/session/import-validate.d.ts +27 -0
  232. package/dist/engine/session/log-digest.d.ts +93 -0
  233. package/dist/engine/session/memory-repo.d.ts +6 -0
  234. package/dist/engine/session/memory-storage.d.ts +2 -0
  235. package/dist/engine/session/session.d.ts +75 -0
  236. package/dist/engine/session/storage-base.d.ts +8 -0
  237. package/dist/fixtures/index.d.ts +36 -0
  238. package/dist/index.d.ts +17 -2
  239. package/dist/index.js +1 -2
  240. package/dist/internal/harness-types.d.ts +6 -0
  241. package/dist/internal/harness.d.ts +11 -0
  242. package/dist/internal/llm.d.ts +6 -0
  243. package/dist/orchestration/builtin-workflows.d.ts +53 -0
  244. package/dist/orchestration/dev-vm-script-runner.d.ts +19 -0
  245. package/dist/orchestration/goal.d.ts +57 -0
  246. package/dist/orchestration/goal.js +3 -0
  247. package/dist/orchestration/run-spec.d.ts +42 -0
  248. package/dist/orchestration/run-spec.js +4 -0
  249. package/dist/orchestration/run-workflow-tool.d.ts +169 -0
  250. package/dist/orchestration/workflow-governance.d.ts +61 -0
  251. package/dist/orchestration/workflow-meta.d.ts +28 -0
  252. package/dist/orchestration/workflow-observe.d.ts +60 -0
  253. package/dist/orchestration/workflow-primitives.d.ts +23 -1
  254. package/dist/orchestration/workflow-sandbox-conformance.d.ts +38 -0
  255. package/dist/orchestration/workflow-script-runner.d.ts +88 -0
  256. package/dist/orchestration/workflow-script-store.d.ts +98 -0
  257. package/dist/orchestration/workflow-size-guideline.d.ts +67 -0
  258. package/dist/orchestration/workflow-types.d.ts +169 -2
  259. package/dist/orchestration/workflow.d.ts +358 -0
  260. package/dist/orchestration/workflow.js +13 -2
  261. package/dist/prompt-assembly/artifact-store.d.ts +33 -0
  262. package/dist/prompt-assembly/artifact.d.ts +25 -0
  263. package/dist/prompt-assembly/assemble.d.ts +20 -0
  264. package/dist/prompt-assembly/composer.d.ts +29 -0
  265. package/dist/prompt-assembly/epoch.d.ts +55 -1
  266. package/dist/prompt-assembly/event-registry.d.ts +35 -0
  267. package/dist/prompt-assembly/explain.d.ts +12 -0
  268. package/dist/prompt-assembly/tool-catalog.d.ts +38 -0
  269. package/dist/prompt-assembly/turn-snapshot.d.ts +40 -0
  270. package/dist/prompt-assembly/types.d.ts +115 -0
  271. package/dist/prompts/coordinator.d.ts +27 -0
  272. package/dist/prompts/default.d.ts +539 -0
  273. package/dist/prompts/simple-sections.d.ts +45 -0
  274. package/dist/prompts/supervisor.d.ts +66 -0
  275. package/dist/scenarios/env.d.ts +28 -0
  276. package/dist/scenarios/full-body.d.ts +50 -0
  277. package/dist/scenarios/scenario-registry.d.ts +60 -0
  278. package/dist/scenarios/teacher-quickstart.d.ts +27 -0
  279. package/dist/server/http.d.ts +17 -0
  280. package/dist/stores/cc/lockfile.d.ts +6 -0
  281. package/dist/stores/cc/mailbox-store.d.ts +8 -0
  282. package/dist/stores/cc/roster-adapter.d.ts +4 -0
  283. package/dist/stores/cc/sidecar-transcript.d.ts +66 -0
  284. package/dist/stores/file/background-agent-store.d.ts +24 -0
  285. package/dist/stores/file/background-agent-store.js +2 -1
  286. package/dist/stores/file/checkpoint-store.d.ts +38 -0
  287. package/dist/stores/file/file-snapshot-store.d.ts +25 -0
  288. package/dist/stores/file/fs-atomic.d.ts +155 -0
  289. package/dist/stores/file/index.d.ts +89 -0
  290. package/dist/stores/file/mailbox-store.d.ts +36 -0
  291. package/dist/stores/file/mailbox-store.js +2 -0
  292. package/dist/stores/file/memory-store.d.ts +82 -0
  293. package/dist/stores/file/permission-rule-store.d.ts +79 -0
  294. package/dist/stores/file/session-policy-store.d.ts +28 -0
  295. package/dist/stores/file/session-store.d.ts +40 -0
  296. package/dist/stores/file/shared-ledger.d.ts +83 -0
  297. package/dist/stores/file/tool-result-store.d.ts +11 -0
  298. package/dist/stores/file/usage-window-store.d.ts +18 -0
  299. package/dist/stores/file/workflow-journal-store.d.ts +100 -0
  300. package/dist/stores/file/workflow-run-store.d.ts +11 -0
  301. package/dist/stores/file/workflow-run-store.js +2 -0
  302. package/dist/tools/fs/bash-readonly-classifier.d.ts +282 -0
  303. package/dist/tools/fs/encoding.d.ts +60 -0
  304. package/dist/tools/fs/fs-bash.d.ts +133 -0
  305. package/dist/tools/fs/fs-pdf.d.ts +28 -0
  306. package/dist/tools/fs/fs-search-tools.d.ts +5 -0
  307. package/dist/tools/fs/fs-shared.d.ts +360 -0
  308. package/dist/tools/fs/fs-write.d.ts +16 -0
  309. package/dist/tools/fs/gh-rate-limit.d.ts +22 -0
  310. package/dist/tools/fs/index.d.ts +79 -0
  311. package/dist/tools/fs/notebook.d.ts +56 -0
  312. package/dist/tools/fs/pdf.d.ts +70 -0
  313. package/dist/tools/fs/pdf.js +8 -2
  314. package/dist/tools/fs/repo-map.d.ts +10 -0
  315. package/dist/tools/fs/safety.d.ts +376 -0
  316. package/dist/tools/fs/search.d.ts +131 -0
  317. package/dist/tools/loop-tick.d.ts +24 -0
  318. package/dist/tools/monitor.d.ts +55 -0
  319. package/dist/tools/scheduler-tools.d.ts +51 -0
  320. package/dist/tools/sql-adapters.d.ts +18 -0
  321. package/dist/tools/sql.d.ts +25 -0
  322. package/dist/tools/task-list.d.ts +77 -0
  323. package/dist/tools/todo.d.ts +8 -0
  324. package/dist/tools/web.d.ts +184 -0
  325. package/dist/tools/web.js +32 -5
  326. package/dist/tools/worktree.d.ts +81 -0
  327. package/package.json +2 -2
  328. package/dist/tools/gitea-issue.d.ts +0 -13
  329. package/dist/tools/gitea-issue.js +0 -75
@@ -1,4 +1,5 @@
1
1
  import type { SubagentEditedFile, SubagentStep } from "../agents/subagent-steps.js";
2
+ /** Terminal/live usage rollup persisted on the row (mirror of the task_notification/BCE fields). */
2
3
  export interface BackgroundAgentUsage {
3
4
  totalTokens?: number;
4
5
  toolUses?: number;
@@ -7,36 +8,120 @@ export interface BackgroundAgentUsage {
7
8
  turns?: number;
8
9
  costMicroUsd?: number;
9
10
  }
11
+ /**
12
+ * One durable background-agent execution row. Field discipline (design/151 §3.1, HIGH-4): revival
13
+ * re-hydration data is LOOKUP KEYS ONLY (`agentType`/`model`/`teamName`/`name` — the CC 2.1.216
14
+ * `.meta.json` sidecar shape) — never a serialized spec and never closures; a tier-3 revival rebuilds
15
+ * the spec the same way a fresh named-teammate spawn would (roster/agent definition + the reviver's
16
+ * deployment assembly).
17
+ */
10
18
  export interface BackgroundAgentRecord {
19
+ /** Row key: the registry handle (`a…` domain), stable across restarts. */
11
20
  handle: string;
21
+ /** Tenant/principal scope — put-time REQUIRED (assertOwnership parity: a row with neither a real
22
+ * scope nor an owner would be world-readable through the fallback; the registry writer always has
23
+ * both). */
12
24
  scope: string;
25
+ /** task-scoped: the host taskId · session-scoped: the sessionId (registry owner semantics). */
13
26
  owner: string;
14
27
  sessionScoped: boolean;
28
+ /** The child's store session id — the transcript / resume anchor. Absent at put (the child session
29
+ * is minted AFTER registration); bound via a follow-up CAS update. */
15
30
  sessionId?: string;
31
+ /** Spawn-time root linkage ([1371]② semantics) — the durable enumeration key for task-scoped rows
32
+ * ({@link BackgroundAgentStore.listBySession}) and the restart read leg of the access predicate. */
16
33
  parentSessionId?: string;
34
+ /** δ 批 [1498]⑦ — the ROOT host session of the delegation tree (fixed point down the internals
35
+ * chain; equals parentSessionId at depth 1). The recovery-face enumeration anchor: after a
36
+ * restart, intermediate spawner sessions are dead ends — "everything under this host session"
37
+ * keys on THIS field (listBySession matches it as a second arm), not on an alias walk. */
17
38
  rootSessionId?: string;
18
39
  parentTaskId?: string;
19
40
  name?: string;
20
41
  agentType?: string;
21
42
  description?: string;
43
+ /** Revival lookup keys (CC meta-sidecar parity); populated when known, never required. */
22
44
  teamName?: string;
23
45
  model?: string;
46
+ /** design/151 §3.1d (HIGH-3): the WRITING process instance id (random per registry instance). A
47
+ * fallback read of a `running` row whose writer is not the reading instance serves an HONEST
48
+ * "outcome unknown here" — never a fabricated "running" liveness claim.
49
+ * S3 revival ORDER OBLIGATION (全景复审 F-7): a cross-process revival must first CAS this field
50
+ * over to the reviving instance's writerId (the claim), THEN register-with-id — a fresh lane's
51
+ * first write against a row still carrying the dead process's writerId reads back "foreign" and
52
+ * poisons itself by design. Claim-CAS first is the only sequence the adjudication admits. */
24
53
  writerId: string;
54
+ /**
55
+ * design/153 §7.2c (r6 H-3) — the monotonic OWNERSHIP GENERATION, bumped by every ownership
56
+ * transfer (tier-3 claim, 件3 resume claim finalize, the in-process retained-revive claim). A
57
+ * ROLLBACK is itself a transfer, so every rollback shape mints a NEW epoch too — the reconciliation
58
+ * sweep's reservation/running rollbacks, the parked-reservation rollback (which additionally syncs
59
+ * this process's SURVIVING lane forward so its own later terminal write does not foreignize), and
60
+ * the revival-claim compensation. No rollback restores a pre-claim epoch: an orphaned lane's
61
+ * authority must never become resumable, and restoring the old generation would let the next claim
62
+ * by the SAME writer land on the very (writerId, epoch) pair that lane still holds. What a rollback
63
+ * restores is the pre-claim writerId and row shape — that is what makes the row addressable again;
64
+ * the fresh generation is what keeps the abandoned lane from speaking for it. The
65
+ * durable-lane adopt matches
66
+ * `writerId + writerEpoch` BOTH: a stale lane of the SAME writer (pre-transfer snapshot still in
67
+ * its chain) reads "foreign" instead of adopting the new rev and replaying its old record — the
68
+ * lane-self-clobber ABA the epoch exists to close. Optional: legacy rows (undefined) keep the
69
+ * pre-epoch writerId-only adopt semantics unchanged.
70
+ */
25
71
  writerEpoch?: number;
26
72
  spawnedAt: number;
27
73
  updatedAt: number;
28
74
  settledAt?: number;
75
+ /** design/153 §7.1: `"parked"` = durably suspended on a pending approval checkpoint (neither live
76
+ * nor terminal) — reap-exempt like `running`; cleared to a real state by resume claim, TaskStop
77
+ * (checkpoint arbitration first), or the reconciliation sweep (checkpoint expired/missing). */
29
78
  status: "running" | "parked" | "completed" | "failed" | "killed";
79
+ /** Open enum (task-registry `StopSource` mirror). */
30
80
  stoppedBy?: string;
81
+ /** P1-3(黑板 [1920]/[1921]/[1924]/[1925]) — the cross-channel completion correlation id
82
+ * (task-registry `SemaTaskHandle.completionId` mirror). Written alongside `status`/`settledAt` at
83
+ * the same durable terminal write that lands them, so a cross-restart fallback read (`TaskOutput`
84
+ * after the writing process is gone) REPLAYS this exact value — there is no second mint point here,
85
+ * this field only ever receives what the in-memory handle already minted before the write. */
31
86
  completionId?: string;
87
+ /** design/144 §1.1 dedup-key continuity (LOW-15): revival cycles re-mint seq FROM the stored value,
88
+ * so `task_id:status:seq` keys never collide across restarts. */
32
89
  seq?: number;
90
+ /**
91
+ * design/153 §7.1 — the durable-approval checkpoint token this row is parked ON (`status:"parked"`
92
+ * only; park mint writes it, resume claim / terminal settle clears it). The checkpoint token CAS is
93
+ * the MASTER arbitration domain (r4 F-05): every parked-row CAS also verifies THIS binding, and the
94
+ * row never adjudicates a park outcome on its own. A row CAS that loses after the checkpoint was
95
+ * committed is compensated by EXPIRING the checkpoint (no "committed but undiscoverable" orphans).
96
+ */
33
97
  parkedCheckpointToken?: string;
98
+ /** design/153 §7.1 — when the park landed (epoch ms). Observability + reconciliation ordering only. */
34
99
  parkedAt?: number;
100
+ /** design/153 §7.2 — the in-flight resume claim's compensable-ticket id (parked→running CAS writes
101
+ * it, a successful attach finalize clears it, a pre-attach failure rolls back BY it). A `running`
102
+ * row still carrying BOTH this and `parkedCheckpointToken` past the claim lease is a stale claim —
103
+ * the reconciliation sweep rolls it back to `parked`. */
35
104
  parkClaimId?: string;
36
105
  summary?: string;
37
106
  finalOutput?: string;
107
+ /** RB-205-B: the FULL result (workflow.ts NH-1 shape via {@link BackgroundAgentTaskHandle.resultFull}),
108
+ * set only when it differs from `finalOutput` — the restart/durable-fallback poll path needs the same
109
+ * pairing the live handle carries, or a process restart loses the very recoverability this field exists
110
+ * to preserve. */
38
111
  finalOutputFull?: string;
112
+ /** The child's failure text (registry `handle.error` mirror; the reap-stop sentinel never lands here).
113
+ * RB-237 ([1937] BA2): the stale-running reap flip ALSO writes its attribution here (`??`-guarded) —
114
+ * `error` is the field the durable serving face renders (`serveDurableAgentRow`), while `summary`
115
+ * has no reader on that face, so an attribution written only to `summary` was invisible: a host
116
+ * crash read as a bare `failed` + "(no result text)". */
39
117
  error?: string;
118
+ /** RB-405 (durable archival mirror) — the classification triplet the in-memory handle carries under
119
+ * the SAME names (`errorCode`/`errorRetryable`/`errorKind`; see RB-386②/RB-405 G3 on
120
+ * {@link import("./task-registry-shared.js").BackgroundAgentTaskHandle}), written to this row at the
121
+ * same terminal write that lands `error` — so a cross-restart fallback read
122
+ * ({@link import("./task-registry-agent.js").serveDurableAgentRowLane}) can render the identical
123
+ * classification clause the live poll does, instead of the row structurally losing it once the
124
+ * writing process exits (the residual this field set closes). */
40
125
  errorCode?: string;
41
126
  errorRetryable?: boolean;
42
127
  errorKind?: string;
@@ -45,12 +130,48 @@ export interface BackgroundAgentRecord {
45
130
  recentSteps?: SubagentStep[];
46
131
  editedFiles?: SubagentEditedFile[];
47
132
  usage?: BackgroundAgentUsage;
133
+ /** The org scopes the row's most recent leg actually mounted. ABSENT is NOT "unknown ⇒
134
+ * unconstrained": the revival reads an absent field as the ZERO verdict (see
135
+ * `readDurableOrgAdmission` in memory-admission.ts), so a pre-#22 row and a row whose leg
136
+ * mounted no org plane both admit nothing on the org axis. Written by the leg itself once its
137
+ * prepare has adjudicated (task-registry `recordBackgroundAgentOrgAdmission`), so every revival
138
+ * cycle re-records its own — necessarily narrower — verdict. */
48
139
  admittedOrgScopes?: string[];
140
+ /** The explicit org WRITE grant that verdict carried; `null` = the org write face was read-only.
141
+ * Same absent-reads-as-zero rule as {@link admittedOrgScopes} (absent ⇒ `null`). */
49
142
  admittedOrgWriteScope?: string | null;
143
+ /** Optimistic-concurrency revision. The writer always CASes with its OWN held rev (design/151
144
+ * MED-8): a foreign row (stale leftover / another writer) has an unknown rev, so the CAS loses
145
+ * instead of clobbering. Bumped by the store on every successful `update`. */
50
146
  rev: number;
51
147
  }
148
+ /**
149
+ * RB-423 — the terminal payload a REVIVAL must erase from the row it is re-launching, as ONE list.
150
+ *
151
+ * A revived handle starts a fresh cycle on an existing row: status flips back to `running`, but every
152
+ * field describing how the PREVIOUS cycle ended is still sitting there. Left standing, each one
153
+ * surfaces the old cycle's answer under the new cycle's status — a stale `finalOutputFull` is served
154
+ * in preference to the fresh `finalOutput` by the durable read face, a stale `errorCode`/`errorKind`
155
+ * pair renders a "network / retryable" classification on a row that has since completed cleanly, a
156
+ * stale `completionId` makes two different completions report one correlation id.
157
+ *
158
+ * There are TWO revival entry points — the in-process wake and the cross-process tier-3 claim-CAS —
159
+ * and they maintained two hand-written copies of this list. The copies drifted: `finalOutputFull` and
160
+ * the error triplet were added to one and not the other, and each addition was a separately-found
161
+ * defect of the same shape. One list, both callers, so the next field added to the terminal snapshot
162
+ * can only be forgotten once.
163
+ *
164
+ * Every member is optional on {@link BackgroundAgentRecord} (that is what makes them clearable);
165
+ * identity, lifecycle, concurrency and GOVERNANCE fields are deliberately absent — a revival
166
+ * inherits those. The org-admission freeze (`admittedOrgScopes` / `admittedOrgWriteScope`) is in
167
+ * the governance group on purpose: clearing it would hand the next cycle a blank slate, which is
168
+ * the widening the freeze exists to prevent.
169
+ */
52
170
  export declare const REVIVED_ROW_CLEARED_FIELDS: readonly ["settledAt", "stoppedBy", "completionId", "finalOutput", "finalOutputFull", "error", "errorCode", "errorRetryable", "errorKind", "errorRetryAfterMs", "resultIsPartial", "summary", "recentSteps", "editedFiles", "usage"];
171
+ /** Erase {@link REVIVED_ROW_CLEARED_FIELDS} from a record a revival is about to write back. */
53
172
  export declare function clearRevivedRowTerminalPayload(record: BackgroundAgentRecord): void;
173
+ /** Content-free projection for list reads (design/151 HIGH-1: `summary`/`finalOutput`/`recentSteps`
174
+ * and friends NEVER ride a list — content is get-by-handle only, behind the full predicate). */
54
175
  export interface BackgroundAgentRowSummary {
55
176
  handle: string;
56
177
  owner: string;
@@ -66,48 +187,185 @@ export interface BackgroundAgentRowSummary {
66
187
  settledAt?: number;
67
188
  usage?: BackgroundAgentUsage;
68
189
  }
190
+ /** Typed store error so callers branch on `code` (mirrors `WorkflowRunStoreError`). */
69
191
  export declare class BackgroundAgentStoreError extends Error {
70
192
  readonly code: "agent_record.already_exists";
71
193
  constructor(code: "agent_record.already_exists", message: string);
72
194
  }
195
+ /**
196
+ * design/151 §3.1c — the fallback access predicate (S-1 定谳 class). Mirrors the live registry's
197
+ * `canAccess` axes with ONE remaining durable-only addition: a task-scoped row is readable by its
198
+ * PARENT SESSION (`parentSessionId` leg) — after a restart the host session is the row's only
199
+ * legitimate owner (the spawn-time task ids are dead). The live registry still does not grant the
200
+ * parentSessionId leg (an intermediate session must not steer a sibling turn's running child);
201
+ * the ROOT arm, however, is now on BOTH faces — RB-236 (2026-07-29) aligned the live `canAccess`
202
+ * with this predicate's [1498]⑦ root-session arm, closing the "running grandchild is not_found to
203
+ * the session that owns the tree" window. Durable rows remain the settled/read/revive face.
204
+ * Cross-session same-scope reads stay not_found ([1498]⑤ content-axis ruling / [1493] root fix).
205
+ *
206
+ * Scope is FAIL-CLOSED both ways (`undefined` never matches) — records are put with a real scope.
207
+ */
73
208
  export declare function canAccessAgentRecord(record: Pick<BackgroundAgentRecord, "scope" | "owner" | "sessionScoped" | "parentSessionId" | "rootSessionId">, access: {
74
209
  owner?: string;
75
210
  scope?: string;
76
211
  sessionId?: string;
77
212
  }): boolean;
213
+ /**
214
+ * The pluggable durable ledger seam. Contract notes for implementations (file/pg):
215
+ * - `put` is create-once: throw {@link BackgroundAgentStoreError} `already_exists` on a live key —
216
+ * never silently overwrite (a leftover row from a dead process must not be clobbered by a
217
+ * fresh-minted colliding handle; the writer treats that as a loud no-durability degrade).
218
+ * - `update` is a CAS (`WHERE handle=? AND scope=? AND rev=?`): return false on a missing row, a
219
+ * scope mismatch (multi-tenant isolation — a wrong-scope update must not win), or a rev mismatch.
220
+ * On success bump `rev` by EXACTLY 1 and persist (全景 S3c F-3: the tier-3 claim derives the
221
+ * post-claim rev as `expect.rev + 1` for its lane seed and rollback CAS — a larger bump would
222
+ * silently downgrade every revival to the adopt-heal slow path and every rollback to the
223
+ * staleRunning sweep; both bundled impls bump by 1, the contract follows them).
224
+ * - `get`/`listBySession` are RAW row reads keyed by (handle|session, scope) — the full access
225
+ * predicate ({@link canAccessAgentRecord}) is applied by the ENGINE consumer (registry fallback),
226
+ * roster-store posture: a store implementation never widens visibility, and a deployment must not
227
+ * serve raw rows without the predicate.
228
+ * - `reap` deletes only what the policy names; a `running` OR `parked` row is deleted by NO policy —
229
+ * the `staleRunningMaxAgeMs` arm first CAS-flips a stale `running` to `failed` (host interrupted),
230
+ * then it ages out as a terminal row. A `parked` row is FULLY reap-exempt (design/153 §7.1: its
231
+ * writer does not heartbeat — the child is durably suspended, silence is its normal state; the
232
+ * checkpoint-bound reconciliation sweep, not row age, owns its cleanup). With no options, reap is
233
+ * a no-op (retention is always an explicit policy).
234
+ * Sizing (codex S1a F2): a LIVE writer renews its running rows' `updatedAt` every
235
+ * `DURABLE_AGENT_HEARTBEAT_MS` (60s — task-registry writer lease), so row age measures SILENCE —
236
+ * of the WRITER PROCESS, specifically (全景复审 verdict-8): a wedged child inside a healthy
237
+ * process keeps renewing and never goes stale, by design (in-process supervision owns that case).
238
+ * Set `staleRunningMaxAgeMs` ≥ 10× the heartbeat (≥10min). A premature flip still self-heals:
239
+ * the live writer's settle reads the row back, adopts the bumped rev (writerId match) and
240
+ * re-CASes the real terminal truth over the reaper's guess.
241
+ * ⚠️ Row deletion does NOT release the child SESSION (the store cannot reach the session store) —
242
+ * the blessed reap path is the registry-side orchestration (design/151 §3.1 MED-7 + codex 终审
243
+ * C-2): it conditionally DELETES the row under its re-verified rev first, and only a WINNING
244
+ * delete releases the transcript session (release-first destroyed a live transcript when a
245
+ * concurrent revive won the CAS after the release). Calling raw `reap` alone strands transcripts.
246
+ * Cross-process caveat (codex 终审 C-3): a revive's durable `running` transition rides the async
247
+ * lane — between the in-memory revive and its flush, a DIFFERENT process's sweep still holds a
248
+ * terminal-looking row whose rev the flush has not yet bumped. In-process sweeps are gated on the
249
+ * live handle; cross-process revival (S3) must claim-CAS FIRST (see {@link BackgroundAgentRecord.writerId}).
250
+ */
251
+ /** RB-237 ([1937] BA2): the stale-running reap flip's attribution, written to BOTH `summary` (legacy
252
+ * slot, kept for any out-of-repo reader) and `error` (the field {@link canAccessAgentRecord}-gated
253
+ * durable serving actually renders). One exported constant so the two store implementations (in-memory
254
+ * here, file twin) can never drift apart (RB-74/RB-111 family). Wording carries CC 2.1.220's three
255
+ * facts (220:950397): what happened (host process gone mid-run), the consequence (in-process state
256
+ * lost), and the action (check the worktree/output for partial work before assuming the task landed). */
78
257
  export declare const STALE_RUNNING_REAP_ATTRIBUTION = "the host process was interrupted while this agent was running \u2014 its in-process state was lost. Check its worktree / output file for partial work before assuming the task landed (stale running row reaped).";
258
+ /**
259
+ * REF-D18: the `updateIf` CAS predicate — the SINGLE shape the interface method and both the
260
+ * In-Memory and File implementations reference (previously each re-declared it inline). Mechanism
261
+ * finding this merge closes: a `class X implements Interface` clause does NOT catch a missing
262
+ * optional field when the implementing method re-declares its own narrower inline param type (TS
263
+ * method-parameter bivariance) — this exact duplicate-signature-drift class already produced a
264
+ * shipped double-counting bug in this file's family (RB-74, then RB-87/RB-111 fixed it in one
265
+ * implementation and not the other, same release; see the file-store twin's own comment).
266
+ */
79
267
  export interface BackgroundAgentUpdateIfExpect {
80
268
  rev: number;
81
269
  status?: BackgroundAgentRecord["status"];
82
270
  parkedCheckpointToken?: string | null;
83
271
  parkClaimId?: string | null;
84
272
  }
273
+ /** REF-D18: `reap`'s retention-policy options — same single-shape rationale as {@link
274
+ * BackgroundAgentUpdateIfExpect} above. */
85
275
  export interface BackgroundAgentReapOptions {
276
+ /** Delete terminal rows settled longer ago than this. Absent = this arm is not applied. Must be a
277
+ * finite, non-negative number of milliseconds. */
86
278
  maxAgeMs?: number;
279
+ /** Keep at most this many terminal rows, newest first. Absent = this arm is not applied. Must be a
280
+ * finite, non-negative whole number — see {@link assertBackgroundAgentReapOptions} for why a
281
+ * malformed value here is the dangerous one. */
87
282
  keep?: number;
283
+ /** Flip `running` rows untouched for longer than this to a failed terminal. Absent = not applied.
284
+ * Must be a finite, non-negative number of milliseconds. */
88
285
  staleRunningMaxAgeMs?: number;
89
286
  }
287
+ /** knob-hygiene #98 — refuse a malformed reap policy before any row is touched. Delegates to the one
288
+ * shared validator ({@link assertRetentionPolicy}) both bundled stores and the sibling mailbox /
289
+ * workflow-run / roster retention seams run through, so no implementation can drift from another. */
290
+ export declare function assertBackgroundAgentReapOptions(opts: BackgroundAgentReapOptions | undefined): void;
90
291
  export interface BackgroundAgentStore {
91
292
  put(record: BackgroundAgentRecord): Promise<void>;
92
293
  get(handle: string, scope: string): Promise<BackgroundAgentRecord | null>;
93
294
  update(handle: string, scope: string, record: BackgroundAgentRecord, expect: {
94
295
  rev: number;
95
296
  }): Promise<boolean>;
297
+ /**
298
+ * design/153 §7.2c (r6 H-3) — the GUARDED CAS the park/claim lanes require: atomic
299
+ * `WHERE rev [AND status] [AND parkedCheckpointToken] [AND parkClaimId]`. The plain `update`'s
300
+ * rev-only guard is NOT enough there (a rev can move for unrelated reasons between read and
301
+ * write while the park-critical fields changed meaning — reservation, rollback and finalize all
302
+ * bind to the FIELD state, not just the revision). Same success semantics as `update` (bump rev
303
+ * by exactly 1). An `expect` field set to a string matches equality; `null` matches ABSENCE.
304
+ * REQUIRED method (BREAKING for store implementers, announced): a silently-ignoring legacy
305
+ * implementation would fail OPEN on the exact CAS the approval chain's safety rests on.
306
+ */
96
307
  updateIf(handle: string, scope: string, record: BackgroundAgentRecord, expect: BackgroundAgentUpdateIfExpect): Promise<boolean>;
308
+ /** Rows whose durable session anchor (`sessionScoped ? owner : parentSessionId`) OR root anchor
309
+ * (`rootSessionId`, δ 批 [1498]⑦ — the whole delegation tree under one host session) equals
310
+ * `sessionId`, newest-first by `spawnedAt`. Content-free projections (HIGH-1). `opts.status`
311
+ * filters one state; `opts.limit` keeps the newest N after the sort. */
97
312
  listBySession(scope: string, sessionId: string, opts?: {
98
313
  status?: BackgroundAgentRecord["status"];
99
314
  limit?: number;
100
315
  }): Promise<BackgroundAgentRowSummary[]>;
316
+ /** codex r2 F1 — ALL of a scope's rows (content-free, newest-first): the joint-reap orchestration's
317
+ * enumeration face (`TaskRegistry.reapDurableAgents` — conditional delete first, session release
318
+ * only after a winning delete; codex 终审 C-2). Deployment-op context, not a model-serving face —
319
+ * model-facing reads stay behind {@link canAccessAgentRecord}. */
101
320
  listByScope(scope: string, opts?: {
102
321
  status?: BackgroundAgentRecord["status"];
103
322
  limit?: number;
104
323
  }): Promise<BackgroundAgentRowSummary[]>;
324
+ /** codex r2 F1 — row-precise removal (the joint-reap deletion arm). Returns false on a miss.
325
+ * codex r3 F1: `expect.rev` makes it CONDITIONAL — a live writer's concurrent revival (heartbeat
326
+ * adopt bumps rev) must beat the reaper's stale snapshot, so the joint reap always deletes with
327
+ * the rev it just re-verified. */
105
328
  delete(handle: string, scope: string, expect?: {
106
329
  rev: number;
107
330
  }): Promise<boolean>;
331
+ /** [1511] server ask (a) — enumerate the scopes that currently hold rows, so a deployment-op
332
+ * retention loop can drive {@link TaskRegistry.reapDurableAgents} per scope without external
333
+ * bookkeeping (a local backend under multi-tenant use otherwise grows principal-scoped rows
334
+ * forever). Optional: a store whose deployment tracks scopes elsewhere (pg: SELECT DISTINCT)
335
+ * may omit it. Deployment-op face, never model-serving. */
108
336
  listScopes?(): Promise<string[]>;
337
+ /** Retention sweep for `scope` (explicit policy, see interface notes). Returns rows deleted+flipped. */
109
338
  reap(scope: string, now: number, opts?: BackgroundAgentReapOptions): Promise<number>;
110
339
  }
340
+ /**
341
+ * design/153 §7.1 (r4 F-03) — the parked-row ↔ checkpoint reconciliation sweep. `parked` rows are
342
+ * reap-exempt (their writer does not heartbeat), so WITHOUT this sweep an expired/removed approval
343
+ * checkpoint leaves the row parked forever. Deployment-op face (same posture as
344
+ * `TaskRegistry.reapDurableAgents`): the deployment calls it on its retention cadence with BOTH
345
+ * stores. Two arms, both master-arbitrated by the checkpoint (never by row age):
346
+ * 1. parked rows whose checkpoint is EXPIRED or MISSING → CAS to `failed` (honest terminal, error
347
+ * names the cause). A `pending` or `resolved` checkpoint leaves the row alone (`resolved` =
348
+ * a resume is mid-flight — the claim path owns it).
349
+ * 2. stale claims (r4 F-04): `running` rows still carrying BOTH `parkClaimId` and
350
+ * `parkedCheckpointToken` past `staleClaimMaxAgeMs` (claimed, then the claimer died before the
351
+ * attach finalize) → CAS BACK to `parked` iff the checkpoint is still pending (redeemable
352
+ * again); expired/missing → arm-1 shape (failed).
353
+ * 3. stranded flip-lost orphans (server cross-probe B1, 2026-07-24): `parked` rows with NO claim
354
+ * whose checkpoint is RESOLVED (the consume flip never landed) → `failed` (approval consumed,
355
+ * outcome unknown). ⚠️ Arms 2-3 run ONLY when `staleClaimMaxAgeMs` is supplied (review F-5:
356
+ * a deployment that never passes it never reaps these shapes), and an in-process caller's own
357
+ * handles are excluded — the stranded arm therefore needs an OUT-OF-PROCESS sweep (or a later
358
+ * run after the owning process exits) to fire.
359
+ * Every write is a rev-CAS — a live writer's concurrent transition wins and the sweep just skips.
360
+ *
361
+ * SPLIT-BRAIN FENCE (件1 codex HIGH): failing a row whose PARKING PROCESS is still alive would
362
+ * desynchronize its live handle (poll keeps saying parked, TaskStop mis-reports). An in-process
363
+ * deployment therefore calls {@link import("./task-registry.js").TaskRegistry.reconcileParkedAgents}
364
+ * (which handles ITS OWN handles live, then delegates here with `excludeWriterId` = its writerId);
365
+ * calling this bare is correct only where no engine instance is live for the scope. Residual (multi-
366
+ * replica shared store, ANOTHER live instance's rows): same documented posture as RB-38③ — that
367
+ * instance's next durable write CAS-fails and poisons its lane loudly rather than silently diverging.
368
+ */
111
369
  export declare function reconcileParkedAgents(stores: {
112
370
  agentStore: BackgroundAgentStore;
113
371
  checkpointStore: Pick<import("./checkpoint-store.js").CheckpointStore, "get">;
@@ -119,13 +377,48 @@ export declare function reconcileParkedAgents(stores: {
119
377
  failed: number;
120
378
  rolledBack: number;
121
379
  }>;
380
+ /**
381
+ * REF-A3 — the query shape both `listBySession` (with {@link sessionId}) and `listByScope` (without it)
382
+ * are expressed in. Named rather than inline because it crosses a module boundary (the file backend
383
+ * imports it), and every field's ABSENCE is a defined "no filter" state rather than a missing value.
384
+ */
122
385
  export interface BackgroundAgentQuery {
386
+ /** Tenant partition key, always in the WHERE — a row in another scope is never visible. */
123
387
  scope: string;
388
+ /**
389
+ * Session-anchored enumeration: a row qualifies when its durable anchor
390
+ * (`sessionScoped ? owner : parentSessionId`) OR its `rootSessionId` (δ 批 [1498]⑦ — the whole
391
+ * delegation tree under one host session) equals this. ABSENT ⇒ scope-wide enumeration.
392
+ */
124
393
  sessionId?: string;
394
+ /** Keep only this status. ABSENT ⇒ every status. */
125
395
  status?: BackgroundAgentRecord["status"];
396
+ /** Keep the newest N, applied AFTER the sort. ABSENT ⇒ no cap. */
126
397
  limit?: number;
127
398
  }
399
+ /**
400
+ * REF-A3 — THE query projection for {@link BackgroundAgentStore.listBySession} /
401
+ * {@link BackgroundAgentStore.listByScope}: filter → sort newest-first by `spawnedAt` → truncate →
402
+ * content-free summary (HIGH-1). Pure (no store state, no I/O): it takes any row iterable, so the
403
+ * in-memory backend passes its `Map` values and the file backend passes the shared ledger's. The two
404
+ * backends held byte-identical hand copies of this before — the same one-of-two-implementations drift
405
+ * hazard RB-60 / RB-74 / RB-87 / RB-111 each landed on, on this very surface.
406
+ *
407
+ * PUBLIC (a serving layer runs the same filter/sort/truncate the bundled backends do, instead of a
408
+ * sixth hand copy). It is a projection over rows the CALLER supplied — it neither reads a store nor
409
+ * authorizes anything: the summaries it returns are content-free but still name handles and session
410
+ * anchors, so a deployment that hands any of them to an external caller applies
411
+ * {@link canAccessAgentRecord} first (the {@link BackgroundAgentStore} interface notes state the same
412
+ * obligation for raw rows: a store never widens visibility, and raw rows are not a serving face).
413
+ */
128
414
  export declare function queryBackgroundAgents(rows: Iterable<BackgroundAgentRecord>, query: BackgroundAgentQuery): BackgroundAgentRowSummary[];
415
+ /**
416
+ * In-process reference implementation. NOT default-mounted (divergence ② above) — single-instance
417
+ * deployments and tests wire it explicitly; it does not survive a restart, so with THIS store the
418
+ * lifecycle flip buys retained transcripts only for the process lifetime (capability presence ≠
419
+ * durability — the `SessionStore.fork` doctrine applies verbatim). `structuredClone` on both
420
+ * boundaries (no aliasing between the caller's live objects and stored rows).
421
+ */
129
422
  export declare class InMemoryBackgroundAgentStore implements BackgroundAgentStore {
130
423
  private rows;
131
424
  private key;
@@ -1,4 +1,5 @@
1
1
  import { uuidv7 } from "../internal/harness.js";
2
+ import { assertRetentionPolicy } from "./retention-policy.js";
2
3
  export const REVIVED_ROW_CLEARED_FIELDS = [
3
4
  "settledAt",
4
5
  "stoppedBy",
@@ -43,6 +44,9 @@ export function canAccessAgentRecord(record, access) {
43
44
  return false;
44
45
  }
45
46
  export const STALE_RUNNING_REAP_ATTRIBUTION = "the host process was interrupted while this agent was running — its in-process state was lost. Check its worktree / output file for partial work before assuming the task landed (stale running row reaped).";
47
+ export function assertBackgroundAgentReapOptions(opts) {
48
+ assertRetentionPolicy("BackgroundAgentStore.reap", opts);
49
+ }
46
50
  export async function reconcileParkedAgents(stores, scope, now, opts) {
47
51
  const out = { failed: 0, rolledBack: 0 };
48
52
  const excluded = (row) => (opts?.excludeHandles?.has(row.handle) ?? false) ||
@@ -256,6 +260,7 @@ export class InMemoryBackgroundAgentStore {
256
260
  return [...new Set([...this.rows.values()].map((r) => r.scope))].sort();
257
261
  }
258
262
  async reap(scope, now, opts) {
263
+ assertBackgroundAgentReapOptions(opts);
259
264
  if (!opts || (opts.maxAgeMs === undefined && opts.keep === undefined && opts.staleRunningMaxAgeMs === undefined))
260
265
  return 0;
261
266
  const flippedKeys = new Set();
@@ -1,45 +1,155 @@
1
+ /**
2
+ * design/103 — 后台 shell seam(detached process)。「手」腿(`ExecutionEnv`)的 long-running 进程能力:启动一个不会
3
+ * 立刻退出的命令、轮询它的输出、需要时杀掉它。让引擎能跑真实开发循环(起 dev server / build watcher → 轮询日志 →
4
+ * 迭代),用于自足 make-real。
5
+ *
6
+ * 这是一个 **env 上的可选能力**(非一种独立 env 类型),所以不 `extends ExecutionEnv` —— 用交叉类型挂到具体实现上,并经
7
+ * {@link hasBackgroundShell} 运行时检测(对齐 remote-env.ts 的 `hasDestroy`/`isRemoteExecutionEnv` 模式,零 vendor 接口改动)。
8
+ *
9
+ * 设计裁定(经 codex + workflow 5-lens 双轨对抗复审收敛,design/103 v2):
10
+ * - **不跨 durable suspend**:后台进程在每条退出路径被 dispose;Runner 必须在 suspendVM **之前** 调
11
+ * {@link BackgroundShellCapability.disposeBackgroundShells}(detached job 不在 suspendVM 的 in-flight 契约射程内)。
12
+ * - **越权隔离**:`pollBackground`/`killBackground` 的 shellId MUST 被校验为本 env 自己 spawn 过的;非本 env 走 `not_found`。
13
+ * - **按-id-可重读**:实现 MUST 保证按 shellId 跨多次独立调用可重复读取累积/增量输出(execStream 的 consume-once 不满足)。
14
+ */
1
15
  import type { ExecutionEnv, ExecutionEnvExecOptions, Result } from "../internal/harness-types.js";
16
+ /**
17
+ * 一个 long-running / detached 进程的句柄。**env-local、非 durable、对调用方不透明** —— adapter 内部把它映射到真实进程/
18
+ * provider job,**绝不**把可猜的 raw provider job id 暴露成 shellId(否则跨租户可枚举,design/103 §3.8 越权红线)。
19
+ */
2
20
  export type BackgroundShellId = string & {
3
21
  readonly __brand: "BackgroundShellId";
4
22
  };
23
+ /** 一个后台进程的生命周期状态。`exited` 携带 exitCode;`failed` = 启动后异常终止(非被 kill)。 */
5
24
  export type BackgroundShellStatus = "running" | "exited" | "killed" | "failed";
25
+ /**
26
+ * 类型化错误码(对齐 `RemoteExecutionErrorCode` 风格)。`timeout`/`io` 覆盖 TOB 下的有界 liveness/传输失败 —— 接口规定
27
+ * 方法 MUST NOT throw(返回 {@link Result}),所以挂掉的 provider RPC 必须有码可表达、而非违约抛异常。
28
+ */
6
29
  export type BackgroundShellErrorCode = "unsupported" | "not_found" | "spawn_failed" | "limit_exceeded" | "timeout" | "io";
30
+ /** 后台 shell 操作的类型化错误。`code` 给程序分类,`message` 给模型自纠(design/103 错误文案纪律)。 */
7
31
  export declare class BackgroundShellError extends Error {
8
32
  readonly code: BackgroundShellErrorCode;
9
33
  readonly cause?: unknown | undefined;
10
34
  constructor(code: BackgroundShellErrorCode, message: string, cause?: unknown | undefined);
11
35
  }
36
+ /**
37
+ * `spawnBackground` 的 options。后台进程只用 `cwd`/`env`/`timeout`;流式回调(`onStdout`/`onStderr`)和 `abortSignal`
38
+ * 都对「启动后轮询」语义无意义(输出进 tail buffer 等 poll;后台进程的生命周期由 kill/timeout/dispose 管,不绑启动它
39
+ * 的工具调用的 signal),故显式 `Omit` 以免实现者误以为传 abortSignal 能约束进程。`timeout` 在后台是**硬墙**
40
+ * (到点自杀 → status `killed`,design/103 §3.6)。
41
+ */
12
42
  export type BackgroundSpawnOptions = Omit<ExecutionEnvExecOptions, "onStdout" | "onStderr" | "abortSignal">;
43
+ /** 一次 {@link BackgroundShellCapability.pollBackground} 的返回:自上次 poll 以来的增量 + 当前状态 + cursor 元数据。 */
13
44
  export interface BackgroundPoll {
45
+ /** 自上次 poll 后的新增 stdout(已应用 `filter`,且 filter 先于截断 —— design/103 §3.4)。 */
14
46
  stdout: string;
47
+ /** 自上次 poll 后的新增 stderr。 */
15
48
  stderr: string;
49
+ /** 当前生命周期状态。 */
16
50
  status: BackgroundShellStatus;
51
+ /** `status==="exited"` 时的退出码。 */
17
52
  exitCode?: number;
53
+ /**
54
+ * 本 cursor 之前有字节因 **8MB tail buffer 的 head-evict 永久丢失**(配合 {@link bytesDroppedBeforeCursor})。
55
+ * 🔴 注意:这是**不可恢复**的丢失,不是「可再 poll 拉取」——进程产出超过 8MB tail 时最早段被挤掉。(单次 poll 增量
56
+ * 超 per-poll 显示上限的 head+tail 截断发生在**工具层**,那是另一回事,由工具的截断 marker 诚实标注。)
57
+ */
18
58
  truncated?: boolean;
59
+ /** 从进程启动至今的总输出字节(cursor 元数据,供模型判断是否错过早期日志)。 */
19
60
  bytesFromStart?: number;
61
+ /** 因 8MB tail buffer head-evict 在本 cursor 之前**永久丢失**的字节数(诚实标注,不谎称「全部」)。 */
20
62
  bytesDroppedBeforeCursor?: number;
63
+ /** Present (`true`) only when the shell reached its terminal state via its OWN background timeout
64
+ * (the env's per-shell hard wall killed it) — distinguishes a self-inflicted timeout from an
65
+ * external kill, which otherwise produce identical `status:"killed"` frames. */
21
66
  timedOut?: boolean;
67
+ /** The timeout budget (seconds) that was actually applied to this shell (requested value clamped
68
+ * to the env's hard cap). Reported alongside {@link timedOut}. */
22
69
  timeoutSec?: number;
23
70
  }
71
+ /**
72
+ * 「手」腿的后台进程能力。一个具体 `ExecutionEnv` 实现可选地附加它(交叉类型),经 {@link hasBackgroundShell} 检测。
73
+ * 不支持的 env(StubExecutionEnv / SSH / ADB)= 不实现(或 `supported:false`),三个后台工具自动不挂(INERT)。
74
+ */
24
75
  export interface BackgroundShellCapability {
76
+ /** 显式声明能力(像 `RemoteExecutionEnv.capabilities` 一样不猜)。per-env / per-adapter。 */
25
77
  readonly backgroundCapabilities: {
78
+ /** 是否真支持后台 spawn;`false` → 三工具不挂(design/103 §3.8)。 */
26
79
  readonly supported: boolean;
80
+ /** 单 env 同时存活的后台进程上限(防 fork bomb;超限 spawn 返回 `limit_exceeded`)。 */
27
81
  readonly maxConcurrent: number;
82
+ /** 后台默认 timeout(秒)。**per-端下沉**(E2B 沙箱寿命 ≠ TOC 宿主),非单一 core 常量。 */
28
83
  readonly defaultBgTimeoutSec: number;
84
+ /** 后台 timeout **硬上限**(秒)。fail-closed 到有限值 —— **绝不允许无界**(design/103 §3.6)。 */
29
85
  readonly maxBgTimeoutSec: number;
86
+ /** design/116 detach(飞轮 [C]):env 是否支持把前台 exec 的运行中子进程「领养」为后台(exec options 的
87
+ * `detachSignal`)。缺省/false ⇒ detach 请求被忽略(exec 继续前台跑完)。 */
30
88
  readonly supportsDetach?: boolean;
89
+ /** design/128 T1-1 留驻声明(TB 2026-07-08 翻红回归修):env 声明后台进程 **outlive the run** ——
90
+ * 一切**自动**收割路径(runner 每退出路径的 `disposeBackgroundShells`、registry 的 run-teardown settle
91
+ * 清扫、session release 的 reap)MUST 跳过 kill,把进程留作孤儿(宿主退出后由部署收尸,e.g. TB 容器)。
92
+ * **显式** TaskStop/KillShell 与 per-shell timeout 硬墙不受影响(host 在世期间照常工作)。
93
+ * 实现侧 `disposeBackgroundShells` 自守 no-op 只护住了 dispose 一条路径;registry 直调 `killBackground`
94
+ * 的清扫(settleKilledForOwner)在 1.257.3 绕穿了它把 TB 留驻服务全数击杀 —— 声明上浮到能力面,让每个
95
+ * 自动收割调用方都看得见。缺省 false = 常规回收行为。 */
31
96
  readonly retainBackgroundProcesses?: boolean;
32
97
  };
98
+ /**
99
+ * 启动一条命令为后台进程,不等退出,返回 env-local 不透明句柄。MUST NOT block on 进程退出。`timeout` 是硬墙(到点自杀)。
100
+ * 后台子进程的 env MUST 经与前台 `exec` **完全相同**的 secret-scrub(design/103 §3.1 红线),cwd 默认 = 追踪的逻辑 cwd。
101
+ */
33
102
  spawnBackground(command: string, options?: BackgroundSpawnOptions): Promise<Result<{
34
103
  shellId: BackgroundShellId;
35
104
  }, BackgroundShellError>>;
105
+ /**
106
+ * 读一个后台进程**自上次 poll 以来的新增**输出 + 当前状态(cursor 语义)。退出后仍可读残余 + exitCode,直到被 dispose/reap。
107
+ *
108
+ * 🔴 越权契约:`shellId` MUST 被校验为**本 env 自己 spawnBackground 返回过**的;非本 env 一律 `not_found`,绝不解析外部 job id。
109
+ * 🔴 重读契约:实现 MUST 保证「按 shellId 跨多次独立调用可重复读取累积/增量」(remote 的 execStream consume-once 不满足 —— 见 design/103 §5.2 两条路径)。
110
+ */
36
111
  pollBackground(shellId: BackgroundShellId): Promise<Result<BackgroundPoll, BackgroundShellError>>;
112
+ /** 杀一个后台进程(幂等:杀已死的是 no-op,返回 ok)。`shellId` 同 {@link pollBackground} 的越权校验。 */
37
113
  killBackground(shellId: BackgroundShellId): Promise<Result<void, BackgroundShellError>>;
114
+ /**
115
+ * 杀掉并清理**本 env 的所有**后台进程。Runner 在每条退出路径调:finish/abort/throw 在 run-loop tail finally,**suspend/
116
+ * review 必须在 `suspendVM` 之前**(design/103 §3.7;detached job 不在 suspendVM in-flight 契约内,不能指望 adapter 隐式处理)。
117
+ * Best-effort,MUST NOT throw(像 `cleanup`/`destroy`)。幂等。
118
+ *
119
+ * 飞轮 [492]② `except`(可选):这些 shellId **留活**(session 驻留 persistent Monitor 的进程 —— 它的全部意义
120
+ * 就是跨 turn 存活;run-end 全灭会留下「registry handle 活着、进程死了」的孤儿 watch)。不认识此参数的旧
121
+ * 实现照旧全灭 = 今天的行为(诚实降级,not silent corruption:watcher 会打出 env-death 终态通知)。
122
+ * suspend/review 前的 dispose **不带** except(挂起整个 VM,进程死亡是既有契约)。
123
+ */
38
124
  disposeBackgroundShells(opts?: {
39
125
  except?: readonly BackgroundShellId[];
40
126
  }): Promise<void>;
41
127
  }
128
+ /**
129
+ * 结构 + 语义检测:`env` 是否暴露后台 shell 能力且声明 `supported:true`。挂载门控用此(对齐 `hasDestroy`)。
130
+ *
131
+ * 单谓词足够:remote-env 刻意拆 `isRemoteExecutionEnv`(结构)/`isSuspendable`(语义)是因为 isolation/suspendable 两轴
132
+ * 彼此独立;这里 `supported` 是唯一语义轴,合进一个谓词不会丢信息。
133
+ */
42
134
  export declare function hasBackgroundShell(env: ExecutionEnv): env is ExecutionEnv & BackgroundShellCapability;
135
+ /**
136
+ * [1712] / RB-164 — the ONE way core runs an env-level background sweep.
137
+ *
138
+ * ## Why a single entry point
139
+ * `disposeBackgroundShells` lives in the execution-env layer and cannot reach the task registry, so the
140
+ * one class of kill a user actually notices — their `run_in_background` job disappearing — was the only
141
+ * one that left no attribution: the row still read `stopped-by:"system"`, which is not a cause but the
142
+ * default, i.e. "nothing recorded who did this". Diagnosing a real incident took a cross-repo timeline
143
+ * argument to establish only that the kill had bypassed the registry.
144
+ *
145
+ * Attribution therefore has to be applied by the CALLER, immediately before the sweep — and this repo has
146
+ * spent the week learning what happens when a rule is applied at some of its call sites. There were six.
147
+ * So there is one function, and `test/defectscan-shell-gate-surface.test.ts`… (see the guard) forbids calling
148
+ * `disposeBackgroundShells` anywhere in `src/core/` except here.
149
+ *
150
+ * `attribution` is taken structurally rather than as a `TaskRegistry` import — this module is below the
151
+ * registry in the dependency order, and inverting that to get a log line would be the wrong trade.
152
+ */
43
153
  export interface EnvSweepAttribution {
44
154
  markStopSourceForEnvSweep(env: unknown, source: string, except?: readonly string[]): string[];
45
155
  }
@@ -1,3 +1,17 @@
1
+ /**
2
+ * Two-phase prefix-cache-break detector (design/31). Each turn it records a structural fingerprint of
3
+ * the prefix (system prompt / per-tool schema / tool set / model namespace) and compares the turn's
4
+ * `cacheRead` against the prior warm turn; on a confirmed drop it attributes the break to a root cause
5
+ * (model switch / a specific tool's drift / tool-set change / system-prefix change / server-or-TTL).
6
+ *
7
+ * The strict superset of the task-end "low hit-rate" heuristic: it pinpoints the BREAK TURN and names
8
+ * the cause, instead of only reporting an aggregate at the end. Provider-agnostic — the only provider
9
+ * input is `cacheRead` (OpenAI `cached_tokens` / Anthropic `cache_read_input_tokens`, already normalized).
10
+ *
11
+ * v1 is task-scoped (compares turns within one run; system/tools are stable so the high-value per-tool
12
+ * attribution mostly fires on a model switch or across runs). A per-session v2 would feed a persisted
13
+ * prior snapshot — the `observe` contract is already shaped for that.
14
+ */
1
15
  export interface CacheBreakFinding {
2
16
  turn: number;
3
17
  cacheReadBefore: number;
@@ -10,6 +24,12 @@ export interface ToolFingerprintInput {
10
24
  description: string;
11
25
  parameters: unknown;
12
26
  }
27
+ /**
28
+ * Project a tool list into the structural inputs the detector fingerprints. Shared by the initial
29
+ * snapshot in `prepareTask` AND the per-materialization refresh in tool-disclosure (design/36): both
30
+ * MUST derive the fingerprint the same way, or a deferred tool going placeholder→full schema would
31
+ * be hashed inconsistently. Keep this the single source of "what counts as the cacheable tool prefix".
32
+ */
13
33
  export declare function toolsToFingerprintInputs(tools: ReadonlyArray<{
14
34
  name: string;
15
35
  description: string;
@@ -17,7 +37,21 @@ export declare function toolsToFingerprintInputs(tools: ReadonlyArray<{
17
37
  }>): ToolFingerprintInput[];
18
38
  export declare class CacheBreakDetector {
19
39
  private prev;
40
+ /**
41
+ * Reset the baseline. **Call ONLY after a SUCCESSFUL compaction** (design/31 red line #11): a legit
42
+ * prefix shrink isn't a break, but resetting when compaction did NOT happen opens a false-negative
43
+ * window (a real break right after would be missed).
44
+ */
20
45
  notifyCompaction(): void;
46
+ /**
47
+ * Record this turn's fingerprint + compare cacheRead to the prior warm turn. Returns a finding on a
48
+ * confirmed break. Hashes are computed here per call **by design**, taking the raw prefix rather than
49
+ * pre-computed hashes. NOTE (design/36): the inputs are NOT necessarily stable within a run — deferred
50
+ * tools materialize placeholder→full schema mid-task, so the caller refreshes the fingerprint at
51
+ * materialization (via `toolsToFingerprintInputs`). A resulting `tool-schema`/`tool-set` finding on
52
+ * that turn is EXPECTED and truthful (the cacheable prefix genuinely changed); the bug this guards
53
+ * against is the opposite — a frozen fingerprint hiding that change (a false negative).
54
+ */
21
55
  observe(input: {
22
56
  turn: number;
23
57
  systemPrompt: string;