@sema-agent/core 7.54.1 → 7.55.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 (399) hide show
  1. package/CHANGELOG.md +437 -0
  2. package/dist/agents/agent-transcript-tool.js +2 -1
  3. package/dist/agents/builtin-agents.d.ts +12 -14
  4. package/dist/agents/cc-peer-directory.d.ts +36 -0
  5. package/dist/agents/cc-peer-directory.js +138 -0
  6. package/dist/agents/cc-peer-wire.d.ts +105 -0
  7. package/dist/agents/cc-peer-wire.js +98 -0
  8. package/dist/agents/cc-uds-peer-channel.d.ts +40 -0
  9. package/dist/agents/cc-uds-peer-channel.js +457 -0
  10. package/dist/agents/cross-session-envelope.d.ts +4 -1
  11. package/dist/agents/cross-session-envelope.js +8 -1
  12. package/dist/agents/cross-session-judge.d.ts +2 -2
  13. package/dist/agents/list-agents-tool.js +2 -1
  14. package/dist/agents/observer.d.ts +4 -5
  15. package/dist/agents/observer.js +2 -1
  16. package/dist/agents/peer-admission.d.ts +6 -0
  17. package/dist/agents/peer-admission.js +4 -1
  18. package/dist/agents/peer-directory.d.ts +43 -9
  19. package/dist/agents/peer-directory.js +66 -23
  20. package/dist/agents/peer-notices.d.ts +1 -1
  21. package/dist/agents/peer-session-drain.d.ts +3 -1
  22. package/dist/agents/peer-session-drain.js +1 -0
  23. package/dist/agents/read-inbox-tool.js +2 -1
  24. package/dist/agents/retain-ledger.d.ts +1 -1
  25. package/dist/agents/roster-store.d.ts +1 -1
  26. package/dist/agents/send-message-tool.d.ts +10 -0
  27. package/dist/agents/send-message-tool.js +34 -5
  28. package/dist/agents/subagent.d.ts +34 -79
  29. package/dist/agents/subagent.js +45 -46
  30. package/dist/agents/tool-filter.d.ts +29 -46
  31. package/dist/agents/tool-filter.js +8 -31
  32. package/dist/agents/verify.d.ts +3 -3
  33. package/dist/brain/anthropic.js +14 -9
  34. package/dist/brain/errors.d.ts +15 -0
  35. package/dist/brain/errors.js +10 -0
  36. package/dist/brain/model-presets.d.ts +4 -4
  37. package/dist/brain/open-responses.js +15 -10
  38. package/dist/brain/openai.js +17 -12
  39. package/dist/brain/provider-dialect.d.ts +39 -3
  40. package/dist/brain/provider-dialect.js +28 -0
  41. package/dist/brain/reasoning.d.ts +1 -1
  42. package/dist/brain/request-params.d.ts +55 -5
  43. package/dist/brain/request-params.js +35 -3
  44. package/dist/brain/retry.d.ts +1 -1
  45. package/dist/brain/route-adjudicator.d.ts +15 -0
  46. package/dist/brain/route-adjudicator.js +15 -0
  47. package/dist/brain/stream-engine.js +6 -5
  48. package/dist/brain/stream-shared.d.ts +1 -1
  49. package/dist/core/advisor-verdict.d.ts +120 -0
  50. package/dist/core/advisor-verdict.js +92 -0
  51. package/dist/core/agent-definition.d.ts +7 -8
  52. package/dist/core/allow-entry.d.ts +49 -23
  53. package/dist/core/allow-entry.js +57 -32
  54. package/dist/core/allow-rule-shadow.d.ts +7 -0
  55. package/dist/core/approval-object.d.ts +2 -1
  56. package/dist/core/approval-object.js +6 -6
  57. package/dist/core/ask-origin.d.ts +63 -11
  58. package/dist/core/ask-origin.js +27 -5
  59. package/dist/core/ask-question.js +10 -4
  60. package/dist/core/auto-compaction.d.ts +11 -8
  61. package/dist/core/auto-compaction.js +4 -2
  62. package/dist/core/auto-mode-arming.d.ts +2 -2
  63. package/dist/core/auto-mode-defaults.d.ts +8 -8
  64. package/dist/core/auto-mode-prompt-assets.d.ts +3 -3
  65. package/dist/core/auto-mode-prompt.d.ts +1 -1
  66. package/dist/core/auto-mode.d.ts +17 -9
  67. package/dist/core/auto-mode.js +9 -6
  68. package/dist/core/background-agent-store.d.ts +3 -3
  69. package/dist/core/canonical-json.d.ts +1 -1
  70. package/dist/core/canonical-json.js +2 -2
  71. package/dist/core/checkpoint-requirements.d.ts +6 -3
  72. package/dist/core/checkpoint-requirements.js +4 -14
  73. package/dist/core/checkpoint-store.d.ts +80 -51
  74. package/dist/core/checkpoint-store.js +56 -74
  75. package/dist/core/child-clamp-seats.d.ts +6 -0
  76. package/dist/core/child-clamp-seats.js +3 -16
  77. package/dist/core/compliance.d.ts +2 -2
  78. package/dist/core/context-edit.d.ts +6 -7
  79. package/dist/core/cross-boundary-taint.d.ts +9 -3
  80. package/dist/core/cross-boundary-taint.js +5 -3
  81. package/dist/core/decision-receipt.js +2 -2
  82. package/dist/core/effective-path-target.d.ts +1 -1
  83. package/dist/core/engine-notice.d.ts +19 -5
  84. package/dist/core/exec-output-tail.d.ts +1 -1
  85. package/dist/core/file-history-retention.d.ts +1 -1
  86. package/dist/core/file-history-store.d.ts +59 -9
  87. package/dist/core/file-history-store.js +35 -17
  88. package/dist/core/gate-fold.js +3 -2
  89. package/dist/core/gate-lanes.js +12 -8
  90. package/dist/core/gate-outcome.d.ts +17 -4
  91. package/dist/core/gate-outcome.js +30 -0
  92. package/dist/core/governance-codes.d.ts +13 -3
  93. package/dist/core/governance-codes.js +10 -0
  94. package/dist/core/hands-band.d.ts +1 -1
  95. package/dist/core/hooks.d.ts +4 -4
  96. package/dist/core/host-target.d.ts +49 -0
  97. package/dist/core/host-target.js +59 -0
  98. package/dist/core/image-downsample.d.ts +1 -1
  99. package/dist/core/lsp-diagnostics.d.ts +4 -4
  100. package/dist/core/lsp.d.ts +3 -3
  101. package/dist/core/mailbox-store.d.ts +4 -0
  102. package/dist/core/mcp-connection-pool.d.ts +18 -2
  103. package/dist/core/mcp-connection-pool.js +53 -6
  104. package/dist/core/mcp-failure.d.ts +23 -4
  105. package/dist/core/mcp-failure.js +26 -11
  106. package/dist/core/mcp-listing-drift.d.ts +10 -0
  107. package/dist/core/mcp-listing-drift.js +6 -0
  108. package/dist/core/mcp-server-link.d.ts +173 -0
  109. package/dist/core/mcp-server-link.js +127 -0
  110. package/dist/core/mcp-server-spec.d.ts +4 -2
  111. package/dist/core/mcp-session-end.d.ts +26 -0
  112. package/dist/core/mcp-session-end.js +29 -0
  113. package/dist/core/mcp-startup-request.d.ts +17 -0
  114. package/dist/core/mcp-startup-request.js +17 -0
  115. package/dist/core/mcp.d.ts +13 -13
  116. package/dist/core/mcp.js +187 -162
  117. package/dist/core/media-byte-cap.d.ts +1 -1
  118. package/dist/core/memory-engine/engine.d.ts +9 -9
  119. package/dist/core/memory-engine/provenance-wording.d.ts +1 -1
  120. package/dist/core/memory-engine/tools.js +4 -1
  121. package/dist/core/mode-policy.d.ts +1 -1
  122. package/dist/core/namespaced-rule-name.d.ts +33 -7
  123. package/dist/core/namespaced-rule-name.js +39 -25
  124. package/dist/core/output-style.d.ts +1 -1
  125. package/dist/core/param-rule-reach.d.ts +15 -0
  126. package/dist/core/param-rule-reach.js +30 -0
  127. package/dist/core/parent-spec-seat.d.ts +8 -1
  128. package/dist/core/parent-spec-seat.js +4 -0
  129. package/dist/core/pause-registry.d.ts +16 -5
  130. package/dist/core/pause-registry.js +6 -2
  131. package/dist/core/peer-channel.d.ts +70 -0
  132. package/dist/core/peer-channel.js +1 -0
  133. package/dist/core/permission-rule-consent.d.ts +11 -5
  134. package/dist/core/permission-rule-consent.js +37 -30
  135. package/dist/core/permission-rule-model.d.ts +233 -64
  136. package/dist/core/permission-rule-model.js +384 -85
  137. package/dist/core/permission-rule-provider.d.ts +2 -1
  138. package/dist/core/permission-rule-store.d.ts +20 -25
  139. package/dist/core/permission-rule-store.js +1 -4
  140. package/dist/core/permission-rule-sync.d.ts +11 -2
  141. package/dist/core/permission-rule-sync.js +8 -1
  142. package/dist/core/permission-rules.d.ts +49 -11
  143. package/dist/core/permission-rules.js +123 -89
  144. package/dist/core/persisted-rule-arms.d.ts +4 -2
  145. package/dist/core/present-plan-tool.js +3 -1
  146. package/dist/core/protocol-naming.d.ts +2 -2
  147. package/dist/core/read-only-shell-table.d.ts +1 -1
  148. package/dist/core/read-only-shell.d.ts +1 -1
  149. package/dist/core/roles.d.ts +6 -2
  150. package/dist/core/roles.js +45 -44
  151. package/dist/core/rule-offer-read.d.ts +53 -0
  152. package/dist/core/rule-offer-read.js +146 -0
  153. package/dist/core/rule-owner.d.ts +46 -0
  154. package/dist/core/rule-owner.js +28 -0
  155. package/dist/core/runner/advisor-instructions.d.ts +70 -0
  156. package/dist/core/runner/advisor-instructions.js +61 -0
  157. package/dist/core/runner/advisor-tool.d.ts +33 -0
  158. package/dist/core/runner/advisor-tool.js +112 -0
  159. package/dist/core/runner/announce-once-ledger.d.ts +4 -26
  160. package/dist/core/runner/announce-once-ledger.js +14 -46
  161. package/dist/core/runner/approval-feedback.js +6 -3
  162. package/dist/core/runner/assemble-result.d.ts +1 -1
  163. package/dist/core/runner/caller-roster.d.ts +7 -0
  164. package/dist/core/runner/caller-roster.js +11 -0
  165. package/dist/core/runner/classifier-ladder.d.ts +27 -5
  166. package/dist/core/runner/classifier-ladder.js +12 -11
  167. package/dist/core/runner/compaction-restate.d.ts +10 -6
  168. package/dist/core/runner/compaction-restate.js +9 -3
  169. package/dist/core/runner/contracts.d.ts +13 -9
  170. package/dist/core/runner/conversation-segment.d.ts +28 -0
  171. package/dist/core/runner/conversation-segment.js +42 -0
  172. package/dist/core/runner/cross-boundary-lane.d.ts +6 -5
  173. package/dist/core/runner/cross-boundary-lane.js +26 -15
  174. package/dist/core/runner/decide-continuation.d.ts +7 -4
  175. package/dist/core/runner/decide-continuation.js +2 -2
  176. package/dist/core/runner/denial-limit-arms.d.ts +2 -2
  177. package/dist/core/runner/derived-route-fallback.d.ts +24 -24
  178. package/dist/core/runner/derived-route-fallback.js +9 -7
  179. package/dist/core/runner/gate-exit.d.ts +6 -0
  180. package/dist/core/runner/gate-exit.js +7 -2
  181. package/dist/core/runner/initial-run-state.js +1 -1
  182. package/dist/core/runner/permission-rule-lanes.d.ts +2 -2
  183. package/dist/core/runner/permission-rule-lanes.js +14 -7
  184. package/dist/core/runner/person-path-rows.js +1 -1
  185. package/dist/core/runner/prepare-advisor.d.ts +63 -0
  186. package/dist/core/runner/prepare-advisor.js +77 -0
  187. package/dist/core/runner/prepare-caps-and-workflow.js +1 -1
  188. package/dist/core/runner/prepare-config-doors.d.ts +6 -4
  189. package/dist/core/runner/prepare-config-doors.js +18 -12
  190. package/dist/core/runner/prepare-delegation-surface.d.ts +2 -2
  191. package/dist/core/runner/prepare-delegation-surface.js +1 -1
  192. package/dist/core/runner/prepare-file-history.js +39 -39
  193. package/dist/core/runner/prepare-gate-stations.d.ts +1 -4
  194. package/dist/core/runner/prepare-gate-stations.js +2 -7
  195. package/dist/core/runner/prepare-inherited-gate.d.ts +5 -4
  196. package/dist/core/runner/prepare-inherited-gate.js +3 -3
  197. package/dist/core/runner/prepare-park-ask.js +7 -7
  198. package/dist/core/runner/prepare-policy-chain.d.ts +1 -1
  199. package/dist/core/runner/prepare-policy-chain.js +4 -10
  200. package/dist/core/runner/prepare-project-context.d.ts +5 -2
  201. package/dist/core/runner/prepare-project-context.js +6 -3
  202. package/dist/core/runner/prepare-prompt-inputs.js +1 -1
  203. package/dist/core/runner/prepare-protocol-tools.d.ts +2 -2
  204. package/dist/core/runner/prepare-protocol-tools.js +3 -2
  205. package/dist/core/runner/prepare-safety-scan.d.ts +9 -12
  206. package/dist/core/runner/prepare-safety-scan.js +8 -6
  207. package/dist/core/runner/prepare-task.js +15 -18
  208. package/dist/core/runner/prepare-tool-disclosure-mount.js +6 -4
  209. package/dist/core/runner/prepare-wiring-manifest.d.ts +6 -3
  210. package/dist/core/runner/prepare-wiring-manifest.js +2 -2
  211. package/dist/core/runner/resume-policy-outcome.js +1 -1
  212. package/dist/core/runner/retired-runner-deps.js +1 -1
  213. package/dist/core/runner/run-attachment-seats.js +0 -1
  214. package/dist/core/runner/run-compaction-machinery.d.ts +1 -1
  215. package/dist/core/runner/run-compaction-machinery.js +2 -12
  216. package/dist/core/runner/run-git-lane.d.ts +1 -0
  217. package/dist/core/runner/run-harness-handlers.js +2 -3
  218. package/dist/core/runner/run-leg.js +13 -0
  219. package/dist/core/runner/run-settle-and-teardown.js +1 -1
  220. package/dist/core/runner/run-telemetry-and-budget-seats.js +1 -1
  221. package/dist/core/runner/run-turn-boundary.d.ts +1 -0
  222. package/dist/core/runner/run-turn-boundary.js +14 -12
  223. package/dist/core/runner/session-rule-policy.d.ts +22 -21
  224. package/dist/core/runner/session-rule-policy.js +13 -28
  225. package/dist/core/runner/side-call-account.d.ts +32 -8
  226. package/dist/core/runner/side-call-account.js +23 -1
  227. package/dist/core/runner/strict-output-schema.d.ts +1 -1
  228. package/dist/core/runner/sub-agent-deny-lists.js +4 -3
  229. package/dist/core/runner/synthetic-tools.d.ts +10 -13
  230. package/dist/core/runner/synthetic-tools.js +4 -2
  231. package/dist/core/runner/tool-disclosure.js +2 -1
  232. package/dist/core/runner/tool-face-overlay.d.ts +2 -1
  233. package/dist/core/runner/tool-face-overlay.js +17 -1
  234. package/dist/core/runner/tool-progress-lane.d.ts +2 -2
  235. package/dist/core/runner/tool-turn-repair-seat.d.ts +3 -2
  236. package/dist/core/runner/turn-attachments.d.ts +60 -67
  237. package/dist/core/runner-deps.d.ts +37 -37
  238. package/dist/core/runtime-caps.d.ts +4 -4
  239. package/dist/core/safety-merge-corpus.js +17 -1
  240. package/dist/core/same-plain-value.d.ts +40 -0
  241. package/dist/core/same-plain-value.js +49 -0
  242. package/dist/core/scheduler.d.ts +1 -1
  243. package/dist/core/sensitive-path-policy.d.ts +1 -1
  244. package/dist/core/sensitive-path-policy.js +1 -1
  245. package/dist/core/session-policy-store.d.ts +77 -22
  246. package/dist/core/session-policy-store.js +56 -14
  247. package/dist/core/session-reconcile.d.ts +2 -2
  248. package/dist/core/session-store.d.ts +80 -30
  249. package/dist/core/session-store.js +118 -76
  250. package/dist/core/session.d.ts +24 -46
  251. package/dist/core/shared-memory/tools.js +3 -1
  252. package/dist/core/shared-memory/types.d.ts +1 -1
  253. package/dist/core/side-query.d.ts +10 -0
  254. package/dist/core/side-query.js +5 -0
  255. package/dist/core/store-contracts/checkpoint-store-contract.js +29 -2
  256. package/dist/core/store-contracts/file-history-store-contract.js +43 -3
  257. package/dist/core/store-contracts/session-policy-store-contract.d.ts +7 -0
  258. package/dist/core/store-contracts/session-policy-store-contract.js +130 -0
  259. package/dist/core/store-contracts/session-repo-contract.js +125 -0
  260. package/dist/core/store-contracts/session-store-contract.d.ts +4 -7
  261. package/dist/core/store-contracts/session-store-contract.js +215 -41
  262. package/dist/core/store-contracts/workflow-journal-store-contract.js +26 -1
  263. package/dist/core/surrogate-safe-slice.d.ts +3 -3
  264. package/dist/core/task-event.d.ts +10 -4
  265. package/dist/core/task-notification.d.ts +3 -3
  266. package/dist/core/task-registry-agent.d.ts +4 -4
  267. package/dist/core/task-registry-shared.d.ts +4 -4
  268. package/dist/core/task-registry-shared.js +1 -0
  269. package/dist/core/task-registry.d.ts +4 -4
  270. package/dist/core/task-registry.js +3 -1
  271. package/dist/core/task-result.d.ts +3 -3
  272. package/dist/core/task-spec.d.ts +52 -52
  273. package/dist/core/task-stream.d.ts +6 -6
  274. package/dist/core/task-tool-shape.d.ts +4 -4
  275. package/dist/core/tighten-task-spec.d.ts +1 -1
  276. package/dist/core/tool-catalog-entries.d.ts +19 -2
  277. package/dist/core/tool-catalog-entries.js +57 -42
  278. package/dist/core/tool-conformance.js +1 -0
  279. package/dist/core/tool-errors.d.ts +2 -2
  280. package/dist/core/tool-face-reader.js +5 -3
  281. package/dist/core/tool-face.d.ts +21 -2
  282. package/dist/core/tool-face.js +1 -1
  283. package/dist/core/tool-model-gate.d.ts +3 -3
  284. package/dist/core/tool-name-aliases.d.ts +29 -8
  285. package/dist/core/tool-name-aliases.js +27 -3
  286. package/dist/core/tool-name-readings.d.ts +5 -8
  287. package/dist/core/tool-name-readings.js +1 -2
  288. package/dist/core/tool-policy.d.ts +24 -5
  289. package/dist/core/tool-policy.js +34 -10
  290. package/dist/core/tool-registry.d.ts +14 -7
  291. package/dist/core/tool-registry.js +17 -7
  292. package/dist/core/tool-result-store.js +2 -1
  293. package/dist/core/tool-roster.d.ts +47 -18
  294. package/dist/core/tool-roster.js +53 -32
  295. package/dist/core/tool-spec-members.js +1 -1
  296. package/dist/core/tool-spec.d.ts +35 -21
  297. package/dist/core/tools.js +3 -2
  298. package/dist/core/trace.d.ts +4 -0
  299. package/dist/core/untrusted-egress.d.ts +1 -1
  300. package/dist/core/untrusted-text.d.ts +1 -1
  301. package/dist/core/warm-resume.d.ts +1 -1
  302. package/dist/core/wiring-manifest.d.ts +49 -0
  303. package/dist/core/wiring-manifest.js +13 -5
  304. package/dist/core/workflow-journal-store.d.ts +62 -0
  305. package/dist/core/workflow-journal-store.js +77 -1
  306. package/dist/core/workflow-run-store.d.ts +6 -0
  307. package/dist/core/workflow-run-store.js +2 -0
  308. package/dist/engine/compaction/compaction.d.ts +9 -9
  309. package/dist/engine/execution-env/node-execution-env.d.ts +19 -5
  310. package/dist/engine/execution-env/node-execution-env.js +43 -22
  311. package/dist/engine/harness/agent-harness.d.ts +14 -8
  312. package/dist/engine/harness/agent-harness.js +33 -26
  313. package/dist/engine/harness/types.d.ts +29 -7
  314. package/dist/engine/harness/types.js +12 -1
  315. package/dist/engine/llm/types.d.ts +9 -9
  316. package/dist/engine/llm/validation.d.ts +4 -1
  317. package/dist/engine/llm/validation.js +13 -1
  318. package/dist/engine/loop/agent-loop.d.ts +1 -1
  319. package/dist/engine/loop/agent-loop.js +10 -8
  320. package/dist/engine/loop/types.d.ts +15 -13
  321. package/dist/engine/lsp/node-lsp-manager.d.ts +2 -2
  322. package/dist/engine/session/memory-repo.d.ts +10 -11
  323. package/dist/engine/session/memory-repo.js +13 -8
  324. package/dist/engine/session/parent-chain-guard.d.ts +3 -2
  325. package/dist/engine/session/parent-chain-guard.js +1 -1
  326. package/dist/engine/session/repo-utils.d.ts +31 -3
  327. package/dist/engine/session/repo-utils.js +42 -5
  328. package/dist/index.d.ts +27 -15
  329. package/dist/index.js +21 -11
  330. package/dist/internal/harness-types.d.ts +1 -1
  331. package/dist/internal/harness.d.ts +3 -3
  332. package/dist/internal/harness.js +2 -2
  333. package/dist/internal/llm.d.ts +1 -1
  334. package/dist/internal/llm.js +1 -1
  335. package/dist/orchestration/goal.js +2 -2
  336. package/dist/orchestration/run-workflow-tool.d.ts +2 -2
  337. package/dist/orchestration/run-workflow-tool.js +5 -3
  338. package/dist/orchestration/workflow-size-guideline.d.ts +4 -4
  339. package/dist/orchestration/workflow-types.d.ts +18 -0
  340. package/dist/orchestration/workflow-types.js +6 -0
  341. package/dist/orchestration/workflow.d.ts +2 -13
  342. package/dist/orchestration/workflow.js +21 -31
  343. package/dist/prompt-assembly/event-registry.js +1 -0
  344. package/dist/prompt-assembly/tool-catalog.d.ts +3 -0
  345. package/dist/prompt-assembly/tool-catalog.js +3 -0
  346. package/dist/prompts/default.d.ts +14 -14
  347. package/dist/scenarios/full-body.d.ts +4 -4
  348. package/dist/stores/file/adoption/adopt.d.ts +4 -3
  349. package/dist/stores/file/adoption/adopt.js +24 -31
  350. package/dist/stores/file/adoption/marker.d.ts +6 -13
  351. package/dist/stores/file/adoption/marker.js +6 -15
  352. package/dist/stores/file/checkpoint-store.d.ts +3 -0
  353. package/dist/stores/file/checkpoint-store.js +9 -3
  354. package/dist/stores/file/file-history-store.d.ts +20 -19
  355. package/dist/stores/file/file-history-store.js +152 -135
  356. package/dist/stores/file/fs-atomic.d.ts +15 -0
  357. package/dist/stores/file/fs-atomic.js +89 -14
  358. package/dist/stores/file/index.d.ts +1 -1
  359. package/dist/stores/file/mailbox-store.d.ts +3 -0
  360. package/dist/stores/file/mailbox-store.js +3 -1
  361. package/dist/stores/file/permission-rule-adopt.d.ts +1 -1
  362. package/dist/stores/file/permission-rule-adopt.js +15 -16
  363. package/dist/stores/file/permission-rule-store.d.ts +18 -2
  364. package/dist/stores/file/permission-rule-store.js +21 -14
  365. package/dist/stores/file/session-policy-store.d.ts +3 -3
  366. package/dist/stores/file/session-store.d.ts +26 -11
  367. package/dist/stores/file/session-store.js +77 -40
  368. package/dist/stores/file/workflow-journal-store.d.ts +10 -4
  369. package/dist/stores/file/workflow-journal-store.js +28 -13
  370. package/dist/tools/artifact/artifact-text.d.ts +1 -1
  371. package/dist/tools/artifact/artifact-tool.js +2 -1
  372. package/dist/tools/fs/bash-readonly-classifier.d.ts +3 -3
  373. package/dist/tools/fs/fs-bash.d.ts +2 -2
  374. package/dist/tools/fs/fs-bash.js +3 -1
  375. package/dist/tools/fs/fs-shared.d.ts +8 -8
  376. package/dist/tools/fs/gh-rate-limit.d.ts +1 -1
  377. package/dist/tools/fs/notebook.d.ts +2 -2
  378. package/dist/tools/fs/read-deny.d.ts +29 -7
  379. package/dist/tools/fs/read-deny.js +63 -22
  380. package/dist/tools/fs/removal-targets.d.ts +1 -1
  381. package/dist/tools/fs/safety.d.ts +9 -9
  382. package/dist/tools/fs/search.d.ts +6 -6
  383. package/dist/tools/fs/shell-read-check.js +6 -1
  384. package/dist/tools/fs/shell-read-judge.d.ts +4 -0
  385. package/dist/tools/fs/shell-read-judge.js +5 -2
  386. package/dist/tools/loop-tick.d.ts +2 -2
  387. package/dist/tools/scheduler-tools.js +5 -1
  388. package/dist/tools/task-list.d.ts +7 -7
  389. package/dist/tools/task-list.js +5 -1
  390. package/dist/tools/todo.js +2 -1
  391. package/dist/tools/web.d.ts +1 -1
  392. package/dist/tools/web.js +40 -37
  393. package/dist/tools/worktree.d.ts +3 -3
  394. package/dist/tools/worktree.js +3 -1
  395. package/package.json +1 -1
  396. package/test/export-surface.snapshot.json +5756 -5638
  397. package/wire-changes/core@7.55.0.json +3318 -0
  398. package/dist/core/store-contracts/session-store-incarnation-contract.d.ts +0 -39
  399. package/dist/core/store-contracts/session-store-incarnation-contract.js +0 -95
@@ -60,7 +60,8 @@ export interface PeerSessionRecord {
60
60
  intent?: string;
61
61
  entrypoint?: string;
62
62
  peerProtocol?: number;
63
- /** CC capability bits (`/^[a-z0-9_]{1,32}$/`, ≤16); `sema_mailbox_v1` marks a store-lane peer. */
63
+ /** CC capability bits (`/^[a-z0-9_]{1,32}$/`, ≤16); a `sema_mailbox_v1_<hex>` bit names the mailbox store the
64
+ * session drains ({@link semaMailboxFeature}, read by {@link peerSessionLane}). */
64
65
  peerFeatures?: readonly string[];
65
66
  sockPath?: string;
66
67
  /** CC `cross_session_inbound: available|unavailable` — the session's SELF-REPORTED inbound posture.
@@ -68,6 +69,26 @@ export interface PeerSessionRecord {
68
69
  * drain point decides. */
69
70
  inboundPosture?: "available" | "unavailable";
70
71
  }
72
+ /** The prefix of the capability bit a session of this engine advertises in its row's `peerFeatures`; the
73
+ * rest of the bit names the mailbox store the session drains ({@link semaMailboxFeature}). The reference's
74
+ * bit grammar is `/^[a-z0-9_]{1,32}$/` and it ignores bits it does not know. */
75
+ export declare const SEMA_MAILBOX_FEATURE_PREFIX = "sema_mailbox_v1_";
76
+ /** The capability bit for a session that drains the store whose `MailboxStore.identity` is `storeIdentity`:
77
+ * the prefix and the first 16 hex of the identity's sha-256 (32 characters, within the bit grammar). */
78
+ export declare function semaMailboxFeature(storeIdentity: string): string;
79
+ /** How a message reaches a peer: its durable session box (`store`), or the reference agent's socket
80
+ * dialect (`uds` — the message itself crosses the socket, at-most-once). */
81
+ export type PeerSessionLane = "store" | "uds";
82
+ /**
83
+ * THE lane reading of a directory row, for a sender whose mailbox store is `ownStore`. A row with no socket
84
+ * has no other lane: the box (the host's directory vouches that its sessions drain the host's store). A row
85
+ * with a socket is reached through the box only when its bit names the SENDER's store — the one place a
86
+ * parked message is provably read; every other row with a socket (a reference-agent session, a session of
87
+ * this engine draining another store, a store that cannot say what it is) is reached over its socket.
88
+ */
89
+ export declare function peerSessionLane(record: Pick<PeerSessionRecord, "sockPath" | "peerFeatures">, ownStore: {
90
+ readonly identity?: string;
91
+ } | undefined): PeerSessionLane;
71
92
  /** The box-address prefix of a session box (design/385 §2.2 — the dot form: `:` is outside the file
72
93
  * backend's path charset, `.` is inside it and outside the a* handle grammar). */
73
94
  export declare const SESSION_BOX_PREFIX = "session.";
@@ -204,9 +225,11 @@ export interface InMemoryPeerDirectory extends PeerDirectory {
204
225
  restorePeerSession(record: PeerSessionRecord): boolean;
205
226
  }
206
227
  export declare function createInMemoryPeerDirectory(): InMemoryPeerDirectory;
207
- /** The closed refusal set of the registry-directory ancestor-chain vetting. Each ancestor from the
208
- * directory up to the filesystem root must be a real directory (no symlink on the chain — a shared
209
- * /tmp lets another uid pre-plant one), owned by this uid, and not group/world-writable. */
228
+ /** The closed refusal set of the registry-directory vetting (a shared /tmp lets another uid pre-plant a
229
+ * directory or a link on the chain). The reference's nine refusal kinds land on these six: its
230
+ * `directory_rule` is `foreign_owner` or `group_or_world_writable` by which half failed, `leaf_shape` is
231
+ * `symlink` / `not_directory` / `foreign_owner`, `dangling_link` is `missing`, `symlink_loop` is
232
+ * `symlink`, `internal` (a relative path) is `not_absolute`. */
210
233
  export type PeerRegistryDirectoryRefusal = "not_absolute" | "missing" | "symlink" | "not_directory" | "foreign_owner" | "group_or_world_writable";
211
234
  export type PeerRegistryDirectoryVerdict = {
212
235
  ok: true;
@@ -215,11 +238,22 @@ export type PeerRegistryDirectoryVerdict = {
215
238
  code: PeerRegistryDirectoryRefusal;
216
239
  path: string;
217
240
  };
218
- /** Vet a registry directory and every ancestor. `uid` defaults to the process uid; on a platform with
219
- * no uid (win32) the owner arm is skipped. Refuses on the FIRST failing ancestor (closest first).
220
- * `platform` (default: this process's) decides whether the permission bits are judged at all
221
- * ({@link posixModeBitsMeaningful}): where they are not meaningful the group/world-writable arm is skipped,
222
- * and nothing in this verdict says so — the caller that reads it owns any disclosure. */
241
+ /**
242
+ * Vet a registry (or sockets) directory and every ancestor — the reference's rules (CC 2.1.296, `directory_rule` (cli296.js:274840); sockets-
243
+ * directory vetting):
244
+ * - the directory ITSELF must be a real directory (never a link), owned by this uid, with no group/world
245
+ * write bit;
246
+ * - every ANCESTOR must be owned by this uid or by root, and be either free of group/world write bits or
247
+ * sticky (`/tmp` is root-owned and sticky by design);
248
+ * - an ancestor that is a LINK owned by this uid or by root is followed, and its target's chain is judged
249
+ * by the same rules (macOS `/var` and `/tmp` are root-owned links); a link anyone else owns refuses,
250
+ * and more than {@link VET_MAX_LINK_DEPTH} links is a loop.
251
+ * `uid` defaults to the process uid; on a platform with no uid (win32) the owner arms are skipped.
252
+ * Refuses on the FIRST failing component (closest first). `platform` (default: this process's) decides
253
+ * whether the permission bits are judged at all ({@link posixModeBitsMeaningful}): where they are not
254
+ * meaningful the mode arms are skipped, and nothing in this verdict says so — the caller that reads it
255
+ * owns any disclosure. `stopAt` names an ancestor at which the walk ends unjudged.
256
+ */
223
257
  export declare function vetPeerRegistryDirectory(dir: string, opts?: {
224
258
  uid?: number;
225
259
  stopAt?: string;
@@ -1,4 +1,6 @@
1
- import { lstat } from "node:fs/promises";
1
+ import { createHash } from "node:crypto";
2
+ import { lstat, readlink } from "node:fs/promises";
3
+ import { physicalPathOfAsync } from "../core/physical-path.js";
2
4
  import { isAbsolute, dirname, resolve as resolvePath } from "node:path";
3
5
  import { formatPeerNameRef, mintPeerRef, normalizePeerName, parsePeerNameRef, PEER_REF_RE } from "./cross-session-ref.js";
4
6
  import { inlineUntrusted } from "../core/untrusted-text.js";
@@ -17,6 +19,16 @@ export function assertPeerPresenceValue(v) {
17
19
  e.code = "config.peer_presence_invalid";
18
20
  throw e;
19
21
  }
22
+ export const SEMA_MAILBOX_FEATURE_PREFIX = "sema_mailbox_v1_";
23
+ export function semaMailboxFeature(storeIdentity) {
24
+ return `${SEMA_MAILBOX_FEATURE_PREFIX}${createHash("sha256").update(storeIdentity).digest("hex").slice(0, 16)}`;
25
+ }
26
+ export function peerSessionLane(record, ownStore) {
27
+ if (record.sockPath === undefined)
28
+ return "store";
29
+ const identity = ownStore?.identity;
30
+ return typeof identity === "string" && identity !== "" && (record.peerFeatures ?? []).includes(semaMailboxFeature(identity)) ? "store" : "uds";
31
+ }
20
32
  export const SESSION_BOX_PREFIX = "session.";
21
33
  const SESSION_ID_RE = /^[A-Za-z0-9_-]{1,80}$/;
22
34
  export const PEER_SESSION_ID_GRAMMAR = "^[A-Za-z0-9_-]{1,80}$";
@@ -249,37 +261,68 @@ export function createInMemoryPeerDirectory() {
249
261
  },
250
262
  };
251
263
  }
264
+ const VET_MAX_LINK_DEPTH = 16;
252
265
  export async function vetPeerRegistryDirectory(dir, opts) {
253
266
  if (!isAbsolute(dir))
254
267
  return { ok: false, code: "not_absolute", path: dir };
255
268
  const uid = opts?.uid ?? (typeof process.getuid === "function" ? process.getuid() : undefined);
256
269
  const judgeModeBits = posixModeBitsMeaningful(opts?.platform);
257
270
  const stopAt = opts?.stopAt !== undefined ? resolvePath(opts.stopAt) : undefined;
258
- let cursor = resolvePath(dir);
259
- for (;;) {
260
- let st;
261
- try {
262
- st = await lstat(cursor);
263
- }
264
- catch {
265
- return { ok: false, code: "missing", path: cursor };
266
- }
267
- if (st.isSymbolicLink())
268
- return { ok: false, code: "symlink", path: cursor };
269
- if (!st.isDirectory())
270
- return { ok: false, code: "not_directory", path: cursor };
271
- const parent = dirname(cursor);
272
- const isRoot = parent === cursor || (stopAt !== undefined && cursor === stopAt);
273
- if (!isRoot) {
274
- if (uid !== undefined && st.uid !== uid)
271
+ const leaf = resolvePath(dir);
272
+ let st;
273
+ try {
274
+ st = await lstat(leaf);
275
+ }
276
+ catch {
277
+ return { ok: false, code: "missing", path: leaf };
278
+ }
279
+ if (st.isSymbolicLink())
280
+ return { ok: false, code: "symlink", path: leaf };
281
+ if (!st.isDirectory())
282
+ return { ok: false, code: "not_directory", path: leaf };
283
+ if (uid !== undefined && st.uid !== uid)
284
+ return { ok: false, code: "foreign_owner", path: leaf };
285
+ if (judgeModeBits && (st.mode & 0o022) !== 0)
286
+ return { ok: false, code: "group_or_world_writable", path: leaf };
287
+ const ownerOk = (owner) => uid === undefined || owner === uid || owner === 0;
288
+ const vetAncestors = async (from, depth) => {
289
+ for (let cursor = from;; cursor = dirname(cursor)) {
290
+ if (dirname(cursor) === cursor || (stopAt !== undefined && cursor === stopAt))
291
+ return { ok: true };
292
+ let a;
293
+ try {
294
+ a = await lstat(cursor);
295
+ }
296
+ catch {
297
+ return { ok: false, code: "missing", path: cursor };
298
+ }
299
+ if (a.isSymbolicLink()) {
300
+ if (!ownerOk(a.uid))
301
+ return { ok: false, code: "foreign_owner", path: cursor };
302
+ if (depth >= VET_MAX_LINK_DEPTH)
303
+ return { ok: false, code: "symlink", path: cursor };
304
+ let target;
305
+ try {
306
+ const link = await readlink(cursor);
307
+ target = isAbsolute(link) ? link : resolvePath(await physicalPathOfAsync(dirname(cursor)), link);
308
+ }
309
+ catch {
310
+ return { ok: false, code: "missing", path: cursor };
311
+ }
312
+ const followed = await vetAncestors(resolvePath(target), depth + 1);
313
+ if (!followed.ok)
314
+ return followed;
315
+ continue;
316
+ }
317
+ if (!a.isDirectory())
318
+ return { ok: false, code: "not_directory", path: cursor };
319
+ if (!ownerOk(a.uid))
275
320
  return { ok: false, code: "foreign_owner", path: cursor };
276
- if (judgeModeBits && (st.mode & 0o022) !== 0)
321
+ if (judgeModeBits && (a.mode & 0o1000) === 0 && (a.mode & 0o022) !== 0)
277
322
  return { ok: false, code: "group_or_world_writable", path: cursor };
278
323
  }
279
- if (isRoot)
280
- return { ok: true };
281
- cursor = parent;
282
- }
324
+ };
325
+ return vetAncestors(dirname(leaf), 0);
283
326
  }
284
327
  export function judgePeerRecordFile(stat, selfUid, platform) {
285
328
  if (!stat.isFile)
@@ -47,7 +47,7 @@ export declare const PEER_DELIVERY_RECEIPT_STATES: readonly ["held", "denied", "
47
47
  export type PeerDeliveryReceiptState = (typeof PEER_DELIVERY_RECEIPT_STATES)[number];
48
48
  export declare function isPeerDeliveryReceiptState(v: unknown): v is PeerDeliveryReceiptState;
49
49
  /**
50
- * The drop reasons a `dropped` receipt may carry (CC vocabulary, kept verbatim — the recipient's ingress guard).
50
+ * The drop reasons a `dropped` receipt may carry (vocabulary kept as is — the recipient's ingress guard).
51
51
  *
52
52
  * `queue-full` is a member of the set but is NOT minted by this engine today: CC judges "recipient's queue
53
53
  * is at its limit" on the recipient's ingress and reports it back as a dropped receipt, whereas here the
@@ -10,6 +10,7 @@ import { createListAgentsTool, type ListAgentsReadSeats } from "./list-agents-to
10
10
  import { foldPermissionModeClass } from "./cross-session-judge.js";
11
11
  import type { AskEffective } from "../core/wiring-manifest.js";
12
12
  import type { SendMessageToolOptions } from "./send-message-tool.js";
13
+ import type { PeerChannel } from "../core/peer-channel.js";
13
14
  import { type PeerClock, type PeerHeldQueue } from "./peer-held-queue.js";
14
15
  import { type PeerIdleMachine } from "./peer-idle.js";
15
16
  /** design/385 §1.2④ — the drain lease TTL. Same sizing law as the tier-3 revive lease: well under the
@@ -232,12 +233,13 @@ export declare function announcePeerLaneMount(deps: {
232
233
  * this session's identity/attestation, whose mode class folds LIVE off the manifest's ask derivation. */
233
234
  export declare function peerLaneSendMessageSeats(args: {
234
235
  peerDirectory: PeerDirectory;
236
+ peerChannel?: PeerChannel;
235
237
  sessionId: string;
236
238
  scope: string;
237
239
  name?: string;
238
240
  refs: PeerLaneRefs;
239
241
  listingMounted?: boolean;
240
- }): Pick<SendMessageToolOptions, "peerDirectory" | "peerSelfSession" | "peerListingMounted">;
242
+ }): Pick<SendMessageToolOptions, "peerDirectory" | "peerChannel" | "peerSelfSession" | "peerListingMounted">;
241
243
  /**
242
244
  * design/385 §5.1 — THE ListAgents mount predicate, single source: the built-in mounts only when the
243
245
  * leg's tool valve leaves it (`leaves`: the valve's one reading, `valveLeaves`) and no caller tool owns either spelling
@@ -763,6 +763,7 @@ export function announcePeerLaneMount(deps, leg) {
763
763
  export function peerLaneSendMessageSeats(args) {
764
764
  return {
765
765
  peerDirectory: args.peerDirectory,
766
+ ...(args.peerChannel !== undefined ? { peerChannel: args.peerChannel } : {}),
766
767
  ...(args.listingMounted !== undefined ? { peerListingMounted: args.listingMounted } : {}),
767
768
  peerSelfSession: {
768
769
  sessionId: args.sessionId,
@@ -1,7 +1,7 @@
1
1
  import { Type } from "typebox";
2
2
  import { defineTool } from "../core/tools.js";
3
3
  import { renderTaskNotificationXml } from "../core/task-notification.js";
4
- import { toolFace } from "../core/tool-catalog-entries.js";
4
+ import { mountRuleFace, toolFace } from "../core/tool-catalog-entries.js";
5
5
  export const READ_INBOX_TOOL_NAME = "ReadInbox";
6
6
  export const READ_INBOX_MAX_LIMIT = 50;
7
7
  export const READ_INBOX_RESULT_BUDGET_CHARS = 20_000;
@@ -9,6 +9,7 @@ export function createReadInboxTool(opts) {
9
9
  return defineTool({
10
10
  name: READ_INBOX_TOOL_NAME,
11
11
  ...toolFace("read-inbox"),
12
+ ruleFace: mountRuleFace("read-inbox"),
12
13
  ...(opts.coversPrincipalInbox === true ? { contentOrigin: "external" } : {}),
13
14
  isConcurrencySafe: () => false,
14
15
  description: `Read the cross-session messages waiting in this session's inbox now, instead of waiting for them to arrive at your next turn boundaries. ` +
@@ -67,7 +67,7 @@ export interface SubagentRetainEntry {
67
67
  };
68
68
  /** The in-flight resume run's abort controller (parent-terminal cleanup aborts it — r1-M2). */
69
69
  activeAbort?: AbortController;
70
- /** Unpin + explicitly release the retained session (best-effort; the TTL reaper is the backstop). */
70
+ /** Unpin + explicitly release the retained session (best-effort: a release that rejects leaves the session standing and nothing retries it — a detached eviction's rejection reaches `RetainLedgerHooks.onEvictionError`; a damaged placed row needs manual cleanup, see TtlSessionStore.release). */
71
71
  release: () => Promise<void>;
72
72
  }
73
73
  /**
@@ -15,7 +15,7 @@ export interface RosterEntry {
15
15
  rootSessionId?: string;
16
16
  /** design/151 S3b — the model RECORD KEY at spawn (revival lookup key; display/model-routing hints
17
17
  * only, never a serialized spec). NOT the resolved model id: a spawn that named a model in WORDS
18
- * records the caller's spelling VERBATIM (a catalog key, tier word or CC alias), because a revival
18
+ * records the caller's spelling as given (a catalog key, tier word or alias), because a revival
19
19
  * re-resolves this value against the catalog in force at WAKE time and a resolved id would only
20
20
  * ever resolve again on deployments whose catalog keys happen to equal model ids. A spawn that
21
21
  * carried a Model OBJECT (definition/tool-level/inherited ref) records that object's id, which on
@@ -5,6 +5,7 @@ import { type ToolCtxEnricher } from "../core/tools.js";
5
5
  import { type TaskAccess } from "../core/task-registry.js";
6
6
  import type { PermissionModeClass } from "./cross-session-envelope.js";
7
7
  import { type PeerDirectory } from "./peer-directory.js";
8
+ import type { PeerChannel } from "../core/peer-channel.js";
8
9
  import { SubagentRetainLedger } from "./retain-ledger.js";
9
10
  import { type SubagentSteerHandle } from "./subagent.js";
10
11
  import { type PeerLaneConfig, type PeerInboundChainRef, type PeerSelfRef } from "./peer-admission.js";
@@ -192,6 +193,15 @@ export interface SendMessageToolOptions {
192
193
  * "no agent matches"). Absent ⇒ byte-identical pre-385 behavior.
193
194
  */
194
195
  peerDirectory?: PeerDirectory;
196
+ /**
197
+ * The socket channel ({@link import("../core/types.js").RunnerDeps.peerChannel}). The
198
+ * peer leg reads each resolved row's lane against {@link mailbox} ({@link peerSessionLane}): a row whose
199
+ * bit names this store keeps the box append and then gets a content-free doorbell on its socket (when it is
200
+ * live); any other row with a socket gets the message itself over the socket, at-most-once
201
+ * (`via: "uds"`). Absent: such a row refuses `peer_send.not_reachable` — no box append for a session that
202
+ * does not drain this store; a row without a socket is unchanged.
203
+ */
204
+ peerChannel?: PeerChannel;
195
205
  /**
196
206
  * design/385 — THIS session's own identity on the cross-session lane: its session id (the sender's
197
207
  * `from-session` / reply address, and the self-target guard), the scope its directory rows live in,
@@ -6,7 +6,7 @@ import { announceTranscriptIntegrityGapOnce, canAccessAgentRecord, clearRevivedR
6
6
  import { uuidv7 } from "../internal/harness.js";
7
7
  import { MAILBOX_TOMBSTONED_RECIPIENT_CODE, mailboxCrossProcessMountVerdict } from "../core/mailbox-store.js";
8
8
  import { peerSendVerdictSeverity } from "./cross-session-judge.js";
9
- import { parsePeerSessionAddress, peerSessionBoxHandle, resolvePeerSessions } from "./peer-directory.js";
9
+ import { parsePeerSessionAddress, peerSessionBoxHandle, peerSessionLane, resolvePeerSessions } from "./peer-directory.js";
10
10
  import { peerIdleMachineFor } from "./peer-idle.js";
11
11
  import { PEER_IDLE_OUTSTANDING_CAP, PEER_IDLE_SUBSCRIPTION_TTL_MS, peerIdleNoticeLabel } from "./peer-notices.js";
12
12
  import { escapeAttributeValue, escapeEnvelopeTag, isObserverTaskId, OBSERVER_SENDMESSAGE_SENDER_REFUSAL, OBSERVER_SENDMESSAGE_TARGET_REFUSAL, } from "./observer.js";
@@ -15,7 +15,7 @@ import { neutralizePeerBody } from "./cross-session-envelope.js";
15
15
  import { SUBAGENT_RESUME_CAP, SubagentRetainLedger, getSessionRetainLedger } from "./retain-ledger.js";
16
16
  import { createSubagentResume } from "./subagent.js";
17
17
  import { appendHopToken, judgePeerAdmission, peerAxisToken, resolvePeerLaneConfig, PEER_MESSAGE_NOTICE, } from "./peer-admission.js";
18
- import { toolFace } from "../core/tool-catalog-entries.js";
18
+ import { mountRuleFace, toolFace } from "../core/tool-catalog-entries.js";
19
19
  import { thrownText } from "../core/thrown-value.js";
20
20
  import { assertNoRetiredKeys } from "../core/retired-keys.js";
21
21
  import { sliceHeadSafe } from "../core/surrogate-safe-slice.js";
@@ -163,6 +163,7 @@ export function createSendMessageTool(opts) {
163
163
  return defineTool({
164
164
  name: SEND_MESSAGE_TOOL_NAME,
165
165
  ...toolFace("send-message"),
166
+ ruleFace: mountRuleFace("send-message"),
166
167
  executionMode: "parallel",
167
168
  description: `Send a follow-up message to a previously spawned background agent. ` +
168
169
  `Your plain text output is NOT visible to other agents — to communicate, you MUST call this tool. Messages addressed to you are delivered automatically; you don't check an inbox. ` +
@@ -187,7 +188,7 @@ export function createSendMessageTool(opts) {
187
188
  : `Continuing a finished agent requires the run to retain sub-agent sessions; when the session was not ` +
188
189
  `retained (or is no longer held) you get an honest error and should launch a new agent with the needed context instead.`) +
189
190
  (peerLane.active
190
- ? ` Peer SESSIONS — other sessions of this engine for the same user${opts.peerListingMounted === false ? "" : opts.peerListingMounted === true ? " (list them with ListAgents)" : " (list them with ListAgents where that tool is mounted)"} — are addressed by name, by \`name [ref]\` when a name is ambiguous, or by their \`session.<id>\` address. A message to a peer is parked durably in its session box and read at its next turn boundary (an offline peer reads it when it next runs); the receipt confirms the box accepted it, not that the peer acted on it.`
191
+ ? ` Peer SESSIONS — other sessions of this engine for the same user${opts.peerListingMounted === false ? "" : opts.peerListingMounted === true ? " (list them with ListAgents)" : " (list them with ListAgents where that tool is mounted)"} — are addressed by name, by \`name [ref]\` when a name is ambiguous, or by their \`session.<id>\` address. A message to a peer is parked durably in its session box and read at its next turn boundary (an offline peer reads it when it next runs); the receipt confirms the box accepted it, not that the peer acted on it.${opts.peerChannel !== undefined ? " A peer whose box is not in this host's mailbox store — a Claude Code session, or a session of this engine on another store — is reached over its socket instead: nothing is parked for it, the message is sent once and only while it runs, and its receipt says so." : ""}`
191
192
  : ""),
192
193
  parameters: sendMessageParameters,
193
194
  execute: async (args, ctx) => {
@@ -282,6 +283,8 @@ export function createSendMessageTool(opts) {
282
283
  }
283
284
  const modeClass = opts.peerSelfSession?.modeClass?.();
284
285
  const now = Date.now();
286
+ if (peerSessionLane(record, opts.mailbox) === "uds")
287
+ return deliverOverSocket(record, peerLabel, modeClass);
285
288
  let boxFull = false;
286
289
  try {
287
290
  boxFull = (await opts.mailbox.peekCount(peerScope, handle)) >= admissionConfig.maxQueuedPeerMessages;
@@ -343,6 +346,7 @@ export function createSendMessageTool(opts) {
343
346
  }
344
347
  }
345
348
  }
349
+ const doorbell = opts.peerChannel !== undefined && record.sockPath !== undefined && record.liveness === "live" && (seq !== undefined || subscriptionSeq !== undefined) ? await opts.peerChannel.nudge(record.sockPath).catch(() => false) : undefined;
346
350
  let rowRestored = "present";
347
351
  try {
348
352
  const rowsNow = await opts.peerDirectory.listPeerSessions({ scope: peerScope });
@@ -372,7 +376,7 @@ export function createSendMessageTool(opts) {
372
376
  }
373
377
  return {
374
378
  content: `Idle subscription recorded for ${peerLabel} (record seq ${subscriptionSeq}): you will get ONE automated notice when that session next goes idle or exits (one-shot; it expires unheard after ${PEER_IDLE_SUBSCRIPTION_TTL_MS / 3_600_000} h). No message was sent. Do not poll for it; continue with your task.${rowNote}`,
375
- details: { type: "send-message", status: "peer_idle_subscribed", to, address: handle, subscription, ...(subscriptionSeq !== undefined ? { subscriptionSeq } : {}), ...(rowRestored !== "present" ? { directoryRow: rowRestored } : {}) },
379
+ details: { type: "send-message", status: "peer_idle_subscribed", to, address: handle, subscription, ...(subscriptionSeq !== undefined ? { subscriptionSeq } : {}), ...(rowRestored !== "present" ? { directoryRow: rowRestored } : {}), ...(doorbell !== undefined ? { doorbell } : {}) },
376
380
  };
377
381
  }
378
382
  const verdict = { ok: true, disposition: offline ? "parked_offline" : "queued", via: "store" };
@@ -380,7 +384,32 @@ export function createSendMessageTool(opts) {
380
384
  content: offline
381
385
  ? `Message parked for ${peerLabel}: that session is offline, so the message was parked durably in its session box (seq ${seq}) and will be delivered when it next runs — subject to the deployment's mailbox retirement policy, which does not notify you. Continue with your task; do not resend the same content.${subscriptionNote}${rowNote}`
382
386
  : `Message queued for ${peerLabel} (seq ${seq}): it is parked durably in that session's box and will be read at its next turn boundary. This receipt confirms acceptance into the box, not the peer's judgment of the message. Continue with your task; do not resend the same content.${subscriptionNote}${rowNote}`,
383
- details: { type: "send-message", status: offline ? "peer_parked_offline" : "peer_queued", to, address: handle, seq, verdict, ...(subscription !== undefined ? { subscription } : {}), ...(subscriptionSeq !== undefined ? { subscriptionSeq } : {}), ...(rowRestored !== "present" ? { directoryRow: rowRestored } : {}) },
387
+ details: { type: "send-message", status: offline ? "peer_parked_offline" : "peer_queued", to, address: handle, seq, verdict, ...(subscription !== undefined ? { subscription } : {}), ...(subscriptionSeq !== undefined ? { subscriptionSeq } : {}), ...(rowRestored !== "present" ? { directoryRow: rowRestored } : {}), ...(doorbell !== undefined ? { doorbell } : {}) },
388
+ };
389
+ };
390
+ const deliverOverSocket = async (record, peerLabel, modeClass) => {
391
+ if (notifyWhenIdle)
392
+ return peerRefusal("peer_send.invalid_target", `notify_when_idle is only supported for peer sessions that drain this host's mailbox store, and ${peerLabel} is reached over its socket. Nothing was sent.`);
393
+ if (opts.peerChannel === undefined)
394
+ return peerRefusal("peer_send.not_reachable", `${peerLabel} does not drain this host's mailbox store (a Claude Code session, or a session of this engine on another store), so a message parked here would never be read, and no socket channel is wired here to reach it (RunnerDeps.peerChannel). Nothing was sent.`);
395
+ if (record.liveness !== "live")
396
+ return peerRefusal("peer_send.not_reachable", `${peerLabel} is reached only over its socket and is not running; nothing holds a message for it while it is down. Nothing was sent.`);
397
+ const recipientKey = peerAxisToken(peerScope, "s", record.sessionId);
398
+ const sendVerdict = judgePeerAdmission(peerScope, recipientKey, { senderKey, body: message, prospectiveChain, ownTokens: [recipientKey] }, admissionConfig, undefined, "send");
399
+ if (!sendVerdict.ok)
400
+ return admissionRefusal(sendVerdict.reason, peerLabel);
401
+ const verdict = await opts.peerChannel.dial(record.sockPath, {
402
+ body: message,
403
+ ...(peerSelfSessionId !== undefined ? { fromSession: peerSelfSessionId } : {}),
404
+ fromName: ownRowName ?? opts.peerSelfSession?.name ?? senderLabel,
405
+ ...(modeClass === "bypass" || modeClass === "prompting" ? { fromMode: modeClass } : {}),
406
+ hopChain: prospectiveChain,
407
+ });
408
+ if (!verdict.ok)
409
+ return peerRefusal(verdict.code, `${peerLabel} could not be reached over its socket — ${verdict.message}.${verdict.code === "peer_send.send_uncertain" ? " It may have arrived: do not resend the same content blindly." : " Nothing was delivered."}`);
410
+ return {
411
+ content: `Message sent to ${peerLabel} over its socket: it does not drain this host's mailbox store, so nothing is parked here, and the socket answers no acknowledgement — the message was written to its socket once and the connection closed cleanly, which is all this receipt confirms (not that its session took it in, nor that its model read it). Continue with your task; do not resend the same content.`,
412
+ details: { type: "send-message", status: "peer_delivered", to, address: peerSessionBoxHandle(record.sessionId), verdict },
384
413
  };
385
414
  };
386
415
  const settlePeerResolution = async (r) => {
@@ -65,7 +65,7 @@ interface ReviewSample {
65
65
  /** Layered head/middle/tail sample of `text` under `budget`, with each skipped span marked in band so the
66
66
  * reader can see that the material is discontinuous. Exported for tests (window determinism). */
67
67
  export declare function layeredReviewSample(text: string, budget?: number, windows?: number): ReviewSample;
68
- /** Default model-facing name of the delegation tool (CC 2.1.187 `Agent`; legacy alias `Task`). */
68
+ /** Default model-facing name of the delegation tool (`Agent`; legacy alias `Task`). */
69
69
  export declare const DEFAULT_SUBAGENT_TOOL_NAME = "Agent";
70
70
  /**
71
71
  * extraTools 快审 S4 — per-root-spawn-tree cap on `extraTools` factory evaluations. The factory runs
@@ -77,8 +77,8 @@ export declare const DEFAULT_SUBAGENT_TOOL_NAME = "Agent";
77
77
  * runs) with the same generic-note + host-sink disclosure as a factory failure (S3 posture).
78
78
  */
79
79
  export declare const EXTRA_TOOLS_MAX_FACTORY_CALLS_PER_TREE = 64;
80
- /** RB-292 — default delegation nesting depth. CC 2.1.220 `bee()` @272064 falls back to `aHu = 3`
81
- * @272076 (cli250.js:37597); the previous value 5 was CC 2.1.201's `Y4t` and is a stale anchor. Semantics (off-by-one)
80
+ /** RB-292 — default delegation nesting depth: 3, the reference's own default (`CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH`, cli296.js:245773).
81
+ * Semantics (off-by-one)
82
82
  * are pinned on {@link SubagentToolOptions.maxDepth}. */
83
83
  export declare const DEFAULT_SUBAGENT_MAX_DEPTH = 3;
84
84
  /**
@@ -91,31 +91,17 @@ export declare const EXTRA_TOOLS_FAILED_NOTE = "note: extraTools evaluation fail
91
91
  /** extraTools 快审 S4 — the fixed model-facing disclosure for a budget-exhausted (skipped) evaluation. */
92
92
  export declare const EXTRA_TOOLS_BUDGET_NOTE = "note: extraTools evaluation was skipped \u2014 this spawn tree exhausted its factory-call budget (64); no dynamic tools were injected for this spawn.";
93
93
  /**
94
- * CC206-B 欠账 — the Agent completed card's structured `toolStats` (CC 206:541193-541201 `sfd` schema:
95
- * seven counters, `.optional()`; counting logic 206:540431-540491 `_my`). CC derives the counts from the
96
- * child's transcript (assistant `tool_use` blocks) and FOLDS nested delegations' toolStats in via each
97
- * user message's `toolUseResult.toolStats`; sema counts on the shared forward-event sink instead — the
98
- * sink re-threads DESCENDANT events too (grandchildren bubble through, see subagent-steps.ts header), so
99
- * the cumulative semantics match without a fold step. Delegation calls themselves are excluded from every
100
- * bucket (CC excludes `gi`=Agent and `yU`=Task, 206:540453-540455). `linesAdded`/`linesRemoved` mirror CC
101
- * `i3r` (206:399357-399375): LINE COUNTS OF THE EDIT ARGUMENTS (new/old_string, Write content, NotebookEdit
102
- * new_source) — not a real diff; honest to CC's own approximation.
94
+ * The Agent completed card's structured `toolStats`: seven counters, each `.optional()`. sema counts them on the
95
+ * shared forward-event sink — the sink re-threads DESCENDANT events too (grandchildren bubble through, see
96
+ * subagent-steps.ts header), so nested delegations are counted without a separate fold step. Delegation calls
97
+ * themselves are excluded from every bucket. `linesAdded`/`linesRemoved` are LINE COUNTS OF THE EDIT ARGUMENTS
98
+ * (new/old_string, Write content, NotebookEdit new_source) — not a real diff.
103
99
  *
104
- * RB-303 — ANCHOR REFRESHED to CC 2.1.220 (schema @409081-409090, counting `U2_` @408252-408312).
105
- * The seven counters below are byte-for-byte the same seven, and the counting rules are unchanged
106
- * (Agent/Task excluded; nested folds via each user message's `toolUseResult.toolStats`). Two 220
107
- * facts the 206 anchor predates:
108
- * • 220 declares an EIGHTH, optional field: `frameCount`. It counts calls to CC's Artifact tool
109
- * (`F2_ = ARTIFACT_TOOL_NAME` @409045) with `input.action !== "list"`, and it is the one counter
110
- * that also joins the "did this child do anything at all" sum (@408306-408312). sema has no
111
- * Artifact tool, so there is no call to count: the field is deliberately NOT added (an
112
- * always-absent counter is noise on every consumer). Registered as a divergence candidate — if a
113
- * deployment ever mounts an artifact-shaped tool, this is where it lands.
114
- * • 220's Agent result carries `modelsUsed` (ordered distinct models, emitted only when length > 1
115
- * @408398) and `resolvedModel` (@466120-466127) beside toolStats. sema reports the resolved model
116
- * through `TaskResult.model` and has no mid-run swap history on the delegation card. Also
117
- * registered rather than added: the swap list needs a per-turn model ledger sema does not keep,
118
- * and inventing a one-element array would be a face without a mechanism.
100
+ * Two fields of the reference's card are deliberately NOT carried, each registered as a divergence candidate:
101
+ * • `frameCount` (cli296.js:34029), a count of artifact-tool calls.
102
+ * • `modelsUsed` (cli296.js:54014), the ordered distinct models: sema reports the resolved model through
103
+ * `TaskResult.model` and has no mid-run swap history on the delegation card; the swap list needs a per-turn
104
+ * model ledger sema does not keep, and inventing a one-element array would be a face without a mechanism.
119
105
  */
120
106
  export interface SubagentToolStats {
121
107
  readCount: number;
@@ -134,9 +120,9 @@ export interface SubagentToolStats {
134
120
  */
135
121
  export declare const FORK_SUBAGENT_TYPE = "fork";
136
122
  /**
137
- * The BUILT-IN "general-purpose" `subagent_type` alias (CC 2.1.207 parity — 锚 pretty.js:459482 `oje`:
123
+ * The BUILT-IN "general-purpose" `subagent_type` alias (the reference ships the same built-in definition:
138
124
  * CC's agent registry always contains a built-in `general-purpose` definition with `tools: ["*"]`, and an
139
- * OMITTED `subagent_type` defaults to it, :492377 `t ?? oje.agentType`). CC-ecosystem prompts/skills
125
+ * OMITTED `subagent_type` defaults to it). CC-ecosystem prompts/skills
140
126
  * therefore hardcode `subagent_type: "general-purpose"` freely. sema's equivalent of that built-in is the
141
127
  * plain clean-context delegation (full tool pool, SUBAGENT_PROMPT persona) — so the literal FOLDS to the
142
128
  * omitted-type path instead of bouncing as an unknown type. A deployment (or builtin) agent definition of
@@ -568,10 +554,7 @@ export interface SubagentToolOptions {
568
554
  * `WiringManifest.fleet.subagentTranscripts` is the ADDRESSABILITY tier and folds to `"none"` on
569
555
  * the absent-row-store arm before it looks at a session store, so it cannot separate the first
570
556
  * shape above from the third. What DOES answer it is this runner's store's own pair of
571
- * declarations — `sessions.durability` and its release/evict policy — read together. Upstream
572
- * (CC 2.1.250) writes a sub-agent transcript unconditionally to its own file beside the parent
573
- * session, so "the child conversation is readable afterwards" is never conditional on a store
574
- * tier there.
557
+ * declarations — `sessions.durability` and its release/evict policy — read together.
575
558
  */
576
559
  runner: RunnerSelfSeat;
577
560
  /**
@@ -644,8 +627,7 @@ export interface SubagentToolOptions {
644
627
  */
645
628
  agents?: AgentDefinition[];
646
629
  /**
647
- * F1 (CC 2.1.198 parity): offer the BUILT-IN read-only `Explore`/`Plan` agent types (CC `HCe`
648
- * registry, GA default-on — pretty.js:487221-487240 + iAt :487127). Default `true` (CC posture);
630
+ * F1: offer the BUILT-IN read-only `Explore`/`Plan` agent types, on by default. Default `true`;
649
631
  * `false` removes them (the config-driven analog of CC's `CLAUDE_AGENT_SDK_DISABLE_BUILTIN_AGENTS`).
650
632
  * A deployment definition named "Explore"/"Plan" SHADOWS the built-in of the same name (definition
651
633
  * wins — fork-shadowing precedent).
@@ -690,7 +672,7 @@ export interface SubagentToolOptions {
690
672
  allowTools?: string[];
691
673
  /** Tool-level denylist (design/38 1A), used when no `agent` is selected: the denied half of the child's own selector layer (a deny wins). */
692
674
  denyTools?: string[];
693
- /** System prompt / persona for the child. Default (1.259.0, CC 198 parity): the LEAN
675
+ /** System prompt / persona for the child. Default (since 1.259.0): the LEAN
694
676
  * {@link SUBAGENT_PROMPT} (agent persona + return contract), NOT the full default constitution role
695
677
  * base — pass `DEFAULT_SYSTEM_PROMPT` here explicitly to restore the pre-1.259 behavior. */
696
678
  systemPrompt?: string;
@@ -704,11 +686,9 @@ export interface SubagentToolOptions {
704
686
  * Max nesting depth of delegation. A child at depth `d` only receives a delegation tool when
705
687
  * `d + 1 < maxDepth`, so it cannot recurse past the limit.
706
688
  *
707
- * Default 3 (RB-292) — CC 2.1.220 parity: `bee()` @272064 returns `CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH`
708
- * when set, else a remote-config value, else the constant `aHu = 3` @272076 (cli250.js:37597). The old default of 5 was
709
- * anchored on CC 2.1.201's `Y4t` and upstream has since moved; 5 is a stale anchor, not a sema choice.
689
+ * Default 3 (RB-292): the same default as the reference (`CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH`, cli296.js:245773).
710
690
  * sema exposes the override as THIS option rather than an env var (deployments configure the tool, not
711
- * the process), so the env/remote-config half of `bee()` has no sema counterpart to keep in sync.
691
+ * the process), so the env/remote-config half of that lookup has no sema counterpart to keep in sync.
712
692
  *
713
693
  * Semantics pin (off-by-one checked): with the default, the main agent + children at depths 1-2 all
714
694
  * carry a delegation tool, the depth-3 child is the STRUCTURAL leaf (no delegation tool mounted —
@@ -814,56 +794,32 @@ export interface SubagentSpawnContext {
814
794
  /** Delegation depth of the SPAWNING tool (0 = the main agent's Agent tool; a grandchild spawn sees 1, …). */
815
795
  depth: number;
816
796
  }
817
- /**
818
- * "general-purpose" alias fold (CC 2.1.207 parity — see {@link GENERAL_PURPOSE_SUBAGENT_TYPE}): rewrite
819
- * `subagent_type: "general-purpose"` to the OMITTED form so it takes the plain clean-context delegation
820
- * path (sema's built-in general-purpose equivalent: full tool pool + SUBAGENT_PROMPT persona). Wired both
821
- * as the tool's `prepareArguments` pre-validation shim (the declared `subagent_type` enum lists only
822
- * DEFINED agent names, so the literal must rewrite BEFORE the schema check) AND inside execute (direct
823
- * ToolSpec.execute callers). Idempotent; identity when `shadowed` (a deployment/builtin definition of the
824
- * same name wins — the literal then resolves as a normal agent lookup, never this fold). This is a LIVE
825
- * cross-vocabulary mapping, not a compatibility arm (RB-479-A③ retired the Fork `{directive}` adapter
826
- * that used to share this wiring).
827
- */
828
- /**
829
- * RB-293 — subagent_type fold, CC 2.1.220 `ulr` @317317 verbatim:
830
- * `e.normalize("NFKC").toLowerCase().replace(/[\p{White_Space}\p{Pd}_]+/gu, "")`.
831
- *
832
- * Deliberately lossy and deliberately NOT a resolver: it exists only to decide whether two spellings
833
- * denote the same roster entry AFTER an exact match has already failed. `\p{Pd}` is the dash punctuation
834
- * class (so an en-dash paste folds like a hyphen), `\p{White_Space}` covers NBSP and friends, and NFKC
835
- * folds fullwidth/compatibility forms — the three ways a name gets mangled between a listing line and a
836
- * tool call. Note it can map DISTINCT roster names onto one key ("code-review" / "code_review"), which
837
- * is exactly why the caller must treat a multi-hit as ambiguous rather than picking a winner.
838
- */
839
- export declare function normalizeSubagentType(value: string): string;
797
+ export { normalizeSubagentType } from "../core/permission-rule-model.js";
840
798
  /**
841
799
  * A system-prompt note you can append to the PARENT task so the model knows delegation exists.
842
800
  * (The tool description below is the primary "explicit instruction"; this is an optional reinforcement.)
843
801
  */
844
802
  export declare const SUBAGENT_SYSTEM_NOTE: string;
845
803
  /**
846
- * G4 (CC 2.1.198 parity — 锚 pretty.js:225024 `Z4t` fork-boilerplate): the MESSAGE-LAYER instruction
847
- * frame prepended to a fork child's directive. 198 keeps the fork's SYSTEM prompt byte-identical to the
804
+ * G4: the MESSAGE-LAYER instruction
805
+ * frame prepended to a fork child's directive. The fork's SYSTEM prompt stays byte-identical to the
848
806
  * parent (prompt-cache) and carries the fork behavior contract in the messages instead — same posture
849
807
  * here: this frame wraps the `prompt` (the child's objective/user turn) and never touches systemPrompt.
850
- * 198-faithful verbatim (2026-07-10 realignment): the no-spawn line is now the full 198 text — the tool
851
- * name matches (198 `is`="Agent" = our DEFAULT_SUBAGENT_TOOL_NAME) and our tool card carries its own
852
- * fork guidance (:939) for the referent. An earlier adaptation dropped the "default to forking" clause
808
+ * The no-spawn line is the full text — the tool
809
+ * name matches our DEFAULT_SUBAGENT_TOOL_NAME and our tool card carries its own
810
+ * fork guidance for the referent. An earlier adaptation dropped the "default to forking" clause
853
811
  * as CC-specific; a live identity-confusion incident (a fork reading the parent's delegation record as
854
812
  * "someone else is on it" and stopping) showed the parent/fork disambiguation clause is load-bearing —
855
- * keep the anchor whole. (NOT the 88-era frame — 88's "STOP. READ THIS
856
- * FIRST… Scope:/Result/Key files" format was rewritten shorter and softer in 198; parity follows 198.)
857
- * Frame TAIL = the literal directive prefix `Your directive: ` (198 `ZDt`, pretty.js:35621; the Z4t
858
- * assembly is `…</fork-boilerplate>\n\n${ZDt}${directive}`, :225038, and 198 strips the SAME prefix on
859
- * read-back, :415673). 1.259.0 合车复审修①: an earlier transcription invented a `<directive-prefix>`
860
- * tag here — that tag does not exist in 198; the anchor is the plain-text prefix.
813
+ * keep the frame whole.
814
+ * Frame TAIL = the literal plain-text directive prefix `Your directive: ` (no `<directive-prefix>` tag exists;
815
+ * the assembly is `…</fork-boilerplate>\n\n${prefix}${directive}`, and the SAME prefix is stripped on
816
+ * read-back).
861
817
  */
862
818
  export declare const FORK_DIRECTIVE_FRAME = "<fork-boilerplate>\nYou are a worker fork. The transcript above is the parent's history \u2014 inherited reference, not your situation. You are NOT a continuation of that agent. Execute ONE directive, then stop.\n\nHard rules:\n- Do NOT spawn subagents with the Agent tool. The \"default to forking\" guidance is for the parent; you ARE the fork, execute directly.\n- One shot: report once and stop. No follow-up questions, no proposed next steps, no waiting for the user.\n\nGuidelines (your directive may override any of these):\n- Stay in scope. Other forks may be handling adjacent work; if you spot something outside your directive, note it in a sentence and move on.\n- Open with one line restating your task, so the parent can spot scope drift at a glance.\n- Be concise \u2014 as short as the answer allows, no shorter. Plain text, no preamble, no meta-commentary.\n- If you committed changes, list the paths and commit hashes in your report.\n</fork-boilerplate>\n\nYour directive: ";
863
819
  /**
864
- * RB-295 (CC 2.1.220 `Kus` @273133 — verbatim modulo the two interpolations): the path-translation note
820
+ * RB-295: the path-translation note
865
821
  * a FORK gets when it also runs under `isolation: "worktree"`. Upstream pushes it as its own message
866
- * appended AFTER the fork's directive messages (@466667: `if (L && Le) de.push(zr({content: Kus(…)}))`)
822
+ * appended AFTER the fork's directive messages
867
823
  * — it exists precisely because a fork INHERITS the parent's transcript, and every absolute path in that
868
824
  * transcript points at the parent's working copy while the fork's tools now resolve inside the worktree.
869
825
  * A non-fork worktree child has no inherited paths and gets no note, exactly as upstream.
@@ -874,7 +830,7 @@ export declare const FORK_DIRECTIVE_FRAME = "<fork-boilerplate>\nYou are a worke
874
830
  */
875
831
  export declare function forkWorktreeTranslationNote(parentCwd: string | undefined, worktreeDir: string): string;
876
832
  /**
877
- * RB-291 — the `async_launched` tool-result card, rebuilt from the CC 2.1.220 anchor (@467305-467320)
833
+ * RB-291 — the `async_launched` tool-result card, rebuilt from the reference's card
878
834
  * and shared by both background lanes (Agent bg + fork bg) so the two copies cannot drift apart again.
879
835
  * Three drifts were repaired against the anchor:
880
836
  * ① the closing instruction had inverted the anchor's meaning — sema said "end your response. Do not
@@ -936,8 +892,7 @@ export declare function agentToolsNote(def: {
936
892
  denyTools?: string[];
937
893
  }): string;
938
894
  /**
939
- * F4 (CC 2.1.198 `tIl` selection half — 锚 pretty.js:453029 `(t && e.whenToUseLean) || e.whenToUse`,
940
- * `t = yg(mainLoopModel)` :479504): pick the roster guidance text for one agent definition. CC keys
895
+ * F4: pick the roster guidance text for one agent definition. CC keys
941
896
  * `lean` on its simple-system-prompt model predicate; sema runs the CC lean-prompt arm wholesale
942
897
  * (provider-neutral engine, web.ts lean-card precedent), so every call site passes the default
943
898
  * `lean = true` — a definition WITH `whenToUseLean` shows the lean text (exactly what modern CC main