@gajae-code/coding-agent 0.11.11 → 0.12.1

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 (344) hide show
  1. package/CHANGELOG.md +131 -4
  2. package/dist/types/async/job-manager.d.ts +17 -3
  3. package/dist/types/cli/read-cli.d.ts +1 -0
  4. package/dist/types/commands/deep-interview.d.ts +9 -0
  5. package/dist/types/commands/harness.d.ts +22 -0
  6. package/dist/types/commands/read.d.ts +6 -0
  7. package/dist/types/config/model-registry.d.ts +4 -0
  8. package/dist/types/config/provider-auth-health.d.ts +14 -0
  9. package/dist/types/config/provider-ranking.d.ts +59 -0
  10. package/dist/types/config/settings-schema.d.ts +83 -1
  11. package/dist/types/config/settings.d.ts +2 -0
  12. package/dist/types/exa/mcp-client.d.ts +10 -1
  13. package/dist/types/exec/bash-executor.d.ts +45 -12
  14. package/dist/types/extensibility/extensions/types.d.ts +38 -4
  15. package/dist/types/extensibility/gjc-plugins/index.d.ts +12 -2
  16. package/dist/types/extensibility/gjc-plugins/installer.d.ts +63 -7
  17. package/dist/types/extensibility/gjc-plugins/lifecycle-reconciliation.d.ts +55 -0
  18. package/dist/types/extensibility/gjc-plugins/lifecycle.d.ts +64 -0
  19. package/dist/types/extensibility/gjc-plugins/runtime-quarantine.d.ts +67 -0
  20. package/dist/types/extensibility/gjc-plugins/session-validation.d.ts +3 -1
  21. package/dist/types/extensibility/gjc-plugins/types.d.ts +124 -0
  22. package/dist/types/extensibility/shared-events.d.ts +6 -0
  23. package/dist/types/gjc-runtime/deep-interview-ambiguity.d.ts +5 -12
  24. package/dist/types/gjc-runtime/deep-interview-recorder.d.ts +17 -32
  25. package/dist/types/gjc-runtime/deep-interview-stage.d.ts +37 -0
  26. package/dist/types/gjc-runtime/deep-interview-state.d.ts +4 -135
  27. package/dist/types/gjc-runtime/gc-runtime.d.ts +1 -1
  28. package/dist/types/gjc-runtime/launch-tmux.d.ts +1 -0
  29. package/dist/types/gjc-runtime/memory-guard-owner-claims.d.ts +47 -0
  30. package/dist/types/gjc-runtime/ralplan-runtime.d.ts +70 -1
  31. package/dist/types/gjc-runtime/state-writer.d.ts +5 -46
  32. package/dist/types/gjc-runtime/team-launch.d.ts +1 -1
  33. package/dist/types/gjc-runtime/team-runtime.d.ts +27 -1
  34. package/dist/types/gjc-runtime/team-store.d.ts +12 -0
  35. package/dist/types/gjc-runtime/team-worker-heartbeat.d.ts +43 -0
  36. package/dist/types/gjc-runtime/team-worker-memory-guard.d.ts +92 -0
  37. package/dist/types/gjc-runtime/tmux-owner-isolation.d.ts +17 -0
  38. package/dist/types/gjc-runtime/ultragoal-receipt-freshness.d.ts +8 -0
  39. package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +31 -80
  40. package/dist/types/gjc-runtime/workflow-manifest.d.ts +3 -5
  41. package/dist/types/internal-urls/local-root-gc.d.ts +2 -0
  42. package/dist/types/main.d.ts +1 -1
  43. package/dist/types/memories/index.d.ts +2 -0
  44. package/dist/types/modes/acp/acp-agent.d.ts +10 -19
  45. package/dist/types/modes/components/assistant-message.d.ts +3 -1
  46. package/dist/types/modes/components/gjc-bundle-settings.d.ts +34 -0
  47. package/dist/types/modes/components/irc-sidebar.d.ts +41 -0
  48. package/dist/types/modes/components/notifications-settings-editor.d.ts +1 -0
  49. package/dist/types/modes/components/read-tool-group.d.ts +4 -4
  50. package/dist/types/modes/components/session-observer-overlay.d.ts +22 -0
  51. package/dist/types/modes/components/settings-selector.d.ts +11 -0
  52. package/dist/types/modes/components/status-line/gh.d.ts +5 -0
  53. package/dist/types/modes/components/tool-execution.d.ts +8 -0
  54. package/dist/types/modes/components/transcript-viewer-overlay.d.ts +18 -1
  55. package/dist/types/modes/controllers/event-controller.d.ts +3 -0
  56. package/dist/types/modes/interactive-mode.d.ts +2 -0
  57. package/dist/types/modes/irc-observation-ledger.d.ts +17 -1
  58. package/dist/types/modes/types.d.ts +2 -0
  59. package/dist/types/modes/utils/ui-helpers.d.ts +16 -0
  60. package/dist/types/reminders/star-reminder.d.ts +3 -13
  61. package/dist/types/runtime-mcp/manager.d.ts +1 -0
  62. package/dist/types/runtime-mcp/smithery-auth.d.ts +5 -0
  63. package/dist/types/sdk/acp/adapter.d.ts +3 -1
  64. package/dist/types/sdk/broker/lifecycle.d.ts +5 -0
  65. package/dist/types/sdk/broker/transport.d.ts +2 -0
  66. package/dist/types/sdk/bus/attachment-registry.d.ts +1 -0
  67. package/dist/types/sdk/bus/chat-daemon-control.d.ts +4 -1
  68. package/dist/types/sdk/bus/config.d.ts +6 -2
  69. package/dist/types/sdk/bus/control-drain-lease.d.ts +52 -0
  70. package/dist/types/sdk/bus/index.d.ts +44 -1
  71. package/dist/types/sdk/bus/kind-aware-reconciliation.d.ts +44 -0
  72. package/dist/types/sdk/bus/lifecycle-control-runtime.d.ts +4 -0
  73. package/dist/types/sdk/bus/prompt-reconciliation.d.ts +2 -1
  74. package/dist/types/sdk/bus/reconciliation-store.d.ts +69 -0
  75. package/dist/types/sdk/bus/rich-draft.d.ts +1 -0
  76. package/dist/types/sdk/bus/rich-render.d.ts +2 -0
  77. package/dist/types/sdk/bus/telegram-adoption-intent.d.ts +165 -0
  78. package/dist/types/sdk/bus/telegram-cli.d.ts +12 -0
  79. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +11 -4
  80. package/dist/types/sdk/bus/telegram-daemon.d.ts +25 -1
  81. package/dist/types/sdk/bus/telegram-reference.d.ts +11 -1
  82. package/dist/types/sdk/bus/threaded-render.d.ts +3 -2
  83. package/dist/types/sdk/bus/topic-registry.d.ts +11 -1
  84. package/dist/types/sdk/host/control/operations.d.ts +1 -1
  85. package/dist/types/sdk/host/host.d.ts +2 -0
  86. package/dist/types/sdk/host/query/handlers.d.ts +5 -0
  87. package/dist/types/sdk/host/query/revision-store.d.ts +2 -0
  88. package/dist/types/sdk/host/reverse-leases.d.ts +1 -1
  89. package/dist/types/sdk/prompt-status.d.ts +23 -3
  90. package/dist/types/sdk/session.d.ts +6 -0
  91. package/dist/types/session/agent-session.d.ts +82 -12
  92. package/dist/types/session/artifacts.d.ts +8 -0
  93. package/dist/types/session/blob-store.d.ts +57 -4
  94. package/dist/types/session/internal/managed-session-storage.d.ts +8 -1
  95. package/dist/types/session/memory-guard-checkpoint-participant.d.ts +69 -0
  96. package/dist/types/session/session-manager.d.ts +48 -19
  97. package/dist/types/session/session-storage.d.ts +4 -0
  98. package/dist/types/session/streaming-output.d.ts +96 -12
  99. package/dist/types/setup/credential-import.d.ts +12 -0
  100. package/dist/types/skill-state/active-state.d.ts +12 -4
  101. package/dist/types/skill-state/workflow-hud.d.ts +9 -0
  102. package/dist/types/task/executor.d.ts +3 -2
  103. package/dist/types/task/index.d.ts +3 -1
  104. package/dist/types/task/provider-retry-status.d.ts +8 -0
  105. package/dist/types/task/receipt.d.ts +7 -1
  106. package/dist/types/task/types.d.ts +23 -0
  107. package/dist/types/tools/ask-answer-registry.d.ts +2 -2
  108. package/dist/types/tools/bash-interactive.d.ts +4 -1
  109. package/dist/types/tools/bash.d.ts +3 -1
  110. package/dist/types/tools/browser/launch.d.ts +7 -0
  111. package/dist/types/tools/fetch.d.ts +17 -1
  112. package/dist/types/tools/image-gen.d.ts +4 -0
  113. package/dist/types/tools/index.d.ts +4 -0
  114. package/dist/types/tools/output-meta.d.ts +44 -3
  115. package/dist/types/tools/path-utils.d.ts +1 -0
  116. package/dist/types/tools/read-internals.d.ts +12 -0
  117. package/dist/types/tools/read.d.ts +45 -7
  118. package/dist/types/tools/resource-gc.d.ts +4 -0
  119. package/dist/types/tools/review.d.ts +5 -7
  120. package/dist/types/tools/subagent.d.ts +2 -0
  121. package/dist/types/tools/tool-result.d.ts +7 -1
  122. package/dist/types/utils/gh.d.ts +13 -0
  123. package/dist/types/utils/image-resize.d.ts +1 -0
  124. package/dist/types/web/search/providers/kimi.d.ts +2 -0
  125. package/dist/types/web/search/providers/searxng.d.ts +7 -0
  126. package/dist/types/web/search/providers/xai.d.ts +2 -0
  127. package/package.json +11 -13
  128. package/scripts/acp-conformance-agent.ts +218 -0
  129. package/scripts/benchmark-sticky-viewport-pr1.ts +239 -0
  130. package/scripts/capture-gjc-bundle-settings.ts +306 -0
  131. package/scripts/capture-sticky-viewport-showcase.ts +292 -0
  132. package/scripts/generate-sdk-operation-inventory.ts +5 -0
  133. package/scripts/resident-memory-bench.ts +1341 -0
  134. package/scripts/run-acp-conformance.ts +285 -0
  135. package/scripts/verify-gjc-sdk-canonicalization.ts +122 -18
  136. package/scripts/verify-sticky-viewport-showcase.ts +611 -0
  137. package/src/async/job-manager.ts +78 -20
  138. package/src/capability/index.ts +8 -0
  139. package/src/cli/fast-help.ts +1 -1
  140. package/src/cli/plugin-cli.ts +176 -18
  141. package/src/cli/read-cli.ts +2 -1
  142. package/src/cli.ts +1 -0
  143. package/src/commands/deep-interview.ts +29 -9
  144. package/src/commands/harness.ts +35 -12
  145. package/src/commands/read.ts +11 -2
  146. package/src/commands/team.ts +20 -2
  147. package/src/config/file-lock.ts +11 -2
  148. package/src/config/model-registry.ts +21 -2
  149. package/src/config/provider-auth-health.ts +42 -0
  150. package/src/config/provider-ranking.ts +119 -0
  151. package/src/config/settings-schema.ts +74 -1
  152. package/src/config/settings.ts +246 -108
  153. package/src/coordinator-mcp/question-gate-codec.ts +1 -1
  154. package/src/coordinator-mcp/server.ts +5 -12
  155. package/src/defaults/gjc/skills/deep-interview/SKILL.md +230 -82
  156. package/src/defaults/gjc/skills/ralplan/SKILL.md +77 -41
  157. package/src/defaults/gjc/skills/team/SKILL.md +3 -1
  158. package/src/defaults/gjc/skills/ultragoal/SKILL.md +62 -39
  159. package/src/defaults/gjc/skills/ultragoal/validation-batch-contracts.md +12 -0
  160. package/src/defaults/gjc-defaults.ts +4 -4
  161. package/src/eval/py/executor.ts +7 -2
  162. package/src/exa/mcp-client.ts +12 -3
  163. package/src/exec/bash-executor.ts +144 -27
  164. package/src/extensibility/extensions/runner.ts +15 -0
  165. package/src/extensibility/extensions/types.ts +46 -5
  166. package/src/extensibility/gjc-plugins/constrained-hooks.ts +8 -2
  167. package/src/extensibility/gjc-plugins/index.ts +19 -2
  168. package/src/extensibility/gjc-plugins/installer.ts +189 -50
  169. package/src/extensibility/gjc-plugins/lifecycle-reconciliation.ts +199 -0
  170. package/src/extensibility/gjc-plugins/lifecycle.ts +626 -0
  171. package/src/extensibility/gjc-plugins/observability.ts +3 -3
  172. package/src/extensibility/gjc-plugins/prompt-appendix.ts +5 -1
  173. package/src/extensibility/gjc-plugins/runtime-adapters.ts +12 -2
  174. package/src/extensibility/gjc-plugins/runtime-quarantine.ts +121 -0
  175. package/src/extensibility/gjc-plugins/schema.ts +84 -12
  176. package/src/extensibility/gjc-plugins/session-validation.ts +9 -3
  177. package/src/extensibility/gjc-plugins/types.ts +141 -0
  178. package/src/extensibility/gjc-plugins/validation.ts +9 -0
  179. package/src/extensibility/shared-events.ts +5 -0
  180. package/src/gjc-runtime/deep-interview-ambiguity.ts +47 -82
  181. package/src/gjc-runtime/deep-interview-recorder.ts +227 -310
  182. package/src/gjc-runtime/deep-interview-runtime.ts +109 -270
  183. package/src/gjc-runtime/deep-interview-stage.ts +1016 -0
  184. package/src/gjc-runtime/deep-interview-state.ts +12 -943
  185. package/src/gjc-runtime/gc-render.ts +1 -0
  186. package/src/gjc-runtime/gc-runtime.ts +11 -1
  187. package/src/gjc-runtime/launch-tmux.ts +25 -6
  188. package/src/gjc-runtime/managed-owner-admission.ts +1 -1
  189. package/src/gjc-runtime/memory-guard-owner-claims.ts +389 -0
  190. package/src/gjc-runtime/ralplan-runtime.ts +1149 -98
  191. package/src/gjc-runtime/state-runtime.ts +2 -1
  192. package/src/gjc-runtime/state-writer.ts +70 -222
  193. package/src/gjc-runtime/team-launch.ts +42 -5
  194. package/src/gjc-runtime/team-runtime.ts +1085 -40
  195. package/src/gjc-runtime/team-store.ts +32 -0
  196. package/src/gjc-runtime/team-worker-heartbeat.ts +149 -0
  197. package/src/gjc-runtime/team-worker-memory-guard.ts +363 -0
  198. package/src/gjc-runtime/team-workers.ts +1 -0
  199. package/src/gjc-runtime/tmux-owner-isolation.ts +28 -0
  200. package/src/gjc-runtime/tmux-sessions.ts +58 -13
  201. package/src/gjc-runtime/ultragoal-receipt-freshness.ts +20 -0
  202. package/src/gjc-runtime/ultragoal-runtime.ts +414 -618
  203. package/src/gjc-runtime/workflow-manifest.generated.json +105 -449
  204. package/src/gjc-runtime/workflow-manifest.ts +38 -247
  205. package/src/hooks/native-skill-hook.ts +17 -4
  206. package/src/hooks/skill-state.ts +1 -23
  207. package/src/internal-urls/docs-index.generated.ts +21 -22
  208. package/src/internal-urls/local-root-gc.ts +127 -0
  209. package/src/main.ts +9 -5
  210. package/src/memories/index.ts +10 -0
  211. package/src/modes/DESIGN.md +98 -0
  212. package/src/modes/acp/acp-agent.ts +339 -191
  213. package/src/modes/acp/acp-event-mapper.ts +14 -7
  214. package/src/modes/acp/acp-mode.ts +39 -3
  215. package/src/modes/components/assistant-message.ts +123 -22
  216. package/src/modes/components/gjc-bundle-settings.ts +508 -0
  217. package/src/modes/components/irc-sidebar.ts +176 -62
  218. package/src/modes/components/model-selector.ts +61 -4
  219. package/src/modes/components/notifications-settings-editor.ts +12 -1
  220. package/src/modes/components/oauth-selector.ts +96 -28
  221. package/src/modes/components/read-tool-group.ts +82 -14
  222. package/src/modes/components/session-observer-overlay.ts +457 -83
  223. package/src/modes/components/settings-selector.ts +116 -23
  224. package/src/modes/components/status-line/gh.ts +16 -0
  225. package/src/modes/components/tool-execution.ts +138 -27
  226. package/src/modes/components/tool-status-header.ts +3 -14
  227. package/src/modes/components/transcript-viewer-overlay.ts +99 -24
  228. package/src/modes/controllers/command-controller.ts +4 -0
  229. package/src/modes/controllers/event-controller.ts +109 -27
  230. package/src/modes/controllers/extension-ui-controller.ts +26 -2
  231. package/src/modes/controllers/input-controller.ts +18 -3
  232. package/src/modes/controllers/selector-controller.ts +127 -36
  233. package/src/modes/interactive-mode.ts +62 -3
  234. package/src/modes/irc-observation-ledger.ts +71 -15
  235. package/src/modes/runtime-init.ts +22 -2
  236. package/src/modes/types.ts +2 -0
  237. package/src/modes/utils/ui-helpers.ts +94 -1
  238. package/src/prompts/agent-fragments/ralplan-persistence.md +4 -3
  239. package/src/prompts/agents/architect.md +9 -1
  240. package/src/prompts/agents/critic.md +9 -0
  241. package/src/prompts/system/eager-todo.md +8 -4
  242. package/src/prompts/system/system-prompt.md +11 -5
  243. package/src/prompts/tools/bash.md +5 -5
  244. package/src/prompts/tools/read.md +4 -2
  245. package/src/prompts/tools/search-tool-bm25.md +5 -0
  246. package/src/prompts/tools/task.md +1 -1
  247. package/src/reminders/star-reminder.ts +4 -42
  248. package/src/runtime-mcp/manager.ts +19 -4
  249. package/src/runtime-mcp/smithery-auth.ts +17 -2
  250. package/src/runtime-mcp/smithery-connect.ts +11 -1
  251. package/src/sdk/acp/adapter.ts +22 -6
  252. package/src/sdk/broker/lifecycle.ts +25 -6
  253. package/src/sdk/broker/transport.ts +35 -3
  254. package/src/sdk/bus/attachment-registry.ts +5 -1
  255. package/src/sdk/bus/chat-daemon-cli.ts +4 -39
  256. package/src/sdk/bus/chat-daemon-control.ts +6 -3
  257. package/src/sdk/bus/config.ts +18 -2
  258. package/src/sdk/bus/control-drain-lease.ts +104 -0
  259. package/src/sdk/bus/index.ts +984 -146
  260. package/src/sdk/bus/kind-aware-reconciliation.ts +317 -0
  261. package/src/sdk/bus/lifecycle-commands.ts +4 -1
  262. package/src/sdk/bus/lifecycle-control-runtime.ts +403 -88
  263. package/src/sdk/bus/prompt-reconciliation.ts +2 -1
  264. package/src/sdk/bus/reconciliation-store.ts +303 -0
  265. package/src/sdk/bus/rich-draft.ts +1 -1
  266. package/src/sdk/bus/rich-render.ts +2 -2
  267. package/src/sdk/bus/telegram-adoption-intent.ts +574 -0
  268. package/src/sdk/bus/telegram-cli.ts +33 -8
  269. package/src/sdk/bus/telegram-daemon-cli.ts +1 -0
  270. package/src/sdk/bus/telegram-daemon-contract.ts +11 -4
  271. package/src/sdk/bus/telegram-daemon.ts +916 -23
  272. package/src/sdk/bus/telegram-reference.ts +40 -3
  273. package/src/sdk/bus/threaded-render.ts +48 -3
  274. package/src/sdk/bus/topic-registry.ts +20 -0
  275. package/src/sdk/host/control/dispatch.ts +5 -1
  276. package/src/sdk/host/control/operations.ts +1 -1
  277. package/src/sdk/host/host.ts +23 -1
  278. package/src/sdk/host/query/handlers.ts +55 -0
  279. package/src/sdk/host/query/revision-store.ts +36 -2
  280. package/src/sdk/host/reverse-leases.ts +44 -7
  281. package/src/sdk/mcp/server.ts +46 -18
  282. package/src/sdk/prompt-status.ts +16 -3
  283. package/src/sdk/protocol/operation-inventory.generated.json +51 -0
  284. package/src/sdk/protocol/operation-registry.ts +7 -2
  285. package/src/sdk/session.ts +101 -10
  286. package/src/session/agent-session.ts +1286 -220
  287. package/src/session/artifacts.ts +22 -0
  288. package/src/session/auth-broker-config.ts +10 -3
  289. package/src/session/blob-store.ts +915 -24
  290. package/src/session/internal/managed-session-scope.ts +44 -6
  291. package/src/session/internal/managed-session-storage.ts +48 -6
  292. package/src/session/memory-guard-checkpoint-participant.ts +131 -0
  293. package/src/session/session-manager.ts +2364 -438
  294. package/src/session/session-storage.ts +9 -1
  295. package/src/session/streaming-output.ts +500 -111
  296. package/src/setup/credential-import.ts +75 -13
  297. package/src/setup/provider-onboarding.ts +19 -4
  298. package/src/skill-state/active-state.ts +32 -10
  299. package/src/skill-state/workflow-hud.ts +42 -2
  300. package/src/skill-state/workflow-mutation-guard.ts +560 -8
  301. package/src/task/executor.ts +122 -39
  302. package/src/task/index.ts +23 -14
  303. package/src/task/provider-retry-status.ts +16 -0
  304. package/src/task/receipt.ts +23 -7
  305. package/src/task/render.ts +6 -2
  306. package/src/task/types.ts +108 -0
  307. package/src/tools/ask-answer-registry.ts +12 -6
  308. package/src/tools/ask.ts +169 -118
  309. package/src/tools/ast-edit.ts +1 -0
  310. package/src/tools/ast-grep.ts +1 -0
  311. package/src/tools/bash-interactive.ts +8 -3
  312. package/src/tools/bash.ts +503 -60
  313. package/src/tools/browser/launch.ts +41 -6
  314. package/src/tools/fetch.ts +114 -23
  315. package/src/tools/find.ts +1 -0
  316. package/src/tools/image-gen.ts +29 -5
  317. package/src/tools/index.ts +4 -0
  318. package/src/tools/output-meta.ts +281 -20
  319. package/src/tools/path-utils.ts +8 -3
  320. package/src/tools/read-internals.ts +44 -0
  321. package/src/tools/read.ts +1560 -310
  322. package/src/tools/resource-gc.ts +182 -18
  323. package/src/tools/review.ts +5 -7
  324. package/src/tools/search.ts +1 -0
  325. package/src/tools/subagent-render.ts +6 -2
  326. package/src/tools/subagent.ts +6 -0
  327. package/src/tools/telegram-send.ts +6 -3
  328. package/src/tools/tool-result.ts +14 -1
  329. package/src/utils/gh.ts +39 -0
  330. package/src/utils/image-resize.ts +3 -0
  331. package/src/web/search/providers/anthropic.ts +4 -4
  332. package/src/web/search/providers/codex.ts +1 -1
  333. package/src/web/search/providers/kimi.ts +15 -5
  334. package/src/web/search/providers/searxng.ts +47 -4
  335. package/src/web/search/providers/xai.ts +7 -2
  336. package/dist/types/gjc-runtime/deep-interview-draft.d.ts +0 -8
  337. package/dist/types/gjc-runtime/deep-interview-payload.d.ts +0 -41
  338. package/dist/types/gjc-runtime/deep-interview-repair.d.ts +0 -17
  339. package/dist/types/gjc-runtime/ultragoal-pipeline.d.ts +0 -23
  340. package/src/defaults/gjc/skills/ultragoal/pipeline-validation-contracts.md +0 -30
  341. package/src/gjc-runtime/deep-interview-draft.ts +0 -843
  342. package/src/gjc-runtime/deep-interview-payload.ts +0 -262
  343. package/src/gjc-runtime/deep-interview-repair.ts +0 -1674
  344. package/src/gjc-runtime/ultragoal-pipeline.ts +0 -306
@@ -1,5 +1,5 @@
1
1
  import type { TSchema } from "@gajae-code/ai";
2
- import { $env, logger } from "@gajae-code/utils";
2
+ import { $credentialEnv, logger } from "@gajae-code/utils";
3
3
  import type { CustomTool, CustomToolResult } from "../extensibility/custom-tools/types";
4
4
  import { callMCP } from "../runtime-mcp/json-rpc";
5
5
  import type {
@@ -11,9 +11,18 @@ import type {
11
11
  MCPToolWrapperConfig,
12
12
  } from "./types";
13
13
 
14
- /** Find EXA_API_KEY from Bun.env or .env files */
14
+ /**
15
+ * Find `EXA_API_KEY` from trusted environment sources.
16
+ *
17
+ * The key authenticates every Exa MCP call and travels in the request URL, so
18
+ * whatever can set it decides which account the agent's searches run through —
19
+ * and therefore who can see those queries. `$env` merges the caller's `cwd/.env`
20
+ * into `process.env`, so reading it there would let repository content supply
21
+ * that account. Resolve it the same way provider credentials are: launching
22
+ * shell plus GJC/user-owned `.env` files, never the project `.env`.
23
+ */
15
24
  export function findApiKey(): string | null {
16
- return $env.EXA_API_KEY;
25
+ return $credentialEnv("EXA_API_KEY") ?? null;
17
26
  }
18
27
 
19
28
  function asRecord(value: unknown): Record<string, unknown> | null {
@@ -8,12 +8,125 @@ import { executeShell, type MinimizerOptions, Shell } from "@gajae-code/natives"
8
8
  import { postmortem } from "@gajae-code/utils";
9
9
  import { Settings, type ShellMinimizerSettings } from "../config/settings";
10
10
  import { formatCrashDiagnosticNotice, writeCrashReport } from "../debug/crash-diagnostics";
11
- import { OutputSink } from "../session/streaming-output";
12
- import { resolveOutputMaxColumns, resolveOutputSinkHeadBytes } from "../tools/output-meta";
11
+ import {
12
+ DEFAULT_ARTIFACT_MAX_BYTES,
13
+ DEFAULT_MAX_BYTES,
14
+ OutputSink,
15
+ type TerminalArtifactPublisher,
16
+ truncateHeadBytes,
17
+ } from "../session/streaming-output";
18
+ import { formatArtifactReference, resolveOutputMaxColumns, resolveOutputSinkHeadBytes } from "../tools/output-meta";
13
19
  import { getOrCreateSnapshot } from "../utils/shell-snapshot";
14
20
  import { NON_INTERACTIVE_ENV } from "./non-interactive-env";
15
21
 
22
+ export interface BashArtifactSaveSummary {
23
+ artifactId: string;
24
+ complete: boolean;
25
+ omittedBytes?: number;
26
+ }
27
+
28
+ export type BashMinimizedSaveReturn = BashArtifactSaveResult | BashArtifactSaveSummary | string | undefined;
29
+
30
+ export type BashArtifactSaveResult =
31
+ | { status: "saved"; artifactId: string; complete: true; omittedBytes?: undefined }
32
+ | { status: "saved"; artifactId: string; complete: false; omittedBytes: number }
33
+ | { status: "unavailable" }
34
+ | { status: "failed"; diagnostic: string };
35
+
36
+ function summarizeLegacyArtifactSave(artifactId: string, originalText: string): BashArtifactSaveResult {
37
+ const inputBytes = Buffer.byteLength(originalText, "utf-8");
38
+ if (inputBytes <= DEFAULT_ARTIFACT_MAX_BYTES) {
39
+ return { status: "saved", artifactId, complete: true };
40
+ }
41
+ const retainedBytes = truncateHeadBytes(originalText, DEFAULT_ARTIFACT_MAX_BYTES).bytes;
42
+ return {
43
+ status: "saved",
44
+ artifactId,
45
+ complete: false,
46
+ omittedBytes: inputBytes - retainedBytes,
47
+ };
48
+ }
49
+
50
+ function normalizeExplicitSavedArtifact(
51
+ artifactId: string,
52
+ complete: boolean,
53
+ omittedBytes: number | undefined,
54
+ ): BashArtifactSaveResult {
55
+ if (complete) {
56
+ return (omittedBytes ?? 0) > 0
57
+ ? { status: "failed", diagnostic: "artifact save reported complete output with omitted bytes" }
58
+ : { status: "saved", artifactId, complete: true };
59
+ }
60
+ return typeof omittedBytes === "number" && omittedBytes > 0
61
+ ? { status: "saved", artifactId, complete: false, omittedBytes }
62
+ : { status: "failed", diagnostic: "artifact save reported incomplete output without omitted bytes" };
63
+ }
64
+
65
+ function normalizeMinimizedSaveResult(value: BashMinimizedSaveReturn, originalText: string): BashArtifactSaveResult {
66
+ if (typeof value === "string") return summarizeLegacyArtifactSave(value, originalText);
67
+ if (!value) return { status: "unavailable" };
68
+ if (!("status" in value)) {
69
+ return normalizeExplicitSavedArtifact(value.artifactId, value.complete, value.omittedBytes);
70
+ }
71
+ if (value.status !== "saved") return value;
72
+ return normalizeExplicitSavedArtifact(value.artifactId, value.complete, value.omittedBytes);
73
+ }
74
+
75
+ export function normalizeMinimizedSaveResultForTests(
76
+ value: BashMinimizedSaveReturn,
77
+ originalText: string,
78
+ ): BashArtifactSaveResult {
79
+ return normalizeMinimizedSaveResult(value, originalText);
80
+ }
81
+
82
+ function completeRawArtifactAvailable(summary: {
83
+ artifactId?: string;
84
+ artifactTruncatedBytes?: number;
85
+ artifactFailureDiagnostic?: string;
86
+ }): boolean {
87
+ return (
88
+ summary.artifactId !== undefined &&
89
+ (summary.artifactTruncatedBytes ?? 0) <= 0 &&
90
+ summary.artifactFailureDiagnostic === undefined
91
+ );
92
+ }
93
+
94
+ function appendModelNotice(output: string, notice: string): string {
95
+ const separator = output.length > 0 && !output.endsWith("\n") ? "\n" : "";
96
+ return `${output}${separator}${notice}\n`;
97
+ }
98
+
99
+ function minimizedSaveNotice(
100
+ result: BashArtifactSaveResult,
101
+ summary: { artifactId?: string; artifactTruncatedBytes?: number; artifactFailureDiagnostic?: string },
102
+ ): string | undefined {
103
+ if (result.status === "failed") return `Bash output artifact save failed: ${result.diagnostic}`;
104
+ if (result.status === "unavailable" && !completeRawArtifactAvailable(summary)) {
105
+ return "Bash output artifact unavailable: full original output could not be stored because artifact storage is unavailable.";
106
+ }
107
+ return undefined;
108
+ }
109
+
110
+ function minimizedArtifactFooter(result: Extract<BashArtifactSaveResult, { status: "saved" }>): string {
111
+ const reference = result.complete
112
+ ? `artifact://${result.artifactId}`
113
+ : formatArtifactReference(result.artifactId, result.omittedBytes);
114
+ return `[raw output: ${reference}]`;
115
+ }
116
+
16
117
  export interface BashExecutorOptions {
118
+ /**
119
+ * Invoked when the native minimizer rewrote the command's output, giving
120
+ * the caller a chance to persist the lossless original capture (typically
121
+ * via the session's `ArtifactManager`). Complete saves preserve the
122
+ * historical `[raw output: artifact://<id>]` footer; capped saves carry an
123
+ * honest retained/omitted reference. A legacy string id is still accepted
124
+ * for non-tool callers and is classified from the original UTF-8 byte count.
125
+ */
126
+ onMinimizedSave?: (
127
+ originalText: string,
128
+ info: { filter: string; inputBytes: number; outputBytes: number },
129
+ ) => Promise<BashMinimizedSaveReturn>;
17
130
  cwd?: string;
18
131
  timeout?: number | null;
19
132
  onChunk?: (chunk: string) => void;
@@ -32,23 +145,18 @@ export interface BashExecutorOptions {
32
145
  /** Artifact path/id for full output storage */
33
146
  artifactPath?: string;
34
147
  artifactId?: string;
148
+ /** Optional terminal publisher for managed artifacts without writable paths. */
149
+ artifactPublisher?: TerminalArtifactPublisher;
150
+ /** Optional Bash-specific retained tail budget in bytes. */
151
+ spillThreshold?: number;
152
+ /** Optional Bash-specific retained head budget in bytes. */
153
+ headBytes?: number;
35
154
  /** Execute without retaining a native Shell in the persistent session registry. */
36
155
  oneShot?: boolean;
37
156
  /** Ignore user-configured shell command prefixes. Used by constrained read-only shells. */
38
157
  ignoreShellPrefix?: boolean;
39
158
  /** Skip sourced shell snapshots. Used by constrained read-only shells. */
40
159
  disableShellSnapshot?: boolean;
41
- /**
42
- * Invoked when the native minimizer rewrote the command's output, giving
43
- * the caller a chance to persist the lossless original capture (typically
44
- * via the session's `ArtifactManager`). The returned id is spliced into
45
- * the sink output as `artifact://<id>` so the agent can retrieve the raw
46
- * bytes. Return `undefined` to skip the footer.
47
- */
48
- onMinimizedSave?: (
49
- originalText: string,
50
- info: { filter: string; inputBytes: number; outputBytes: number },
51
- ) => Promise<string | undefined>;
52
160
  }
53
161
 
54
162
  export interface BashResult {
@@ -61,6 +169,8 @@ export interface BashResult {
61
169
  outputLines: number;
62
170
  outputBytes: number;
63
171
  artifactId?: string;
172
+ artifactTruncatedBytes?: number;
173
+ artifactFailureDiagnostic?: string;
64
174
  }
65
175
 
66
176
  const shellSessions = new Map<string, Shell>();
@@ -144,7 +254,9 @@ export async function executeBash(command: string, options?: BashExecutorOptions
144
254
  onRawChunk: options?.onRawChunk,
145
255
  artifactPath: options?.artifactPath,
146
256
  artifactId: options?.artifactId,
147
- headBytes: resolveOutputSinkHeadBytes(settings),
257
+ artifactPublisher: options?.artifactPublisher,
258
+ spillThreshold: options?.spillThreshold ?? DEFAULT_MAX_BYTES,
259
+ headBytes: options?.headBytes ?? resolveOutputSinkHeadBytes(settings),
148
260
  maxColumns: resolveOutputMaxColumns(settings),
149
261
  // Throttle the streaming preview callback to avoid saturating the
150
262
  // event loop when commands produce massive output (e.g. seq 1 50M).
@@ -332,21 +444,23 @@ export async function executeBash(command: string, options?: BashExecutorOptions
332
444
 
333
445
  // When the native minimizer rewrote the output, swap the sink's accumulated
334
446
  // raw stream for the minimized text, persist the original as a session
335
- // artifact, and splice an `artifact://<id>` footer into the visible text so
336
- // the agent can retrieve the raw bytes losslessly.
447
+ // artifact, and splice an artifact footer into the visible text so the agent
448
+ // can retrieve retained raw bytes without a false completeness claim.
337
449
  const minimized = winner.result.minimized;
450
+ let minimizedSaveResult: BashArtifactSaveResult | undefined;
338
451
  if (minimized && minimized.text !== minimized.originalText) {
339
452
  sink.replace(minimized.text);
340
- if (options?.onMinimizedSave) {
341
- const artifactId = await options.onMinimizedSave(minimized.originalText, {
342
- filter: minimized.filter,
343
- inputBytes: minimized.inputBytes,
344
- outputBytes: minimized.outputBytes,
345
- });
346
- if (artifactId) {
347
- const sep = minimized.text.endsWith("\n") ? "" : "\n";
348
- sink.push(`${sep}[raw output: artifact://${artifactId}]\n`);
349
- }
453
+ const saved = options?.onMinimizedSave
454
+ ? await options.onMinimizedSave(minimized.originalText, {
455
+ filter: minimized.filter,
456
+ inputBytes: minimized.inputBytes,
457
+ outputBytes: minimized.outputBytes,
458
+ })
459
+ : undefined;
460
+ minimizedSaveResult = normalizeMinimizedSaveResult(saved, minimized.originalText);
461
+ if (minimizedSaveResult.status === "saved") {
462
+ const sep = minimized.text.endsWith("\n") ? "" : "\n";
463
+ sink.push(`${sep}${minimizedArtifactFooter(minimizedSaveResult)}\n`);
350
464
  }
351
465
  }
352
466
 
@@ -366,10 +480,13 @@ export async function executeBash(command: string, options?: BashExecutorOptions
366
480
  }
367
481
 
368
482
  // Normal completion
483
+ const summary = await sink.dump();
484
+ const saveNotice = minimizedSaveResult ? minimizedSaveNotice(minimizedSaveResult, summary) : undefined;
369
485
  return {
370
486
  exitCode: winner.result.exitCode,
371
487
  cancelled: false,
372
- ...(await sink.dump()),
488
+ ...summary,
489
+ ...(saveNotice ? { output: appendModelNotice(summary.output, saveNotice) } : {}),
373
490
  };
374
491
  } catch (err) {
375
492
  resetSession = true;
@@ -179,8 +179,12 @@ export class ExtensionRunner {
179
179
 
180
180
  #getModel: () => Model | undefined = () => undefined;
181
181
  #isIdleFn: () => boolean = () => true;
182
+ #getActivePromptHandleFn: () => string | undefined = () => undefined;
182
183
  #waitForIdleFn: () => Promise<void> = async () => {};
183
184
  #abortFn: () => void = () => {};
185
+ #abortPromptAndWaitFn: NonNullable<ExtensionContextActions["abortPromptAndWait"]> = async () => {
186
+ throw new Error("abortPromptAndWait binding is unavailable");
187
+ };
184
188
  #hasPendingMessagesFn: () => boolean = () => false;
185
189
  #getPendingMessageCountsFn: () => { steering: number; followUp: number; nextTurn: number } = () => ({
186
190
  steering: 0,
@@ -214,6 +218,7 @@ export class ExtensionRunner {
214
218
  #getJobsFn: ExtensionContextActions["getJobs"] = undefined;
215
219
  #sdkControlFn: ExtensionContextActions["sdkControl"] = undefined;
216
220
  #setSdkPermissionProviderFn: ExtensionContextActions["setSdkPermissionProvider"] = undefined;
221
+ #setSdkClientBridgeFn: ExtensionContextActions["setSdkClientBridge"] = undefined;
217
222
 
218
223
  #invokeSkillFn: ExtensionContextActions["invokeSkill"] = undefined;
219
224
  #setPlanModeFn: ExtensionContextActions["setPlanMode"] = undefined;
@@ -297,7 +302,13 @@ export class ExtensionRunner {
297
302
  // Context actions (required)
298
303
  this.#getModel = contextActions.getModel;
299
304
  this.#isIdleFn = contextActions.isIdle;
305
+ this.#getActivePromptHandleFn = contextActions.getActivePromptHandle ?? (() => undefined);
300
306
  this.#abortFn = contextActions.abort;
307
+ this.#abortPromptAndWaitFn =
308
+ contextActions.abortPromptAndWait ??
309
+ (async () => {
310
+ throw new Error("abortPromptAndWait binding is unavailable");
311
+ });
301
312
  this.#hasPendingMessagesFn = contextActions.hasPendingMessages;
302
313
  this.#getPendingMessageCountsFn =
303
314
  contextActions.getPendingMessageCounts ?? (() => ({ steering: 0, followUp: 0, nextTurn: 0 }));
@@ -331,6 +342,7 @@ export class ExtensionRunner {
331
342
  this.#getJobsFn = contextActions.getJobs;
332
343
  this.#sdkControlFn = contextActions.sdkControl;
333
344
  this.#setSdkPermissionProviderFn = contextActions.setSdkPermissionProvider;
345
+ this.#setSdkClientBridgeFn = contextActions.setSdkClientBridge;
334
346
 
335
347
  // Command context actions (optional, only for interactive mode)
336
348
  if (commandContextActions) {
@@ -551,8 +563,10 @@ export class ExtensionRunner {
551
563
  get model() {
552
564
  return getModel();
553
565
  },
566
+ getActivePromptHandle: () => this.#getActivePromptHandleFn(),
554
567
  isIdle: () => this.#isIdleFn(),
555
568
  abort: () => this.#abortFn(),
569
+ abortPromptAndWait: (handle, options) => this.#abortPromptAndWaitFn(handle, options),
556
570
  hasPendingMessages: () => this.#hasPendingMessagesFn(),
557
571
  getPendingMessageCounts: () => this.#getPendingMessageCountsFn(),
558
572
  getTranscript: () => this.#getTranscriptFn(),
@@ -582,6 +596,7 @@ export class ExtensionRunner {
582
596
  getJobs: () => this.#getJobsFn?.(),
583
597
  sdkControl: (operation, input) => this.#sdkControlFn?.(operation, input),
584
598
  setSdkPermissionProvider: provider => this.#setSdkPermissionProviderFn?.(provider),
599
+ setSdkClientBridge: bridge => this.#setSdkClientBridgeFn?.(bridge),
585
600
  sdkBindings: () => [
586
601
  ...(this.#cycleModelFn ? ["cycleModel"] : []),
587
602
  ...(this.#setModelProfileFn ? ["setModelProfile"] : []),
@@ -8,7 +8,13 @@
8
8
  * - Interact with the user via UI primitives
9
9
  */
10
10
 
11
- import type { AgentMessage, AgentToolResult, AgentToolUpdateCallback, ThinkingLevel } from "@gajae-code/agent-core";
11
+ import type {
12
+ AgentMessage,
13
+ AgentToolResult,
14
+ AgentToolUpdateCallback,
15
+ RunSettlementProof,
16
+ ThinkingLevel,
17
+ } from "@gajae-code/agent-core";
12
18
  import type { CompactionResult } from "@gajae-code/agent-core/compaction";
13
19
  import type {
14
20
  Api,
@@ -38,6 +44,7 @@ import type { CustomEditor } from "../../modes/components/custom-editor";
38
44
  import type { WorkflowGateEmitter } from "../../modes/shared/agent-wire/workflow-gate-broker";
39
45
  import type { Theme } from "../../modes/theme/theme";
40
46
  import type {
47
+ ClientBridge,
41
48
  ClientBridgePermissionOption,
42
49
  ClientBridgePermissionOutcome,
43
50
  ClientBridgePermissionToolCall,
@@ -355,8 +362,12 @@ export interface ExtensionContext {
355
362
  model: Model | undefined;
356
363
  /** Whether the agent is idle (not streaming) */
357
364
  isIdle(): boolean;
365
+ /** Stable resource ownership identifier for the active prompt run. */
366
+ getActivePromptHandle(): string | undefined;
358
367
  /** Abort the current agent operation */
359
368
  abort(): void;
369
+ /** Abort and prove whether resources for a specific prompt settled. */
370
+ abortPromptAndWait?(handle: string, options: { graceMs: number }): Promise<RunSettlementProof>;
360
371
  /** Whether there are queued messages waiting */
361
372
  hasPendingMessages(): boolean;
362
373
  /** Typed pending-message counts per queue (steering, follow-up, next-turn). */
@@ -392,7 +403,15 @@ export interface ExtensionContext {
392
403
 
393
404
  getJobs(): unknown;
394
405
  /** Typed skill and mode controls exposed to the SDK host. */
395
- invokeSkill?(name: string, args?: string): Promise<unknown>;
406
+ invokeSkill?(
407
+ name: string,
408
+ args?: string,
409
+ options?: {
410
+ onPreflightAccepted?: () => void;
411
+ onPreflightAcceptCommit?: () => void | Promise<void>;
412
+ onSkillPrepared?: (meta: { name: string; path: string; lineCount?: number; cleanedArgs?: string }) => void;
413
+ },
414
+ ): Promise<unknown>;
396
415
  setPlanMode?(on: boolean): unknown;
397
416
  operateGoal?(op: "create" | "get" | "resume" | "pause" | "complete" | "drop", objective?: string): Promise<unknown>;
398
417
 
@@ -408,6 +427,8 @@ export interface ExtensionContext {
408
427
  ) => Promise<ClientBridgePermissionOutcome>)
409
428
  | undefined,
410
429
  ): void;
430
+ /** Install a client bridge backed by a live SDK reverse provider lease. */
431
+ setSdkClientBridge?(bridge: ClientBridge | undefined): void;
411
432
  /** Names of session SDK seams actually installed by the active runtime. */
412
433
  sdkBindings?(): readonly string[];
413
434
 
@@ -1135,7 +1156,11 @@ export interface ExtensionAPI {
1135
1156
  /** Send a user message to the agent, or queue it when deliverAs is set. */
1136
1157
  sendUserMessage(
1137
1158
  content: string | (TextContent | ImageContent)[],
1138
- options?: { deliverAs?: "steer" | "followUp"; onPreflightAccepted?: () => void },
1159
+ options?: {
1160
+ deliverAs?: "steer" | "followUp";
1161
+ onPreflightAccepted?: () => void;
1162
+ onPreflightAcceptCommit?: () => void | Promise<void>;
1163
+ },
1139
1164
  ): Promise<void>;
1140
1165
 
1141
1166
  /** Append a custom entry to the session for state persistence (not sent to LLM). */
@@ -1344,7 +1369,11 @@ export type SendMessageHandler = <T = unknown>(
1344
1369
 
1345
1370
  export type SendUserMessageHandler = (
1346
1371
  content: string | (TextContent | ImageContent)[],
1347
- options?: { deliverAs?: "steer" | "followUp"; onPreflightAccepted?: () => void },
1372
+ options?: {
1373
+ deliverAs?: "steer" | "followUp";
1374
+ onPreflightAccepted?: () => void;
1375
+ onPreflightAcceptCommit?: () => void | Promise<void>;
1376
+ },
1348
1377
  ) => void | Promise<void>;
1349
1378
 
1350
1379
  export type AppendEntryHandler = <T = unknown>(customType: string, data?: T) => void;
@@ -1420,7 +1449,10 @@ export interface ExtensionActions {
1420
1449
  export interface ExtensionContextActions {
1421
1450
  getModel: () => Model | undefined;
1422
1451
  isIdle: () => boolean;
1452
+ /** Stable resource ownership identifier for the active prompt run. */
1453
+ getActivePromptHandle?: () => string | undefined;
1423
1454
  abort: () => void;
1455
+ abortPromptAndWait?: (handle: string, options: { graceMs: number }) => Promise<RunSettlementProof>;
1424
1456
  hasPendingMessages: () => boolean;
1425
1457
  /** Typed pending-message counts per queue; optional for embedders without a counted queue. */
1426
1458
  getPendingMessageCounts?: () => { steering: number; followUp: number; nextTurn: number };
@@ -1468,8 +1500,17 @@ export interface ExtensionContextActions {
1468
1500
  ) => Promise<ClientBridgePermissionOutcome>)
1469
1501
  | undefined,
1470
1502
  ) => void;
1503
+ setSdkClientBridge?: (bridge: ClientBridge | undefined) => void;
1471
1504
  sdkControl?: (operation: string, input: Record<string, unknown>) => unknown | Promise<unknown>;
1472
- invokeSkill?: (name: string, args?: string) => Promise<unknown>;
1505
+ invokeSkill?: (
1506
+ name: string,
1507
+ args?: string,
1508
+ options?: {
1509
+ onPreflightAccepted?: () => void;
1510
+ onPreflightAcceptCommit?: () => void | Promise<void>;
1511
+ onSkillPrepared?: (meta: { name: string; path: string; lineCount?: number; cleanedArgs?: string }) => void;
1512
+ },
1513
+ ) => Promise<unknown>;
1473
1514
  setPlanMode?: (on: boolean) => unknown;
1474
1515
  operateGoal?: (
1475
1516
  op: "create" | "get" | "resume" | "pause" | "complete" | "drop",
@@ -1,8 +1,8 @@
1
1
  import { logger } from "@gajae-code/utils";
2
-
2
+ import { bundleIdentity } from "./lifecycle-reconciliation";
3
3
  import { loadEffectiveGjcPluginRegistry } from "./registry";
4
4
  import { type SessionQuarantine, validateSessionBundles, verifyEntryHashes } from "./session-validation";
5
- import { GjcPluginLoadError, type GjcPluginRegistryEntry } from "./types";
5
+ import { GjcPluginLoadError, type GjcPluginRegistryEntry, type GjcPluginScope } from "./types";
6
6
 
7
7
  /**
8
8
  * Constrained plugin-hook loader.
@@ -37,6 +37,7 @@ const DENIED_API_METHODS = [
37
37
 
38
38
  interface DeclaredHook {
39
39
  plugin: string;
40
+ scope: GjcPluginScope;
40
41
  event: string;
41
42
  target?: string;
42
43
  phase?: "before" | "after";
@@ -52,6 +53,7 @@ function collectDeclaredHooks(entries: readonly GjcPluginRegistryEntry[]): Decla
52
53
  if (disabled.has(h.extensionId)) continue;
53
54
  out.push({
54
55
  plugin: entry.name,
56
+ scope: entry.scope,
55
57
  event: h.event,
56
58
  target: h.target,
57
59
  phase: h.phase,
@@ -88,6 +90,7 @@ async function loadOneHook(
88
90
  return {
89
91
  hook: null,
90
92
  quarantine: {
93
+ identity: bundleIdentity(declared.scope, declared.plugin),
91
94
  plugin: declared.plugin,
92
95
  surfaceId: `hook:${declared.event}:${declared.target ?? ""}`,
93
96
  code: "invalid_hook",
@@ -99,6 +102,7 @@ async function loadOneHook(
99
102
  return {
100
103
  hook: null,
101
104
  quarantine: {
105
+ identity: bundleIdentity(declared.scope, declared.plugin),
102
106
  plugin: declared.plugin,
103
107
  surfaceId: `hook:${declared.event}`,
104
108
  code: "invalid_hook",
@@ -113,6 +117,7 @@ async function loadOneHook(
113
117
  return {
114
118
  hook: null,
115
119
  quarantine: {
120
+ identity: bundleIdentity(declared.scope, declared.plugin),
116
121
  plugin: declared.plugin,
117
122
  surfaceId: `hook:${declared.event}`,
118
123
  code,
@@ -125,6 +130,7 @@ async function loadOneHook(
125
130
  return {
126
131
  hook: null,
127
132
  quarantine: {
133
+ identity: bundleIdentity(declared.scope, declared.plugin),
128
134
  plugin: declared.plugin,
129
135
  surfaceId: `hook:${declared.event}`,
130
136
  code: "runtime_mismatch",
@@ -2,14 +2,31 @@ export * from "./activation";
2
2
  export * from "./compiler";
3
3
  export * from "./constrained-hooks";
4
4
  export * from "./injection";
5
- export * from "./installer";
5
+ /**
6
+ * Public barrel. Mutation primitives are deliberately NOT re-exported here:
7
+ * `lifecycle.ts` is the sole policy and persistence writer, so the installer
8
+ * transaction and the registry writers stay reachable only through their own
9
+ * modules. Re-exporting them would let a caller commit a replacement and
10
+ * bypass the create-only rule.
11
+ */
12
+ export { isGjcPluginBundleSource, isGjcPluginSourceShape } from "./installer";
13
+ export * from "./lifecycle";
14
+ export * from "./lifecycle-reconciliation";
6
15
  export * from "./loader";
7
16
  export * from "./mcp-policy";
8
17
  export * from "./observability";
9
18
  export * from "./paths";
10
19
  export * from "./prompt-appendix";
11
- export * from "./registry";
20
+ export {
21
+ loadEffectiveGjcPluginRegistry,
22
+ readRegistry,
23
+ registryEntryFingerprint,
24
+ registryPathForScope,
25
+ registryRootForScope,
26
+ sortRegistryEntries,
27
+ } from "./registry";
12
28
  export * from "./runtime-adapters";
29
+ export * from "./runtime-quarantine";
13
30
  export * from "./schema";
14
31
  export * from "./session-validation";
15
32
  export * from "./state";