@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
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Provider-neutral session-import contract (issue #3709).
3
+ *
4
+ * An import accepts ONE explicit user-selected Codex or Claude transcript/export
5
+ * file, normalizes it into the intermediate representation below, and rebuilds a
6
+ * bounded, redacted continuation context inside a NEW GJC session. The source
7
+ * file is only ever read; provider process state is never scraped.
8
+ */
9
+
10
+ /** Providers with a first-party observable transcript/export format. */
11
+ export type SessionImportProviderId = "codex" | "claude";
12
+
13
+ /** Concrete on-disk format variants the adapters understand. */
14
+ export type SessionImportFormatId = "codex-rollout-jsonl" | "claude-code-jsonl" | "claude-export-json";
15
+
16
+ /** One normalized conversational unit produced by a provider adapter. */
17
+ export interface ImportedMessage {
18
+ /** Conversational role. Tool evidence is attached to assistant turns. */
19
+ role: "user" | "assistant";
20
+ /** Visible text (may be empty when only tool evidence exists). */
21
+ text: string;
22
+ /** ISO-8601 source timestamp when the record carried one. */
23
+ timestamp?: string;
24
+ /**
25
+ * Bounded, already redacted tool/file evidence lines (e.g. `$ ls` → `ok`).
26
+ * Rendered inline after the text so completed work stays visible.
27
+ */
28
+ toolEvidence?: string[];
29
+ }
30
+
31
+ /** Provider-neutral normalized conversation. */
32
+ export interface ImportedConversation {
33
+ provider: SessionImportProviderId;
34
+ format: SessionImportFormatId;
35
+ /** Source-side session/conversation identifier when the format carries one. */
36
+ sourceSessionId?: string;
37
+ /** Source title when the format carries one. */
38
+ title?: string;
39
+ /** Source workspace cwd when the format carries one. */
40
+ cwd?: string;
41
+ messages: ImportedMessage[];
42
+ }
43
+
44
+ /** Deterministic, actionable import failure codes. */
45
+ export type SessionImportErrorCode =
46
+ | "invalid_request"
47
+ | "source_not_found"
48
+ | "source_unreadable"
49
+ | "source_changed"
50
+ | "unsupported_format"
51
+ | "format_mismatch"
52
+ | "malformed_input"
53
+ | "content_too_large"
54
+ | "destination_conflict"
55
+ | "io_failed";
56
+
57
+ /** Import pipeline phase a failure belongs to. */
58
+ export type SessionImportPhase = "request" | "read" | "detect" | "parse" | "normalize" | "persist" | "switch";
59
+
60
+ export class SessionImportError extends Error {
61
+ readonly code: SessionImportErrorCode;
62
+ readonly phase: SessionImportPhase;
63
+ readonly retryable: boolean;
64
+ readonly limitBytes?: number;
65
+ readonly observedBytes?: number;
66
+
67
+ constructor(
68
+ code: SessionImportErrorCode,
69
+ phase: SessionImportPhase,
70
+ message: string,
71
+ options?: { retryable?: boolean; limitBytes?: number; observedBytes?: number },
72
+ ) {
73
+ super(message);
74
+ this.name = "SessionImportError";
75
+ this.code = code;
76
+ this.phase = phase;
77
+ this.retryable = options?.retryable ?? false;
78
+ this.limitBytes = options?.limitBytes;
79
+ this.observedBytes = options?.observedBytes;
80
+ }
81
+ }
82
+
83
+ /** One record the adapter could not map. Never carries raw content. */
84
+ export interface ImportQuarantineRecord {
85
+ /** 1-based record/line number in the source. */
86
+ record: number;
87
+ byteLength: number;
88
+ sha256: string;
89
+ reason: "invalid_json" | "unknown_record" | "missing_fields" | "oversized_record";
90
+ }
91
+
92
+ /** Bounded tallies reported to the user and persisted in provenance. */
93
+ export interface SessionImportCounts {
94
+ /** Records successfully mapped into the normalized conversation. */
95
+ mapped: number;
96
+ /** Records quarantined (never silently dropped). */
97
+ quarantined: number;
98
+ /** Secret/credential redactions applied to imported text. */
99
+ redacted: number;
100
+ /** Messages omitted from the rendered context by head/tail bounding. */
101
+ omitted: number;
102
+ }
103
+
104
+ /** Provenance persisted as a `custom` session entry on the import target. */
105
+ export interface SessionImportProvenance {
106
+ schemaVersion: 1;
107
+ customType: "session-import";
108
+ provider: SessionImportProviderId;
109
+ format: SessionImportFormatId;
110
+ /** Basename of the explicit user-selected source file (never a full path). */
111
+ sourceFileName: string;
112
+ sourceSessionId?: string;
113
+ sourceTitle?: string;
114
+ /** SHA-256 over the exact source bytes that were imported. */
115
+ sourceSha256: string;
116
+ sourceBytes: number;
117
+ /** RFC 4122 UUID of the GJC session that received the import. */
118
+ targetSessionId: string;
119
+ importedAt: string;
120
+ converterVersion: number;
121
+ sanitizerVersion: number;
122
+ counts: SessionImportCounts;
123
+ /** True when head/tail bounding elided part of the conversation. */
124
+ truncated: boolean;
125
+ quarantine: { present: boolean; truncated: boolean; records: ImportQuarantineRecord[] };
126
+ }
127
+
128
+ /** Fully prepared import: parsed, normalized, redacted, bounded. No session state mutated yet. */
129
+ export interface PreparedSessionImport {
130
+ conversation: ImportedConversation;
131
+ /** Rendered continuation context for the `custom_message` entry. */
132
+ contextText: string;
133
+ provenance: Omit<SessionImportProvenance, "targetSessionId" | "importedAt">;
134
+ counts: SessionImportCounts;
135
+ /** Distinct redaction pattern ids that fired (for the user-facing summary). */
136
+ redactionKinds: string[];
137
+ sourcePath: string;
138
+ sourceSha256: string;
139
+ sourceBytes: number;
140
+ }
141
+
142
+ /** Result of a completed import into a freshly created session file. */
143
+ export interface SessionImportCompleted {
144
+ targetSessionId: string;
145
+ targetPath: string;
146
+ title: string;
147
+ prepared: PreparedSessionImport;
148
+ }
@@ -0,0 +1,213 @@
1
+ /**
2
+ * Read-only diagnosis for `gjc setup paseo --check`.
3
+ *
4
+ * Two layers, deliberately separated:
5
+ *
6
+ * - L1 is everything GJC can observe on the filesystem. Any non-clean L1
7
+ * condition is `drift`, checked first and independent of the daemon.
8
+ * - L2 is a bounded probe of the Paseo daemon. It only runs when L1 is clean,
9
+ * and it partitions the remaining three states by its own outcome.
10
+ *
11
+ * That ordering is what makes the four states mutually exclusive: `pass`,
12
+ * `stale`, and `skipped` all require a clean L1 and are then distinguished
13
+ * solely by whether the daemon answered and whether it listed our entry. A
14
+ * daemon that is merely down can never produce `drift`.
15
+ *
16
+ * This module never writes. `stale` in particular must not restart anything --
17
+ * Paseo has no reload verb and its own skill forbids restarting without
18
+ * explicit user approval, which is exactly why `stale` exists as a state.
19
+ */
20
+ import * as fs from "node:fs/promises";
21
+ import { recoverIntent } from "./install-saga";
22
+ import { PaseoPublishError, readTarget } from "./json-publisher";
23
+ import { createOrchestrationSeed } from "./orchestration-preferences";
24
+ import { readIntent } from "./paseo-ownership";
25
+ import { buildProviderEntry, hasProviderConflict, providerKeyFor, resolveGjcCommand } from "./provider-config";
26
+ import type { DriftReason, SetupCheckResult } from "./result-types";
27
+ import { INSTALL_SKILL_NAMES, type PaseoSetupDependencies } from "./setup-deps";
28
+ import { scanSkillsBridgeDrift } from "./skills-bridge";
29
+
30
+ const PROBE_TIMEOUT_MS = 5_000;
31
+
32
+ export const STALE_GUIDANCE =
33
+ "Paseo has not picked up the new provider entry yet. Paseo does not reload config.json automatically; restart the Paseo daemon yourself when convenient (GJC will not restart it for you).";
34
+
35
+ export interface CheckOptions {
36
+ readonly mpreset?: string;
37
+ readonly force?: boolean;
38
+ }
39
+
40
+ /** Collect every L1 (filesystem) observation without touching the daemon. */
41
+ async function collectL1(deps: PaseoSetupDependencies, options: CheckOptions): Promise<DriftReason[]> {
42
+ const reasons: DriftReason[] = [];
43
+ const providerKey = providerKeyFor(options.mpreset);
44
+
45
+ // An interrupted earlier run leaves a durable intent. Report it, never repair
46
+ // it here -- `--check` is read-only.
47
+ const intent = await readIntent(deps.paths.intentRecord);
48
+ if (intent) {
49
+ // `repair: false` keeps this read-only; the intent is reported, never settled.
50
+ const recovery = await recoverIntent(deps.paths.intentRecord, { repair: false });
51
+ if (recovery) {
52
+ reasons.push({
53
+ code: "partial-install",
54
+ subject: deps.paths.intentRecord,
55
+ detail: recovery.detail,
56
+ });
57
+ }
58
+ }
59
+
60
+ const resolution = resolveGjcCommand();
61
+ if (!resolution.ok) {
62
+ reasons.push({ code: "missing-executable", subject: "command[0]", detail: resolution.detail });
63
+ }
64
+
65
+ let configParsed: Record<string, unknown> | undefined;
66
+ try {
67
+ const config = await readTarget(deps.paths.configJson);
68
+ configParsed = config.parsed;
69
+ } catch (error) {
70
+ if (error instanceof PaseoPublishError && error.refusal.reason !== "cas-conflict") {
71
+ reasons.push({
72
+ code: error.refusal.reason === "parse-refusal" ? "parse-refusal" : "format-drift",
73
+ subject: deps.paths.configJson,
74
+ detail: error.message,
75
+ });
76
+ } else {
77
+ throw error;
78
+ }
79
+ }
80
+
81
+ if (configParsed) {
82
+ const providers = readProviders(configParsed);
83
+ const existing = providers?.[providerKey];
84
+ if (existing === undefined) {
85
+ reasons.push({
86
+ code: "missing-provider-entry",
87
+ subject: `agents.providers.${providerKey}`,
88
+ detail: "GJC is not registered as a Paseo provider",
89
+ });
90
+ } else if (resolution.ok) {
91
+ const desired = buildProviderEntry(resolution.command, options.mpreset);
92
+ const conflict = hasProviderConflict(configParsed, providerKey, desired);
93
+ if (conflict.conflict && !options.force) {
94
+ reasons.push({
95
+ code: "owned-key-conflict",
96
+ subject: conflict.subject,
97
+ detail: `${conflict.detail} Re-run with --force to overwrite it.`,
98
+ });
99
+ }
100
+ }
101
+ }
102
+
103
+ // AC-14 is about what the provider file actually records, not about what we
104
+ // would write today: a stale entry pointing at a deleted binary is exactly the
105
+ // case worth reporting, and it must surface even under --force.
106
+ if (configParsed) {
107
+ const recorded = readProviders(configParsed)?.[providerKey];
108
+ const command =
109
+ recorded && typeof recorded === "object" ? (recorded as { command?: unknown }).command : undefined;
110
+ const executable = Array.isArray(command) && typeof command[0] === "string" ? command[0] : undefined;
111
+ if (executable !== undefined && !(await isExecutable(executable))) {
112
+ reasons.push({
113
+ code: "missing-executable",
114
+ subject: executable,
115
+ detail: "the provider entry records a command that is missing or not executable",
116
+ });
117
+ }
118
+ }
119
+
120
+ try {
121
+ const preferences = await readTarget(deps.paths.orchestrationPreferences);
122
+ const seed = createOrchestrationSeed(preferences.parsed);
123
+ if (seed.seededKeys.length > 0) {
124
+ reasons.push({
125
+ code: "unseeded-orchestration-role",
126
+ subject: deps.paths.orchestrationPreferences,
127
+ detail: `orchestration roles still unset: ${seed.seededKeys.join(", ")}`,
128
+ });
129
+ }
130
+ } catch (error) {
131
+ if (error instanceof PaseoPublishError && error.refusal.reason !== "cas-conflict") {
132
+ reasons.push({
133
+ code: error.refusal.reason === "parse-refusal" ? "parse-refusal" : "format-drift",
134
+ subject: deps.paths.orchestrationPreferences,
135
+ detail: error.message,
136
+ });
137
+ } else {
138
+ throw error;
139
+ }
140
+ }
141
+
142
+ for (const name of INSTALL_SKILL_NAMES) {
143
+ const link = `${deps.paths.bridgeDir}/${name}`;
144
+ const linked = await fs
145
+ .lstat(link)
146
+ .then(stat => stat.isSymbolicLink())
147
+ .catch(() => false);
148
+ if (!linked) {
149
+ reasons.push({ code: "missing-bridge-link", subject: link, detail: "bridge symlink is missing" });
150
+ }
151
+ }
152
+
153
+ reasons.push(...(await scanSkillsBridgeDrift(deps)));
154
+ return reasons;
155
+ }
156
+
157
+ function readProviders(config: Record<string, unknown>): Record<string, unknown> | undefined {
158
+ const agents = config.agents;
159
+ if (!agents || typeof agents !== "object" || Array.isArray(agents)) return undefined;
160
+ const providers = (agents as Record<string, unknown>).providers;
161
+ if (!providers || typeof providers !== "object" || Array.isArray(providers)) return undefined;
162
+ return providers as Record<string, unknown>;
163
+ }
164
+
165
+ async function isExecutable(candidate: string): Promise<boolean> {
166
+ try {
167
+ await fs.access(candidate, fs.constants.X_OK);
168
+ return true;
169
+ } catch {
170
+ return false;
171
+ }
172
+ }
173
+
174
+ /**
175
+ * Diagnose the installation.
176
+ *
177
+ * Precedence is total and the predicates are disjoint by construction:
178
+ * drift absorbs every non-clean L1 condition, and the remaining three states
179
+ * partition the L2 outcome space (reachable-with-entry / reachable-without-entry
180
+ * / unreachable).
181
+ */
182
+ export async function checkPaseoSetup(
183
+ deps: PaseoSetupDependencies,
184
+ options: CheckOptions = {},
185
+ ): Promise<SetupCheckResult> {
186
+ const reasons = await collectL1(deps, options);
187
+ if (reasons.length > 0) return { component: "paseo", status: "drift", reasons };
188
+
189
+ const outcome = await deps.runProviderLs(PROBE_TIMEOUT_MS);
190
+ if (outcome.kind !== "ok") {
191
+ // The daemon being down, slow, or speaking an unexpected dialect says
192
+ // nothing about whether our files are correct -- and L1 already proved
193
+ // they are. Reporting drift here would blame GJC for Paseo being asleep.
194
+ return { component: "paseo", status: "skipped", reasons: [] };
195
+ }
196
+
197
+ const providerKey = providerKeyFor(options.mpreset);
198
+ const row = outcome.rows.find(candidate => candidate.id === providerKey);
199
+ if (!row) return { component: "paseo", status: "stale", reasons: [], guidance: STALE_GUIDANCE };
200
+
201
+ // Paseo listing the provider is not the same as Paseo being able to use it.
202
+ // Reporting `pass` for a row it marks unavailable would claim a working
203
+ // integration the user does not have.
204
+ if (row.status !== undefined && row.status !== "available") {
205
+ return {
206
+ component: "paseo",
207
+ status: "stale",
208
+ reasons: [],
209
+ guidance: `Paseo knows about the GJC provider but reports it as "${row.status}". ${STALE_GUIDANCE}`,
210
+ };
211
+ }
212
+ return { component: "paseo", status: "pass", reasons: [] };
213
+ }
@@ -0,0 +1,293 @@
1
+ /**
2
+ * Four-step install saga with reverse-order compensation.
3
+ *
4
+ * GJC writes to four files it does not own, across two applications, with no
5
+ * distributed lock available. Nothing here can be made atomic across files, so
6
+ * the design is instead: refuse early, record enough to recover, and undo in
7
+ * reverse on failure.
8
+ *
9
+ * Forward order is fixed:
10
+ * 1. `~/.paseo/config.json` provider entry + provider-key provenance
11
+ * 2. `~/.paseo/orchestration-preferences.json` seeded roles + seeded-key provenance
12
+ * 3. `<agentDir>/paseo-skills/` symlink bridge
13
+ * 4. `~/.gjc/agent/config.yml` `skills.customDirectories` append
14
+ *
15
+ * Steps 1 and 2 each mutate a Paseo file AND the GJC provenance ledger. Those
16
+ * are separate files, so a durable intent record is written BEFORE either one,
17
+ * carrying preflight and expected-post identities for BOTH. Recovery classifies
18
+ * each file independently and refuses whenever the ledger diverged.
19
+ */
20
+ import type { CasReceipt } from "../../config/atomic-yaml-patch";
21
+ import { currentIdentity, hashBytes, planPublish, publishPlan, readTarget } from "./json-publisher";
22
+ import {
23
+ classifyIntent,
24
+ clearIntent,
25
+ INTENT_VERSION,
26
+ type IntentRecord,
27
+ type IntentStep,
28
+ type ProvenanceLedger,
29
+ pendingLedgerOf,
30
+ readIntent,
31
+ readProvenance,
32
+ writeIntent,
33
+ writeProvenance,
34
+ } from "./paseo-ownership";
35
+ import type { PartialInstallEvidence } from "./result-types";
36
+
37
+ /** One completed forward step, retaining exactly what its inverse needs. */
38
+ export interface CompletedStep {
39
+ readonly label: string;
40
+ /** Undo this step. Resolves to `"reverted"`, or `"conflict"` when the resource moved underneath us. */
41
+ undo(): Promise<StepUndoResult>;
42
+ }
43
+
44
+ export type StepUndoResult =
45
+ | { readonly status: "reverted" }
46
+ | { readonly status: "conflict"; readonly detail: string; readonly retained: readonly string[] };
47
+
48
+ export class SagaStepError extends Error {
49
+ readonly label: string;
50
+ readonly retained: readonly string[];
51
+
52
+ constructor(label: string, message: string, retained: readonly string[] = []) {
53
+ super(message);
54
+ this.name = "SagaStepError";
55
+ this.label = label;
56
+ this.retained = retained;
57
+ }
58
+ }
59
+
60
+ export interface CompensationOutcome {
61
+ readonly compensated: readonly string[];
62
+ readonly uncompensated: readonly string[];
63
+ readonly evidence: PartialInstallEvidence;
64
+ }
65
+
66
+ /**
67
+ * Undo completed steps newest-first, halting at the first inverse that reports
68
+ * a conflict.
69
+ *
70
+ * Halting is deliberate: once one resource has diverged, continuing to unwind
71
+ * the others would leave a stranger mix of reverted and live state that no
72
+ * later run could interpret. Stopping preserves an interpretable prefix.
73
+ */
74
+ export async function compensate(
75
+ completed: readonly CompletedStep[],
76
+ failure: SagaStepError,
77
+ ): Promise<CompensationOutcome> {
78
+ const compensated: string[] = [];
79
+ const uncompensated: string[] = [];
80
+ const retained = [...failure.retained];
81
+ let conflictDetail: string | undefined;
82
+
83
+ for (let index = completed.length - 1; index >= 0; index--) {
84
+ const step = completed[index]!;
85
+ if (conflictDetail !== undefined) {
86
+ uncompensated.push(step.label);
87
+ continue;
88
+ }
89
+ const result = await step.undo();
90
+ if (result.status === "reverted") {
91
+ compensated.push(step.label);
92
+ continue;
93
+ }
94
+ conflictDetail = result.detail;
95
+ uncompensated.push(step.label);
96
+ retained.push(...result.retained);
97
+ }
98
+
99
+ return {
100
+ compensated,
101
+ uncompensated,
102
+ evidence: {
103
+ failedStep: failure.label,
104
+ detail: conflictDetail ? `${failure.message}; compensation halted: ${conflictDetail}` : failure.message,
105
+ retained: [...new Set(retained)],
106
+ },
107
+ };
108
+ }
109
+
110
+ export interface JsonStepInput {
111
+ readonly label: string;
112
+ readonly step: IntentStep;
113
+ readonly targetPath: string;
114
+ readonly provenancePath: string;
115
+ readonly intentPath: string;
116
+ readonly ownedKeys: readonly string[];
117
+ /** Mutates the parsed target in place. */
118
+ readonly mutate: (draft: Record<string, unknown>) => void;
119
+ /** Produces the ledger that must exist once this step commits. */
120
+ readonly nextLedger: (ledger: ProvenanceLedger) => ProvenanceLedger;
121
+ /** Reverts the target, removing only what this step added. */
122
+ readonly revert: (draft: Record<string, unknown>) => void;
123
+ /** Produces the ledger that must exist once this step is undone. */
124
+ readonly revertLedger: (ledger: ProvenanceLedger) => ProvenanceLedger;
125
+ readonly now: Date;
126
+ }
127
+
128
+ export interface JsonStepOutput {
129
+ readonly completed: CompletedStep;
130
+ readonly changed: boolean;
131
+ readonly backupPath?: string;
132
+ }
133
+
134
+ /**
135
+ * Run one JSON step: intent, target publish, ledger commit, intent clear.
136
+ *
137
+ * The intent is written first and cleared last. Between those points a crash is
138
+ * recoverable because the record alone identifies whether the target carries
139
+ * pre-write bytes, the exact bytes we intended, or something a third party
140
+ * produced.
141
+ */
142
+ export async function runJsonStep(input: JsonStepInput): Promise<JsonStepOutput> {
143
+ const current = await readTarget(input.targetPath);
144
+ const plan = planPublish(current, input.mutate);
145
+
146
+ const ledgerBefore = await readProvenance(input.provenancePath);
147
+ const ledgerAfter = input.nextLedger(ledgerBefore);
148
+ const provenancePreflightIdentity = await currentIdentity(input.provenancePath);
149
+ const provenanceExpectedIdentity = ledgerIdentity(ledgerAfter);
150
+
151
+ if (plan.unchanged && provenancePreflightIdentity === provenanceExpectedIdentity) {
152
+ return { completed: { label: input.label, undo: async () => ({ status: "reverted" }) }, changed: false };
153
+ }
154
+
155
+ const intent: IntentRecord = {
156
+ version: INTENT_VERSION,
157
+ step: input.step,
158
+ targetPath: input.targetPath,
159
+ ownedKeys: input.ownedKeys,
160
+ targetPreflightIdentity: current.identity,
161
+ targetExpectedIdentity: plan.expectedIdentity,
162
+ provenancePath: input.provenancePath,
163
+ provenancePreflightIdentity,
164
+ provenanceExpectedIdentity,
165
+ provenancePayload: ledgerAfter,
166
+ startedAt: input.now.toISOString(),
167
+ };
168
+ await writeIntent(input.intentPath, intent);
169
+
170
+ let backupPath: string | undefined;
171
+ try {
172
+ const published = await publishPlan(input.targetPath, plan, {
173
+ expectedIdentity: current.identity,
174
+ backup: true,
175
+ now: input.now,
176
+ });
177
+ backupPath = published.backupPath;
178
+ await writeProvenance(input.provenancePath, ledgerAfter);
179
+ } catch (error) {
180
+ throw new SagaStepError(input.label, error instanceof Error ? error.message : String(error), [
181
+ input.intentPath,
182
+ ...(backupPath ? [backupPath] : []),
183
+ ]);
184
+ }
185
+ await clearIntent(input.intentPath);
186
+
187
+ const successIdentity = plan.expectedIdentity;
188
+ return {
189
+ completed: {
190
+ label: input.label,
191
+ undo: async (): Promise<StepUndoResult> => {
192
+ const observed = await currentIdentity(input.targetPath);
193
+ if (observed !== successIdentity) {
194
+ return {
195
+ status: "conflict",
196
+ detail: `${input.targetPath} changed after GJC wrote it; GJC will not overwrite the newer contents`,
197
+ retained: [input.provenancePath, ...(backupPath ? [backupPath] : [])],
198
+ };
199
+ }
200
+ const now = await readTarget(input.targetPath);
201
+ const revertPlan = planPublish(now, input.revert);
202
+ await publishPlan(input.targetPath, revertPlan, {
203
+ expectedIdentity: now.identity,
204
+ backup: false,
205
+ now: input.now,
206
+ });
207
+ await writeProvenance(input.provenancePath, input.revertLedger(await readProvenance(input.provenancePath)));
208
+ return { status: "reverted" };
209
+ },
210
+ },
211
+ changed: true,
212
+ backupPath,
213
+ };
214
+ }
215
+
216
+ /** Hash a ledger exactly as it will be serialized, so the expected identity is computable up front. */
217
+ function ledgerIdentity(ledger: ProvenanceLedger): string {
218
+ return hashBytes(`${JSON.stringify(ledger, null, 2)}\n`);
219
+ }
220
+
221
+ /** Wrap a `CasReceipt` as a compensable step. */
222
+ export function receiptStep(label: string, receipt: CasReceipt): CompletedStep {
223
+ return {
224
+ label,
225
+ undo: async (): Promise<StepUndoResult> => {
226
+ const restored = await receipt.restore();
227
+ if (restored.status === "restored" || restored.status === "discarded") return { status: "reverted" };
228
+ if (restored.status === "conflict") {
229
+ return {
230
+ status: "conflict",
231
+ detail: `config.yml changed at ${restored.paths.join(", ")} since GJC appended to it`,
232
+ retained: [],
233
+ };
234
+ }
235
+ return { status: "conflict", detail: "the config.yml change is not restorable", retained: [] };
236
+ },
237
+ };
238
+ }
239
+
240
+ export interface RecoverIntentOptions {
241
+ /**
242
+ * Act on the classification rather than only reporting it.
243
+ *
244
+ * Install passes `true`. `--check` passes `false` because it must stay
245
+ * read-only: it surfaces the lingering intent as drift and leaves the repair
246
+ * to the next install.
247
+ */
248
+ readonly repair: boolean;
249
+ }
250
+
251
+ /**
252
+ * Classify a lingering intent left by an interrupted run, and optionally act.
253
+ *
254
+ * The outcome comes from classifying BOTH the target and the ledger:
255
+ *
256
+ * - `discard` the publish never landed, so nothing was mutated. Safe to clear.
257
+ * - `complete-ledger` the publish landed but the ledger commit did not. Re-running
258
+ * the same install re-derives and commits the identical provenance in step 1,
259
+ * so recovery is to PROCEED. The intent is deliberately left in place until
260
+ * that step overwrites it, because clearing it first would lose recoverability
261
+ * if the retry is interrupted too.
262
+ * - `refuse` a third party changed one of the files. Never replay a recorded
263
+ * write over someone else's change.
264
+ */
265
+ export async function recoverIntent(
266
+ intentPath: string,
267
+ options: RecoverIntentOptions = { repair: false },
268
+ ): Promise<{ recovered: boolean; detail: string } | undefined> {
269
+ const intent = await readIntent(intentPath);
270
+ if (!intent) return undefined;
271
+ const recovery = await classifyIntent(intent);
272
+ if (recovery.action === "refuse") return { recovered: false, detail: recovery.detail };
273
+ if (!options.repair) return { recovered: false, detail: recovery.detail };
274
+ if (recovery.action === "discard") {
275
+ await clearIntent(intentPath);
276
+ return { recovered: true, detail: recovery.detail };
277
+ }
278
+
279
+ // complete-ledger: the publish landed, the ledger commit did not. Finish it
280
+ // from the intent's own payload rather than relying on a retry to re-run the
281
+ // step -- a seed-if-empty step would be skipped on retry, because its own
282
+ // publish already filled the roles it was gated on.
283
+ const pending = pendingLedgerOf(intent);
284
+ if (!pending) {
285
+ return {
286
+ recovered: false,
287
+ detail: `${recovery.detail}, but the interrupted step recorded no ledger payload to finish`,
288
+ };
289
+ }
290
+ await writeProvenance(intent.provenancePath, pending);
291
+ await clearIntent(intentPath);
292
+ return { recovered: true, detail: `${recovery.detail}; provenance recorded` };
293
+ }