@gajae-code/coding-agent 0.13.3 → 0.14.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 (599) hide show
  1. package/CHANGELOG.md +184 -2
  2. package/README.md +2 -0
  3. package/bin/gajaessi.js +4 -0
  4. package/dist/types/async/job-manager.d.ts +55 -2
  5. package/dist/types/async/support.d.ts +14 -0
  6. package/dist/types/capability/mcp.d.ts +6 -0
  7. package/dist/types/capability/types.d.ts +6 -0
  8. package/dist/types/cli/accounts-cli.d.ts +19 -0
  9. package/dist/types/cli/args.d.ts +3 -0
  10. package/dist/types/cli/config-cli.d.ts +6 -0
  11. package/dist/types/cli/crash-cli.d.ts +10 -0
  12. package/dist/types/cli/customize-doctor.d.ts +145 -0
  13. package/dist/types/cli/daemon-cli.d.ts +3 -1
  14. package/dist/types/cli/mcp-cli.d.ts +11 -0
  15. package/dist/types/cli/notify-cli.d.ts +1 -1
  16. package/dist/types/cli/root-flags.d.ts +12 -0
  17. package/dist/types/cli/setup-cli.d.ts +3 -1
  18. package/dist/types/cli/skills-cli.d.ts +2 -1
  19. package/dist/types/cli/update-cli.d.ts +19 -1
  20. package/dist/types/cli.d.ts +6 -0
  21. package/dist/types/commands/accounts.d.ts +40 -0
  22. package/dist/types/commands/crash.d.ts +24 -0
  23. package/dist/types/commands/customize.d.ts +22 -0
  24. package/dist/types/commands/daemon.d.ts +1 -1
  25. package/dist/types/commands/launch.d.ts +6 -0
  26. package/dist/types/commands/setup.d.ts +6 -0
  27. package/dist/types/commands/skills.d.ts +6 -1
  28. package/dist/types/commands/update.d.ts +7 -0
  29. package/dist/types/config/atomic-yaml-patch-worker.d.ts +25 -0
  30. package/dist/types/config/atomic-yaml-patch.d.ts +62 -2
  31. package/dist/types/config/config-schema-version.d.ts +10 -0
  32. package/dist/types/config/file-lock.d.ts +18 -0
  33. package/dist/types/config/model-profile-activation.d.ts +3 -1
  34. package/dist/types/config/model-registry.d.ts +9 -1
  35. package/dist/types/config/models-config-schema.d.ts +2 -0
  36. package/dist/types/config/settings-schema.d.ts +70 -6
  37. package/dist/types/config/settings.d.ts +63 -0
  38. package/dist/types/config/skill-settings-defaults.d.ts +26 -0
  39. package/dist/types/config/task-delegation.d.ts +39 -0
  40. package/dist/types/config/update-channel.d.ts +10 -0
  41. package/dist/types/coordinator-mcp/server.d.ts +5 -1
  42. package/dist/types/crash/index-store.d.ts +87 -0
  43. package/dist/types/crash/nudge.d.ts +50 -0
  44. package/dist/types/crash/record-loader.d.ts +17 -0
  45. package/dist/types/crash/report.d.ts +134 -0
  46. package/dist/types/crash/sanitize.d.ts +25 -0
  47. package/dist/types/cursor.d.ts +13 -2
  48. package/dist/types/customization/import.d.ts +37 -0
  49. package/dist/types/customization/index.d.ts +4 -0
  50. package/dist/types/customization/inventory.d.ts +25 -0
  51. package/dist/types/customization/mutations.d.ts +32 -0
  52. package/dist/types/customization/types.d.ts +115 -0
  53. package/dist/types/daemon/control-types.d.ts +8 -1
  54. package/dist/types/daemon/operator-contract.d.ts +4 -4
  55. package/dist/types/discovery/claude.d.ts +39 -1
  56. package/dist/types/discovery/codex.d.ts +39 -1
  57. package/dist/types/discovery/index.d.ts +2 -0
  58. package/dist/types/discovery/mcp-compat.d.ts +30 -0
  59. package/dist/types/edit/renderer.d.ts +23 -0
  60. package/dist/types/extensibility/extensions/runner.d.ts +3 -0
  61. package/dist/types/extensibility/extensions/types.d.ts +21 -4
  62. package/dist/types/extensibility/gjc-plugins/observability.d.ts +6 -1
  63. package/dist/types/extensibility/gjc-plugins/registry.d.ts +8 -1
  64. package/dist/types/extensibility/hooks/loader.d.ts +19 -5
  65. package/dist/types/extensibility/runtime-skill-discovery.d.ts +22 -1
  66. package/dist/types/extensibility/skill-management.d.ts +107 -0
  67. package/dist/types/gjc-runtime/deep-interview-runtime.d.ts +3 -1
  68. package/dist/types/gjc-runtime/launch-worktree.d.ts +8 -0
  69. package/dist/types/gjc-runtime/linux-proc.d.ts +3 -0
  70. package/dist/types/gjc-runtime/ralplan-runtime.d.ts +10 -6
  71. package/dist/types/gjc-runtime/session-state-lock.d.ts +104 -0
  72. package/dist/types/gjc-runtime/session-state-sidecar.d.ts +120 -2
  73. package/dist/types/gjc-runtime/state-writer.d.ts +10 -1
  74. package/dist/types/gjc-runtime/ultragoal-guard.d.ts +4 -2
  75. package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +8 -6
  76. package/dist/types/gjc-runtime/workflow-settings.d.ts +109 -0
  77. package/dist/types/hooks/events.d.ts +60 -0
  78. package/dist/types/hooks/normalize.d.ts +83 -0
  79. package/dist/types/hooks/skill-state.d.ts +9 -2
  80. package/dist/types/main.d.ts +1 -1
  81. package/dist/types/modes/acp/abort-scope.d.ts +13 -0
  82. package/dist/types/modes/acp/acp-agent.d.ts +7 -4
  83. package/dist/types/modes/components/customization/customization-dashboard.d.ts +44 -0
  84. package/dist/types/modes/components/customization/import-wizard.d.ts +21 -0
  85. package/dist/types/modes/components/customization/index.d.ts +1 -0
  86. package/dist/types/modes/components/gajae-pet-widget.d.ts +8 -30
  87. package/dist/types/modes/components/irc-sidebar.d.ts +1 -0
  88. package/dist/types/modes/components/iterm-pet-transport.d.ts +122 -0
  89. package/dist/types/modes/components/oauth-selector.d.ts +10 -4
  90. package/dist/types/modes/components/pet-capability.d.ts +11 -25
  91. package/dist/types/modes/components/status-line/gh.d.ts +6 -2
  92. package/dist/types/modes/controllers/extension-ui-controller.d.ts +1 -1
  93. package/dist/types/modes/controllers/selector-controller.d.ts +7 -8
  94. package/dist/types/modes/controllers/stt-controller.d.ts +1 -1
  95. package/dist/types/modes/interactive-mode.d.ts +1 -0
  96. package/dist/types/modes/types.d.ts +1 -0
  97. package/dist/types/modes/utils/injected-user-submission.d.ts +10 -0
  98. package/dist/types/runtime-mcp/config.d.ts +9 -0
  99. package/dist/types/runtime-mcp/manager.d.ts +26 -1
  100. package/dist/types/runtime-mcp/oauth-discovery.d.ts +4 -0
  101. package/dist/types/runtime-mcp/oauth-flow.d.ts +24 -1
  102. package/dist/types/runtime-mcp/pool-key.d.ts +2 -0
  103. package/dist/types/runtime-mcp/protocol.d.ts +278 -0
  104. package/dist/types/runtime-mcp/scope-config.d.ts +29 -0
  105. package/dist/types/runtime-mcp/tool-bridge.d.ts +15 -13
  106. package/dist/types/runtime-mcp/transports/http.d.ts +9 -0
  107. package/dist/types/runtime-mcp/types.d.ts +102 -10
  108. package/dist/types/sdk/acp/adapter.d.ts +26 -5
  109. package/dist/types/sdk/broker/broker.d.ts +3 -55
  110. package/dist/types/sdk/broker/lifecycle.d.ts +18 -12
  111. package/dist/types/sdk/broker/session-index.d.ts +14 -5
  112. package/dist/types/sdk/broker/startup-failure.d.ts +16 -1
  113. package/dist/types/sdk/bus/chat-daemon-control.d.ts +51 -1
  114. package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +4 -41
  115. package/dist/types/sdk/bus/config.d.ts +11 -0
  116. package/dist/types/sdk/bus/conversation-store.d.ts +0 -1
  117. package/dist/types/sdk/bus/daemon-paths.d.ts +6 -0
  118. package/dist/types/sdk/bus/discord-conversation.d.ts +2 -0
  119. package/dist/types/sdk/bus/discord-daemon.d.ts +17 -12
  120. package/dist/types/sdk/bus/existing-thread-readiness.d.ts +4 -34
  121. package/dist/types/sdk/bus/inbound-reaction-ordering.d.ts +61 -0
  122. package/dist/types/sdk/bus/index.d.ts +85 -99
  123. package/dist/types/sdk/bus/kind-aware-reconciliation.d.ts +29 -7
  124. package/dist/types/sdk/bus/managed-daemon.d.ts +2 -32
  125. package/dist/types/sdk/bus/notification-service.d.ts +52 -0
  126. package/dist/types/sdk/bus/operator-runtime.d.ts +1 -1
  127. package/dist/types/sdk/bus/prompt-reconciliation.d.ts +16 -5
  128. package/dist/types/sdk/bus/reconciliation-store.d.ts +113 -5
  129. package/dist/types/sdk/bus/session-control.d.ts +25 -1
  130. package/dist/types/sdk/bus/slack-conversation.d.ts +4 -0
  131. package/dist/types/sdk/bus/slack-daemon.d.ts +9 -17
  132. package/dist/types/sdk/bus/slack-live-provider.d.ts +3 -1
  133. package/dist/types/sdk/bus/slack-provider.d.ts +4 -0
  134. package/dist/types/sdk/bus/slack-thread-binding.d.ts +6 -40
  135. package/dist/types/sdk/bus/telegram-adoption-intent.d.ts +30 -104
  136. package/dist/types/sdk/bus/telegram-daemon-cli.d.ts +10 -0
  137. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +262 -19
  138. package/dist/types/sdk/bus/telegram-daemon-orphan-reap.d.ts +125 -0
  139. package/dist/types/sdk/bus/telegram-daemon-owner-registry.d.ts +22 -0
  140. package/dist/types/sdk/bus/telegram-daemon.d.ts +119 -310
  141. package/dist/types/sdk/bus/telegram-reference.d.ts +1 -47
  142. package/dist/types/sdk/bus/threaded-render.d.ts +1 -0
  143. package/dist/types/sdk/bus/topic-registry.d.ts +33 -17
  144. package/dist/types/sdk/cli/rows.d.ts +2 -11
  145. package/dist/types/sdk/cli/session-cli.d.ts +15 -25
  146. package/dist/types/sdk/client/client.d.ts +97 -1
  147. package/dist/types/sdk/host/control/dispatch.d.ts +0 -7
  148. package/dist/types/sdk/host/control/index.d.ts +1 -1
  149. package/dist/types/sdk/host/control/operations.d.ts +18 -5
  150. package/dist/types/sdk/host/control/runtime-gate.d.ts +19 -0
  151. package/dist/types/sdk/host/host.d.ts +15 -1
  152. package/dist/types/sdk/host/query/handlers.d.ts +5 -0
  153. package/dist/types/sdk/host/reverse-leases.d.ts +1 -1
  154. package/dist/types/sdk/host/session-runtime.d.ts +127 -7
  155. package/dist/types/sdk/host/types.d.ts +1 -1
  156. package/dist/types/sdk/host/websocket-transport.d.ts +1 -1
  157. package/dist/types/sdk/index.d.ts +2 -1
  158. package/dist/types/sdk/lifecycle/broker-client.d.ts +8 -0
  159. package/dist/types/sdk/lifecycle/client.d.ts +59 -0
  160. package/dist/types/sdk/lifecycle/index.d.ts +3 -0
  161. package/dist/types/sdk/lifecycle/service.d.ts +232 -0
  162. package/dist/types/sdk/mcp/server.d.ts +9 -6
  163. package/dist/types/sdk/prompt-deadline-lease.d.ts +43 -0
  164. package/dist/types/sdk/prompt-deadline-manager.d.ts +28 -0
  165. package/dist/types/sdk/prompt-status.d.ts +10 -3
  166. package/dist/types/sdk/protocol/operation-registry.d.ts +5 -0
  167. package/dist/types/sdk/receipt-state.d.ts +17 -0
  168. package/dist/types/sdk/reconciliation-extensions.d.ts +2 -0
  169. package/dist/types/sdk/router/index.d.ts +1 -0
  170. package/dist/types/sdk/router/session-router.d.ts +152 -0
  171. package/dist/types/sdk/session-list.d.ts +22 -0
  172. package/dist/types/sdk/session-reconnect.d.ts +43 -1
  173. package/dist/types/sdk/session.d.ts +34 -1
  174. package/dist/types/sdk/transport/serve-cli.d.ts +1 -4
  175. package/dist/types/session/account-inventory.d.ts +86 -0
  176. package/dist/types/session/agent-session.d.ts +145 -6
  177. package/dist/types/session/agent-storage.d.ts +10 -0
  178. package/dist/types/session/coordinator-tool-label.d.ts +28 -0
  179. package/dist/types/session/internal/managed-session-storage.d.ts +23 -4
  180. package/dist/types/session/messages.d.ts +1 -1
  181. package/dist/types/session/secure-token-file.d.ts +3 -0
  182. package/dist/types/session/session-manager.d.ts +40 -1
  183. package/dist/types/session/startup-auth-config.d.ts +44 -0
  184. package/dist/types/session/terminal-abort.d.ts +378 -0
  185. package/dist/types/session/yield-queue.d.ts +7 -0
  186. package/dist/types/session-import/claude.d.ts +26 -0
  187. package/dist/types/session-import/codex.d.ts +88 -0
  188. package/dist/types/session-import/command.d.ts +35 -0
  189. package/dist/types/session-import/detect.d.ts +22 -0
  190. package/dist/types/session-import/index.d.ts +7 -0
  191. package/dist/types/session-import/provider-codex.d.ts +22 -0
  192. package/dist/types/session-import/provider-service.d.ts +38 -0
  193. package/dist/types/session-import/redact.d.ts +23 -0
  194. package/dist/types/session-import/service.d.ts +47 -0
  195. package/dist/types/session-import/types.d.ts +120 -0
  196. package/dist/types/setup/paseo/check.d.ts +16 -0
  197. package/dist/types/setup/paseo/install-saga.d.ts +115 -0
  198. package/dist/types/setup/paseo/json-publisher.d.ts +76 -0
  199. package/dist/types/setup/paseo/orchestration-preferences.d.ts +24 -0
  200. package/dist/types/setup/paseo/paseo-ownership.d.ts +87 -0
  201. package/dist/types/setup/paseo/paseo-setup.d.ts +29 -0
  202. package/dist/types/setup/paseo/provider-config.d.ts +35 -0
  203. package/dist/types/setup/paseo/remove.d.ts +14 -0
  204. package/dist/types/setup/paseo/result-types.d.ts +59 -0
  205. package/dist/types/setup/paseo/setup-deps.d.ts +73 -0
  206. package/dist/types/setup/paseo/skills-bridge.d.ts +44 -0
  207. package/dist/types/skill-state/active-state.d.ts +5 -1
  208. package/dist/types/slash-commands/acp-builtins.d.ts +5 -1
  209. package/dist/types/slash-commands/builtin-registry.d.ts +2 -0
  210. package/dist/types/slash-commands/helpers/credential-switch.d.ts +12 -0
  211. package/dist/types/slash-commands/helpers/usage-report.d.ts +5 -6
  212. package/dist/types/slash-commands/types.d.ts +7 -1
  213. package/dist/types/task/executor.d.ts +10 -0
  214. package/dist/types/task/index.d.ts +3 -1
  215. package/dist/types/tools/ask-answer-registry.d.ts +6 -3
  216. package/dist/types/tools/bash-sleep-advisory.d.ts +14 -0
  217. package/dist/types/tools/bash.d.ts +2 -6
  218. package/dist/types/tools/browser/attach.d.ts +11 -0
  219. package/dist/types/tools/browser/launch.d.ts +20 -0
  220. package/dist/types/tools/browser/profile-discovery.d.ts +6 -0
  221. package/dist/types/tools/browser/render.d.ts +1 -0
  222. package/dist/types/tools/browser.d.ts +3 -1
  223. package/dist/types/tools/image-gen.d.ts +9 -2
  224. package/dist/types/tools/index.d.ts +8 -0
  225. package/dist/types/tools/monitor.d.ts +1 -1
  226. package/dist/types/tools/skill-discovery.d.ts +8 -1
  227. package/dist/types/tools/subagent.d.ts +2 -0
  228. package/dist/types/tools/ultragoal-ask-guard.d.ts +2 -2
  229. package/dist/types/utils/herdr-pane.d.ts +76 -0
  230. package/package.json +19 -9
  231. package/scripts/build-binary.ts +2 -1
  232. package/scripts/build-sdk-package-smoke.ts +2 -13
  233. package/scripts/capture-sticky-viewport-showcase.ts +0 -1
  234. package/scripts/compile-args.ts +2 -0
  235. package/scripts/generate-sdk-adapter-parity-manifest.ts +31 -16
  236. package/scripts/generate-sdk-operation-inventory.ts +28 -0
  237. package/scripts/generate-telegram-baseline-manifest.ts +1 -0
  238. package/scripts/generate-tool-catalog.ts +6 -4
  239. package/scripts/verify-gjc-sdk-canonicalization.ts +5 -39
  240. package/src/async/job-manager.ts +352 -17
  241. package/src/async/support.ts +25 -0
  242. package/src/autoresearch/dashboard.ts +28 -13
  243. package/src/capability/index.ts +3 -1
  244. package/src/capability/mcp.ts +6 -0
  245. package/src/capability/types.ts +6 -0
  246. package/src/cli/accounts-cli.ts +395 -0
  247. package/src/cli/args.ts +23 -0
  248. package/src/cli/auth-broker-cli.ts +136 -66
  249. package/src/cli/auth-gateway-cli.ts +94 -70
  250. package/src/cli/config-cli.ts +27 -2
  251. package/src/cli/crash-cli.ts +78 -0
  252. package/src/cli/customize-doctor.ts +1605 -0
  253. package/src/cli/daemon-cli.ts +12 -3
  254. package/src/cli/fast-help.ts +1 -0
  255. package/src/cli/mcp-cli.ts +128 -60
  256. package/src/cli/notify-cli.ts +8 -14
  257. package/src/cli/root-flags.ts +8 -0
  258. package/src/cli/setup-cli.ts +145 -0
  259. package/src/cli/skills-cli.ts +38 -2
  260. package/src/cli/update-cli.ts +167 -12
  261. package/src/cli.ts +4 -0
  262. package/src/commands/accounts.ts +71 -0
  263. package/src/commands/crash.ts +35 -0
  264. package/src/commands/customize.ts +84 -0
  265. package/src/commands/daemon.ts +2 -2
  266. package/src/commands/deep-interview.ts +2 -0
  267. package/src/commands/launch.ts +1 -0
  268. package/src/commands/mcp.ts +12 -7
  269. package/src/commands/ralplan.ts +2 -0
  270. package/src/commands/sdk.ts +65 -32
  271. package/src/commands/setup.ts +5 -0
  272. package/src/commands/skills.ts +14 -4
  273. package/src/commands/ultragoal.ts +10 -1
  274. package/src/commands/update.ts +26 -15
  275. package/src/config/atomic-yaml-patch-worker.ts +57 -0
  276. package/src/config/atomic-yaml-patch.ts +769 -29
  277. package/src/config/config-schema-version.ts +10 -0
  278. package/src/config/file-lock.ts +70 -1
  279. package/src/config/mcp-schema.json +52 -14
  280. package/src/config/model-profile-activation.ts +20 -1
  281. package/src/config/model-profiles.ts +29 -19
  282. package/src/config/model-registry.ts +132 -21
  283. package/src/config/models-config-schema.ts +1 -1
  284. package/src/config/settings-schema.ts +76 -6
  285. package/src/config/settings.ts +4038 -199
  286. package/src/config/skill-settings-defaults.ts +41 -3
  287. package/src/config/task-delegation.ts +87 -0
  288. package/src/config/update-channel.ts +23 -0
  289. package/src/coordinator-mcp/server.ts +377 -308
  290. package/src/crash/index-store.ts +723 -0
  291. package/src/crash/nudge.ts +89 -0
  292. package/src/crash/record-loader.ts +149 -0
  293. package/src/crash/report.ts +551 -0
  294. package/src/crash/sanitize.ts +129 -0
  295. package/src/cursor.ts +36 -10
  296. package/src/customization/import.ts +946 -0
  297. package/src/customization/index.ts +4 -0
  298. package/src/customization/inventory.ts +335 -0
  299. package/src/customization/mutations.ts +141 -0
  300. package/src/customization/types.ts +223 -0
  301. package/src/daemon/control-types.ts +8 -1
  302. package/src/daemon/operator-contract.ts +6 -6
  303. package/src/defaults/gjc/skills/deep-interview/SKILL.md +11 -22
  304. package/src/defaults/gjc/skills/ralplan/SKILL.md +36 -23
  305. package/src/defaults/gjc/skills/ultragoal/SKILL.md +16 -0
  306. package/src/discovery/claude-hooks.ts +38 -0
  307. package/src/discovery/claude.ts +142 -209
  308. package/src/discovery/codex-hooks.ts +38 -0
  309. package/src/discovery/codex.ts +132 -198
  310. package/src/discovery/helpers.ts +8 -1
  311. package/src/discovery/index.ts +2 -0
  312. package/src/discovery/mcp-compat.ts +234 -0
  313. package/src/discovery/mcp-json.ts +6 -0
  314. package/src/edit/renderer.ts +40 -0
  315. package/src/edit/streaming.ts +4 -2
  316. package/src/exec/bash-executor.ts +24 -20
  317. package/src/export/html/index.ts +51 -2
  318. package/src/extensibility/extensions/loader.ts +9 -1
  319. package/src/extensibility/extensions/runner.ts +17 -4
  320. package/src/extensibility/extensions/types.ts +31 -6
  321. package/src/extensibility/gjc-plugins/constrained-hooks.ts +33 -0
  322. package/src/extensibility/gjc-plugins/installer.ts +9 -5
  323. package/src/extensibility/gjc-plugins/observability.ts +8 -2
  324. package/src/extensibility/gjc-plugins/registry.ts +13 -2
  325. package/src/extensibility/gjc-plugins/runtime-adapters.ts +3 -1
  326. package/src/extensibility/gjc-plugins/schema.ts +222 -39
  327. package/src/extensibility/hooks/loader.ts +154 -10
  328. package/src/extensibility/runtime-skill-discovery.ts +257 -60
  329. package/src/extensibility/skill-management.ts +368 -0
  330. package/src/extensibility/skills.ts +52 -16
  331. package/src/gjc-runtime/deep-interview-runtime.ts +45 -61
  332. package/src/gjc-runtime/launch-worktree.ts +56 -2
  333. package/src/gjc-runtime/linux-proc.ts +7 -1
  334. package/src/gjc-runtime/ralplan-runtime.ts +100 -164
  335. package/src/gjc-runtime/session-state-lock.ts +992 -0
  336. package/src/gjc-runtime/session-state-sidecar.ts +644 -142
  337. package/src/gjc-runtime/state-writer.ts +39 -14
  338. package/src/gjc-runtime/tmux-owner-isolation.ts +5 -4
  339. package/src/gjc-runtime/ultragoal-guard.ts +11 -4
  340. package/src/gjc-runtime/ultragoal-runtime.ts +44 -41
  341. package/src/gjc-runtime/workflow-settings.ts +596 -0
  342. package/src/goals/tools/goal-tool.ts +6 -1
  343. package/src/hooks/events.ts +291 -0
  344. package/src/hooks/native-skill-hook.ts +4 -0
  345. package/src/hooks/normalize.ts +369 -0
  346. package/src/hooks/skill-state.ts +165 -46
  347. package/src/internal-urls/docs-index.generated.ts +40 -32
  348. package/src/main.ts +32 -5
  349. package/src/migrate/mcp-mapper.ts +25 -2
  350. package/src/modes/acp/abort-scope.ts +29 -0
  351. package/src/modes/acp/acp-agent.ts +423 -98
  352. package/src/modes/components/assistant-message.ts +6 -1
  353. package/src/modes/components/customization/customization-dashboard.ts +443 -0
  354. package/src/modes/components/customization/import-wizard.ts +372 -0
  355. package/src/modes/components/customization/index.ts +1 -0
  356. package/src/modes/components/gajae-pet-widget.ts +539 -213
  357. package/src/modes/components/irc-sidebar.ts +11 -0
  358. package/src/modes/components/iterm-pet-transport.ts +585 -0
  359. package/src/modes/components/oauth-selector.ts +277 -86
  360. package/src/modes/components/pet-capability.ts +39 -40
  361. package/src/modes/components/settings-selector.ts +9 -0
  362. package/src/modes/components/status-line/gh.ts +45 -1
  363. package/src/modes/components/status-line/segments.ts +16 -1
  364. package/src/modes/components/tool-status-header.ts +13 -3
  365. package/src/modes/controllers/command-controller.ts +20 -8
  366. package/src/modes/controllers/extension-ui-controller.ts +56 -257
  367. package/src/modes/controllers/input-controller.ts +10 -0
  368. package/src/modes/controllers/runtime-mcp-command-controller.ts +16 -3
  369. package/src/modes/controllers/selector-controller.ts +177 -72
  370. package/src/modes/controllers/stt-controller.ts +3 -3
  371. package/src/modes/interactive-mode.ts +88 -16
  372. package/src/modes/print-mode.ts +35 -6
  373. package/src/modes/runtime-init.ts +21 -68
  374. package/src/modes/types.ts +1 -0
  375. package/src/modes/utils/injected-user-submission.ts +25 -0
  376. package/src/modes/utils/terminal-bell.ts +15 -1
  377. package/src/prompts/agent-fragments/ralplan-persistence.md +1 -1
  378. package/src/prompts/agent-fragments/restricted-bash.md +1 -1
  379. package/src/prompts/agents/critic.md +1 -1
  380. package/src/prompts/system/rlm-research.md +1 -1
  381. package/src/prompts/system/system-prompt.md +0 -2
  382. package/src/prompts/tools/bash.md +7 -1
  383. package/src/prompts/tools/browser.md +1 -1
  384. package/src/prompts/tools/cron.md +6 -6
  385. package/src/prompts/tools/read.md +0 -2
  386. package/src/prompts/tools/skill-discovery.md +4 -2
  387. package/src/runtime-mcp/client.ts +427 -23
  388. package/src/runtime-mcp/config.ts +37 -5
  389. package/src/runtime-mcp/manager-pool.test.ts +56 -0
  390. package/src/runtime-mcp/manager.ts +52 -2
  391. package/src/runtime-mcp/oauth-discovery.ts +13 -0
  392. package/src/runtime-mcp/oauth-flow.ts +46 -1
  393. package/src/runtime-mcp/pool-key.ts +5 -1
  394. package/src/runtime-mcp/pool.test.ts +9 -0
  395. package/src/runtime-mcp/protocol.test.ts +353 -0
  396. package/src/runtime-mcp/protocol.ts +624 -0
  397. package/src/runtime-mcp/scope-config.ts +78 -0
  398. package/src/runtime-mcp/tool-bridge.ts +44 -10
  399. package/src/runtime-mcp/transports/http.ts +84 -13
  400. package/src/runtime-mcp/types.ts +123 -12
  401. package/src/sdk/acp/adapter.ts +328 -97
  402. package/src/sdk/broker/broker.ts +160 -741
  403. package/src/sdk/broker/ensure.ts +9 -1
  404. package/src/sdk/broker/lifecycle.ts +510 -116
  405. package/src/sdk/broker/operation-receipt-ledger.ts +11 -2
  406. package/src/sdk/broker/process-incarnation.ts +19 -0
  407. package/src/sdk/broker/session-index.ts +516 -117
  408. package/src/sdk/broker/startup-failure.ts +28 -5
  409. package/src/sdk/broker/transport.ts +1 -13
  410. package/src/sdk/bus/chat-daemon-cli.ts +4 -2
  411. package/src/sdk/bus/chat-daemon-control.ts +67 -6
  412. package/src/sdk/bus/chat-daemon-runtime.ts +183 -859
  413. package/src/sdk/bus/config.ts +13 -0
  414. package/src/sdk/bus/conversation-store.ts +59 -171
  415. package/src/sdk/bus/daemon-paths.ts +20 -0
  416. package/src/sdk/bus/discord-conversation.ts +2 -0
  417. package/src/sdk/bus/discord-daemon.ts +524 -126
  418. package/src/sdk/bus/discord-live-provider.ts +206 -79
  419. package/src/sdk/bus/existing-thread-readiness.ts +4 -97
  420. package/src/sdk/bus/inbound-reaction-ordering.ts +122 -0
  421. package/src/sdk/bus/index.ts +2480 -456
  422. package/src/sdk/bus/kind-aware-reconciliation.ts +204 -34
  423. package/src/sdk/bus/lifecycle-commands.ts +2 -2
  424. package/src/sdk/bus/managed-daemon.ts +2 -145
  425. package/src/sdk/bus/notification-service.ts +196 -0
  426. package/src/sdk/bus/operator-runtime.ts +1 -1
  427. package/src/sdk/bus/prompt-reconciliation.ts +24 -15
  428. package/src/sdk/bus/reconciliation-store.ts +553 -24
  429. package/src/sdk/bus/session-control.ts +49 -3
  430. package/src/sdk/bus/slack-conversation.ts +4 -0
  431. package/src/sdk/bus/slack-daemon.ts +733 -134
  432. package/src/sdk/bus/slack-live-provider.ts +65 -15
  433. package/src/sdk/bus/slack-provider.ts +4 -0
  434. package/src/sdk/bus/slack-thread-binding.ts +9 -104
  435. package/src/sdk/bus/telegram-adoption-intent.ts +299 -209
  436. package/src/sdk/bus/telegram-daemon-cli.ts +194 -7
  437. package/src/sdk/bus/telegram-daemon-contract.ts +265 -19
  438. package/src/sdk/bus/telegram-daemon-control.ts +3 -13
  439. package/src/sdk/bus/telegram-daemon-orphan-reap.ts +498 -0
  440. package/src/sdk/bus/telegram-daemon-owner-registry.ts +176 -0
  441. package/src/sdk/bus/telegram-daemon.ts +2552 -2280
  442. package/src/sdk/bus/telegram-reference.ts +1 -226
  443. package/src/sdk/bus/telegram-setup.ts +2 -2
  444. package/src/sdk/bus/threaded-render.ts +1 -0
  445. package/src/sdk/bus/topic-registry.ts +279 -146
  446. package/src/sdk/cli/rows.ts +2 -35
  447. package/src/sdk/cli/session-cli.ts +776 -700
  448. package/src/sdk/client/client.ts +892 -1
  449. package/src/sdk/host/control/dispatch.ts +93 -58
  450. package/src/sdk/host/control/index.ts +1 -1
  451. package/src/sdk/host/control/operations.ts +18 -10
  452. package/src/sdk/host/control/runtime-gate.ts +40 -0
  453. package/src/sdk/host/host.ts +63 -12
  454. package/src/sdk/host/query/handlers.ts +66 -7
  455. package/src/sdk/host/reverse-leases.ts +2 -2
  456. package/src/sdk/host/sdk-surface-parity.test.ts +1 -1
  457. package/src/sdk/host/session-runtime.test.ts +2787 -34
  458. package/src/sdk/host/session-runtime.ts +1489 -101
  459. package/src/sdk/host/surface-policy.ts +12 -8
  460. package/src/sdk/host/types.ts +1 -1
  461. package/src/sdk/host/websocket-transport.lifecycle.test.ts +31 -59
  462. package/src/sdk/host/websocket-transport.ts +85 -50
  463. package/src/sdk/index.ts +2 -1
  464. package/src/sdk/lifecycle/broker-client.ts +53 -0
  465. package/src/sdk/lifecycle/client.ts +234 -0
  466. package/src/sdk/lifecycle/index.ts +3 -0
  467. package/src/sdk/{bus/recent-activity.ts → lifecycle/recent-sessions.ts} +5 -2
  468. package/src/sdk/lifecycle/service.ts +720 -0
  469. package/src/sdk/mcp/server.ts +226 -188
  470. package/src/sdk/prompt-deadline-lease.ts +55 -0
  471. package/src/sdk/prompt-deadline-manager.ts +148 -0
  472. package/src/sdk/prompt-status.ts +11 -3
  473. package/src/sdk/protocol/operation-inventory.generated.json +272 -129
  474. package/src/sdk/protocol/operation-registry.ts +71 -8
  475. package/src/sdk/receipt-state.ts +43 -0
  476. package/src/sdk/reconciliation-extensions.ts +14 -0
  477. package/src/sdk/router/index.ts +1 -0
  478. package/src/sdk/router/session-router.ts +1658 -0
  479. package/src/sdk/session-list.ts +93 -0
  480. package/src/sdk/session-reconnect.ts +45 -1
  481. package/src/sdk/session.ts +716 -120
  482. package/src/sdk/transport/serve-cli.ts +18 -34
  483. package/src/session/account-inventory.ts +603 -0
  484. package/src/session/agent-session.ts +2857 -582
  485. package/src/session/agent-storage.ts +35 -0
  486. package/src/session/blob-store.ts +32 -1
  487. package/src/session/coordinator-tool-label.ts +40 -0
  488. package/src/session/internal/managed-session-scope.ts +4 -0
  489. package/src/session/internal/managed-session-storage.ts +173 -12
  490. package/src/session/messages.ts +1 -1
  491. package/src/session/secure-token-file.ts +80 -0
  492. package/src/session/session-manager.ts +730 -58
  493. package/src/session/session-storage.ts +25 -16
  494. package/src/session/startup-auth-config.ts +297 -0
  495. package/src/session/terminal-abort.ts +1253 -0
  496. package/src/session/yield-queue.ts +57 -15
  497. package/src/session-import/claude.ts +334 -0
  498. package/src/session-import/codex.ts +1033 -0
  499. package/src/session-import/command.ts +77 -0
  500. package/src/session-import/detect.ts +133 -0
  501. package/src/session-import/index.ts +7 -0
  502. package/src/session-import/provider-codex.ts +327 -0
  503. package/src/session-import/provider-service.ts +457 -0
  504. package/src/session-import/redact.ts +128 -0
  505. package/src/session-import/service.ts +1264 -0
  506. package/src/session-import/types.ts +148 -0
  507. package/src/setup/paseo/check.ts +213 -0
  508. package/src/setup/paseo/install-saga.ts +293 -0
  509. package/src/setup/paseo/json-publisher.ts +263 -0
  510. package/src/setup/paseo/orchestration-preferences.ts +86 -0
  511. package/src/setup/paseo/paseo-ownership.ts +224 -0
  512. package/src/setup/paseo/paseo-setup.ts +253 -0
  513. package/src/setup/paseo/provider-config.ts +139 -0
  514. package/src/setup/paseo/remove.ts +183 -0
  515. package/src/setup/paseo/result-types.ts +79 -0
  516. package/src/setup/paseo/setup-deps.ts +175 -0
  517. package/src/setup/paseo/skills-bridge.ts +260 -0
  518. package/src/skill-state/active-state.ts +21 -11
  519. package/src/slash-commands/acp-builtins.ts +9 -1
  520. package/src/slash-commands/builtin-registry.ts +98 -16
  521. package/src/slash-commands/helpers/credential-switch.ts +143 -0
  522. package/src/slash-commands/helpers/mcp.ts +9 -3
  523. package/src/slash-commands/helpers/usage-report.ts +61 -56
  524. package/src/slash-commands/types.ts +7 -2
  525. package/src/task/executor.ts +30 -11
  526. package/src/task/index.ts +66 -7
  527. package/src/task/render.ts +23 -9
  528. package/src/tools/ask-answer-registry.ts +23 -7
  529. package/src/tools/ask.ts +8 -4
  530. package/src/tools/bash-sleep-advisory.ts +115 -0
  531. package/src/tools/bash.ts +98 -18
  532. package/src/tools/browser/attach.ts +71 -3
  533. package/src/tools/browser/launch.ts +86 -13
  534. package/src/tools/browser/profile-discovery.ts +57 -7
  535. package/src/tools/browser/render.ts +8 -1
  536. package/src/tools/browser.ts +130 -21
  537. package/src/tools/computer.enforcement.test.ts +1 -1
  538. package/src/tools/computer.ts +3 -2
  539. package/src/tools/cron.ts +12 -1
  540. package/src/tools/image-gen.ts +27 -16
  541. package/src/tools/index.ts +8 -0
  542. package/src/tools/job.ts +33 -6
  543. package/src/tools/monitor.ts +41 -2
  544. package/src/tools/skill-discovery.ts +21 -29
  545. package/src/tools/subagent.ts +142 -24
  546. package/src/tools/tool-catalog.generated.ts +6 -6
  547. package/src/tools/ultragoal-ask-guard.ts +10 -3
  548. package/src/utils/herdr-pane.ts +345 -0
  549. package/src/utils/title-generator.ts +2 -0
  550. package/src/web/scrapers/index.ts +6 -4
  551. package/dist/types/cli/malloc-env-guard.test.d.ts +0 -1
  552. package/dist/types/defaults/gjc-defaults.test.d.ts +0 -1
  553. package/dist/types/memory-backend/lazy-loading.test.d.ts +0 -1
  554. package/dist/types/runtime/boot-ordering.test.d.ts +0 -1
  555. package/dist/types/runtime/lazy-service.test.d.ts +0 -1
  556. package/dist/types/runtime/network-prewarm-service.test.d.ts +0 -1
  557. package/dist/types/runtime/workspace-tree-service.test.d.ts +0 -1
  558. package/dist/types/runtime-mcp/config.test.d.ts +0 -1
  559. package/dist/types/runtime-mcp/http.test.d.ts +0 -1
  560. package/dist/types/runtime-mcp/manager-pool.test.d.ts +0 -1
  561. package/dist/types/runtime-mcp/pool-key.test.d.ts +0 -1
  562. package/dist/types/runtime-mcp/pool.test.d.ts +0 -1
  563. package/dist/types/sdk/bus/lifecycle-control-runtime.d.ts +0 -117
  564. package/dist/types/sdk/bus/lifecycle-orchestrator.d.ts +0 -141
  565. package/dist/types/sdk/bus/telegram-cli.d.ts +0 -31
  566. package/dist/types/sdk/elevation/allowlist.d.ts +0 -20
  567. package/dist/types/sdk/elevation/audit.d.ts +0 -93
  568. package/dist/types/sdk/elevation/capability.d.ts +0 -3
  569. package/dist/types/sdk/elevation/digest.d.ts +0 -72
  570. package/dist/types/sdk/elevation/dispatch-receipt.d.ts +0 -85
  571. package/dist/types/sdk/elevation/grant-ledger.d.ts +0 -163
  572. package/dist/types/sdk/elevation/owner.d.ts +0 -48
  573. package/dist/types/sdk/host/import-graph.test.d.ts +0 -1
  574. package/dist/types/sdk/host/sdk-surface-parity.test.d.ts +0 -1
  575. package/dist/types/sdk/host/session-runtime.test.d.ts +0 -1
  576. package/dist/types/sdk/host/websocket-transport.lifecycle.test.d.ts +0 -1
  577. package/dist/types/session/auth-broker-config.d.ts +0 -13
  578. package/dist/types/session/heap-eviction-artifacts.test.d.ts +0 -1
  579. package/dist/types/skills/skills.test.d.ts +0 -1
  580. package/dist/types/slash-commands/notify-command.test.d.ts +0 -1
  581. package/dist/types/task/token-log.test.d.ts +0 -1
  582. package/dist/types/tools/computer.enforcement.test.d.ts +0 -1
  583. package/dist/types/tools/descriptors.test.d.ts +0 -1
  584. package/scripts/g005-daemon-smoke.ts +0 -180
  585. package/scripts/g011-daemon-path-smoke.ts +0 -153
  586. package/src/sdk/bus/lifecycle-control-runtime.ts +0 -1733
  587. package/src/sdk/bus/lifecycle-orchestrator.ts +0 -489
  588. package/src/sdk/bus/telegram-cli.ts +0 -212
  589. package/src/sdk/elevation/allowlist.ts +0 -54
  590. package/src/sdk/elevation/audit.ts +0 -208
  591. package/src/sdk/elevation/capability.ts +0 -41
  592. package/src/sdk/elevation/digest.ts +0 -129
  593. package/src/sdk/elevation/dispatch-receipt.ts +0 -184
  594. package/src/sdk/elevation/grant-ledger.ts +0 -1142
  595. package/src/sdk/elevation/owner.ts +0 -109
  596. package/src/session/auth-broker-config.ts +0 -109
  597. /package/dist/types/{ai-core-import-gate.test.d.ts → discovery/claude-hooks.d.ts} +0 -0
  598. /package/dist/types/{cli/fixture-report.test.d.ts → discovery/codex-hooks.d.ts} +0 -0
  599. /package/dist/types/sdk/{bus/recent-activity.d.ts → lifecycle/recent-sessions.d.ts} +0 -0
@@ -261,11 +261,46 @@ FROM model_usage_legacy
261
261
  key: row.key,
262
262
  error: String(error),
263
263
  });
264
+ // A malformed row must fail the whole read: the migration drains
265
+ // rows only after a fully successful read, and deleting a row that
266
+ // never decoded would permanently lose its value. Throwing keeps
267
+ // every row (including the malformed one) in place for repair.
268
+ throw error;
264
269
  }
265
270
  }
266
271
  return settings as Settings;
267
272
  }
268
273
 
274
+ /**
275
+ * @deprecated Settings are now stored in config.yml, not agent.db.
276
+ * Clears the legacy settings rows after they have been drained into
277
+ * config.yml so a later load never re-imports them (the database has no
278
+ * other one-time guard). Retries transient SQLITE_BUSY contention with
279
+ * exponential backoff and THROWS on persistent failure: the migration must
280
+ * not treat a failed drain as success while stale rows stay eligible for
281
+ * re-import on a later load.
282
+ */
283
+ async clearSettings(): Promise<void> {
284
+ const maxRetries = 3;
285
+ const baseDelayMs = 100;
286
+ let lastError: Error | undefined;
287
+ for (let attempt = 0; attempt < maxRetries; attempt++) {
288
+ try {
289
+ this.#db.run("DELETE FROM settings");
290
+ return;
291
+ } catch (error) {
292
+ const isSqliteBusy =
293
+ error && typeof error === "object" && (error as { code?: string }).code === "SQLITE_BUSY";
294
+ if (!isSqliteBusy) {
295
+ throw error;
296
+ }
297
+ lastError = error as Error;
298
+ await Bun.sleep(baseDelayMs * 2 ** attempt);
299
+ }
300
+ }
301
+ throw lastError ?? new Error("Failed to clear legacy settings after retries");
302
+ }
303
+
269
304
  /**
270
305
  * @deprecated Settings are now stored in config.yml, not agent.db.
271
306
  * This method is kept for backward compatibility but does nothing.
@@ -388,10 +388,41 @@ function removeResidentCacheTreeNoFollow(pathname: string): void {
388
388
  fs.unlinkSync(pathname);
389
389
  }
390
390
 
391
+ /**
392
+ * Disposal-time parent authority is an *identity* contract: the retained descriptor
393
+ * must still name the same owned directory, so a substituted parent (rename, symlink,
394
+ * or a foreign directory moved into place) fails closed and keeps disposal retryable.
395
+ *
396
+ * It deliberately does not re-assert the parent's owner-only mode. Adoption and every
397
+ * read/write path already refuse an untrusted (group/other-accessible) cache root, and
398
+ * the instance directory itself stays fully verified here — owner, mode, `O_NOFOLLOW`
399
+ * open, and post-rename `dev`/`ino` identity. Requiring owner-only mode on the parent
400
+ * *at disposal time* would instead turn a widened root into permanent retention of the
401
+ * predecessor's resident session bytes, which is the leak disposal exists to prevent.
402
+ */
403
+ function assertResidentCacheDisposalParentIdentity(pathname: string, descriptor: number, uid: number): void {
404
+ let current: fs.Stats;
405
+ try {
406
+ current = fs.lstatSync(pathname);
407
+ } catch (error) {
408
+ throw residentCacheTrustError("directory_unverifiable", pathname, error);
409
+ }
410
+ if (!current.isDirectory() || current.isSymbolicLink() || current.uid !== uid)
411
+ throw new ResidentCacheTrustError("directory_untrusted", pathname);
412
+ let opened: fs.Stats;
413
+ try {
414
+ opened = fs.fstatSync(descriptor);
415
+ } catch (error) {
416
+ throw residentCacheTrustError("directory_descriptor_unverifiable", pathname, error);
417
+ }
418
+ if (!opened.isDirectory() || opened.uid !== uid || !hasSameFilesystemIdentity(current, opened))
419
+ throw new ResidentCacheTrustError("directory_identity_changed", pathname);
420
+ }
421
+
391
422
  function assertResidentCacheDisposalParent(instanceDir: string, parentDescriptor: number): void {
392
423
  const parentDir = path.dirname(instanceDir);
393
424
  try {
394
- assertResidentCacheDirectoryPathMatchesDescriptor(parentDir, parentDescriptor, residentCacheOwnerUid(parentDir));
425
+ assertResidentCacheDisposalParentIdentity(parentDir, parentDescriptor, residentCacheOwnerUid(parentDir));
395
426
  } catch (error) {
396
427
  throw residentCacheTrustError("parent_authority_changed", instanceDir, error);
397
428
  }
@@ -0,0 +1,40 @@
1
+ import { UNPROVEN_TOOL_LABEL } from "../gjc-runtime/session-state-sidecar";
2
+ import { TOOL_DESCRIPTORS } from "../tools/descriptors";
3
+
4
+ /**
5
+ * Proves whether the tool OBJECT that actually ran is one this session constructed from a
6
+ * built-in descriptor, before any extension, MCP, or dynamically registered tool could
7
+ * override that registry name.
8
+ */
9
+ export type BuiltinToolProvenance = (tool: object) => boolean;
10
+
11
+ /**
12
+ * Canonical public label for the tool object a call was ACTUALLY dispatched to.
13
+ *
14
+ * The input is the object the producer bound to the event, never a name resolved here. A
15
+ * wire name is model text and the tool list behind it is mutable: a `setTools`, MCP
16
+ * reload, or tool refresh between dispatch and this call would otherwise publish whatever
17
+ * holds the name by now instead of what ran.
18
+ *
19
+ * Two independent facts must hold before a canonical label is published:
20
+ *
21
+ * 1. the producer bound a dispatched tool object at all (an unknown name the loop
22
+ * rejected, and a call aborted before dispatch, bind nothing), AND
23
+ * 2. that object carries built-in provenance and its canonical name is one of the closed
24
+ * built-in descriptors.
25
+ *
26
+ * The object check is what makes the label trustworthy. A registry name is not
27
+ * provenance: an SDK extension, MCP, or custom tool may register itself as `bash` or
28
+ * `edit`, or claim a built-in `customWireName`, and would otherwise be published under
29
+ * the built-in's label. Without proven provenance — including for a direct AgentSession
30
+ * construction that supplies none — the answer is `custom`.
31
+ */
32
+ export function canonicalCoordinatorToolLabel(
33
+ dispatchedTool: object | undefined,
34
+ isBuiltinToolObject: BuiltinToolProvenance,
35
+ ): string {
36
+ if (!dispatchedTool || !isBuiltinToolObject(dispatchedTool)) return UNPROVEN_TOOL_LABEL;
37
+ const name = (dispatchedTool as { name?: unknown }).name;
38
+ if (typeof name !== "string" || !Object.hasOwn(TOOL_DESCRIPTORS, name)) return UNPROVEN_TOOL_LABEL;
39
+ return name;
40
+ }
@@ -1090,6 +1090,10 @@ export function prepareManagedSessionScopeForWriteSync(
1090
1090
  policy,
1091
1091
  );
1092
1092
  stage = "store";
1093
+ // This must precede the first managed-store mutation: binding publication
1094
+ // reconciles receipts with the normal 50k fail-closed bound, while an older
1095
+ // macOS scope can contain only proven, terminal zero-byte remnants above it.
1096
+ reapScrubbedProtocolRemnantsSync(scope.directoryPath);
1093
1097
  let store: ManagedSessionDescendantStore;
1094
1098
  const openManagedStore = (): ManagedSessionDescendantStore => {
1095
1099
  const next = buildStore();
@@ -43,7 +43,7 @@ function nativeSessionStorage(): NativeManagedSessionStorage {
43
43
 
44
44
  export const MANAGED_ARTIFACT_MAX_DEPTH = 32;
45
45
  export const MANAGED_ARTIFACT_MAX_FILES = 50_000;
46
- export const MANAGED_ARTIFACT_MAX_FILE_BYTES = 64 * 1024 * 1024;
46
+ export const MANAGED_ARTIFACT_MAX_FILE_BYTES = 128 * 1024 * 1024;
47
47
  export const MANAGED_ARTIFACT_MAX_TOTAL_BYTES = 512 * 1024 * 1024;
48
48
  const REPLACEMENT_CLEANUP_RECEIPT_MAX_BYTES = 64 * 1024;
49
49
  const REPLACEMENT_CLEANUP_RECEIPT_SCAN_LIMIT = MANAGED_ARTIFACT_MAX_FILES;
@@ -62,12 +62,14 @@ export class ManagedPublishError extends Error {
62
62
  | "io_error"
63
63
  | "durability_failed";
64
64
  readonly diagnostic: string;
65
+ readonly stagingCleanupSafe: boolean;
65
66
 
66
67
  constructor(classification: ManagedPublishError["classification"], outcome: NativePublishOutcome) {
67
68
  super(classification);
68
69
  this.name = "ManagedPublishError";
69
70
  this.classification = classification;
70
71
  this.diagnostic = formatNativePublishDiagnostic(outcome);
72
+ this.stagingCleanupSafe = mayCleanCurrentStaging(outcome);
71
73
  }
72
74
  }
73
75
  export class ManagedReplaceError extends Error {
@@ -77,6 +79,9 @@ export class ManagedReplaceError extends Error {
77
79
  readonly retainedSuccessorPath: string | undefined;
78
80
  readonly retainedPlaceholderPath: string | undefined;
79
81
  readonly retainedUnknownPath: string | undefined;
82
+ /** Path-free Windows NTSTATUS of the underlying pre-mutation failure, when
83
+ * the native layer preserved one (e.g. `0xC0000043` for a sharing violation). */
84
+ readonly windowsErrorCode: string | undefined;
80
85
  readonly replacementCause: unknown;
81
86
 
82
87
  constructor(result: NativeExactUnlinkResult, cleanupReceiptPath: string, replacementCause?: unknown) {
@@ -89,6 +94,7 @@ export class ManagedReplaceError extends Error {
89
94
  this.retainedSuccessorPath = result.retainedSuccessorPath;
90
95
  this.retainedPlaceholderPath = result.retainedPlaceholderPath;
91
96
  this.retainedUnknownPath = result.retainedUnknownPath;
97
+ this.windowsErrorCode = result.windowsErrorCode;
92
98
  this.replacementCause = replacementCause;
93
99
  }
94
100
  }
@@ -170,7 +176,7 @@ function sameDirectoryTreeSnapshotAfterRename(
170
176
  );
171
177
  }
172
178
 
173
- class ManagedTreeMoveOutcomeError extends Error {
179
+ export class ManagedTreeMoveOutcomeError extends Error {
174
180
  constructor(
175
181
  message: string,
176
182
  readonly stagingCleanupSafe: boolean,
@@ -260,6 +266,17 @@ export interface ManagedAppendReceipt {
260
266
  identity: ManagedFileIdentity;
261
267
  }
262
268
 
269
+ function sameManagedIdentity(left: ManagedFileIdentity, right: ManagedFileIdentity): boolean {
270
+ return (
271
+ left.dev === right.dev &&
272
+ left.ino === right.ino &&
273
+ left.nlink === right.nlink &&
274
+ left.size === right.size &&
275
+ left.mtimeNs === right.mtimeNs &&
276
+ left.ctimeNs === right.ctimeNs
277
+ );
278
+ }
279
+
263
280
  export interface ManagedBoundedAppendExpectation {
264
281
  readonly dev: string;
265
282
  readonly ino: string;
@@ -516,28 +533,30 @@ function reportScrubbedProtocolRemnantReap(reaped: number, failures: number): Sc
516
533
  });
517
534
  return { reaped, failures };
518
535
  }
536
+
519
537
  /**
520
538
  * Best-effort removal of scrubbed write-protocol remnants from one managed
521
539
  * directory. Only zero-length, single-link, non-symlink regular files whose
522
540
  * names carry a terminal remnant prefix and whose timestamps are older than
523
541
  * the age gate are removed: a zero-length single-link entry is exactly what
524
542
  * the scrub proof leaves behind, and non-zero entries (displaced predecessors
525
- * or detached receipts retained as evidence) are never touched. Failures are
526
- * swallowed — a concurrent same-owner writer may legitimately own or already
527
- * have reconciled any candidate.
543
+ * or detached receipts retained as evidence) are never touched. A proven
544
+ * concurrent disappearance (ENOENT) is benign; all other I/O failures are
545
+ * returned and logged once without aborting scope preparation.
528
546
  */
529
547
  export function reapScrubbedProtocolRemnantsSync(
530
548
  directory: string,
531
549
  minAgeMs: number = SCRUBBED_REMNANT_MIN_AGE_MS,
532
- ): number {
550
+ ): ScrubbedProtocolRemnantReapResult {
533
551
  let names: string[];
534
552
  try {
535
553
  names = fs.readdirSync(directory);
536
- } catch {
537
- return 0;
554
+ } catch (error) {
555
+ return reportScrubbedProtocolRemnantReap(0, isEnoent(error) ? 0 : 1);
538
556
  }
539
557
  const cutoff = Date.now() - minAgeMs;
540
558
  let reaped = 0;
559
+ let failures = 0;
541
560
  for (const name of names) {
542
561
  if (!SCRUBBED_REMNANT_PREFIXES.some(prefix => name.startsWith(prefix))) continue;
543
562
  const pathname = path.join(directory, name);
@@ -547,11 +566,11 @@ export function reapScrubbedProtocolRemnantsSync(
547
566
  if (named.mtimeMs > cutoff) continue;
548
567
  fs.unlinkSync(pathname);
549
568
  reaped += 1;
550
- } catch {
551
- // Best effort: concurrently reconciled or removed remnants are not errors.
569
+ } catch (error) {
570
+ if (!isEnoent(error)) failures += 1;
552
571
  }
553
572
  }
554
- return reaped;
573
+ return reportScrubbedProtocolRemnantReap(reaped, failures);
555
574
  }
556
575
 
557
576
  /** Number of candidate remnants inspected between event-loop yields. */
@@ -1480,6 +1499,72 @@ export class ManagedSessionDescendantStore {
1480
1499
  this.#publishRetainedNoReplace(this.#relative(resolved), bytes);
1481
1500
  this.#assertBound();
1482
1501
  }
1502
+ /**
1503
+ * Atomically publishes an already-written managed staging file without
1504
+ * materializing its contents. The staging file and destination must be
1505
+ * descendants of this retained store.
1506
+ */
1507
+ publishStagedFileNoReplace(
1508
+ sourceRelativePath: string,
1509
+ destinationRelativePath: string,
1510
+ expected: { bytes: number; sha256: string },
1511
+ ): void {
1512
+ this.#beforeMutation();
1513
+ this.#assertBound();
1514
+ const source = this.#resolve(sourceRelativePath);
1515
+ const destination = this.#resolve(destinationRelativePath);
1516
+ const fd = fs.openSync(source, fs.constants.O_RDONLY | fs.constants.O_NOFOLLOW);
1517
+ let sourceIdentity: ManagedFileSnapshot["identity"] | undefined;
1518
+ try {
1519
+ const descriptorStat = fs.fstatSync(fd, { bigint: true });
1520
+ const before = identity(descriptorStat);
1521
+ const named = identity(fs.lstatSync(source, { bigint: true }));
1522
+ if (
1523
+ !descriptorStat.isFile() ||
1524
+ before.nlink !== 1n ||
1525
+ !sameIdentity(before, named) ||
1526
+ before.size !== expected.bytes
1527
+ )
1528
+ throw new Error("managed_publish_identity_mismatch");
1529
+ const digest = createHash("sha256");
1530
+ const chunk = Buffer.allocUnsafe(1024 * 1024);
1531
+ let offset = 0;
1532
+ for (;;) {
1533
+ const bytesRead = fs.readSync(fd, chunk, 0, chunk.length, offset);
1534
+ if (bytesRead === 0) break;
1535
+ digest.update(chunk.subarray(0, bytesRead));
1536
+ offset += bytesRead;
1537
+ }
1538
+ if (digest.digest("hex") !== expected.sha256) throw new Error("managed_publish_identity_mismatch");
1539
+ fs.fsyncSync(fd);
1540
+ const after = identity(fs.fstatSync(fd, { bigint: true }));
1541
+ const namedAfter = identity(fs.lstatSync(source, { bigint: true }));
1542
+ if (!sameIdentity(before, after) || !sameIdentity(after, namedAfter))
1543
+ throw new Error("managed_publish_identity_mismatch");
1544
+ sourceIdentity = after;
1545
+ } finally {
1546
+ fs.closeSync(fd);
1547
+ }
1548
+ if (!sourceIdentity) throw new Error("managed_publish_identity_unavailable");
1549
+ const relativeSource = this.#relative(source);
1550
+ const relativeDestination = this.#relative(destination);
1551
+ const published = this.#authority
1552
+ ? this.#authority.renameManagedFileNoReplace(
1553
+ relativeSource,
1554
+ relativeDestination,
1555
+ sourceIdentity.dev.toString(),
1556
+ sourceIdentity.ino.toString(),
1557
+ sourceIdentity.size.toString(),
1558
+ sourceIdentity.mtimeNs.toString(),
1559
+ sourceIdentity.ctimeNs.toString(),
1560
+ expected.sha256,
1561
+ )
1562
+ : nativeSessionStorage().renameNoReplacePath(source, destination);
1563
+ const outcome = classifyNativePublishOutcome(published, this.#authority ? "retained_file" : "direct_rename");
1564
+ if (!outcome.ok) throw publishFailure(outcome);
1565
+ if (!this.#authority) fsyncDirectory(this.#baseDir);
1566
+ this.#assertBound();
1567
+ }
1483
1568
 
1484
1569
  async replace(relativePath: string, bytes: Uint8Array): Promise<void> {
1485
1570
  this.#beforeMutation();
@@ -1501,6 +1586,49 @@ export class ManagedSessionDescendantStore {
1501
1586
  this.#assertBound();
1502
1587
  }
1503
1588
 
1589
+ replaceExpectedIdentitySync(relativePath: string, bytes: Uint8Array, expected: ManagedFileIdentity): void {
1590
+ this.#beforeMutation();
1591
+ this.#assertBound();
1592
+ const resolved = this.#resolve(relativePath);
1593
+ if (!this.#authority) {
1594
+ const current = captureManagedFileIdentityStreamingNoFollow(resolved);
1595
+ if (!sameManagedIdentity(current, expected)) throw new Error("managed_replace_identity_mismatch");
1596
+ replaceManagedFileSync(resolved, bytes, this.#subtreeRoot, this.#policy, undefined, current);
1597
+ this.#assertBound();
1598
+ return;
1599
+ }
1600
+ const relative = this.#relative(resolved);
1601
+ const observed = this.#authority.stat(relative);
1602
+ if (!observed.ok || !observed.identity) {
1603
+ const rawCode =
1604
+ typeof (observed as { code?: unknown })?.code === "string" ? (observed as { code: string }).code : "";
1605
+ // Authority reports "not_found" for missing, non-authority uses ENOENT.
1606
+ // Normalize to ENOENT so callers' isEnoent() recovers via create.
1607
+ const err = new Error(rawCode || "managed_replace_missing") as NodeJS.ErrnoException;
1608
+ err.code = rawCode === "not_found" ? "ENOENT" : rawCode || "managed_replace_missing";
1609
+ throw err;
1610
+ }
1611
+ const current = managedFileIdentityFromNative(observed.identity);
1612
+ if (!sameManagedIdentity(current, expected)) throw new Error("managed_replace_identity_mismatch");
1613
+ const expectedSha256 =
1614
+ typeof observed.identity.sha256 === "string" && /^[0-9a-f]{64}$/i.test(observed.identity.sha256)
1615
+ ? observed.identity.sha256.toLowerCase()
1616
+ : this.readExpected(relativePath)?.identity.sha256;
1617
+ if (!expectedSha256) throw new Error("managed_replace_identity_unavailable");
1618
+ const replaced = (this.#authority as RecoveryFsRoot & RetainedManagedReplacer).replaceManaged(
1619
+ relative,
1620
+ bytes,
1621
+ observed.identity.dev,
1622
+ observed.identity.ino,
1623
+ observed.identity.size,
1624
+ observed.identity.mtimeNs,
1625
+ observed.identity.ctimeNs,
1626
+ expectedSha256,
1627
+ );
1628
+ if (!replaced.ok) throw new Error(replaced.code ?? "managed_replace_failed");
1629
+ this.#assertBound();
1630
+ }
1631
+
1504
1632
  replaceExpected(relativePath: string, bytes: Uint8Array, expected: ManagedFileSnapshot): void {
1505
1633
  this.#beforeMutation();
1506
1634
  this.#assertBound();
@@ -1608,6 +1736,24 @@ export class ManagedSessionDescendantStore {
1608
1736
  return managedAppendReceiptFromIdentity(managedFileIdentityFromNative(appended.identity));
1609
1737
  }
1610
1738
 
1739
+ appendExpectedIdentitySync(
1740
+ relativePath: string,
1741
+ bytes: Uint8Array,
1742
+ expected: ManagedFileIdentity,
1743
+ ): ManagedAppendReceipt {
1744
+ const bounded = this.captureBoundedAppendExpectation(relativePath);
1745
+ if (
1746
+ !bounded ||
1747
+ bounded.dev !== expected.dev.toString() ||
1748
+ bounded.ino !== expected.ino.toString() ||
1749
+ bounded.size !== String(expected.size) ||
1750
+ bounded.mtimeNs !== expected.mtimeNs.toString() ||
1751
+ bounded.ctimeNs !== expected.ctimeNs.toString()
1752
+ )
1753
+ throw new Error("managed_append_identity_mismatch");
1754
+ return this.appendExpectedSync(relativePath, bytes, bounded);
1755
+ }
1756
+
1611
1757
  appendSync(relativePath: string, bytes: Uint8Array): ManagedAppendReceipt {
1612
1758
  this.#beforeMutation();
1613
1759
  this.#assertBound();
@@ -1615,7 +1761,13 @@ export class ManagedSessionDescendantStore {
1615
1761
  if (this.#authority) {
1616
1762
  const relative = this.#relative(resolved);
1617
1763
  const observed = this.#authority.stat(relative);
1618
- if (!observed.ok || !observed.identity) throw new Error(observed.code ?? "managed_append_missing");
1764
+ if (!observed.ok || !observed.identity) {
1765
+ const rawCode =
1766
+ typeof (observed as { code?: unknown })?.code === "string" ? (observed as { code: string }).code : "";
1767
+ const err = new Error(rawCode || "managed_append_missing") as NodeJS.ErrnoException;
1768
+ err.code = rawCode === "not_found" ? "ENOENT" : rawCode || "managed_append_missing";
1769
+ throw err;
1770
+ }
1619
1771
  const nativeSha256 = observed.identity.sha256;
1620
1772
  const expectedSha256 =
1621
1773
  typeof nativeSha256 === "string" && /^[0-9a-f]{64}$/i.test(nativeSha256)
@@ -2891,6 +3043,15 @@ function replaceManagedFileGeneratedSync(
2891
3043
  identity: publishedReceiptIdentity,
2892
3044
  predecessor: expectedDestination,
2893
3045
  };
3046
+ // Transient Windows sharing violations (a concurrent holder denying delete
3047
+ // sharing on the destination, issue #4330) are retried at the narrow
3048
+ // pre-mutation syscall boundary inside the native `exactReplacePath`: the
3049
+ // destination open is retried a bounded number of times while nothing has
3050
+ // been renamed or unlinked, and only `sharing_violation`/`io_error` with no
3051
+ // detached/retained paths can ever reach this throw from that open. This
3052
+ // TypeScript layer deliberately never retries: once `exactReplacePath`
3053
+ // returns, any failure that carries a detached/retained path is
3054
+ // post-mutation evidence and must surface unchanged for receipt recovery.
2894
3055
  const replaced = nativeSessionStorage().exactReplacePath(
2895
3056
  staging,
2896
3057
  destination,
@@ -122,7 +122,7 @@ export function readPendingDisplayTag(details: unknown): string | undefined {
122
122
  * the CustomMessageEntry to disk. Scoped intentionally narrow: only fields
123
123
  * declared here are stripped. Adding a new entry is a deliberate, reviewed
124
124
  * change — unrelated future payload fields are never silently dropped. */
125
- export const INTERNAL_DETAILS_FIELDS = ["__pendingDisplayTag"] as const;
125
+ export const INTERNAL_DETAILS_FIELDS = ["__pendingDisplayTag", "ownedCompletions"] as const;
126
126
 
127
127
  /** Return a `details` copy with every key in `INTERNAL_DETAILS_FIELDS`
128
128
  * removed. Returns the input unchanged when there is nothing to strip
@@ -0,0 +1,80 @@
1
+ import * as fs from "node:fs/promises";
2
+ import * as path from "node:path";
3
+ import { isEnoent } from "@gajae-code/utils";
4
+
5
+ function isPosix(): boolean {
6
+ return process.platform !== "win32";
7
+ }
8
+
9
+ async function validateDirectory(directory: string): Promise<void> {
10
+ await fs.mkdir(directory, { recursive: true, mode: 0o700 });
11
+ const stat = await fs.lstat(directory);
12
+ if (stat.isSymbolicLink() || !stat.isDirectory()) throw new Error("Credential token directory is unsafe.");
13
+ if (isPosix()) {
14
+ if (typeof process.getuid === "function" && stat.uid !== process.getuid()) {
15
+ throw new Error("Credential token directory has an unexpected owner.");
16
+ }
17
+ if ((stat.mode & 0o077) !== 0) await fs.chmod(directory, 0o700);
18
+ const repaired = await fs.lstat(directory);
19
+ if ((repaired.mode & 0o077) !== 0) throw new Error("Credential token directory is not owner-only.");
20
+ }
21
+ }
22
+
23
+ async function validateTokenPath(file: string): Promise<boolean> {
24
+ let stat: Awaited<ReturnType<typeof fs.lstat>>;
25
+ try {
26
+ stat = await fs.lstat(file);
27
+ } catch (error) {
28
+ if (isEnoent(error)) return false;
29
+ throw error;
30
+ }
31
+ if (stat.isSymbolicLink() || !stat.isFile()) throw new Error("Credential token path is unsafe.");
32
+ if (isPosix()) {
33
+ if (typeof process.getuid === "function" && stat.uid !== process.getuid()) {
34
+ throw new Error("Credential token file has an unexpected owner.");
35
+ }
36
+ if ((stat.mode & 0o077) !== 0) await fs.chmod(file, 0o600);
37
+ const repaired = await fs.lstat(file);
38
+ if ((repaired.mode & 0o077) !== 0) throw new Error("Credential token file is not owner-only.");
39
+ }
40
+ return true;
41
+ }
42
+
43
+ export async function readSecureTokenFile(file: string): Promise<string | null> {
44
+ await validateDirectory(path.dirname(file));
45
+ if (!(await validateTokenPath(file))) return null;
46
+ const handle = await fs.open(file, "r");
47
+ try {
48
+ const opened = await handle.stat();
49
+ if (!opened.isFile()) throw new Error("Credential token path is unsafe.");
50
+ const value = (await handle.readFile("utf8")).trim();
51
+ return value || null;
52
+ } finally {
53
+ await handle.close();
54
+ }
55
+ }
56
+
57
+ export async function writeSecureTokenFile(file: string, token: string): Promise<void> {
58
+ await validateDirectory(path.dirname(file));
59
+ if (await validateTokenPath(file)) {
60
+ await fs.writeFile(file, token, { mode: 0o600 });
61
+ } else {
62
+ await fs.writeFile(file, token, { flag: "wx", mode: 0o600 });
63
+ }
64
+ if (isPosix()) await fs.chmod(file, 0o600);
65
+ }
66
+
67
+ export async function createSecureTokenFileExclusive(file: string, token: string): Promise<boolean> {
68
+ await validateDirectory(path.dirname(file));
69
+ try {
70
+ await fs.writeFile(file, token, { flag: "wx", mode: 0o600 });
71
+ } catch (error) {
72
+ if ((error as NodeJS.ErrnoException).code === "EEXIST") {
73
+ await validateTokenPath(file);
74
+ return false;
75
+ }
76
+ throw error;
77
+ }
78
+ if (isPosix()) await fs.chmod(file, 0o600);
79
+ return true;
80
+ }