@sayknow-cli/coding-agent 0.3.16 → 0.4.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 (1474) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/package.json +127 -110
  3. package/scripts/build-sdk-package-smoke.ts +132 -0
  4. package/scripts/capture-notifications-settings-showcase.ts +435 -0
  5. package/scripts/compile-args.ts +5 -2
  6. package/scripts/g005-daemon-smoke.ts +4 -5
  7. package/scripts/g011-daemon-path-smoke.ts +5 -5
  8. package/scripts/generate-hotkeys-docs.ts +74 -0
  9. package/scripts/generate-sdk-adapter-parity-manifest.ts +163 -0
  10. package/scripts/generate-sdk-operation-inventory.ts +914 -0
  11. package/scripts/generate-telegram-baseline-manifest.ts +128 -0
  12. package/scripts/manifest-schema.ts +124 -0
  13. package/scripts/run-test-manifest.ts +153 -0
  14. package/scripts/run-threat-model-check.ts +217 -0
  15. package/scripts/verify-skc-sdk-canonicalization.ts +3647 -0
  16. package/scripts/verify-skc-sdk-rename.ts +90 -0
  17. package/src/append-only-mode.ts +1 -1
  18. package/src/async/job-manager.ts +455 -69
  19. package/src/cli/args.ts +43 -12
  20. package/src/cli/auth-gateway-cli.ts +2 -2
  21. package/src/cli/config-cli.ts +77 -3
  22. package/src/cli/daemon-cli.ts +63 -14
  23. package/src/cli/launch-disposition.ts +42 -0
  24. package/src/cli/list-models.ts +1 -1
  25. package/src/cli/notify-cli.ts +373 -283
  26. package/src/cli/session-picker.ts +20 -3
  27. package/src/cli/setup-cli.ts +1 -1
  28. package/src/cli/worktree-cli.ts +9 -287
  29. package/src/cli.ts +31 -11
  30. package/src/commands/config.ts +1 -1
  31. package/src/commands/daemon.ts +50 -6
  32. package/src/commands/gc.ts +11 -1
  33. package/src/commands/harness.ts +127 -142
  34. package/src/commands/launch.ts +11 -6
  35. package/src/commands/mcp-serve.ts +97 -13
  36. package/src/commands/mcp.ts +2 -2
  37. package/src/commands/notify.ts +44 -7
  38. package/src/commands/sdk.ts +453 -0
  39. package/src/commands/ultragoal.ts +4 -1
  40. package/src/commands/worktree.ts +10 -53
  41. package/src/commit/agentic/agent.ts +1 -0
  42. package/src/config/atomic-yaml-patch.ts +490 -0
  43. package/src/config/file-lock.ts +105 -43
  44. package/src/config/keybindings.ts +64 -20
  45. package/src/config/model-auth.ts +9 -0
  46. package/src/config/model-bindings-applier.ts +139 -0
  47. package/src/config/model-discovery-manager.ts +224 -0
  48. package/src/config/model-equivalence.ts +66 -0
  49. package/src/config/model-profile-activation.ts +233 -86
  50. package/src/config/model-profiles.ts +52 -49
  51. package/src/config/model-registry.ts +5 -4
  52. package/src/config/model-resolver.ts +487 -410
  53. package/src/config/model-selector-value.ts +50 -0
  54. package/src/config/models-config-schema.ts +17 -23
  55. package/src/config/settings-schema.ts +372 -21
  56. package/src/config/settings.ts +1120 -182
  57. package/src/coordinator-mcp/model-preset.ts +74 -20
  58. package/src/coordinator-mcp/policy.ts +76 -11
  59. package/src/coordinator-mcp/question-gate-codec.ts +274 -0
  60. package/src/coordinator-mcp/question-state.ts +778 -0
  61. package/src/coordinator-mcp/server.ts +3120 -3111
  62. package/src/daemon/builtin.ts +8 -5
  63. package/src/daemon/control-types.ts +1 -1
  64. package/src/daemon/runtime.ts +2 -2
  65. package/src/debug/index.ts +1 -1
  66. package/src/defaults/skc/skills/team/SKILL.md +27 -13
  67. package/src/defaults/skc/skills/ultragoal/SKILL.md +0 -2
  68. package/src/discovery/helpers.ts +1 -50
  69. package/src/discovery/mcp-json.ts +327 -20
  70. package/src/edit/index.ts +64 -0
  71. package/src/eval/js/shared/runtime.ts +1 -1
  72. package/src/eval/py/env.ts +26 -0
  73. package/src/eval/py/index.ts +2 -2
  74. package/src/eval/py/kernel.ts +5 -3
  75. package/src/export/html/template.generated.ts +1 -1
  76. package/src/export/html/template.js +52 -18
  77. package/src/extensibility/custom-tools/types.ts +1 -1
  78. package/src/extensibility/extensions/compact-handler.ts +3 -3
  79. package/src/extensibility/extensions/get-commands-handler.ts +2 -2
  80. package/src/extensibility/extensions/loader.ts +77 -5
  81. package/src/extensibility/extensions/runner.ts +124 -7
  82. package/src/extensibility/extensions/types.ts +215 -18
  83. package/src/extensibility/hooks/runner.ts +2 -2
  84. package/src/extensibility/hooks/types.ts +1 -1
  85. package/src/extensibility/plugins/marketplace/manager.ts +94 -10
  86. package/src/extensibility/runtime-skill-discovery.ts +33 -13
  87. package/src/extensibility/shared-events.ts +2 -0
  88. package/src/extensibility/skc-plugins/installer.ts +16 -16
  89. package/src/extensibility/slash-commands.ts +3 -3
  90. package/src/goals/continuation-timeout-guard.ts +79 -0
  91. package/src/goals/runtime.ts +7 -5
  92. package/src/goals/state.ts +18 -0
  93. package/src/harness-control-plane/lifecycle-reconciliation.ts +64 -0
  94. package/src/harness-control-plane/operate.ts +9 -9
  95. package/src/harness-control-plane/owner.ts +341 -41
  96. package/src/harness-control-plane/phase-rollup.ts +4 -7
  97. package/src/harness-control-plane/receipt-ingest.ts +5 -0
  98. package/src/harness-control-plane/receipt-spool.ts +51 -7
  99. package/src/harness-control-plane/receipts.ts +0 -1
  100. package/src/harness-control-plane/sdk-transport.ts +395 -0
  101. package/src/harness-control-plane/session-lease.ts +12 -130
  102. package/src/harness-control-plane/session-transport.ts +94 -0
  103. package/src/harness-control-plane/types.ts +1 -1
  104. package/src/hindsight/backend.ts +26 -27
  105. package/src/hindsight/client.ts +65 -2
  106. package/src/hindsight/state.ts +101 -32
  107. package/src/hooks/skill-state.ts +17 -11
  108. package/src/i18n/messages/en.ts +1 -0
  109. package/src/internal-urls/agent-protocol.ts +76 -5
  110. package/src/internal-urls/docs-index.generated.ts +44 -37
  111. package/src/internal-urls/local-protocol.ts +420 -18
  112. package/src/lsp/client.ts +43 -7
  113. package/src/lsp/config.ts +145 -26
  114. package/src/lsp/index.ts +7 -91
  115. package/src/lsp/lspmux.ts +39 -10
  116. package/src/lsp/path-trust.ts +81 -0
  117. package/src/main.ts +451 -236
  118. package/src/memories/index.ts +1 -0
  119. package/src/memories/storage.ts +6 -2
  120. package/src/modes/DESIGN.md +258 -0
  121. package/src/modes/acp/acp-agent.ts +1236 -2612
  122. package/src/modes/acp/acp-client-bridge.ts +2 -20
  123. package/src/modes/acp/acp-event-mapper.ts +18 -2
  124. package/src/modes/acp/acp-mode.ts +8 -36
  125. package/src/modes/acp/permission-mode.ts +25 -0
  126. package/src/modes/acp/startup-options.ts +6 -0
  127. package/src/modes/action-registry.ts +165 -0
  128. package/src/modes/bridge/bridge-mode.ts +6 -4
  129. package/src/modes/components/agent-dashboard.ts +37 -17
  130. package/src/modes/components/ansi-display-validator.ts +54 -0
  131. package/src/modes/components/chrome.ts +40 -0
  132. package/src/modes/components/command-palette.ts +168 -0
  133. package/src/modes/components/custom-editor.ts +105 -33
  134. package/src/modes/components/custom-provider-wizard.ts +77 -15
  135. package/src/modes/components/index.ts +2 -1
  136. package/src/modes/components/model-selector.ts +93 -35
  137. package/src/modes/components/notifications-settings-editor.ts +1403 -0
  138. package/src/modes/components/pet-capability.ts +115 -0
  139. package/src/modes/components/pet-selector.ts +15 -23
  140. package/src/modes/components/plan-preview-overlay.ts +295 -0
  141. package/src/modes/components/queue-mode-selector.ts +10 -27
  142. package/src/modes/components/queue-pane.ts +79 -0
  143. package/src/modes/components/read-tool-group.ts +13 -0
  144. package/src/modes/components/sayknow-pet-widget.ts +169 -20
  145. package/src/modes/components/session-observer-overlay.ts +213 -775
  146. package/src/modes/components/sessions-dashboard.ts +181 -0
  147. package/src/modes/components/settings-selector.ts +89 -12
  148. package/src/modes/components/show-images-selector.ts +10 -24
  149. package/src/modes/components/status-line/types.ts +1 -1
  150. package/src/modes/components/status-line.ts +1 -969
  151. package/src/modes/components/tasks-pane.ts +73 -0
  152. package/src/modes/components/theme-selector.ts +11 -31
  153. package/src/modes/components/tool-execution.ts +22 -0
  154. package/src/modes/components/tool-status-header.ts +1056 -0
  155. package/src/modes/components/tool-transcript-format.ts +393 -0
  156. package/src/modes/components/transcript-viewer-overlay.ts +446 -0
  157. package/src/modes/components/welcome.ts +4 -4
  158. package/src/modes/controllers/btw-controller.ts +1 -0
  159. package/src/modes/controllers/command-controller.ts +25 -17
  160. package/src/modes/controllers/event-controller.ts +14 -18
  161. package/src/modes/controllers/extension-ui-controller.ts +441 -37
  162. package/src/modes/controllers/goal-mode-controller.ts +493 -0
  163. package/src/modes/controllers/input-controller.ts +889 -263
  164. package/src/modes/controllers/mode-gate.ts +24 -0
  165. package/src/modes/controllers/plan-mode-controller.ts +519 -0
  166. package/src/modes/controllers/runtime-mcp-command-controller.ts +3 -0
  167. package/src/modes/controllers/selector-controller.ts +957 -54
  168. package/src/modes/controllers/stt-controller.ts +125 -0
  169. package/src/modes/index.ts +0 -22
  170. package/src/modes/interactive-mode.ts +376 -1130
  171. package/src/modes/jobs-observer.ts +3 -0
  172. package/src/modes/prompt-action-autocomplete.ts +7 -0
  173. package/src/modes/rpc/rpc-mode.ts +3 -1
  174. package/src/modes/runtime-init.ts +320 -6
  175. package/src/modes/shared/agent-wire/approval-gate.ts +9 -11
  176. package/src/modes/shared/agent-wire/command-dispatch.ts +3 -1
  177. package/src/modes/shared/agent-wire/deep-interview-gate.ts +65 -111
  178. package/src/modes/shared/agent-wire/event-contract.ts +7 -8
  179. package/src/modes/shared/agent-wire/event-envelope.ts +9 -17
  180. package/src/modes/shared/agent-wire/event-observation.ts +16 -7
  181. package/src/modes/shared/agent-wire/workflow-gate-broker.ts +1331 -89
  182. package/src/modes/shared/agent-wire/workflow-gate-schema.ts +19 -17
  183. package/src/modes/shared/agent-wire/workflow-gate-types.ts +407 -0
  184. package/src/modes/tasks-aggregator.ts +199 -0
  185. package/src/modes/transcript-item-registry.ts +229 -0
  186. package/src/modes/types.ts +63 -21
  187. package/src/modes/utils/ui-helpers.ts +17 -9
  188. package/src/notifications/index.ts +8 -2
  189. package/src/plan-mode/approved-plan.ts +3 -1
  190. package/src/prompts/agent-fragments/ralplan-persistence.md +6 -0
  191. package/src/prompts/agent-fragments/restricted-bash.md +1 -0
  192. package/src/prompts/agents/architect.md +3 -8
  193. package/src/prompts/agents/critic.md +3 -8
  194. package/src/prompts/agents/executor.md +3 -0
  195. package/src/prompts/agents/planner.md +4 -12
  196. package/src/prompts/system/custom-system-prompt.md +2 -24
  197. package/src/prompts/system/plan-mode-approved.md +8 -0
  198. package/src/prompts/system/system-prompt.md +18 -94
  199. package/src/prompts/tools/bash.md +4 -4
  200. package/src/prompts/tools/browser.md +15 -52
  201. package/src/prompts/tools/find.md +2 -2
  202. package/src/prompts/tools/hashline.md +13 -55
  203. package/src/prompts/tools/lsp.md +3 -3
  204. package/src/prompts/tools/read.md +3 -6
  205. package/src/prompts/tools/search-tool-bm25.md +0 -2
  206. package/src/prompts/tools/search.md +2 -4
  207. package/src/prompts/tools/skill-discovery.md +1 -2
  208. package/src/prompts/tools/task.md +1 -1
  209. package/src/runtime-mcp/client.ts +94 -19
  210. package/src/runtime-mcp/config.ts +27 -15
  211. package/src/runtime-mcp/discoverable-tool-metadata.ts +16 -13
  212. package/src/runtime-mcp/manager.ts +359 -106
  213. package/src/runtime-mcp/oauth-discovery.ts +116 -26
  214. package/src/runtime-mcp/oauth-flow.ts +42 -12
  215. package/src/runtime-mcp/transports/http.ts +49 -19
  216. package/src/runtime-mcp/transports/stdio.ts +47 -28
  217. package/src/runtime-mcp/types.ts +10 -0
  218. package/src/sdk/acp/adapter.ts +418 -0
  219. package/src/sdk/acp/index.ts +2 -0
  220. package/src/sdk/broker/broker.ts +877 -0
  221. package/src/sdk/broker/discovery.ts +238 -0
  222. package/src/sdk/broker/ensure.ts +393 -0
  223. package/src/sdk/broker/identity.ts +42 -0
  224. package/src/sdk/broker/index.ts +8 -0
  225. package/src/sdk/broker/internal-source-marker-2178.txt +1 -0
  226. package/src/sdk/broker/internal-source.bunfig.toml +1 -0
  227. package/src/sdk/broker/internal.ts +10 -0
  228. package/src/sdk/broker/lifecycle-codec.ts +11 -0
  229. package/src/sdk/broker/lifecycle-ledger.ts +583 -0
  230. package/src/sdk/broker/lifecycle.ts +3413 -0
  231. package/src/sdk/broker/process-incarnation.ts +151 -0
  232. package/src/sdk/broker/runtime.ts +164 -0
  233. package/src/sdk/broker/session-index.ts +678 -0
  234. package/src/sdk/broker/state-version.ts +47 -0
  235. package/src/sdk/broker/transport.ts +125 -0
  236. package/src/sdk/bus/attachment-registry.ts +23 -0
  237. package/src/sdk/bus/chat-adapters.ts +147 -0
  238. package/src/sdk/bus/chat-command-policy.ts +107 -0
  239. package/src/sdk/bus/chat-daemon-cli.ts +278 -0
  240. package/src/sdk/bus/chat-daemon-control.ts +1101 -0
  241. package/src/sdk/bus/chat-daemon-runtime.ts +527 -0
  242. package/src/sdk/bus/chat-effect-journal.ts +363 -0
  243. package/src/sdk/bus/config-commands.ts +192 -0
  244. package/src/sdk/bus/config.ts +568 -0
  245. package/src/sdk/bus/conversation-store.ts +367 -0
  246. package/src/sdk/bus/daemon-paths.ts +34 -0
  247. package/src/sdk/bus/discord-conversation.ts +85 -0
  248. package/src/sdk/bus/discord-daemon.ts +2292 -0
  249. package/src/sdk/bus/discord-live-provider.ts +521 -0
  250. package/src/sdk/bus/discord-provider.ts +56 -0
  251. package/src/sdk/bus/engine.ts +100 -0
  252. package/src/sdk/bus/helpers.ts +135 -0
  253. package/src/sdk/bus/html-format.ts +518 -0
  254. package/src/sdk/bus/index.ts +4961 -0
  255. package/src/sdk/bus/lifecycle-commands.ts +291 -0
  256. package/src/sdk/bus/lifecycle-control-runtime.ts +1409 -0
  257. package/src/sdk/bus/lifecycle-orchestrator.ts +458 -0
  258. package/src/sdk/bus/managed-daemon.ts +163 -0
  259. package/src/sdk/bus/native-runtime-compatibility.ts +42 -0
  260. package/src/sdk/bus/natives-augment.d.ts +63 -0
  261. package/src/sdk/bus/notification-orchestration.ts +535 -0
  262. package/src/sdk/bus/notification-service.ts +1174 -0
  263. package/src/sdk/bus/operator-runtime.ts +171 -0
  264. package/src/sdk/bus/rate-limit-pool.ts +276 -0
  265. package/src/sdk/bus/recent-activity.ts +279 -0
  266. package/src/sdk/bus/reply-sent-store.ts +134 -0
  267. package/src/sdk/bus/rich-document.ts +258 -0
  268. package/src/sdk/bus/rich-draft.ts +107 -0
  269. package/src/sdk/bus/rich-render.ts +135 -0
  270. package/src/sdk/bus/session-control.ts +439 -0
  271. package/src/sdk/bus/slack-conversation.ts +74 -0
  272. package/src/sdk/bus/slack-daemon.ts +2144 -0
  273. package/src/sdk/bus/slack-live-provider.ts +380 -0
  274. package/src/sdk/bus/slack-provider.ts +76 -0
  275. package/src/sdk/bus/telegram-cli.ts +194 -0
  276. package/src/sdk/bus/telegram-daemon-cli.ts +292 -0
  277. package/src/sdk/bus/telegram-daemon-contract.ts +27 -0
  278. package/src/sdk/bus/telegram-daemon-control.ts +642 -0
  279. package/src/sdk/bus/telegram-daemon.ts +6675 -0
  280. package/src/sdk/bus/telegram-reference.ts +436 -0
  281. package/src/sdk/bus/telegram-setup.ts +663 -0
  282. package/src/sdk/bus/threaded-inbound.ts +141 -0
  283. package/src/sdk/bus/threaded-render.ts +294 -0
  284. package/src/sdk/bus/topic-registry.ts +364 -0
  285. package/src/sdk/cli/index.ts +1 -0
  286. package/src/sdk/cli/session-cli.ts +275 -0
  287. package/src/sdk/client/client.ts +1 -0
  288. package/src/sdk/client/discovery.ts +108 -0
  289. package/src/sdk/client/index.ts +2 -0
  290. package/src/sdk/host/control/dispatch.ts +388 -0
  291. package/src/sdk/host/control/index.ts +10 -0
  292. package/src/sdk/host/control/operations.ts +68 -0
  293. package/src/sdk/host/events.ts +91 -0
  294. package/src/sdk/host/host.ts +338 -0
  295. package/src/sdk/host/index.ts +4 -0
  296. package/src/sdk/host/query/cursor.ts +189 -0
  297. package/src/sdk/host/query/handlers.ts +531 -0
  298. package/src/sdk/host/query/index.ts +3 -0
  299. package/src/sdk/host/query/revision-store.ts +1149 -0
  300. package/src/sdk/host/reverse-leases.ts +325 -0
  301. package/src/sdk/host/types.ts +29 -0
  302. package/src/sdk/index.ts +14 -0
  303. package/src/sdk/lifecycle-session.ts +39 -0
  304. package/src/sdk/mcp/index.ts +1 -0
  305. package/src/sdk/mcp/server.ts +332 -0
  306. package/src/sdk/models.ts +168 -0
  307. package/src/sdk/protocol/adapter-validation.ts +48 -0
  308. package/src/sdk/protocol/operation-inventory.generated.json +4719 -0
  309. package/src/sdk/protocol/operation-registry.ts +312 -0
  310. package/src/sdk/session-directory.ts +141 -0
  311. package/src/sdk/session.ts +2869 -0
  312. package/src/sdk/startup-capability.ts +189 -0
  313. package/src/secrets/index.ts +53 -10
  314. package/src/secrets/obfuscator.ts +21 -18
  315. package/src/secrets/regex.ts +2 -0
  316. package/src/session/agent-session.ts +5602 -2138
  317. package/src/session/agent-storage.ts +18 -0
  318. package/src/session/artifacts.ts +188 -23
  319. package/src/session/cache-economics.ts +25 -8
  320. package/src/session/context-estimation.ts +7 -2
  321. package/src/session/default-model-selection.ts +93 -0
  322. package/src/session/fallback-chain-controller.ts +186 -0
  323. package/src/session/internal/managed-session-scope.ts +2402 -0
  324. package/src/session/internal/managed-session-storage.ts +1559 -0
  325. package/src/session/messages.ts +91 -2
  326. package/src/session/session-manager-internal.ts +33 -0
  327. package/src/session/session-manager.ts +2578 -392
  328. package/src/session/session-storage.ts +550 -40
  329. package/src/session/streaming-output.ts +6 -0
  330. package/src/session/volatile-context-pruning.ts +78 -0
  331. package/src/session/yield-queue.ts +20 -0
  332. package/src/setup/credential-auto-import.ts +291 -35
  333. package/src/setup/hermes/templates/operator-instructions.v1.md +4 -6
  334. package/src/setup/provider-onboarding.ts +36 -61
  335. package/src/setup/provider-presets.json +5 -0
  336. package/src/skc-runtime/deep-interview-recorder.ts +70 -3
  337. package/src/skc-runtime/deep-interview-state.ts +441 -5
  338. package/src/skc-runtime/gc-render.ts +19 -1
  339. package/src/skc-runtime/gc-runtime.ts +68 -3
  340. package/src/skc-runtime/goal-mode-request.ts +55 -8
  341. package/src/skc-runtime/launch-worktree.ts +5 -5
  342. package/src/skc-runtime/linux-proc.ts +71 -0
  343. package/src/skc-runtime/managed-owner-admission.ts +352 -0
  344. package/src/skc-runtime/managed-owner-supervisor.ts +162 -0
  345. package/src/skc-runtime/psmux-detect.ts +82 -4
  346. package/src/skc-runtime/ralplan-runtime.ts +74 -90
  347. package/src/skc-runtime/session-resolution.ts +18 -3
  348. package/src/skc-runtime/session-state-sidecar.ts +47 -138
  349. package/src/skc-runtime/state-argv.ts +292 -0
  350. package/src/skc-runtime/state-migrations.ts +1 -1
  351. package/src/skc-runtime/state-runtime.ts +387 -451
  352. package/src/skc-runtime/state-writer.ts +36 -40
  353. package/src/skc-runtime/team-launch.ts +319 -0
  354. package/src/skc-runtime/team-notify.ts +326 -0
  355. package/src/skc-runtime/team-runtime.ts +8 -2
  356. package/src/skc-runtime/team-store.ts +828 -0
  357. package/src/skc-runtime/team-workers.ts +962 -0
  358. package/src/skc-runtime/tmux-owner-isolation-cli.ts +55 -28
  359. package/src/skc-runtime/tmux-owner-isolation.ts +136 -11
  360. package/src/skc-runtime/tmux-sessions.ts +23 -34
  361. package/src/skc-runtime/ultragoal-change-set.ts +172 -0
  362. package/src/skc-runtime/ultragoal-evidence.ts +874 -0
  363. package/src/skc-runtime/ultragoal-guard.ts +136 -18
  364. package/src/skc-runtime/ultragoal-owner-loss-recovery.ts +328 -0
  365. package/src/skc-runtime/ultragoal-pipeline.ts +306 -0
  366. package/src/skc-runtime/ultragoal-receipt-freshness.ts +102 -1
  367. package/src/skc-runtime/ultragoal-runtime.ts +325 -1322
  368. package/src/skc-runtime/windows-powershell-command.ts +58 -0
  369. package/src/skc-runtime/workflow-cli-common.ts +30 -0
  370. package/src/skc-runtime/workflow-manifest.generated.json +58 -0
  371. package/src/skc-runtime/workflow-manifest.ts +18 -0
  372. package/src/skill-state/active-state.ts +3 -13
  373. package/src/skill-state/workflow-mutation-guard.ts +661 -0
  374. package/src/skill-state/workflow-state-contract.ts +6 -41
  375. package/src/slash-commands/builtin-registry.ts +115 -41
  376. package/src/system-prompt.ts +37 -44
  377. package/src/task/agents.ts +19 -1
  378. package/src/task/executor.ts +223 -45
  379. package/src/task/index.ts +124 -56
  380. package/src/thinking.ts +21 -6
  381. package/src/tool-discovery/tool-index.ts +20 -134
  382. package/src/tools/ask-answer-registry.ts +16 -2
  383. package/src/tools/ast-edit.ts +1 -1
  384. package/src/tools/bash-allowed-prefixes.ts +79 -29
  385. package/src/tools/bash-skill-urls.ts +14 -3
  386. package/src/tools/bash.ts +40 -2
  387. package/src/tools/browser/STEALTH-THIRD-PARTY-NOTICES.md +26 -0
  388. package/src/tools/browser/benchmark/detector-report.ts +157 -0
  389. package/src/tools/browser/benchmark/run-suite.ts +39 -0
  390. package/src/tools/browser/dead-tab-recovery.ts +78 -0
  391. package/src/tools/browser/launch.ts +127 -20
  392. package/src/tools/browser/profile-discovery.ts +63 -0
  393. package/src/tools/browser/profile-posture.ts +59 -0
  394. package/src/tools/browser/profile-reuse.ts +102 -0
  395. package/src/tools/browser/profile-warmup.ts +109 -0
  396. package/src/tools/browser/readable.ts +1 -1
  397. package/src/tools/browser/registry.ts +87 -11
  398. package/src/tools/browser/screenshot-format.ts +34 -0
  399. package/src/tools/browser/tab-protocol.ts +4 -0
  400. package/src/tools/browser/tab-supervisor.ts +392 -142
  401. package/src/tools/browser/tab-worker-entry.ts +33 -14
  402. package/src/tools/browser/tab-worker-path-resolver.ts +67 -0
  403. package/src/tools/browser/tab-worker-smoke.ts +87 -0
  404. package/src/tools/browser/tab-worker.ts +8 -6
  405. package/src/tools/browser.ts +6 -0
  406. package/src/tools/computer.ts +10 -3
  407. package/src/tools/cron.ts +30 -16
  408. package/src/tools/fetch.ts +11 -4
  409. package/src/tools/index.ts +88 -32
  410. package/src/tools/output-meta.ts +19 -7
  411. package/src/tools/path-utils.ts +42 -35
  412. package/src/tools/plan-mode-guard.ts +1 -0
  413. package/src/tools/puppeteer/14_stealth_permissions.txt +57 -0
  414. package/src/tools/puppeteer/15_stealth_webrtc.txt +60 -0
  415. package/src/tools/read.ts +226 -65
  416. package/src/tools/resource-gc.ts +125 -36
  417. package/src/tools/search-tool-bm25.ts +11 -74
  418. package/src/tools/sqlite-reader.ts +3 -2
  419. package/src/tools/subagent-render.ts +19 -8
  420. package/src/tools/subagent.ts +129 -34
  421. package/src/tools/telegram-send.ts +2 -2
  422. package/src/utils/event-bus.ts +9 -4
  423. package/src/utils/file-mentions.ts +4 -4
  424. package/src/utils/image-loading.ts +85 -34
  425. package/src/utils/image-resize.ts +16 -9
  426. package/src/utils/pasted-image-loading.ts +514 -0
  427. package/src/utils/pasted-image-path.ts +223 -98
  428. package/src/web/scrapers/html-to-markdown.ts +68 -0
  429. package/src/web/scrapers/readthedocs.ts +1 -1
  430. package/src/web/scrapers/types.ts +1 -68
  431. package/src/web/search/index.ts +3 -3
  432. package/src/web/search/providers/openai-compatible.ts +76 -23
  433. package/dist/types/append-only-mode.d.ts +0 -31
  434. package/dist/types/async/index.d.ts +0 -2
  435. package/dist/types/async/job-manager.d.ts +0 -328
  436. package/dist/types/async/support.d.ts +0 -2
  437. package/dist/types/autoresearch/dashboard.d.ts +0 -4
  438. package/dist/types/autoresearch/git.d.ts +0 -36
  439. package/dist/types/autoresearch/helpers.d.ts +0 -24
  440. package/dist/types/autoresearch/index.d.ts +0 -2
  441. package/dist/types/autoresearch/state.d.ts +0 -17
  442. package/dist/types/autoresearch/storage.d.ts +0 -142
  443. package/dist/types/autoresearch/tools/init-experiment.d.ts +0 -31
  444. package/dist/types/autoresearch/tools/log-experiment.d.ts +0 -23
  445. package/dist/types/autoresearch/tools/run-experiment.d.ts +0 -8
  446. package/dist/types/autoresearch/tools/update-notes.d.ts +0 -12
  447. package/dist/types/autoresearch/types.d.ts +0 -154
  448. package/dist/types/build-metadata.d.ts +0 -7
  449. package/dist/types/capability/context-file.d.ts +0 -17
  450. package/dist/types/capability/extension-module.d.ts +0 -15
  451. package/dist/types/capability/extension.d.ts +0 -28
  452. package/dist/types/capability/fs.d.ts +0 -20
  453. package/dist/types/capability/hook.d.ts +0 -19
  454. package/dist/types/capability/index.d.ts +0 -80
  455. package/dist/types/capability/instruction.d.ts +0 -17
  456. package/dist/types/capability/mcp.d.ts +0 -49
  457. package/dist/types/capability/prompt.d.ts +0 -15
  458. package/dist/types/capability/rule.d.ts +0 -69
  459. package/dist/types/capability/settings.d.ts +0 -15
  460. package/dist/types/capability/skill.d.ts +0 -36
  461. package/dist/types/capability/slash-command.d.ts +0 -17
  462. package/dist/types/capability/ssh.d.ts +0 -23
  463. package/dist/types/capability/system-prompt.d.ts +0 -15
  464. package/dist/types/capability/tool.d.ts +0 -19
  465. package/dist/types/capability/types.d.ts +0 -154
  466. package/dist/types/cli/agents-cli.d.ts +0 -12
  467. package/dist/types/cli/args.d.ts +0 -57
  468. package/dist/types/cli/auth-broker-cli.d.ts +0 -25
  469. package/dist/types/cli/auth-gateway-cli.d.ts +0 -18
  470. package/dist/types/cli/classify-install-target.d.ts +0 -8
  471. package/dist/types/cli/commands/init-xdg.d.ts +0 -1
  472. package/dist/types/cli/completion-cli.d.ts +0 -41
  473. package/dist/types/cli/config-cli.d.ts +0 -23
  474. package/dist/types/cli/daemon-cli.d.ts +0 -27
  475. package/dist/types/cli/fast-help.d.ts +0 -1
  476. package/dist/types/cli/file-processor.d.ts +0 -11
  477. package/dist/types/cli/fixture-report.d.ts +0 -20
  478. package/dist/types/cli/fixture-report.test.d.ts +0 -1
  479. package/dist/types/cli/grep-cli.d.ts +0 -17
  480. package/dist/types/cli/initial-message.d.ts +0 -17
  481. package/dist/types/cli/list-models.d.ts +0 -36
  482. package/dist/types/cli/local-provider-smoke.d.ts +0 -59
  483. package/dist/types/cli/malloc-env-guard.d.ts +0 -65
  484. package/dist/types/cli/malloc-env-guard.test.d.ts +0 -1
  485. package/dist/types/cli/mcp-cli.d.ts +0 -25
  486. package/dist/types/cli/migrate-cli.d.ts +0 -20
  487. package/dist/types/cli/nofile-limit.d.ts +0 -11
  488. package/dist/types/cli/notify-cli.d.ts +0 -39
  489. package/dist/types/cli/plugin-cli.d.ts +0 -34
  490. package/dist/types/cli/read-cli.d.ts +0 -4
  491. package/dist/types/cli/session-picker.d.ts +0 -4
  492. package/dist/types/cli/setup-cli.d.ts +0 -73
  493. package/dist/types/cli/shell-cli.d.ts +0 -8
  494. package/dist/types/cli/skills-cli.d.ts +0 -9
  495. package/dist/types/cli/ssh-cli.d.ts +0 -21
  496. package/dist/types/cli/stats-cli.d.ts +0 -17
  497. package/dist/types/cli/telegram-cli.d.ts +0 -13
  498. package/dist/types/cli/update-cli.d.ts +0 -108
  499. package/dist/types/cli/web-search-cli.d.ts +0 -32
  500. package/dist/types/cli/worktree-cli.d.ts +0 -26
  501. package/dist/types/cli.d.ts +0 -140
  502. package/dist/types/commands/acp.d.ts +0 -12
  503. package/dist/types/commands/agents.d.ts +0 -34
  504. package/dist/types/commands/auth-broker.d.ts +0 -54
  505. package/dist/types/commands/auth-gateway.d.ts +0 -32
  506. package/dist/types/commands/codex-native-hook.d.ts +0 -6
  507. package/dist/types/commands/commit.d.ts +0 -27
  508. package/dist/types/commands/completion.d.ts +0 -29
  509. package/dist/types/commands/config.d.ts +0 -33
  510. package/dist/types/commands/contribution-prep.d.ts +0 -18
  511. package/dist/types/commands/coordinator.d.ts +0 -19
  512. package/dist/types/commands/daemon.d.ts +0 -45
  513. package/dist/types/commands/deep-interview.d.ts +0 -54
  514. package/dist/types/commands/gc.d.ts +0 -26
  515. package/dist/types/commands/grep.d.ts +0 -42
  516. package/dist/types/commands/harness.d.ts +0 -43
  517. package/dist/types/commands/launch.d.ts +0 -131
  518. package/dist/types/commands/local-provider.d.ts +0 -34
  519. package/dist/types/commands/mcp-serve.d.ts +0 -24
  520. package/dist/types/commands/mcp.d.ts +0 -70
  521. package/dist/types/commands/migrate.d.ts +0 -33
  522. package/dist/types/commands/notify.d.ts +0 -47
  523. package/dist/types/commands/plugin.d.ts +0 -58
  524. package/dist/types/commands/ralplan.d.ts +0 -7
  525. package/dist/types/commands/read.d.ts +0 -15
  526. package/dist/types/commands/rlm.d.ts +0 -10
  527. package/dist/types/commands/session.d.ts +0 -30
  528. package/dist/types/commands/setup.d.ts +0 -105
  529. package/dist/types/commands/shell.d.ts +0 -21
  530. package/dist/types/commands/skills.d.ts +0 -26
  531. package/dist/types/commands/ssh.d.ts +0 -48
  532. package/dist/types/commands/state.d.ts +0 -7
  533. package/dist/types/commands/stats.d.ts +0 -25
  534. package/dist/types/commands/team.d.ts +0 -24
  535. package/dist/types/commands/telegram.d.ts +0 -22
  536. package/dist/types/commands/ultragoal.d.ts +0 -8
  537. package/dist/types/commands/update.d.ts +0 -20
  538. package/dist/types/commands/web-search.d.ts +0 -87
  539. package/dist/types/commands/worktree.d.ts +0 -34
  540. package/dist/types/commit/agentic/agent.d.ts +0 -31
  541. package/dist/types/commit/agentic/fallback.d.ts +0 -5
  542. package/dist/types/commit/agentic/index.d.ts +0 -2
  543. package/dist/types/commit/agentic/state.d.ts +0 -58
  544. package/dist/types/commit/agentic/tools/analyze-file.d.ts +0 -19
  545. package/dist/types/commit/agentic/tools/git-file-diff.d.ts +0 -10
  546. package/dist/types/commit/agentic/tools/git-hunk.d.ts +0 -9
  547. package/dist/types/commit/agentic/tools/git-overview.d.ts +0 -9
  548. package/dist/types/commit/agentic/tools/index.d.ts +0 -16
  549. package/dist/types/commit/agentic/tools/propose-changelog.d.ts +0 -28
  550. package/dist/types/commit/agentic/tools/propose-commit.d.ts +0 -36
  551. package/dist/types/commit/agentic/tools/recent-commits.d.ts +0 -7
  552. package/dist/types/commit/agentic/tools/schemas.d.ts +0 -27
  553. package/dist/types/commit/agentic/tools/split-commit.d.ts +0 -53
  554. package/dist/types/commit/agentic/topo-sort.d.ts +0 -4
  555. package/dist/types/commit/agentic/trivial.d.ts +0 -7
  556. package/dist/types/commit/agentic/validation.d.ts +0 -20
  557. package/dist/types/commit/analysis/conventional.d.ts +0 -22
  558. package/dist/types/commit/analysis/index.d.ts +0 -4
  559. package/dist/types/commit/analysis/scope.d.ts +0 -6
  560. package/dist/types/commit/analysis/summary.d.ts +0 -19
  561. package/dist/types/commit/analysis/validation.d.ts +0 -8
  562. package/dist/types/commit/changelog/detect.d.ts +0 -2
  563. package/dist/types/commit/changelog/generate.d.ts +0 -30
  564. package/dist/types/commit/changelog/index.d.ts +0 -30
  565. package/dist/types/commit/changelog/parse.d.ts +0 -2
  566. package/dist/types/commit/cli.d.ts +0 -3
  567. package/dist/types/commit/git/diff.d.ts +0 -5
  568. package/dist/types/commit/index.d.ts +0 -4
  569. package/dist/types/commit/map-reduce/index.d.ts +0 -28
  570. package/dist/types/commit/map-reduce/map-phase.d.ts +0 -17
  571. package/dist/types/commit/map-reduce/reduce-phase.d.ts +0 -13
  572. package/dist/types/commit/map-reduce/utils.d.ts +0 -2
  573. package/dist/types/commit/message.d.ts +0 -2
  574. package/dist/types/commit/model-selection.d.ts +0 -15
  575. package/dist/types/commit/pipeline.d.ts +0 -5
  576. package/dist/types/commit/shared-llm.d.ts +0 -54
  577. package/dist/types/commit/types.d.ts +0 -78
  578. package/dist/types/commit/utils/exclusions.d.ts +0 -4
  579. package/dist/types/commit/utils.d.ts +0 -20
  580. package/dist/types/config/config-file.d.ts +0 -58
  581. package/dist/types/config/file-lock-gc.d.ts +0 -5
  582. package/dist/types/config/file-lock.d.ts +0 -36
  583. package/dist/types/config/keybindings.d.ts +0 -364
  584. package/dist/types/config/model-equivalence.d.ts +0 -24
  585. package/dist/types/config/model-profile-activation.d.ts +0 -65
  586. package/dist/types/config/model-profiles.d.ts +0 -39
  587. package/dist/types/config/model-registry.d.ts +0 -473
  588. package/dist/types/config/model-resolver.d.ts +0 -217
  589. package/dist/types/config/models-config-schema.d.ts +0 -700
  590. package/dist/types/config/prompt-templates.d.ts +0 -32
  591. package/dist/types/config/resolve-config-value.d.ts +0 -17
  592. package/dist/types/config/settings-schema.d.ts +0 -4223
  593. package/dist/types/config/settings.d.ts +0 -158
  594. package/dist/types/config/skill-settings-defaults.d.ts +0 -14
  595. package/dist/types/config/telegram-autostart.d.ts +0 -14
  596. package/dist/types/config/telegram-env-bridge.d.ts +0 -18
  597. package/dist/types/config.d.ts +0 -66
  598. package/dist/types/coordinator/contract.d.ts +0 -4
  599. package/dist/types/coordinator-mcp/model-preset.d.ts +0 -45
  600. package/dist/types/coordinator-mcp/policy.d.ts +0 -27
  601. package/dist/types/coordinator-mcp/safety.d.ts +0 -26
  602. package/dist/types/coordinator-mcp/server.d.ts +0 -139
  603. package/dist/types/coordinator-mcp/session-reaper.d.ts +0 -53
  604. package/dist/types/cursor.d.ts +0 -24
  605. package/dist/types/daemon/builtin.d.ts +0 -20
  606. package/dist/types/daemon/control-types.d.ts +0 -67
  607. package/dist/types/daemon/operator-contract.d.ts +0 -47
  608. package/dist/types/daemon/runtime.d.ts +0 -25
  609. package/dist/types/dap/client.d.ts +0 -39
  610. package/dist/types/dap/config.d.ts +0 -6
  611. package/dist/types/dap/index.d.ts +0 -4
  612. package/dist/types/dap/session.d.ts +0 -108
  613. package/dist/types/dap/types.d.ts +0 -524
  614. package/dist/types/debug/crash-diagnostics.d.ts +0 -45
  615. package/dist/types/debug/index.d.ts +0 -15
  616. package/dist/types/debug/log-formatting.d.ts +0 -4
  617. package/dist/types/debug/log-viewer.d.ts +0 -68
  618. package/dist/types/debug/profiler.d.ts +0 -24
  619. package/dist/types/debug/raw-sse-buffer.d.ts +0 -44
  620. package/dist/types/debug/raw-sse.d.ts +0 -16
  621. package/dist/types/debug/report-bundle.d.ts +0 -55
  622. package/dist/types/debug/runtime-gauges.d.ts +0 -6
  623. package/dist/types/debug/system-info.d.ts +0 -26
  624. package/dist/types/deep-interview/plaintext-gate-guard.d.ts +0 -11
  625. package/dist/types/deep-interview/render-middleware.d.ts +0 -6
  626. package/dist/types/defaults/skc/extensions/grok-build/index.d.ts +0 -1
  627. package/dist/types/defaults/skc/extensions/grok-cli-vendor/src/index.d.ts +0 -1
  628. package/dist/types/defaults/skc/extensions/grok-cli-vendor/src/models/catalog.d.ts +0 -29
  629. package/dist/types/defaults/skc/extensions/grok-cli-vendor/src/payload/sanitize.d.ts +0 -27
  630. package/dist/types/defaults/skc/extensions/grok-cli-vendor/src/provider/billing.d.ts +0 -8
  631. package/dist/types/defaults/skc/extensions/grok-cli-vendor/src/provider/register.d.ts +0 -5
  632. package/dist/types/defaults/skc/extensions/grok-cli-vendor/src/provider/stream.d.ts +0 -10
  633. package/dist/types/defaults/skc/extensions/grok-cli-vendor/src/provider/usage.d.ts +0 -2
  634. package/dist/types/defaults/skc/extensions/grok-cli-vendor/src/shared/base-url.d.ts +0 -2
  635. package/dist/types/defaults/skc/extensions/grok-cli-vendor/src/shared/errors.d.ts +0 -38
  636. package/dist/types/defaults/skc-defaults.d.ts +0 -64
  637. package/dist/types/defaults/skc-grok-cli.d.ts +0 -5
  638. package/dist/types/discovery/agents-md.d.ts +0 -1
  639. package/dist/types/discovery/agents.d.ts +0 -12
  640. package/dist/types/discovery/builtin.d.ts +0 -1
  641. package/dist/types/discovery/claude-plugins.d.ts +0 -1
  642. package/dist/types/discovery/claude.d.ts +0 -1
  643. package/dist/types/discovery/cline.d.ts +0 -1
  644. package/dist/types/discovery/codex.d.ts +0 -1
  645. package/dist/types/discovery/cursor.d.ts +0 -19
  646. package/dist/types/discovery/gemini.d.ts +0 -1
  647. package/dist/types/discovery/github.d.ts +0 -1
  648. package/dist/types/discovery/helpers.d.ts +0 -271
  649. package/dist/types/discovery/index.d.ts +0 -48
  650. package/dist/types/discovery/mcp-json.d.ts +0 -1
  651. package/dist/types/discovery/opencode.d.ts +0 -1
  652. package/dist/types/discovery/plugin-dir-roots.d.ts +0 -15
  653. package/dist/types/discovery/ssh.d.ts +0 -1
  654. package/dist/types/discovery/substitute-plugin-root.d.ts +0 -1
  655. package/dist/types/discovery/vscode.d.ts +0 -1
  656. package/dist/types/discovery/windsurf.d.ts +0 -15
  657. package/dist/types/edit/apply-patch/index.d.ts +0 -35
  658. package/dist/types/edit/apply-patch/parser.d.ts +0 -34
  659. package/dist/types/edit/diff.d.ts +0 -75
  660. package/dist/types/edit/file-read-cache.d.ts +0 -25
  661. package/dist/types/edit/index.d.ts +0 -58
  662. package/dist/types/edit/modes/apply-patch.d.ts +0 -24
  663. package/dist/types/edit/modes/patch.d.ts +0 -99
  664. package/dist/types/edit/modes/replace.d.ts +0 -149
  665. package/dist/types/edit/normalize.d.ts +0 -43
  666. package/dist/types/edit/notebook.d.ts +0 -26
  667. package/dist/types/edit/read-file.d.ts +0 -8
  668. package/dist/types/edit/renderer.d.ts +0 -110
  669. package/dist/types/edit/streaming.d.ts +0 -66
  670. package/dist/types/eval/backend.d.ts +0 -40
  671. package/dist/types/eval/index.d.ts +0 -4
  672. package/dist/types/eval/js/context-manager.d.ts +0 -27
  673. package/dist/types/eval/js/executor.d.ts +0 -29
  674. package/dist/types/eval/js/index.d.ts +0 -10
  675. package/dist/types/eval/js/shared/helpers.d.ts +0 -38
  676. package/dist/types/eval/js/shared/indirect-eval.d.ts +0 -14
  677. package/dist/types/eval/js/shared/prelude.d.ts +0 -1
  678. package/dist/types/eval/js/shared/rewrite-imports.d.ts +0 -6
  679. package/dist/types/eval/js/shared/runtime.d.ts +0 -47
  680. package/dist/types/eval/js/shared/types.d.ts +0 -24
  681. package/dist/types/eval/js/tool-bridge.d.ts +0 -18
  682. package/dist/types/eval/js/worker-core.d.ts +0 -5
  683. package/dist/types/eval/js/worker-entry.d.ts +0 -1
  684. package/dist/types/eval/js/worker-protocol.d.ts +0 -77
  685. package/dist/types/eval/py/display.d.ts +0 -25
  686. package/dist/types/eval/py/executor.d.ts +0 -88
  687. package/dist/types/eval/py/index.d.ts +0 -10
  688. package/dist/types/eval/py/kernel.d.ts +0 -65
  689. package/dist/types/eval/py/prelude.d.ts +0 -1
  690. package/dist/types/eval/py/runtime.d.ts +0 -29
  691. package/dist/types/eval/py/tool-bridge.d.ts +0 -20
  692. package/dist/types/eval/types.d.ts +0 -52
  693. package/dist/types/exa/factory.d.ts +0 -13
  694. package/dist/types/exa/index.d.ts +0 -20
  695. package/dist/types/exa/mcp-client.d.ts +0 -45
  696. package/dist/types/exa/render.d.ts +0 -19
  697. package/dist/types/exa/researcher.d.ts +0 -9
  698. package/dist/types/exa/search.d.ts +0 -9
  699. package/dist/types/exa/types.d.ts +0 -155
  700. package/dist/types/exa/websets.d.ts +0 -9
  701. package/dist/types/exec/bash-executor.d.ts +0 -64
  702. package/dist/types/exec/exec.d.ts +0 -25
  703. package/dist/types/exec/idle-timeout-watchdog.d.ts +0 -18
  704. package/dist/types/exec/non-interactive-env.d.ts +0 -1
  705. package/dist/types/export/custom-share.d.ts +0 -20
  706. package/dist/types/export/html/index.d.ts +0 -10
  707. package/dist/types/export/html/template.generated.d.ts +0 -1
  708. package/dist/types/export/html/template.macro.d.ts +0 -5
  709. package/dist/types/export/ttsr.d.ts +0 -55
  710. package/dist/types/extensibility/custom-commands/bundled/ci-green/index.d.ts +0 -9
  711. package/dist/types/extensibility/custom-commands/index.d.ts +0 -2
  712. package/dist/types/extensibility/custom-commands/loader.d.ts +0 -29
  713. package/dist/types/extensibility/custom-commands/types.d.ts +0 -106
  714. package/dist/types/extensibility/custom-tools/index.d.ts +0 -6
  715. package/dist/types/extensibility/custom-tools/loader.d.ts +0 -69
  716. package/dist/types/extensibility/custom-tools/types.d.ts +0 -229
  717. package/dist/types/extensibility/custom-tools/wrapper.d.ts +0 -24
  718. package/dist/types/extensibility/extensions/compact-handler.d.ts +0 -26
  719. package/dist/types/extensibility/extensions/get-commands-handler.d.ts +0 -29
  720. package/dist/types/extensibility/extensions/index.d.ts +0 -9
  721. package/dist/types/extensibility/extensions/loader.d.ts +0 -43
  722. package/dist/types/extensibility/extensions/prefix-command-bridge.d.ts +0 -35
  723. package/dist/types/extensibility/extensions/runner.d.ts +0 -135
  724. package/dist/types/extensibility/extensions/types.d.ts +0 -920
  725. package/dist/types/extensibility/extensions/wrapper.d.ts +0 -55
  726. package/dist/types/extensibility/hooks/index.d.ts +0 -5
  727. package/dist/types/extensibility/hooks/loader.d.ts +0 -89
  728. package/dist/types/extensibility/hooks/runner.d.ts +0 -126
  729. package/dist/types/extensibility/hooks/tool-wrapper.d.ts +0 -25
  730. package/dist/types/extensibility/hooks/types.d.ts +0 -431
  731. package/dist/types/extensibility/plugins/doctor.d.ts +0 -3
  732. package/dist/types/extensibility/plugins/git-url.d.ts +0 -34
  733. package/dist/types/extensibility/plugins/index.d.ts +0 -8
  734. package/dist/types/extensibility/plugins/installer.d.ts +0 -5
  735. package/dist/types/extensibility/plugins/legacy-pi-compat.d.ts +0 -2
  736. package/dist/types/extensibility/plugins/loader.d.ts +0 -31
  737. package/dist/types/extensibility/plugins/manager.d.ts +0 -65
  738. package/dist/types/extensibility/plugins/marketplace/cache.d.ts +0 -41
  739. package/dist/types/extensibility/plugins/marketplace/fetcher.d.ts +0 -48
  740. package/dist/types/extensibility/plugins/marketplace/index.d.ts +0 -6
  741. package/dist/types/extensibility/plugins/marketplace/manager.d.ts +0 -57
  742. package/dist/types/extensibility/plugins/marketplace/registry.d.ts +0 -34
  743. package/dist/types/extensibility/plugins/marketplace/source-resolver.d.ts +0 -28
  744. package/dist/types/extensibility/plugins/marketplace/types.d.ts +0 -130
  745. package/dist/types/extensibility/plugins/parser.d.ts +0 -52
  746. package/dist/types/extensibility/plugins/security-scanner.d.ts +0 -31
  747. package/dist/types/extensibility/plugins/types.d.ts +0 -149
  748. package/dist/types/extensibility/runtime-skill-discovery.d.ts +0 -20
  749. package/dist/types/extensibility/shared-events.d.ts +0 -281
  750. package/dist/types/extensibility/skc-plugins/activation.d.ts +0 -14
  751. package/dist/types/extensibility/skc-plugins/compiler.d.ts +0 -19
  752. package/dist/types/extensibility/skc-plugins/constrained-hooks.d.ts +0 -29
  753. package/dist/types/extensibility/skc-plugins/index.d.ts +0 -18
  754. package/dist/types/extensibility/skc-plugins/injection.d.ts +0 -40
  755. package/dist/types/extensibility/skc-plugins/installer.d.ts +0 -13
  756. package/dist/types/extensibility/skc-plugins/loader.d.ts +0 -3
  757. package/dist/types/extensibility/skc-plugins/mcp-policy.d.ts +0 -26
  758. package/dist/types/extensibility/skc-plugins/observability.d.ts +0 -27
  759. package/dist/types/extensibility/skc-plugins/paths.d.ts +0 -8
  760. package/dist/types/extensibility/skc-plugins/prompt-appendix.d.ts +0 -16
  761. package/dist/types/extensibility/skc-plugins/registry.d.ts +0 -32
  762. package/dist/types/extensibility/skc-plugins/runtime-adapters.d.ts +0 -64
  763. package/dist/types/extensibility/skc-plugins/schema.d.ts +0 -3
  764. package/dist/types/extensibility/skc-plugins/session-validation.d.ts +0 -42
  765. package/dist/types/extensibility/skc-plugins/state.d.ts +0 -9
  766. package/dist/types/extensibility/skc-plugins/tools.d.ts +0 -8
  767. package/dist/types/extensibility/skc-plugins/types.d.ts +0 -220
  768. package/dist/types/extensibility/skc-plugins/validation.d.ts +0 -11
  769. package/dist/types/extensibility/skills.d.ts +0 -82
  770. package/dist/types/extensibility/slash-commands.d.ts +0 -48
  771. package/dist/types/extensibility/tool-proxy.d.ts +0 -4
  772. package/dist/types/extensibility/typebox.d.ts +0 -155
  773. package/dist/types/extensibility/utils.d.ts +0 -12
  774. package/dist/types/goals/index.d.ts +0 -3
  775. package/dist/types/goals/runtime.d.ts +0 -63
  776. package/dist/types/goals/state.d.ts +0 -32
  777. package/dist/types/goals/tools/goal-tool.d.ts +0 -62
  778. package/dist/types/harness-control-plane/classifier.d.ts +0 -13
  779. package/dist/types/harness-control-plane/control-endpoint.d.ts +0 -31
  780. package/dist/types/harness-control-plane/finalize.d.ts +0 -60
  781. package/dist/types/harness-control-plane/gc-adapter.d.ts +0 -3
  782. package/dist/types/harness-control-plane/operate.d.ts +0 -35
  783. package/dist/types/harness-control-plane/owner.d.ts +0 -53
  784. package/dist/types/harness-control-plane/phase-rollup.d.ts +0 -23
  785. package/dist/types/harness-control-plane/preserve.d.ts +0 -19
  786. package/dist/types/harness-control-plane/receipt-ingest.d.ts +0 -19
  787. package/dist/types/harness-control-plane/receipt-spool.d.ts +0 -19
  788. package/dist/types/harness-control-plane/receipts.d.ts +0 -149
  789. package/dist/types/harness-control-plane/rpc-adapter.d.ts +0 -69
  790. package/dist/types/harness-control-plane/seams.d.ts +0 -21
  791. package/dist/types/harness-control-plane/session-lease.d.ts +0 -65
  792. package/dist/types/harness-control-plane/state-machine.d.ts +0 -24
  793. package/dist/types/harness-control-plane/storage.d.ts +0 -81
  794. package/dist/types/harness-control-plane/types.d.ts +0 -187
  795. package/dist/types/hashline/anchors.d.ts +0 -20
  796. package/dist/types/hashline/apply.d.ts +0 -14
  797. package/dist/types/hashline/constants.d.ts +0 -19
  798. package/dist/types/hashline/diff-preview.d.ts +0 -2
  799. package/dist/types/hashline/diff.d.ts +0 -17
  800. package/dist/types/hashline/execute.d.ts +0 -4
  801. package/dist/types/hashline/hash.d.ts +0 -123
  802. package/dist/types/hashline/index.d.ts +0 -13
  803. package/dist/types/hashline/input.d.ts +0 -11
  804. package/dist/types/hashline/parser.d.ts +0 -7
  805. package/dist/types/hashline/prefixes.d.ts +0 -7
  806. package/dist/types/hashline/recovery.d.ts +0 -27
  807. package/dist/types/hashline/stream.d.ts +0 -2
  808. package/dist/types/hashline/types.d.ts +0 -77
  809. package/dist/types/hindsight/backend.d.ts +0 -13
  810. package/dist/types/hindsight/bank.d.ts +0 -54
  811. package/dist/types/hindsight/client.d.ts +0 -224
  812. package/dist/types/hindsight/config.d.ts +0 -51
  813. package/dist/types/hindsight/content.d.ts +0 -70
  814. package/dist/types/hindsight/index.d.ts +0 -8
  815. package/dist/types/hindsight/mental-models.d.ts +0 -125
  816. package/dist/types/hindsight/state.d.ts +0 -99
  817. package/dist/types/hindsight/transcript.d.ts +0 -28
  818. package/dist/types/hooks/codex-native-hooks-config.d.ts +0 -29
  819. package/dist/types/hooks/native-skill-hook.d.ts +0 -28
  820. package/dist/types/hooks/skill-keywords.d.ts +0 -18
  821. package/dist/types/hooks/skill-state.d.ts +0 -93
  822. package/dist/types/i18n/index.d.ts +0 -38
  823. package/dist/types/i18n/messages/de.d.ts +0 -2
  824. package/dist/types/i18n/messages/de.messages.d.ts +0 -1
  825. package/dist/types/i18n/messages/de.settings.d.ts +0 -1
  826. package/dist/types/i18n/messages/en.d.ts +0 -81
  827. package/dist/types/i18n/messages/es.d.ts +0 -2
  828. package/dist/types/i18n/messages/es.messages.d.ts +0 -1
  829. package/dist/types/i18n/messages/es.settings.d.ts +0 -1
  830. package/dist/types/i18n/messages/fr.d.ts +0 -2
  831. package/dist/types/i18n/messages/fr.messages.d.ts +0 -1
  832. package/dist/types/i18n/messages/fr.settings.d.ts +0 -1
  833. package/dist/types/i18n/messages/ja.d.ts +0 -2
  834. package/dist/types/i18n/messages/ja.messages.d.ts +0 -1
  835. package/dist/types/i18n/messages/ja.settings.d.ts +0 -1
  836. package/dist/types/i18n/messages/ko.d.ts +0 -2
  837. package/dist/types/i18n/messages/ko.messages.d.ts +0 -1
  838. package/dist/types/i18n/messages/ko.settings.d.ts +0 -1
  839. package/dist/types/i18n/messages/zh.d.ts +0 -2
  840. package/dist/types/i18n/messages/zh.messages.d.ts +0 -1
  841. package/dist/types/i18n/messages/zh.settings.d.ts +0 -1
  842. package/dist/types/index.d.ts +0 -33
  843. package/dist/types/internal-urls/agent-protocol.d.ts +0 -12
  844. package/dist/types/internal-urls/artifact-protocol.d.ts +0 -6
  845. package/dist/types/internal-urls/docs-index.generated.d.ts +0 -2
  846. package/dist/types/internal-urls/index.d.ts +0 -20
  847. package/dist/types/internal-urls/issue-pr-protocol.d.ts +0 -17
  848. package/dist/types/internal-urls/json-query.d.ts +0 -30
  849. package/dist/types/internal-urls/local-protocol.d.ts +0 -43
  850. package/dist/types/internal-urls/mcp-protocol.d.ts +0 -12
  851. package/dist/types/internal-urls/memory-protocol.d.ts +0 -23
  852. package/dist/types/internal-urls/parse.d.ts +0 -19
  853. package/dist/types/internal-urls/registry-helpers.d.ts +0 -11
  854. package/dist/types/internal-urls/router.d.ts +0 -14
  855. package/dist/types/internal-urls/rule-protocol.d.ts +0 -6
  856. package/dist/types/internal-urls/skc-protocol.d.ts +0 -12
  857. package/dist/types/internal-urls/skill-protocol.d.ts +0 -13
  858. package/dist/types/internal-urls/types.d.ts +0 -109
  859. package/dist/types/lsp/client.d.ts +0 -66
  860. package/dist/types/lsp/clients/biome-client.d.ts +0 -16
  861. package/dist/types/lsp/clients/index.d.ts +0 -19
  862. package/dist/types/lsp/clients/lsp-linter-client.d.ts +0 -16
  863. package/dist/types/lsp/clients/swiftlint-client.d.ts +0 -20
  864. package/dist/types/lsp/config.d.ts +0 -65
  865. package/dist/types/lsp/edits.d.ts +0 -23
  866. package/dist/types/lsp/index.d.ts +0 -130
  867. package/dist/types/lsp/lspmux.d.ts +0 -58
  868. package/dist/types/lsp/render.d.ts +0 -32
  869. package/dist/types/lsp/startup-events.d.ts +0 -12
  870. package/dist/types/lsp/types.d.ts +0 -306
  871. package/dist/types/lsp/utils.d.ts +0 -108
  872. package/dist/types/main.d.ts +0 -139
  873. package/dist/types/memories/index.d.ts +0 -28
  874. package/dist/types/memories/storage.d.ts +0 -110
  875. package/dist/types/memory-backend/index.d.ts +0 -4
  876. package/dist/types/memory-backend/local-backend.d.ts +0 -9
  877. package/dist/types/memory-backend/off-backend.d.ts +0 -7
  878. package/dist/types/memory-backend/resolve.d.ts +0 -15
  879. package/dist/types/memory-backend/types.d.ts +0 -61
  880. package/dist/types/migrate/action-planner.d.ts +0 -11
  881. package/dist/types/migrate/adapters/claude-code.d.ts +0 -2
  882. package/dist/types/migrate/adapters/codex.d.ts +0 -5
  883. package/dist/types/migrate/adapters/index.d.ts +0 -45
  884. package/dist/types/migrate/adapters/opencode.d.ts +0 -2
  885. package/dist/types/migrate/executor.d.ts +0 -2
  886. package/dist/types/migrate/mcp-mapper.d.ts +0 -20
  887. package/dist/types/migrate/report.d.ts +0 -18
  888. package/dist/types/migrate/skill-normalizer.d.ts +0 -27
  889. package/dist/types/migrate/types.d.ts +0 -126
  890. package/dist/types/modes/acp/acp-agent.d.ts +0 -78
  891. package/dist/types/modes/acp/acp-client-bridge.d.ts +0 -9
  892. package/dist/types/modes/acp/acp-event-mapper.d.ts +0 -36
  893. package/dist/types/modes/acp/acp-mode.d.ts +0 -17
  894. package/dist/types/modes/acp/index.d.ts +0 -2
  895. package/dist/types/modes/acp/terminal-auth.d.ts +0 -6
  896. package/dist/types/modes/bridge/auth.d.ts +0 -12
  897. package/dist/types/modes/bridge/bridge-client-bridge.d.ts +0 -9
  898. package/dist/types/modes/bridge/bridge-mode.d.ts +0 -47
  899. package/dist/types/modes/bridge/bridge-ui-context.d.ts +0 -88
  900. package/dist/types/modes/bridge/event-stream.d.ts +0 -8
  901. package/dist/types/modes/components/agent-dashboard.d.ts +0 -21
  902. package/dist/types/modes/components/assistant-message.d.ts +0 -20
  903. package/dist/types/modes/components/bash-execution.d.ts +0 -29
  904. package/dist/types/modes/components/bordered-loader.d.ts +0 -11
  905. package/dist/types/modes/components/branch-summary-message.d.ts +0 -13
  906. package/dist/types/modes/components/btw-panel.d.ts +0 -16
  907. package/dist/types/modes/components/compaction-summary-message.d.ts +0 -13
  908. package/dist/types/modes/components/countdown-timer.d.ts +0 -14
  909. package/dist/types/modes/components/custom-editor.d.ts +0 -69
  910. package/dist/types/modes/components/custom-message.d.ts +0 -15
  911. package/dist/types/modes/components/custom-model-preset-wizard.d.ts +0 -12
  912. package/dist/types/modes/components/custom-provider-wizard.d.ts +0 -10
  913. package/dist/types/modes/components/diff.d.ts +0 -11
  914. package/dist/types/modes/components/dynamic-border.d.ts +0 -14
  915. package/dist/types/modes/components/eval-execution.d.ts +0 -23
  916. package/dist/types/modes/components/execution-shared.d.ts +0 -46
  917. package/dist/types/modes/components/extensions/extension-dashboard.d.ts +0 -26
  918. package/dist/types/modes/components/extensions/extension-list.d.ts +0 -39
  919. package/dist/types/modes/components/extensions/index.d.ts +0 -8
  920. package/dist/types/modes/components/extensions/inspector-panel.d.ts +0 -8
  921. package/dist/types/modes/components/extensions/state-manager.d.ts +0 -50
  922. package/dist/types/modes/components/extensions/types.d.ts +0 -151
  923. package/dist/types/modes/components/footer.d.ts +0 -30
  924. package/dist/types/modes/components/history-search.d.ts +0 -7
  925. package/dist/types/modes/components/hook-editor.d.ts +0 -18
  926. package/dist/types/modes/components/hook-input.d.ts +0 -15
  927. package/dist/types/modes/components/hook-message.d.ts +0 -15
  928. package/dist/types/modes/components/hook-selector.d.ts +0 -59
  929. package/dist/types/modes/components/index.d.ts +0 -35
  930. package/dist/types/modes/components/irc-sidebar.d.ts +0 -32
  931. package/dist/types/modes/components/jobs-overlay-model.d.ts +0 -31
  932. package/dist/types/modes/components/jobs-overlay.d.ts +0 -30
  933. package/dist/types/modes/components/keybinding-hints.d.ts +0 -40
  934. package/dist/types/modes/components/login-dialog.d.ts +0 -32
  935. package/dist/types/modes/components/message-frame.d.ts +0 -42
  936. package/dist/types/modes/components/model-selector.d.ts +0 -60
  937. package/dist/types/modes/components/oauth-selector.d.ts +0 -17
  938. package/dist/types/modes/components/pet-selector.d.ts +0 -11
  939. package/dist/types/modes/components/plugin-selector.d.ts +0 -26
  940. package/dist/types/modes/components/plugin-settings.d.ts +0 -66
  941. package/dist/types/modes/components/provider-onboarding-selector.d.ts +0 -7
  942. package/dist/types/modes/components/queue-mode-selector.d.ts +0 -9
  943. package/dist/types/modes/components/queued-message-selector.d.ts +0 -12
  944. package/dist/types/modes/components/read-tool-group.d.ts +0 -30
  945. package/dist/types/modes/components/runtime-mcp-add-wizard.d.ts +0 -26
  946. package/dist/types/modes/components/sayknow-pet-widget.d.ts +0 -59
  947. package/dist/types/modes/components/session-observer-overlay.d.ts +0 -11
  948. package/dist/types/modes/components/session-selector.d.ts +0 -43
  949. package/dist/types/modes/components/settings-defs.d.ts +0 -50
  950. package/dist/types/modes/components/settings-selector.d.ts +0 -64
  951. package/dist/types/modes/components/show-images-selector.d.ts +0 -9
  952. package/dist/types/modes/components/skill-hud/render.d.ts +0 -2
  953. package/dist/types/modes/components/skill-message.d.ts +0 -10
  954. package/dist/types/modes/components/status-line/context-thresholds.d.ts +0 -4
  955. package/dist/types/modes/components/status-line/git-utils.d.ts +0 -28
  956. package/dist/types/modes/components/status-line/index.d.ts +0 -4
  957. package/dist/types/modes/components/status-line/presets.d.ts +0 -3
  958. package/dist/types/modes/components/status-line/segments.d.ts +0 -5
  959. package/dist/types/modes/components/status-line/separators.d.ts +0 -3
  960. package/dist/types/modes/components/status-line/token-rate.d.ts +0 -10
  961. package/dist/types/modes/components/status-line/types.d.ts +0 -83
  962. package/dist/types/modes/components/status-line.d.ts +0 -94
  963. package/dist/types/modes/components/theme-selector.d.ts +0 -10
  964. package/dist/types/modes/components/thinking-selector.d.ts +0 -15
  965. package/dist/types/modes/components/todo-reminder.d.ts +0 -13
  966. package/dist/types/modes/components/tool-execution.d.ts +0 -55
  967. package/dist/types/modes/components/tree-selector.d.ts +0 -31
  968. package/dist/types/modes/components/ttsr-notification.d.ts +0 -13
  969. package/dist/types/modes/components/two-column-body.d.ts +0 -9
  970. package/dist/types/modes/components/user-message-selector.d.ts +0 -28
  971. package/dist/types/modes/components/user-message.d.ts +0 -8
  972. package/dist/types/modes/components/visual-truncate.d.ts +0 -19
  973. package/dist/types/modes/components/welcome.d.ts +0 -46
  974. package/dist/types/modes/controllers/btw-controller.d.ts +0 -10
  975. package/dist/types/modes/controllers/command-controller-shared.d.ts +0 -47
  976. package/dist/types/modes/controllers/command-controller.d.ts +0 -40
  977. package/dist/types/modes/controllers/event-controller.d.ts +0 -21
  978. package/dist/types/modes/controllers/extension-ui-controller.d.ts +0 -80
  979. package/dist/types/modes/controllers/input-controller.d.ts +0 -42
  980. package/dist/types/modes/controllers/runtime-mcp-command-controller.d.ts +0 -10
  981. package/dist/types/modes/controllers/selector-controller.d.ts +0 -68
  982. package/dist/types/modes/controllers/ssh-command-controller.d.ts +0 -10
  983. package/dist/types/modes/controllers/todo-command-controller.d.ts +0 -7
  984. package/dist/types/modes/emoji-autocomplete.d.ts +0 -16
  985. package/dist/types/modes/index.d.ts +0 -10
  986. package/dist/types/modes/interactive-mode.d.ts +0 -297
  987. package/dist/types/modes/irc-observation-ledger.d.ts +0 -22
  988. package/dist/types/modes/jobs-observer.d.ts +0 -57
  989. package/dist/types/modes/oauth-manual-input.d.ts +0 -8
  990. package/dist/types/modes/print-mode.d.ts +0 -44
  991. package/dist/types/modes/prompt-action-autocomplete.d.ts +0 -50
  992. package/dist/types/modes/rpc/host-tools.d.ts +0 -1
  993. package/dist/types/modes/rpc/host-uris.d.ts +0 -1
  994. package/dist/types/modes/rpc/rpc-client.d.ts +0 -299
  995. package/dist/types/modes/rpc/rpc-mode.d.ts +0 -86
  996. package/dist/types/modes/rpc/rpc-socket-security.d.ts +0 -10
  997. package/dist/types/modes/rpc/rpc-types.d.ts +0 -810
  998. package/dist/types/modes/runtime-init.d.ts +0 -21
  999. package/dist/types/modes/session-observer-registry.d.ts +0 -26
  1000. package/dist/types/modes/shared/agent-wire/approval-gate.d.ts +0 -57
  1001. package/dist/types/modes/shared/agent-wire/command-contract.d.ts +0 -18
  1002. package/dist/types/modes/shared/agent-wire/command-dispatch.d.ts +0 -37
  1003. package/dist/types/modes/shared/agent-wire/command-validation.d.ts +0 -2
  1004. package/dist/types/modes/shared/agent-wire/deep-interview-gate.d.ts +0 -102
  1005. package/dist/types/modes/shared/agent-wire/event-contract.d.ts +0 -103
  1006. package/dist/types/modes/shared/agent-wire/event-envelope.d.ts +0 -60
  1007. package/dist/types/modes/shared/agent-wire/event-observation.d.ts +0 -37
  1008. package/dist/types/modes/shared/agent-wire/handshake.d.ts +0 -56
  1009. package/dist/types/modes/shared/agent-wire/host-tool-bridge.d.ts +0 -16
  1010. package/dist/types/modes/shared/agent-wire/host-uri-bridge.d.ts +0 -17
  1011. package/dist/types/modes/shared/agent-wire/protocol.d.ts +0 -25
  1012. package/dist/types/modes/shared/agent-wire/responses.d.ts +0 -4
  1013. package/dist/types/modes/shared/agent-wire/scopes.d.ts +0 -18
  1014. package/dist/types/modes/shared/agent-wire/session-registry.d.ts +0 -25
  1015. package/dist/types/modes/shared/agent-wire/ui-request-broker.d.ts +0 -42
  1016. package/dist/types/modes/shared/agent-wire/ui-result.d.ts +0 -27
  1017. package/dist/types/modes/shared/agent-wire/unattended-action-policy.d.ts +0 -29
  1018. package/dist/types/modes/shared/agent-wire/unattended-audit.d.ts +0 -68
  1019. package/dist/types/modes/shared/agent-wire/unattended-run-controller.d.ts +0 -166
  1020. package/dist/types/modes/shared/agent-wire/unattended-session.d.ts +0 -127
  1021. package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +0 -154
  1022. package/dist/types/modes/shared/agent-wire/workflow-gate-schema.d.ts +0 -39
  1023. package/dist/types/modes/shared.d.ts +0 -15
  1024. package/dist/types/modes/slash-command-visibility.d.ts +0 -1
  1025. package/dist/types/modes/theme/defaults/index.d.ts +0 -652
  1026. package/dist/types/modes/theme/mermaid-cache.d.ts +0 -9
  1027. package/dist/types/modes/theme/shimmer.d.ts +0 -38
  1028. package/dist/types/modes/theme/theme.d.ts +0 -275
  1029. package/dist/types/modes/tmux-scroll.d.ts +0 -18
  1030. package/dist/types/modes/types.d.ts +0 -318
  1031. package/dist/types/modes/utils/abort-message.d.ts +0 -4
  1032. package/dist/types/modes/utils/context-usage.d.ts +0 -36
  1033. package/dist/types/modes/utils/hotkeys-markdown.d.ts +0 -5
  1034. package/dist/types/modes/utils/injected-user-submission.d.ts +0 -52
  1035. package/dist/types/modes/utils/irc-message.d.ts +0 -38
  1036. package/dist/types/modes/utils/keybinding-matchers.d.ts +0 -10
  1037. package/dist/types/modes/utils/terminal-bell.d.ts +0 -3
  1038. package/dist/types/modes/utils/tools-markdown.d.ts +0 -5
  1039. package/dist/types/modes/utils/ui-helpers.d.ts +0 -75
  1040. package/dist/types/notifications/attachment-registry.d.ts +0 -17
  1041. package/dist/types/notifications/chat-adapters.d.ts +0 -9
  1042. package/dist/types/notifications/config-commands.d.ts +0 -64
  1043. package/dist/types/notifications/config.d.ts +0 -132
  1044. package/dist/types/notifications/daemon-paths.d.ts +0 -17
  1045. package/dist/types/notifications/engine.d.ts +0 -59
  1046. package/dist/types/notifications/helpers.d.ts +0 -55
  1047. package/dist/types/notifications/html-format.d.ts +0 -75
  1048. package/dist/types/notifications/index.d.ts +0 -219
  1049. package/dist/types/notifications/lifecycle-commands.d.ts +0 -69
  1050. package/dist/types/notifications/lifecycle-control-runtime.d.ts +0 -107
  1051. package/dist/types/notifications/lifecycle-orchestrator.d.ts +0 -144
  1052. package/dist/types/notifications/managed-daemon.d.ts +0 -48
  1053. package/dist/types/notifications/notification-service.d.ts +0 -144
  1054. package/dist/types/notifications/operator-runtime.d.ts +0 -52
  1055. package/dist/types/notifications/rate-limit-pool.d.ts +0 -113
  1056. package/dist/types/notifications/recent-activity.d.ts +0 -39
  1057. package/dist/types/notifications/reply-sent-store.d.ts +0 -53
  1058. package/dist/types/notifications/rich-draft.d.ts +0 -68
  1059. package/dist/types/notifications/rich-render.d.ts +0 -90
  1060. package/dist/types/notifications/telegram-cli.d.ts +0 -19
  1061. package/dist/types/notifications/telegram-daemon-cli.d.ts +0 -28
  1062. package/dist/types/notifications/telegram-daemon-control.d.ts +0 -70
  1063. package/dist/types/notifications/telegram-daemon.d.ts +0 -558
  1064. package/dist/types/notifications/telegram-reference.d.ts +0 -136
  1065. package/dist/types/notifications/threaded-inbound.d.ts +0 -77
  1066. package/dist/types/notifications/threaded-render.d.ts +0 -88
  1067. package/dist/types/notifications/topic-registry.d.ts +0 -89
  1068. package/dist/types/plan-mode/approved-plan.d.ts +0 -49
  1069. package/dist/types/plan-mode/state.d.ts +0 -6
  1070. package/dist/types/registry/agent-registry.d.ts +0 -64
  1071. package/dist/types/reminders/star-reminder.d.ts +0 -115
  1072. package/dist/types/research-plan/index.d.ts +0 -1
  1073. package/dist/types/research-plan/ledger.d.ts +0 -33
  1074. package/dist/types/rlm/artifacts.d.ts +0 -9
  1075. package/dist/types/rlm/complete-research-tool.d.ts +0 -35
  1076. package/dist/types/rlm/data-context.d.ts +0 -6
  1077. package/dist/types/rlm/index.d.ts +0 -47
  1078. package/dist/types/rlm/notebook.d.ts +0 -12
  1079. package/dist/types/rlm/preset.d.ts +0 -23
  1080. package/dist/types/rlm/python-tool.d.ts +0 -16
  1081. package/dist/types/rlm/report.d.ts +0 -14
  1082. package/dist/types/rlm/types.d.ts +0 -37
  1083. package/dist/types/runtime/process-lifecycle.d.ts +0 -108
  1084. package/dist/types/runtime-api-key.d.ts +0 -7
  1085. package/dist/types/runtime-credential-selector.d.ts +0 -7
  1086. package/dist/types/runtime-mcp/client.d.ts +0 -74
  1087. package/dist/types/runtime-mcp/config-writer.d.ts +0 -89
  1088. package/dist/types/runtime-mcp/config.d.ts +0 -77
  1089. package/dist/types/runtime-mcp/discoverable-tool-metadata.d.ts +0 -7
  1090. package/dist/types/runtime-mcp/index.d.ts +0 -18
  1091. package/dist/types/runtime-mcp/json-rpc.d.ts +0 -22
  1092. package/dist/types/runtime-mcp/loader.d.ts +0 -45
  1093. package/dist/types/runtime-mcp/manager.d.ts +0 -195
  1094. package/dist/types/runtime-mcp/oauth-discovery.d.ts +0 -40
  1095. package/dist/types/runtime-mcp/oauth-flow.d.ts +0 -59
  1096. package/dist/types/runtime-mcp/render.d.ts +0 -25
  1097. package/dist/types/runtime-mcp/smithery-auth.d.ts +0 -16
  1098. package/dist/types/runtime-mcp/smithery-connect.d.ts +0 -38
  1099. package/dist/types/runtime-mcp/smithery-registry.d.ts +0 -51
  1100. package/dist/types/runtime-mcp/tool-bridge.d.ts +0 -86
  1101. package/dist/types/runtime-mcp/tool-cache.d.ts +0 -8
  1102. package/dist/types/runtime-mcp/transports/http.d.ts +0 -36
  1103. package/dist/types/runtime-mcp/transports/index.d.ts +0 -5
  1104. package/dist/types/runtime-mcp/transports/stdio.d.ts +0 -29
  1105. package/dist/types/runtime-mcp/types.d.ts +0 -349
  1106. package/dist/types/sdk.d.ts +0 -256
  1107. package/dist/types/secrets/index.d.ts +0 -9
  1108. package/dist/types/secrets/obfuscator.d.ts +0 -23
  1109. package/dist/types/secrets/regex.d.ts +0 -2
  1110. package/dist/types/session/agent-session.d.ts +0 -1238
  1111. package/dist/types/session/agent-storage.d.ts +0 -101
  1112. package/dist/types/session/artifacts.d.ts +0 -64
  1113. package/dist/types/session/auth-broker-config.d.ts +0 -13
  1114. package/dist/types/session/auth-storage.d.ts +0 -6
  1115. package/dist/types/session/blob-store.d.ts +0 -160
  1116. package/dist/types/session/cache-economics.d.ts +0 -79
  1117. package/dist/types/session/client-bridge.d.ts +0 -88
  1118. package/dist/types/session/context-estimation.d.ts +0 -31
  1119. package/dist/types/session/contribution-prep.d.ts +0 -47
  1120. package/dist/types/session/file-mention-pruning.d.ts +0 -8
  1121. package/dist/types/session/history-storage.d.ts +0 -16
  1122. package/dist/types/session/messages.d.ts +0 -169
  1123. package/dist/types/session/provider-safety-stop.d.ts +0 -5
  1124. package/dist/types/session/session-dump-format.d.ts +0 -22
  1125. package/dist/types/session/session-manager.d.ts +0 -781
  1126. package/dist/types/session/session-storage.d.ts +0 -230
  1127. package/dist/types/session/streaming-output.d.ts +0 -209
  1128. package/dist/types/session/tool-choice-queue.d.ts +0 -84
  1129. package/dist/types/session/yield-queue.d.ts +0 -24
  1130. package/dist/types/setup/credential-auto-import.d.ts +0 -63
  1131. package/dist/types/setup/credential-import.d.ts +0 -82
  1132. package/dist/types/setup/hermes-setup.d.ts +0 -78
  1133. package/dist/types/setup/host-plugin-setup.d.ts +0 -39
  1134. package/dist/types/setup/model-onboarding-guidance.d.ts +0 -9
  1135. package/dist/types/setup/provider-onboarding.d.ts +0 -52
  1136. package/dist/types/skc-runtime/cli-write-receipt.d.ts +0 -24
  1137. package/dist/types/skc-runtime/deep-interview-ambiguity.d.ts +0 -39
  1138. package/dist/types/skc-runtime/deep-interview-recorder.d.ts +0 -114
  1139. package/dist/types/skc-runtime/deep-interview-runtime.d.ts +0 -36
  1140. package/dist/types/skc-runtime/deep-interview-state.d.ts +0 -127
  1141. package/dist/types/skc-runtime/gc-render.d.ts +0 -6
  1142. package/dist/types/skc-runtime/gc-runtime.d.ts +0 -134
  1143. package/dist/types/skc-runtime/goal-mode-request.d.ts +0 -53
  1144. package/dist/types/skc-runtime/launch-tmux.d.ts +0 -78
  1145. package/dist/types/skc-runtime/launch-worktree.d.ts +0 -46
  1146. package/dist/types/skc-runtime/ledger-event-renderer.d.ts +0 -68
  1147. package/dist/types/skc-runtime/psmux-detect.d.ts +0 -78
  1148. package/dist/types/skc-runtime/ralplan-runtime.d.ts +0 -26
  1149. package/dist/types/skc-runtime/restricted-role-agent-bash.d.ts +0 -3
  1150. package/dist/types/skc-runtime/session-layout.d.ts +0 -59
  1151. package/dist/types/skc-runtime/session-resolution.d.ts +0 -47
  1152. package/dist/types/skc-runtime/session-state-sidecar.d.ts +0 -70
  1153. package/dist/types/skc-runtime/state-graph.d.ts +0 -4
  1154. package/dist/types/skc-runtime/state-migrations.d.ts +0 -33
  1155. package/dist/types/skc-runtime/state-renderer.d.ts +0 -70
  1156. package/dist/types/skc-runtime/state-runtime.d.ts +0 -38
  1157. package/dist/types/skc-runtime/state-schema.d.ts +0 -319
  1158. package/dist/types/skc-runtime/state-validation.d.ts +0 -6
  1159. package/dist/types/skc-runtime/state-writer.d.ts +0 -244
  1160. package/dist/types/skc-runtime/team-gc.d.ts +0 -7
  1161. package/dist/types/skc-runtime/team-runtime.d.ts +0 -355
  1162. package/dist/types/skc-runtime/tmux-common.d.ts +0 -111
  1163. package/dist/types/skc-runtime/tmux-gc.d.ts +0 -7
  1164. package/dist/types/skc-runtime/tmux-owner-isolation-cli.d.ts +0 -5
  1165. package/dist/types/skc-runtime/tmux-owner-isolation.d.ts +0 -309
  1166. package/dist/types/skc-runtime/tmux-sessions.d.ts +0 -94
  1167. package/dist/types/skc-runtime/ultragoal-guard.d.ts +0 -93
  1168. package/dist/types/skc-runtime/ultragoal-receipt-freshness.d.ts +0 -42
  1169. package/dist/types/skc-runtime/ultragoal-runtime.d.ts +0 -410
  1170. package/dist/types/skc-runtime/workflow-command-ref.d.ts +0 -43
  1171. package/dist/types/skc-runtime/workflow-manifest.d.ts +0 -54
  1172. package/dist/types/skill-state/active-state.d.ts +0 -126
  1173. package/dist/types/skill-state/canonical-skills.d.ts +0 -3
  1174. package/dist/types/skill-state/deep-interview-mutation-guard.d.ts +0 -38
  1175. package/dist/types/skill-state/initial-phase.d.ts +0 -12
  1176. package/dist/types/skill-state/workflow-hud.d.ts +0 -83
  1177. package/dist/types/skill-state/workflow-state-contract.d.ts +0 -57
  1178. package/dist/types/skill-state/workflow-state-version.d.ts +0 -3
  1179. package/dist/types/slash-commands/acp-builtins.d.ts +0 -18
  1180. package/dist/types/slash-commands/builtin-registry.d.ts +0 -24
  1181. package/dist/types/slash-commands/helpers/context-report.d.ts +0 -7
  1182. package/dist/types/slash-commands/helpers/fast-status-report.d.ts +0 -82
  1183. package/dist/types/slash-commands/helpers/format.d.ts +0 -10
  1184. package/dist/types/slash-commands/helpers/mcp.d.ts +0 -3
  1185. package/dist/types/slash-commands/helpers/parse.d.ts +0 -33
  1186. package/dist/types/slash-commands/helpers/ssh.d.ts +0 -3
  1187. package/dist/types/slash-commands/helpers/todo.d.ts +0 -3
  1188. package/dist/types/slash-commands/helpers/usage-report.d.ts +0 -7
  1189. package/dist/types/slash-commands/types.d.ts +0 -120
  1190. package/dist/types/ssh/config-writer.d.ts +0 -49
  1191. package/dist/types/ssh/connection-manager.d.ts +0 -33
  1192. package/dist/types/ssh/ssh-executor.d.ts +0 -37
  1193. package/dist/types/ssh/sshfs-mount.d.ts +0 -6
  1194. package/dist/types/ssh/utils.d.ts +0 -2
  1195. package/dist/types/stt/downloader.d.ts +0 -9
  1196. package/dist/types/stt/index.d.ts +0 -3
  1197. package/dist/types/stt/recorder.d.ts +0 -13
  1198. package/dist/types/stt/setup.d.ts +0 -18
  1199. package/dist/types/stt/stt-controller.d.ts +0 -16
  1200. package/dist/types/stt/transcriber.d.ts +0 -16
  1201. package/dist/types/system-prompt.d.ts +0 -118
  1202. package/dist/types/task/agents.d.ts +0 -28
  1203. package/dist/types/task/commands.d.ts +0 -35
  1204. package/dist/types/task/discovery.d.ts +0 -19
  1205. package/dist/types/task/executor.d.ts +0 -127
  1206. package/dist/types/task/fork-context-advisory.d.ts +0 -13
  1207. package/dist/types/task/fork-context-budget.d.ts +0 -7
  1208. package/dist/types/task/id.d.ts +0 -7
  1209. package/dist/types/task/index.d.ts +0 -43
  1210. package/dist/types/task/name-generator.d.ts +0 -16
  1211. package/dist/types/task/output-manager.d.ts +0 -36
  1212. package/dist/types/task/parallel.d.ts +0 -34
  1213. package/dist/types/task/receipt.d.ts +0 -89
  1214. package/dist/types/task/render.d.ts +0 -28
  1215. package/dist/types/task/roi-reconciliation.d.ts +0 -27
  1216. package/dist/types/task/simple-mode.d.ts +0 -8
  1217. package/dist/types/task/skc-command.d.ts +0 -7
  1218. package/dist/types/task/spawn-gate.d.ts +0 -29
  1219. package/dist/types/task/subprocess-tool-registry.d.ts +0 -72
  1220. package/dist/types/task/token-log.d.ts +0 -30
  1221. package/dist/types/task/token-log.test.d.ts +0 -1
  1222. package/dist/types/task/types.d.ts +0 -516
  1223. package/dist/types/task/worktree.d.ts +0 -94
  1224. package/dist/types/thinking-metadata.d.ts +0 -16
  1225. package/dist/types/thinking.d.ts +0 -22
  1226. package/dist/types/tool-discovery/tool-index.d.ts +0 -112
  1227. package/dist/types/tools/archive-reader.d.ts +0 -40
  1228. package/dist/types/tools/ask-answer-registry.d.ts +0 -18
  1229. package/dist/types/tools/ask.d.ts +0 -123
  1230. package/dist/types/tools/ast-edit.d.ts +0 -77
  1231. package/dist/types/tools/ast-grep.d.ts +0 -69
  1232. package/dist/types/tools/auto-generated-guard.d.ts +0 -17
  1233. package/dist/types/tools/bash-allowed-prefixes.d.ts +0 -10
  1234. package/dist/types/tools/bash-command-fixup.d.ts +0 -11
  1235. package/dist/types/tools/bash-interactive.d.ts +0 -16
  1236. package/dist/types/tools/bash-interceptor.d.ts +0 -24
  1237. package/dist/types/tools/bash-pty-selection.d.ts +0 -7
  1238. package/dist/types/tools/bash-skill-urls.d.ts +0 -31
  1239. package/dist/types/tools/bash.d.ts +0 -157
  1240. package/dist/types/tools/bisect.d.ts +0 -81
  1241. package/dist/types/tools/browser/actions.d.ts +0 -54
  1242. package/dist/types/tools/browser/attach.d.ts +0 -50
  1243. package/dist/types/tools/browser/launch.d.ts +0 -62
  1244. package/dist/types/tools/browser/readable.d.ts +0 -17
  1245. package/dist/types/tools/browser/registry.d.ts +0 -57
  1246. package/dist/types/tools/browser/render.d.ts +0 -53
  1247. package/dist/types/tools/browser/tab-protocol.d.ts +0 -144
  1248. package/dist/types/tools/browser/tab-supervisor.d.ts +0 -109
  1249. package/dist/types/tools/browser/tab-worker-entry.d.ts +0 -1
  1250. package/dist/types/tools/browser/tab-worker.d.ts +0 -19
  1251. package/dist/types/tools/browser.d.ts +0 -211
  1252. package/dist/types/tools/calculator.d.ts +0 -76
  1253. package/dist/types/tools/checkpoint.d.ts +0 -63
  1254. package/dist/types/tools/composer-bash-policy.d.ts +0 -14
  1255. package/dist/types/tools/computer/render.d.ts +0 -17
  1256. package/dist/types/tools/computer-gc.d.ts +0 -23
  1257. package/dist/types/tools/computer.d.ts +0 -465
  1258. package/dist/types/tools/conflict-detect.d.ts +0 -205
  1259. package/dist/types/tools/context.d.ts +0 -19
  1260. package/dist/types/tools/cron.d.ts +0 -91
  1261. package/dist/types/tools/debug.d.ts +0 -209
  1262. package/dist/types/tools/eval.d.ts +0 -108
  1263. package/dist/types/tools/fetch.d.ts +0 -84
  1264. package/dist/types/tools/file-recorder.d.ts +0 -13
  1265. package/dist/types/tools/find.d.ts +0 -95
  1266. package/dist/types/tools/fs-cache-invalidation.d.ts +0 -15
  1267. package/dist/types/tools/gh-format.d.ts +0 -6
  1268. package/dist/types/tools/gh-renderer.d.ts +0 -25
  1269. package/dist/types/tools/gh.d.ts +0 -356
  1270. package/dist/types/tools/github-cache.d.ts +0 -103
  1271. package/dist/types/tools/grouped-file-output.d.ts +0 -36
  1272. package/dist/types/tools/hindsight-recall.d.ts +0 -21
  1273. package/dist/types/tools/hindsight-reflect.d.ts +0 -23
  1274. package/dist/types/tools/hindsight-retain.d.ts +0 -27
  1275. package/dist/types/tools/image-gen.d.ts +0 -79
  1276. package/dist/types/tools/index.d.ts +0 -371
  1277. package/dist/types/tools/irc.d.ts +0 -79
  1278. package/dist/types/tools/job.d.ts +0 -78
  1279. package/dist/types/tools/json-tree.d.ts +0 -23
  1280. package/dist/types/tools/jtd-to-json-schema.d.ts +0 -29
  1281. package/dist/types/tools/jtd-to-typescript.d.ts +0 -26
  1282. package/dist/types/tools/jtd-utils.d.ts +0 -42
  1283. package/dist/types/tools/list-limit.d.ts +0 -12
  1284. package/dist/types/tools/match-line-format.d.ts +0 -11
  1285. package/dist/types/tools/monitor.d.ts +0 -54
  1286. package/dist/types/tools/output-meta.d.ts +0 -204
  1287. package/dist/types/tools/path-utils.d.ts +0 -147
  1288. package/dist/types/tools/plan-mode-guard.d.ts +0 -18
  1289. package/dist/types/tools/read.d.ts +0 -85
  1290. package/dist/types/tools/recipe/index.d.ts +0 -45
  1291. package/dist/types/tools/recipe/render.d.ts +0 -36
  1292. package/dist/types/tools/recipe/runner.d.ts +0 -60
  1293. package/dist/types/tools/recipe/runners/cargo.d.ts +0 -16
  1294. package/dist/types/tools/recipe/runners/index.d.ts +0 -2
  1295. package/dist/types/tools/recipe/runners/just.d.ts +0 -2
  1296. package/dist/types/tools/recipe/runners/make.d.ts +0 -2
  1297. package/dist/types/tools/recipe/runners/pkg.d.ts +0 -2
  1298. package/dist/types/tools/recipe/runners/task.d.ts +0 -2
  1299. package/dist/types/tools/render-mermaid.d.ts +0 -37
  1300. package/dist/types/tools/render-utils.d.ts +0 -158
  1301. package/dist/types/tools/renderers.d.ts +0 -26
  1302. package/dist/types/tools/resolve.d.ts +0 -80
  1303. package/dist/types/tools/resource-gc.d.ts +0 -54
  1304. package/dist/types/tools/review.d.ts +0 -63
  1305. package/dist/types/tools/search-tool-bm25.d.ts +0 -65
  1306. package/dist/types/tools/search.d.ts +0 -93
  1307. package/dist/types/tools/skill-discovery.d.ts +0 -40
  1308. package/dist/types/tools/skill.d.ts +0 -48
  1309. package/dist/types/tools/sqlite-reader.d.ts +0 -94
  1310. package/dist/types/tools/ssh.d.ts +0 -67
  1311. package/dist/types/tools/subagent-render.d.ts +0 -31
  1312. package/dist/types/tools/subagent.d.ts +0 -117
  1313. package/dist/types/tools/telegram-send.d.ts +0 -39
  1314. package/dist/types/tools/todo-write.d.ts +0 -120
  1315. package/dist/types/tools/tool-errors.d.ts +0 -33
  1316. package/dist/types/tools/tool-result.d.ts +0 -30
  1317. package/dist/types/tools/tool-timeouts.d.ts +0 -56
  1318. package/dist/types/tools/ultragoal-ask-guard.d.ts +0 -12
  1319. package/dist/types/tools/vim.d.ts +0 -58
  1320. package/dist/types/tools/write.d.ts +0 -59
  1321. package/dist/types/tools/yield.d.ts +0 -25
  1322. package/dist/types/tui/code-cell.d.ts +0 -32
  1323. package/dist/types/tui/file-list.d.ts +0 -22
  1324. package/dist/types/tui/hyperlink.d.ts +0 -42
  1325. package/dist/types/tui/index.d.ts +0 -11
  1326. package/dist/types/tui/output-block.d.ts +0 -28
  1327. package/dist/types/tui/status-line.d.ts +0 -18
  1328. package/dist/types/tui/tree-list.d.ts +0 -19
  1329. package/dist/types/tui/types.d.ts +0 -13
  1330. package/dist/types/tui/utils.d.ts +0 -36
  1331. package/dist/types/utils/changelog.d.ts +0 -37
  1332. package/dist/types/utils/clipboard.d.ts +0 -22
  1333. package/dist/types/utils/cmux-workspace.d.ts +0 -52
  1334. package/dist/types/utils/command-args.d.ts +0 -9
  1335. package/dist/types/utils/commit-message-generator.d.ts +0 -7
  1336. package/dist/types/utils/edit-mode.d.ts +0 -13
  1337. package/dist/types/utils/event-bus.d.ts +0 -6
  1338. package/dist/types/utils/external-editor.d.ts +0 -19
  1339. package/dist/types/utils/file-display-mode.d.ts +0 -27
  1340. package/dist/types/utils/file-mentions.d.ts +0 -25
  1341. package/dist/types/utils/git.d.ts +0 -393
  1342. package/dist/types/utils/image-loading.d.ts +0 -26
  1343. package/dist/types/utils/image-resize.d.ts +0 -39
  1344. package/dist/types/utils/lang-from-path.d.ts +0 -8
  1345. package/dist/types/utils/linkedom.d.ts +0 -4
  1346. package/dist/types/utils/markit.d.ts +0 -7
  1347. package/dist/types/utils/open.d.ts +0 -2
  1348. package/dist/types/utils/pasted-image-path.d.ts +0 -32
  1349. package/dist/types/utils/session-color.d.ts +0 -10
  1350. package/dist/types/utils/shell-snapshot.d.ts +0 -5
  1351. package/dist/types/utils/sixel.d.ts +0 -21
  1352. package/dist/types/utils/title-generator.d.ts +0 -31
  1353. package/dist/types/utils/tool-choice.d.ts +0 -20
  1354. package/dist/types/utils/tools-manager.d.ts +0 -9
  1355. package/dist/types/vim/buffer.d.ts +0 -41
  1356. package/dist/types/vim/commands.d.ts +0 -6
  1357. package/dist/types/vim/engine.d.ts +0 -47
  1358. package/dist/types/vim/parser.d.ts +0 -3
  1359. package/dist/types/vim/render.d.ts +0 -25
  1360. package/dist/types/vim/types.d.ts +0 -182
  1361. package/dist/types/web/insane/bridge.d.ts +0 -103
  1362. package/dist/types/web/insane/url-guard.d.ts +0 -25
  1363. package/dist/types/web/kagi.d.ts +0 -23
  1364. package/dist/types/web/parallel.d.ts +0 -58
  1365. package/dist/types/web/scrapers/artifacthub.d.ts +0 -6
  1366. package/dist/types/web/scrapers/arxiv.d.ts +0 -5
  1367. package/dist/types/web/scrapers/aur.d.ts +0 -5
  1368. package/dist/types/web/scrapers/biorxiv.d.ts +0 -5
  1369. package/dist/types/web/scrapers/bluesky.d.ts +0 -5
  1370. package/dist/types/web/scrapers/brew.d.ts +0 -5
  1371. package/dist/types/web/scrapers/cheatsh.d.ts +0 -8
  1372. package/dist/types/web/scrapers/chocolatey.d.ts +0 -5
  1373. package/dist/types/web/scrapers/choosealicense.d.ts +0 -2
  1374. package/dist/types/web/scrapers/cisa-kev.d.ts +0 -5
  1375. package/dist/types/web/scrapers/clojars.d.ts +0 -5
  1376. package/dist/types/web/scrapers/coingecko.d.ts +0 -5
  1377. package/dist/types/web/scrapers/crates-io.d.ts +0 -5
  1378. package/dist/types/web/scrapers/crossref.d.ts +0 -2
  1379. package/dist/types/web/scrapers/devto.d.ts +0 -5
  1380. package/dist/types/web/scrapers/discogs.d.ts +0 -8
  1381. package/dist/types/web/scrapers/discourse.d.ts +0 -5
  1382. package/dist/types/web/scrapers/dockerhub.d.ts +0 -5
  1383. package/dist/types/web/scrapers/docs-rs.d.ts +0 -2
  1384. package/dist/types/web/scrapers/fdroid.d.ts +0 -5
  1385. package/dist/types/web/scrapers/firefox-addons.d.ts +0 -2
  1386. package/dist/types/web/scrapers/flathub.d.ts +0 -2
  1387. package/dist/types/web/scrapers/github-gist.d.ts +0 -5
  1388. package/dist/types/web/scrapers/github.d.ts +0 -12
  1389. package/dist/types/web/scrapers/gitlab.d.ts +0 -5
  1390. package/dist/types/web/scrapers/go-pkg.d.ts +0 -5
  1391. package/dist/types/web/scrapers/hackage.d.ts +0 -5
  1392. package/dist/types/web/scrapers/hackernews.d.ts +0 -2
  1393. package/dist/types/web/scrapers/hex.d.ts +0 -5
  1394. package/dist/types/web/scrapers/huggingface.d.ts +0 -2
  1395. package/dist/types/web/scrapers/iacr.d.ts +0 -5
  1396. package/dist/types/web/scrapers/index.d.ts +0 -84
  1397. package/dist/types/web/scrapers/jetbrains-marketplace.d.ts +0 -2
  1398. package/dist/types/web/scrapers/lemmy.d.ts +0 -2
  1399. package/dist/types/web/scrapers/lobsters.d.ts +0 -5
  1400. package/dist/types/web/scrapers/mastodon.d.ts +0 -5
  1401. package/dist/types/web/scrapers/maven.d.ts +0 -6
  1402. package/dist/types/web/scrapers/mdn.d.ts +0 -2
  1403. package/dist/types/web/scrapers/metacpan.d.ts +0 -5
  1404. package/dist/types/web/scrapers/musicbrainz.d.ts +0 -5
  1405. package/dist/types/web/scrapers/npm.d.ts +0 -5
  1406. package/dist/types/web/scrapers/nuget.d.ts +0 -5
  1407. package/dist/types/web/scrapers/nvd.d.ts +0 -5
  1408. package/dist/types/web/scrapers/ollama.d.ts +0 -2
  1409. package/dist/types/web/scrapers/open-vsx.d.ts +0 -5
  1410. package/dist/types/web/scrapers/opencorporates.d.ts +0 -5
  1411. package/dist/types/web/scrapers/openlibrary.d.ts +0 -5
  1412. package/dist/types/web/scrapers/orcid.d.ts +0 -5
  1413. package/dist/types/web/scrapers/osv.d.ts +0 -5
  1414. package/dist/types/web/scrapers/packagist.d.ts +0 -5
  1415. package/dist/types/web/scrapers/pub-dev.d.ts +0 -5
  1416. package/dist/types/web/scrapers/pubmed.d.ts +0 -5
  1417. package/dist/types/web/scrapers/pypi.d.ts +0 -5
  1418. package/dist/types/web/scrapers/rawg.d.ts +0 -2
  1419. package/dist/types/web/scrapers/readthedocs.d.ts +0 -2
  1420. package/dist/types/web/scrapers/reddit.d.ts +0 -5
  1421. package/dist/types/web/scrapers/repology.d.ts +0 -5
  1422. package/dist/types/web/scrapers/rfc.d.ts +0 -5
  1423. package/dist/types/web/scrapers/rubygems.d.ts +0 -5
  1424. package/dist/types/web/scrapers/searchcode.d.ts +0 -2
  1425. package/dist/types/web/scrapers/sec-edgar.d.ts +0 -5
  1426. package/dist/types/web/scrapers/semantic-scholar.d.ts +0 -2
  1427. package/dist/types/web/scrapers/snapcraft.d.ts +0 -2
  1428. package/dist/types/web/scrapers/sourcegraph.d.ts +0 -2
  1429. package/dist/types/web/scrapers/spdx.d.ts +0 -5
  1430. package/dist/types/web/scrapers/spotify.d.ts +0 -8
  1431. package/dist/types/web/scrapers/stackoverflow.d.ts +0 -6
  1432. package/dist/types/web/scrapers/terraform.d.ts +0 -5
  1433. package/dist/types/web/scrapers/tldr.d.ts +0 -7
  1434. package/dist/types/web/scrapers/twitter.d.ts +0 -5
  1435. package/dist/types/web/scrapers/types.d.ts +0 -83
  1436. package/dist/types/web/scrapers/utils.d.ts +0 -32
  1437. package/dist/types/web/scrapers/vimeo.d.ts +0 -5
  1438. package/dist/types/web/scrapers/vscode-marketplace.d.ts +0 -5
  1439. package/dist/types/web/scrapers/w3c.d.ts +0 -2
  1440. package/dist/types/web/scrapers/wikidata.d.ts +0 -5
  1441. package/dist/types/web/scrapers/wikipedia.d.ts +0 -5
  1442. package/dist/types/web/scrapers/youtube.d.ts +0 -13
  1443. package/dist/types/web/search/index.d.ts +0 -118
  1444. package/dist/types/web/search/provider.d.ts +0 -55
  1445. package/dist/types/web/search/providers/anthropic.d.ts +0 -32
  1446. package/dist/types/web/search/providers/base.d.ts +0 -90
  1447. package/dist/types/web/search/providers/brave.d.ts +0 -27
  1448. package/dist/types/web/search/providers/codex.d.ts +0 -35
  1449. package/dist/types/web/search/providers/duckduckgo.d.ts +0 -57
  1450. package/dist/types/web/search/providers/exa.d.ts +0 -52
  1451. package/dist/types/web/search/providers/gemini.d.ts +0 -57
  1452. package/dist/types/web/search/providers/insane.d.ts +0 -53
  1453. package/dist/types/web/search/providers/jina.d.ts +0 -26
  1454. package/dist/types/web/search/providers/kagi.d.ts +0 -24
  1455. package/dist/types/web/search/providers/kimi.d.ts +0 -27
  1456. package/dist/types/web/search/providers/openai-compatible.d.ts +0 -9
  1457. package/dist/types/web/search/providers/parallel.d.ts +0 -15
  1458. package/dist/types/web/search/providers/perplexity.d.ts +0 -38
  1459. package/dist/types/web/search/providers/searxng.d.ts +0 -44
  1460. package/dist/types/web/search/providers/synthetic.d.ts +0 -21
  1461. package/dist/types/web/search/providers/tavily.d.ts +0 -29
  1462. package/dist/types/web/search/providers/text-citations.d.ts +0 -23
  1463. package/dist/types/web/search/providers/utils.d.ts +0 -88
  1464. package/dist/types/web/search/providers/xai.d.ts +0 -64
  1465. package/dist/types/web/search/providers/zai.d.ts +0 -28
  1466. package/dist/types/web/search/render.d.ts +0 -36
  1467. package/dist/types/web/search/types.d.ts +0 -372
  1468. package/dist/types/web/search/utils.d.ts +0 -4
  1469. package/dist/types/workflow/workflow-intent-diff.d.ts +0 -25
  1470. package/dist/types/workflow/workflow-intent-report-consumer.d.ts +0 -50
  1471. package/dist/types/workflow/workflow-intent-report-schema.d.ts +0 -2
  1472. package/dist/types/workflow/workflow-intent-report.d.ts +0 -48
  1473. package/dist/types/workspace-tree.d.ts +0 -42
  1474. package/src/sdk.ts +0 -2623
@@ -0,0 +1,2402 @@
1
+ import { createHash } from "node:crypto";
2
+ import * as fs from "node:fs";
3
+ import * as os from "node:os";
4
+ import * as path from "node:path";
5
+ import * as native from "@sayknow-cli/natives";
6
+ import { canonicalExistingDirectoryIdentity, verifyOwnerOnlyPathSecurity } from "@sayknow-cli/natives";
7
+ import { pathIsWithin } from "@sayknow-cli/utils";
8
+ import type { ResumeSessionIdentity } from "../session-manager";
9
+ import {
10
+ FileSessionStorage,
11
+ type NativeDirectoryTreeSnapshot,
12
+ type SessionStorageFileIdentity,
13
+ } from "../session-storage";
14
+ import {
15
+ acquireManagedLock,
16
+ captureManagedFileNoFollow,
17
+ captureManagedFilePrefixNoFollow,
18
+ copyManagedFileNoReplace,
19
+ ensureManagedDirectory,
20
+ fsyncManagedArtifactTree,
21
+ ManagedSessionDescendantStore,
22
+ type ManagedStorageLock,
23
+ managedDirectoryRoot,
24
+ publishManagedFileNoReplace,
25
+ publishManagedTombstone,
26
+ retainManagedDirectoryAuthority,
27
+ validateManagedArtifactTree,
28
+ } from "./managed-session-storage";
29
+
30
+ export const MANAGED_SESSION_LAYOUT_VERSION = 2 as const;
31
+ export const MANAGED_SESSION_IDENTITY_VERSION = 1 as const;
32
+ export const MANAGED_SESSION_BINDING_FILE = ".skc-managed-session-scope.v2.json";
33
+
34
+ export interface ManagedScope {
35
+ apiVersion: 1;
36
+ layoutVersion: 2;
37
+ identityVersion: 1;
38
+ agentDir: string;
39
+ sessionsRoot: string;
40
+ canonicalCwd: string;
41
+ legacyLexicalCwd: string;
42
+ directoryName: string;
43
+ directoryPath: string;
44
+ platform: "posix" | "win32";
45
+ }
46
+
47
+ const managedRoots = new WeakMap<ManagedScope, ReturnType<typeof managedDirectoryRoot>>();
48
+ const managedDirectoryIdentities = new WeakMap<ManagedScope, { dev: bigint; ino: bigint }>();
49
+ const managedDirectoryAuthorities = new WeakMap<ManagedScope, native.RecoveryFsRoot | undefined>();
50
+
51
+ export function managedDirectoryAuthorityForScope(scope: ManagedScope): native.RecoveryFsRoot | undefined {
52
+ if (!managedDirectoryAuthorities.has(scope)) throw new Error("Managed session directory authority was not prepared");
53
+ return managedDirectoryAuthorities.get(scope);
54
+ }
55
+
56
+ export function managedDirectoryIdentityForScope(scope: ManagedScope): { dev: bigint; ino: bigint } {
57
+ const identity = managedDirectoryIdentities.get(scope);
58
+ if (!identity) throw new Error("Managed session directory identity was not prepared");
59
+ return identity;
60
+ }
61
+
62
+ function configuredRootPath(scope: ManagedScope): string {
63
+ let candidate = pathIsWithin(scope.agentDir, scope.sessionsRoot) ? scope.agentDir : path.dirname(scope.sessionsRoot);
64
+ for (;;) {
65
+ try {
66
+ const stat = fs.lstatSync(candidate);
67
+ if (!stat.isDirectory() || stat.isSymbolicLink()) throw new Error(`Unsafe configured root: ${candidate}`);
68
+ return fs.realpathSync.native(candidate);
69
+ } catch (error) {
70
+ if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
71
+ const parent = path.dirname(candidate);
72
+ if (parent === candidate) throw new Error("Configured managed root is unavailable.");
73
+ candidate = parent;
74
+ }
75
+ }
76
+ }
77
+
78
+ function scopeRoot(scope: ManagedScope) {
79
+ const retained = managedRoots.get(scope);
80
+ if (retained) return retained;
81
+ const root = managedDirectoryRoot(configuredRootPath(scope));
82
+ managedRoots.set(scope, root);
83
+ return root;
84
+ }
85
+
86
+ export function managedRootForScope(scope: ManagedScope) {
87
+ return scopeRoot(scope);
88
+ }
89
+
90
+ export type ManagedMigrationPolicy = "copy-retain" | "disabled";
91
+
92
+ export type ManagedScopeErrorCode =
93
+ | "cwd_missing"
94
+ | "cwd_not_directory"
95
+ | "identity_unavailable"
96
+ | "network_unsupported"
97
+ | "sessions_root_unavailable"
98
+ | "binding_conflict"
99
+ | "binding_invalid";
100
+
101
+ export type ManagedScopeResolution =
102
+ | { kind: "resolved"; scope: ManagedScope }
103
+ | { kind: "error"; code: ManagedScopeErrorCode; message: string };
104
+
105
+ export interface ManagedCandidate {
106
+ sessionId: string;
107
+ path: string;
108
+ cwd: string;
109
+ provenance: "v2" | "legacy";
110
+ identity: ResumeSessionIdentity;
111
+ migrationState: "native_v2" | "legacy_unmigrated" | "migrated_v2";
112
+ }
113
+
114
+ export type ManagedCandidateListing =
115
+ | {
116
+ kind: "complete";
117
+ scope: ManagedScope;
118
+ owned: readonly ManagedCandidate[];
119
+ foreignCount: number;
120
+ invalid: readonly { code: string }[];
121
+ }
122
+ | { kind: "error"; code: "scan_failed" | "unsafe_root" | "invalid_candidate"; message: string };
123
+
124
+ export type ManagedOpenFailure =
125
+ | "migration_busy"
126
+ | "binding_conflict"
127
+ | "binding_invalid"
128
+ | "destination_conflict"
129
+ | "source_changed"
130
+ | "unsafe_artifacts"
131
+ | "durability_failed"
132
+ | "migration_retired"
133
+ | "legacy_migration_disabled"
134
+ | "managed_storage_unsupported";
135
+
136
+ export type ManagedOpenCandidateResult =
137
+ | { kind: "opened"; path: string; candidate: ManagedCandidate; migrated: boolean }
138
+ | { kind: "error"; code: ManagedOpenFailure; message: string };
139
+
140
+ export type ManagedDeleteCandidateResult =
141
+ | { kind: "deleted"; tombstonePath: string }
142
+ | { kind: "already_deleted"; tombstonePath: string }
143
+ | { kind: "error"; code: ManagedOpenFailure; message: string };
144
+
145
+ type NativeIdentity =
146
+ | { ok: true; platform: "posix" | "win32"; canonicalPath: string }
147
+ | { ok: false; code: NativeIdentityFailureCode };
148
+ type CanonicalNativeIdentity = Extract<NativeIdentity, { ok: true }>;
149
+
150
+ type NativeIdentityFailureCode =
151
+ | "not_found"
152
+ | "not_directory"
153
+ | "not_utf8"
154
+ | "network_unsupported"
155
+ | "identity_unavailable"
156
+ | "io_error";
157
+
158
+ type NativeSecurity = { ok: true } | { ok: false; code: string };
159
+
160
+ interface Binding {
161
+ schemaVersion: 1;
162
+ layoutVersion: 2;
163
+ identityVersion: 1;
164
+ platform: "posix" | "win32";
165
+ canonicalPath: string;
166
+ identityDigest: string;
167
+ }
168
+
169
+ const BASE32 = "abcdefghijklmnopqrstuvwxyz234567";
170
+ const HEADER_MAX_BYTES = 64 * 1024;
171
+
172
+ function scopeDigest(platform: "posix" | "win32", canonicalPath: string): string {
173
+ const bytes = createHash("sha256")
174
+ .update("skc-managed-session-scope\0identity-v1\0", "utf8")
175
+ .update(platform, "utf8")
176
+ .update("\0", "utf8")
177
+ .update(canonicalPath, "utf8")
178
+ .digest();
179
+ let result = "";
180
+ let accumulator = 0;
181
+ let bits = 0;
182
+ for (const byte of bytes) {
183
+ accumulator = (accumulator << 8) | byte;
184
+ bits += 8;
185
+ while (bits >= 5) {
186
+ result += BASE32[(accumulator >>> (bits - 5)) & 31];
187
+ bits -= 5;
188
+ }
189
+ }
190
+ if (bits > 0) result += BASE32[(accumulator << (5 - bits)) & 31];
191
+ return result;
192
+ }
193
+ export const computeManagedScopeDigest = scopeDigest;
194
+
195
+ function identityFor(cwd: string): NativeIdentity {
196
+ return canonicalExistingDirectoryIdentity(cwd) as NativeIdentity;
197
+ }
198
+
199
+ function canonicalExistingPathForIo(base: string, identity: CanonicalNativeIdentity): string {
200
+ if (identity.platform !== "win32") return identity.canonicalPath;
201
+ try {
202
+ // Native identity uses a stable Volume GUID path on Windows. Bun 1.3.14
203
+ // cannot reliably create/read files through that path, so retain the
204
+ // symlink-resolved DOS path for JavaScript filesystem I/O.
205
+ return fs.realpathSync.native(base);
206
+ } catch {
207
+ return path.resolve(base);
208
+ }
209
+ }
210
+
211
+ /**
212
+ * Resolve benign symlinks in the deepest existing ancestor of a trusted storage
213
+ * root (e.g. macOS `/var -> /private/var`, or a symlinked `$HOME`) while keeping
214
+ * any not-yet-created tail verbatim. The native owner-only primitive and the
215
+ * session-storage reparse guard traverse with `O_NOFOLLOW` and reject every
216
+ * symlink component, so the trusted root must be canonical before it reaches
217
+ * them; canonicalizing only the existing prefix never follows an
218
+ * attacker-plantable component below the root.
219
+ */
220
+ export function canonicalizeTrustedPath(target: string): string {
221
+ let base = path.resolve(target);
222
+ const suffix: string[] = [];
223
+ for (;;) {
224
+ const identity = canonicalExistingDirectoryIdentity(base) as NativeIdentity;
225
+ if (identity.ok) {
226
+ const canonicalBase = canonicalExistingPathForIo(base, identity);
227
+ return suffix.length === 0 ? canonicalBase : path.join(canonicalBase, ...suffix);
228
+ }
229
+ if (identity.code !== "not_found" && identity.code !== "not_directory") return path.resolve(target);
230
+ const parent = path.dirname(base);
231
+ if (parent === base) return path.resolve(target);
232
+ suffix.unshift(path.basename(base));
233
+ base = parent;
234
+ }
235
+ }
236
+
237
+ function nativeFailure(code: NativeIdentityFailureCode): ManagedScopeResolution {
238
+ if (code === "not_found")
239
+ return { kind: "error", code: "cwd_missing", message: "The workspace directory does not exist." };
240
+ if (code === "not_directory")
241
+ return { kind: "error", code: "cwd_not_directory", message: "The workspace path is not a directory." };
242
+ if (code === "network_unsupported") {
243
+ return {
244
+ kind: "error",
245
+ code: "network_unsupported",
246
+ message: "Network workspace directories are not supported.",
247
+ };
248
+ }
249
+ return { kind: "error", code: "identity_unavailable", message: "Workspace directory identity is unavailable." };
250
+ }
251
+
252
+ function bindingFor(scope: ManagedScope): Binding {
253
+ return {
254
+ schemaVersion: 1,
255
+ layoutVersion: 2,
256
+ identityVersion: 1,
257
+ platform: scope.platform,
258
+ canonicalPath: scope.canonicalCwd,
259
+ identityDigest: scope.directoryName.slice(3),
260
+ };
261
+ }
262
+
263
+ function isBinding(value: unknown): value is Binding {
264
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
265
+ const binding = value as Record<string, unknown>;
266
+ return (
267
+ binding.schemaVersion === 1 &&
268
+ binding.layoutVersion === 2 &&
269
+ binding.identityVersion === 1 &&
270
+ (binding.platform === "posix" || binding.platform === "win32") &&
271
+ typeof binding.canonicalPath === "string" &&
272
+ typeof binding.identityDigest === "string" &&
273
+ /^[a-z2-7]{52}$/.test(binding.identityDigest)
274
+ );
275
+ }
276
+
277
+ function validateBindingRaw(scope: ManagedScope, raw: string): ManagedScopeResolution | undefined {
278
+ let parsed: unknown;
279
+ try {
280
+ parsed = JSON.parse(raw);
281
+ } catch {
282
+ return { kind: "error", code: "binding_invalid", message: "The managed scope binding is invalid JSON." };
283
+ }
284
+ if (!isBinding(parsed))
285
+ return { kind: "error", code: "binding_invalid", message: "The managed scope binding is invalid." };
286
+ const expected = bindingFor(scope);
287
+ if (
288
+ parsed.platform !== expected.platform ||
289
+ parsed.canonicalPath !== expected.canonicalPath ||
290
+ parsed.identityDigest !== expected.identityDigest
291
+ ) {
292
+ return {
293
+ kind: "error",
294
+ code: "binding_conflict",
295
+ message: "The managed scope binding belongs to another workspace.",
296
+ };
297
+ }
298
+ if (raw !== `${JSON.stringify(expected)}\n`) {
299
+ return {
300
+ kind: "error",
301
+ code: "binding_invalid",
302
+ message: "The managed scope binding is not canonically encoded.",
303
+ };
304
+ }
305
+ return undefined;
306
+ }
307
+
308
+ function validateExistingBinding(scope: ManagedScope): ManagedScopeResolution | undefined {
309
+ const bindingPath = path.join(scope.directoryPath, MANAGED_SESSION_BINDING_FILE);
310
+ let raw: string;
311
+ try {
312
+ raw = captureManagedFileNoFollow(bindingPath).bytes.toString("utf8");
313
+ } catch (error) {
314
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") return undefined;
315
+ return { kind: "error", code: "binding_invalid", message: "The managed scope binding is invalid JSON." };
316
+ }
317
+ return validateBindingRaw(scope, raw);
318
+ }
319
+
320
+ export function resolveManagedScope(input: {
321
+ cwd: string;
322
+ agentDir: string;
323
+ sessionsRoot: string;
324
+ }): ManagedScopeResolution {
325
+ const identity = identityFor(input.cwd);
326
+ if (!identity.ok) return nativeFailure(identity.code);
327
+ try {
328
+ if (fs.lstatSync(input.sessionsRoot).isSymbolicLink()) {
329
+ return {
330
+ kind: "error",
331
+ code: "sessions_root_unavailable",
332
+ message: "The sessions root is not a safe directory.",
333
+ };
334
+ }
335
+ } catch (error) {
336
+ if ((error as NodeJS.ErrnoException).code !== "ENOENT") {
337
+ return {
338
+ kind: "error",
339
+ code: "sessions_root_unavailable",
340
+ message: "The sessions root could not be inspected.",
341
+ };
342
+ }
343
+ }
344
+ const sessionsRoot = canonicalizeTrustedPath(input.sessionsRoot);
345
+ const agentDir = canonicalizeTrustedPath(input.agentDir);
346
+ const digest = scopeDigest(identity.platform, identity.canonicalPath);
347
+ const scope: ManagedScope = {
348
+ apiVersion: 1,
349
+ layoutVersion: MANAGED_SESSION_LAYOUT_VERSION,
350
+ identityVersion: MANAGED_SESSION_IDENTITY_VERSION,
351
+ agentDir,
352
+ sessionsRoot,
353
+ canonicalCwd: identity.canonicalPath,
354
+ legacyLexicalCwd: path.resolve(input.cwd),
355
+ directoryName: `v2-${digest}`,
356
+ directoryPath: path.join(sessionsRoot, `v2-${digest}`),
357
+ platform: identity.platform,
358
+ };
359
+ try {
360
+ const root = fs.lstatSync(sessionsRoot);
361
+ if (!root.isDirectory() || root.isSymbolicLink()) {
362
+ return {
363
+ kind: "error",
364
+ code: "sessions_root_unavailable",
365
+ message: "The sessions root is not a safe directory.",
366
+ };
367
+ }
368
+ } catch (error) {
369
+ if ((error as NodeJS.ErrnoException).code !== "ENOENT") {
370
+ return {
371
+ kind: "error",
372
+ code: "sessions_root_unavailable",
373
+ message: "The sessions root could not be inspected.",
374
+ };
375
+ }
376
+ }
377
+ try {
378
+ const directory = fs.lstatSync(scope.directoryPath);
379
+ if (!directory.isDirectory() || directory.isSymbolicLink()) {
380
+ return { kind: "error", code: "binding_invalid", message: "The managed scope path is not a safe directory." };
381
+ }
382
+ const security = verifyOwnerOnlyPathSecurity(scope.directoryPath, "directory") as NativeSecurity;
383
+ if (!security.ok)
384
+ return {
385
+ kind: "error",
386
+ code: "binding_invalid",
387
+ message: "The managed scope security could not be verified.",
388
+ };
389
+ } catch (error) {
390
+ if ((error as NodeJS.ErrnoException).code !== "ENOENT") {
391
+ return { kind: "error", code: "binding_invalid", message: "The managed scope path could not be inspected." };
392
+ }
393
+ }
394
+ return validateExistingBinding(scope) ?? { kind: "resolved", scope };
395
+ }
396
+
397
+ function legacyDirectoryNames(
398
+ platform: ManagedScope["platform"],
399
+ canonicalCwd: string,
400
+ lexicalCwd: string,
401
+ ): readonly string[] {
402
+ const pathApi = platform === "win32" ? path.win32 : path.posix;
403
+ const encodeAbsolute = (value: string): string => `--${value.replace(/^[/\\]/, "").replace(/[/\\:]/g, "-")}--`;
404
+ const encodeRelative = (value: string): string => value.replace(/[/\\:]/g, "-");
405
+ const relativeTo = (root: string, target: string): string | undefined => {
406
+ const relative = pathApi.relative(root, target);
407
+ return relative === ".." || relative.startsWith(`..${pathApi.sep}`) || pathApi.isAbsolute(relative)
408
+ ? undefined
409
+ : relative;
410
+ };
411
+ const names = new Set<string>([encodeAbsolute(canonicalCwd), encodeAbsolute(lexicalCwd)]);
412
+ const canonicalRoot = (root: string): string => {
413
+ const identity = canonicalExistingDirectoryIdentity(root);
414
+ return identity.ok ? identity.canonicalPath : pathApi.resolve(root);
415
+ };
416
+ const home = os.homedir();
417
+ // Volume-GUID canonical identities cannot be relativized against normal drive paths.
418
+ // Legacy directories were named from lexical drive/POSIX aliases in that case.
419
+ const legacyRelativeCwd = (root: string): string | undefined =>
420
+ relativeTo(canonicalRoot(root), canonicalCwd) ?? relativeTo(pathApi.resolve(root), lexicalCwd);
421
+ const homeRelative = legacyRelativeCwd(home);
422
+ if (homeRelative !== undefined) {
423
+ const encodedHome = encodeRelative(home);
424
+ const encodedRelative = encodeRelative(homeRelative);
425
+ names.add(`-${encodedRelative}`);
426
+ names.add(homeRelative === "" ? "----" : `---${encodedRelative}--`);
427
+ if (homeRelative === "") names.add(`--${encodedHome}--`);
428
+ else names.add(`--${encodedHome}-${encodedRelative}--`);
429
+ }
430
+ const tempRelative = legacyRelativeCwd(os.tmpdir());
431
+ if (tempRelative !== undefined) {
432
+ const encodedTempRelative = encodeRelative(tempRelative);
433
+ names.add(`-tmp${tempRelative ? `-${encodedTempRelative}` : ""}`);
434
+ names.add(`---tmp${tempRelative ? `-${encodedTempRelative}` : ""}--`);
435
+ }
436
+ return [...names];
437
+ }
438
+
439
+ function fsyncManagedParent(pathname: string): void {
440
+ if (process.platform === "win32") return;
441
+ let parent = path.dirname(pathname);
442
+ for (;;) {
443
+ let descriptor: number;
444
+ try {
445
+ descriptor = fs.openSync(parent, fs.constants.O_RDONLY | fs.constants.O_DIRECTORY | fs.constants.O_NOFOLLOW);
446
+ } catch (error) {
447
+ if ((error as NodeJS.ErrnoException).code === "ENOENT" && path.dirname(parent) !== parent) {
448
+ parent = path.dirname(parent);
449
+ continue;
450
+ }
451
+ throw new Error("durability_failed", { cause: error });
452
+ }
453
+ try {
454
+ fs.fsyncSync(descriptor);
455
+ } catch (error) {
456
+ throw new Error("durability_failed", { cause: error });
457
+ } finally {
458
+ fs.closeSync(descriptor);
459
+ }
460
+ return;
461
+ }
462
+ }
463
+
464
+ type CandidatePreflight =
465
+ | { kind: "capture"; identity: { dev: bigint; ino: bigint; size: number; mtimeNs: bigint } }
466
+ | {
467
+ kind: "foreign";
468
+ }
469
+ | {
470
+ kind: "invalid";
471
+ code: string;
472
+ };
473
+
474
+ function preflightCandidate(filePath: string, scope: ManagedScope): CandidatePreflight {
475
+ try {
476
+ const snapshot = captureManagedFilePrefixNoFollow(filePath, HEADER_MAX_BYTES);
477
+ const lineEnd = snapshot.bytes.indexOf(0x0a);
478
+ if (lineEnd < 0) return { kind: "invalid", code: "invalid_header" };
479
+ const value: unknown = JSON.parse(snapshot.bytes.subarray(0, lineEnd).toString("utf8"));
480
+ if (!value || typeof value !== "object" || Array.isArray(value))
481
+ return { kind: "invalid", code: "invalid_header" };
482
+ const header = value as Record<string, unknown>;
483
+ if (header.type !== "session" || typeof header.id !== "string" || typeof header.cwd !== "string")
484
+ return { kind: "invalid", code: "invalid_header" };
485
+ const candidateIdentity = identityFor(header.cwd);
486
+ if (
487
+ candidateIdentity.ok &&
488
+ (candidateIdentity.platform !== scope.platform || candidateIdentity.canonicalPath !== scope.canonicalCwd)
489
+ )
490
+ return { kind: "foreign" };
491
+ return { kind: "capture", identity: snapshot.identity };
492
+ } catch {
493
+ return { kind: "invalid", code: "unreadable_candidate" };
494
+ }
495
+ }
496
+
497
+ function matchesPreflightIdentity(candidate: ManagedCandidate, preflight: CandidatePreflight): boolean {
498
+ return (
499
+ preflight.kind === "capture" &&
500
+ candidate.identity.dev === preflight.identity.dev &&
501
+ candidate.identity.ino === preflight.identity.ino &&
502
+ candidate.identity.size === preflight.identity.size &&
503
+ candidate.identity.mtimeNs === preflight.identity.mtimeNs
504
+ );
505
+ }
506
+
507
+ function inspectCandidate(filePath: string, provenance: "v2" | "legacy"): ManagedCandidate | { code: string } {
508
+ try {
509
+ const snapshot = captureManagedFileNoFollow(filePath);
510
+ const lineEnd = snapshot.bytes.subarray(0, HEADER_MAX_BYTES).indexOf(0x0a);
511
+ if (lineEnd < 0) return { code: "invalid_header" };
512
+ const value: unknown = JSON.parse(snapshot.bytes.subarray(0, lineEnd).toString("utf8"));
513
+ if (!value || typeof value !== "object" || Array.isArray(value)) return { code: "invalid_header" };
514
+ const header = value as Record<string, unknown>;
515
+ if (header.type !== "session" || typeof header.id !== "string" || typeof header.cwd !== "string")
516
+ return { code: "invalid_header" };
517
+ const cwdIdentity = identityFor(header.cwd);
518
+ if (!cwdIdentity.ok) return { code: `cwd_${cwdIdentity.code}` };
519
+ const named = fs.lstatSync(filePath, { bigint: true });
520
+ if (
521
+ !named.isFile() ||
522
+ named.isSymbolicLink() ||
523
+ named.dev !== snapshot.identity.dev ||
524
+ named.ino !== snapshot.identity.ino ||
525
+ Number(named.size) !== snapshot.identity.size ||
526
+ named.mtimeNs !== snapshot.identity.mtimeNs
527
+ )
528
+ return { code: "source_changed" };
529
+ return {
530
+ sessionId: header.id,
531
+ path: filePath,
532
+ cwd: header.cwd,
533
+ provenance,
534
+ migrationState: provenance === "v2" ? "native_v2" : "legacy_unmigrated",
535
+ identity: {
536
+ canonicalPath: path.resolve(filePath),
537
+ sessionId: header.id,
538
+ ...snapshot.identity,
539
+ mtimeMs: Number(named.mtimeMs),
540
+ sha256: createHash("sha256").update(snapshot.bytes).digest("hex"),
541
+ },
542
+ };
543
+ } catch (error) {
544
+ return { code: (error as Error).message === "source_changed" ? "source_changed" : "unreadable_candidate" };
545
+ }
546
+ }
547
+
548
+ const MAX_DISCOVERED_LEGACY_DIRECTORIES = 256;
549
+
550
+ function discoveredLegacyDirectoryNames(scope: ManagedScope): readonly string[] {
551
+ const known = new Set(legacyDirectoryNames(scope.platform, scope.canonicalCwd, scope.legacyLexicalCwd));
552
+ const discovered = fs
553
+ .readdirSync(scope.sessionsRoot, { withFileTypes: true })
554
+ .filter(
555
+ entry =>
556
+ entry.isDirectory() &&
557
+ entry.name.startsWith("-") &&
558
+ !entry.name.startsWith("v2-") &&
559
+ entry.name !== MANAGED_INTERNAL_DIRECTORY,
560
+ )
561
+ .map(entry => entry.name)
562
+ .sort()
563
+ .filter(name => !known.has(name))
564
+ .slice(0, MAX_DISCOVERED_LEGACY_DIRECTORIES);
565
+ return [...known, ...discovered];
566
+ }
567
+
568
+ type CandidateInspection = ManagedCandidate | { code: string } | { foreign: true };
569
+
570
+ function listDirectoryCandidates(
571
+ directory: string,
572
+ provenance: "v2" | "legacy",
573
+ scope: ManagedScope,
574
+ ): readonly CandidateInspection[] {
575
+ let directoryStat: fs.Stats;
576
+ try {
577
+ directoryStat = fs.lstatSync(directory);
578
+ } catch (error) {
579
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") return [];
580
+ throw error;
581
+ }
582
+ if (!directoryStat.isDirectory() || directoryStat.isSymbolicLink()) throw new Error("unsafe directory");
583
+ return fs
584
+ .readdirSync(directory, { withFileTypes: true })
585
+ .filter(entry => entry.name.endsWith(".jsonl"))
586
+ .map(entry => {
587
+ const filePath = path.join(directory, entry.name);
588
+ const preflight = preflightCandidate(filePath, scope);
589
+ if (preflight.kind === "invalid") return { code: preflight.code };
590
+ if (preflight.kind === "foreign") return { foreign: true };
591
+ const candidate = inspectCandidate(filePath, provenance);
592
+ if ("code" in candidate) return candidate;
593
+ return matchesPreflightIdentity(candidate, preflight) ? candidate : { code: "source_changed" };
594
+ });
595
+ }
596
+
597
+ export async function ensureManagedScope(scope: ManagedScope): Promise<ManagedScopeResolution> {
598
+ try {
599
+ const root = scopeRoot(scope);
600
+ ensureManagedDirectory(scope.sessionsRoot, root);
601
+ ensureManagedDirectory(scope.directoryPath, root);
602
+ const bindingPath = path.join(scope.directoryPath, MANAGED_SESSION_BINDING_FILE);
603
+ const binding = `${JSON.stringify(bindingFor(scope))}\n`;
604
+ try {
605
+ await publishManagedFileNoReplace(bindingPath, new TextEncoder().encode(binding), undefined, root);
606
+ } catch (error) {
607
+ if ((error as Error).message !== "destination_conflict") throw error;
608
+ }
609
+ return validateExistingBinding(scope) ?? { kind: "resolved", scope };
610
+ } catch (error) {
611
+ return {
612
+ kind: "error",
613
+ code: "binding_invalid",
614
+ message: error instanceof Error ? error.message : "The managed scope could not be initialized.",
615
+ };
616
+ }
617
+ }
618
+
619
+ /** Synchronously create and validate the v2 binding before a default session writer exists. */
620
+ export function prepareManagedSessionScopeForWriteSync(scope: ManagedScope): ManagedScopeResolution {
621
+ try {
622
+ const root = scopeRoot(scope);
623
+ ensureManagedDirectory(scope.sessionsRoot, root);
624
+ ensureManagedDirectory(scope.directoryPath, root);
625
+ const preparedDirectory = fs.lstatSync(scope.directoryPath, { bigint: true });
626
+ if (!preparedDirectory.isDirectory() || preparedDirectory.isSymbolicLink())
627
+ throw new Error("Managed session directory changed");
628
+ const retainedAuthority = retainManagedDirectoryAuthority(root, scope.directoryPath, {
629
+ dev: preparedDirectory.dev,
630
+ ino: preparedDirectory.ino,
631
+ });
632
+ const store = new ManagedSessionDescendantStore(
633
+ root,
634
+ scope.directoryPath,
635
+ retainedAuthority ? { authority: retainedAuthority, authorityBaseDir: scope.directoryPath } : undefined,
636
+ );
637
+ const binding = new TextEncoder().encode(`${JSON.stringify(bindingFor(scope))}\n`);
638
+ try {
639
+ store.publishNoReplaceSync(MANAGED_SESSION_BINDING_FILE, binding);
640
+ } catch (error) {
641
+ if ((error as Error).message !== "destination_conflict") throw error;
642
+ }
643
+ const capturedBinding = store.readExpected(MANAGED_SESSION_BINDING_FILE);
644
+ if (!capturedBinding) throw new Error("Managed scope binding is unavailable");
645
+ const validated = validateBindingRaw(scope, capturedBinding.bytes.toString("utf8"));
646
+ managedDirectoryAuthorities.set(scope, retainedAuthority);
647
+ const directoryStat = fs.lstatSync(scope.directoryPath, { bigint: true });
648
+ if (
649
+ !directoryStat.isDirectory() ||
650
+ directoryStat.isSymbolicLink() ||
651
+ directoryStat.dev !== preparedDirectory.dev ||
652
+ directoryStat.ino !== preparedDirectory.ino
653
+ )
654
+ throw new Error("Managed session directory changed");
655
+ managedDirectoryIdentities.set(scope, { dev: preparedDirectory.dev, ino: preparedDirectory.ino });
656
+ if (validated) return validated;
657
+ const internal = managedInternalDirectory(scope);
658
+ ensureManagedDirectory(internal, root);
659
+ ensureManagedDirectory(path.join(internal, MANAGED_LOCKS_DIRECTORY), root);
660
+ ensureManagedDirectory(path.join(internal, MANAGED_RECEIPTS_DIRECTORY), root);
661
+ ensureManagedDirectory(path.join(internal, MANAGED_TOMBSTONES_DIRECTORY), root);
662
+ return { kind: "resolved", scope };
663
+ } catch (error) {
664
+ return {
665
+ kind: "error",
666
+ code: "binding_invalid",
667
+ message: error instanceof Error ? error.message : "Managed write protocol setup failed.",
668
+ };
669
+ }
670
+ }
671
+
672
+ export function listManagedCandidates(scope: ManagedScope): ManagedCandidateListing {
673
+ try {
674
+ let root: fs.Stats;
675
+ try {
676
+ root = fs.lstatSync(scope.sessionsRoot);
677
+ } catch (error) {
678
+ if ((error as NodeJS.ErrnoException).code === "ENOENT")
679
+ return { kind: "complete", scope, owned: [], foreignCount: 0, invalid: [] };
680
+ throw error;
681
+ }
682
+ if (!root.isDirectory() || root.isSymbolicLink())
683
+ return { kind: "error", code: "unsafe_root", message: "The sessions root is unsafe." };
684
+ const owned: ManagedCandidate[] = [];
685
+ const invalid: { code: string }[] = [];
686
+ let foreignCount = 0;
687
+ const directories: Array<{ path: string; provenance: "v2" | "legacy" }> = [
688
+ { path: scope.directoryPath, provenance: "v2" },
689
+ ...discoveredLegacyDirectoryNames(scope).map(directoryName => ({
690
+ path: path.join(scope.sessionsRoot, directoryName),
691
+ provenance: "legacy" as const,
692
+ })),
693
+ ];
694
+ const seen = new Set<string>();
695
+ for (const directory of directories) {
696
+ for (const candidate of listDirectoryCandidates(directory.path, directory.provenance, scope)) {
697
+ if ("code" in candidate) {
698
+ invalid.push({ code: candidate.code });
699
+ continue;
700
+ }
701
+ if ("foreign" in candidate) {
702
+ foreignCount++;
703
+ continue;
704
+ }
705
+ const candidateIdentity = identityFor(candidate.cwd);
706
+ if (!candidateIdentity.ok) {
707
+ invalid.push({ code: `cwd_${candidateIdentity.code}` });
708
+ continue;
709
+ }
710
+ if (
711
+ candidateIdentity.platform !== scope.platform ||
712
+ candidateIdentity.canonicalPath !== scope.canonicalCwd
713
+ ) {
714
+ foreignCount++;
715
+ continue;
716
+ }
717
+ if (!seen.has(candidate.identity.canonicalPath)) {
718
+ seen.add(candidate.identity.canonicalPath);
719
+ owned.push(candidate);
720
+ }
721
+ }
722
+ }
723
+ const visible = owned.filter(candidate => !isRetired(scope, candidate));
724
+ const active = visible.filter(
725
+ candidate =>
726
+ candidate.provenance === "v2" ||
727
+ !visible.some(
728
+ destination =>
729
+ destination.provenance === "v2" &&
730
+ receiptMatches(receiptPathFor(scope, candidate), candidate, destination, scope),
731
+ ),
732
+ );
733
+ return {
734
+ kind: "complete",
735
+ scope,
736
+ owned: active.map(candidate => {
737
+ if (candidate.provenance !== "v2") return candidate;
738
+ const migrated = visible.some(
739
+ source =>
740
+ source.provenance === "legacy" &&
741
+ receiptMatches(receiptPathFor(scope, source), source, candidate, scope),
742
+ );
743
+ return migrated ? { ...candidate, migrationState: "migrated_v2" as const } : candidate;
744
+ }),
745
+ foreignCount,
746
+ invalid,
747
+ };
748
+ } catch (error) {
749
+ return {
750
+ kind: "error",
751
+ code: "scan_failed",
752
+ message: error instanceof Error ? error.message : "Session scan failed.",
753
+ };
754
+ }
755
+ }
756
+
757
+ const MANAGED_INTERNAL_DIRECTORY = ".skc-managed-session-internal";
758
+ const MANAGED_RECEIPTS_DIRECTORY = "receipts";
759
+ const MANAGED_LOCKS_DIRECTORY = "locks";
760
+ const MANAGED_TOMBSTONES_DIRECTORY = "tombstones";
761
+
762
+ function managedInternalDirectory(scope: ManagedScope): string {
763
+ return path.join(scope.directoryPath, MANAGED_INTERNAL_DIRECTORY);
764
+ }
765
+
766
+ function stableOperationName(candidate: ManagedCandidate): string {
767
+ return createHash("sha256")
768
+ .update(candidate.identity.canonicalPath)
769
+ .update("\0")
770
+ .update(candidate.identity.dev.toString())
771
+ .update("\0")
772
+ .update(candidate.identity.ino.toString())
773
+ .update("\0")
774
+ .update(candidate.identity.size.toString())
775
+ .update("\0")
776
+ .update(candidate.identity.mtimeNs.toString())
777
+ .update("\0")
778
+ .update(candidate.identity.sha256)
779
+ .digest("hex");
780
+ }
781
+
782
+ function expectedFailure(error: unknown): ManagedOpenFailure {
783
+ const message = error instanceof Error ? error.message : "";
784
+ return message === "migration_busy" ||
785
+ message === "binding_conflict" ||
786
+ message === "binding_invalid" ||
787
+ message === "destination_conflict" ||
788
+ message === "source_changed" ||
789
+ message === "unsafe_artifacts" ||
790
+ message === "durability_failed" ||
791
+ message === "migration_retired"
792
+ ? message
793
+ : "managed_storage_unsupported";
794
+ }
795
+
796
+ function sameCandidate(left: ManagedCandidate, right: ManagedCandidate): boolean {
797
+ return (
798
+ left.path === right.path &&
799
+ left.identity.dev === right.identity.dev &&
800
+ left.identity.ino === right.identity.ino &&
801
+ left.identity.size === right.identity.size &&
802
+ left.identity.mtimeNs === right.identity.mtimeNs &&
803
+ left.identity.sha256 === right.identity.sha256
804
+ );
805
+ }
806
+
807
+ function receiptPathFor(
808
+ scope: ManagedScope,
809
+ source: ManagedCandidate,
810
+ state: "prepared" | "published" | "committed" = "committed",
811
+ ): string {
812
+ const suffix = state === "committed" ? "" : `.${state}`;
813
+ return path.join(
814
+ managedInternalDirectory(scope),
815
+ MANAGED_RECEIPTS_DIRECTORY,
816
+ `${stableOperationName(source)}${suffix}.json`,
817
+ );
818
+ }
819
+
820
+ function receiptMatches(
821
+ receiptPath: string,
822
+ source: ManagedCandidate,
823
+ destination: ManagedCandidate,
824
+ scope: ManagedScope,
825
+ ): boolean {
826
+ try {
827
+ const value: unknown = JSON.parse(captureManagedFileNoFollow(receiptPath).bytes.toString("utf8"));
828
+ if (!value || typeof value !== "object") return false;
829
+ const record = value as {
830
+ schemaVersion?: unknown;
831
+ state?: unknown;
832
+ policy?: unknown;
833
+ scope?: unknown;
834
+ source?: {
835
+ path?: unknown;
836
+ sha256?: unknown;
837
+ sessionId?: unknown;
838
+ header?: { id?: unknown; cwd?: unknown };
839
+ identity?: { dev?: unknown; ino?: unknown; size?: unknown; mtimeNs?: unknown };
840
+ };
841
+ destination?: {
842
+ path?: unknown;
843
+ sha256?: unknown;
844
+ sessionId?: unknown;
845
+ header?: { id?: unknown; cwd?: unknown };
846
+ identity?: { dev?: unknown; ino?: unknown; size?: unknown; mtimeNs?: unknown };
847
+ };
848
+ artifactManifest?: unknown;
849
+ };
850
+ const exact = (
851
+ recorded: { dev?: unknown; ino?: unknown; size?: unknown; mtimeNs?: unknown } | undefined,
852
+ candidate: ManagedCandidate,
853
+ ): boolean =>
854
+ recorded?.dev === String(candidate.identity.dev) &&
855
+ recorded.ino === String(candidate.identity.ino) &&
856
+ recorded.size === candidate.identity.size &&
857
+ recorded.mtimeNs === String(candidate.identity.mtimeNs);
858
+ const lineage = (recorded: { dev?: unknown; ino?: unknown } | undefined, candidate: ManagedCandidate): boolean =>
859
+ recorded?.dev === String(candidate.identity.dev) && recorded.ino === String(candidate.identity.ino);
860
+ const sourceSnapshot = captureManagedFileNoFollow(source.path);
861
+ const destinationSnapshot = captureManagedFileNoFollow(destination.path);
862
+ const appendLineage =
863
+ sourceSnapshot.identity.dev === source.identity.dev &&
864
+ sourceSnapshot.identity.ino === source.identity.ino &&
865
+ sourceSnapshot.identity.size === source.identity.size &&
866
+ sourceSnapshot.identity.mtimeNs === source.identity.mtimeNs &&
867
+ destinationSnapshot.identity.dev === destination.identity.dev &&
868
+ destinationSnapshot.identity.ino === destination.identity.ino &&
869
+ destinationSnapshot.bytes.length >= sourceSnapshot.bytes.length &&
870
+ destinationSnapshot.bytes.subarray(0, sourceSnapshot.bytes.length).equals(sourceSnapshot.bytes);
871
+ const manifest = record.artifactManifest;
872
+ const validManifest =
873
+ Array.isArray(manifest) &&
874
+ manifest.every(entry => {
875
+ if (!entry || typeof entry !== "object" || Array.isArray(entry)) return false;
876
+ const item = entry as { kind?: unknown; path?: unknown; sha256?: unknown; size?: unknown };
877
+ const safePath =
878
+ typeof item.path === "string" && !path.isAbsolute(item.path) && !item.path.split(/[\\/]/).includes("..");
879
+ if (!safePath) return false;
880
+ if (item.kind === "directory") return true;
881
+ return (
882
+ item.kind === "file" &&
883
+ /^[a-f0-9]{64}$/.test(String(item.sha256)) &&
884
+ typeof item.size === "number" &&
885
+ Number.isSafeInteger(item.size) &&
886
+ item.size >= 0
887
+ );
888
+ });
889
+ return (
890
+ record.schemaVersion === 2 &&
891
+ record.state === "committed" &&
892
+ record.policy === "copy-retain" &&
893
+ record.scope === scopeDigest(scope.platform, scope.canonicalCwd) &&
894
+ validManifest &&
895
+ manifestContains(destination.path, manifest as readonly ArtifactManifestEntry[]) &&
896
+ record.source?.path === source.path &&
897
+ record.source?.sessionId === source.sessionId &&
898
+ record.source?.header?.id === source.sessionId &&
899
+ record.source?.header?.cwd === source.cwd &&
900
+ record.source?.sha256 === source.identity.sha256 &&
901
+ exact(record.source?.identity, source) &&
902
+ record.destination?.path === destination.path &&
903
+ record.destination?.sessionId === destination.sessionId &&
904
+ record.destination?.header?.id === destination.sessionId &&
905
+ record.destination?.header?.cwd === destination.cwd &&
906
+ lineage(record.destination?.identity, destination) &&
907
+ appendLineage
908
+ );
909
+ } catch {
910
+ return false;
911
+ }
912
+ }
913
+
914
+ function preparedReceiptMatches(
915
+ receiptPath: string,
916
+ scope: ManagedScope,
917
+ source: ManagedCandidate,
918
+ destination: { path: string; sessionId: string; cwd: string },
919
+ artifactPlan: DetachedArtifactRoot | undefined,
920
+ ): boolean {
921
+ try {
922
+ const record = JSON.parse(captureManagedFileNoFollow(receiptPath).bytes.toString("utf8")) as Record<
923
+ string,
924
+ unknown
925
+ >;
926
+ const recordedSource = record.source as Record<string, unknown> | undefined;
927
+ const recordedDestination = record.destination as Record<string, unknown> | undefined;
928
+ const quarantine = record.sourceArtifactQuarantine as Record<string, unknown> | undefined;
929
+ const identity = quarantine?.identity as Record<string, unknown> | undefined;
930
+ return (
931
+ record.schemaVersion === 2 &&
932
+ record.state === "prepared" &&
933
+ record.policy === "copy-retain" &&
934
+ record.scope === scopeDigest(scope.platform, scope.canonicalCwd) &&
935
+ Array.isArray(record.artifactManifest) &&
936
+ record.artifactManifest.length === 0 &&
937
+ recordedSource?.path === source.path &&
938
+ recordedSource.sessionId === source.sessionId &&
939
+ recordedSource.sha256 === source.identity.sha256 &&
940
+ (recordedSource.identity as Record<string, unknown> | undefined)?.dev === String(source.identity.dev) &&
941
+ (recordedSource.identity as Record<string, unknown> | undefined)?.ino === String(source.identity.ino) &&
942
+ (recordedSource.identity as Record<string, unknown> | undefined)?.size === source.identity.size &&
943
+ (recordedSource.identity as Record<string, unknown> | undefined)?.mtimeNs ===
944
+ String(source.identity.mtimeNs) &&
945
+ recordedDestination?.path === destination.path &&
946
+ recordedDestination.sessionId === destination.sessionId &&
947
+ recordedDestination.header instanceof Object &&
948
+ (recordedDestination.header as Record<string, unknown>).id === destination.sessionId &&
949
+ (recordedDestination.header as Record<string, unknown>).cwd === destination.cwd &&
950
+ (artifactPlan
951
+ ? quarantine?.path === artifactPlan.originalPath &&
952
+ quarantine.detachedPath === artifactPlan.detachedPath &&
953
+ identity?.dev === String(artifactPlan.identity.dev) &&
954
+ identity.ino === String(artifactPlan.identity.ino) &&
955
+ identity.size === String(artifactPlan.identity.size) &&
956
+ identity.mtimeNs === String(artifactPlan.identity.mtimeNs) &&
957
+ JSON.stringify(artifactTreeSnapshot(quarantine.tree)) === JSON.stringify(artifactPlan.tree)
958
+ : quarantine === undefined)
959
+ );
960
+ } catch {
961
+ return false;
962
+ }
963
+ }
964
+
965
+ type RetiredTarget = ManagedCandidate;
966
+
967
+ function retiredTargets(scope: ManagedScope, pathname: string): readonly RetiredTarget[] | undefined {
968
+ try {
969
+ const value: unknown = JSON.parse(captureManagedFileNoFollow(pathname).bytes.toString("utf8"));
970
+ if (!value || typeof value !== "object") return undefined;
971
+ const record = value as { schemaVersion?: unknown; state?: unknown; scope?: unknown; targets?: unknown };
972
+ if (
973
+ record.schemaVersion !== 2 ||
974
+ record.state !== "retired" ||
975
+ record.scope !== scopeDigest(scope.platform, scope.canonicalCwd) ||
976
+ !Array.isArray(record.targets)
977
+ )
978
+ return undefined;
979
+ const targets: RetiredTarget[] = [];
980
+ for (const target of record.targets) {
981
+ if (!target || typeof target !== "object" || Array.isArray(target)) return undefined;
982
+ const item = target as Record<string, unknown>;
983
+ const identity = item.identity;
984
+ if (!identity || typeof identity !== "object" || Array.isArray(identity)) return undefined;
985
+ const fields = identity as Record<string, unknown>;
986
+ if (
987
+ typeof item.path !== "string" ||
988
+ typeof item.sessionId !== "string" ||
989
+ typeof item.cwd !== "string" ||
990
+ !pathIsWithin(scope.sessionsRoot, item.path) ||
991
+ (item.provenance !== undefined && item.provenance !== "v2" && item.provenance !== "legacy") ||
992
+ typeof fields.canonicalPath !== "string" ||
993
+ typeof fields.dev !== "string" ||
994
+ typeof fields.ino !== "string" ||
995
+ typeof fields.size !== "number" ||
996
+ typeof fields.mtimeMs !== "number" ||
997
+ typeof fields.mtimeNs !== "string" ||
998
+ typeof fields.sha256 !== "string"
999
+ )
1000
+ return undefined;
1001
+ const provenance =
1002
+ item.provenance === "v2" || item.provenance === "legacy"
1003
+ ? item.provenance
1004
+ : path.dirname(item.path) === scope.directoryPath
1005
+ ? "v2"
1006
+ : "legacy";
1007
+ targets.push({
1008
+ path: item.path,
1009
+ sessionId: item.sessionId,
1010
+ cwd: item.cwd,
1011
+ provenance,
1012
+ migrationState: provenance === "v2" ? "native_v2" : "legacy_unmigrated",
1013
+ identity: {
1014
+ canonicalPath: fields.canonicalPath,
1015
+ dev: BigInt(fields.dev),
1016
+ ino: BigInt(fields.ino),
1017
+ size: fields.size,
1018
+ mtimeMs: fields.mtimeMs,
1019
+ mtimeNs: BigInt(fields.mtimeNs),
1020
+ sha256: fields.sha256,
1021
+ sessionId: item.sessionId,
1022
+ },
1023
+ });
1024
+ }
1025
+ return targets;
1026
+ } catch {
1027
+ return undefined;
1028
+ }
1029
+ }
1030
+
1031
+ /**
1032
+ * Append-only cleanup state machine:
1033
+ * `pending(N)` durably authorizes only its planned quarantine names before detach;
1034
+ * a returned partial result appends `pending(N + 1)` with the observed detached
1035
+ * identity/path. Restart accepts only a contiguous, target-bound sequence.
1036
+ */
1037
+ type CleanupReceipt = {
1038
+ attempt: number;
1039
+ target: RetiredTarget;
1040
+ expectedArtifactsIdentity?: SessionStorageFileIdentity;
1041
+ expectedArtifactsTree?: NativeDirectoryTreeSnapshot;
1042
+ detachedArtifactsPath?: string;
1043
+ detachedTranscriptPath?: string;
1044
+ plannedArtifactsPath: string;
1045
+ plannedTranscriptPath: string;
1046
+ };
1047
+
1048
+ function cleanupReceiptPath(
1049
+ tombstone: string,
1050
+ target: RetiredTarget,
1051
+ state: "pending" | "artifacts_removed" | "completed",
1052
+ attempt: number,
1053
+ ): string {
1054
+ return path.join(
1055
+ path.dirname(tombstone),
1056
+ `${path.basename(tombstone, ".json")}.${stableOperationName(target)}.cleanup-${state}-${attempt}.json`,
1057
+ );
1058
+ }
1059
+
1060
+ function cleanupReceipt(scope: ManagedScope, tombstone: string, receipt: CleanupReceipt): Record<string, unknown> {
1061
+ return {
1062
+ schemaVersion: 2,
1063
+ state: "cleanup_pending",
1064
+ scope: scopeDigest(scope.platform, scope.canonicalCwd),
1065
+ tombstone,
1066
+ attempt: receipt.attempt,
1067
+ target: {
1068
+ path: receipt.target.path,
1069
+ sessionId: receipt.target.sessionId,
1070
+ cwd: receipt.target.cwd,
1071
+ identity: receipt.target.identity,
1072
+ },
1073
+ ...(receipt.expectedArtifactsIdentity ? { expectedArtifactsIdentity: receipt.expectedArtifactsIdentity } : {}),
1074
+ ...(receipt.expectedArtifactsTree ? { expectedArtifactsTree: receipt.expectedArtifactsTree } : {}),
1075
+ ...(receipt.detachedArtifactsPath ? { detachedArtifactsPath: receipt.detachedArtifactsPath } : {}),
1076
+ ...(receipt.detachedTranscriptPath ? { detachedTranscriptPath: receipt.detachedTranscriptPath } : {}),
1077
+ plannedArtifactsPath: receipt.plannedArtifactsPath,
1078
+ plannedTranscriptPath: receipt.plannedTranscriptPath,
1079
+ };
1080
+ }
1081
+
1082
+ function cleanupArtifactsRemoved(
1083
+ scope: ManagedScope,
1084
+ tombstone: string,
1085
+ target: RetiredTarget,
1086
+ attempt: number,
1087
+ ): boolean {
1088
+ try {
1089
+ const value: unknown = JSON.parse(
1090
+ captureManagedFileNoFollow(cleanupReceiptPath(tombstone, target, "artifacts_removed", attempt)).bytes.toString(
1091
+ "utf8",
1092
+ ),
1093
+ );
1094
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
1095
+ const record = value as Record<string, unknown>;
1096
+ const recorded = record.target as Record<string, unknown> | undefined;
1097
+ return (
1098
+ record.schemaVersion === 2 &&
1099
+ record.state === "artifacts_removed" &&
1100
+ record.scope === scopeDigest(scope.platform, scope.canonicalCwd) &&
1101
+ record.tombstone === tombstone &&
1102
+ record.attempt === attempt &&
1103
+ recorded?.path === target.path &&
1104
+ recorded.sessionId === target.sessionId &&
1105
+ recorded.cwd === target.cwd
1106
+ );
1107
+ } catch {
1108
+ return false;
1109
+ }
1110
+ }
1111
+
1112
+ async function publishCleanupArtifactsRemoved(
1113
+ scope: ManagedScope,
1114
+ tombstone: string,
1115
+ receipt: CleanupReceipt,
1116
+ lock: ManagedStorageLock,
1117
+ ): Promise<void> {
1118
+ await publishManagedTombstone(
1119
+ cleanupReceiptPath(tombstone, receipt.target, "artifacts_removed", receipt.attempt),
1120
+ { ...cleanupReceipt(scope, tombstone, receipt), state: "artifacts_removed" },
1121
+ lock.assertOwned,
1122
+ ).catch(error => {
1123
+ if ((error as Error).message !== "destination_conflict") throw error;
1124
+ });
1125
+ if (!cleanupArtifactsRemoved(scope, tombstone, receipt.target, receipt.attempt))
1126
+ throw new Error("durability_failed");
1127
+ }
1128
+
1129
+ function isQuarantinePath(target: RetiredTarget, pathname: unknown): pathname is string {
1130
+ return (
1131
+ typeof pathname === "string" &&
1132
+ path.dirname(pathname) === path.dirname(target.path) &&
1133
+ path.basename(pathname).startsWith(".skc-delete-")
1134
+ );
1135
+ }
1136
+
1137
+ function deterministicRemovalRoot(plannedRoot: string): string {
1138
+ return `${plannedRoot}.removing`;
1139
+ }
1140
+
1141
+ function isAuthorizedArtifactRoot(target: RetiredTarget, plannedRoot: string, pathname: unknown): pathname is string {
1142
+ return (
1143
+ isQuarantinePath(target, pathname) &&
1144
+ (pathname === plannedRoot || pathname === deterministicRemovalRoot(plannedRoot))
1145
+ );
1146
+ }
1147
+
1148
+ function artifactRootsAbsent(
1149
+ _scope: ManagedScope,
1150
+ tombstone: string,
1151
+ target: RetiredTarget,
1152
+ pending: CleanupReceipt,
1153
+ ): boolean {
1154
+ const prefix = `${path.basename(tombstone, ".json")}.${stableOperationName(target)}.cleanup-pending-`;
1155
+ const roots = new Set<string>([
1156
+ pending.plannedArtifactsPath,
1157
+ deterministicRemovalRoot(pending.plannedArtifactsPath),
1158
+ ...(pending.detachedArtifactsPath ? [pending.detachedArtifactsPath] : []),
1159
+ ]);
1160
+ for (const name of fs.readdirSync(path.dirname(tombstone))) {
1161
+ if (!name.startsWith(prefix) || !name.endsWith(".json")) continue;
1162
+ const record = JSON.parse(
1163
+ captureManagedFileNoFollow(path.join(path.dirname(tombstone), name)).bytes.toString("utf8"),
1164
+ ) as {
1165
+ plannedArtifactsPath?: unknown;
1166
+ detachedArtifactsPath?: unknown;
1167
+ };
1168
+ if (isQuarantinePath(target, record.plannedArtifactsPath)) {
1169
+ roots.add(record.plannedArtifactsPath);
1170
+ roots.add(deterministicRemovalRoot(record.plannedArtifactsPath));
1171
+ }
1172
+ if (isQuarantinePath(target, record.detachedArtifactsPath)) roots.add(record.detachedArtifactsPath);
1173
+ }
1174
+ return [...roots].every(pathname => !fs.existsSync(pathname));
1175
+ }
1176
+
1177
+ function sameArtifactRootIdentity(left: SessionStorageFileIdentity, right: SessionStorageFileIdentity): boolean {
1178
+ return left.dev === right.dev && left.ino === right.ino;
1179
+ }
1180
+
1181
+ /**
1182
+ * A pending receipt is written before the native no-replace detach. If a crash
1183
+ * happens after that detach, the next receipt may only inherit the exact
1184
+ * planned quarantine pathname and identity from its predecessor.
1185
+ */
1186
+ function probePlannedCleanupDetach(target: RetiredTarget, pending: CleanupReceipt): CleanupReceipt {
1187
+ let detachedArtifactsPath = pending.detachedArtifactsPath;
1188
+ let detachedTranscriptPath = pending.detachedTranscriptPath;
1189
+ for (const pathname of [pending.plannedArtifactsPath, deterministicRemovalRoot(pending.plannedArtifactsPath)]) {
1190
+ if (!fs.existsSync(pathname)) continue;
1191
+ if (!pending.expectedArtifactsIdentity) throw new Error("durability_failed");
1192
+ const observed = artifactIdentityAt(pathname);
1193
+ if (!observed || !sameArtifactRootIdentity(observed, pending.expectedArtifactsIdentity))
1194
+ throw new Error("durability_failed");
1195
+ if (detachedArtifactsPath && detachedArtifactsPath !== pathname) throw new Error("durability_failed");
1196
+ detachedArtifactsPath = pathname;
1197
+ }
1198
+ if (fs.existsSync(pending.plannedTranscriptPath)) {
1199
+ const observed = captureManagedFileNoFollow(pending.plannedTranscriptPath);
1200
+ const digest = createHash("sha256").update(observed.bytes).digest("hex");
1201
+ if (
1202
+ observed.identity.dev !== target.identity.dev ||
1203
+ observed.identity.ino !== target.identity.ino ||
1204
+ observed.identity.size !== target.identity.size ||
1205
+ observed.identity.mtimeNs !== target.identity.mtimeNs ||
1206
+ digest !== target.identity.sha256
1207
+ )
1208
+ throw new Error("durability_failed");
1209
+ detachedTranscriptPath = pending.plannedTranscriptPath;
1210
+ }
1211
+ return { ...pending, detachedArtifactsPath, detachedTranscriptPath };
1212
+ }
1213
+
1214
+ function artifactIdentityAt(pathname: string): SessionStorageFileIdentity | undefined {
1215
+ try {
1216
+ const stat = fs.lstatSync(pathname, { bigint: true });
1217
+ if (stat.isSymbolicLink() || !stat.isDirectory()) return undefined;
1218
+ return { dev: stat.dev, ino: stat.ino, size: Number(stat.size), mtimeNs: stat.mtimeNs, sha256: "" };
1219
+ } catch (error) {
1220
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") return undefined;
1221
+ throw error;
1222
+ }
1223
+ }
1224
+
1225
+ function artifactTreeSnapshot(value: unknown): NativeDirectoryTreeSnapshot | undefined {
1226
+ if (!value || typeof value !== "object" || Array.isArray(value)) return undefined;
1227
+ const snapshot = value as Record<string, unknown>;
1228
+ if (typeof snapshot.rootDev !== "string" || typeof snapshot.rootIno !== "string" || !Array.isArray(snapshot.entries))
1229
+ return undefined;
1230
+ if (
1231
+ snapshot.entries.length === 0 ||
1232
+ !snapshot.entries.every(entry => {
1233
+ if (!entry || typeof entry !== "object" || Array.isArray(entry)) return false;
1234
+ const item = entry as Record<string, unknown>;
1235
+ return (
1236
+ typeof item.relativePath === "string" &&
1237
+ !path.isAbsolute(item.relativePath) &&
1238
+ !item.relativePath.split(/[\\/]/).includes("..") &&
1239
+ (item.kind === "file" || item.kind === "directory") &&
1240
+ typeof item.dev === "string" &&
1241
+ typeof item.ino === "string" &&
1242
+ typeof item.size === "string" &&
1243
+ typeof item.mtimeNs === "string" &&
1244
+ typeof item.ctimeNs === "string" &&
1245
+ (item.sha256 === undefined || typeof item.sha256 === "string")
1246
+ );
1247
+ })
1248
+ )
1249
+ return undefined;
1250
+ return snapshot as unknown as NativeDirectoryTreeSnapshot;
1251
+ }
1252
+
1253
+ function pendingCleanupReceipt(
1254
+ scope: ManagedScope,
1255
+ tombstone: string,
1256
+ target: RetiredTarget,
1257
+ ): CleanupReceipt | undefined {
1258
+ try {
1259
+ const prefix = `${path.basename(tombstone, ".json")}.${stableOperationName(target)}.cleanup-pending-`;
1260
+ const records = fs
1261
+ .readdirSync(path.dirname(tombstone))
1262
+ .filter(name => name.startsWith(prefix) && name.endsWith(".json"))
1263
+ .map(
1264
+ name =>
1265
+ JSON.parse(
1266
+ captureManagedFileNoFollow(path.join(path.dirname(tombstone), name)).bytes.toString("utf8"),
1267
+ ) as unknown,
1268
+ )
1269
+ .filter(
1270
+ (value): value is Record<string, unknown> => !!value && typeof value === "object" && !Array.isArray(value),
1271
+ )
1272
+ .sort((left, right) => Number(left.attempt) - Number(right.attempt));
1273
+ let latest: CleanupReceipt | undefined;
1274
+ const plannedPaths = new Set<string>();
1275
+ for (const record of records) {
1276
+ const attempt = record.attempt;
1277
+ const recorded = record.target as Record<string, unknown> | undefined;
1278
+ const identity = recorded?.identity as Record<string, unknown> | undefined;
1279
+ if (
1280
+ record.schemaVersion !== 2 ||
1281
+ record.state !== "cleanup_pending" ||
1282
+ record.scope !== scopeDigest(scope.platform, scope.canonicalCwd) ||
1283
+ record.tombstone !== tombstone ||
1284
+ typeof attempt !== "number" ||
1285
+ !Number.isSafeInteger(attempt) ||
1286
+ attempt !== (latest?.attempt ?? 0) + 1 ||
1287
+ recorded?.path !== target.path ||
1288
+ recorded.sessionId !== target.sessionId ||
1289
+ recorded.cwd !== target.cwd ||
1290
+ identity?.dev !== String(target.identity.dev) ||
1291
+ identity.ino !== String(target.identity.ino) ||
1292
+ identity.size !== target.identity.size ||
1293
+ identity.mtimeNs !== String(target.identity.mtimeNs) ||
1294
+ identity.sha256 !== target.identity.sha256 ||
1295
+ !isQuarantinePath(target, record.plannedArtifactsPath) ||
1296
+ !isQuarantinePath(target, record.plannedTranscriptPath) ||
1297
+ record.plannedArtifactsPath === record.plannedTranscriptPath ||
1298
+ plannedPaths.has(record.plannedArtifactsPath as string) ||
1299
+ plannedPaths.has(record.plannedTranscriptPath as string) ||
1300
+ (record.detachedArtifactsPath !== undefined && !isQuarantinePath(target, record.detachedArtifactsPath)) ||
1301
+ (record.detachedTranscriptPath !== undefined && !isQuarantinePath(target, record.detachedTranscriptPath))
1302
+ )
1303
+ throw new Error("durability_failed");
1304
+ const artifact = record.expectedArtifactsIdentity as Record<string, unknown> | undefined;
1305
+ const expectedArtifactsIdentity = artifact
1306
+ ? typeof artifact.dev === "string" &&
1307
+ typeof artifact.ino === "string" &&
1308
+ typeof artifact.size === "number" &&
1309
+ typeof artifact.mtimeNs === "string" &&
1310
+ typeof artifact.sha256 === "string"
1311
+ ? {
1312
+ dev: BigInt(artifact.dev),
1313
+ ino: BigInt(artifact.ino),
1314
+ size: artifact.size,
1315
+ mtimeNs: BigInt(artifact.mtimeNs),
1316
+ sha256: artifact.sha256,
1317
+ }
1318
+ : undefined
1319
+ : undefined;
1320
+ if (artifact && !expectedArtifactsIdentity) throw new Error("durability_failed");
1321
+ const expectedArtifactsTree =
1322
+ record.expectedArtifactsTree === undefined ? undefined : artifactTreeSnapshot(record.expectedArtifactsTree);
1323
+ if (record.expectedArtifactsTree !== undefined && !expectedArtifactsTree) throw new Error("durability_failed");
1324
+ if (record.detachedArtifactsPath !== undefined && !expectedArtifactsTree) throw new Error("durability_failed");
1325
+ if (
1326
+ latest &&
1327
+ ((record.detachedArtifactsPath !== undefined &&
1328
+ ![...plannedPaths].some(planned =>
1329
+ isAuthorizedArtifactRoot(target, planned, record.detachedArtifactsPath),
1330
+ )) ||
1331
+ (record.detachedTranscriptPath !== undefined && !plannedPaths.has(record.detachedTranscriptPath)))
1332
+ )
1333
+ throw new Error("durability_failed");
1334
+ plannedPaths.add(record.plannedArtifactsPath as string);
1335
+ plannedPaths.add(record.plannedTranscriptPath as string);
1336
+ latest = {
1337
+ attempt,
1338
+ target,
1339
+ expectedArtifactsIdentity,
1340
+ expectedArtifactsTree,
1341
+ detachedArtifactsPath: record.detachedArtifactsPath as string | undefined,
1342
+ detachedTranscriptPath: record.detachedTranscriptPath as string | undefined,
1343
+ plannedArtifactsPath: record.plannedArtifactsPath as string,
1344
+ plannedTranscriptPath: record.plannedTranscriptPath as string,
1345
+ };
1346
+ }
1347
+ return latest;
1348
+ } catch (error) {
1349
+ if ((error as Error).message === "durability_failed") throw error;
1350
+ return undefined;
1351
+ }
1352
+ }
1353
+
1354
+ function artifactIdentityForCleanup(target: RetiredTarget): SessionStorageFileIdentity | undefined {
1355
+ try {
1356
+ const stat = fs.lstatSync(target.path.slice(0, -6), { bigint: true });
1357
+ if (stat.isSymbolicLink() || !stat.isDirectory()) throw new Error("unsafe_artifacts");
1358
+ return { dev: stat.dev, ino: stat.ino, size: Number(stat.size), mtimeNs: stat.mtimeNs, sha256: "" };
1359
+ } catch (error) {
1360
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") return undefined;
1361
+ throw error;
1362
+ }
1363
+ }
1364
+
1365
+ type NativeDirectorySnapshotApi = {
1366
+ snapshotDirectoryTree(
1367
+ pathname: string,
1368
+ ): { ok: true; snapshot: NativeDirectoryTreeSnapshot } | { ok: false; code: string; snapshot?: undefined };
1369
+ };
1370
+ function snapshotArtifactTree(pathname: string): NativeDirectoryTreeSnapshot {
1371
+ validateManagedArtifactTree(pathname);
1372
+ const result = (native as unknown as NativeDirectorySnapshotApi).snapshotDirectoryTree(pathname);
1373
+ if (!result.ok || !result.snapshot) throw new Error(result.ok ? "unsafe_artifacts" : result.code);
1374
+ return result.snapshot;
1375
+ }
1376
+
1377
+ function nextCleanupReceipt(target: RetiredTarget, pending: CleanupReceipt | undefined): CleanupReceipt {
1378
+ const attempt = (pending?.attempt ?? 0) + 1;
1379
+ const directory = path.dirname(target.path);
1380
+ const operation = stableOperationName(target);
1381
+ const expectedArtifactsIdentity = pending?.expectedArtifactsIdentity ?? artifactIdentityForCleanup(target);
1382
+ const expectedArtifactsTree =
1383
+ pending?.expectedArtifactsTree ??
1384
+ (expectedArtifactsIdentity ? snapshotArtifactTree(target.path.slice(0, -6)) : undefined);
1385
+ if (pending?.expectedArtifactsIdentity && !expectedArtifactsTree) throw new Error("durability_failed");
1386
+ return {
1387
+ attempt,
1388
+ target,
1389
+ expectedArtifactsIdentity,
1390
+ expectedArtifactsTree,
1391
+ detachedArtifactsPath: pending?.detachedArtifactsPath,
1392
+ detachedTranscriptPath: pending?.detachedTranscriptPath,
1393
+ plannedArtifactsPath: path.join(directory, `.skc-delete-${operation}-artifacts-${attempt}`),
1394
+ plannedTranscriptPath: path.join(directory, `.skc-delete-${operation}-transcript-${attempt}`),
1395
+ };
1396
+ }
1397
+
1398
+ function requiresFreshCleanupPlan(pending: CleanupReceipt): boolean {
1399
+ return (
1400
+ (pending.detachedArtifactsPath !== undefined && pending.detachedArtifactsPath === pending.plannedArtifactsPath) ||
1401
+ (pending.detachedTranscriptPath !== undefined && pending.detachedTranscriptPath === pending.plannedTranscriptPath)
1402
+ );
1403
+ }
1404
+
1405
+ async function publishCleanupPending(
1406
+ scope: ManagedScope,
1407
+ tombstone: string,
1408
+ receipt: CleanupReceipt,
1409
+ lock: ManagedStorageLock,
1410
+ ): Promise<void> {
1411
+ try {
1412
+ await publishManagedTombstone(
1413
+ cleanupReceiptPath(tombstone, receipt.target, "pending", receipt.attempt),
1414
+ cleanupReceipt(scope, tombstone, receipt),
1415
+ lock.assertOwned,
1416
+ );
1417
+ } catch (error) {
1418
+ if ((error as Error).message !== "destination_conflict") throw error;
1419
+ }
1420
+ const persisted = pendingCleanupReceipt(scope, tombstone, receipt.target);
1421
+ if (!persisted || persisted.attempt !== receipt.attempt) throw new Error("durability_failed");
1422
+ }
1423
+
1424
+ function cleanupCompleted(scope: ManagedScope, tombstone: string, target: RetiredTarget): boolean {
1425
+ try {
1426
+ const value: unknown = JSON.parse(
1427
+ captureManagedFileNoFollow(cleanupReceiptPath(tombstone, target, "completed", 1)).bytes.toString("utf8"),
1428
+ );
1429
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
1430
+ const record = value as Record<string, unknown>;
1431
+ const recorded = record.target as Record<string, unknown> | undefined;
1432
+ const identity = recorded?.identity as Record<string, unknown> | undefined;
1433
+ return (
1434
+ record.schemaVersion === 1 &&
1435
+ record.state === "cleanup_completed" &&
1436
+ record.scope === scopeDigest(scope.platform, scope.canonicalCwd) &&
1437
+ record.tombstone === tombstone &&
1438
+ record.attempt === 1 &&
1439
+ recorded?.path === target.path &&
1440
+ recorded.sessionId === target.sessionId &&
1441
+ recorded.cwd === target.cwd &&
1442
+ identity?.dev === String(target.identity.dev) &&
1443
+ identity.ino === String(target.identity.ino) &&
1444
+ identity.size === target.identity.size &&
1445
+ identity.mtimeNs === String(target.identity.mtimeNs) &&
1446
+ identity.sha256 === target.identity.sha256
1447
+ );
1448
+ } catch {
1449
+ return false;
1450
+ }
1451
+ }
1452
+
1453
+ async function publishCleanupCompleted(
1454
+ scope: ManagedScope,
1455
+ tombstone: string,
1456
+ target: RetiredTarget,
1457
+ lock: ManagedStorageLock,
1458
+ ): Promise<void> {
1459
+ try {
1460
+ await publishManagedTombstone(
1461
+ cleanupReceiptPath(tombstone, target, "completed", 1),
1462
+ {
1463
+ schemaVersion: 1,
1464
+ state: "cleanup_completed",
1465
+ scope: scopeDigest(scope.platform, scope.canonicalCwd),
1466
+ tombstone,
1467
+ attempt: 1,
1468
+ target: { path: target.path, sessionId: target.sessionId, cwd: target.cwd, identity: target.identity },
1469
+ },
1470
+ lock.assertOwned,
1471
+ );
1472
+ } catch (error) {
1473
+ if ((error as Error).message !== "destination_conflict") throw error;
1474
+ }
1475
+ }
1476
+
1477
+ function tombstonePathContaining(scope: ManagedScope, candidate: ManagedCandidate): string | undefined {
1478
+ const directory = path.join(managedInternalDirectory(scope), MANAGED_TOMBSTONES_DIRECTORY);
1479
+ try {
1480
+ for (const name of fs.readdirSync(directory)) {
1481
+ const pathname = path.join(directory, name);
1482
+ if (retiredTargets(scope, pathname)?.some(target => sameCandidate(target, candidate))) return pathname;
1483
+ }
1484
+ } catch {
1485
+ return undefined;
1486
+ }
1487
+ return undefined;
1488
+ }
1489
+
1490
+ function isRetired(scope: ManagedScope, candidate: ManagedCandidate): boolean {
1491
+ const directory = path.join(managedInternalDirectory(scope), MANAGED_TOMBSTONES_DIRECTORY);
1492
+ try {
1493
+ for (const name of fs.readdirSync(directory)) {
1494
+ const pathname = path.join(directory, name);
1495
+ const value: unknown = JSON.parse(captureManagedFileNoFollow(pathname).bytes.toString("utf8"));
1496
+ if (!value || typeof value !== "object") continue;
1497
+ const record = value as { schemaVersion?: unknown; state?: unknown; scope?: unknown; targets?: unknown };
1498
+ if (
1499
+ record.schemaVersion !== 2 ||
1500
+ record.state !== "retired" ||
1501
+ record.scope !== scopeDigest(scope.platform, scope.canonicalCwd) ||
1502
+ !Array.isArray(record.targets)
1503
+ )
1504
+ continue;
1505
+ if (
1506
+ record.targets.some(target => {
1507
+ if (!target || typeof target !== "object") return false;
1508
+ const value = target as {
1509
+ path?: unknown;
1510
+ sessionId?: unknown;
1511
+ cwd?: unknown;
1512
+ identity?: {
1513
+ canonicalPath?: unknown;
1514
+ dev?: unknown;
1515
+ ino?: unknown;
1516
+ size?: unknown;
1517
+ mtimeNs?: unknown;
1518
+ sha256?: unknown;
1519
+ };
1520
+ };
1521
+ const identity = value.identity;
1522
+ if (!identity) return false;
1523
+ return (
1524
+ value.path === candidate.path &&
1525
+ value.sessionId === candidate.sessionId &&
1526
+ value.cwd === candidate.cwd &&
1527
+ identity.canonicalPath === candidate.identity.canonicalPath &&
1528
+ identity.dev === String(candidate.identity.dev) &&
1529
+ identity.ino === String(candidate.identity.ino) &&
1530
+ identity.size === candidate.identity.size &&
1531
+ identity.mtimeNs === String(candidate.identity.mtimeNs) &&
1532
+ identity.sha256 === candidate.identity.sha256
1533
+ );
1534
+ })
1535
+ )
1536
+ return true;
1537
+ }
1538
+ } catch {
1539
+ /* a missing/malformed tombstone grants no retirement authority */
1540
+ }
1541
+ return false;
1542
+ }
1543
+
1544
+ type ArtifactManifestEntry =
1545
+ | { kind: "directory"; path: string }
1546
+ | { kind: "file"; path: string; sha256: string; size: number };
1547
+
1548
+ function artifactManifestFromSnapshot(snapshot: NativeDirectoryTreeSnapshot): readonly ArtifactManifestEntry[] {
1549
+ return snapshot.entries
1550
+ .map(entry => {
1551
+ if (entry.kind === "directory") return { kind: "directory" as const, path: entry.relativePath };
1552
+ const size = Number(entry.size);
1553
+ if (
1554
+ entry.kind !== "file" ||
1555
+ !Number.isSafeInteger(size) ||
1556
+ size < 0 ||
1557
+ typeof entry.sha256 !== "string" ||
1558
+ !/^[a-f0-9]{64}$/.test(entry.sha256)
1559
+ )
1560
+ throw new Error("unsafe_artifacts");
1561
+ return { kind: "file" as const, path: entry.relativePath, size, sha256: entry.sha256 };
1562
+ })
1563
+ .sort((left, right) => left.path.localeCompare(right.path) || left.kind.localeCompare(right.kind));
1564
+ }
1565
+
1566
+ function artifactManifest(transcriptPath: string, rootOverride?: string): readonly ArtifactManifestEntry[] {
1567
+ const root = rootOverride ?? transcriptPath.slice(0, -6);
1568
+ try {
1569
+ validateManagedArtifactTree(root);
1570
+ const entries: ArtifactManifestEntry[] = [{ kind: "directory", path: "" }];
1571
+ const walk = (directory: string): void => {
1572
+ for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
1573
+ const pathname = path.join(directory, entry.name);
1574
+ const relative = path.relative(root, pathname).split(path.sep).join("/");
1575
+ if (entry.isDirectory()) {
1576
+ entries.push({ kind: "directory", path: relative });
1577
+ walk(pathname);
1578
+ } else {
1579
+ const snapshot = captureManagedFileNoFollow(pathname);
1580
+ entries.push({
1581
+ kind: "file",
1582
+ path: relative,
1583
+ size: snapshot.bytes.byteLength,
1584
+ sha256: createHash("sha256").update(snapshot.bytes).digest("hex"),
1585
+ });
1586
+ }
1587
+ }
1588
+ };
1589
+ walk(root);
1590
+ return entries.sort((left, right) => left.path.localeCompare(right.path) || left.kind.localeCompare(right.kind));
1591
+ } catch (error) {
1592
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") return [];
1593
+ throw error;
1594
+ }
1595
+ }
1596
+
1597
+ function manifestMatches(
1598
+ transcriptPath: string,
1599
+ manifest: readonly ArtifactManifestEntry[],
1600
+ rootOverride?: string,
1601
+ ): boolean {
1602
+ try {
1603
+ const actual = artifactManifest(transcriptPath, rootOverride);
1604
+ return (
1605
+ actual.length === manifest.length &&
1606
+ actual.every((entry, index) => {
1607
+ const expected = manifest[index];
1608
+ return entry.kind === "directory"
1609
+ ? expected?.kind === "directory" && entry.path === expected.path
1610
+ : expected?.kind === "file" &&
1611
+ entry.path === expected.path &&
1612
+ entry.sha256 === expected.sha256 &&
1613
+ entry.size === expected.size;
1614
+ })
1615
+ );
1616
+ } catch {
1617
+ return false;
1618
+ }
1619
+ }
1620
+
1621
+ function manifestContains(transcriptPath: string, manifest: readonly ArtifactManifestEntry[]): boolean {
1622
+ try {
1623
+ const actual = artifactManifest(transcriptPath);
1624
+ return manifest.every(expected =>
1625
+ actual.some(entry =>
1626
+ entry.kind === "directory"
1627
+ ? expected.kind === "directory" && entry.path === expected.path
1628
+ : expected.kind === "file" &&
1629
+ entry.path === expected.path &&
1630
+ entry.sha256 === expected.sha256 &&
1631
+ entry.size === expected.size,
1632
+ ),
1633
+ );
1634
+ } catch {
1635
+ return false;
1636
+ }
1637
+ }
1638
+
1639
+ type DetachedArtifactRoot = {
1640
+ originalPath: string;
1641
+ detachedPath: string;
1642
+ identity: { dev: bigint; ino: bigint; size: bigint; mtimeNs: bigint };
1643
+ tree: NativeDirectoryTreeSnapshot;
1644
+ };
1645
+
1646
+ function planArtifactRootForMigration(sourceTranscript: string, operation: string): DetachedArtifactRoot | undefined {
1647
+ const originalPath = sourceTranscript.slice(0, -6);
1648
+ let stat: fs.BigIntStats;
1649
+ try {
1650
+ stat = fs.lstatSync(originalPath, { bigint: true });
1651
+ } catch (error) {
1652
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") return undefined;
1653
+ throw error;
1654
+ }
1655
+ if (!stat.isDirectory() || stat.isSymbolicLink()) throw new Error("unsafe_artifacts");
1656
+ return {
1657
+ originalPath,
1658
+ detachedPath: path.join(path.dirname(originalPath), `.skc-migrate-${operation}-artifacts`),
1659
+ identity: { dev: stat.dev, ino: stat.ino, size: stat.size, mtimeNs: stat.mtimeNs },
1660
+ tree: snapshotArtifactTree(originalPath),
1661
+ };
1662
+ }
1663
+
1664
+ function sameDirectoryObject(leftPath: string, rightPath: string): boolean {
1665
+ try {
1666
+ const left = fs.lstatSync(leftPath, { bigint: true });
1667
+ const right = fs.lstatSync(rightPath, { bigint: true });
1668
+ return (
1669
+ left.isDirectory() &&
1670
+ right.isDirectory() &&
1671
+ !left.isSymbolicLink() &&
1672
+ !right.isSymbolicLink() &&
1673
+ left.dev === right.dev &&
1674
+ left.ino === right.ino
1675
+ );
1676
+ } catch {
1677
+ return false;
1678
+ }
1679
+ }
1680
+
1681
+ function matchesDetachedArtifactRoot(pathname: string, plan: DetachedArtifactRoot): boolean {
1682
+ try {
1683
+ const stat = fs.lstatSync(pathname, { bigint: true });
1684
+ return (
1685
+ stat.isDirectory() &&
1686
+ !stat.isSymbolicLink() &&
1687
+ stat.dev === plan.identity.dev &&
1688
+ stat.ino === plan.identity.ino &&
1689
+ stat.size === plan.identity.size &&
1690
+ stat.mtimeNs === plan.identity.mtimeNs &&
1691
+ sameDirectoryObject(path.dirname(pathname), path.dirname(plan.detachedPath))
1692
+ );
1693
+ } catch {
1694
+ return false;
1695
+ }
1696
+ }
1697
+
1698
+ function detachArtifactRootForMigration(plan: DetachedArtifactRoot): DetachedArtifactRoot {
1699
+ const result = native.exactUnlink(plan.originalPath, {
1700
+ ...plan.identity,
1701
+ directory: true,
1702
+ detachOnly: true,
1703
+ quarantineName: path.basename(plan.detachedPath),
1704
+ });
1705
+ if (!result.ok || !result.detachedPath || !matchesDetachedArtifactRoot(result.detachedPath, plan))
1706
+ throw new Error("durability_failed");
1707
+ return { ...plan, detachedPath: result.detachedPath };
1708
+ }
1709
+
1710
+ function restorePreparedArtifactRoot(scope: ManagedScope, source: ManagedCandidate): void {
1711
+ const receipt = receiptPathFor(scope, source, "prepared");
1712
+ let record: {
1713
+ sourceArtifactQuarantine?: {
1714
+ path?: unknown;
1715
+ detachedPath?: unknown;
1716
+ identity?: Record<string, unknown>;
1717
+ tree?: unknown;
1718
+ };
1719
+ };
1720
+ try {
1721
+ record = JSON.parse(captureManagedFileNoFollow(receipt).bytes.toString("utf8")) as typeof record;
1722
+ } catch {
1723
+ if (!fs.existsSync(receipt)) return;
1724
+ throw new Error("durability_failed");
1725
+ }
1726
+ const quarantine = record.sourceArtifactQuarantine;
1727
+ if (!quarantine) return;
1728
+ const identity = quarantine.identity;
1729
+ if (
1730
+ quarantine.path !== source.path.slice(0, -6) ||
1731
+ typeof quarantine.detachedPath !== "string" ||
1732
+ path.dirname(quarantine.detachedPath) !== path.dirname(source.path) ||
1733
+ !path.basename(quarantine.detachedPath).startsWith(".skc-migrate-") ||
1734
+ !artifactTreeSnapshot(quarantine.tree) ||
1735
+ !identity ||
1736
+ typeof identity.dev !== "string" ||
1737
+ typeof identity.ino !== "string" ||
1738
+ typeof identity.size !== "string" ||
1739
+ typeof identity.mtimeNs !== "string"
1740
+ )
1741
+ throw new Error("durability_failed");
1742
+ const expectedTree = artifactTreeSnapshot(quarantine.tree)!;
1743
+ const assertPreparedTree = (pathname: string): void => {
1744
+ validateManagedArtifactTree(pathname);
1745
+ const observed = native.snapshotDirectoryTree(pathname);
1746
+ if (!observed.ok || !observed.snapshot || JSON.stringify(observed.snapshot) !== JSON.stringify(expectedTree))
1747
+ throw new Error("durability_failed");
1748
+ };
1749
+ if (fs.existsSync(quarantine.path)) {
1750
+ const existing = fs.lstatSync(quarantine.path, { bigint: true });
1751
+ if (
1752
+ existing.isSymbolicLink() ||
1753
+ !existing.isDirectory() ||
1754
+ existing.dev !== BigInt(identity.dev) ||
1755
+ existing.ino !== BigInt(identity.ino) ||
1756
+ existing.size !== BigInt(identity.size) ||
1757
+ existing.mtimeNs !== BigInt(identity.mtimeNs)
1758
+ )
1759
+ throw new Error("durability_failed");
1760
+ assertPreparedTree(quarantine.path);
1761
+ return;
1762
+ }
1763
+ assertPreparedTree(quarantine.detachedPath);
1764
+ const result = native.exactRestore(quarantine.detachedPath, quarantine.path, {
1765
+ dev: BigInt(identity.dev),
1766
+ ino: BigInt(identity.ino),
1767
+ size: BigInt(identity.size),
1768
+ mtimeNs: BigInt(identity.mtimeNs),
1769
+ directory: true,
1770
+ });
1771
+ if (!result.ok) throw new Error("durability_failed");
1772
+ }
1773
+
1774
+ function restoreDetachedArtifactRoot(detached: DetachedArtifactRoot): void {
1775
+ const result = native.exactRestore(detached.detachedPath, detached.originalPath, {
1776
+ ...detached.identity,
1777
+ directory: true,
1778
+ });
1779
+ if (!result.ok) throw new Error("durability_failed");
1780
+ }
1781
+
1782
+ async function copyArtifacts(
1783
+ scope: ManagedScope,
1784
+ sourceTranscript: string,
1785
+ destinationTranscript: string,
1786
+ manifest: readonly ArtifactManifestEntry[],
1787
+ lock: ManagedStorageLock,
1788
+ sourceRootOverride?: string,
1789
+ ): Promise<void> {
1790
+ const root = scopeRoot(scope);
1791
+ if (manifest.length === 0) return;
1792
+ const sourceRoot = sourceRootOverride ?? sourceTranscript.slice(0, -6);
1793
+ if (!manifestMatches(sourceTranscript, manifest, sourceRoot)) throw new Error("source_changed");
1794
+ const destinationRoot = destinationTranscript.slice(0, -6);
1795
+ for (const entry of manifest) {
1796
+ lock.assertOwned();
1797
+ const source = path.join(sourceRoot, entry.path);
1798
+ const destination = path.join(destinationRoot, entry.path);
1799
+ if (entry.kind === "directory") {
1800
+ if (entry.path === "") ensureManagedDirectory(destinationRoot, root);
1801
+ else ensureManagedDirectory(destination, root);
1802
+ continue;
1803
+ }
1804
+ const snapshot = captureManagedFileNoFollow(source);
1805
+ if (
1806
+ snapshot.bytes.byteLength !== entry.size ||
1807
+ createHash("sha256").update(snapshot.bytes).digest("hex") !== entry.sha256
1808
+ )
1809
+ throw new Error("source_changed");
1810
+ try {
1811
+ await copyManagedFileNoReplace(source, destination, snapshot, root);
1812
+ } catch (error) {
1813
+ if ((error as Error).message !== "destination_conflict") throw error;
1814
+ }
1815
+ lock.assertOwned();
1816
+ const copied = captureManagedFileNoFollow(destination);
1817
+ if (
1818
+ copied.bytes.byteLength !== entry.size ||
1819
+ createHash("sha256").update(copied.bytes).digest("hex") !== entry.sha256
1820
+ )
1821
+ throw new Error("durability_failed");
1822
+ }
1823
+ if (!manifestMatches(sourceTranscript, manifest, sourceRoot) || !manifestMatches(destinationTranscript, manifest))
1824
+ throw new Error("durability_failed");
1825
+ }
1826
+
1827
+ function migrationReceipt(
1828
+ scope: ManagedScope,
1829
+ lock: ManagedStorageLock,
1830
+ state: "prepared" | "published" | "committed",
1831
+ source: ManagedCandidate,
1832
+ destination: ManagedCandidate | { path: string; sessionId: string; cwd: string },
1833
+ manifest: readonly ArtifactManifestEntry[],
1834
+ sourceArtifactQuarantine?: {
1835
+ path: string;
1836
+ detachedPath: string;
1837
+ identity: DetachedArtifactRoot["identity"];
1838
+ tree: NativeDirectoryTreeSnapshot;
1839
+ },
1840
+ ): Uint8Array {
1841
+ lock.assertOwned();
1842
+ const destinationRecord =
1843
+ "identity" in destination
1844
+ ? {
1845
+ path: destination.path,
1846
+ sessionId: destination.sessionId,
1847
+ header: { id: destination.sessionId, cwd: destination.cwd },
1848
+ identity: destination.identity,
1849
+ sha256: destination.identity.sha256,
1850
+ }
1851
+ : {
1852
+ path: destination.path,
1853
+ sessionId: destination.sessionId,
1854
+ header: { id: destination.sessionId, cwd: destination.cwd },
1855
+ };
1856
+ return new TextEncoder().encode(
1857
+ `${JSON.stringify({ schemaVersion: 2, state, policy: "copy-retain", attemptId: lock.attemptId, scope: scopeDigest(scope.platform, scope.canonicalCwd), source: { path: source.path, sessionId: source.sessionId, header: { id: source.sessionId, cwd: source.cwd }, identity: source.identity, sha256: source.identity.sha256 }, destination: destinationRecord, artifactManifest: manifest, ...(sourceArtifactQuarantine ? { sourceArtifactQuarantine } : {}) }, (_key, value: unknown) => (typeof value === "bigint" ? value.toString() : value))}\n`,
1858
+ );
1859
+ }
1860
+
1861
+ async function removeStagedReceipts(scope: ManagedScope, candidate: ManagedCandidate): Promise<void> {
1862
+ for (const state of ["prepared", "published"] as const) {
1863
+ const pathname = receiptPathFor(scope, candidate, state);
1864
+ try {
1865
+ const stat = fs.lstatSync(pathname);
1866
+ if (stat.isFile() || stat.isSymbolicLink()) await fs.promises.unlink(pathname);
1867
+ } catch (error) {
1868
+ if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
1869
+ }
1870
+ }
1871
+ }
1872
+
1873
+ function receiptPair(scope: ManagedScope, candidate: ManagedCandidate): ManagedCandidate | undefined {
1874
+ const directory = path.join(managedInternalDirectory(scope), MANAGED_RECEIPTS_DIRECTORY);
1875
+ try {
1876
+ for (const name of fs.readdirSync(directory)) {
1877
+ const pathname = path.join(directory, name);
1878
+ const value: unknown = JSON.parse(captureManagedFileNoFollow(pathname).bytes.toString("utf8"));
1879
+ if (!value || typeof value !== "object") continue;
1880
+ const record = value as { source?: { path?: unknown }; destination?: { path?: unknown } };
1881
+ const otherPath =
1882
+ record.source?.path === candidate.path
1883
+ ? record.destination?.path
1884
+ : record.destination?.path === candidate.path
1885
+ ? record.source?.path
1886
+ : undefined;
1887
+ if (typeof otherPath !== "string") continue;
1888
+ const other = inspectCandidate(otherPath, candidate.provenance === "v2" ? "legacy" : "v2");
1889
+ if (
1890
+ "code" in other ||
1891
+ !receiptMatches(
1892
+ pathname,
1893
+ candidate.provenance === "legacy" ? candidate : other,
1894
+ candidate.provenance === "v2" ? candidate : other,
1895
+ scope,
1896
+ )
1897
+ )
1898
+ continue;
1899
+ return other;
1900
+ }
1901
+ } catch {
1902
+ /* no committed pair grants no shadow authority */
1903
+ }
1904
+ return undefined;
1905
+ }
1906
+
1907
+ function validateCandidateForScope(scope: ManagedScope, candidate: ManagedCandidate): ManagedCandidate | undefined {
1908
+ const inspected = inspectCandidate(candidate.path, candidate.provenance);
1909
+ if ("code" in inspected || !sameCandidate(inspected, candidate)) return undefined;
1910
+ const identity = identityFor(inspected.cwd);
1911
+ if (!identity.ok || identity.platform !== scope.platform || identity.canonicalPath !== scope.canonicalCwd)
1912
+ return undefined;
1913
+ return inspected;
1914
+ }
1915
+
1916
+ /** Resume tombstoned cleanup under its original operation lease without restoring retired candidates. */
1917
+ export async function reconcileManagedTombstones(scope: ManagedScope): Promise<void> {
1918
+ const directory = path.join(managedInternalDirectory(scope), MANAGED_TOMBSTONES_DIRECTORY);
1919
+ for (const name of fs.readdirSync(directory)) {
1920
+ const tombstone = path.join(directory, name);
1921
+ const targets = retiredTargets(scope, tombstone);
1922
+ if (!targets) continue;
1923
+ let lock: ManagedStorageLock | undefined;
1924
+ try {
1925
+ lock = await acquireManagedLock(
1926
+ path.join(managedInternalDirectory(scope), MANAGED_LOCKS_DIRECTORY),
1927
+ path.basename(tombstone, ".json"),
1928
+ scopeRoot(scope),
1929
+ );
1930
+ const lockedTargets = retiredTargets(scope, tombstone);
1931
+ if (!lockedTargets) continue;
1932
+ for (const target of lockedTargets) {
1933
+ lock.assertOwned();
1934
+ if (cleanupCompleted(scope, tombstone, target)) continue;
1935
+ const pending = pendingCleanupReceipt(scope, tombstone, target);
1936
+ const observedPending = pending ? probePlannedCleanupDetach(target, pending) : undefined;
1937
+ try {
1938
+ fs.lstatSync(target.path);
1939
+ } catch (error) {
1940
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") {
1941
+ if (!observedPending) continue;
1942
+ if (
1943
+ cleanupArtifactsRemoved(scope, tombstone, target, observedPending.attempt) &&
1944
+ artifactRootsAbsent(scope, tombstone, target, observedPending) &&
1945
+ !fs.existsSync(observedPending.plannedTranscriptPath)
1946
+ ) {
1947
+ fsyncManagedParent(target.path);
1948
+ await publishCleanupCompleted(scope, tombstone, target, lock);
1949
+ continue;
1950
+ }
1951
+ } else throw error;
1952
+ }
1953
+ const verified = observedPending ? target : validateCandidateForScope(scope, target);
1954
+ if (!verified || !sameCandidate(verified, target)) throw new Error("source_changed");
1955
+ const discoveredDetach =
1956
+ !!observedPending &&
1957
+ (observedPending.detachedArtifactsPath !== pending?.detachedArtifactsPath ||
1958
+ observedPending.detachedTranscriptPath !== pending?.detachedTranscriptPath);
1959
+ const active =
1960
+ discoveredDetach || (observedPending && requiresFreshCleanupPlan(observedPending))
1961
+ ? nextCleanupReceipt(target, observedPending)
1962
+ : (observedPending ?? nextCleanupReceipt(target, undefined));
1963
+ if (!observedPending || discoveredDetach || requiresFreshCleanupPlan(observedPending))
1964
+ await publishCleanupPending(scope, tombstone, active, lock);
1965
+ let deletion = await new FileSessionStorage().deleteSessionVerified({
1966
+ sessionsRoot: scope.sessionsRoot,
1967
+ transcriptPath: target.path,
1968
+ sessionId: target.sessionId,
1969
+ cwd: target.cwd,
1970
+ transcriptIdentity: target.identity,
1971
+ expectedArtifactsIdentity: active.expectedArtifactsIdentity,
1972
+ expectedArtifactsTree: active.expectedArtifactsTree,
1973
+ detachedArtifactsPath:
1974
+ active.detachedArtifactsPath ??
1975
+ observedPending?.detachedArtifactsPath ??
1976
+ (fs.existsSync(active.plannedArtifactsPath) ? active.plannedArtifactsPath : undefined),
1977
+ detachedTranscriptPath:
1978
+ active.detachedTranscriptPath ??
1979
+ observedPending?.detachedTranscriptPath ??
1980
+ (pending && fs.existsSync(pending.plannedTranscriptPath)
1981
+ ? pending.plannedTranscriptPath
1982
+ : undefined) ??
1983
+ (fs.existsSync(active.plannedTranscriptPath) ? active.plannedTranscriptPath : undefined),
1984
+ plannedArtifactsPath: active.plannedArtifactsPath,
1985
+ plannedTranscriptPath: active.plannedTranscriptPath,
1986
+ ...(cleanupArtifactsRemoved(scope, tombstone, target, pending?.attempt ?? active.attempt)
1987
+ ? { artifactsRemoved: true as const }
1988
+ : {}),
1989
+ });
1990
+ if (deletion.kind === "artifacts_removed") {
1991
+ await publishCleanupArtifactsRemoved(scope, tombstone, active, lock);
1992
+ deletion = await new FileSessionStorage().deleteSessionVerified({
1993
+ sessionsRoot: scope.sessionsRoot,
1994
+ transcriptPath: target.path,
1995
+ sessionId: target.sessionId,
1996
+ cwd: target.cwd,
1997
+ transcriptIdentity: target.identity,
1998
+ plannedArtifactsPath: active.plannedArtifactsPath,
1999
+ plannedTranscriptPath: active.plannedTranscriptPath,
2000
+ artifactsRemoved: true,
2001
+ });
2002
+ }
2003
+ if (deletion.kind === "cleanup_pending") {
2004
+ const retry = nextCleanupReceipt(target, active);
2005
+ await publishCleanupPending(
2006
+ scope,
2007
+ tombstone,
2008
+ {
2009
+ ...retry,
2010
+ expectedArtifactsIdentity:
2011
+ deletion.phase === "artifacts" ? deletion.artifactsIdentity : active.expectedArtifactsIdentity,
2012
+ expectedArtifactsTree:
2013
+ deletion.phase === "artifacts" ? deletion.artifactsTree : active.expectedArtifactsTree,
2014
+ detachedArtifactsPath:
2015
+ deletion.phase === "artifacts" ? deletion.detachedArtifactsPath : active.detachedArtifactsPath,
2016
+ detachedTranscriptPath:
2017
+ deletion.phase === "transcript"
2018
+ ? deletion.detachedTranscriptPath
2019
+ : active.detachedTranscriptPath,
2020
+ },
2021
+ lock,
2022
+ );
2023
+ throw new Error("durability_failed");
2024
+ }
2025
+ fsyncManagedParent(target.path);
2026
+ await publishCleanupCompleted(scope, tombstone, target, lock);
2027
+ }
2028
+ } finally {
2029
+ if (lock) await lock.release().catch(() => undefined);
2030
+ }
2031
+ }
2032
+ }
2033
+
2034
+ /** Create the v2 binding and private write protocol directories before managed writes. */
2035
+ export async function prepareManagedSessionScopeForWrite(scope: ManagedScope): Promise<ManagedScopeResolution> {
2036
+ const prepared = await ensureManagedScope(scope);
2037
+ if (prepared.kind === "error") return prepared;
2038
+ try {
2039
+ const internal = managedInternalDirectory(scope);
2040
+ const root = scopeRoot(scope);
2041
+ ensureManagedDirectory(internal, root);
2042
+ ensureManagedDirectory(path.join(internal, MANAGED_LOCKS_DIRECTORY), root);
2043
+ ensureManagedDirectory(path.join(internal, MANAGED_RECEIPTS_DIRECTORY), root);
2044
+ ensureManagedDirectory(path.join(internal, MANAGED_TOMBSTONES_DIRECTORY), root);
2045
+ await reconcileManagedTombstones(scope);
2046
+ return { kind: "resolved", scope };
2047
+ } catch (error) {
2048
+ if (error instanceof Error && error.message === "durability_failed") return { kind: "resolved", scope };
2049
+ return {
2050
+ kind: "error",
2051
+ code: "binding_invalid",
2052
+ message: error instanceof Error ? error.message : "Managed write protocol setup failed.",
2053
+ };
2054
+ }
2055
+ }
2056
+
2057
+ /**
2058
+ * Open a validated candidate for mutation. Legacy transcripts are copied exactly once
2059
+ * into v2 and retained at their original location; no transcript data is merged.
2060
+ */
2061
+ export async function openManagedCandidateForWrite(
2062
+ scope: ManagedScope,
2063
+ candidate: ManagedCandidate,
2064
+ migrationPolicy: ManagedMigrationPolicy = "copy-retain",
2065
+ ): Promise<ManagedOpenCandidateResult> {
2066
+ if (migrationPolicy === "disabled" && candidate.provenance === "legacy")
2067
+ return {
2068
+ kind: "error",
2069
+ code: "legacy_migration_disabled",
2070
+ message: "Legacy session migration is disabled for this workspace.",
2071
+ };
2072
+ const prepared = await prepareManagedSessionScopeForWrite(scope);
2073
+ if (prepared.kind === "error")
2074
+ return {
2075
+ kind: "error",
2076
+ code: prepared.code === "binding_conflict" ? "binding_conflict" : "binding_invalid",
2077
+ message: prepared.message,
2078
+ };
2079
+ const current = validateCandidateForScope(scope, candidate);
2080
+ if (!current)
2081
+ return {
2082
+ kind: "error",
2083
+ code: "source_changed",
2084
+ message: "The managed candidate changed before it could be opened.",
2085
+ };
2086
+ if (isRetired(scope, current))
2087
+ return { kind: "error", code: "migration_retired", message: "The managed session has been retired." };
2088
+ if (current.provenance === "v2") return { kind: "opened", path: current.path, candidate: current, migrated: false };
2089
+
2090
+ const operation = stableOperationName(current);
2091
+ const internal = managedInternalDirectory(scope);
2092
+ let lock: ManagedStorageLock | undefined;
2093
+ let detachedArtifacts: DetachedArtifactRoot | undefined;
2094
+ try {
2095
+ lock = await acquireManagedLock(path.join(internal, MANAGED_LOCKS_DIRECTORY), operation, scopeRoot(scope));
2096
+ const afterLock = validateCandidateForScope(scope, current);
2097
+ if (!afterLock)
2098
+ return { kind: "error", code: "source_changed", message: "The legacy candidate changed during migration." };
2099
+ const listing = listManagedCandidates(scope);
2100
+ if (listing.kind === "error") return { kind: "error", code: "binding_invalid", message: listing.message };
2101
+ const destination = path.join(scope.directoryPath, path.basename(afterLock.path));
2102
+ const sameId = listing.owned.filter(item => item.provenance === "v2" && item.sessionId === afterLock.sessionId);
2103
+ const existing = sameId.find(item => path.resolve(item.path) === path.resolve(destination));
2104
+ if (sameId.some(item => item !== existing))
2105
+ return {
2106
+ kind: "error",
2107
+ code: "destination_conflict",
2108
+ message: "A distinct v2 transcript already owns this session id.",
2109
+ };
2110
+ restorePreparedArtifactRoot(scope, afterLock);
2111
+ const sourceSnapshot = captureManagedFileNoFollow(afterLock.path);
2112
+ let manifest: readonly ArtifactManifestEntry[] = [];
2113
+ const artifactPlan = planArtifactRootForMigration(afterLock.path, operation);
2114
+ const intendedDestination = { path: destination, sessionId: afterLock.sessionId, cwd: afterLock.cwd };
2115
+ if (existing && existing.identity.sha256 !== afterLock.identity.sha256) {
2116
+ return {
2117
+ kind: "error",
2118
+ code: "destination_conflict",
2119
+ message: "A different v2 transcript already occupies the migration destination.",
2120
+ };
2121
+ }
2122
+ if (!existing && fs.existsSync(destination)) {
2123
+ return {
2124
+ kind: "error",
2125
+ code: "destination_conflict",
2126
+ message: "The migration destination already exists without validated ownership.",
2127
+ };
2128
+ }
2129
+ const preparedReceipt = receiptPathFor(scope, afterLock, "prepared");
2130
+ try {
2131
+ lock.assertOwned();
2132
+ await publishManagedFileNoReplace(
2133
+ preparedReceipt,
2134
+ migrationReceipt(
2135
+ scope,
2136
+ lock,
2137
+ "prepared",
2138
+ afterLock,
2139
+ intendedDestination,
2140
+ manifest,
2141
+ artifactPlan
2142
+ ? {
2143
+ path: artifactPlan.originalPath,
2144
+ detachedPath: artifactPlan.detachedPath,
2145
+ identity: artifactPlan.identity,
2146
+ tree: artifactPlan.tree,
2147
+ }
2148
+ : undefined,
2149
+ ),
2150
+ lock.assertOwned,
2151
+ );
2152
+ } catch (error) {
2153
+ if ((error as Error).message !== "destination_conflict") throw error;
2154
+ }
2155
+ lock.assertOwned();
2156
+ if (!preparedReceiptMatches(preparedReceipt, scope, afterLock, intendedDestination, artifactPlan))
2157
+ throw new Error("durability_failed");
2158
+ if (artifactPlan && fs.existsSync(artifactPlan.detachedPath)) throw new Error("destination_conflict");
2159
+ detachedArtifacts = artifactPlan ? detachArtifactRootForMigration(artifactPlan) : undefined;
2160
+ manifest = detachedArtifacts ? artifactManifestFromSnapshot(detachedArtifacts.tree) : [];
2161
+ await copyArtifacts(scope, afterLock.path, destination, manifest, lock, detachedArtifacts?.detachedPath);
2162
+ if (!existing) {
2163
+ try {
2164
+ lock.assertOwned();
2165
+ await copyManagedFileNoReplace(afterLock.path, destination, sourceSnapshot, scopeRoot(scope));
2166
+ } catch (error) {
2167
+ if ((error as Error).message !== "destination_conflict") throw error;
2168
+ }
2169
+ }
2170
+ // Artifact files, directories, and the transcript must be durable before a receipt can grant shadow authority.
2171
+ if (manifest.length > 0) fsyncManagedArtifactTree(destination.slice(0, -6));
2172
+ lock.assertOwned();
2173
+ const migrated = inspectCandidate(destination, "v2");
2174
+ if (
2175
+ "code" in migrated ||
2176
+ migrated.sessionId !== afterLock.sessionId ||
2177
+ migrated.cwd !== afterLock.cwd ||
2178
+ migrated.identity.sha256 !== afterLock.identity.sha256 ||
2179
+ !manifestMatches(destination, manifest)
2180
+ )
2181
+ throw new Error("durability_failed");
2182
+ if (detachedArtifacts) {
2183
+ restoreDetachedArtifactRoot(detachedArtifacts);
2184
+ detachedArtifacts = undefined;
2185
+ }
2186
+ const latest = validateCandidateForScope(scope, afterLock);
2187
+ if (!latest || !sameCandidate(latest, afterLock) || !manifestMatches(afterLock.path, manifest))
2188
+ return {
2189
+ kind: "error",
2190
+ code: "source_changed",
2191
+ message: "The legacy candidate or its artifacts changed before migration commit.",
2192
+ };
2193
+ for (const state of ["published", "committed"] as const) {
2194
+ const receipt = receiptPathFor(scope, afterLock, state);
2195
+ try {
2196
+ lock.assertOwned();
2197
+ await publishManagedFileNoReplace(
2198
+ receipt,
2199
+ migrationReceipt(scope, lock, state, afterLock, migrated, manifest),
2200
+ lock.assertOwned,
2201
+ );
2202
+ } catch (error) {
2203
+ if ((error as Error).message !== "destination_conflict") throw error;
2204
+ }
2205
+ }
2206
+ const receipt = receiptPathFor(scope, afterLock);
2207
+ lock.assertOwned();
2208
+ if (!receiptMatches(receipt, afterLock, migrated, scope))
2209
+ return {
2210
+ kind: "error",
2211
+ code: "durability_failed",
2212
+ message: "The migration receipt does not bind the copied v2 transcript and artifacts.",
2213
+ };
2214
+ await removeStagedReceipts(scope, afterLock);
2215
+ return {
2216
+ kind: "opened",
2217
+ path: migrated.path,
2218
+ candidate: { ...migrated, migrationState: "migrated_v2" },
2219
+ migrated: true,
2220
+ };
2221
+ } catch (error) {
2222
+ try {
2223
+ if (detachedArtifacts) restoreDetachedArtifactRoot(detachedArtifacts);
2224
+ } catch {
2225
+ return {
2226
+ kind: "error",
2227
+ code: "durability_failed",
2228
+ message: "The detached legacy artifacts could not be restored without replacing a collision.",
2229
+ };
2230
+ }
2231
+ const code = expectedFailure(error);
2232
+ return { kind: "error", code, message: error instanceof Error ? error.message : "Managed migration failed." };
2233
+ } finally {
2234
+ if (lock) await lock.release().catch(() => undefined);
2235
+ }
2236
+ }
2237
+
2238
+ /** Tombstone a verified managed candidate before exact-identity deletion. */
2239
+ export async function deleteManagedSessionCandidate(
2240
+ scope: ManagedScope,
2241
+ candidate: ManagedCandidate,
2242
+ ): Promise<ManagedDeleteCandidateResult> {
2243
+ const prepared = await prepareManagedSessionScopeForWrite(scope);
2244
+ if (prepared.kind === "error")
2245
+ return {
2246
+ kind: "error",
2247
+ code: prepared.code === "binding_conflict" ? "binding_conflict" : "binding_invalid",
2248
+ message: prepared.message,
2249
+ };
2250
+ const current = validateCandidateForScope(scope, candidate);
2251
+ const paired = current ? receiptPair(scope, current) : undefined;
2252
+ const logical = paired?.provenance === "legacy" ? paired : (current ?? candidate);
2253
+ const existingTombstone = tombstonePathContaining(scope, candidate);
2254
+ const tombstone =
2255
+ existingTombstone ??
2256
+ path.join(managedInternalDirectory(scope), MANAGED_TOMBSTONES_DIRECTORY, `${stableOperationName(logical)}.json`);
2257
+ if (!current && !existingTombstone)
2258
+ return { kind: "error", code: "source_changed", message: "The managed candidate changed before deletion." };
2259
+ const operation = path.basename(tombstone, ".json");
2260
+ let lock: ManagedStorageLock | undefined;
2261
+ try {
2262
+ lock = await acquireManagedLock(
2263
+ path.join(managedInternalDirectory(scope), MANAGED_LOCKS_DIRECTORY),
2264
+ operation,
2265
+ scopeRoot(scope),
2266
+ );
2267
+ let targets = retiredTargets(scope, tombstone);
2268
+ if (!targets) {
2269
+ if (!current) throw new Error("source_changed");
2270
+ targets = [current, ...(paired ? [paired] : [])];
2271
+ lock.assertOwned();
2272
+ try {
2273
+ await publishManagedTombstone(
2274
+ tombstone,
2275
+ {
2276
+ schemaVersion: 2,
2277
+ state: "retired",
2278
+ scope: scopeDigest(scope.platform, scope.canonicalCwd),
2279
+ targets: targets.map(target => ({
2280
+ path: target.path,
2281
+ sessionId: target.sessionId,
2282
+ cwd: target.cwd,
2283
+ provenance: target.provenance,
2284
+ identity: target.identity,
2285
+ })),
2286
+ },
2287
+ lock.assertOwned,
2288
+ );
2289
+ } catch (error) {
2290
+ if ((error as Error).message !== "destination_conflict") throw error;
2291
+ }
2292
+ targets = retiredTargets(scope, tombstone);
2293
+ if (!targets) throw new Error("durability_failed");
2294
+ }
2295
+ let deletedAny = false;
2296
+ for (const target of targets) {
2297
+ lock.assertOwned();
2298
+ const pending = pendingCleanupReceipt(scope, tombstone, target);
2299
+ const observedPending = pending ? probePlannedCleanupDetach(target, pending) : undefined;
2300
+ try {
2301
+ fs.lstatSync(target.path);
2302
+ } catch (error) {
2303
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") {
2304
+ if (!observedPending) continue;
2305
+ if (
2306
+ cleanupArtifactsRemoved(scope, tombstone, target, observedPending.attempt) &&
2307
+ artifactRootsAbsent(scope, tombstone, target, observedPending) &&
2308
+ !fs.existsSync(observedPending.plannedTranscriptPath)
2309
+ ) {
2310
+ fsyncManagedParent(target.path);
2311
+ await publishCleanupCompleted(scope, tombstone, target, lock);
2312
+ continue;
2313
+ }
2314
+ } else throw error;
2315
+ }
2316
+ if (cleanupCompleted(scope, tombstone, target)) continue;
2317
+ deletedAny = true;
2318
+ const verified = observedPending ? target : validateCandidateForScope(scope, target);
2319
+ if (!verified || !sameCandidate(verified, target)) throw new Error("source_changed");
2320
+ const discoveredDetach =
2321
+ !!observedPending &&
2322
+ (observedPending.detachedArtifactsPath !== pending?.detachedArtifactsPath ||
2323
+ observedPending.detachedTranscriptPath !== pending?.detachedTranscriptPath);
2324
+ const active =
2325
+ discoveredDetach || (observedPending && requiresFreshCleanupPlan(observedPending))
2326
+ ? nextCleanupReceipt(target, observedPending)
2327
+ : (observedPending ?? nextCleanupReceipt(target, undefined));
2328
+ if (!observedPending || discoveredDetach || requiresFreshCleanupPlan(observedPending))
2329
+ await publishCleanupPending(scope, tombstone, active, lock);
2330
+ let deletion = await new FileSessionStorage().deleteSessionVerified({
2331
+ sessionsRoot: scope.sessionsRoot,
2332
+ transcriptPath: target.path,
2333
+ sessionId: target.sessionId,
2334
+ cwd: target.cwd,
2335
+ transcriptIdentity: target.identity,
2336
+ expectedArtifactsIdentity: active.expectedArtifactsIdentity,
2337
+ expectedArtifactsTree: active.expectedArtifactsTree,
2338
+ detachedArtifactsPath: active.detachedArtifactsPath ?? observedPending?.detachedArtifactsPath,
2339
+ detachedTranscriptPath:
2340
+ active.detachedTranscriptPath ??
2341
+ observedPending?.detachedTranscriptPath ??
2342
+ (pending && fs.existsSync(pending.plannedTranscriptPath) ? pending.plannedTranscriptPath : undefined),
2343
+ plannedArtifactsPath: active.plannedArtifactsPath,
2344
+ plannedTranscriptPath: active.plannedTranscriptPath,
2345
+ ...(cleanupArtifactsRemoved(scope, tombstone, target, pending?.attempt ?? active.attempt)
2346
+ ? { artifactsRemoved: true as const }
2347
+ : {}),
2348
+ });
2349
+ if (deletion.kind === "artifacts_removed") {
2350
+ await publishCleanupArtifactsRemoved(scope, tombstone, active, lock);
2351
+ deletion = await new FileSessionStorage().deleteSessionVerified({
2352
+ sessionsRoot: scope.sessionsRoot,
2353
+ transcriptPath: target.path,
2354
+ sessionId: target.sessionId,
2355
+ cwd: target.cwd,
2356
+ transcriptIdentity: target.identity,
2357
+ plannedArtifactsPath: active.plannedArtifactsPath,
2358
+ plannedTranscriptPath: active.plannedTranscriptPath,
2359
+ artifactsRemoved: true,
2360
+ });
2361
+ }
2362
+ if (deletion.kind === "cleanup_pending") {
2363
+ if (
2364
+ (deletion.phase === "artifacts" &&
2365
+ !isAuthorizedArtifactRoot(
2366
+ target,
2367
+ active.detachedArtifactsPath ?? active.plannedArtifactsPath,
2368
+ deletion.detachedArtifactsPath,
2369
+ )) ||
2370
+ (deletion.phase === "transcript" && deletion.detachedTranscriptPath !== active.plannedTranscriptPath)
2371
+ )
2372
+ throw new Error("durability_failed");
2373
+ const retry = nextCleanupReceipt(target, active);
2374
+ await publishCleanupPending(
2375
+ scope,
2376
+ tombstone,
2377
+ {
2378
+ ...retry,
2379
+ expectedArtifactsIdentity:
2380
+ deletion.phase === "artifacts" ? deletion.artifactsIdentity : active.expectedArtifactsIdentity,
2381
+ expectedArtifactsTree:
2382
+ deletion.phase === "artifacts" ? deletion.artifactsTree : active.expectedArtifactsTree,
2383
+ detachedArtifactsPath:
2384
+ deletion.phase === "artifacts" ? deletion.detachedArtifactsPath : active.detachedArtifactsPath,
2385
+ detachedTranscriptPath:
2386
+ deletion.phase === "transcript" ? deletion.detachedTranscriptPath : active.detachedTranscriptPath,
2387
+ },
2388
+ lock,
2389
+ );
2390
+ throw new Error("durability_failed");
2391
+ }
2392
+ fsyncManagedParent(target.path);
2393
+ await publishCleanupCompleted(scope, tombstone, target, lock);
2394
+ }
2395
+ return { kind: deletedAny ? "deleted" : "already_deleted", tombstonePath: tombstone };
2396
+ } catch (error) {
2397
+ const code = expectedFailure(error);
2398
+ return { kind: "error", code, message: error instanceof Error ? error.message : "Managed deletion failed." };
2399
+ } finally {
2400
+ if (lock) await lock.release().catch(() => undefined);
2401
+ }
2402
+ }