@gajae-code/coding-agent 0.13.2 → 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 (610) hide show
  1. package/CHANGELOG.md +215 -8
  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 +10 -1
  35. package/dist/types/config/models-config-schema.d.ts +2 -0
  36. package/dist/types/config/settings-schema.d.ts +73 -9
  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 +2 -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/dynamic-theme-text.d.ts +9 -0
  87. package/dist/types/modes/components/gajae-pet-widget.d.ts +6 -28
  88. package/dist/types/modes/components/irc-sidebar.d.ts +1 -0
  89. package/dist/types/modes/components/iterm-pet-transport.d.ts +122 -0
  90. package/dist/types/modes/components/oauth-selector.d.ts +10 -4
  91. package/dist/types/modes/components/pet-capability.d.ts +7 -21
  92. package/dist/types/modes/components/settings-selector.d.ts +5 -0
  93. package/dist/types/modes/components/status-line/gh.d.ts +6 -2
  94. package/dist/types/modes/controllers/extension-ui-controller.d.ts +1 -1
  95. package/dist/types/modes/controllers/selector-controller.d.ts +7 -8
  96. package/dist/types/modes/controllers/stt-controller.d.ts +1 -1
  97. package/dist/types/modes/interactive-mode.d.ts +1 -0
  98. package/dist/types/modes/theme/defaults/index.d.ts +118 -0
  99. package/dist/types/modes/types.d.ts +1 -0
  100. package/dist/types/modes/utils/injected-user-submission.d.ts +10 -0
  101. package/dist/types/runtime-mcp/config.d.ts +9 -0
  102. package/dist/types/runtime-mcp/manager.d.ts +26 -1
  103. package/dist/types/runtime-mcp/oauth-discovery.d.ts +4 -0
  104. package/dist/types/runtime-mcp/oauth-flow.d.ts +24 -1
  105. package/dist/types/runtime-mcp/pool-key.d.ts +2 -0
  106. package/dist/types/runtime-mcp/protocol.d.ts +278 -0
  107. package/dist/types/runtime-mcp/scope-config.d.ts +29 -0
  108. package/dist/types/runtime-mcp/tool-bridge.d.ts +15 -13
  109. package/dist/types/runtime-mcp/transports/http.d.ts +9 -0
  110. package/dist/types/runtime-mcp/types.d.ts +102 -10
  111. package/dist/types/sdk/acp/adapter.d.ts +26 -5
  112. package/dist/types/sdk/broker/broker.d.ts +3 -55
  113. package/dist/types/sdk/broker/lifecycle.d.ts +18 -12
  114. package/dist/types/sdk/broker/session-index.d.ts +14 -5
  115. package/dist/types/sdk/broker/startup-failure.d.ts +16 -1
  116. package/dist/types/sdk/bus/chat-daemon-control.d.ts +51 -1
  117. package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +4 -41
  118. package/dist/types/sdk/bus/config.d.ts +11 -0
  119. package/dist/types/sdk/bus/conversation-store.d.ts +0 -1
  120. package/dist/types/sdk/bus/daemon-paths.d.ts +6 -0
  121. package/dist/types/sdk/bus/discord-conversation.d.ts +2 -0
  122. package/dist/types/sdk/bus/discord-daemon.d.ts +17 -12
  123. package/dist/types/sdk/bus/existing-thread-readiness.d.ts +4 -34
  124. package/dist/types/sdk/bus/inbound-reaction-ordering.d.ts +61 -0
  125. package/dist/types/sdk/bus/index.d.ts +85 -99
  126. package/dist/types/sdk/bus/kind-aware-reconciliation.d.ts +29 -7
  127. package/dist/types/sdk/bus/managed-daemon.d.ts +2 -32
  128. package/dist/types/sdk/bus/notification-service.d.ts +52 -0
  129. package/dist/types/sdk/bus/operator-runtime.d.ts +1 -1
  130. package/dist/types/sdk/bus/prompt-reconciliation.d.ts +16 -5
  131. package/dist/types/sdk/bus/reconciliation-store.d.ts +113 -5
  132. package/dist/types/sdk/bus/session-control.d.ts +25 -1
  133. package/dist/types/sdk/bus/slack-conversation.d.ts +4 -0
  134. package/dist/types/sdk/bus/slack-daemon.d.ts +9 -17
  135. package/dist/types/sdk/bus/slack-live-provider.d.ts +3 -1
  136. package/dist/types/sdk/bus/slack-provider.d.ts +4 -0
  137. package/dist/types/sdk/bus/slack-thread-binding.d.ts +6 -40
  138. package/dist/types/sdk/bus/telegram-adoption-intent.d.ts +30 -104
  139. package/dist/types/sdk/bus/telegram-daemon-cli.d.ts +10 -0
  140. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +262 -19
  141. package/dist/types/sdk/bus/telegram-daemon-orphan-reap.d.ts +125 -0
  142. package/dist/types/sdk/bus/telegram-daemon-owner-registry.d.ts +22 -0
  143. package/dist/types/sdk/bus/telegram-daemon.d.ts +119 -310
  144. package/dist/types/sdk/bus/telegram-reference.d.ts +1 -47
  145. package/dist/types/sdk/bus/threaded-render.d.ts +1 -0
  146. package/dist/types/sdk/bus/topic-registry.d.ts +33 -17
  147. package/dist/types/sdk/cli/rows.d.ts +2 -11
  148. package/dist/types/sdk/cli/session-cli.d.ts +15 -25
  149. package/dist/types/sdk/client/client.d.ts +97 -1
  150. package/dist/types/sdk/host/control/dispatch.d.ts +0 -7
  151. package/dist/types/sdk/host/control/index.d.ts +1 -1
  152. package/dist/types/sdk/host/control/operations.d.ts +18 -5
  153. package/dist/types/sdk/host/control/runtime-gate.d.ts +19 -0
  154. package/dist/types/sdk/host/host.d.ts +15 -1
  155. package/dist/types/sdk/host/query/handlers.d.ts +5 -0
  156. package/dist/types/sdk/host/reverse-leases.d.ts +1 -1
  157. package/dist/types/sdk/host/session-runtime.d.ts +127 -7
  158. package/dist/types/sdk/host/types.d.ts +1 -1
  159. package/dist/types/sdk/host/websocket-transport.d.ts +1 -1
  160. package/dist/types/sdk/index.d.ts +2 -1
  161. package/dist/types/sdk/lifecycle/broker-client.d.ts +8 -0
  162. package/dist/types/sdk/lifecycle/client.d.ts +59 -0
  163. package/dist/types/sdk/lifecycle/index.d.ts +3 -0
  164. package/dist/types/sdk/lifecycle/service.d.ts +232 -0
  165. package/dist/types/sdk/mcp/server.d.ts +9 -6
  166. package/dist/types/sdk/prompt-deadline-lease.d.ts +43 -0
  167. package/dist/types/sdk/prompt-deadline-manager.d.ts +28 -0
  168. package/dist/types/sdk/prompt-status.d.ts +10 -3
  169. package/dist/types/sdk/protocol/operation-registry.d.ts +5 -0
  170. package/dist/types/sdk/receipt-state.d.ts +17 -0
  171. package/dist/types/sdk/reconciliation-extensions.d.ts +2 -0
  172. package/dist/types/sdk/router/index.d.ts +1 -0
  173. package/dist/types/sdk/router/session-router.d.ts +152 -0
  174. package/dist/types/sdk/session-list.d.ts +22 -0
  175. package/dist/types/sdk/session-reconnect.d.ts +43 -1
  176. package/dist/types/sdk/session.d.ts +34 -1
  177. package/dist/types/sdk/transport/serve-cli.d.ts +1 -4
  178. package/dist/types/session/account-inventory.d.ts +86 -0
  179. package/dist/types/session/agent-session.d.ts +145 -6
  180. package/dist/types/session/agent-storage.d.ts +10 -0
  181. package/dist/types/session/coordinator-tool-label.d.ts +28 -0
  182. package/dist/types/session/internal/managed-session-storage.d.ts +23 -4
  183. package/dist/types/session/messages.d.ts +1 -1
  184. package/dist/types/session/secure-token-file.d.ts +3 -0
  185. package/dist/types/session/session-manager.d.ts +47 -1
  186. package/dist/types/session/startup-auth-config.d.ts +44 -0
  187. package/dist/types/session/terminal-abort.d.ts +378 -0
  188. package/dist/types/session/yield-queue.d.ts +7 -0
  189. package/dist/types/session-import/claude.d.ts +26 -0
  190. package/dist/types/session-import/codex.d.ts +88 -0
  191. package/dist/types/session-import/command.d.ts +35 -0
  192. package/dist/types/session-import/detect.d.ts +22 -0
  193. package/dist/types/session-import/index.d.ts +7 -0
  194. package/dist/types/session-import/provider-codex.d.ts +22 -0
  195. package/dist/types/session-import/provider-service.d.ts +38 -0
  196. package/dist/types/session-import/redact.d.ts +23 -0
  197. package/dist/types/session-import/service.d.ts +47 -0
  198. package/dist/types/session-import/types.d.ts +120 -0
  199. package/dist/types/setup/paseo/check.d.ts +16 -0
  200. package/dist/types/setup/paseo/install-saga.d.ts +115 -0
  201. package/dist/types/setup/paseo/json-publisher.d.ts +76 -0
  202. package/dist/types/setup/paseo/orchestration-preferences.d.ts +24 -0
  203. package/dist/types/setup/paseo/paseo-ownership.d.ts +87 -0
  204. package/dist/types/setup/paseo/paseo-setup.d.ts +29 -0
  205. package/dist/types/setup/paseo/provider-config.d.ts +35 -0
  206. package/dist/types/setup/paseo/remove.d.ts +14 -0
  207. package/dist/types/setup/paseo/result-types.d.ts +59 -0
  208. package/dist/types/setup/paseo/setup-deps.d.ts +73 -0
  209. package/dist/types/setup/paseo/skills-bridge.d.ts +44 -0
  210. package/dist/types/skill-state/active-state.d.ts +5 -1
  211. package/dist/types/slash-commands/acp-builtins.d.ts +5 -1
  212. package/dist/types/slash-commands/builtin-registry.d.ts +2 -0
  213. package/dist/types/slash-commands/helpers/credential-switch.d.ts +12 -0
  214. package/dist/types/slash-commands/helpers/usage-report.d.ts +5 -6
  215. package/dist/types/slash-commands/types.d.ts +7 -1
  216. package/dist/types/task/executor.d.ts +10 -0
  217. package/dist/types/task/index.d.ts +3 -1
  218. package/dist/types/tools/ask-answer-registry.d.ts +6 -3
  219. package/dist/types/tools/bash-sleep-advisory.d.ts +14 -0
  220. package/dist/types/tools/bash.d.ts +2 -6
  221. package/dist/types/tools/browser/attach.d.ts +11 -0
  222. package/dist/types/tools/browser/launch.d.ts +20 -0
  223. package/dist/types/tools/browser/profile-discovery.d.ts +6 -0
  224. package/dist/types/tools/browser/render.d.ts +1 -0
  225. package/dist/types/tools/browser.d.ts +3 -1
  226. package/dist/types/tools/image-gen.d.ts +10 -2
  227. package/dist/types/tools/index.d.ts +8 -0
  228. package/dist/types/tools/monitor.d.ts +1 -1
  229. package/dist/types/tools/skill-discovery.d.ts +8 -1
  230. package/dist/types/tools/subagent.d.ts +2 -0
  231. package/dist/types/tools/ultragoal-ask-guard.d.ts +2 -2
  232. package/dist/types/utils/herdr-pane.d.ts +76 -0
  233. package/package.json +19 -9
  234. package/scripts/build-binary.ts +2 -1
  235. package/scripts/build-sdk-package-smoke.ts +2 -13
  236. package/scripts/capture-sticky-viewport-showcase.ts +0 -1
  237. package/scripts/compile-args.ts +2 -0
  238. package/scripts/generate-sdk-adapter-parity-manifest.ts +31 -16
  239. package/scripts/generate-sdk-operation-inventory.ts +28 -0
  240. package/scripts/generate-telegram-baseline-manifest.ts +1 -0
  241. package/scripts/generate-tool-catalog.ts +6 -4
  242. package/scripts/verify-gjc-sdk-canonicalization.ts +5 -39
  243. package/src/async/job-manager.ts +352 -17
  244. package/src/async/support.ts +25 -0
  245. package/src/autoresearch/dashboard.ts +28 -13
  246. package/src/capability/index.ts +3 -1
  247. package/src/capability/mcp.ts +6 -0
  248. package/src/capability/types.ts +6 -0
  249. package/src/cli/accounts-cli.ts +395 -0
  250. package/src/cli/args.ts +23 -0
  251. package/src/cli/auth-broker-cli.ts +136 -66
  252. package/src/cli/auth-gateway-cli.ts +94 -70
  253. package/src/cli/config-cli.ts +27 -2
  254. package/src/cli/crash-cli.ts +78 -0
  255. package/src/cli/customize-doctor.ts +1605 -0
  256. package/src/cli/daemon-cli.ts +12 -3
  257. package/src/cli/fast-help.ts +1 -0
  258. package/src/cli/mcp-cli.ts +128 -60
  259. package/src/cli/notify-cli.ts +8 -14
  260. package/src/cli/root-flags.ts +8 -0
  261. package/src/cli/setup-cli.ts +145 -0
  262. package/src/cli/skills-cli.ts +38 -2
  263. package/src/cli/update-cli.ts +167 -12
  264. package/src/cli.ts +4 -0
  265. package/src/commands/accounts.ts +71 -0
  266. package/src/commands/crash.ts +35 -0
  267. package/src/commands/customize.ts +84 -0
  268. package/src/commands/daemon.ts +2 -2
  269. package/src/commands/deep-interview.ts +2 -0
  270. package/src/commands/launch.ts +1 -0
  271. package/src/commands/mcp.ts +12 -7
  272. package/src/commands/ralplan.ts +2 -0
  273. package/src/commands/sdk.ts +65 -32
  274. package/src/commands/setup.ts +5 -0
  275. package/src/commands/skills.ts +14 -4
  276. package/src/commands/ultragoal.ts +10 -1
  277. package/src/commands/update.ts +26 -15
  278. package/src/config/atomic-yaml-patch-worker.ts +57 -0
  279. package/src/config/atomic-yaml-patch.ts +769 -29
  280. package/src/config/config-schema-version.ts +10 -0
  281. package/src/config/file-lock.ts +70 -1
  282. package/src/config/mcp-schema.json +52 -14
  283. package/src/config/model-profile-activation.ts +23 -2
  284. package/src/config/model-profiles.ts +88 -21
  285. package/src/config/model-registry.ts +147 -21
  286. package/src/config/models-config-schema.ts +1 -1
  287. package/src/config/settings-schema.ts +77 -7
  288. package/src/config/settings.ts +4038 -199
  289. package/src/config/skill-settings-defaults.ts +41 -3
  290. package/src/config/task-delegation.ts +87 -0
  291. package/src/config/update-channel.ts +23 -0
  292. package/src/coordinator-mcp/server.ts +377 -308
  293. package/src/crash/index-store.ts +723 -0
  294. package/src/crash/nudge.ts +89 -0
  295. package/src/crash/record-loader.ts +149 -0
  296. package/src/crash/report.ts +551 -0
  297. package/src/crash/sanitize.ts +129 -0
  298. package/src/cursor.ts +36 -10
  299. package/src/customization/import.ts +946 -0
  300. package/src/customization/index.ts +4 -0
  301. package/src/customization/inventory.ts +335 -0
  302. package/src/customization/mutations.ts +141 -0
  303. package/src/customization/types.ts +223 -0
  304. package/src/daemon/control-types.ts +8 -1
  305. package/src/daemon/operator-contract.ts +6 -6
  306. package/src/defaults/gjc/extensions/grok-cli-vendor/src/models/catalog.ts +31 -6
  307. package/src/defaults/gjc/skills/deep-interview/SKILL.md +11 -22
  308. package/src/defaults/gjc/skills/ralplan/SKILL.md +36 -23
  309. package/src/defaults/gjc/skills/ultragoal/SKILL.md +16 -0
  310. package/src/discovery/claude-hooks.ts +38 -0
  311. package/src/discovery/claude.ts +142 -209
  312. package/src/discovery/codex-hooks.ts +38 -0
  313. package/src/discovery/codex.ts +132 -198
  314. package/src/discovery/helpers.ts +8 -1
  315. package/src/discovery/index.ts +2 -0
  316. package/src/discovery/mcp-compat.ts +234 -0
  317. package/src/discovery/mcp-json.ts +6 -0
  318. package/src/edit/renderer.ts +40 -0
  319. package/src/edit/streaming.ts +4 -2
  320. package/src/exec/bash-executor.ts +24 -20
  321. package/src/export/html/index.ts +51 -2
  322. package/src/extensibility/extensions/loader.ts +9 -1
  323. package/src/extensibility/extensions/runner.ts +17 -4
  324. package/src/extensibility/extensions/types.ts +31 -6
  325. package/src/extensibility/gjc-plugins/constrained-hooks.ts +33 -0
  326. package/src/extensibility/gjc-plugins/installer.ts +9 -5
  327. package/src/extensibility/gjc-plugins/observability.ts +8 -2
  328. package/src/extensibility/gjc-plugins/registry.ts +13 -2
  329. package/src/extensibility/gjc-plugins/runtime-adapters.ts +3 -1
  330. package/src/extensibility/gjc-plugins/schema.ts +222 -39
  331. package/src/extensibility/hooks/loader.ts +154 -10
  332. package/src/extensibility/runtime-skill-discovery.ts +257 -60
  333. package/src/extensibility/skill-management.ts +368 -0
  334. package/src/extensibility/skills.ts +52 -16
  335. package/src/gjc-runtime/deep-interview-runtime.ts +45 -61
  336. package/src/gjc-runtime/launch-worktree.ts +56 -2
  337. package/src/gjc-runtime/linux-proc.ts +7 -1
  338. package/src/gjc-runtime/ralplan-runtime.ts +100 -164
  339. package/src/gjc-runtime/session-state-lock.ts +992 -0
  340. package/src/gjc-runtime/session-state-sidecar.ts +644 -142
  341. package/src/gjc-runtime/state-writer.ts +39 -14
  342. package/src/gjc-runtime/tmux-owner-isolation.ts +5 -4
  343. package/src/gjc-runtime/ultragoal-guard.ts +11 -4
  344. package/src/gjc-runtime/ultragoal-runtime.ts +44 -41
  345. package/src/gjc-runtime/workflow-settings.ts +596 -0
  346. package/src/goals/tools/goal-tool.ts +6 -1
  347. package/src/hooks/events.ts +291 -0
  348. package/src/hooks/native-skill-hook.ts +4 -0
  349. package/src/hooks/normalize.ts +369 -0
  350. package/src/hooks/skill-state.ts +165 -46
  351. package/src/internal-urls/docs-index.generated.ts +41 -32
  352. package/src/main.ts +36 -5
  353. package/src/migrate/mcp-mapper.ts +25 -2
  354. package/src/modes/acp/abort-scope.ts +29 -0
  355. package/src/modes/acp/acp-agent.ts +423 -98
  356. package/src/modes/components/assistant-message.ts +6 -1
  357. package/src/modes/components/chrome.ts +4 -3
  358. package/src/modes/components/customization/customization-dashboard.ts +443 -0
  359. package/src/modes/components/customization/import-wizard.ts +372 -0
  360. package/src/modes/components/customization/index.ts +1 -0
  361. package/src/modes/components/dynamic-theme-text.ts +22 -0
  362. package/src/modes/components/gajae-pet-widget.ts +607 -193
  363. package/src/modes/components/irc-sidebar.ts +11 -0
  364. package/src/modes/components/iterm-pet-transport.ts +585 -0
  365. package/src/modes/components/model-selector.ts +1 -6
  366. package/src/modes/components/oauth-selector.ts +277 -86
  367. package/src/modes/components/pet-capability.ts +35 -31
  368. package/src/modes/components/settings-selector.ts +29 -5
  369. package/src/modes/components/status-line/gh.ts +45 -1
  370. package/src/modes/components/status-line/segments.ts +19 -4
  371. package/src/modes/components/tool-status-header.ts +13 -3
  372. package/src/modes/controllers/command-controller.ts +20 -8
  373. package/src/modes/controllers/extension-ui-controller.ts +56 -257
  374. package/src/modes/controllers/input-controller.ts +10 -0
  375. package/src/modes/controllers/runtime-mcp-command-controller.ts +16 -3
  376. package/src/modes/controllers/selector-controller.ts +238 -77
  377. package/src/modes/controllers/stt-controller.ts +3 -3
  378. package/src/modes/interactive-mode.ts +88 -16
  379. package/src/modes/print-mode.ts +35 -6
  380. package/src/modes/runtime-init.ts +21 -68
  381. package/src/modes/theme/defaults/index.ts +2 -0
  382. package/src/modes/theme/defaults/ouroboros.json +118 -0
  383. package/src/modes/types.ts +1 -0
  384. package/src/modes/utils/injected-user-submission.ts +25 -0
  385. package/src/modes/utils/terminal-bell.ts +15 -1
  386. package/src/prompts/agent-fragments/ralplan-persistence.md +1 -1
  387. package/src/prompts/agent-fragments/restricted-bash.md +1 -1
  388. package/src/prompts/agents/critic.md +1 -1
  389. package/src/prompts/system/rlm-research.md +1 -1
  390. package/src/prompts/system/system-prompt.md +0 -2
  391. package/src/prompts/tools/bash.md +7 -1
  392. package/src/prompts/tools/browser.md +1 -1
  393. package/src/prompts/tools/cron.md +6 -6
  394. package/src/prompts/tools/read.md +0 -2
  395. package/src/prompts/tools/skill-discovery.md +4 -2
  396. package/src/runtime-mcp/client.ts +427 -23
  397. package/src/runtime-mcp/config.ts +37 -5
  398. package/src/runtime-mcp/manager-pool.test.ts +56 -0
  399. package/src/runtime-mcp/manager.ts +52 -2
  400. package/src/runtime-mcp/oauth-discovery.ts +13 -0
  401. package/src/runtime-mcp/oauth-flow.ts +46 -1
  402. package/src/runtime-mcp/pool-key.ts +5 -1
  403. package/src/runtime-mcp/pool.test.ts +9 -0
  404. package/src/runtime-mcp/protocol.test.ts +353 -0
  405. package/src/runtime-mcp/protocol.ts +624 -0
  406. package/src/runtime-mcp/scope-config.ts +78 -0
  407. package/src/runtime-mcp/tool-bridge.ts +44 -10
  408. package/src/runtime-mcp/transports/http.ts +84 -13
  409. package/src/runtime-mcp/types.ts +123 -12
  410. package/src/sdk/acp/adapter.ts +328 -97
  411. package/src/sdk/broker/broker.ts +160 -741
  412. package/src/sdk/broker/ensure.ts +9 -1
  413. package/src/sdk/broker/lifecycle.ts +510 -116
  414. package/src/sdk/broker/operation-receipt-ledger.ts +11 -2
  415. package/src/sdk/broker/process-incarnation.ts +19 -0
  416. package/src/sdk/broker/session-index.ts +516 -117
  417. package/src/sdk/broker/startup-failure.ts +28 -5
  418. package/src/sdk/broker/transport.ts +1 -13
  419. package/src/sdk/bus/chat-daemon-cli.ts +4 -2
  420. package/src/sdk/bus/chat-daemon-control.ts +67 -6
  421. package/src/sdk/bus/chat-daemon-runtime.ts +183 -859
  422. package/src/sdk/bus/config.ts +13 -0
  423. package/src/sdk/bus/conversation-store.ts +59 -171
  424. package/src/sdk/bus/daemon-paths.ts +20 -0
  425. package/src/sdk/bus/discord-conversation.ts +2 -0
  426. package/src/sdk/bus/discord-daemon.ts +524 -126
  427. package/src/sdk/bus/discord-live-provider.ts +206 -79
  428. package/src/sdk/bus/existing-thread-readiness.ts +4 -97
  429. package/src/sdk/bus/inbound-reaction-ordering.ts +122 -0
  430. package/src/sdk/bus/index.ts +2480 -456
  431. package/src/sdk/bus/kind-aware-reconciliation.ts +204 -34
  432. package/src/sdk/bus/lifecycle-commands.ts +2 -2
  433. package/src/sdk/bus/managed-daemon.ts +2 -145
  434. package/src/sdk/bus/notification-service.ts +196 -0
  435. package/src/sdk/bus/operator-runtime.ts +1 -1
  436. package/src/sdk/bus/prompt-reconciliation.ts +24 -15
  437. package/src/sdk/bus/reconciliation-store.ts +553 -24
  438. package/src/sdk/bus/session-control.ts +49 -3
  439. package/src/sdk/bus/slack-conversation.ts +4 -0
  440. package/src/sdk/bus/slack-daemon.ts +733 -134
  441. package/src/sdk/bus/slack-live-provider.ts +65 -15
  442. package/src/sdk/bus/slack-provider.ts +4 -0
  443. package/src/sdk/bus/slack-thread-binding.ts +9 -104
  444. package/src/sdk/bus/telegram-adoption-intent.ts +299 -209
  445. package/src/sdk/bus/telegram-daemon-cli.ts +194 -7
  446. package/src/sdk/bus/telegram-daemon-contract.ts +265 -19
  447. package/src/sdk/bus/telegram-daemon-control.ts +3 -13
  448. package/src/sdk/bus/telegram-daemon-orphan-reap.ts +498 -0
  449. package/src/sdk/bus/telegram-daemon-owner-registry.ts +176 -0
  450. package/src/sdk/bus/telegram-daemon.ts +2552 -2280
  451. package/src/sdk/bus/telegram-reference.ts +1 -226
  452. package/src/sdk/bus/telegram-setup.ts +2 -2
  453. package/src/sdk/bus/threaded-render.ts +1 -0
  454. package/src/sdk/bus/topic-registry.ts +279 -146
  455. package/src/sdk/cli/rows.ts +2 -35
  456. package/src/sdk/cli/session-cli.ts +776 -700
  457. package/src/sdk/client/client.ts +892 -1
  458. package/src/sdk/host/control/dispatch.ts +93 -58
  459. package/src/sdk/host/control/index.ts +1 -1
  460. package/src/sdk/host/control/operations.ts +18 -10
  461. package/src/sdk/host/control/runtime-gate.ts +40 -0
  462. package/src/sdk/host/host.ts +63 -12
  463. package/src/sdk/host/query/handlers.ts +66 -7
  464. package/src/sdk/host/reverse-leases.ts +2 -2
  465. package/src/sdk/host/sdk-surface-parity.test.ts +1 -1
  466. package/src/sdk/host/session-runtime.test.ts +2787 -34
  467. package/src/sdk/host/session-runtime.ts +1489 -101
  468. package/src/sdk/host/surface-policy.ts +12 -8
  469. package/src/sdk/host/types.ts +1 -1
  470. package/src/sdk/host/websocket-transport.lifecycle.test.ts +31 -59
  471. package/src/sdk/host/websocket-transport.ts +85 -50
  472. package/src/sdk/index.ts +2 -1
  473. package/src/sdk/lifecycle/broker-client.ts +53 -0
  474. package/src/sdk/lifecycle/client.ts +234 -0
  475. package/src/sdk/lifecycle/index.ts +3 -0
  476. package/src/sdk/{bus/recent-activity.ts → lifecycle/recent-sessions.ts} +5 -2
  477. package/src/sdk/lifecycle/service.ts +720 -0
  478. package/src/sdk/mcp/server.ts +226 -188
  479. package/src/sdk/prompt-deadline-lease.ts +55 -0
  480. package/src/sdk/prompt-deadline-manager.ts +148 -0
  481. package/src/sdk/prompt-status.ts +11 -3
  482. package/src/sdk/protocol/operation-inventory.generated.json +272 -129
  483. package/src/sdk/protocol/operation-registry.ts +71 -8
  484. package/src/sdk/receipt-state.ts +43 -0
  485. package/src/sdk/reconciliation-extensions.ts +14 -0
  486. package/src/sdk/router/index.ts +1 -0
  487. package/src/sdk/router/session-router.ts +1658 -0
  488. package/src/sdk/session-list.ts +93 -0
  489. package/src/sdk/session-reconnect.ts +45 -1
  490. package/src/sdk/session.ts +716 -120
  491. package/src/sdk/transport/serve-cli.ts +18 -34
  492. package/src/session/account-inventory.ts +603 -0
  493. package/src/session/agent-session.ts +2873 -559
  494. package/src/session/agent-storage.ts +35 -0
  495. package/src/session/blob-store.ts +32 -1
  496. package/src/session/coordinator-tool-label.ts +40 -0
  497. package/src/session/internal/managed-session-scope.ts +4 -0
  498. package/src/session/internal/managed-session-storage.ts +199 -31
  499. package/src/session/messages.ts +1 -1
  500. package/src/session/secure-token-file.ts +80 -0
  501. package/src/session/session-manager.ts +757 -57
  502. package/src/session/session-storage.ts +25 -16
  503. package/src/session/startup-auth-config.ts +297 -0
  504. package/src/session/terminal-abort.ts +1253 -0
  505. package/src/session/yield-queue.ts +57 -15
  506. package/src/session-import/claude.ts +334 -0
  507. package/src/session-import/codex.ts +1033 -0
  508. package/src/session-import/command.ts +77 -0
  509. package/src/session-import/detect.ts +133 -0
  510. package/src/session-import/index.ts +7 -0
  511. package/src/session-import/provider-codex.ts +327 -0
  512. package/src/session-import/provider-service.ts +457 -0
  513. package/src/session-import/redact.ts +128 -0
  514. package/src/session-import/service.ts +1264 -0
  515. package/src/session-import/types.ts +148 -0
  516. package/src/setup/paseo/check.ts +213 -0
  517. package/src/setup/paseo/install-saga.ts +293 -0
  518. package/src/setup/paseo/json-publisher.ts +263 -0
  519. package/src/setup/paseo/orchestration-preferences.ts +86 -0
  520. package/src/setup/paseo/paseo-ownership.ts +224 -0
  521. package/src/setup/paseo/paseo-setup.ts +253 -0
  522. package/src/setup/paseo/provider-config.ts +139 -0
  523. package/src/setup/paseo/remove.ts +183 -0
  524. package/src/setup/paseo/result-types.ts +79 -0
  525. package/src/setup/paseo/setup-deps.ts +175 -0
  526. package/src/setup/paseo/skills-bridge.ts +260 -0
  527. package/src/skill-state/active-state.ts +21 -11
  528. package/src/slash-commands/acp-builtins.ts +9 -1
  529. package/src/slash-commands/builtin-registry.ts +117 -19
  530. package/src/slash-commands/helpers/credential-switch.ts +143 -0
  531. package/src/slash-commands/helpers/mcp.ts +9 -3
  532. package/src/slash-commands/helpers/usage-report.ts +61 -56
  533. package/src/slash-commands/types.ts +7 -2
  534. package/src/task/executor.ts +30 -11
  535. package/src/task/index.ts +66 -7
  536. package/src/task/render.ts +23 -9
  537. package/src/tools/ask-answer-registry.ts +23 -7
  538. package/src/tools/ask.ts +8 -4
  539. package/src/tools/bash-sleep-advisory.ts +115 -0
  540. package/src/tools/bash.ts +98 -18
  541. package/src/tools/browser/attach.ts +71 -3
  542. package/src/tools/browser/launch.ts +86 -13
  543. package/src/tools/browser/profile-discovery.ts +57 -7
  544. package/src/tools/browser/render.ts +8 -1
  545. package/src/tools/browser.ts +130 -21
  546. package/src/tools/computer.enforcement.test.ts +1 -1
  547. package/src/tools/computer.ts +3 -2
  548. package/src/tools/cron.ts +12 -1
  549. package/src/tools/image-gen.ts +349 -142
  550. package/src/tools/index.ts +8 -0
  551. package/src/tools/job.ts +33 -6
  552. package/src/tools/monitor.ts +41 -2
  553. package/src/tools/skill-discovery.ts +21 -29
  554. package/src/tools/subagent.ts +142 -24
  555. package/src/tools/todo-contract.ts +55 -3
  556. package/src/tools/todo-write.ts +4 -3
  557. package/src/tools/tool-catalog.generated.ts +6 -6
  558. package/src/tools/ultragoal-ask-guard.ts +10 -3
  559. package/src/utils/herdr-pane.ts +345 -0
  560. package/src/utils/title-generator.ts +2 -0
  561. package/src/web/scrapers/index.ts +6 -4
  562. package/dist/types/cli/malloc-env-guard.test.d.ts +0 -1
  563. package/dist/types/defaults/gjc-defaults.test.d.ts +0 -1
  564. package/dist/types/memory-backend/lazy-loading.test.d.ts +0 -1
  565. package/dist/types/runtime/boot-ordering.test.d.ts +0 -1
  566. package/dist/types/runtime/lazy-service.test.d.ts +0 -1
  567. package/dist/types/runtime/network-prewarm-service.test.d.ts +0 -1
  568. package/dist/types/runtime/workspace-tree-service.test.d.ts +0 -1
  569. package/dist/types/runtime-mcp/config.test.d.ts +0 -1
  570. package/dist/types/runtime-mcp/http.test.d.ts +0 -1
  571. package/dist/types/runtime-mcp/manager-pool.test.d.ts +0 -1
  572. package/dist/types/runtime-mcp/pool-key.test.d.ts +0 -1
  573. package/dist/types/runtime-mcp/pool.test.d.ts +0 -1
  574. package/dist/types/sdk/bus/lifecycle-control-runtime.d.ts +0 -117
  575. package/dist/types/sdk/bus/lifecycle-orchestrator.d.ts +0 -141
  576. package/dist/types/sdk/bus/telegram-cli.d.ts +0 -31
  577. package/dist/types/sdk/elevation/allowlist.d.ts +0 -20
  578. package/dist/types/sdk/elevation/audit.d.ts +0 -93
  579. package/dist/types/sdk/elevation/capability.d.ts +0 -3
  580. package/dist/types/sdk/elevation/digest.d.ts +0 -72
  581. package/dist/types/sdk/elevation/dispatch-receipt.d.ts +0 -85
  582. package/dist/types/sdk/elevation/grant-ledger.d.ts +0 -163
  583. package/dist/types/sdk/elevation/owner.d.ts +0 -48
  584. package/dist/types/sdk/host/import-graph.test.d.ts +0 -1
  585. package/dist/types/sdk/host/sdk-surface-parity.test.d.ts +0 -1
  586. package/dist/types/sdk/host/session-runtime.test.d.ts +0 -1
  587. package/dist/types/sdk/host/websocket-transport.lifecycle.test.d.ts +0 -1
  588. package/dist/types/session/auth-broker-config.d.ts +0 -13
  589. package/dist/types/session/heap-eviction-artifacts.test.d.ts +0 -1
  590. package/dist/types/skills/skills.test.d.ts +0 -1
  591. package/dist/types/slash-commands/notify-command.test.d.ts +0 -1
  592. package/dist/types/task/token-log.test.d.ts +0 -1
  593. package/dist/types/tools/computer.enforcement.test.d.ts +0 -1
  594. package/dist/types/tools/descriptors.test.d.ts +0 -1
  595. package/scripts/g005-daemon-smoke.ts +0 -180
  596. package/scripts/g011-daemon-path-smoke.ts +0 -153
  597. package/src/sdk/bus/lifecycle-control-runtime.ts +0 -1733
  598. package/src/sdk/bus/lifecycle-orchestrator.ts +0 -489
  599. package/src/sdk/bus/telegram-cli.ts +0 -212
  600. package/src/sdk/elevation/allowlist.ts +0 -54
  601. package/src/sdk/elevation/audit.ts +0 -208
  602. package/src/sdk/elevation/capability.ts +0 -41
  603. package/src/sdk/elevation/digest.ts +0 -129
  604. package/src/sdk/elevation/dispatch-receipt.ts +0 -184
  605. package/src/sdk/elevation/grant-ledger.ts +0 -1142
  606. package/src/sdk/elevation/owner.ts +0 -109
  607. package/src/session/auth-broker-config.ts +0 -109
  608. /package/dist/types/{ai-core-import-gate.test.d.ts → discovery/claude-hooks.d.ts} +0 -0
  609. /package/dist/types/{cli/fixture-report.test.d.ts → discovery/codex-hooks.d.ts} +0 -0
  610. /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. */
@@ -1336,25 +1355,32 @@ export class ManagedSessionDescendantStore {
1336
1355
  fsyncDirectory(this.#baseDir);
1337
1356
  return;
1338
1357
  }
1339
- if (outcome.reason === "destination_exists") {
1340
- const existing = captureManagedFilePrefixNoFollow(destination, REPLACEMENT_CLEANUP_RECEIPT_MAX_BYTES);
1341
- if (existing.identity.sha256 !== pending.identity.sha256)
1342
- throw new Error("managed_replace_cleanup_receipt_invalid");
1343
- const removed = nativeSessionStorage().exactUnlink(receiptPath, {
1344
- dev: pending.identity.dev,
1345
- ino: pending.identity.ino,
1346
- nlink: pending.identity.nlink,
1347
- parentDev: this.#subtreeRoot.dev,
1348
- parentIno: this.#subtreeRoot.ino,
1349
- size: BigInt(pending.identity.size),
1350
- mtimeNs: pending.identity.mtimeNs,
1351
- sha256: pending.identity.sha256,
1352
- quarantineName: `.gjc-receipt-pending-remove-${pending.identity.dev.toString(16)}-${pending.identity.ino.toString(16)}`,
1353
- });
1354
- if (!exactUnlinkCompleted(removed) && removed.code !== "not_found")
1355
- throw new Error(`managed_replace_receipt_cleanup_pending:${removed.code ?? "unknown"}`);
1356
- fsyncDirectory(this.#baseDir);
1357
- return;
1358
+ if (outcome.reason === "destination_exists" || outcome.reason === "invalid_request") {
1359
+ const captureIfPresent = (pathname: string): ManagedFileSnapshot | undefined => {
1360
+ try {
1361
+ return captureManagedFilePrefixNoFollow(pathname, REPLACEMENT_CLEANUP_RECEIPT_MAX_BYTES);
1362
+ } catch (error) {
1363
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") return undefined;
1364
+ throw error;
1365
+ }
1366
+ };
1367
+ const currentPending = captureIfPresent(receiptPath);
1368
+ const existing = captureIfPresent(destination);
1369
+ if (!currentPending && existing) {
1370
+ if (
1371
+ !sameReplacementIdentity(existing.identity, pending.identity) ||
1372
+ existing.identity.sha256 !== pending.identity.sha256
1373
+ )
1374
+ throw new Error("managed_replace_cleanup_receipt_invalid");
1375
+ fsyncDirectory(this.#baseDir);
1376
+ return;
1377
+ }
1378
+ if (currentPending && !existing) throw publishFailure(outcome);
1379
+ // Two names cannot both authoritatively represent the one receipt identity
1380
+ // encoded in the canonical filename. A byte-identical copy has a different
1381
+ // filesystem identity and would make the canonical receipt fail its next
1382
+ // reconciliation, while a hard link violates the single-link capture fence.
1383
+ throw new Error("managed_replace_cleanup_receipt_invalid");
1358
1384
  }
1359
1385
  throw publishFailure(outcome);
1360
1386
  }
@@ -1473,6 +1499,72 @@ export class ManagedSessionDescendantStore {
1473
1499
  this.#publishRetainedNoReplace(this.#relative(resolved), bytes);
1474
1500
  this.#assertBound();
1475
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
+ }
1476
1568
 
1477
1569
  async replace(relativePath: string, bytes: Uint8Array): Promise<void> {
1478
1570
  this.#beforeMutation();
@@ -1494,6 +1586,49 @@ export class ManagedSessionDescendantStore {
1494
1586
  this.#assertBound();
1495
1587
  }
1496
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
+
1497
1632
  replaceExpected(relativePath: string, bytes: Uint8Array, expected: ManagedFileSnapshot): void {
1498
1633
  this.#beforeMutation();
1499
1634
  this.#assertBound();
@@ -1601,6 +1736,24 @@ export class ManagedSessionDescendantStore {
1601
1736
  return managedAppendReceiptFromIdentity(managedFileIdentityFromNative(appended.identity));
1602
1737
  }
1603
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
+
1604
1757
  appendSync(relativePath: string, bytes: Uint8Array): ManagedAppendReceipt {
1605
1758
  this.#beforeMutation();
1606
1759
  this.#assertBound();
@@ -1608,7 +1761,13 @@ export class ManagedSessionDescendantStore {
1608
1761
  if (this.#authority) {
1609
1762
  const relative = this.#relative(resolved);
1610
1763
  const observed = this.#authority.stat(relative);
1611
- 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
+ }
1612
1771
  const nativeSha256 = observed.identity.sha256;
1613
1772
  const expectedSha256 =
1614
1773
  typeof nativeSha256 === "string" && /^[0-9a-f]{64}$/i.test(nativeSha256)
@@ -2884,6 +3043,15 @@ function replaceManagedFileGeneratedSync(
2884
3043
  identity: publishedReceiptIdentity,
2885
3044
  predecessor: expectedDestination,
2886
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.
2887
3055
  const replaced = nativeSessionStorage().exactReplacePath(
2888
3056
  staging,
2889
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
+ }