@sema-agent/core 7.54.0 → 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 (403) hide show
  1. package/CHANGELOG.md +451 -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-acquire-reconcile.d.ts +4 -5
  186. package/dist/core/runner/prepare-acquire-reconcile.js +5 -3
  187. package/dist/core/runner/prepare-advisor.d.ts +63 -0
  188. package/dist/core/runner/prepare-advisor.js +77 -0
  189. package/dist/core/runner/prepare-caps-and-workflow.js +1 -1
  190. package/dist/core/runner/prepare-config-doors.d.ts +6 -4
  191. package/dist/core/runner/prepare-config-doors.js +18 -12
  192. package/dist/core/runner/prepare-delegation-surface.d.ts +2 -2
  193. package/dist/core/runner/prepare-delegation-surface.js +1 -1
  194. package/dist/core/runner/prepare-file-history.js +39 -39
  195. package/dist/core/runner/prepare-gate-stations.d.ts +1 -4
  196. package/dist/core/runner/prepare-gate-stations.js +2 -7
  197. package/dist/core/runner/prepare-inherited-gate.d.ts +5 -4
  198. package/dist/core/runner/prepare-inherited-gate.js +3 -3
  199. package/dist/core/runner/prepare-park-ask.js +7 -7
  200. package/dist/core/runner/prepare-policy-chain.d.ts +1 -1
  201. package/dist/core/runner/prepare-policy-chain.js +4 -10
  202. package/dist/core/runner/prepare-project-context.d.ts +5 -2
  203. package/dist/core/runner/prepare-project-context.js +6 -3
  204. package/dist/core/runner/prepare-prompt-inputs.js +1 -1
  205. package/dist/core/runner/prepare-protocol-tools.d.ts +2 -2
  206. package/dist/core/runner/prepare-protocol-tools.js +3 -2
  207. package/dist/core/runner/prepare-safety-scan.d.ts +9 -12
  208. package/dist/core/runner/prepare-safety-scan.js +8 -6
  209. package/dist/core/runner/prepare-task.js +15 -18
  210. package/dist/core/runner/prepare-tool-disclosure-mount.js +6 -4
  211. package/dist/core/runner/prepare-wiring-manifest.d.ts +6 -3
  212. package/dist/core/runner/prepare-wiring-manifest.js +2 -2
  213. package/dist/core/runner/resume-policy-outcome.js +1 -1
  214. package/dist/core/runner/retired-runner-deps.js +1 -1
  215. package/dist/core/runner/run-attachment-seats.js +0 -1
  216. package/dist/core/runner/run-compaction-machinery.d.ts +1 -1
  217. package/dist/core/runner/run-compaction-machinery.js +2 -12
  218. package/dist/core/runner/run-git-lane.d.ts +1 -0
  219. package/dist/core/runner/run-harness-handlers.js +2 -3
  220. package/dist/core/runner/run-leg.js +13 -0
  221. package/dist/core/runner/run-settle-and-teardown.js +1 -1
  222. package/dist/core/runner/run-telemetry-and-budget-seats.js +1 -1
  223. package/dist/core/runner/run-turn-boundary.d.ts +1 -0
  224. package/dist/core/runner/run-turn-boundary.js +14 -12
  225. package/dist/core/runner/session-rule-policy.d.ts +22 -21
  226. package/dist/core/runner/session-rule-policy.js +13 -28
  227. package/dist/core/runner/side-call-account.d.ts +32 -8
  228. package/dist/core/runner/side-call-account.js +23 -1
  229. package/dist/core/runner/strict-output-schema.d.ts +1 -1
  230. package/dist/core/runner/sub-agent-deny-lists.js +4 -3
  231. package/dist/core/runner/synthetic-tools.d.ts +10 -13
  232. package/dist/core/runner/synthetic-tools.js +4 -2
  233. package/dist/core/runner/tool-disclosure.js +2 -1
  234. package/dist/core/runner/tool-face-overlay.d.ts +2 -1
  235. package/dist/core/runner/tool-face-overlay.js +17 -1
  236. package/dist/core/runner/tool-progress-lane.d.ts +2 -2
  237. package/dist/core/runner/tool-turn-repair-seat.d.ts +3 -2
  238. package/dist/core/runner/turn-attachments.d.ts +60 -67
  239. package/dist/core/runner-deps.d.ts +37 -37
  240. package/dist/core/runtime-caps.d.ts +4 -4
  241. package/dist/core/safety-merge-corpus.js +17 -1
  242. package/dist/core/same-plain-value.d.ts +40 -0
  243. package/dist/core/same-plain-value.js +49 -0
  244. package/dist/core/scheduler.d.ts +1 -1
  245. package/dist/core/sensitive-path-policy.d.ts +1 -1
  246. package/dist/core/sensitive-path-policy.js +1 -1
  247. package/dist/core/session-policy-store.d.ts +77 -22
  248. package/dist/core/session-policy-store.js +56 -14
  249. package/dist/core/session-reconcile.d.ts +2 -2
  250. package/dist/core/session-store.d.ts +80 -30
  251. package/dist/core/session-store.js +118 -76
  252. package/dist/core/session.d.ts +24 -46
  253. package/dist/core/shared-memory/tools.js +3 -1
  254. package/dist/core/shared-memory/types.d.ts +1 -1
  255. package/dist/core/side-query.d.ts +10 -0
  256. package/dist/core/side-query.js +5 -0
  257. package/dist/core/store-contracts/checkpoint-store-contract.js +29 -2
  258. package/dist/core/store-contracts/file-history-store-contract.js +43 -3
  259. package/dist/core/store-contracts/session-policy-store-contract.d.ts +7 -0
  260. package/dist/core/store-contracts/session-policy-store-contract.js +130 -0
  261. package/dist/core/store-contracts/session-repo-contract.js +125 -0
  262. package/dist/core/store-contracts/session-store-contract.d.ts +4 -7
  263. package/dist/core/store-contracts/session-store-contract.js +259 -41
  264. package/dist/core/store-contracts/workflow-journal-store-contract.js +26 -1
  265. package/dist/core/surrogate-safe-slice.d.ts +3 -3
  266. package/dist/core/task-event.d.ts +10 -4
  267. package/dist/core/task-notification.d.ts +3 -3
  268. package/dist/core/task-registry-agent.d.ts +4 -4
  269. package/dist/core/task-registry-shared.d.ts +4 -4
  270. package/dist/core/task-registry-shared.js +1 -0
  271. package/dist/core/task-registry.d.ts +4 -4
  272. package/dist/core/task-registry.js +3 -1
  273. package/dist/core/task-result.d.ts +3 -3
  274. package/dist/core/task-spec.d.ts +52 -52
  275. package/dist/core/task-stream.d.ts +6 -6
  276. package/dist/core/task-tool-shape.d.ts +4 -4
  277. package/dist/core/tighten-task-spec.d.ts +1 -1
  278. package/dist/core/tool-catalog-entries.d.ts +19 -2
  279. package/dist/core/tool-catalog-entries.js +57 -42
  280. package/dist/core/tool-conformance.js +1 -0
  281. package/dist/core/tool-errors.d.ts +2 -2
  282. package/dist/core/tool-face-reader.js +5 -3
  283. package/dist/core/tool-face.d.ts +21 -2
  284. package/dist/core/tool-face.js +1 -1
  285. package/dist/core/tool-model-gate.d.ts +3 -3
  286. package/dist/core/tool-name-aliases.d.ts +29 -8
  287. package/dist/core/tool-name-aliases.js +27 -3
  288. package/dist/core/tool-name-readings.d.ts +5 -8
  289. package/dist/core/tool-name-readings.js +1 -2
  290. package/dist/core/tool-policy.d.ts +24 -5
  291. package/dist/core/tool-policy.js +34 -10
  292. package/dist/core/tool-registry.d.ts +14 -7
  293. package/dist/core/tool-registry.js +17 -7
  294. package/dist/core/tool-result-store.js +2 -1
  295. package/dist/core/tool-roster.d.ts +47 -18
  296. package/dist/core/tool-roster.js +53 -32
  297. package/dist/core/tool-spec-members.js +1 -1
  298. package/dist/core/tool-spec.d.ts +35 -21
  299. package/dist/core/tools.js +3 -2
  300. package/dist/core/trace.d.ts +4 -0
  301. package/dist/core/untrusted-egress.d.ts +1 -1
  302. package/dist/core/untrusted-text.d.ts +1 -1
  303. package/dist/core/warm-resume.d.ts +1 -1
  304. package/dist/core/wiring-manifest.d.ts +49 -0
  305. package/dist/core/wiring-manifest.js +13 -5
  306. package/dist/core/workflow-journal-store.d.ts +62 -0
  307. package/dist/core/workflow-journal-store.js +77 -1
  308. package/dist/core/workflow-run-store.d.ts +6 -0
  309. package/dist/core/workflow-run-store.js +2 -0
  310. package/dist/engine/compaction/compaction.d.ts +9 -9
  311. package/dist/engine/execution-env/node-execution-env.d.ts +19 -5
  312. package/dist/engine/execution-env/node-execution-env.js +43 -22
  313. package/dist/engine/harness/agent-harness.d.ts +14 -8
  314. package/dist/engine/harness/agent-harness.js +33 -26
  315. package/dist/engine/harness/types.d.ts +29 -7
  316. package/dist/engine/harness/types.js +12 -1
  317. package/dist/engine/llm/types.d.ts +9 -9
  318. package/dist/engine/llm/validation.d.ts +4 -1
  319. package/dist/engine/llm/validation.js +13 -1
  320. package/dist/engine/loop/agent-loop.d.ts +1 -1
  321. package/dist/engine/loop/agent-loop.js +10 -8
  322. package/dist/engine/loop/types.d.ts +15 -13
  323. package/dist/engine/lsp/node-lsp-manager.d.ts +2 -2
  324. package/dist/engine/session/memory-repo.d.ts +10 -11
  325. package/dist/engine/session/memory-repo.js +13 -8
  326. package/dist/engine/session/parent-chain-guard.d.ts +11 -0
  327. package/dist/engine/session/parent-chain-guard.js +10 -0
  328. package/dist/engine/session/repo-utils.d.ts +31 -3
  329. package/dist/engine/session/repo-utils.js +42 -5
  330. package/dist/engine/session/storage-base.js +3 -0
  331. package/dist/index.d.ts +27 -15
  332. package/dist/index.js +21 -11
  333. package/dist/internal/harness-types.d.ts +1 -1
  334. package/dist/internal/harness.d.ts +4 -3
  335. package/dist/internal/harness.js +3 -2
  336. package/dist/internal/llm.d.ts +1 -1
  337. package/dist/internal/llm.js +1 -1
  338. package/dist/orchestration/goal.js +2 -2
  339. package/dist/orchestration/run-workflow-tool.d.ts +2 -2
  340. package/dist/orchestration/run-workflow-tool.js +5 -3
  341. package/dist/orchestration/workflow-size-guideline.d.ts +4 -4
  342. package/dist/orchestration/workflow-types.d.ts +18 -0
  343. package/dist/orchestration/workflow-types.js +6 -0
  344. package/dist/orchestration/workflow.d.ts +2 -13
  345. package/dist/orchestration/workflow.js +21 -31
  346. package/dist/prompt-assembly/event-registry.js +1 -0
  347. package/dist/prompt-assembly/tool-catalog.d.ts +3 -0
  348. package/dist/prompt-assembly/tool-catalog.js +3 -0
  349. package/dist/prompts/default.d.ts +14 -14
  350. package/dist/scenarios/full-body.d.ts +4 -4
  351. package/dist/stores/file/adoption/adopt.d.ts +4 -3
  352. package/dist/stores/file/adoption/adopt.js +24 -31
  353. package/dist/stores/file/adoption/marker.d.ts +6 -13
  354. package/dist/stores/file/adoption/marker.js +6 -15
  355. package/dist/stores/file/checkpoint-store.d.ts +3 -0
  356. package/dist/stores/file/checkpoint-store.js +9 -3
  357. package/dist/stores/file/file-history-store.d.ts +20 -19
  358. package/dist/stores/file/file-history-store.js +152 -135
  359. package/dist/stores/file/fs-atomic.d.ts +15 -0
  360. package/dist/stores/file/fs-atomic.js +89 -14
  361. package/dist/stores/file/index.d.ts +1 -1
  362. package/dist/stores/file/mailbox-store.d.ts +3 -0
  363. package/dist/stores/file/mailbox-store.js +3 -1
  364. package/dist/stores/file/permission-rule-adopt.d.ts +1 -1
  365. package/dist/stores/file/permission-rule-adopt.js +15 -16
  366. package/dist/stores/file/permission-rule-store.d.ts +18 -2
  367. package/dist/stores/file/permission-rule-store.js +21 -14
  368. package/dist/stores/file/session-policy-store.d.ts +3 -3
  369. package/dist/stores/file/session-store.d.ts +26 -11
  370. package/dist/stores/file/session-store.js +77 -40
  371. package/dist/stores/file/workflow-journal-store.d.ts +10 -4
  372. package/dist/stores/file/workflow-journal-store.js +28 -13
  373. package/dist/tools/artifact/artifact-text.d.ts +1 -1
  374. package/dist/tools/artifact/artifact-tool.js +2 -1
  375. package/dist/tools/fs/bash-readonly-classifier.d.ts +3 -3
  376. package/dist/tools/fs/fs-bash.d.ts +2 -2
  377. package/dist/tools/fs/fs-bash.js +3 -1
  378. package/dist/tools/fs/fs-shared.d.ts +8 -8
  379. package/dist/tools/fs/gh-rate-limit.d.ts +1 -1
  380. package/dist/tools/fs/notebook.d.ts +2 -2
  381. package/dist/tools/fs/read-deny.d.ts +29 -7
  382. package/dist/tools/fs/read-deny.js +63 -22
  383. package/dist/tools/fs/removal-targets.d.ts +1 -1
  384. package/dist/tools/fs/safety.d.ts +9 -9
  385. package/dist/tools/fs/search.d.ts +6 -6
  386. package/dist/tools/fs/shell-read-check.js +6 -1
  387. package/dist/tools/fs/shell-read-judge.d.ts +4 -0
  388. package/dist/tools/fs/shell-read-judge.js +5 -2
  389. package/dist/tools/loop-tick.d.ts +2 -2
  390. package/dist/tools/scheduler-tools.js +5 -1
  391. package/dist/tools/task-list.d.ts +7 -7
  392. package/dist/tools/task-list.js +5 -1
  393. package/dist/tools/todo.js +2 -1
  394. package/dist/tools/web.d.ts +1 -1
  395. package/dist/tools/web.js +40 -37
  396. package/dist/tools/worktree.d.ts +3 -3
  397. package/dist/tools/worktree.js +3 -1
  398. package/package.json +1 -1
  399. package/test/export-surface.snapshot.json +5756 -5638
  400. package/wire-changes/core@7.54.1.json +37 -0
  401. package/wire-changes/core@7.55.0.json +3318 -0
  402. package/dist/core/store-contracts/session-store-incarnation-contract.d.ts +0 -39
  403. package/dist/core/store-contracts/session-store-incarnation-contract.js +0 -95
@@ -1,7 +1,7 @@
1
- import { existsSync, readdirSync, rmSync, statSync } from "node:fs";
1
+ import { closeSync, existsSync, fstatSync, openSync, readdirSync, rmSync, statSync } from "node:fs";
2
2
  import { join } from "node:path";
3
- import { BaseSessionStorage, StoredSession, SessionError, assertForkTarget, forkRowCells, getEntriesToFork, incarnationCell, uuidv7, validateEntriesForImport, } from "../../internal/harness.js";
4
- import { canonicalStoreKey, AppendLog, atomicWriteFile, ensureDir, readJsonlRecords, sanitizePathComponent } from "./fs-atomic.js";
3
+ import { BaseSessionStorage, StoredSession, SessionError, assertForkTarget, compareOccupants, forkRowCells, frozenRow, getEntriesToFork, importRowCells, incarnationCell, leafIdAfterEntry, ownerCell, readIncarnationCell, readOwnerCell, uuidv7, validateEntriesForImport, } from "../../internal/harness.js";
4
+ import { canonicalStoreKey, AppendLog, atomicWriteFile, ensureDir, firstJsonlRecord, lastJsonlRecord, readJsonlRecords, sanitizePathComponent, writeThenLink } from "./fs-atomic.js";
5
5
  import { guardCorruptSink } from "./corrupt-read-sink.js";
6
6
  import { assertAdoptionBootGate } from "./adoption/marker.js";
7
7
  import { thrownText } from "../../core/thrown-value.js";
@@ -9,9 +9,14 @@ const SUFFIX = ".jsonl";
9
9
  const SESSION_LINE_JUDGE = {
10
10
  accepts: (r) => {
11
11
  const line = r;
12
- return line.kind === "meta" || (line.kind === "entry" && line.entry !== null && typeof line.entry === "object");
12
+ if (line.kind === "meta")
13
+ return true;
14
+ if (line.kind !== "entry" || line.entry === null || typeof line.entry !== "object" || Array.isArray(line.entry))
15
+ return false;
16
+ const entry = line.entry;
17
+ return typeof entry.id === "string" && (entry.type !== "leaf" || entry.targetId === null || typeof entry.targetId === "string");
13
18
  },
14
- what: "a session line is neither a meta header nor an entry record",
19
+ what: "a session line is neither a meta header nor an entry record with a string id (and, for a leaf, a string or null target)",
15
20
  };
16
21
  const sharedSessionStorages = new Map();
17
22
  const sessionStorageFinalizer = new FinalizationRegistry(({ canonical, log }) => {
@@ -31,10 +36,12 @@ class FileSessionStorage extends BaseSessionStorage {
31
36
  log;
32
37
  canonicalPath;
33
38
  holders = new Set();
39
+ occupant;
34
40
  constructor(log, meta, entries, canonicalPath) {
35
41
  super(meta, entries);
36
42
  this.log = log;
37
43
  this.canonicalPath = canonicalPath;
44
+ this.occupant = { incarnation: meta.incarnation };
38
45
  }
39
46
  addHolder(holder) {
40
47
  this.holders.add(holder);
@@ -46,6 +53,9 @@ class FileSessionStorage extends BaseSessionStorage {
46
53
  closeLog() {
47
54
  this.log.close();
48
55
  }
56
+ isViewOf(row) {
57
+ return this.log.isFileAtPath() && compareOccupants(this.occupant, row) !== "different";
58
+ }
49
59
  persistSync(entry) {
50
60
  this.log.append({ kind: "entry", entry }, true);
51
61
  }
@@ -91,45 +101,63 @@ export class FileSessionRepo {
91
101
  tally = info;
92
102
  this.onCorruptRead?.({ ...info, sessionId: id });
93
103
  }, SESSION_LINE_JUDGE);
94
- let meta;
104
+ const meta = this.headerOf(id, path, lines[0], () => ` (${tally?.dropped ?? 0} of ${tally?.total ?? lines.length} records skipped as corrupt)`);
95
105
  const entries = [];
96
- for (const line of lines) {
97
- if (line.kind === "meta")
98
- meta = line;
99
- else
106
+ for (const line of lines)
107
+ if (line.kind === "entry")
100
108
  entries.push(line.entry);
109
+ return { meta, entries };
110
+ }
111
+ headerOf(id, path, first, skipped = () => "") {
112
+ if (first === undefined || first.kind !== "meta")
113
+ throw new SessionError("corrupt_session", `Session ${id} is unreadable: its log has no meta header${skipped()}`);
114
+ const said = (key) => (detail) => this.disclose(path, `session header ${key}: ${detail}`, id);
115
+ const incarnation = readIncarnationCell(first.incarnation, said("incarnation"));
116
+ const forkedFromIncarnation = readIncarnationCell(first.forkedFromIncarnation, said("forkedFromIncarnation"));
117
+ return {
118
+ id,
119
+ createdAt: first.createdAt,
120
+ ...(first.forkedFrom !== undefined ? { forkedFrom: first.forkedFrom } : {}),
121
+ ...(first.placement !== undefined ? { placement: first.placement } : {}),
122
+ ...(incarnation !== undefined ? { incarnation } : {}),
123
+ ...(forkedFromIncarnation !== undefined ? { forkedFromIncarnation } : {}),
124
+ owner: readOwnerCell(first.owner, id),
125
+ };
126
+ }
127
+ async headOf(sessionId) {
128
+ const path = this.pathFor(sessionId);
129
+ let fd;
130
+ try {
131
+ fd = openSync(path, "r");
101
132
  }
102
- if (meta === undefined) {
103
- throw new SessionError("corrupt_session", `Session ${id} is unreadable: its log has no meta header (${tally?.dropped ?? 0} of ${tally?.total ?? lines.length} records skipped as corrupt)`);
133
+ catch (err) {
134
+ if (err.code === "ENOENT")
135
+ return undefined;
136
+ throw err;
104
137
  }
105
- const { createdAt, forkedFrom, placement, incarnation, forkedFromIncarnation } = meta;
106
- for (const [key, token] of [["incarnation", incarnation], ["forkedFromIncarnation", forkedFromIncarnation]]) {
107
- if (token !== undefined && typeof token !== "string")
108
- this.disclose(path, `session header carries a non-string ${key} (${typeof token}) — read as an UNKNOWN occupant`, id);
138
+ try {
139
+ const size = fstatSync(fd).size;
140
+ const meta = this.headerOf(sessionId, path, firstJsonlRecord(fd, size, SESSION_LINE_JUDGE));
141
+ const last = lastJsonlRecord(fd, size, (r) => r.kind === "entry", SESSION_LINE_JUDGE);
142
+ return { owner: meta.owner ?? null, incarnation: meta.incarnation, leafId: last === undefined ? null : leafIdAfterEntry(last.entry) };
143
+ }
144
+ finally {
145
+ closeSync(fd);
109
146
  }
110
- return {
111
- meta: {
112
- id,
113
- createdAt,
114
- ...(forkedFrom !== undefined ? { forkedFrom } : {}),
115
- ...(placement !== undefined ? { placement } : {}),
116
- ...(typeof incarnation === "string" ? { incarnation } : {}),
117
- ...(typeof forkedFromIncarnation === "string" ? { forkedFromIncarnation } : {}),
118
- },
119
- entries,
120
- };
121
147
  }
122
148
  storage(meta, entries) {
123
149
  const { id } = meta;
124
150
  const canonical = canonicalStoreKey(this.pathFor(id));
125
151
  const live = sharedSessionStorages.get(canonical)?.deref();
126
- if (live !== undefined) {
152
+ if (live !== undefined && live.isViewOf(meta)) {
127
153
  live.addHolder(this);
128
154
  this.joined.set(canonical, new WeakRef(live));
129
155
  return live;
130
156
  }
157
+ if (live !== undefined)
158
+ evictSharedSessionStorage(canonical);
131
159
  const log = new AppendLog(this.pathFor(id));
132
- const created = new FileSessionStorage(log, meta, entries, canonical);
160
+ const created = new FileSessionStorage(log, frozenRow({ ...meta, ...(meta.placement !== undefined ? { placement: { ...meta.placement } } : {}) }), entries, canonical);
133
161
  sharedSessionStorages.set(canonical, new WeakRef(created));
134
162
  created.addHolder(this);
135
163
  this.joined.set(canonical, new WeakRef(created));
@@ -153,10 +181,17 @@ export class FileSessionRepo {
153
181
  const createdAt = new Date().toISOString();
154
182
  const path = this.pathFor(id);
155
183
  if (!existsSync(path)) {
156
- evictSharedSessionStorage(canonicalStoreKey(path));
184
+ const owner = ownerCell(options.owner);
157
185
  const placement = options.placement !== undefined ? { ...options.placement, placedAt: options.placement.placedAt ?? Date.now() } : undefined;
158
- const meta = { id, createdAt, ...(placement !== undefined ? { placement } : {}), ...incarnationCell(undefined) };
159
- atomicWriteFile(this.tmpDir, path, `${JSON.stringify({ kind: "meta", ...meta })}\n`);
186
+ const meta = { id, createdAt, ...(placement !== undefined ? { placement } : {}), ...incarnationCell(undefined), ...owner };
187
+ try {
188
+ writeThenLink(path, `${JSON.stringify({ kind: "meta", ...meta })}\n`);
189
+ }
190
+ catch (err) {
191
+ if (err.code === "EEXIST")
192
+ throw new SessionError("conflict", `session ${id} was created by another writer between this create's existence check and its write — refusing to replace or attach to that row`);
193
+ throw err;
194
+ }
160
195
  return new StoredSession(this.storage(meta, []));
161
196
  }
162
197
  const { meta, entries } = this.read(id);
@@ -248,15 +283,19 @@ export class FileSessionRepo {
248
283
  return this.read(id).meta;
249
284
  }
250
285
  catch (err) {
251
- return err instanceof SessionError && err.code === "not_found" ? undefined : {};
286
+ if (err instanceof SessionError && err.code === "not_found")
287
+ return undefined;
288
+ throw err;
252
289
  }
253
290
  }
254
291
  async placementOf(sessionId) {
255
292
  try {
256
293
  return this.read(sessionId).meta.placement;
257
294
  }
258
- catch {
259
- return undefined;
295
+ catch (err) {
296
+ if (err instanceof SessionError && err.code === "not_found")
297
+ return undefined;
298
+ throw err;
260
299
  }
261
300
  }
262
301
  async delete(metadata) {
@@ -275,7 +314,7 @@ export class FileSessionRepo {
275
314
  const id = options.id ?? uuidv7();
276
315
  const createdAt = new Date().toISOString();
277
316
  const path = this.pathFor(id);
278
- const meta = { id, createdAt, ...forkRowCells(await source.getMetadata()) };
317
+ const meta = { id, createdAt, ...forkRowCells(await source.getMetadata(), options.owner) };
279
318
  const lines = [JSON.stringify({ kind: "meta", ...meta })];
280
319
  for (const entry of forked) {
281
320
  lines.push(JSON.stringify({ kind: "entry", entry }));
@@ -288,12 +327,10 @@ export class FileSessionRepo {
288
327
  return this.read(sessionId).entries;
289
328
  }
290
329
  async importEntries(sessionId, owner, entries, options) {
291
- void owner;
292
330
  const validated = validateEntriesForImport(entries, options);
293
- const prior = this.priorHeader(sessionId);
331
+ const meta = importRowCells(sessionId, owner, this.priorHeader(sessionId), new Date().toISOString());
294
332
  evictSharedSessionStorage(canonicalStoreKey(this.pathFor(sessionId)));
295
- const createdAt = new Date().toISOString();
296
- const lines = [JSON.stringify({ kind: "meta", id: sessionId, createdAt, ...incarnationCell(prior) })];
333
+ const lines = [JSON.stringify({ kind: "meta", ...meta })];
297
334
  for (const entry of validated) {
298
335
  lines.push(JSON.stringify({ kind: "entry", entry }));
299
336
  }
@@ -48,9 +48,9 @@ export declare const RESUME_CLAIM_SWEEP_INTERVAL_MS = 60000;
48
48
  */
49
49
  export declare const RESUME_CLAIM_REAP_GRACE_MS: number;
50
50
  export interface FileWorkflowJournalStoreOptions {
51
- /** Disclosure seat for a ledger line this store DROPPED on replay (not JSON, not a record, or a record
52
- * with none of this ledger's members) — a resume that silently finds "nothing to replay" re-runs the
53
- * work with no signal. Never fires on a missing ledger; swallow-guarded. */
51
+ /** Disclosure seat for a ledger line that is not one of the run's records (not JSON, not an object, no `scope` /
52
+ * `ordinal`, another scope) and — with the refusal, carrying the ledger's path — for whatever refused a `load`.
53
+ * Never fires on a missing ledger or on a crash's unterminated tail; swallow-guarded. */
54
54
  onCorruptRead?: (info: CorruptReadInfo) => void;
55
55
  }
56
56
  export declare class FileWorkflowJournalStore implements WorkflowJournalStore {
@@ -79,9 +79,15 @@ export declare class FileWorkflowJournalStore implements WorkflowJournalStore {
79
79
  /** CC local form: the run's on-disk journal path for the notification diagnostics line.
80
80
  * Traversal-shaped ids (LLM-controlled on some paths) degrade to undefined, never throw. */
81
81
  locator(runId: string): string | undefined;
82
- /** Replay a run's ledger: last-writer-wins per ordinal; a torn/unparsable line is skipped (uncommitted). */
82
+ /** Replay a run's ledger: last-writer-wins per ordinal, with every line that is not one of the run's records
83
+ * (`notRecords`) and the scope the first record fixes. Rows come back as written — which arm each one is, and
84
+ * whether anything refuses, is {@link load}'s question, so the scope lookup `append` makes refuses on nothing. */
83
85
  private replay;
84
86
  append(runId: string, scope: string, entry: WorkflowJournalEntry): Promise<void>;
87
+ /** The run's entries, ascending by ordinal, each winning line read through {@link readWorkflowJournalEntry}. A
88
+ * ledger line that is not one of the run's records, or a corrupt row, REFUSES the whole load: dropped, what it
89
+ * held would look never journaled and a resume would run it again. Only the unterminated tail a crash leaves is
90
+ * uncommitted. The location goes to `onCorruptRead`, not into the message; a superseded line is not read. */
85
91
  load(runId: string, scope: string): Promise<WorkflowJournalEntry[]>;
86
92
  /**
87
93
  * RB-242 — the claim file for `(sourceRunId, scope)`. Keyed by BOTH: a cross-scope caller already
@@ -1,18 +1,13 @@
1
1
  import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, unlinkSync } from "node:fs";
2
2
  import { createHash } from "node:crypto";
3
3
  import { join } from "node:path";
4
- import { callKeyOrdinal } from "../../core/workflow-journal-store.js";
4
+ import { callKeyOrdinal, readWorkflowJournalEntry, WorkflowJournalIncompatibleError, } from "../../core/workflow-journal-store.js";
5
5
  import { AppendLog, readJsonlRecords } from "./fs-atomic.js";
6
6
  import { guardCorruptSink } from "./corrupt-read-sink.js";
7
7
  import { canonicalStoreKey, sanitizePathComponent, writeThenLink } from "./fs-atomic.js";
8
8
  import { assertAdoptionBootGate } from "./adoption/marker.js";
9
9
  import { assertJournalEntryFits } from "../../core/workflow-journal-store.js";
10
10
  export { MAX_JOURNAL_RESULT_BYTES, oversizeJournalResult } from "../../core/workflow-journal-store.js";
11
- function entryOf(rec) {
12
- if (rec.parked !== undefined)
13
- return { callKey: rec.callKey, parked: rec.parked };
14
- return { callKey: rec.callKey, result: rec.result };
15
- }
16
11
  export const RESUME_CLAIM_TTL_MS = 60 * 60 * 1000;
17
12
  export const RESUME_CLAIM_RELEASE_GRACE_MS = 5_000;
18
13
  export const RESUME_CLAIM_SWEEP_INTERVAL_MS = 60_000;
@@ -21,7 +16,7 @@ const sharedJournalDirs = new Map();
21
16
  const MAX_OPEN_JOURNAL_LOGS = 64;
22
17
  function isJournalLine(r) {
23
18
  const rec = r;
24
- return typeof rec.callKey === "string" && typeof rec.scope === "string" && Number.isFinite(rec.ordinal);
19
+ return typeof rec.scope === "string" && Number.isFinite(rec.ordinal);
25
20
  }
26
21
  export class FileWorkflowJournalStore {
27
22
  fsyncEnabled;
@@ -86,11 +81,17 @@ export class FileWorkflowJournalStore {
86
81
  scope ??= r.scope;
87
82
  return r.scope === scope;
88
83
  },
89
- what: "a journal line carries no callKey/scope pair, or a scope other than its run's first line",
84
+ what: "a journal line carries no scope/ordinal pair, or a scope other than its run's first line",
85
+ };
86
+ const notRecords = [];
87
+ const onCorrupt = (info) => {
88
+ if (info.kind === "record")
89
+ notRecords.push(info);
90
+ this.discloseCorrupt?.(info);
90
91
  };
91
- for (const rec of readJsonlRecords(path, this.discloseCorrupt, judge))
92
- byOrdinal.set(rec.ordinal, entryOf(rec));
93
- return scope === undefined ? undefined : { scope, byOrdinal };
92
+ for (const rec of readJsonlRecords(path, onCorrupt, judge))
93
+ byOrdinal.set(rec.ordinal, rec);
94
+ return { scope, byOrdinal, notRecords };
94
95
  }
95
96
  async append(runId, scope, entry) {
96
97
  assertJournalEntryFits(entry);
@@ -126,9 +127,23 @@ export class FileWorkflowJournalStore {
126
127
  }
127
128
  async load(runId, scope) {
128
129
  const rec = this.replay(runId);
129
- if (!rec || rec.scope !== scope)
130
+ if (!rec || (rec.scope !== undefined && rec.scope !== scope))
130
131
  return [];
131
- return [...rec.byOrdinal.entries()].sort((a, b) => a[0] - b[0]).map(([, e]) => e);
132
+ const lost = rec.notRecords[0];
133
+ if (lost !== undefined) {
134
+ this.discloseCorrupt?.({ kind: "file", path: this.pathFor(runId), reason: `${lost.form}: ledger line ${lost.line} is not one of the run's records (the run's journal is refused)` });
135
+ throw WorkflowJournalIncompatibleError.ledgerLine(runId, lost.line, lost.form);
136
+ }
137
+ const out = [];
138
+ for (const [ordinal, line] of [...rec.byOrdinal.entries()].sort((a, b) => a[0] - b[0])) {
139
+ const read = readWorkflowJournalEntry(line);
140
+ if ("corrupt" in read) {
141
+ this.discloseCorrupt?.({ kind: "file", path: this.pathFor(runId), reason: `${read.corrupt}: journal entry #${ordinal} ${read.why} (the run's journal is refused)` });
142
+ throw new WorkflowJournalIncompatibleError(runId, ordinal, line);
143
+ }
144
+ out.push(read.entry);
145
+ }
146
+ return out;
132
147
  }
133
148
  claimPathFor(sourceRunId, scope) {
134
149
  const scopeTag = createHash("sha256").update(scope).digest("hex").slice(0, 16);
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * The model-facing text of the Artifact tool. Every sentence is the upstream tool's wording, taken
3
- * byte-for-byte from the reference corpus (Claude Code 2.1.259, `cli259.js`; the line of each constant is
3
+ * byte-for-byte from the reference corpus (the line of each constant is
4
4
  * noted beside it) with one class of edit: a reference to a hosting product this library does not have
5
5
  * (`claude.ai`, its terminal/gallery/Slack surfaces, an `out_dir` save) is replaced by the smallest
6
6
  * neutral phrase. The replacement list is registered in the divergence register beside this package.
@@ -8,7 +8,7 @@ const ARTIFACT_ACTION_LEGS = {
8
8
  hosted: { publish: ["env", "outside_write"], list: ["outside_read"], read: ["outside_read"], list_files: ["outside_read"], read_file: ["outside_read"] },
9
9
  "local-stub": { publish: ["env"], list: [], read: [], list_files: [], read_file: [] },
10
10
  };
11
- import { ARTIFACT_TOOL_NAME, toolFace } from "../../core/tool-catalog-entries.js";
11
+ import { ARTIFACT_TOOL_NAME, mountRuleFace, toolFace } from "../../core/tool-catalog-entries.js";
12
12
  import { resolveAsk } from "../../core/tool-policy.js";
13
13
  import { NOT_BINDABLE } from "../../core/skill-grant-binding.js";
14
14
  import { approvalCardOf } from "../../core/tool-roster.js";
@@ -448,6 +448,7 @@ export function createArtifactTool(opts) {
448
448
  return {
449
449
  name: ARTIFACT_TOOL_NAME,
450
450
  ...toolFace("artifact"),
451
+ ruleFace: mountRuleFace("artifact"),
451
452
  contentOrigin: ARTIFACT_PLANE_CONTENT_ORIGIN[caps.plane],
452
453
  description: artifactDescription(caps.plane, caps.actions),
453
454
  parameters: buildSchema(caps),
@@ -267,9 +267,9 @@ export declare function splitShellCompoundSegments(source: string, options?: {
267
267
  *
268
268
  * The allowlist vets `argv[0]` only, so until this face existed every listed reader could name ANY
269
269
  * path: `ls /etc` and `cat /etc/passwd` classified read-only, and a deployment whose manual-mode shell
270
- * gate auto-allows the read-only verdict served the whole filesystem with no approval prompt. CC 2.1.220
271
- * demotes exactly these shapes (its per-command path extractor + working-directory containment check,
272
- * pretty220 @457568) and renders an approval option naming the directory (@905642 (cli250.js:66007)).
270
+ * gate auto-allows the read-only verdict served the whole filesystem with no approval prompt. The reference
271
+ * demotes exactly these shapes (its per-command path extractor + working-directory containment check)
272
+ * and renders an approval option naming the directory.
273
273
  *
274
274
  * Supplying this object turns the check ON; omitting it leaves the classifier byte-identical to its
275
275
  * name-only behaviour, so a consumer pinned to an older calling convention is unaffected.
@@ -35,7 +35,7 @@ export declare function bashReversibilityProbe(allow?: readonly string[], bounda
35
35
  * fullShellReachable roster assertion (its first load-bearing consumer).
36
36
  */
37
37
  export { FULL_SHELL_CONTRACT_ID } from "../../core/tool-catalog-entries.js";
38
- /** The CC-verbatim exit-1 interpretation for `command`, or undefined when exit 1 means a real error.
38
+ /** The exit-1 interpretation for `command`, or undefined when exit 1 means a real error.
39
39
  * Read off the lexer's segments: the last one (the last `;`/`&&`/`||`/newline statement's last `|` piece) → its
40
40
  * written command word past the leading assignments bash strips, path prefix stripped;
41
41
  * `git grep`/`git diff` special-cased (CC `cLp`). Exported for its unit tests. */
@@ -110,7 +110,7 @@ export declare function createBashTool(env: ExecutionEnv, rootCanonical: string,
110
110
  * Is a PERSON's input waiting for this run's next turn boundary? Read on each liveness tick of a
111
111
  * running foreground command: `true` on an {@link autoBackgroundOnTimeout}-armed command moves that
112
112
  * command into the background (through the SAME detach verb ctrl+b fires) so the message is
113
- * delivered this turn instead of after the command. CC 2.1.259 `backgroundedToDeliverMessage`.
113
+ * delivered this turn instead of after the command. Reference field `backgroundedToDeliverMessage` (cli296.js:134207).
114
114
  *
115
115
  * The predicate is the HARNESS's own accepted-but-unserved account and deliberately counts only what
116
116
  * a PERSON sent: an engine-authored reminder is not somebody waiting, and stepping a build aside for
@@ -17,7 +17,7 @@ import { ghRateLimitHint } from "./gh-rate-limit.js";
17
17
  import { backgroundLifetimeNote } from "./fs-bash-background-text.js";
18
18
  import { resolveBashTimeoutCaps, bashTimeoutCapsSec, bashTimeoutArgRefusal, bashTimeoutParamDescription, envErrorDetail, bashMaxOutputChars, clipShellOutput, writeShellOverflowFile, shellRecoveryHint, CWD_SENTINEL, stripCwdSentinel, } from "./fs-shared.js";
19
19
  import { bashClassifyDefaultAllow, BASH_READONLY_DEFAULT_ALLOW, coarseReadonlyCheck, classifyBoundedReadonlyPollLoopDetailed, classifyCompoundReadonlyDetailed } from "./bash-readonly-classifier.js";
20
- import { toolFace } from "../../core/tool-catalog-entries.js";
20
+ import { mountRuleFace, toolFace } from "../../core/tool-catalog-entries.js";
21
21
  import { argvOf, compoundValueHidesRun, expansionHidesRun, expansionsInHeredocBody, lexShell } from "../../shell/lex.js";
22
22
  import { arithmeticAssignedNames } from "./shell-read-bindings.js";
23
23
  import { thrownText } from "../../core/thrown-value.js";
@@ -812,6 +812,7 @@ export function createEnvTaskOutputTool(env) {
812
812
  return defineTool({
813
813
  name: TASK_OUTPUT_TOOL_NAME,
814
814
  ...toolFace("task-output-hands"),
815
+ ruleFace: mountRuleFace("task-output-hands"),
815
816
  description: composeTaskOutputDescription(ENV_DIRECT_TASK_TOOL_CAPS),
816
817
  parameters: composeTaskOutputParams(ENV_DIRECT_TASK_TOOL_CAPS),
817
818
  execute: async (args) => {
@@ -849,6 +850,7 @@ export function createEnvTaskStopTool(env, registry = defaultTaskRegistry) {
849
850
  return defineTool({
850
851
  name: TASK_STOP_TOOL_NAME,
851
852
  ...toolFace("task-stop-hands"),
853
+ ruleFace: mountRuleFace("task-stop-hands"),
852
854
  description: composeTaskStopDescription(ENV_DIRECT_TASK_TOOL_CAPS),
853
855
  parameters: TASK_STOP_PARAMS,
854
856
  execute: async (args) => {
@@ -25,14 +25,14 @@ export declare const MAX_READ_BYTES: number;
25
25
  * explicit slice, with guidance to stream a portion via bash (`sed -n` / `head -c`) instead, which
26
26
  * never loads the whole file. */
27
27
  export declare const SLICED_READ_MAX_BYTES: number;
28
- /** The byte cap Edit refuses ABOVE (CC's own constant, verbatim). CC stats the target before touching
28
+ /** The byte cap Edit refuses ABOVE. CC stats the target before touching
29
29
  * it and refuses with a formatted-size message when it exceeds this. Without the gate, Edit goes
30
30
  * straight to a whole-file `readBinaryFile` (twice: the `old_string:""` full-overwrite branch and the
31
31
  * normal find/replace branch), so a multi-GB target is an unguarded OOM lever an ordinary Edit call
32
32
  * can pull. The shape is Read's: a pre-read `env.fileInfo` stat plus a post-read TOCTOU recheck
33
33
  * ({@link SLICED_READ_MAX_BYTES} above). */
34
34
  export declare const MAX_EDIT_BYTES: number;
35
- /** `Edit`'s human-readable byte-count formatter (CC `pl()` verbatim: bytes below 1KB, else
35
+ /** `Edit`'s human-readable byte-count formatter (bytes below 1KB, else
36
36
  * KB/MB/GB with one decimal, trailing ".0" stripped). */
37
37
  export declare function formatByteSize(n: number): string;
38
38
  /** Node's own string-length ceiling (`buffer.constants.MAX_STRING_LENGTH` — ~512MiB on V8/Node 24)
@@ -103,7 +103,7 @@ export interface RecordedEdit {
103
103
  export declare function applyRecordedEdit(text: string, edit: RecordedEdit): string;
104
104
  /** Render the read-before-edit refusal, appending the slice/bash escape hatch when the target is over
105
105
  * the Read byte cap — a bare "read it first" is un-followable there (a default whole-file Read
106
- * refuses such files). Best-effort: an un-stattable file keeps the bare CC-verbatim refusal.
106
+ * refuses such files). Best-effort: an un-stattable file keeps the bare refusal.
107
107
  *
108
108
  * `fallbackHint` is a caller-supplied parenthetical for the case NO branch below diagnosed anything
109
109
  * (all three writing tools pass {@link READ_REFUSED_ESCAPE_HINT} — the Read-refuses-this-file
@@ -332,7 +332,7 @@ export declare function createShellOverflowSpoolFence(env: ExecutionEnv): (path:
332
332
  * executable. Full `bash` keeps the precise form.
333
333
  */
334
334
  export declare function shellRecoveryHint(path: string, readOnly: boolean | undefined): string;
335
- /** CC 2.1.198 live-verbatim Edit/Write success trailer — appended to every Edit/Write success message
335
+ /** Edit/Write success trailer — appended to every Edit/Write success message
336
336
  * (NOT NotebookEdit — CC ships it without the trailer). */
337
337
  export declare const FILE_STATE_TRAILER = " (file state is current in your context \u2014 no need to Read it back)";
338
338
  export declare const CWD_SENTINEL = "__cc_cwd_9f2c1b__";
@@ -383,11 +383,11 @@ export declare function ipynbRedirect(toolName: string, path: string): string |
383
383
  * ends in "\n". Behavior is identical for content WITHOUT a trailing newline. Shared by read_file's
384
384
  * `total`, edit_file/write_file's "N lines" report, and the persisted ReadFileState.totalLines. */
385
385
  export declare function countLines(s: string): number;
386
- /** CC 2.1.204 VERBATIM: the reminder served when a DEFAULT whole-file Read hits a startup-seeded,
386
+ /** The reminder served when a DEFAULT whole-file Read hits a startup-seeded,
387
387
  * unchanged file. `filePath` is the CANONICAL key (CC passes the resolved full path, matching the
388
388
  * `Contents of <path>` header its context seeding emits — deployments seeding files should title the
389
389
  * injected block the same way so the back-reference lands). Locked verbatim by test: the BODY and
390
- * close tag stay CC-verbatim; the open tag alone is rendered by the mint home and carries the session
390
+ * close tag stay fixed; the open tag alone is rendered by the mint home and carries the session
391
391
  * mark when one is threaded (the recorded wire-form divergence). */
392
392
  export declare function seededFileUnchangedReminder(filePath: string, mark?: string): string;
393
393
  /**
@@ -404,7 +404,7 @@ export declare function seededFileUnchangedReminder(filePath: string, mark?: str
404
404
  */
405
405
  export declare function isReadDedupStubResult(resultText: string): boolean;
406
406
  /** Pre-seed the hands' read state for a file whose FULL, disk-verbatim text was injected into the
407
- * model's context at startup (CC 2.1.204 `seededFromContext` seeding of the memory preload; sema:
407
+ * model's context at startup (`seededFromContext` seeding of the memory preload; sema:
408
408
  * ProjectMemoryLoad.seededFiles → prepare-task).
409
409
  * `content` MUST be the file's exact disk text at load time — the Read tool's seeded dedup treats a
410
410
  * hash match as "unchanged"; a truncated/annotated variant must NOT be seeded (CC exempts those via
@@ -505,7 +505,7 @@ export type ReadFileStateShrink =
505
505
  transmissions: ReadonlyArray<string>;
506
506
  };
507
507
  export declare function applyContextShrinkToReadFileState(state: ReadFileState, shrink: ReadFileStateShrink): void;
508
- /** CC 2.1.198 verbatim skeleton: the ENOENT error body for a
508
+ /** The ENOENT error body for a
509
509
  * missing Read/Edit target — `File does not exist. Note: your current working directory is <cwd>.`
510
510
  * plus a `Did you mean <sibling>?` correction when the parent directory holds a near-name (case
511
511
  * variant / same stem different extension — the high-frequency self-heal path). Best-effort: a
@@ -1,5 +1,5 @@
1
1
  /**
2
- * gh rate-limit hint (CC 2.1.198 parity).
2
+ * gh rate-limit hint.
3
3
  *
4
4
  * CC appends a one-shot <system-reminder> to a FOREGROUND Bash result when a `gh` invocation hits the
5
5
  * GitHub API rate limit, so the model sleeps/schedules instead of hammering retries. The command gate,
@@ -1,6 +1,6 @@
1
1
  import type { ImageContent } from "../../internal/llm.js";
2
2
  /**
3
- * The Read tool's Jupyter-notebook projection: `.ipynb` is rendered as cells with outputs (CC 2.1.220
3
+ * The Read tool's Jupyter-notebook projection: `.ipynb` is rendered as cells with outputs (reference
4
4
  * parity), never as raw JSON text. Raw-JSON rendering lets a notebook's base64 outputs overflow the
5
5
  * Read token cap, auto-paginate into an `isPartialView` entry, and thereby lock NotebookEdit out via
6
6
  * the requireRead gate — with the marker's own offset/limit hint pointing at a range that itself
@@ -80,7 +80,7 @@ export interface NotebookRender {
80
80
  imageChars: number;
81
81
  }
82
82
  /**
83
- * CC `eI_`/`tI_`/`Atd`: render projected cells to content blocks. Tag shape is CC-verbatim, including
83
+ * Render projected cells to content blocks. Tag shape is the reference's, including
84
84
  * the deliberately malformed closing tag `</cell id="X">`; `<cell_type>` only when not code,
85
85
  * `<language>` only for code cells whose language !== "python". Output text rides with a leading "\n"
86
86
  * and adjacent text blocks merge with "\n", so an all-text notebook collapses to a single text block.
@@ -115,7 +115,7 @@ export declare function ruleHeadParts(rows: readonly Pick<PathRuleDenyRow, "head
115
115
  * below that part. Every part, not the head alone: a link inside the rule's literal prefix that is re-pointed after the
116
116
  * rows were placed still meets the row through the parts above it. One rule for every row form and every judge (the
117
117
  * gate's lanes and the deny tables): the reference compiles the same "physical twin" of every deny / ask rule's literal
118
- * prefix (cli280.js `ei` 9766583, compiled in `mt` 9767083). `leads` is the leg's resolution of each part (absent or
118
+ * prefix. `leads` is the leg's resolution of each part (absent or
119
119
  * `undefined` = no twin there); a part that only extends its parent's resolution adds no row. A twin is the row's own
120
120
  * kind (it keeps every member but the head), so a judgment reports the rule the twin stands for.
121
121
  */
@@ -416,12 +416,32 @@ export declare function activeReadDenyBuiltinTiers(config?: ReadDenyBuiltinConfi
416
416
  * renders "what COULD be switched on".
417
417
  */
418
418
  export declare const READ_FACE_DEFAULT_DENY_ENTRIES: readonly ReadDenyEntry[];
419
+ /**
420
+ * The fold the "unicode" mode applies — the one a RegExp `i` flag without `u` applies, one UTF-16 code unit at a time: the
421
+ * upper-case mapping when it is a single unit and does not step from a non-ASCII unit down into ASCII (`ı` and `ſ` stay
422
+ * themselves, `ß` stays `ß`). Both sides of a comparison go through it.
423
+ */
424
+ export declare function ignoreCaseFold(s: string): string;
425
+ /** How a compiled pattern compares: `none` byte for byte; `ascii` and `unicode` through the fold of that name, both sides —
426
+ * the pattern's side at compile, the segments' side by whoever tests (once per path: {@link segmentReadingsOf}). */
427
+ export type SegmentFold = "none" | "ascii" | "unicode";
428
+ /** The function that folds a string as each fold folds — the one place that says which function that is (the pattern at compile,
429
+ * a path's segments in the readings, an anchor's segments all read it, at the time they fold). */
430
+ export declare const SEGMENT_FOLDS: Record<SegmentFold, (s: string) => string>;
431
+ /** One compiled segment of a pattern: `*` stands for any run of characters but a separator, every other character for itself. */
432
+ export interface SegmentMatcher {
433
+ /** Does the whole of `segment` match? The segment is folded as the pattern's fold folds ({@link CompiledSegmentPattern.fold}) —
434
+ * by the caller; a segment that holds a separator never matches. */
435
+ test(segment: string): boolean;
436
+ /** The pattern is stars only: it matches every one segment. */
437
+ readonly anything: boolean;
438
+ }
419
439
  /** A compiled segment-run pattern (shared engine — the write guard delegates here too). */
420
440
  export interface CompiledSegmentPattern {
421
441
  raw: string;
422
- segments: RegExp[];
423
- /** Fold BOTH sides through {@link asciiLower} before testing (compile lowered the pattern side). */
424
- foldAscii: boolean;
442
+ segments: SegmentMatcher[];
443
+ /** Fold BOTH sides before testing: compile folded the pattern side; the segments tested are folded the same way. */
444
+ fold: SegmentFold;
425
445
  /** The segment lists of the directories the run is ANCHORED at (folded as the pattern folds): the run must start
426
446
  * right after one of them. Absent = the run matches anywhere. */
427
447
  anchors?: readonly (readonly string[])[];
@@ -437,12 +457,14 @@ export interface CompiledSegmentPattern {
437
457
  * Compile one segment-glob pattern (shared engine). `fold`:
438
458
  * · "none" — byte-exact segments;
439
459
  * · "ascii" — ASCII-case-insensitive (deny-set contract);
440
- * · "unicode" — RegExp `i` flag (the write guard's historical host-keyed behavior — kept for it
441
- * byte-identically; NOT used by the deny set).
460
+ * · "unicode" — the fold a RegExp `i` flag applies, {@link ignoreCaseFold} (the write guard's historical host-keyed
461
+ * behavior — kept for it answer for answer; NOT used by the deny set).
462
+ * The pattern is folded here, once; the segments a row is tested on are folded by whoever tests, once per path
463
+ * ({@link segmentReadingsOf}) — never once per row per test.
442
464
  * Returns null when the pattern reduces to zero segments — the CALLER owns its loud path (the two
443
465
  * consumers refuse with their own surface-specific texts).
444
466
  */
445
- export declare function compileSegmentPattern(raw: string, fold: "none" | "ascii" | "unicode"): CompiledSegmentPattern | null;
467
+ export declare function compileSegmentPattern(raw: string, fold: SegmentFold): CompiledSegmentPattern | null;
446
468
  /**
447
469
  * Does the path contain a compiled pattern as a CONTIGUOUS run of full path segments? (Shared engine:
448
470
  * `.git/hooks` matches `/repo/.git/hooks/pre-commit`; `.ssh` matches any `.ssh` segment.) An ANCHORED pattern