@gajae-code/coding-agent 0.14.2 → 0.15.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 (345) hide show
  1. package/CHANGELOG.md +120 -1
  2. package/dist/types/async/job-manager.d.ts +4 -1
  3. package/dist/types/autoresearch/dashboard.d.ts +29 -4
  4. package/dist/types/autoresearch/data-context.d.ts +25 -0
  5. package/dist/types/autoresearch/git.d.ts +65 -7
  6. package/dist/types/autoresearch/harness.d.ts +58 -0
  7. package/dist/types/autoresearch/prompts.d.ts +51 -0
  8. package/dist/types/autoresearch/runs.d.ts +173 -0
  9. package/dist/types/autoresearch/types.d.ts +9 -139
  10. package/dist/types/capability/types.d.ts +20 -0
  11. package/dist/types/cli/accounts-cli.d.ts +1 -0
  12. package/dist/types/commands/{rlm.d.ts → autoresearch.d.ts} +2 -4
  13. package/dist/types/config/autorouting-contract.d.ts +146 -0
  14. package/dist/types/config/autorouting-generator.d.ts +40 -0
  15. package/dist/types/config/autorouting-tier-map.d.ts +16844 -0
  16. package/dist/types/config/autorouting.d.ts +35 -0
  17. package/dist/types/config/model-discovery-manager.d.ts +8 -1
  18. package/dist/types/config/model-registry.d.ts +30 -1
  19. package/dist/types/config/provider-selection-policy.d.ts +23 -0
  20. package/dist/types/config/settings-schema.d.ts +61 -3
  21. package/dist/types/config/settings.d.ts +3 -0
  22. package/dist/types/coordinator/contract.d.ts +1 -1
  23. package/dist/types/coordinator-mcp/durability.d.ts +29 -0
  24. package/dist/types/coordinator-mcp/event-webhook.d.ts +50 -0
  25. package/dist/types/coordinator-mcp/question-state.d.ts +1 -1
  26. package/dist/types/coordinator-mcp/server.d.ts +14 -0
  27. package/dist/types/crash/index-store.d.ts +3 -0
  28. package/dist/types/crash/record-loader.d.ts +2 -0
  29. package/dist/types/crash/upstream/relay.d.ts +5 -3
  30. package/dist/types/cursor.d.ts +12 -0
  31. package/dist/types/defaults/gjc-defaults.d.ts +35 -1
  32. package/dist/types/defaults/gjc-skills.generated.d.ts +1 -1
  33. package/dist/types/discovery/helpers.d.ts +1 -1
  34. package/dist/types/edit/index.d.ts +2 -1
  35. package/dist/types/eval/py/executor.d.ts +2 -0
  36. package/dist/types/extensibility/extensions/loader.d.ts +32 -0
  37. package/dist/types/extensibility/gjc-plugins/types.d.ts +1 -1
  38. package/dist/types/extensibility/skills.d.ts +2 -0
  39. package/dist/types/gjc-runtime/autoresearch-runtime.d.ts +194 -0
  40. package/dist/types/gjc-runtime/gc-runtime.d.ts +1 -1
  41. package/dist/types/gjc-runtime/psmux-detect.d.ts +1 -1
  42. package/dist/types/gjc-runtime/python-transcript.d.ts +19 -0
  43. package/dist/types/gjc-runtime/ralplan-runtime.d.ts +2 -8
  44. package/dist/types/gjc-runtime/session-layout.d.ts +6 -3
  45. package/dist/types/gjc-runtime/state-renderer.d.ts +0 -22
  46. package/dist/types/gjc-runtime/state-schema.d.ts +7 -7
  47. package/dist/types/gjc-runtime/tmux-common.d.ts +2 -2
  48. package/dist/types/gjc-runtime/ultragoal-change-set.d.ts +38 -1
  49. package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +2 -24
  50. package/dist/types/gjc-runtime/ultragoal-validation-policy.d.ts +73 -0
  51. package/dist/types/gjc-runtime/workflow-recovery-projection.d.ts +100 -0
  52. package/dist/types/hooks/skill-keywords.d.ts +1 -1
  53. package/dist/types/main.d.ts +0 -10
  54. package/dist/types/modes/acp/acp-agent.d.ts +13 -6
  55. package/dist/types/modes/components/model-selector.d.ts +14 -0
  56. package/dist/types/modes/components/skill-hud/render.d.ts +6 -1
  57. package/dist/types/modes/components/smart-routing-panel.d.ts +82 -0
  58. package/dist/types/modes/controllers/selector-controller.d.ts +14 -0
  59. package/dist/types/modes/interactive-mode.d.ts +3 -0
  60. package/dist/types/modes/types.d.ts +9 -0
  61. package/dist/types/rlm/artifacts.d.ts +4 -4
  62. package/dist/types/runtime/optional-runtime-services.d.ts +2 -1
  63. package/dist/types/runtime/workspace-tree-service.d.ts +5 -1
  64. package/dist/types/runtime-mcp/config.d.ts +6 -0
  65. package/dist/types/runtime-mcp/manager.d.ts +10 -0
  66. package/dist/types/sdk/acp/adapter.d.ts +0 -4
  67. package/dist/types/sdk/broker/broker.d.ts +1 -1
  68. package/dist/types/sdk/broker/lifecycle.d.ts +57 -2
  69. package/dist/types/sdk/broker/session-index.d.ts +15 -0
  70. package/dist/types/sdk/bus/chat-daemon-control.d.ts +6 -0
  71. package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +4 -0
  72. package/dist/types/sdk/bus/index.d.ts +8 -0
  73. package/dist/types/sdk/bus/kind-aware-reconciliation.d.ts +2 -0
  74. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +12 -2
  75. package/dist/types/sdk/client/client.d.ts +39 -4
  76. package/dist/types/sdk/host/host.d.ts +1 -0
  77. package/dist/types/sdk/host/internal-autorouting-state.d.ts +3 -0
  78. package/dist/types/sdk/host/model-pin.d.ts +29 -0
  79. package/dist/types/sdk/host/session-runtime.d.ts +2 -1
  80. package/dist/types/sdk/lifecycle-session.d.ts +13 -0
  81. package/dist/types/sdk/router/session-router.d.ts +27 -1
  82. package/dist/types/sdk/session.d.ts +11 -1
  83. package/dist/types/session/agent-session.d.ts +36 -6
  84. package/dist/types/session/artifacts.d.ts +16 -1
  85. package/dist/types/session/internal/managed-session-storage.d.ts +7 -0
  86. package/dist/types/session/session-manager.d.ts +84 -2
  87. package/dist/types/session/session-staging-paths.d.ts +3 -0
  88. package/dist/types/skill-state/canonical-skills.d.ts +1 -1
  89. package/dist/types/skill-state/workflow-hud.d.ts +12 -21
  90. package/dist/types/skill-state/workflow-mutation-guard.d.ts +1 -0
  91. package/dist/types/slash-commands/helpers/autorouting-status.d.ts +8 -0
  92. package/dist/types/system-prompt.d.ts +23 -0
  93. package/dist/types/task/executor.d.ts +35 -4
  94. package/dist/types/task/index.d.ts +17 -3
  95. package/dist/types/task/receipt.d.ts +3 -1
  96. package/dist/types/task/types.d.ts +144 -0
  97. package/dist/types/tools/atomic-file-write.d.ts +72 -0
  98. package/dist/types/tools/descriptors.d.ts +1 -0
  99. package/dist/types/tools/index.d.ts +36 -1
  100. package/dist/types/tools/move-session.d.ts +40 -0
  101. package/dist/types/tools/python.d.ts +12 -0
  102. package/dist/types/tools/resource-gc.d.ts +0 -3
  103. package/dist/types/tools/search.d.ts +8 -1
  104. package/dist/types/tools/skill.d.ts +9 -4
  105. package/dist/types/tools/subagent.d.ts +33 -3
  106. package/dist/types/utils/xml-escape.d.ts +2 -0
  107. package/dist/types/workflow/workflow-intent-diff.d.ts +2 -2
  108. package/dist/types/workflow/workflow-intent-report-consumer.d.ts +1 -1
  109. package/package.json +11 -12
  110. package/scripts/build-sdk-package-smoke.ts +7 -5
  111. package/scripts/check-autorouting-tier-map.ts +183 -0
  112. package/scripts/generate-sdk-operation-inventory.ts +12 -0
  113. package/scripts/generate-tool-catalog.ts +40 -5
  114. package/src/async/job-manager.ts +5 -2
  115. package/src/autoresearch/dashboard.ts +134 -314
  116. package/src/autoresearch/data-context.ts +35 -0
  117. package/src/autoresearch/git.ts +186 -26
  118. package/src/autoresearch/{helpers.ts → harness.ts} +65 -40
  119. package/src/autoresearch/{prompt-setup.md → prompts/prompt-setup.md} +7 -7
  120. package/src/autoresearch/prompts/prompt.md +103 -0
  121. package/src/autoresearch/prompts.ts +126 -0
  122. package/src/autoresearch/runs.ts +708 -0
  123. package/src/autoresearch/types.ts +9 -150
  124. package/src/capability/index.ts +4 -4
  125. package/src/capability/types.ts +20 -0
  126. package/src/cli/accounts-cli.ts +21 -5
  127. package/src/cli/config-cli.ts +25 -1
  128. package/src/cli/fast-help.ts +1 -2
  129. package/src/cli/list-models.ts +5 -8
  130. package/src/cli/setup-cli.ts +8 -0
  131. package/src/cli.ts +2 -21
  132. package/src/commands/autoresearch.ts +33 -0
  133. package/src/commands/coordinator.ts +15 -0
  134. package/src/commands/launch.ts +2 -4
  135. package/src/commands/quick-lane.ts +1 -1
  136. package/src/commands/sdk.ts +24 -0
  137. package/src/commands/state.ts +1 -1
  138. package/src/config/autorouting-contract.ts +474 -0
  139. package/src/config/autorouting-generator.ts +238 -0
  140. package/src/config/autorouting-tier-map.ts +6108 -0
  141. package/src/config/autorouting.ts +120 -0
  142. package/src/config/model-discovery-manager.ts +42 -11
  143. package/src/config/model-registry.ts +348 -68
  144. package/src/config/provider-selection-policy.ts +60 -9
  145. package/src/config/settings-schema.ts +195 -6
  146. package/src/config/settings.ts +62 -1
  147. package/src/config.ts +2 -3
  148. package/src/coordinator/contract.ts +0 -1
  149. package/src/coordinator-mcp/codex-handoff.ts +68 -42
  150. package/src/coordinator-mcp/durability.ts +200 -0
  151. package/src/coordinator-mcp/event-webhook.ts +278 -0
  152. package/src/coordinator-mcp/question-state.ts +109 -46
  153. package/src/coordinator-mcp/server.ts +932 -504
  154. package/src/crash/index-store.ts +126 -22
  155. package/src/crash/record-loader.ts +7 -0
  156. package/src/crash/upstream/relay.ts +82 -34
  157. package/src/cursor.ts +84 -1
  158. package/src/debug/index.ts +26 -0
  159. package/src/defaults/gjc/skills/autoresearch/SKILL.md +116 -0
  160. package/src/defaults/gjc/skills/autoresearch/auto-critic.md +46 -0
  161. package/src/defaults/gjc/skills/autoresearch/auto-iterate.md +42 -0
  162. package/src/defaults/gjc/skills/deep-interview/SKILL.md +17 -37
  163. package/src/defaults/gjc/skills/ralplan/SKILL.md +21 -18
  164. package/src/defaults/gjc/skills/ultragoal/SKILL.md +6 -17
  165. package/src/defaults/gjc/skills/ultragoal/ai-slop-cleaner.md +2 -2
  166. package/src/defaults/gjc-defaults.ts +89 -2
  167. package/src/defaults/gjc-skills.generated.ts +24 -17
  168. package/src/discovery/builtin.ts +18 -5
  169. package/src/discovery/helpers.ts +6 -6
  170. package/src/edit/index.ts +5 -2
  171. package/src/eval/py/executor.ts +8 -0
  172. package/src/extensibility/extensions/loader.ts +135 -13
  173. package/src/extensibility/extensions/wrapper.ts +1 -2
  174. package/src/extensibility/gjc-plugins/schema.ts +1 -1
  175. package/src/extensibility/runtime-skill-discovery.ts +2 -2
  176. package/src/extensibility/skill-management.ts +2 -3
  177. package/src/extensibility/skills.ts +16 -8
  178. package/src/gjc-runtime/autoresearch-runtime.ts +1509 -0
  179. package/src/gjc-runtime/gc-render.ts +0 -1
  180. package/src/gjc-runtime/gc-runtime.ts +1 -11
  181. package/src/gjc-runtime/launch-tmux.ts +3 -3
  182. package/src/gjc-runtime/psmux-detect.ts +2 -2
  183. package/src/gjc-runtime/python-transcript.ts +58 -0
  184. package/src/gjc-runtime/ralplan-runtime.ts +6 -18
  185. package/src/gjc-runtime/session-layout.ts +18 -7
  186. package/src/gjc-runtime/session-state-sidecar.ts +58 -9
  187. package/src/gjc-runtime/state-renderer.ts +0 -38
  188. package/src/gjc-runtime/state-runtime.ts +43 -22
  189. package/src/gjc-runtime/state-schema.ts +1 -1
  190. package/src/gjc-runtime/tmux-common.ts +7 -7
  191. package/src/gjc-runtime/ultragoal-change-set.ts +232 -11
  192. package/src/gjc-runtime/ultragoal-runtime.ts +309 -114
  193. package/src/gjc-runtime/ultragoal-validation-policy.ts +247 -0
  194. package/src/gjc-runtime/workflow-command-ref.ts +15 -11
  195. package/src/gjc-runtime/workflow-manifest.generated.json +413 -532
  196. package/src/gjc-runtime/workflow-manifest.ts +43 -83
  197. package/src/gjc-runtime/workflow-recovery-projection.ts +616 -0
  198. package/src/hooks/skill-keywords.ts +3 -3
  199. package/src/hooks/skill-state.ts +2 -2
  200. package/src/internal-urls/docs-index.generated.ts +26 -24
  201. package/src/lsp/index.ts +25 -5
  202. package/src/main.ts +2 -27
  203. package/src/modes/acp/acp-agent.ts +200 -75
  204. package/src/modes/components/model-selector.ts +216 -13
  205. package/src/modes/components/oauth-selector.ts +5 -5
  206. package/src/modes/components/skill-hud/render.ts +173 -35
  207. package/src/modes/components/smart-routing-panel.ts +531 -0
  208. package/src/modes/components/tool-status-header.ts +6 -3
  209. package/src/modes/controllers/command-controller.ts +17 -7
  210. package/src/modes/controllers/input-controller.ts +44 -9
  211. package/src/modes/controllers/runtime-mcp-command-controller.ts +4 -0
  212. package/src/modes/controllers/selector-controller.ts +298 -65
  213. package/src/modes/interactive-mode.ts +8 -1
  214. package/src/modes/shared/agent-wire/workflow-gate-types.ts +1 -1
  215. package/src/modes/types.ts +9 -1
  216. package/src/prompts/agents/planner.md +1 -1
  217. package/src/prompts/system/system-prompt.md +1 -1
  218. package/src/prompts/system/volatile-project-context.md +2 -1
  219. package/src/prompts/tools/move-session.md +15 -0
  220. package/src/prompts/tools/python.md +12 -0
  221. package/src/prompts/tools/skill-discovery.md +1 -1
  222. package/src/prompts/tools/skill.md +2 -2
  223. package/src/prompts/tools/task-summary.md +1 -0
  224. package/src/prompts/tools/task.md +6 -0
  225. package/src/rlm/artifacts.ts +12 -10
  226. package/src/runtime/optional-runtime-services.ts +3 -2
  227. package/src/runtime/workspace-tree-service.ts +11 -3
  228. package/src/runtime-mcp/config.ts +8 -1
  229. package/src/runtime-mcp/manager.ts +33 -0
  230. package/src/sdk/acp/adapter.ts +48 -1
  231. package/src/sdk/broker/broker.ts +30 -2
  232. package/src/sdk/broker/discovery.ts +217 -2
  233. package/src/sdk/broker/lifecycle.ts +385 -59
  234. package/src/sdk/broker/session-index.ts +243 -48
  235. package/src/sdk/broker/transport.ts +1 -0
  236. package/src/sdk/bus/chat-daemon-control.ts +8 -2
  237. package/src/sdk/bus/chat-daemon-runtime.ts +5 -0
  238. package/src/sdk/bus/index.ts +208 -11
  239. package/src/sdk/bus/kind-aware-reconciliation.ts +16 -0
  240. package/src/sdk/bus/reconciliation-store.ts +27 -5
  241. package/src/sdk/bus/telegram-daemon-contract.ts +12 -2
  242. package/src/sdk/client/client.ts +204 -22
  243. package/src/sdk/host/host.ts +16 -0
  244. package/src/sdk/host/internal-autorouting-state.ts +13 -0
  245. package/src/sdk/host/model-pin.ts +101 -0
  246. package/src/sdk/host/reverse-leases.ts +2 -1
  247. package/src/sdk/host/session-runtime.test.ts +224 -1
  248. package/src/sdk/host/session-runtime.ts +125 -37
  249. package/src/sdk/lifecycle/service.ts +3 -1
  250. package/src/sdk/lifecycle-session.ts +42 -1
  251. package/src/sdk/protocol/operation-inventory.generated.json +66 -0
  252. package/src/sdk/router/session-router.ts +375 -36
  253. package/src/sdk/session.ts +547 -47
  254. package/src/session/account-inventory.ts +1 -1
  255. package/src/session/agent-session.ts +765 -189
  256. package/src/session/artifacts.ts +234 -4
  257. package/src/session/internal/managed-session-storage.ts +91 -4
  258. package/src/session/provider-safety-stop-hint.ts +3 -2
  259. package/src/session/session-manager.ts +775 -16
  260. package/src/session/session-staging-paths.ts +8 -0
  261. package/src/setup/hermes/templates/operator-instructions.v1.md +0 -1
  262. package/src/setup/host-plugin-setup.ts +2 -2
  263. package/src/skill-state/active-state.ts +2 -2
  264. package/src/skill-state/canonical-skills.ts +1 -1
  265. package/src/skill-state/initial-phase.ts +1 -1
  266. package/src/skill-state/workflow-hud.ts +41 -41
  267. package/src/skill-state/workflow-mutation-guard.ts +26 -7
  268. package/src/slash-commands/builtin-registry.ts +77 -0
  269. package/src/slash-commands/helpers/autorouting-status.ts +55 -0
  270. package/src/system-prompt.ts +102 -5
  271. package/src/task/discovery.ts +2 -3
  272. package/src/task/executor.ts +617 -43
  273. package/src/task/index.ts +262 -15
  274. package/src/task/receipt.ts +30 -0
  275. package/src/task/render.ts +11 -1
  276. package/src/task/types.ts +316 -0
  277. package/src/tools/atomic-file-write.ts +594 -0
  278. package/src/tools/bisect.ts +3 -2
  279. package/src/tools/descriptors.test.ts +3 -0
  280. package/src/tools/descriptors.ts +24 -0
  281. package/src/tools/image-gen.ts +5 -1
  282. package/src/tools/index.ts +62 -5
  283. package/src/tools/move-session.ts +107 -0
  284. package/src/tools/python.ts +205 -0
  285. package/src/tools/read.ts +88 -15
  286. package/src/tools/renderers.ts +2 -0
  287. package/src/tools/resource-gc.ts +8 -177
  288. package/src/tools/search.ts +30 -6
  289. package/src/tools/skill-discovery.ts +1 -0
  290. package/src/tools/skill.ts +37 -7
  291. package/src/tools/subagent-render.ts +119 -13
  292. package/src/tools/subagent.ts +91 -74
  293. package/src/tools/tool-catalog.generated.ts +64 -2
  294. package/src/tools/write.ts +16 -12
  295. package/src/utils/xml-escape.ts +14 -0
  296. package/src/web/search/providers/codex.ts +2 -2
  297. package/src/workflow/workflow-intent-diff.ts +13 -12
  298. package/src/workflow/workflow-intent-report-consumer.ts +6 -6
  299. package/dist/types/autoresearch/helpers.d.ts +0 -24
  300. package/dist/types/autoresearch/index.d.ts +0 -2
  301. package/dist/types/autoresearch/state.d.ts +0 -17
  302. package/dist/types/autoresearch/storage.d.ts +0 -142
  303. package/dist/types/autoresearch/tools/init-experiment.d.ts +0 -31
  304. package/dist/types/autoresearch/tools/log-experiment.d.ts +0 -23
  305. package/dist/types/autoresearch/tools/run-experiment.d.ts +0 -8
  306. package/dist/types/autoresearch/tools/update-notes.d.ts +0 -12
  307. package/dist/types/commands/team.d.ts +0 -24
  308. package/dist/types/gjc-runtime/team-gc.d.ts +0 -7
  309. package/dist/types/gjc-runtime/team-launch.d.ts +0 -61
  310. package/dist/types/gjc-runtime/team-notify.d.ts +0 -45
  311. package/dist/types/gjc-runtime/team-runtime.d.ts +0 -336
  312. package/dist/types/gjc-runtime/team-store.d.ts +0 -168
  313. package/dist/types/gjc-runtime/team-worker-heartbeat.d.ts +0 -43
  314. package/dist/types/gjc-runtime/team-worker-memory-guard.d.ts +0 -92
  315. package/dist/types/gjc-runtime/team-workers.d.ts +0 -83
  316. package/dist/types/rlm/index.d.ts +0 -47
  317. package/dist/types/rlm/preset.d.ts +0 -23
  318. package/dist/types/rlm/python-tool.d.ts +0 -16
  319. package/src/autoresearch/command-resume.md +0 -14
  320. package/src/autoresearch/index.ts +0 -536
  321. package/src/autoresearch/prompt.md +0 -103
  322. package/src/autoresearch/resume-message.md +0 -10
  323. package/src/autoresearch/state.ts +0 -273
  324. package/src/autoresearch/storage.ts +0 -699
  325. package/src/autoresearch/tools/init-experiment.ts +0 -272
  326. package/src/autoresearch/tools/log-experiment.ts +0 -524
  327. package/src/autoresearch/tools/run-experiment.ts +0 -475
  328. package/src/autoresearch/tools/update-notes.ts +0 -109
  329. package/src/commands/rlm.ts +0 -19
  330. package/src/commands/team.ts +0 -238
  331. package/src/defaults/gjc/skills/deep-interview/auto-research-greenfield.md +0 -42
  332. package/src/defaults/gjc/skills/team/SKILL.md +0 -467
  333. package/src/gjc-runtime/team-gc.ts +0 -49
  334. package/src/gjc-runtime/team-launch.ts +0 -404
  335. package/src/gjc-runtime/team-notify.ts +0 -326
  336. package/src/gjc-runtime/team-runtime.ts +0 -5923
  337. package/src/gjc-runtime/team-store.ts +0 -878
  338. package/src/gjc-runtime/team-worker-heartbeat.ts +0 -149
  339. package/src/gjc-runtime/team-worker-memory-guard.ts +0 -363
  340. package/src/gjc-runtime/team-workers.ts +0 -1123
  341. package/src/prompts/system/rlm-report-command.md +0 -1
  342. package/src/prompts/system/rlm-research.md +0 -23
  343. package/src/rlm/index.ts +0 -365
  344. package/src/rlm/preset.ts +0 -76
  345. package/src/rlm/python-tool.ts +0 -68
@@ -147,26 +147,116 @@ export class ExtensionRuntime implements IExtensionRuntime {
147
147
  }
148
148
  }
149
149
 
150
+ /**
151
+ * Per-extension activation transaction over the shared runtime state.
152
+ *
153
+ * Registration writes from a factory are staged here (stage); the factory
154
+ * completing without throwing is the validation step; commit copies the
155
+ * staged mutations into the shared runtime; rollback discards them, so a
156
+ * factory that fails midway leaves no registration behind (issue #4718).
157
+ */
158
+ export class ExtensionActivationScope {
159
+ readonly #runtime: IExtensionRuntime;
160
+ readonly #stagedFlagDefaults = new Map<string, boolean | string>();
161
+ readonly #stagedProviderRegistrations: Array<{
162
+ name: string;
163
+ config: import("./types").ProviderConfig;
164
+ sourceId: string;
165
+ }> = [];
166
+ #closed = false;
167
+
168
+ /** True while staged writes may still be added or committed. */
169
+ get open(): boolean {
170
+ return !this.#closed;
171
+ }
172
+
173
+ constructor(runtime: IExtensionRuntime) {
174
+ this.#runtime = runtime;
175
+ }
176
+
177
+ get flagValues(): Map<string, boolean | string> {
178
+ return this.#stagedFlagDefaults;
179
+ }
180
+
181
+ get pendingProviderRegistrations(): Array<{
182
+ name: string;
183
+ config: import("./types").ProviderConfig;
184
+ sourceId: string;
185
+ }> {
186
+ return this.#stagedProviderRegistrations;
187
+ }
188
+
189
+ /**
190
+ * Publish the staged mutations into the shared runtime as one transaction.
191
+ *
192
+ * Prior state is journaled before any live mutation so a throw partway
193
+ * through publication is undone before it escapes: flag entries that did
194
+ * not exist are removed, overwritten entries are restored, and the
195
+ * provider queue is truncated to its prior length. The scope only becomes
196
+ * terminal once publication has fully succeeded, so a failed commit
197
+ * leaves the shared runtime exactly as it was (issue #4718).
198
+ */
199
+ commit(): void {
200
+ if (this.#closed) return;
201
+ const priorFlagEntries = new Map<string, { existed: true; value: boolean | string } | { existed: false }>();
202
+ for (const name of this.#stagedFlagDefaults.keys()) {
203
+ // Flag values are `boolean | string`, so `undefined` means absent.
204
+ const current = this.#runtime.flagValues.get(name);
205
+ priorFlagEntries.set(name, current === undefined ? { existed: false } : { existed: true, value: current });
206
+ }
207
+ const priorProviderCount = this.#runtime.pendingProviderRegistrations.length;
208
+
209
+ try {
210
+ for (const [name, value] of this.#stagedFlagDefaults) {
211
+ this.#runtime.flagValues.set(name, value);
212
+ }
213
+ for (const registration of this.#stagedProviderRegistrations) {
214
+ this.#runtime.pendingProviderRegistrations.push(registration);
215
+ }
216
+ } catch (err) {
217
+ for (const [name, prior] of priorFlagEntries) {
218
+ if (prior.existed) {
219
+ this.#runtime.flagValues.set(name, prior.value);
220
+ } else {
221
+ this.#runtime.flagValues.delete(name);
222
+ }
223
+ }
224
+ this.#runtime.pendingProviderRegistrations.length = priorProviderCount;
225
+ this.#close();
226
+ throw err;
227
+ }
228
+
229
+ this.#closed = true;
230
+ }
231
+
232
+ rollback(): void {
233
+ if (this.#closed) return;
234
+ this.#close();
235
+ }
236
+
237
+ /** Mark the scope terminal and drop the staged copies. */
238
+ #close(): void {
239
+ this.#closed = true;
240
+ this.#stagedFlagDefaults.clear();
241
+ this.#stagedProviderRegistrations.length = 0;
242
+ }
243
+ }
244
+
150
245
  /**
151
246
  * ExtensionAPI implementation for an extension.
152
247
  * Registration methods write to the extension object.
153
248
  * Action methods delegate to the shared runtime.
154
249
  */
155
- class ConcreteExtensionAPI implements ExtensionAPI, IExtensionRuntime {
250
+ class ConcreteExtensionAPI implements ExtensionAPI {
156
251
  readonly logger = logger;
157
252
  readonly typebox = TypeBox;
158
253
  readonly zod = Zod;
159
- readonly flagValues = new Map<string, boolean | string>();
160
- readonly pendingProviderRegistrations: Array<{
161
- name: string;
162
- config: import("./types").ProviderConfig;
163
- sourceId: string;
164
- }> = [];
165
254
 
166
255
  constructor(
167
256
  public readonly pi: typeof import("@gajae-code/coding-agent"),
168
257
  private readonly extension: Extension,
169
258
  private readonly runtime: IExtensionRuntime,
259
+ private readonly activation: ExtensionActivationScope,
170
260
  private readonly cwd: string,
171
261
  public readonly events: EventBus,
172
262
  ) {}
@@ -218,7 +308,7 @@ class ConcreteExtensionAPI implements ExtensionAPI, IExtensionRuntime {
218
308
  ): void {
219
309
  this.extension.flags.set(name, { name, extensionPath: this.extension.path, ...options });
220
310
  if (options.default !== undefined) {
221
- this.runtime.flagValues.set(name, options.default);
311
+ this.activation.flagValues.set(name, options.default);
222
312
  }
223
313
  }
224
314
 
@@ -228,7 +318,14 @@ class ConcreteExtensionAPI implements ExtensionAPI, IExtensionRuntime {
228
318
 
229
319
  getFlag(name: string): boolean | string | undefined {
230
320
  if (!this.extension.flags.has(name)) return undefined;
231
- return this.runtime.flagValues.get(name);
321
+ if (!this.activation.open) {
322
+ // Post-commit: the shared runtime is authoritative, so runtime-side
323
+ // writes (CLI flag overrides, later extensions) stay observable.
324
+ return this.runtime.flagValues.get(name);
325
+ }
326
+ // Activation in flight: prefer this factory's staged default so the
327
+ // extension reads back what it just registered.
328
+ return this.activation.flagValues.get(name) ?? this.runtime.flagValues.get(name);
232
329
  }
233
330
 
234
331
  sendMessage<T = unknown>(
@@ -338,7 +435,7 @@ class ConcreteExtensionAPI implements ExtensionAPI, IExtensionRuntime {
338
435
  }
339
436
 
340
437
  registerProvider(name: string, config: import("./types").ProviderConfig): void {
341
- this.runtime.pendingProviderRegistrations.push({ name, config, sourceId: this.extension.path });
438
+ this.activation.pendingProviderRegistrations.push({ name, config, sourceId: this.extension.path });
342
439
  }
343
440
  }
344
441
 
@@ -365,6 +462,7 @@ async function loadExtension(
365
462
  runtime: IExtensionRuntime,
366
463
  ): Promise<{ extension: Extension | null; error: string | null }> {
367
464
  const resolvedPath = resolvePath(extensionPath, cwd);
465
+ let activation: ExtensionActivationScope | undefined;
368
466
  try {
369
467
  const module = (await loadLegacyPiModule(resolvedPath)) as LoadedExtensionModule;
370
468
  const factory = getExtensionFactory(module);
@@ -377,11 +475,21 @@ async function loadExtension(
377
475
  }
378
476
 
379
477
  const extension = createExtension(extensionPath, resolvedPath);
380
- const api = new ConcreteExtensionAPI(await import("@gajae-code/coding-agent"), extension, runtime, cwd, eventBus);
478
+ activation = new ExtensionActivationScope(runtime);
479
+ const api = new ConcreteExtensionAPI(
480
+ await import("@gajae-code/coding-agent"),
481
+ extension,
482
+ runtime,
483
+ activation,
484
+ cwd,
485
+ eventBus,
486
+ );
381
487
  await factory(api);
488
+ activation.commit();
382
489
 
383
490
  return { extension, error: null };
384
491
  } catch (err) {
492
+ activation?.rollback();
385
493
  const message = err instanceof Error ? err.message : String(err);
386
494
  return { extension: null, error: `Failed to load extension: ${message}` };
387
495
  }
@@ -398,8 +506,22 @@ export async function loadExtensionFromFactory(
398
506
  name = "<inline>",
399
507
  ): Promise<Extension> {
400
508
  const extension = createExtension(name, name);
401
- const api = new ConcreteExtensionAPI(await import("@gajae-code/coding-agent"), extension, runtime, cwd, eventBus);
402
- await factory(api);
509
+ const activation = new ExtensionActivationScope(runtime);
510
+ const api = new ConcreteExtensionAPI(
511
+ await import("@gajae-code/coding-agent"),
512
+ extension,
513
+ runtime,
514
+ activation,
515
+ cwd,
516
+ eventBus,
517
+ );
518
+ try {
519
+ await factory(api);
520
+ } catch (err) {
521
+ activation.rollback();
522
+ throw err;
523
+ }
524
+ activation.commit();
403
525
  return extension;
404
526
  }
405
527
 
@@ -26,8 +26,6 @@ export class RegisteredToolAdapter implements AgentTool<any, any, any> {
26
26
  private registeredTool: RegisteredTool,
27
27
  private runner: ExtensionRunner,
28
28
  ) {
29
- applyToolProxy(registeredTool.definition, this);
30
-
31
29
  // Only define render methods when the underlying definition provides them.
32
30
  // If these exist unconditionally on the prototype, ToolExecutionComponent
33
31
  // enters the custom-renderer path, gets undefined back, and silently
@@ -45,6 +43,7 @@ export class RegisteredToolAdapter implements AgentTool<any, any, any> {
45
43
  args,
46
44
  );
47
45
  }
46
+ applyToolProxy(registeredTool.definition, this);
48
47
  }
49
48
 
50
49
  async execute(
@@ -26,7 +26,7 @@ const FORBIDDEN_MANIFEST_KEYS = ["skills", "slash-commands", "commands", "agents
26
26
  type ForbiddenManifestKey = (typeof FORBIDDEN_MANIFEST_KEYS)[number];
27
27
 
28
28
  const FORBIDDEN_SURFACE_DIAGNOSTICS: Record<ForbiddenManifestKey, string> = {
29
- skills: `Forbidden GJC plugin surface "skills": bundles may only EXTEND the four bundled workflow skills (deep-interview, ralplan, ultragoal, team) and the four role agents (executor, architect, planner, critic), never register a new top-level skill. Bind an inline sub-skill with the canonical "subskills" surface (frontmatter binds_to/phase/activation_arg), or drop the manifest and use the loose surface .gjc/skills/<name>/SKILL.md (project) / ~/.gjc/agent/skills/<name>/SKILL.md (user).`,
29
+ skills: `Forbidden GJC plugin surface "skills": bundles may only EXTEND the four bundled workflow skills (deep-interview, ralplan, ultragoal, autoresearch) and the four role agents (executor, architect, planner, critic), never register a new top-level skill. Bind an inline sub-skill with the canonical "subskills" surface (frontmatter binds_to/phase/activation_arg), or drop the manifest and use the loose surface .gjc/skills/<name>/SKILL.md (project) / ~/.gjc/agent/skills/<name>/SKILL.md (user).`,
30
30
  "slash-commands": `Forbidden GJC plugin surface "slash-commands": bundles cannot register slash commands. Use the loose surface .gjc/commands/<name> (TypeScript module) or a markdown slash-command file instead.`,
31
31
  commands: `Forbidden GJC plugin surface "commands" (Claude Code plugin.json vocabulary): bundles cannot register slash commands. Use the loose surface .gjc/commands/<name> (TypeScript module) or a markdown slash-command file instead.`,
32
32
  agents: `Forbidden GJC plugin surface "agents" (Claude Code plugin.json vocabulary): bundles cannot register top-level agents; executor/architect/planner/critic are protected. Bind a sub-skill to an existing agent with the canonical "subskills" surface (frontmatter binds_to: one of executor|architect|planner|critic, phase, activation_arg) instead.`,
@@ -1,6 +1,6 @@
1
1
  import * as fs from "node:fs/promises";
2
- import * as os from "node:os";
3
2
  import * as path from "node:path";
3
+ import { getTrustedHomeDir } from "@gajae-code/utils";
4
4
  import { findRepoRoot } from "../capability/fs";
5
5
  import type { Skill as CapabilitySkill } from "../capability/skill";
6
6
  import type { SkillsSettings } from "../config/settings-schema";
@@ -47,7 +47,7 @@ export interface DiscoverRuntimeSkillsOptions {
47
47
  }
48
48
 
49
49
  function getRuntimeHome(): string {
50
- return process.env.HOME || os.homedir();
50
+ return getTrustedHomeDir();
51
51
  }
52
52
 
53
53
  const DEFAULT_LIMIT = 20;
@@ -13,9 +13,8 @@
13
13
  * preview/apply transaction and the UI itself are owned by #4291.
14
14
  */
15
15
  import * as fs from "node:fs/promises";
16
- import * as os from "node:os";
17
16
  import * as path from "node:path";
18
- import { parseFrontmatter } from "@gajae-code/utils";
17
+ import { getTrustedHomeDir, parseFrontmatter } from "@gajae-code/utils";
19
18
  import { findRepoRoot } from "../capability/fs";
20
19
  import type { Skill as CapabilitySkill } from "../capability/skill";
21
20
  import { resolveSkillScopeTrust } from "../config/skill-settings-defaults";
@@ -97,7 +96,7 @@ export class SkillFrontmatterError extends Error {
97
96
  const BUILT_IN_SKILL_NAMES = new Set<string>(CANONICAL_GJC_WORKFLOW_SKILLS);
98
97
 
99
98
  function getRuntimeHome(): string {
100
- return process.env.HOME || os.homedir();
99
+ return getTrustedHomeDir();
101
100
  }
102
101
 
103
102
  /** Ancestor directories from `cwd` (inclusive) up to `stop` (inclusive), excluding `home`. */
@@ -1,11 +1,11 @@
1
1
  import * as fs from "node:fs/promises";
2
- import * as os from "node:os";
3
- import { getProjectDir } from "@gajae-code/utils";
2
+ import { getProjectDir, getTrustedHomeDir } from "@gajae-code/utils";
3
+ import { findRepoRoot } from "../capability/fs";
4
4
  import { skillCapability } from "../capability/skill";
5
5
  import type { SourceMeta } from "../capability/types";
6
6
  import type { SkillsSettings } from "../config/settings";
7
7
  import { resolveSkillScopeTrust } from "../config/skill-settings-defaults";
8
- import { type Skill as CapabilitySkill, loadCapability } from "../discovery";
8
+ import { type Skill as CapabilitySkill, getCapability } from "../discovery";
9
9
  import { compareSkillOrder, scanSkillsFromDir } from "../discovery/helpers";
10
10
  import type { SkillPromptDetails } from "../session/messages";
11
11
  import { CANONICAL_GJC_WORKFLOW_SKILLS } from "../skill-state/canonical-skills";
@@ -77,11 +77,12 @@ export interface LoadSkillsFromDirOptions {
77
77
  }
78
78
 
79
79
  export async function loadSkillsFromDir(options: LoadSkillsFromDirOptions): Promise<LoadSkillsResult> {
80
+ const home = getTrustedHomeDir();
80
81
  const [rawProviderId, rawLevel] = options.source.split(":", 2);
81
82
  const providerId = rawProviderId || "custom";
82
83
  const level: "user" | "project" = rawLevel === "project" ? "project" : "user";
83
84
  const result = await scanSkillsFromDir(
84
- { cwd: getProjectDir(), home: os.homedir(), repoRoot: null },
85
+ { cwd: getProjectDir(), home, repoRoot: null },
85
86
  {
86
87
  dir: options.dir,
87
88
  providerId,
@@ -108,6 +109,8 @@ export async function loadSkillsFromDir(options: LoadSkillsFromDirOptions): Prom
108
109
  export interface LoadSkillsOptions extends SkillsSettings {
109
110
  /** Working directory for project-local skills. Default: getProjectDir() */
110
111
  cwd?: string;
112
+ /** Explicit user home for skill discovery. Default: getTrustedHomeDir(). */
113
+ home?: string;
111
114
  }
112
115
 
113
116
  /**
@@ -137,6 +140,7 @@ export async function loadSkills(options: LoadSkillsOptions = {}): Promise<LoadS
137
140
  if (!enabled) {
138
141
  return { skills: [], warnings: [] };
139
142
  }
143
+ const home = options.home ?? getTrustedHomeDir();
140
144
 
141
145
  const projectTrusted = resolveSkillScopeTrust(options, "project");
142
146
  const userTrusted = resolveSkillScopeTrust(options, "user");
@@ -156,7 +160,11 @@ export async function loadSkills(options: LoadSkillsOptions = {}): Promise<LoadS
156
160
  // Use capability API to load all skills. `all` (rather than `items`) keeps
157
161
  // shadowed duplicates so this function can apply the documented precedence
158
162
  // itself: project scope beats user scope.
159
- const result = await loadCapability<CapabilitySkill>(skillCapability.id, { cwd, disabledExtensions });
163
+ const nativeProvider = getCapability<CapabilitySkill>(skillCapability.id)?.providers.find(
164
+ provider => provider.id === "native",
165
+ );
166
+ if (!nativeProvider) throw new Error("Native skill provider is unavailable");
167
+ const result = await nativeProvider.load({ cwd, home, repoRoot: await findRepoRoot(cwd) });
160
168
 
161
169
  const skillMap = new Map<string, Skill>();
162
170
  const realPathSet = new Set<string>();
@@ -182,7 +190,7 @@ export async function loadSkills(options: LoadSkillsOptions = {}): Promise<LoadS
182
190
  // precedence. `all` is already in native provider order with project dirs
183
191
  // before user dirs; a stable sort by level lifts every project item above
184
192
  // every user item, giving: project `.gjc/skills` > user roots.
185
- const filteredSkills = result.all
193
+ const filteredSkills = result.items
186
194
  .filter(capSkill => {
187
195
  if (!isSourceEnabled(capSkill._source)) return false;
188
196
  if (disabledSkillNames.has(capSkill.name)) return false;
@@ -250,9 +258,9 @@ export async function loadSkills(options: LoadSkillsOptions = {}): Promise<LoadS
250
258
 
251
259
  const customDirectoryResults = await Promise.all(
252
260
  customDirectories.map(async dir => {
253
- const expandedDir = expandTilde(dir);
261
+ const expandedDir = expandTilde(dir, home);
254
262
  const scanResult = await scanSkillsFromDir(
255
- { cwd, home: os.homedir(), repoRoot: null },
263
+ { cwd, home, repoRoot: null },
256
264
  {
257
265
  dir: expandedDir,
258
266
  providerId: "custom",