@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,4 @@
1
+ export * from "./import";
2
+ export * from "./inventory";
3
+ export * from "./mutations";
4
+ export * from "./types";
@@ -0,0 +1,335 @@
1
+ /**
2
+ * Inventory aggregation for the `/extensions` umbrella customization surface.
3
+ *
4
+ * Status authority is the runtime's own contracts, not a parallel state model:
5
+ * - Skills: `listNativeSkillsForManagement` (#4285) — the authoritative
6
+ * discovery/policy model (trust, include/ignore, disabledExtensions,
7
+ * bundled-name protection). A narrow supplemental scan flags SKILL.md files
8
+ * the management loader rejects as `invalid` rows.
9
+ * - Hooks: canonical `<root>/hooks/<pre|post>/` layout with the runtime's
10
+ * project-first, first-wins dedupe key (`<type>:<tool>:<name>`); losers are
11
+ * shown as `shadowed`.
12
+ * - MCPs: canonical config files for both scopes with the runtime's
13
+ * project-first precedence and the union of disabled markers; malformed
14
+ * files surface as `invalid` rows without leaking raw JSON.
15
+ *
16
+ * All display fields are secret-safe: env/header values are never rendered,
17
+ * and command/argument text is masked for token-shaped assignments.
18
+ */
19
+ import type { Dirent } from "node:fs";
20
+ import * as fs from "node:fs/promises";
21
+ import * as path from "node:path";
22
+ import { parseFrontmatter } from "@gajae-code/utils";
23
+ import { mcpCapability } from "../capability/mcp";
24
+ import { listNativeSkillsForManagement, type SkillManagementPolicy } from "../extensibility/skill-management";
25
+ import { readMCPConfigFile } from "../runtime-mcp/config-writer";
26
+ import type { CustomizationSurface, GjcScope, InventoryRow, InventoryStatus } from "./types";
27
+ import { resolveScopePaths, scopeLabel } from "./types";
28
+
29
+ /** Frontmatter key written by the import flow to record provenance. */
30
+ export const IMPORTED_FROM_FRONTMATTER_KEY = "x-gjc-imported-from";
31
+
32
+ export interface LoadCustomizationInventoryOptions {
33
+ cwd: string;
34
+ /** Runtime home override (tests); defaults to the process home. */
35
+ home?: string;
36
+ /** Skill management policy snapshot (trust, include/ignore, disabledExtensions). */
37
+ policy?: SkillManagementPolicy;
38
+ /** Disabled extension ids (`skill:<name>` / `mcp:<name>`) from settings. */
39
+ disabledExtensions?: string[];
40
+ }
41
+
42
+ export interface CustomizationInventory {
43
+ rows: InventoryRow[];
44
+ warnings: string[];
45
+ }
46
+
47
+ /** Stable row identity used for selection and mutations. */
48
+ export function inventoryRowId(surface: CustomizationSurface, scope: GjcScope, rowPath: string): string {
49
+ return `${surface}:${scope}:${rowPath}`;
50
+ }
51
+
52
+ // ---------------------------------------------------------------------------
53
+ // Display redaction
54
+ // ---------------------------------------------------------------------------
55
+
56
+ function redactServerForDisplay(server: Record<string, unknown>): Record<string, unknown> {
57
+ return {
58
+ type: typeof server.type === "string" ? server.type : undefined,
59
+ enabled: typeof server.enabled === "boolean" ? server.enabled : undefined,
60
+ autoload: typeof server.autoload === "boolean" ? server.autoload : undefined,
61
+ sharing: typeof server.sharing === "string" ? server.sharing : undefined,
62
+ timeout: typeof server.timeout === "number" ? server.timeout : undefined,
63
+ command: server.command === undefined ? undefined : "[command redacted]",
64
+ args: server.args === undefined ? undefined : "[arguments redacted]",
65
+ url: server.url === undefined ? undefined : "[URL redacted]",
66
+ envKeys: server.env && typeof server.env === "object" ? Object.keys(server.env) : undefined,
67
+ headerKeys: server.headers && typeof server.headers === "object" ? Object.keys(server.headers) : undefined,
68
+ };
69
+ }
70
+
71
+ // ---------------------------------------------------------------------------
72
+ // Skills
73
+ // ---------------------------------------------------------------------------
74
+
75
+ async function readImportMarker(skillPath: string): Promise<string | null> {
76
+ try {
77
+ const content = await fs.readFile(skillPath, "utf-8");
78
+ const { frontmatter } = parseFrontmatter(content, { level: "off" });
79
+ // parseFrontmatter camelCases keys: x-gjc-imported-from → xGjcImportedFrom.
80
+ const marker = frontmatter[IMPORTED_FROM_FRONTMATTER_KEY] ?? frontmatter.xGjcImportedFrom;
81
+ return typeof marker === "string" ? marker : null;
82
+ } catch {
83
+ return null;
84
+ }
85
+ }
86
+
87
+ function importedProductLabel(marker: string): string {
88
+ return marker === "claude-code" ? "Claude Code" : marker === "codex" ? "Codex" : marker;
89
+ }
90
+
91
+ async function loadSkillRows(options: LoadCustomizationInventoryOptions, _warnings: string[]): Promise<InventoryRow[]> {
92
+ const rows: InventoryRow[] = [];
93
+ const records = await listNativeSkillsForManagement({
94
+ cwd: options.cwd,
95
+ home: options.home,
96
+ policy: options.policy,
97
+ });
98
+ const managedPaths = new Set<string>();
99
+ for (const record of records) {
100
+ managedPaths.add(path.resolve(record.path));
101
+ const scope: GjcScope = record.scope === "project" ? "project" : "global";
102
+ const marker = await readImportMarker(record.path);
103
+ let status: InventoryStatus;
104
+ const diagnostics: string[] = [];
105
+ if (options.policy?.enabled === false) {
106
+ status = "disabled";
107
+ diagnostics.push("native skills are disabled globally (skills.enabled=false)");
108
+ } else if (record.enabled) {
109
+ status = marker ? "imported" : "enabled";
110
+ } else if (record.disabledReason === "protected") {
111
+ // Bundled workflow skills are always active; the name is protected.
112
+ status = "enabled";
113
+ diagnostics.push("bundled GJC workflow skill — protected name, always available");
114
+ } else {
115
+ status = "disabled";
116
+ if (record.disabledReason) diagnostics.push(`disabled (${record.disabledReason})`);
117
+ }
118
+ const provenance = marker ? `${record.source} · imported from ${importedProductLabel(marker)}` : record.source;
119
+ rows.push({
120
+ id: inventoryRowId("skills", scope, record.path),
121
+ surface: "skills",
122
+ name: record.name,
123
+ displayName: record.name,
124
+ status,
125
+ provenance,
126
+ path: record.path,
127
+ scope,
128
+ description: record.description || undefined,
129
+ diagnostics: diagnostics.length > 0 ? diagnostics : undefined,
130
+ raw: { name: record.name, source: record.source, hidden: record.hidden },
131
+ });
132
+ }
133
+
134
+ // Narrow supplemental pass: flag SKILL.md files the management loader
135
+ // rejected (missing/invalid frontmatter) as invalid rows with remediation.
136
+ for (const scope of ["project", "global"] as const) {
137
+ const skillsDir = resolveScopePaths(scope, options.cwd).skillsDir;
138
+ let dirNames: string[];
139
+ try {
140
+ dirNames = (await fs.readdir(skillsDir, { withFileTypes: true }))
141
+ .filter(entry => entry.isDirectory() && !entry.name.startsWith("."))
142
+ .map(entry => entry.name)
143
+ .sort();
144
+ } catch {
145
+ continue;
146
+ }
147
+ for (const dirName of dirNames) {
148
+ const skillPath = path.join(skillsDir, dirName, "SKILL.md");
149
+ if (managedPaths.has(path.resolve(skillPath))) continue;
150
+ try {
151
+ const stat = await fs.lstat(skillPath);
152
+ if (stat.isSymbolicLink() || !stat.isFile()) continue;
153
+ const content = await fs.readFile(skillPath, "utf-8");
154
+ const { frontmatter } = parseFrontmatter(content, { level: "off" });
155
+ const description = typeof frontmatter.description === "string" ? frontmatter.description.trim() : "";
156
+ if (description) continue; // valid but shadowed/deduped — authority is the loader
157
+ rows.push({
158
+ id: inventoryRowId("skills", scope, skillPath),
159
+ surface: "skills",
160
+ name: dirName,
161
+ displayName: dirName,
162
+ status: "invalid",
163
+ provenance: `${scopeLabel(scope)} skills`,
164
+ path: skillPath,
165
+ scope,
166
+ diagnostics: ["invalid skill frontmatter: add a YAML frontmatter block with a non-empty description"],
167
+ raw: { name: dirName },
168
+ });
169
+ } catch {
170
+ // Unreadable files are simply not listed; the loader remains authority.
171
+ }
172
+ }
173
+ }
174
+ return rows;
175
+ }
176
+
177
+ // ---------------------------------------------------------------------------
178
+ // Hooks
179
+ // ---------------------------------------------------------------------------
180
+
181
+ const HOOK_PHASES = ["pre", "post"] as const;
182
+
183
+ async function loadHookRows(options: LoadCustomizationInventoryOptions, _warnings: string[]): Promise<InventoryRow[]> {
184
+ const rows: InventoryRow[] = [];
185
+ // Runtime semantics: project-first, first-wins on `<type>:<tool>:<name>`.
186
+ const seen = new Set<string>();
187
+ for (const scope of ["project", "global"] as const) {
188
+ const hooksDir = resolveScopePaths(scope, options.cwd).hooksDir;
189
+ for (const phase of HOOK_PHASES) {
190
+ const phaseDir = path.join(hooksDir, phase);
191
+ let entries: Dirent[];
192
+ try {
193
+ entries = await fs.readdir(phaseDir, { withFileTypes: true });
194
+ } catch {
195
+ continue;
196
+ }
197
+ for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
198
+ if (entry.name.startsWith(".") || !entry.isFile()) continue;
199
+ const hookPath = path.join(phaseDir, entry.name);
200
+ const baseName = entry.name.includes(".") ? entry.name.slice(0, entry.name.lastIndexOf(".")) : entry.name;
201
+ const key = `${phase}:${baseName}:${entry.name}`;
202
+ const shadowed = seen.has(key);
203
+ seen.add(key);
204
+ rows.push({
205
+ id: inventoryRowId("hooks", scope, hookPath),
206
+ surface: "hooks",
207
+ name: entry.name,
208
+ displayName: `${phase}/${entry.name}`,
209
+ status: shadowed ? "shadowed" : "enabled",
210
+ provenance: `${scopeLabel(scope)} hooks/${phase}`,
211
+ path: hookPath,
212
+ scope,
213
+ description: `${phase}-tool hook for ${baseName}`,
214
+ diagnostics: shadowed ? ["shadowed by the same hook at higher-precedence scope"] : undefined,
215
+ raw: { name: entry.name, type: phase, tool: baseName },
216
+ });
217
+ }
218
+ }
219
+ }
220
+ return rows;
221
+ }
222
+
223
+ // ---------------------------------------------------------------------------
224
+ // MCPs
225
+ // ---------------------------------------------------------------------------
226
+
227
+ function mcpDescription(name: string, server: Record<string, unknown>): string {
228
+ if (typeof server.command === "string" && server.command) {
229
+ return `stdio MCP "${name}" (command redacted)`;
230
+ }
231
+ const type = typeof server.type === "string" ? server.type : "http";
232
+ return `${type} MCP "${name}" (endpoint redacted)`;
233
+ }
234
+
235
+ async function loadMcpRows(options: LoadCustomizationInventoryOptions, warnings: string[]): Promise<InventoryRow[]> {
236
+ const rows: InventoryRow[] = [];
237
+ const disabledExtensions = new Set(
238
+ (options.disabledExtensions ?? []).filter(id => id.startsWith("mcp:")).map(id => id.slice("mcp:".length)),
239
+ );
240
+ const scopeConfigs = await Promise.all(
241
+ (["project", "global"] as const).map(async scope => {
242
+ const configPath = resolveScopePaths(scope, options.cwd).mcpConfigPath;
243
+ const config = await readMCPConfigFile(configPath).catch(() => null);
244
+ return { scope, configPath, config };
245
+ }),
246
+ );
247
+ const disabledServers = new Set(
248
+ scopeConfigs.flatMap(({ config }) => (Array.isArray(config?.disabledServers) ? config.disabledServers : [])),
249
+ );
250
+ // Runtime semantics: project scope wins; the user-global entry is shadowed.
251
+ const seen = new Set<string>();
252
+ for (const { scope, configPath: mcpConfigPath, config } of scopeConfigs) {
253
+ if (config === null) {
254
+ let exists = false;
255
+ try {
256
+ exists = (await fs.lstat(mcpConfigPath)).isFile();
257
+ } catch {
258
+ exists = false;
259
+ }
260
+ if (exists) {
261
+ warnings.push(`${mcpConfigPath} is malformed; fix or remove it to manage MCP servers`);
262
+ rows.push({
263
+ id: inventoryRowId("mcps", scope, mcpConfigPath),
264
+ surface: "mcps",
265
+ name: path.basename(mcpConfigPath),
266
+ displayName: path.basename(mcpConfigPath),
267
+ status: "invalid",
268
+ provenance: `${scopeLabel(scope)} MCP config`,
269
+ path: mcpConfigPath,
270
+ scope,
271
+ diagnostics: ["malformed MCP config file; fix or remove it (contents not shown)"],
272
+ raw: { path: mcpConfigPath },
273
+ });
274
+ }
275
+ continue;
276
+ }
277
+ const servers = config.mcpServers ?? {};
278
+ for (const [name, server] of Object.entries(servers).sort(([a], [b]) => a.localeCompare(b))) {
279
+ const shadowed = seen.has(name);
280
+ seen.add(name);
281
+ const record = server as unknown as Record<string, unknown>;
282
+ const validationError = mcpCapability.validate?.({
283
+ name,
284
+ ...record,
285
+ } as Parameters<NonNullable<typeof mcpCapability.validate>>[0]);
286
+ const isDisabled = disabledExtensions.has(name) || disabledServers.has(name) || record.enabled === false;
287
+ const status: InventoryStatus = validationError
288
+ ? "invalid"
289
+ : shadowed
290
+ ? "shadowed"
291
+ : isDisabled
292
+ ? "disabled"
293
+ : "enabled";
294
+ rows.push({
295
+ id: inventoryRowId("mcps", scope, `${mcpConfigPath}#${name}`),
296
+ surface: "mcps",
297
+ name,
298
+ displayName: name,
299
+ status,
300
+ provenance: `${scopeLabel(scope)} mcp.json`,
301
+ path: mcpConfigPath,
302
+ scope,
303
+ description: mcpDescription(name, record),
304
+ diagnostics: validationError
305
+ ? [validationError]
306
+ : shadowed
307
+ ? ["shadowed by the same server at higher-precedence scope"]
308
+ : undefined,
309
+ raw: redactServerForDisplay(record),
310
+ });
311
+ }
312
+ }
313
+ return rows;
314
+ }
315
+
316
+ // ---------------------------------------------------------------------------
317
+ // Aggregate
318
+ // ---------------------------------------------------------------------------
319
+
320
+ /**
321
+ * Load the full Skills/Hooks/MCPs inventory for the `/extensions` dashboard.
322
+ * Reads only the canonical `.gjc` scopes; foreign Claude/Codex layouts are
323
+ * import sources handled by the explicit import flow, never managed entries.
324
+ */
325
+ export async function loadCustomizationInventory(
326
+ options: LoadCustomizationInventoryOptions,
327
+ ): Promise<CustomizationInventory> {
328
+ const warnings: string[] = [];
329
+ const [skills, hooks, mcps] = await Promise.all([
330
+ loadSkillRows(options, warnings),
331
+ loadHookRows(options, warnings),
332
+ loadMcpRows(options, warnings),
333
+ ]);
334
+ return { rows: [...skills, ...hooks, ...mcps], warnings };
335
+ }
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Safe mutations for the `/extensions` umbrella customization surface
3
+ * (issue #4291). Every operation goes through the same canonical
4
+ * loaders/writers the runtime and CLI use — no parallel state model.
5
+ *
6
+ * - Skills: enable/disable via the authoritative `setNativeSkillEnabled`
7
+ * policy contract (the caller persists the returned `disabledExtensions`
8
+ * list through Settings); remove targets the exact discovered SKILL.md
9
+ * path identity with bundled-name and symlink protection.
10
+ * - MCPs: enable/disable via the `enabled` flag and remove via the canonical
11
+ * config writer (atomic write, cache invalidation included).
12
+ * - Hooks: remove only, by exact discovered path; enable/disable is not part
13
+ * of the canonical hook contract and is rejected by the UI with a
14
+ * diagnostic.
15
+ */
16
+ import * as fs from "node:fs/promises";
17
+ import * as path from "node:path";
18
+ import { setNativeSkillEnabled } from "../extensibility/skill-management";
19
+ import {
20
+ readMCPConfigFile,
21
+ removeMCPServer,
22
+ setServerDisabled,
23
+ writeMCPConfigFile,
24
+ } from "../runtime-mcp/config-writer";
25
+ import { CANONICAL_GJC_WORKFLOW_SKILLS } from "../skill-state/canonical-skills";
26
+
27
+ const BUNDLED_SKILL_NAMES: ReadonlySet<string> = new Set(CANONICAL_GJC_WORKFLOW_SKILLS);
28
+
29
+ export type MutationResult = { ok: true } | { ok: false; reason: string };
30
+
31
+ // ---------------------------------------------------------------------------
32
+ // Skills
33
+ // ---------------------------------------------------------------------------
34
+
35
+ /**
36
+ * Toggle a native skill through the authoritative policy contract. Returns
37
+ * the updated `disabledExtensions` list; the caller persists it via Settings.
38
+ * Bundled workflow skill names cannot be disabled.
39
+ */
40
+ export function setSkillEnabled(
41
+ name: string,
42
+ enabled: boolean,
43
+ disabledExtensions: string[],
44
+ ): MutationResult & { disabledExtensions?: string[] } {
45
+ if (!enabled && BUNDLED_SKILL_NAMES.has(name)) {
46
+ return { ok: false, reason: `"${name}" is a protected bundled workflow skill name` };
47
+ }
48
+ return { ok: true, disabledExtensions: setNativeSkillEnabled(name, enabled, disabledExtensions) };
49
+ }
50
+
51
+ /**
52
+ * Remove a native skill by its exact discovered SKILL.md path identity.
53
+ * Fails when the discovered file is absent, refuses symlinked directories or
54
+ * files, and never removes protected bundled workflow skill names.
55
+ */
56
+ export async function removeSkill(record: { name: string; path: string }): Promise<MutationResult> {
57
+ if (BUNDLED_SKILL_NAMES.has(record.name)) {
58
+ return { ok: false, reason: `"${record.name}" is a protected bundled workflow skill name` };
59
+ }
60
+ const dir = path.dirname(record.path);
61
+ try {
62
+ const fileStat = await fs.lstat(record.path);
63
+ if (fileStat.isSymbolicLink())
64
+ return { ok: false, reason: `refusing to remove symlinked skill file: ${record.path}` };
65
+ if (!fileStat.isFile())
66
+ return { ok: false, reason: `discovered skill file is not a regular file: ${record.path}` };
67
+ const dirStat = await fs.lstat(dir);
68
+ if (dirStat.isSymbolicLink())
69
+ return { ok: false, reason: `refusing to remove symlinked skill directory: ${dir}` };
70
+ if (!dirStat.isDirectory()) return { ok: false, reason: `not a skill directory: ${dir}` };
71
+ } catch {
72
+ return { ok: false, reason: `discovered skill file is absent: ${record.path}` };
73
+ }
74
+ await fs.rm(dir, { recursive: true, force: false });
75
+ return { ok: true };
76
+ }
77
+
78
+ // ---------------------------------------------------------------------------
79
+ // MCPs
80
+ // ---------------------------------------------------------------------------
81
+
82
+ /** Toggle a server through the canonical disabledServers denylist. */
83
+ export async function setMcpServerEnabled(
84
+ mcpConfigPath: string,
85
+ name: string,
86
+ enabled: boolean,
87
+ disabledExtensions: string[] = [],
88
+ ): Promise<MutationResult> {
89
+ const config = await readMCPConfigFile(mcpConfigPath).catch(() => null);
90
+ if (!config) return { ok: false, reason: `${mcpConfigPath} is malformed; fix or remove it first` };
91
+ const server = config.mcpServers?.[name];
92
+ if (!server) return { ok: false, reason: `server "${name}" not found in ${mcpConfigPath}` };
93
+ if (enabled && server.enabled === false) {
94
+ const updatedServer = { ...server };
95
+ delete updatedServer.enabled;
96
+ await writeMCPConfigFile(mcpConfigPath, {
97
+ ...config,
98
+ mcpServers: { ...config.mcpServers, [name]: updatedServer },
99
+ });
100
+ }
101
+ await setServerDisabled(mcpConfigPath, name, !enabled);
102
+ const id = `mcp:${name}`;
103
+ const nextDisabledExtensions = enabled
104
+ ? disabledExtensions.filter(entry => entry !== id)
105
+ : disabledExtensions.includes(id)
106
+ ? disabledExtensions
107
+ : [...disabledExtensions, id];
108
+ return { ok: true, disabledExtensions: nextDisabledExtensions } as MutationResult & {
109
+ disabledExtensions: string[];
110
+ };
111
+ }
112
+
113
+ /** Remove a server via the canonical config writer. */
114
+ export async function removeMcpServerEntry(mcpConfigPath: string, name: string): Promise<MutationResult> {
115
+ try {
116
+ await removeMCPServer(mcpConfigPath, name);
117
+ return { ok: true };
118
+ } catch (error) {
119
+ return { ok: false, reason: (error as Error).message };
120
+ }
121
+ }
122
+
123
+ // ---------------------------------------------------------------------------
124
+ // Hooks
125
+ // ---------------------------------------------------------------------------
126
+
127
+ /**
128
+ * Remove a hook by its exact discovered path. Refuses symlinks, non-files,
129
+ * and paths that do not exist (no silent success).
130
+ */
131
+ export async function removeHookFile(hookPath: string): Promise<MutationResult> {
132
+ try {
133
+ const stat = await fs.lstat(hookPath);
134
+ if (stat.isSymbolicLink()) return { ok: false, reason: `refusing to remove symlinked hook: ${hookPath}` };
135
+ if (!stat.isFile()) return { ok: false, reason: `not a hook file: ${hookPath}` };
136
+ await fs.rm(hookPath, { force: false });
137
+ return { ok: true };
138
+ } catch (error) {
139
+ return { ok: false, reason: (error as Error).message };
140
+ }
141
+ }