@gajae-code/coding-agent 0.13.3 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (599) hide show
  1. package/CHANGELOG.md +184 -2
  2. package/README.md +2 -0
  3. package/bin/gajaessi.js +4 -0
  4. package/dist/types/async/job-manager.d.ts +55 -2
  5. package/dist/types/async/support.d.ts +14 -0
  6. package/dist/types/capability/mcp.d.ts +6 -0
  7. package/dist/types/capability/types.d.ts +6 -0
  8. package/dist/types/cli/accounts-cli.d.ts +19 -0
  9. package/dist/types/cli/args.d.ts +3 -0
  10. package/dist/types/cli/config-cli.d.ts +6 -0
  11. package/dist/types/cli/crash-cli.d.ts +10 -0
  12. package/dist/types/cli/customize-doctor.d.ts +145 -0
  13. package/dist/types/cli/daemon-cli.d.ts +3 -1
  14. package/dist/types/cli/mcp-cli.d.ts +11 -0
  15. package/dist/types/cli/notify-cli.d.ts +1 -1
  16. package/dist/types/cli/root-flags.d.ts +12 -0
  17. package/dist/types/cli/setup-cli.d.ts +3 -1
  18. package/dist/types/cli/skills-cli.d.ts +2 -1
  19. package/dist/types/cli/update-cli.d.ts +19 -1
  20. package/dist/types/cli.d.ts +6 -0
  21. package/dist/types/commands/accounts.d.ts +40 -0
  22. package/dist/types/commands/crash.d.ts +24 -0
  23. package/dist/types/commands/customize.d.ts +22 -0
  24. package/dist/types/commands/daemon.d.ts +1 -1
  25. package/dist/types/commands/launch.d.ts +6 -0
  26. package/dist/types/commands/setup.d.ts +6 -0
  27. package/dist/types/commands/skills.d.ts +6 -1
  28. package/dist/types/commands/update.d.ts +7 -0
  29. package/dist/types/config/atomic-yaml-patch-worker.d.ts +25 -0
  30. package/dist/types/config/atomic-yaml-patch.d.ts +62 -2
  31. package/dist/types/config/config-schema-version.d.ts +10 -0
  32. package/dist/types/config/file-lock.d.ts +18 -0
  33. package/dist/types/config/model-profile-activation.d.ts +3 -1
  34. package/dist/types/config/model-registry.d.ts +9 -1
  35. package/dist/types/config/models-config-schema.d.ts +2 -0
  36. package/dist/types/config/settings-schema.d.ts +70 -6
  37. package/dist/types/config/settings.d.ts +63 -0
  38. package/dist/types/config/skill-settings-defaults.d.ts +26 -0
  39. package/dist/types/config/task-delegation.d.ts +39 -0
  40. package/dist/types/config/update-channel.d.ts +10 -0
  41. package/dist/types/coordinator-mcp/server.d.ts +5 -1
  42. package/dist/types/crash/index-store.d.ts +87 -0
  43. package/dist/types/crash/nudge.d.ts +50 -0
  44. package/dist/types/crash/record-loader.d.ts +17 -0
  45. package/dist/types/crash/report.d.ts +134 -0
  46. package/dist/types/crash/sanitize.d.ts +25 -0
  47. package/dist/types/cursor.d.ts +13 -2
  48. package/dist/types/customization/import.d.ts +37 -0
  49. package/dist/types/customization/index.d.ts +4 -0
  50. package/dist/types/customization/inventory.d.ts +25 -0
  51. package/dist/types/customization/mutations.d.ts +32 -0
  52. package/dist/types/customization/types.d.ts +115 -0
  53. package/dist/types/daemon/control-types.d.ts +8 -1
  54. package/dist/types/daemon/operator-contract.d.ts +4 -4
  55. package/dist/types/discovery/claude.d.ts +39 -1
  56. package/dist/types/discovery/codex.d.ts +39 -1
  57. package/dist/types/discovery/index.d.ts +2 -0
  58. package/dist/types/discovery/mcp-compat.d.ts +30 -0
  59. package/dist/types/edit/renderer.d.ts +23 -0
  60. package/dist/types/extensibility/extensions/runner.d.ts +3 -0
  61. package/dist/types/extensibility/extensions/types.d.ts +21 -4
  62. package/dist/types/extensibility/gjc-plugins/observability.d.ts +6 -1
  63. package/dist/types/extensibility/gjc-plugins/registry.d.ts +8 -1
  64. package/dist/types/extensibility/hooks/loader.d.ts +19 -5
  65. package/dist/types/extensibility/runtime-skill-discovery.d.ts +22 -1
  66. package/dist/types/extensibility/skill-management.d.ts +107 -0
  67. package/dist/types/gjc-runtime/deep-interview-runtime.d.ts +3 -1
  68. package/dist/types/gjc-runtime/launch-worktree.d.ts +8 -0
  69. package/dist/types/gjc-runtime/linux-proc.d.ts +3 -0
  70. package/dist/types/gjc-runtime/ralplan-runtime.d.ts +10 -6
  71. package/dist/types/gjc-runtime/session-state-lock.d.ts +104 -0
  72. package/dist/types/gjc-runtime/session-state-sidecar.d.ts +120 -2
  73. package/dist/types/gjc-runtime/state-writer.d.ts +10 -1
  74. package/dist/types/gjc-runtime/ultragoal-guard.d.ts +4 -2
  75. package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +8 -6
  76. package/dist/types/gjc-runtime/workflow-settings.d.ts +109 -0
  77. package/dist/types/hooks/events.d.ts +60 -0
  78. package/dist/types/hooks/normalize.d.ts +83 -0
  79. package/dist/types/hooks/skill-state.d.ts +9 -2
  80. package/dist/types/main.d.ts +1 -1
  81. package/dist/types/modes/acp/abort-scope.d.ts +13 -0
  82. package/dist/types/modes/acp/acp-agent.d.ts +7 -4
  83. package/dist/types/modes/components/customization/customization-dashboard.d.ts +44 -0
  84. package/dist/types/modes/components/customization/import-wizard.d.ts +21 -0
  85. package/dist/types/modes/components/customization/index.d.ts +1 -0
  86. package/dist/types/modes/components/gajae-pet-widget.d.ts +8 -30
  87. package/dist/types/modes/components/irc-sidebar.d.ts +1 -0
  88. package/dist/types/modes/components/iterm-pet-transport.d.ts +122 -0
  89. package/dist/types/modes/components/oauth-selector.d.ts +10 -4
  90. package/dist/types/modes/components/pet-capability.d.ts +11 -25
  91. package/dist/types/modes/components/status-line/gh.d.ts +6 -2
  92. package/dist/types/modes/controllers/extension-ui-controller.d.ts +1 -1
  93. package/dist/types/modes/controllers/selector-controller.d.ts +7 -8
  94. package/dist/types/modes/controllers/stt-controller.d.ts +1 -1
  95. package/dist/types/modes/interactive-mode.d.ts +1 -0
  96. package/dist/types/modes/types.d.ts +1 -0
  97. package/dist/types/modes/utils/injected-user-submission.d.ts +10 -0
  98. package/dist/types/runtime-mcp/config.d.ts +9 -0
  99. package/dist/types/runtime-mcp/manager.d.ts +26 -1
  100. package/dist/types/runtime-mcp/oauth-discovery.d.ts +4 -0
  101. package/dist/types/runtime-mcp/oauth-flow.d.ts +24 -1
  102. package/dist/types/runtime-mcp/pool-key.d.ts +2 -0
  103. package/dist/types/runtime-mcp/protocol.d.ts +278 -0
  104. package/dist/types/runtime-mcp/scope-config.d.ts +29 -0
  105. package/dist/types/runtime-mcp/tool-bridge.d.ts +15 -13
  106. package/dist/types/runtime-mcp/transports/http.d.ts +9 -0
  107. package/dist/types/runtime-mcp/types.d.ts +102 -10
  108. package/dist/types/sdk/acp/adapter.d.ts +26 -5
  109. package/dist/types/sdk/broker/broker.d.ts +3 -55
  110. package/dist/types/sdk/broker/lifecycle.d.ts +18 -12
  111. package/dist/types/sdk/broker/session-index.d.ts +14 -5
  112. package/dist/types/sdk/broker/startup-failure.d.ts +16 -1
  113. package/dist/types/sdk/bus/chat-daemon-control.d.ts +51 -1
  114. package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +4 -41
  115. package/dist/types/sdk/bus/config.d.ts +11 -0
  116. package/dist/types/sdk/bus/conversation-store.d.ts +0 -1
  117. package/dist/types/sdk/bus/daemon-paths.d.ts +6 -0
  118. package/dist/types/sdk/bus/discord-conversation.d.ts +2 -0
  119. package/dist/types/sdk/bus/discord-daemon.d.ts +17 -12
  120. package/dist/types/sdk/bus/existing-thread-readiness.d.ts +4 -34
  121. package/dist/types/sdk/bus/inbound-reaction-ordering.d.ts +61 -0
  122. package/dist/types/sdk/bus/index.d.ts +85 -99
  123. package/dist/types/sdk/bus/kind-aware-reconciliation.d.ts +29 -7
  124. package/dist/types/sdk/bus/managed-daemon.d.ts +2 -32
  125. package/dist/types/sdk/bus/notification-service.d.ts +52 -0
  126. package/dist/types/sdk/bus/operator-runtime.d.ts +1 -1
  127. package/dist/types/sdk/bus/prompt-reconciliation.d.ts +16 -5
  128. package/dist/types/sdk/bus/reconciliation-store.d.ts +113 -5
  129. package/dist/types/sdk/bus/session-control.d.ts +25 -1
  130. package/dist/types/sdk/bus/slack-conversation.d.ts +4 -0
  131. package/dist/types/sdk/bus/slack-daemon.d.ts +9 -17
  132. package/dist/types/sdk/bus/slack-live-provider.d.ts +3 -1
  133. package/dist/types/sdk/bus/slack-provider.d.ts +4 -0
  134. package/dist/types/sdk/bus/slack-thread-binding.d.ts +6 -40
  135. package/dist/types/sdk/bus/telegram-adoption-intent.d.ts +30 -104
  136. package/dist/types/sdk/bus/telegram-daemon-cli.d.ts +10 -0
  137. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +262 -19
  138. package/dist/types/sdk/bus/telegram-daemon-orphan-reap.d.ts +125 -0
  139. package/dist/types/sdk/bus/telegram-daemon-owner-registry.d.ts +22 -0
  140. package/dist/types/sdk/bus/telegram-daemon.d.ts +119 -310
  141. package/dist/types/sdk/bus/telegram-reference.d.ts +1 -47
  142. package/dist/types/sdk/bus/threaded-render.d.ts +1 -0
  143. package/dist/types/sdk/bus/topic-registry.d.ts +33 -17
  144. package/dist/types/sdk/cli/rows.d.ts +2 -11
  145. package/dist/types/sdk/cli/session-cli.d.ts +15 -25
  146. package/dist/types/sdk/client/client.d.ts +97 -1
  147. package/dist/types/sdk/host/control/dispatch.d.ts +0 -7
  148. package/dist/types/sdk/host/control/index.d.ts +1 -1
  149. package/dist/types/sdk/host/control/operations.d.ts +18 -5
  150. package/dist/types/sdk/host/control/runtime-gate.d.ts +19 -0
  151. package/dist/types/sdk/host/host.d.ts +15 -1
  152. package/dist/types/sdk/host/query/handlers.d.ts +5 -0
  153. package/dist/types/sdk/host/reverse-leases.d.ts +1 -1
  154. package/dist/types/sdk/host/session-runtime.d.ts +127 -7
  155. package/dist/types/sdk/host/types.d.ts +1 -1
  156. package/dist/types/sdk/host/websocket-transport.d.ts +1 -1
  157. package/dist/types/sdk/index.d.ts +2 -1
  158. package/dist/types/sdk/lifecycle/broker-client.d.ts +8 -0
  159. package/dist/types/sdk/lifecycle/client.d.ts +59 -0
  160. package/dist/types/sdk/lifecycle/index.d.ts +3 -0
  161. package/dist/types/sdk/lifecycle/service.d.ts +232 -0
  162. package/dist/types/sdk/mcp/server.d.ts +9 -6
  163. package/dist/types/sdk/prompt-deadline-lease.d.ts +43 -0
  164. package/dist/types/sdk/prompt-deadline-manager.d.ts +28 -0
  165. package/dist/types/sdk/prompt-status.d.ts +10 -3
  166. package/dist/types/sdk/protocol/operation-registry.d.ts +5 -0
  167. package/dist/types/sdk/receipt-state.d.ts +17 -0
  168. package/dist/types/sdk/reconciliation-extensions.d.ts +2 -0
  169. package/dist/types/sdk/router/index.d.ts +1 -0
  170. package/dist/types/sdk/router/session-router.d.ts +152 -0
  171. package/dist/types/sdk/session-list.d.ts +22 -0
  172. package/dist/types/sdk/session-reconnect.d.ts +43 -1
  173. package/dist/types/sdk/session.d.ts +34 -1
  174. package/dist/types/sdk/transport/serve-cli.d.ts +1 -4
  175. package/dist/types/session/account-inventory.d.ts +86 -0
  176. package/dist/types/session/agent-session.d.ts +145 -6
  177. package/dist/types/session/agent-storage.d.ts +10 -0
  178. package/dist/types/session/coordinator-tool-label.d.ts +28 -0
  179. package/dist/types/session/internal/managed-session-storage.d.ts +23 -4
  180. package/dist/types/session/messages.d.ts +1 -1
  181. package/dist/types/session/secure-token-file.d.ts +3 -0
  182. package/dist/types/session/session-manager.d.ts +40 -1
  183. package/dist/types/session/startup-auth-config.d.ts +44 -0
  184. package/dist/types/session/terminal-abort.d.ts +378 -0
  185. package/dist/types/session/yield-queue.d.ts +7 -0
  186. package/dist/types/session-import/claude.d.ts +26 -0
  187. package/dist/types/session-import/codex.d.ts +88 -0
  188. package/dist/types/session-import/command.d.ts +35 -0
  189. package/dist/types/session-import/detect.d.ts +22 -0
  190. package/dist/types/session-import/index.d.ts +7 -0
  191. package/dist/types/session-import/provider-codex.d.ts +22 -0
  192. package/dist/types/session-import/provider-service.d.ts +38 -0
  193. package/dist/types/session-import/redact.d.ts +23 -0
  194. package/dist/types/session-import/service.d.ts +47 -0
  195. package/dist/types/session-import/types.d.ts +120 -0
  196. package/dist/types/setup/paseo/check.d.ts +16 -0
  197. package/dist/types/setup/paseo/install-saga.d.ts +115 -0
  198. package/dist/types/setup/paseo/json-publisher.d.ts +76 -0
  199. package/dist/types/setup/paseo/orchestration-preferences.d.ts +24 -0
  200. package/dist/types/setup/paseo/paseo-ownership.d.ts +87 -0
  201. package/dist/types/setup/paseo/paseo-setup.d.ts +29 -0
  202. package/dist/types/setup/paseo/provider-config.d.ts +35 -0
  203. package/dist/types/setup/paseo/remove.d.ts +14 -0
  204. package/dist/types/setup/paseo/result-types.d.ts +59 -0
  205. package/dist/types/setup/paseo/setup-deps.d.ts +73 -0
  206. package/dist/types/setup/paseo/skills-bridge.d.ts +44 -0
  207. package/dist/types/skill-state/active-state.d.ts +5 -1
  208. package/dist/types/slash-commands/acp-builtins.d.ts +5 -1
  209. package/dist/types/slash-commands/builtin-registry.d.ts +2 -0
  210. package/dist/types/slash-commands/helpers/credential-switch.d.ts +12 -0
  211. package/dist/types/slash-commands/helpers/usage-report.d.ts +5 -6
  212. package/dist/types/slash-commands/types.d.ts +7 -1
  213. package/dist/types/task/executor.d.ts +10 -0
  214. package/dist/types/task/index.d.ts +3 -1
  215. package/dist/types/tools/ask-answer-registry.d.ts +6 -3
  216. package/dist/types/tools/bash-sleep-advisory.d.ts +14 -0
  217. package/dist/types/tools/bash.d.ts +2 -6
  218. package/dist/types/tools/browser/attach.d.ts +11 -0
  219. package/dist/types/tools/browser/launch.d.ts +20 -0
  220. package/dist/types/tools/browser/profile-discovery.d.ts +6 -0
  221. package/dist/types/tools/browser/render.d.ts +1 -0
  222. package/dist/types/tools/browser.d.ts +3 -1
  223. package/dist/types/tools/image-gen.d.ts +9 -2
  224. package/dist/types/tools/index.d.ts +8 -0
  225. package/dist/types/tools/monitor.d.ts +1 -1
  226. package/dist/types/tools/skill-discovery.d.ts +8 -1
  227. package/dist/types/tools/subagent.d.ts +2 -0
  228. package/dist/types/tools/ultragoal-ask-guard.d.ts +2 -2
  229. package/dist/types/utils/herdr-pane.d.ts +76 -0
  230. package/package.json +19 -9
  231. package/scripts/build-binary.ts +2 -1
  232. package/scripts/build-sdk-package-smoke.ts +2 -13
  233. package/scripts/capture-sticky-viewport-showcase.ts +0 -1
  234. package/scripts/compile-args.ts +2 -0
  235. package/scripts/generate-sdk-adapter-parity-manifest.ts +31 -16
  236. package/scripts/generate-sdk-operation-inventory.ts +28 -0
  237. package/scripts/generate-telegram-baseline-manifest.ts +1 -0
  238. package/scripts/generate-tool-catalog.ts +6 -4
  239. package/scripts/verify-gjc-sdk-canonicalization.ts +5 -39
  240. package/src/async/job-manager.ts +352 -17
  241. package/src/async/support.ts +25 -0
  242. package/src/autoresearch/dashboard.ts +28 -13
  243. package/src/capability/index.ts +3 -1
  244. package/src/capability/mcp.ts +6 -0
  245. package/src/capability/types.ts +6 -0
  246. package/src/cli/accounts-cli.ts +395 -0
  247. package/src/cli/args.ts +23 -0
  248. package/src/cli/auth-broker-cli.ts +136 -66
  249. package/src/cli/auth-gateway-cli.ts +94 -70
  250. package/src/cli/config-cli.ts +27 -2
  251. package/src/cli/crash-cli.ts +78 -0
  252. package/src/cli/customize-doctor.ts +1605 -0
  253. package/src/cli/daemon-cli.ts +12 -3
  254. package/src/cli/fast-help.ts +1 -0
  255. package/src/cli/mcp-cli.ts +128 -60
  256. package/src/cli/notify-cli.ts +8 -14
  257. package/src/cli/root-flags.ts +8 -0
  258. package/src/cli/setup-cli.ts +145 -0
  259. package/src/cli/skills-cli.ts +38 -2
  260. package/src/cli/update-cli.ts +167 -12
  261. package/src/cli.ts +4 -0
  262. package/src/commands/accounts.ts +71 -0
  263. package/src/commands/crash.ts +35 -0
  264. package/src/commands/customize.ts +84 -0
  265. package/src/commands/daemon.ts +2 -2
  266. package/src/commands/deep-interview.ts +2 -0
  267. package/src/commands/launch.ts +1 -0
  268. package/src/commands/mcp.ts +12 -7
  269. package/src/commands/ralplan.ts +2 -0
  270. package/src/commands/sdk.ts +65 -32
  271. package/src/commands/setup.ts +5 -0
  272. package/src/commands/skills.ts +14 -4
  273. package/src/commands/ultragoal.ts +10 -1
  274. package/src/commands/update.ts +26 -15
  275. package/src/config/atomic-yaml-patch-worker.ts +57 -0
  276. package/src/config/atomic-yaml-patch.ts +769 -29
  277. package/src/config/config-schema-version.ts +10 -0
  278. package/src/config/file-lock.ts +70 -1
  279. package/src/config/mcp-schema.json +52 -14
  280. package/src/config/model-profile-activation.ts +20 -1
  281. package/src/config/model-profiles.ts +29 -19
  282. package/src/config/model-registry.ts +132 -21
  283. package/src/config/models-config-schema.ts +1 -1
  284. package/src/config/settings-schema.ts +76 -6
  285. package/src/config/settings.ts +4038 -199
  286. package/src/config/skill-settings-defaults.ts +41 -3
  287. package/src/config/task-delegation.ts +87 -0
  288. package/src/config/update-channel.ts +23 -0
  289. package/src/coordinator-mcp/server.ts +377 -308
  290. package/src/crash/index-store.ts +723 -0
  291. package/src/crash/nudge.ts +89 -0
  292. package/src/crash/record-loader.ts +149 -0
  293. package/src/crash/report.ts +551 -0
  294. package/src/crash/sanitize.ts +129 -0
  295. package/src/cursor.ts +36 -10
  296. package/src/customization/import.ts +946 -0
  297. package/src/customization/index.ts +4 -0
  298. package/src/customization/inventory.ts +335 -0
  299. package/src/customization/mutations.ts +141 -0
  300. package/src/customization/types.ts +223 -0
  301. package/src/daemon/control-types.ts +8 -1
  302. package/src/daemon/operator-contract.ts +6 -6
  303. package/src/defaults/gjc/skills/deep-interview/SKILL.md +11 -22
  304. package/src/defaults/gjc/skills/ralplan/SKILL.md +36 -23
  305. package/src/defaults/gjc/skills/ultragoal/SKILL.md +16 -0
  306. package/src/discovery/claude-hooks.ts +38 -0
  307. package/src/discovery/claude.ts +142 -209
  308. package/src/discovery/codex-hooks.ts +38 -0
  309. package/src/discovery/codex.ts +132 -198
  310. package/src/discovery/helpers.ts +8 -1
  311. package/src/discovery/index.ts +2 -0
  312. package/src/discovery/mcp-compat.ts +234 -0
  313. package/src/discovery/mcp-json.ts +6 -0
  314. package/src/edit/renderer.ts +40 -0
  315. package/src/edit/streaming.ts +4 -2
  316. package/src/exec/bash-executor.ts +24 -20
  317. package/src/export/html/index.ts +51 -2
  318. package/src/extensibility/extensions/loader.ts +9 -1
  319. package/src/extensibility/extensions/runner.ts +17 -4
  320. package/src/extensibility/extensions/types.ts +31 -6
  321. package/src/extensibility/gjc-plugins/constrained-hooks.ts +33 -0
  322. package/src/extensibility/gjc-plugins/installer.ts +9 -5
  323. package/src/extensibility/gjc-plugins/observability.ts +8 -2
  324. package/src/extensibility/gjc-plugins/registry.ts +13 -2
  325. package/src/extensibility/gjc-plugins/runtime-adapters.ts +3 -1
  326. package/src/extensibility/gjc-plugins/schema.ts +222 -39
  327. package/src/extensibility/hooks/loader.ts +154 -10
  328. package/src/extensibility/runtime-skill-discovery.ts +257 -60
  329. package/src/extensibility/skill-management.ts +368 -0
  330. package/src/extensibility/skills.ts +52 -16
  331. package/src/gjc-runtime/deep-interview-runtime.ts +45 -61
  332. package/src/gjc-runtime/launch-worktree.ts +56 -2
  333. package/src/gjc-runtime/linux-proc.ts +7 -1
  334. package/src/gjc-runtime/ralplan-runtime.ts +100 -164
  335. package/src/gjc-runtime/session-state-lock.ts +992 -0
  336. package/src/gjc-runtime/session-state-sidecar.ts +644 -142
  337. package/src/gjc-runtime/state-writer.ts +39 -14
  338. package/src/gjc-runtime/tmux-owner-isolation.ts +5 -4
  339. package/src/gjc-runtime/ultragoal-guard.ts +11 -4
  340. package/src/gjc-runtime/ultragoal-runtime.ts +44 -41
  341. package/src/gjc-runtime/workflow-settings.ts +596 -0
  342. package/src/goals/tools/goal-tool.ts +6 -1
  343. package/src/hooks/events.ts +291 -0
  344. package/src/hooks/native-skill-hook.ts +4 -0
  345. package/src/hooks/normalize.ts +369 -0
  346. package/src/hooks/skill-state.ts +165 -46
  347. package/src/internal-urls/docs-index.generated.ts +40 -32
  348. package/src/main.ts +32 -5
  349. package/src/migrate/mcp-mapper.ts +25 -2
  350. package/src/modes/acp/abort-scope.ts +29 -0
  351. package/src/modes/acp/acp-agent.ts +423 -98
  352. package/src/modes/components/assistant-message.ts +6 -1
  353. package/src/modes/components/customization/customization-dashboard.ts +443 -0
  354. package/src/modes/components/customization/import-wizard.ts +372 -0
  355. package/src/modes/components/customization/index.ts +1 -0
  356. package/src/modes/components/gajae-pet-widget.ts +539 -213
  357. package/src/modes/components/irc-sidebar.ts +11 -0
  358. package/src/modes/components/iterm-pet-transport.ts +585 -0
  359. package/src/modes/components/oauth-selector.ts +277 -86
  360. package/src/modes/components/pet-capability.ts +39 -40
  361. package/src/modes/components/settings-selector.ts +9 -0
  362. package/src/modes/components/status-line/gh.ts +45 -1
  363. package/src/modes/components/status-line/segments.ts +16 -1
  364. package/src/modes/components/tool-status-header.ts +13 -3
  365. package/src/modes/controllers/command-controller.ts +20 -8
  366. package/src/modes/controllers/extension-ui-controller.ts +56 -257
  367. package/src/modes/controllers/input-controller.ts +10 -0
  368. package/src/modes/controllers/runtime-mcp-command-controller.ts +16 -3
  369. package/src/modes/controllers/selector-controller.ts +177 -72
  370. package/src/modes/controllers/stt-controller.ts +3 -3
  371. package/src/modes/interactive-mode.ts +88 -16
  372. package/src/modes/print-mode.ts +35 -6
  373. package/src/modes/runtime-init.ts +21 -68
  374. package/src/modes/types.ts +1 -0
  375. package/src/modes/utils/injected-user-submission.ts +25 -0
  376. package/src/modes/utils/terminal-bell.ts +15 -1
  377. package/src/prompts/agent-fragments/ralplan-persistence.md +1 -1
  378. package/src/prompts/agent-fragments/restricted-bash.md +1 -1
  379. package/src/prompts/agents/critic.md +1 -1
  380. package/src/prompts/system/rlm-research.md +1 -1
  381. package/src/prompts/system/system-prompt.md +0 -2
  382. package/src/prompts/tools/bash.md +7 -1
  383. package/src/prompts/tools/browser.md +1 -1
  384. package/src/prompts/tools/cron.md +6 -6
  385. package/src/prompts/tools/read.md +0 -2
  386. package/src/prompts/tools/skill-discovery.md +4 -2
  387. package/src/runtime-mcp/client.ts +427 -23
  388. package/src/runtime-mcp/config.ts +37 -5
  389. package/src/runtime-mcp/manager-pool.test.ts +56 -0
  390. package/src/runtime-mcp/manager.ts +52 -2
  391. package/src/runtime-mcp/oauth-discovery.ts +13 -0
  392. package/src/runtime-mcp/oauth-flow.ts +46 -1
  393. package/src/runtime-mcp/pool-key.ts +5 -1
  394. package/src/runtime-mcp/pool.test.ts +9 -0
  395. package/src/runtime-mcp/protocol.test.ts +353 -0
  396. package/src/runtime-mcp/protocol.ts +624 -0
  397. package/src/runtime-mcp/scope-config.ts +78 -0
  398. package/src/runtime-mcp/tool-bridge.ts +44 -10
  399. package/src/runtime-mcp/transports/http.ts +84 -13
  400. package/src/runtime-mcp/types.ts +123 -12
  401. package/src/sdk/acp/adapter.ts +328 -97
  402. package/src/sdk/broker/broker.ts +160 -741
  403. package/src/sdk/broker/ensure.ts +9 -1
  404. package/src/sdk/broker/lifecycle.ts +510 -116
  405. package/src/sdk/broker/operation-receipt-ledger.ts +11 -2
  406. package/src/sdk/broker/process-incarnation.ts +19 -0
  407. package/src/sdk/broker/session-index.ts +516 -117
  408. package/src/sdk/broker/startup-failure.ts +28 -5
  409. package/src/sdk/broker/transport.ts +1 -13
  410. package/src/sdk/bus/chat-daemon-cli.ts +4 -2
  411. package/src/sdk/bus/chat-daemon-control.ts +67 -6
  412. package/src/sdk/bus/chat-daemon-runtime.ts +183 -859
  413. package/src/sdk/bus/config.ts +13 -0
  414. package/src/sdk/bus/conversation-store.ts +59 -171
  415. package/src/sdk/bus/daemon-paths.ts +20 -0
  416. package/src/sdk/bus/discord-conversation.ts +2 -0
  417. package/src/sdk/bus/discord-daemon.ts +524 -126
  418. package/src/sdk/bus/discord-live-provider.ts +206 -79
  419. package/src/sdk/bus/existing-thread-readiness.ts +4 -97
  420. package/src/sdk/bus/inbound-reaction-ordering.ts +122 -0
  421. package/src/sdk/bus/index.ts +2480 -456
  422. package/src/sdk/bus/kind-aware-reconciliation.ts +204 -34
  423. package/src/sdk/bus/lifecycle-commands.ts +2 -2
  424. package/src/sdk/bus/managed-daemon.ts +2 -145
  425. package/src/sdk/bus/notification-service.ts +196 -0
  426. package/src/sdk/bus/operator-runtime.ts +1 -1
  427. package/src/sdk/bus/prompt-reconciliation.ts +24 -15
  428. package/src/sdk/bus/reconciliation-store.ts +553 -24
  429. package/src/sdk/bus/session-control.ts +49 -3
  430. package/src/sdk/bus/slack-conversation.ts +4 -0
  431. package/src/sdk/bus/slack-daemon.ts +733 -134
  432. package/src/sdk/bus/slack-live-provider.ts +65 -15
  433. package/src/sdk/bus/slack-provider.ts +4 -0
  434. package/src/sdk/bus/slack-thread-binding.ts +9 -104
  435. package/src/sdk/bus/telegram-adoption-intent.ts +299 -209
  436. package/src/sdk/bus/telegram-daemon-cli.ts +194 -7
  437. package/src/sdk/bus/telegram-daemon-contract.ts +265 -19
  438. package/src/sdk/bus/telegram-daemon-control.ts +3 -13
  439. package/src/sdk/bus/telegram-daemon-orphan-reap.ts +498 -0
  440. package/src/sdk/bus/telegram-daemon-owner-registry.ts +176 -0
  441. package/src/sdk/bus/telegram-daemon.ts +2552 -2280
  442. package/src/sdk/bus/telegram-reference.ts +1 -226
  443. package/src/sdk/bus/telegram-setup.ts +2 -2
  444. package/src/sdk/bus/threaded-render.ts +1 -0
  445. package/src/sdk/bus/topic-registry.ts +279 -146
  446. package/src/sdk/cli/rows.ts +2 -35
  447. package/src/sdk/cli/session-cli.ts +776 -700
  448. package/src/sdk/client/client.ts +892 -1
  449. package/src/sdk/host/control/dispatch.ts +93 -58
  450. package/src/sdk/host/control/index.ts +1 -1
  451. package/src/sdk/host/control/operations.ts +18 -10
  452. package/src/sdk/host/control/runtime-gate.ts +40 -0
  453. package/src/sdk/host/host.ts +63 -12
  454. package/src/sdk/host/query/handlers.ts +66 -7
  455. package/src/sdk/host/reverse-leases.ts +2 -2
  456. package/src/sdk/host/sdk-surface-parity.test.ts +1 -1
  457. package/src/sdk/host/session-runtime.test.ts +2787 -34
  458. package/src/sdk/host/session-runtime.ts +1489 -101
  459. package/src/sdk/host/surface-policy.ts +12 -8
  460. package/src/sdk/host/types.ts +1 -1
  461. package/src/sdk/host/websocket-transport.lifecycle.test.ts +31 -59
  462. package/src/sdk/host/websocket-transport.ts +85 -50
  463. package/src/sdk/index.ts +2 -1
  464. package/src/sdk/lifecycle/broker-client.ts +53 -0
  465. package/src/sdk/lifecycle/client.ts +234 -0
  466. package/src/sdk/lifecycle/index.ts +3 -0
  467. package/src/sdk/{bus/recent-activity.ts → lifecycle/recent-sessions.ts} +5 -2
  468. package/src/sdk/lifecycle/service.ts +720 -0
  469. package/src/sdk/mcp/server.ts +226 -188
  470. package/src/sdk/prompt-deadline-lease.ts +55 -0
  471. package/src/sdk/prompt-deadline-manager.ts +148 -0
  472. package/src/sdk/prompt-status.ts +11 -3
  473. package/src/sdk/protocol/operation-inventory.generated.json +272 -129
  474. package/src/sdk/protocol/operation-registry.ts +71 -8
  475. package/src/sdk/receipt-state.ts +43 -0
  476. package/src/sdk/reconciliation-extensions.ts +14 -0
  477. package/src/sdk/router/index.ts +1 -0
  478. package/src/sdk/router/session-router.ts +1658 -0
  479. package/src/sdk/session-list.ts +93 -0
  480. package/src/sdk/session-reconnect.ts +45 -1
  481. package/src/sdk/session.ts +716 -120
  482. package/src/sdk/transport/serve-cli.ts +18 -34
  483. package/src/session/account-inventory.ts +603 -0
  484. package/src/session/agent-session.ts +2857 -582
  485. package/src/session/agent-storage.ts +35 -0
  486. package/src/session/blob-store.ts +32 -1
  487. package/src/session/coordinator-tool-label.ts +40 -0
  488. package/src/session/internal/managed-session-scope.ts +4 -0
  489. package/src/session/internal/managed-session-storage.ts +173 -12
  490. package/src/session/messages.ts +1 -1
  491. package/src/session/secure-token-file.ts +80 -0
  492. package/src/session/session-manager.ts +730 -58
  493. package/src/session/session-storage.ts +25 -16
  494. package/src/session/startup-auth-config.ts +297 -0
  495. package/src/session/terminal-abort.ts +1253 -0
  496. package/src/session/yield-queue.ts +57 -15
  497. package/src/session-import/claude.ts +334 -0
  498. package/src/session-import/codex.ts +1033 -0
  499. package/src/session-import/command.ts +77 -0
  500. package/src/session-import/detect.ts +133 -0
  501. package/src/session-import/index.ts +7 -0
  502. package/src/session-import/provider-codex.ts +327 -0
  503. package/src/session-import/provider-service.ts +457 -0
  504. package/src/session-import/redact.ts +128 -0
  505. package/src/session-import/service.ts +1264 -0
  506. package/src/session-import/types.ts +148 -0
  507. package/src/setup/paseo/check.ts +213 -0
  508. package/src/setup/paseo/install-saga.ts +293 -0
  509. package/src/setup/paseo/json-publisher.ts +263 -0
  510. package/src/setup/paseo/orchestration-preferences.ts +86 -0
  511. package/src/setup/paseo/paseo-ownership.ts +224 -0
  512. package/src/setup/paseo/paseo-setup.ts +253 -0
  513. package/src/setup/paseo/provider-config.ts +139 -0
  514. package/src/setup/paseo/remove.ts +183 -0
  515. package/src/setup/paseo/result-types.ts +79 -0
  516. package/src/setup/paseo/setup-deps.ts +175 -0
  517. package/src/setup/paseo/skills-bridge.ts +260 -0
  518. package/src/skill-state/active-state.ts +21 -11
  519. package/src/slash-commands/acp-builtins.ts +9 -1
  520. package/src/slash-commands/builtin-registry.ts +98 -16
  521. package/src/slash-commands/helpers/credential-switch.ts +143 -0
  522. package/src/slash-commands/helpers/mcp.ts +9 -3
  523. package/src/slash-commands/helpers/usage-report.ts +61 -56
  524. package/src/slash-commands/types.ts +7 -2
  525. package/src/task/executor.ts +30 -11
  526. package/src/task/index.ts +66 -7
  527. package/src/task/render.ts +23 -9
  528. package/src/tools/ask-answer-registry.ts +23 -7
  529. package/src/tools/ask.ts +8 -4
  530. package/src/tools/bash-sleep-advisory.ts +115 -0
  531. package/src/tools/bash.ts +98 -18
  532. package/src/tools/browser/attach.ts +71 -3
  533. package/src/tools/browser/launch.ts +86 -13
  534. package/src/tools/browser/profile-discovery.ts +57 -7
  535. package/src/tools/browser/render.ts +8 -1
  536. package/src/tools/browser.ts +130 -21
  537. package/src/tools/computer.enforcement.test.ts +1 -1
  538. package/src/tools/computer.ts +3 -2
  539. package/src/tools/cron.ts +12 -1
  540. package/src/tools/image-gen.ts +27 -16
  541. package/src/tools/index.ts +8 -0
  542. package/src/tools/job.ts +33 -6
  543. package/src/tools/monitor.ts +41 -2
  544. package/src/tools/skill-discovery.ts +21 -29
  545. package/src/tools/subagent.ts +142 -24
  546. package/src/tools/tool-catalog.generated.ts +6 -6
  547. package/src/tools/ultragoal-ask-guard.ts +10 -3
  548. package/src/utils/herdr-pane.ts +345 -0
  549. package/src/utils/title-generator.ts +2 -0
  550. package/src/web/scrapers/index.ts +6 -4
  551. package/dist/types/cli/malloc-env-guard.test.d.ts +0 -1
  552. package/dist/types/defaults/gjc-defaults.test.d.ts +0 -1
  553. package/dist/types/memory-backend/lazy-loading.test.d.ts +0 -1
  554. package/dist/types/runtime/boot-ordering.test.d.ts +0 -1
  555. package/dist/types/runtime/lazy-service.test.d.ts +0 -1
  556. package/dist/types/runtime/network-prewarm-service.test.d.ts +0 -1
  557. package/dist/types/runtime/workspace-tree-service.test.d.ts +0 -1
  558. package/dist/types/runtime-mcp/config.test.d.ts +0 -1
  559. package/dist/types/runtime-mcp/http.test.d.ts +0 -1
  560. package/dist/types/runtime-mcp/manager-pool.test.d.ts +0 -1
  561. package/dist/types/runtime-mcp/pool-key.test.d.ts +0 -1
  562. package/dist/types/runtime-mcp/pool.test.d.ts +0 -1
  563. package/dist/types/sdk/bus/lifecycle-control-runtime.d.ts +0 -117
  564. package/dist/types/sdk/bus/lifecycle-orchestrator.d.ts +0 -141
  565. package/dist/types/sdk/bus/telegram-cli.d.ts +0 -31
  566. package/dist/types/sdk/elevation/allowlist.d.ts +0 -20
  567. package/dist/types/sdk/elevation/audit.d.ts +0 -93
  568. package/dist/types/sdk/elevation/capability.d.ts +0 -3
  569. package/dist/types/sdk/elevation/digest.d.ts +0 -72
  570. package/dist/types/sdk/elevation/dispatch-receipt.d.ts +0 -85
  571. package/dist/types/sdk/elevation/grant-ledger.d.ts +0 -163
  572. package/dist/types/sdk/elevation/owner.d.ts +0 -48
  573. package/dist/types/sdk/host/import-graph.test.d.ts +0 -1
  574. package/dist/types/sdk/host/sdk-surface-parity.test.d.ts +0 -1
  575. package/dist/types/sdk/host/session-runtime.test.d.ts +0 -1
  576. package/dist/types/sdk/host/websocket-transport.lifecycle.test.d.ts +0 -1
  577. package/dist/types/session/auth-broker-config.d.ts +0 -13
  578. package/dist/types/session/heap-eviction-artifacts.test.d.ts +0 -1
  579. package/dist/types/skills/skills.test.d.ts +0 -1
  580. package/dist/types/slash-commands/notify-command.test.d.ts +0 -1
  581. package/dist/types/task/token-log.test.d.ts +0 -1
  582. package/dist/types/tools/computer.enforcement.test.d.ts +0 -1
  583. package/dist/types/tools/descriptors.test.d.ts +0 -1
  584. package/scripts/g005-daemon-smoke.ts +0 -180
  585. package/scripts/g011-daemon-path-smoke.ts +0 -153
  586. package/src/sdk/bus/lifecycle-control-runtime.ts +0 -1733
  587. package/src/sdk/bus/lifecycle-orchestrator.ts +0 -489
  588. package/src/sdk/bus/telegram-cli.ts +0 -212
  589. package/src/sdk/elevation/allowlist.ts +0 -54
  590. package/src/sdk/elevation/audit.ts +0 -208
  591. package/src/sdk/elevation/capability.ts +0 -41
  592. package/src/sdk/elevation/digest.ts +0 -129
  593. package/src/sdk/elevation/dispatch-receipt.ts +0 -184
  594. package/src/sdk/elevation/grant-ledger.ts +0 -1142
  595. package/src/sdk/elevation/owner.ts +0 -109
  596. package/src/session/auth-broker-config.ts +0 -109
  597. /package/dist/types/{ai-core-import-gate.test.d.ts → discovery/claude-hooks.d.ts} +0 -0
  598. /package/dist/types/{cli/fixture-report.test.d.ts → discovery/codex-hooks.d.ts} +0 -0
  599. /package/dist/types/sdk/{bus/recent-activity.d.ts → lifecycle/recent-sessions.d.ts} +0 -0
@@ -17,6 +17,7 @@ import * as crypto from "node:crypto";
17
17
  import * as fs from "node:fs/promises";
18
18
  import * as os from "node:os";
19
19
  import * as path from "node:path";
20
+ import { cleanReason } from "@gajae-code/ai/auth-broker/redact";
20
21
  import {
21
22
  AuthBrokerClient,
22
23
  type AuthCredential,
@@ -28,13 +29,19 @@ import {
28
29
  listProvidersWithEnvKey,
29
30
  type OAuthCredential,
30
31
  type OAuthProvider,
32
+ resolveOAuthStorageProvider,
31
33
  SqliteAuthCredentialStore,
32
34
  startAuthBroker,
33
35
  } from "@gajae-code/ai/core";
34
- import { $which, APP_NAME, getAgentDbPath, getConfigRootDir, isEnoent, logger, VERSION } from "@gajae-code/utils";
36
+ import { $which, APP_NAME, getAgentDbPath, getConfigRootDir, logger, VERSION } from "@gajae-code/utils";
35
37
  import { $ } from "bun";
36
38
  import chalk from "chalk";
37
- import { resolveAuthBrokerConfig } from "../session/auth-broker-config";
39
+ import {
40
+ createSecureTokenFileExclusive,
41
+ readSecureTokenFile,
42
+ writeSecureTokenFile,
43
+ } from "../session/secure-token-file";
44
+ import { resolveStartupAuthConfig } from "../session/startup-auth-config";
38
45
 
39
46
  export type AuthBrokerAction = "serve" | "token" | "login" | "logout" | "status" | "import" | "migrate";
40
47
 
@@ -62,6 +69,39 @@ export interface AuthBrokerCommandArgs {
62
69
 
63
70
  const ACTIONS: readonly AuthBrokerAction[] = ["serve", "token", "login", "logout", "import", "migrate", "status"];
64
71
 
72
+ type AuthBrokerCliErrorCode =
73
+ | "broker_unavailable"
74
+ | "credential_import_failed"
75
+ | "credential_migration_failed"
76
+ | "auth_broker_command_failed";
77
+
78
+ function stableErrorForAction(action: AuthBrokerAction): { code: AuthBrokerCliErrorCode; message: string } {
79
+ switch (action) {
80
+ case "status":
81
+ return { code: "broker_unavailable", message: "Auth broker is unavailable." };
82
+ case "import":
83
+ return { code: "credential_import_failed", message: "Credential import failed." };
84
+ case "migrate":
85
+ return { code: "credential_migration_failed", message: "Credential migration failed." };
86
+ default:
87
+ return { code: "auth_broker_command_failed", message: "Auth broker command failed." };
88
+ }
89
+ }
90
+
91
+ function safeDiagnostic(value: unknown, fallback: string): string {
92
+ return cleanReason(value) ?? fallback;
93
+ }
94
+
95
+ function writeCommandFailure(action: AuthBrokerAction, flags: AuthBrokerCommandArgs["flags"], error: unknown): void {
96
+ const stable = stableErrorForAction(action);
97
+ if (flags.json) {
98
+ process.stdout.write(`${JSON.stringify({ ok: false, error: stable })}\n`);
99
+ } else {
100
+ process.stderr.write(`${chalk.red("FAILED")} ${safeDiagnostic(error, stable.message)}\n`);
101
+ }
102
+ process.exitCode = 1;
103
+ }
104
+
65
105
  /** Callback ports baked from the per-provider OAuth flow modules. */
66
106
  const CALLBACK_PORTS: Record<string, number> = {
67
107
  anthropic: 54545,
@@ -78,25 +118,15 @@ function getTokenFilePath(): string {
78
118
  }
79
119
 
80
120
  async function readToken(): Promise<string | null> {
81
- try {
82
- const raw = await Bun.file(getTokenFilePath()).text();
83
- const trimmed = raw.trim();
84
- return trimmed.length > 0 ? trimmed : null;
85
- } catch (err) {
86
- if (isEnoent(err)) return null;
87
- throw err;
88
- }
121
+ return readSecureTokenFile(getTokenFilePath());
89
122
  }
90
123
 
91
124
  async function writeToken(token: string): Promise<void> {
92
- const file = getTokenFilePath();
93
- await fs.mkdir(path.dirname(file), { recursive: true, mode: 0o700 });
94
- await Bun.write(file, token);
95
- try {
96
- await fs.chmod(file, 0o600);
97
- } catch {
98
- // Best-effort (e.g. Windows).
99
- }
125
+ await writeSecureTokenFile(getTokenFilePath(), token);
126
+ }
127
+
128
+ async function createTokenExclusive(token: string): Promise<boolean> {
129
+ return createSecureTokenFileExclusive(getTokenFilePath(), token);
100
130
  }
101
131
 
102
132
  function generateToken(): string {
@@ -107,8 +137,19 @@ async function ensureToken(): Promise<string> {
107
137
  const existing = await readToken();
108
138
  if (existing) return existing;
109
139
  const token = generateToken();
110
- await writeToken(token);
111
- return token;
140
+ if (await createTokenExclusive(token)) return token;
141
+ // Another concurrent invocation won the create race. Its file may exist
142
+ // briefly before the winner writes the token, so retry reads without ever
143
+ // overwriting the winner's file.
144
+ for (let attempt = 0; attempt < 5; attempt++) {
145
+ const fromRace = await readToken();
146
+ if (fromRace) return fromRace;
147
+ if (attempt < 4) await Bun.sleep(10);
148
+ }
149
+ // If the file disappeared, make one final exclusive-create attempt. Never
150
+ // fall back to an unconditional write after observing EEXIST.
151
+ if (await createTokenExclusive(token)) return token;
152
+ throw new Error("Unable to initialize auth-broker token: another process owns an empty token file.");
112
153
  }
113
154
 
114
155
  async function runServe(flags: AuthBrokerCommandArgs["flags"]): Promise<void> {
@@ -133,7 +174,7 @@ async function runServe(flags: AuthBrokerCommandArgs["flags"]): Promise<void> {
133
174
  logger.info("auth-broker bearer token loaded", { path: getTokenFilePath(), mode: "0600" });
134
175
 
135
176
  const credentialDisabledUnsub = storage.onCredentialDisabled((event: CredentialDisabledEvent) => {
136
- logger.warn("auth-broker credential disabled", { ...event });
177
+ logger.warn("auth-broker credential disabled", { provider: event.provider });
137
178
  });
138
179
 
139
180
  const shutdown = async (signal: NodeJS.Signals): Promise<void> => {
@@ -241,10 +282,11 @@ async function runLogout(flags: AuthBrokerCommandArgs["flags"]): Promise<void> {
241
282
  if (!providerArg) {
242
283
  throw new Error("Usage: gjc auth-broker logout <provider>");
243
284
  }
285
+ const provider = resolveOAuthStorageProvider(providerArg);
244
286
  const store = await SqliteAuthCredentialStore.open(getAgentDbPath());
245
287
  try {
246
- store.deleteAuthCredentialsForProvider(providerArg, "logged out by user");
247
- process.stdout.write(`Logged out of ${providerArg}\n`);
288
+ store.deleteAuthCredentialsForProvider(provider, "logged out by user");
289
+ process.stdout.write(`Logged out of ${provider}\n`);
248
290
  } finally {
249
291
  store.close();
250
292
  }
@@ -338,7 +380,7 @@ async function loadImportPlan(
338
380
  try {
339
381
  json = (await Bun.file(file).json()) as CliProxyCredentialJson;
340
382
  } catch (err) {
341
- skipped.push({ file, reason: `unreadable JSON: ${String(err)}` });
383
+ skipped.push({ file, reason: `unreadable JSON: ${safeDiagnostic(err, "unreadable JSON")}` });
342
384
  continue;
343
385
  }
344
386
  if (json.disabled === true && !includeDisabled) {
@@ -415,14 +457,19 @@ async function runImport(flags: AuthBrokerCommandArgs["flags"]): Promise<void> {
415
457
  disabled: e.disabled,
416
458
  file: e.sourceFile,
417
459
  })),
418
- skipped,
460
+ skipped: skipped.map(skip => ({
461
+ ...skip,
462
+ reason: safeDiagnostic(skip.reason, "Credential import skipped."),
463
+ })),
419
464
  })}\n`,
420
465
  );
421
466
  }
422
467
 
423
468
  if (!flags.json) {
424
469
  for (const skip of skipped) {
425
- process.stdout.write(`${chalk.yellow("skip")} ${skip.file}: ${skip.reason}\n`);
470
+ process.stdout.write(
471
+ `${chalk.yellow("skip")} ${skip.file}: ${safeDiagnostic(skip.reason, "Credential import skipped.")}\n`,
472
+ );
426
473
  }
427
474
  }
428
475
 
@@ -439,7 +486,7 @@ async function runImport(flags: AuthBrokerCommandArgs["flags"]): Promise<void> {
439
486
  return;
440
487
  }
441
488
 
442
- const brokerConfig = await resolveAuthBrokerConfig();
489
+ const brokerConfig = (await resolveStartupAuthConfig()).broker;
443
490
  if (brokerConfig) {
444
491
  const client = new AuthBrokerClient({ url: brokerConfig.url, token: brokerConfig.token });
445
492
  for (const entry of entries) {
@@ -449,11 +496,14 @@ async function runImport(flags: AuthBrokerCommandArgs["flags"]): Promise<void> {
449
496
  process.stdout.write(`${chalk.green("uploaded")} ${describeImportEntry(entry)} → ${brokerConfig.url}\n`);
450
497
  }
451
498
  } catch (error) {
452
- const message = error instanceof Error ? error.message : String(error);
453
499
  if (flags.json) {
454
- process.stdout.write(`${JSON.stringify({ error: message, file: entry.sourceFile })}\n`);
500
+ process.stdout.write(
501
+ `${JSON.stringify({ ok: false, error: { code: "credential_import_failed", message: "Credential import failed." }, file: entry.sourceFile })}\n`,
502
+ );
455
503
  } else {
456
- process.stdout.write(`${chalk.red("failed")} ${describeImportEntry(entry)}: ${message}\n`);
504
+ process.stdout.write(
505
+ `${chalk.red("failed")} ${describeImportEntry(entry)}: ${safeDiagnostic(error, "Credential import failed.")}\n`,
506
+ );
457
507
  }
458
508
  process.exitCode = 1;
459
509
  }
@@ -531,7 +581,7 @@ function brokerAlreadyHas(existing: Map<string, Set<string>>, provider: string,
531
581
  }
532
582
 
533
583
  async function runMigrate(flags: AuthBrokerCommandArgs["flags"]): Promise<void> {
534
- const brokerConfig = await resolveAuthBrokerConfig();
584
+ const brokerConfig = (await resolveStartupAuthConfig()).broker;
535
585
  if (!brokerConfig) {
536
586
  throw new Error(
537
587
  "GJC_AUTH_BROKER_URL must be set (or `auth.broker.url` in config.yml). `migrate` uploads local credentials to a configured broker.",
@@ -640,13 +690,16 @@ async function runMigrate(flags: AuthBrokerCommandArgs["flags"]): Promise<void>
640
690
  `${JSON.stringify({
641
691
  dryRun: flags.dryRun === true,
642
692
  plan: plan.map(p => ({ source: p.source, provider: p.provider, identity: p.identity })),
643
- skipped,
693
+ skipped: skipped.map(skip => ({
694
+ ...skip,
695
+ reason: safeDiagnostic(skip.reason, "Credential migration skipped."),
696
+ })),
644
697
  })}\n`,
645
698
  );
646
699
  } else {
647
700
  for (const skip of skipped) {
648
701
  process.stdout.write(
649
- `${chalk.yellow("skip")} [${skip.source}] ${skip.provider} ${skip.identity}: ${skip.reason}\n`,
702
+ `${chalk.yellow("skip")} [${skip.source}] ${skip.provider} ${skip.identity}: ${safeDiagnostic(skip.reason, "Credential migration skipped.")}\n`,
650
703
  );
651
704
  }
652
705
  }
@@ -673,11 +726,14 @@ async function runMigrate(flags: AuthBrokerCommandArgs["flags"]): Promise<void>
673
726
  process.stdout.write(`${chalk.green("uploaded")} [${entry.source}] ${entry.provider} ${entry.identity}\n`);
674
727
  }
675
728
  } catch (error) {
676
- const message = error instanceof Error ? error.message : String(error);
677
729
  if (flags.json) {
678
- process.stdout.write(`${JSON.stringify({ error: message, provider: entry.provider })}\n`);
730
+ process.stdout.write(
731
+ `${JSON.stringify({ ok: false, error: { code: "credential_migration_failed", message: "Credential migration failed." }, provider: entry.provider })}\n`,
732
+ );
679
733
  } else {
680
- process.stdout.write(`${chalk.red("failed")} [${entry.source}] ${entry.provider}: ${message}\n`);
734
+ process.stdout.write(
735
+ `${chalk.red("failed")} [${entry.source}] ${entry.provider}: ${safeDiagnostic(error, "Credential migration failed.")}\n`,
736
+ );
681
737
  }
682
738
  process.exitCode = 1;
683
739
  }
@@ -685,10 +741,13 @@ async function runMigrate(flags: AuthBrokerCommandArgs["flags"]): Promise<void>
685
741
  }
686
742
 
687
743
  async function runStatus(flags: AuthBrokerCommandArgs["flags"]): Promise<void> {
688
- const cfg = await resolveAuthBrokerConfig();
744
+ const cfg = (await resolveStartupAuthConfig()).broker;
689
745
  if (!cfg) {
690
746
  const message = "No auth-broker configured (set GJC_AUTH_BROKER_URL to enable).";
691
- if (flags.json) process.stdout.write(`${JSON.stringify({ ok: false, reason: "not_configured" })}\n`);
747
+ if (flags.json)
748
+ process.stdout.write(
749
+ `${JSON.stringify({ ok: false, error: { code: "broker_not_configured", message: "Auth broker is not configured." } })}\n`,
750
+ );
692
751
  else process.stdout.write(`${chalk.yellow(message)}\n`);
693
752
  return;
694
753
  }
@@ -701,44 +760,55 @@ async function runStatus(flags: AuthBrokerCommandArgs["flags"]): Promise<void> {
701
760
  process.stdout.write(`${chalk.green("OK")} ${cfg.url} (version=${health.version ?? "unknown"})\n`);
702
761
  }
703
762
  } catch (error) {
704
- const message = error instanceof Error ? error.message : String(error);
705
763
  if (flags.json) {
706
- process.stdout.write(`${JSON.stringify({ ok: false, url: cfg.url, error: message })}\n`);
764
+ process.stdout.write(
765
+ `${JSON.stringify({ ok: false, url: cfg.url, error: { code: "broker_unavailable", message: "Auth broker is unavailable." } })}\n`,
766
+ );
707
767
  } else {
708
- process.stdout.write(`${chalk.red("FAILED")} ${cfg.url}: ${message}\n`);
768
+ process.stdout.write(
769
+ `${chalk.red("FAILED")} ${cfg.url}: ${safeDiagnostic(error, "Auth broker is unavailable.")}\n`,
770
+ );
709
771
  }
710
772
  process.exitCode = 1;
711
773
  }
712
774
  }
713
775
 
714
776
  export async function runAuthBrokerCommand(cmd: AuthBrokerCommandArgs): Promise<void> {
715
- switch (cmd.action) {
716
- case "serve":
717
- await runServe(cmd.flags);
718
- return;
719
- case "token":
720
- await runToken(cmd.flags);
721
- return;
722
- case "login":
723
- await runLogin(cmd.flags);
724
- return;
725
- case "logout":
726
- await runLogout(cmd.flags);
727
- return;
728
- case "import":
729
- await runImport(cmd.flags);
730
- return;
731
- case "migrate":
732
- await runMigrate(cmd.flags);
733
- return;
734
- case "status":
735
- await runStatus(cmd.flags);
777
+ try {
778
+ switch (cmd.action) {
779
+ case "serve":
780
+ await runServe(cmd.flags);
781
+ return;
782
+ case "token":
783
+ await runToken(cmd.flags);
784
+ return;
785
+ case "login":
786
+ await runLogin(cmd.flags);
787
+ return;
788
+ case "logout":
789
+ await runLogout(cmd.flags);
790
+ return;
791
+ case "import":
792
+ await runImport(cmd.flags);
793
+ return;
794
+ case "migrate":
795
+ await runMigrate(cmd.flags);
796
+ return;
797
+ case "status":
798
+ await runStatus(cmd.flags);
799
+ return;
800
+ default: {
801
+ // Exhaustive check.
802
+ const _exhaustive: never = cmd.action;
803
+ throw new Error(`Unknown auth-broker action: ${String(_exhaustive)}`);
804
+ }
805
+ }
806
+ } catch (error) {
807
+ if (cmd.action === "status" || cmd.action === "import" || cmd.action === "migrate") {
808
+ writeCommandFailure(cmd.action, cmd.flags, error);
736
809
  return;
737
- default: {
738
- // Exhaustive check.
739
- const _exhaustive: never = cmd.action;
740
- throw new Error(`Unknown auth-broker action: ${String(_exhaustive)}`);
741
810
  }
811
+ throw error;
742
812
  }
743
813
  }
744
814
 
@@ -13,8 +13,8 @@
13
13
  * - `status` — prints the locally-stored gateway token and bind hint.
14
14
  */
15
15
  import * as crypto from "node:crypto";
16
- import * as fs from "node:fs/promises";
17
16
  import * as path from "node:path";
17
+ import { cleanReason } from "@gajae-code/ai/auth-broker/redact";
18
18
  import { startAuthGateway } from "@gajae-code/ai/auth-gateway/server";
19
19
  import {
20
20
  type Api,
@@ -28,9 +28,14 @@ import {
28
28
  RemoteAuthCredentialStore,
29
29
  type SnapshotResponse,
30
30
  } from "@gajae-code/ai/core";
31
- import { getConfigRootDir, isEnoent, VERSION } from "@gajae-code/utils";
31
+ import { getConfigRootDir, VERSION } from "@gajae-code/utils";
32
32
  import chalk from "chalk";
33
- import { type AuthBrokerClientConfig, resolveAuthBrokerConfig } from "../session/auth-broker-config";
33
+ import {
34
+ createSecureTokenFileExclusive,
35
+ readSecureTokenFile,
36
+ writeSecureTokenFile,
37
+ } from "../session/secure-token-file";
38
+ import { type AuthBrokerClientConfig, resolveStartupAuthConfig } from "../session/startup-auth-config";
34
39
 
35
40
  export type AuthGatewayAction = "serve" | "token" | "status" | "check";
36
41
 
@@ -51,53 +56,51 @@ export interface AuthGatewayCommandArgs {
51
56
 
52
57
  const ACTIONS: readonly AuthGatewayAction[] = ["serve", "token", "status", "check"];
53
58
 
59
+ type AuthGatewayCliErrorCode =
60
+ | "broker_not_configured"
61
+ | "broker_unavailable"
62
+ | "credential_check_failed"
63
+ | "auth_gateway_command_failed";
64
+
65
+ function stableErrorForAction(action: AuthGatewayAction): { code: AuthGatewayCliErrorCode; message: string } {
66
+ switch (action) {
67
+ case "status":
68
+ return { code: "broker_unavailable", message: "Auth broker is unavailable." };
69
+ case "check":
70
+ return { code: "credential_check_failed", message: "Credential check failed." };
71
+ default:
72
+ return { code: "auth_gateway_command_failed", message: "Auth gateway command failed." };
73
+ }
74
+ }
75
+
76
+ function safeDiagnostic(value: unknown, fallback: string): string {
77
+ return cleanReason(value) ?? fallback;
78
+ }
79
+
80
+ function writeCommandFailure(action: AuthGatewayAction, flags: AuthGatewayCommandArgs["flags"], error: unknown): void {
81
+ const stable = stableErrorForAction(action);
82
+ if (flags.json) {
83
+ process.stdout.write(`${JSON.stringify({ ok: false, error: stable })}\n`);
84
+ } else {
85
+ process.stderr.write(`${chalk.red("FAILED")} ${safeDiagnostic(error, stable.message)}\n`);
86
+ }
87
+ process.exitCode = 1;
88
+ }
89
+
54
90
  function getTokenFilePath(): string {
55
91
  return path.join(getConfigRootDir(), "auth-gateway.token");
56
92
  }
57
93
 
58
94
  async function readToken(): Promise<string | null> {
59
- try {
60
- const raw = await Bun.file(getTokenFilePath()).text();
61
- const trimmed = raw.trim();
62
- return trimmed.length > 0 ? trimmed : null;
63
- } catch (err) {
64
- if (isEnoent(err)) return null;
65
- throw err;
66
- }
95
+ return readSecureTokenFile(getTokenFilePath());
67
96
  }
68
97
 
69
98
  async function writeToken(token: string): Promise<void> {
70
- const file = getTokenFilePath();
71
- await fs.mkdir(path.dirname(file), { recursive: true, mode: 0o700 });
72
- await fs.writeFile(file, token, { mode: 0o600 });
73
- try {
74
- await fs.chmod(file, 0o600);
75
- } catch {
76
- // Best-effort (e.g. Windows).
77
- }
99
+ await writeSecureTokenFile(getTokenFilePath(), token);
78
100
  }
79
101
 
80
- /**
81
- * Atomically create the token file, refusing to clobber an existing one.
82
- * Returns `true` on success, `false` when the file already existed (so the
83
- * caller re-reads it instead of racing another concurrent `ensureToken`).
84
- */
85
102
  async function createTokenExclusive(token: string): Promise<boolean> {
86
- const file = getTokenFilePath();
87
- await fs.mkdir(path.dirname(file), { recursive: true, mode: 0o700 });
88
- try {
89
- // `wx` = O_CREAT | O_EXCL — fails with EEXIST if the file is already there.
90
- await fs.writeFile(file, token, { flag: "wx", mode: 0o600 });
91
- } catch (err) {
92
- if ((err as NodeJS.ErrnoException).code === "EEXIST") return false;
93
- throw err;
94
- }
95
- try {
96
- await fs.chmod(file, 0o600);
97
- } catch {
98
- // Best-effort (e.g. Windows).
99
- }
100
- return true;
103
+ return createSecureTokenFileExclusive(getTokenFilePath(), token);
101
104
  }
102
105
 
103
106
  function generateToken(): string {
@@ -109,13 +112,18 @@ async function ensureToken(): Promise<string> {
109
112
  if (existing) return existing;
110
113
  const token = generateToken();
111
114
  if (await createTokenExclusive(token)) return token;
112
- // Another concurrent invocation won the create race; read what they wrote.
113
- const fromRace = await readToken();
114
- if (fromRace) return fromRace;
115
- // File existed-then-disappeared between EEXIST and read; last resort, write
116
- // our generated token unconditionally so callers don't see an empty string.
117
- await writeToken(token);
118
- return token;
115
+ // Another concurrent invocation won the create race. Its file may exist
116
+ // briefly before the winner writes the token, so retry reads without ever
117
+ // overwriting the winner's file.
118
+ for (let attempt = 0; attempt < 5; attempt++) {
119
+ const fromRace = await readToken();
120
+ if (fromRace) return fromRace;
121
+ if (attempt < 4) await Bun.sleep(10);
122
+ }
123
+ // If the file disappeared, make one final exclusive-create attempt. Never
124
+ // fall back to an unconditional write after observing EEXIST.
125
+ if (await createTokenExclusive(token)) return token;
126
+ throw new Error("Unable to initialize auth-gateway token: another process owns an empty token file.");
119
127
  }
120
128
 
121
129
  function createBrokerClient(brokerConfig: AuthBrokerClientConfig): AuthBrokerClient {
@@ -129,7 +137,7 @@ async function fetchBrokerSnapshot(client: AuthBrokerClient): Promise<SnapshotRe
129
137
  }
130
138
 
131
139
  async function runServe(flags: AuthGatewayCommandArgs["flags"]): Promise<void> {
132
- const brokerConfig = await resolveAuthBrokerConfig();
140
+ const brokerConfig = (await resolveStartupAuthConfig()).broker;
133
141
  if (!brokerConfig) {
134
142
  throw new Error(
135
143
  "`gjc auth-gateway serve` requires GJC_AUTH_BROKER_URL (or `auth.broker.url`/`auth.broker.token` in config.yml). The gateway is itself a broker client.",
@@ -243,12 +251,13 @@ async function runToken(flags: AuthGatewayCommandArgs["flags"]): Promise<void> {
243
251
 
244
252
  async function runStatus(flags: AuthGatewayCommandArgs["flags"]): Promise<void> {
245
253
  const token = await readToken();
246
- const brokerConfig = await resolveAuthBrokerConfig();
254
+ const brokerConfig = (await resolveStartupAuthConfig()).broker;
247
255
  const tokenFile = getTokenFilePath();
248
256
  if (!brokerConfig) {
249
257
  const status = {
250
258
  ready: false,
251
- reason: "not_configured",
259
+ reason: "broker_not_configured",
260
+ error: { code: "broker_not_configured", message: "Auth broker is not configured." },
252
261
  tokenFile,
253
262
  tokenPresent: token !== null,
254
263
  broker: null,
@@ -298,7 +307,6 @@ async function runStatus(flags: AuthGatewayCommandArgs["flags"]): Promise<void>
298
307
  }
299
308
  if (!tokenPresent) process.exitCode = 1;
300
309
  } catch (error) {
301
- const message = error instanceof Error ? error.message : String(error);
302
310
  const status = {
303
311
  ready: false,
304
312
  reason: "broker_unavailable",
@@ -307,12 +315,14 @@ async function runStatus(flags: AuthGatewayCommandArgs["flags"]): Promise<void>
307
315
  broker: brokerConfig.url,
308
316
  brokerConfigured: true,
309
317
  brokerAuthenticated: false,
310
- error: message,
318
+ error: { code: "broker_unavailable", message: "Auth broker is unavailable." },
311
319
  };
312
320
  if (flags.json) {
313
321
  process.stdout.write(`${JSON.stringify(status)}\n`);
314
322
  } else {
315
- process.stdout.write(`${chalk.red("FAILED")} upstream broker: ${brokerConfig.url}: ${message}\n`);
323
+ process.stdout.write(
324
+ `${chalk.red("FAILED")} upstream broker: ${brokerConfig.url}: ${safeDiagnostic(error, "Auth broker is unavailable.")}\n`,
325
+ );
316
326
  process.stdout.write(
317
327
  `token: ${status.tokenPresent ? chalk.green("present") : chalk.red("missing")} at ${status.tokenFile}\n`,
318
328
  );
@@ -322,23 +332,31 @@ async function runStatus(flags: AuthGatewayCommandArgs["flags"]): Promise<void>
322
332
  }
323
333
 
324
334
  export async function runAuthGatewayCommand(cmd: AuthGatewayCommandArgs): Promise<void> {
325
- switch (cmd.action) {
326
- case "serve":
327
- await runServe(cmd.flags);
328
- return;
329
- case "token":
330
- await runToken(cmd.flags);
331
- return;
332
- case "status":
333
- await runStatus(cmd.flags);
334
- return;
335
- case "check":
336
- await runCheck(cmd.flags);
335
+ try {
336
+ switch (cmd.action) {
337
+ case "serve":
338
+ await runServe(cmd.flags);
339
+ return;
340
+ case "token":
341
+ await runToken(cmd.flags);
342
+ return;
343
+ case "status":
344
+ await runStatus(cmd.flags);
345
+ return;
346
+ case "check":
347
+ await runCheck(cmd.flags);
348
+ return;
349
+ default: {
350
+ const _exhaustive: never = cmd.action;
351
+ throw new Error(`Unknown auth-gateway action: ${String(_exhaustive)}`);
352
+ }
353
+ }
354
+ } catch (error) {
355
+ if (cmd.action === "status" || cmd.action === "check") {
356
+ writeCommandFailure(cmd.action, cmd.flags, error);
337
357
  return;
338
- default: {
339
- const _exhaustive: never = cmd.action;
340
- throw new Error(`Unknown auth-gateway action: ${String(_exhaustive)}`);
341
358
  }
359
+ throw error;
342
360
  }
343
361
  }
344
362
 
@@ -350,7 +368,7 @@ export async function runAuthGatewayCommand(cmd: AuthGatewayCommandArgs): Promis
350
368
  * dedicated diagnostic is the only way to see which credentials failed.
351
369
  */
352
370
  async function runCheck(flags: AuthGatewayCommandArgs["flags"]): Promise<void> {
353
- const brokerConfig = await resolveAuthBrokerConfig();
371
+ const brokerConfig = (await resolveStartupAuthConfig()).broker;
354
372
  if (!brokerConfig) {
355
373
  throw new Error(
356
374
  "`gjc auth-gateway check` requires GJC_AUTH_BROKER_URL (or `auth.broker.url`/`auth.broker.token` in config.yml). It probes the same credentials the gateway would serve.",
@@ -366,7 +384,11 @@ async function runCheck(flags: AuthGatewayCommandArgs["flags"]): Promise<void> {
366
384
  const results = await storage.checkCredentials();
367
385
 
368
386
  if (flags.json) {
369
- process.stdout.write(`${JSON.stringify({ broker: brokerConfig.url, credentials: results }, null, 2)}\n`);
387
+ const credentials = results.map(row => ({
388
+ ...row,
389
+ ...(row.reason ? { reason: safeDiagnostic(row.reason, "Credential check failed.") } : {}),
390
+ }));
391
+ process.stdout.write(`${JSON.stringify({ broker: brokerConfig.url, credentials }, null, 2)}\n`);
370
392
  } else {
371
393
  const grouped = new Map<string, typeof results>();
372
394
  for (const row of results) {
@@ -389,7 +411,9 @@ async function runCheck(flags: AuthGatewayCommandArgs["flags"]): Promise<void> {
389
411
  const identity =
390
412
  row.email ?? row.accountId ?? (row.type === "api_key" ? "(api key)" : "(no identity on credential)");
391
413
  const remote = row.remoteRefresh ? chalk.dim(" [remote-refresh]") : "";
392
- const reason = row.reason ? chalk.dim(` — ${row.reason}`) : "";
414
+ const reason = row.reason
415
+ ? chalk.dim(` — ${safeDiagnostic(row.reason, "Credential check failed.")}`)
416
+ : "";
393
417
  process.stdout.write(
394
418
  ` ${status} id=${row.id.toString().padStart(3)} ${row.type.padEnd(7)} ${identity}${remote}${reason}\n`,
395
419
  );
@@ -10,6 +10,9 @@ import type * as path from "node:path";
10
10
  import { APP_NAME, getAgentDir } from "@gajae-code/utils";
11
11
  import { YAML } from "bun";
12
12
  import chalk from "chalk";
13
+ import { resolveModelProfileName } from "../config/model-profile-contract";
14
+ import { mergeModelProfiles } from "../config/model-profiles";
15
+ import { ModelsConfigFile } from "../config/model-registry";
13
16
  import {
14
17
  getDefault,
15
18
  getEnumValues,
@@ -21,6 +24,7 @@ import {
21
24
  type SettingValue,
22
25
  settings,
23
26
  } from "../config/settings";
27
+ import { resolveEagerTaskDelegation } from "../config/task-delegation";
24
28
  import { theme } from "../modes/theme/theme";
25
29
  import { initXdg } from "./commands/init-xdg";
26
30
 
@@ -449,17 +453,38 @@ function handlePath(): void {
449
453
  console.log(getAgentDir());
450
454
  }
451
455
 
456
+ /**
457
+ * Configuration conflicts that no schema check can see: an explicit
458
+ * `task.eager false` keeps a vendor-separated profile's workers unused, so the
459
+ * main provider's quota pays for work the layout meant to offload.
460
+ */
461
+ export function collectConfigAdvisories(): string[] {
462
+ const profileName = settings.get("modelProfile.default");
463
+ const profiles = mergeModelProfiles(ModelsConfigFile.load()?.profiles);
464
+ const resolvedProfileName = profileName ? resolveModelProfileName(profileName, profiles) : undefined;
465
+ const delegation = resolveEagerTaskDelegation({
466
+ settings,
467
+ profile: resolvedProfileName ? profiles.get(resolvedProfileName) : undefined,
468
+ });
469
+ if (!delegation.suppressedByExplicitSetting) return [];
470
+ return [
471
+ `task.eager is false while ${delegation.vendorSeparatedRoles.join(" and ")} run on a different provider than the default role; those workers will not be used. Run \`${APP_NAME} config set task.eager true\` or reset task.eager to delegate by default.`,
472
+ ];
473
+ }
474
+
452
475
  function handleDoctor(flags: { json?: boolean }): void {
453
476
  const report = settings.getSchemaReport();
477
+ const advisories = collectConfigAdvisories();
454
478
  if (flags.json) {
455
- console.log(JSON.stringify(report, null, 2));
479
+ console.log(JSON.stringify({ ...report, advisories }, null, 2));
456
480
  return;
457
481
  }
458
- if (report.issues.length === 0) {
482
+ if (report.issues.length === 0 && advisories.length === 0) {
459
483
  console.log(chalk.green("Settings schema is healthy."));
460
484
  return;
461
485
  }
462
486
  for (const issue of report.issues) console.log(`${issue.kind}\t${issue.path}\t${issue.detail}`);
487
+ for (const advisory of advisories) console.log(chalk.yellow(`advisory\ttask.eager\t${advisory}`));
463
488
  }
464
489
 
465
490
  type ConfigDoctorReport = {