@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
@@ -50,6 +50,7 @@ gjc ultragoal create-goals --brief "<brief>"
50
50
  gjc ultragoal create-goals --brief-file <path>
51
51
  gjc ultragoal complete-goals
52
52
  gjc ultragoal complete-goals --retry-failed
53
+ gjc ultragoal quality-gate source-hash --json
53
54
  gjc ultragoal quality-gate validate --quality-gate-json <quality-gate-json-or-path> [--goal-id <id>] [--json]
54
55
  gjc ultragoal checkpoint --goal-id <id> --status complete --evidence "<evidence>" --quality-gate-json <quality-gate-json-or-path>
55
56
  gjc ultragoal checkpoint --goal-id <id> --status failed --evidence "<blocker/evidence>"
@@ -230,17 +231,17 @@ The Ultragoal leader owns `.gjc/_session-{sessionid}/ultragoal/goals.json` and `
230
231
 
231
232
  ### Native executor parallelism contract
232
233
 
233
- Native subagent parallelism is a contract for bounded `executor` delegation, not a runtime scheduler and not a Team-mode rule:
234
+ Native subagent parallelism is a contract for bounded `executor` delegation, not a runtime scheduler:
234
235
 
235
236
  - **Use native `executor` parallelism only** when a story's expected diffs fall in genuinely different sub-domains/modules/systems, each boundable by a per-slice coordination contract.
236
237
  - **Default to direct leader edits** otherwise; sequence any work with real dependencies, shared-file overlap, or a single-domain footprint, and never parallelize work that lacks a safe contract.
237
238
  - Worker agents **MUST NOT mutate `.gjc/_session-{sessionid}/ultragoal`**, call goal tools, make checkpoint decisions, own integration, or own final verification. The Ultragoal leader keeps those responsibilities.
239
+ - Workers must not run `gjc ultragoal checkpoint`: checkpoint authority stays with the leader after worker tasks are terminal. The leader checkpoints from worker evidence plus the current-session GJC goal snapshot, and performs no hidden goal mutation.
238
240
 
239
241
  Before workers start, each per-slice coordination contract MUST name the target files/surfaces, independence assumptions, allowed coordination channel, conflict-escalation rule, expected evidence, and terminal status. Conflict or assignment changes remain leader-owned and must be auditable through durable ledger evidence.
240
242
 
241
243
  For failed, timed-out, or contract-violating slices, record durable ledger evidence; preserve successful terminal slices only when safe; and reassign, retry, or collapse the invalid work to serial execution under an updated contract. Completion after parallel work still requires terminal worker evidence, leader integration, targeted verification, and the existing cleaner + architect + executor QA/red-team gate before checkpoint complete.
242
244
 
243
- Team remains explicit and separate: Team is not auto-launched, not a hidden pipeline scheduler, and never owns Ultragoal goals, checkpoints, or ledger state.
244
245
 
245
246
  ## Boundary verification (aggregate default)
246
247
 
@@ -282,18 +283,6 @@ Checkpoint contract summary — the full contract lives in the `validation-batch
282
283
 
283
284
  Cohort lanes are parallel by construction: the boundary gate freezes one `sourceHash` first, so `cleaner`, `architect`, and `qa` can run concurrently against the identical immutable snapshot and then join. Fall back to **sequential** lanes only when code is still changing (nothing can be frozen yet), when the red-team lane depends on architect fixes, or when architect findings gate the QA scope. Either way the lanes must **join before checkpoint** — no lane checkpoints independently, and repair work starts only after the join.
284
285
 
285
- ## Use Ultragoal and Team together
286
-
287
- Use ultragoal and team together for a durable Ultragoal story that benefits from one visible tmux worker session. Ultragoal remains leader-owned: `.gjc/_session-{sessionid}/ultragoal/goals.json` stores the story plan and `.gjc/_session-{sessionid}/ultragoal/ledger.jsonl` stores checkpoints. Team is the single-worker tmux execution engine and returns task/evidence status to the leader.
288
-
289
- The leader checkpoints Ultragoal from Team evidence plus the current-session GJC goal snapshot; durable state remains leader-owned in `goals.json` and `ledger.jsonl`:
290
-
291
- ```sh
292
- gjc ultragoal checkpoint --goal-id <id> --status complete --evidence "<team evidence mentioning .gjc/_session-{sessionid}/ultragoal and <id>>" --quality-gate-json <quality-gate-json-or-path>
293
- ```
294
-
295
- Workers do not own ultragoal goal state, do not create worker ultragoal ledgers, and do not checkpoint Ultragoal. Workers must not run `gjc ultragoal checkpoint`; checkpoint authority stays with the leader after worker tasks are terminal. Team launch remains explicit; Ultragoal does not auto-launch Team and performs no hidden goal mutation.
296
-
297
286
  ## Internal Ultragoal sub-skill fragments
298
287
 
299
288
  The completion-gate cleanup sweep is driven by `ai-slop-cleaner`, an internal Ultragoal sub-skill bundled as a `kind: "skill-fragment"` prompt with parent skill `ultragoal` (installed at `skill-fragments/ultragoal/ai-slop-cleaner.md`). It is analogous to deep-interview's auto-research fragment: loaded on demand for one specific hook, never a user-facing skill.
@@ -302,7 +291,7 @@ The completion-gate cleanup sweep is driven by `ai-slop-cleaner`, an internal Ul
302
291
  - It is a read-only detector+reporter over the active story's changed files only: it never edits code, writes files, mutates `.gjc/`, checkpoints, calls goal tools, or spawns workflows.
303
292
  - It classifies every finding as blocking or advisory across the full taxonomy (fallback-like masking vs. grounded, duplication, dead code, needless abstraction, boundary violations, UI/design slop, missing tests).
304
293
  - The leader and a leader-spawned `executor` own all fixes; the cleaner reruns until zero blocking findings remain. Advisory findings live in the gate report only.
305
- - Recursion guard: it must not spawn nested `ralplan`/`team`/`deep-interview`/`ultragoal`; broad or architectural findings are handed back to the leader as review blockers.
294
+ - Recursion guard: it must not spawn nested `ralplan`/`deep-interview`/`ultragoal`; broad or architectural findings are handed back to the leader as review blockers.
306
295
 
307
296
  ## Boundary completion cohort gate
308
297
 
@@ -311,7 +300,7 @@ The heavyweight gate runs **once per boundary generation**, not once per story a
311
300
  One generation freezes the change set and reviews it exactly once:
312
301
 
313
302
  1. Run implementation verification for the boundary's cumulative change set.
314
- 2. **Freeze the change set.** Compute one immutable `sourceHash` over the reviewed source. Every lane in this generation inspects that same frozen snapshot; a lane verdict carrying a different `sourceHash` is rejected.
303
+ 2. **Freeze the change set.** Run `gjc ultragoal quality-gate source-hash --json` on the clean reviewed snapshot and use its `sourceHash` exactly. The runtime binds this digest to the integration base, merge base, normalized changed paths, captured diff, and untracked-content digest. Every lane in this generation inspects that same frozen snapshot; a lane verdict carrying a different `sourceHash` is rejected. Any later source or base change requires rerunning this command and starting a new generation.
315
304
  3. **Run the cohort lanes on the frozen snapshot** — at most one `cleaner`, one `architect`, and one `qa` lane per generation. They may run in parallel because they share the frozen source; a second architect or QA lane in the same generation is rejected. The `cleaner` lane is the internal ai-slop-cleaner skill fragment run over the frozen change set: a read-only detector that emits an `AI SLOP CLEANUP REPORT`, and it still runs and records a passed/no-op report when there are no relevant edits. Its BLOCKING findings join the cohort findings rather than starting their own fix loop; advisory findings are included in the gate report only and are not written to the Ultragoal ledger.
316
305
  4. Delegate an `architect` review covering all three lanes:
317
306
  - architecture-side: system boundaries, layering, data/control flow, operational risks.
@@ -429,7 +418,7 @@ The critic must verify that the `human_blocked` classification is genuine, inclu
429
418
 
430
419
  ### Invocation and containment
431
420
 
432
- At each terminus, the leader gives the read-only `critic` role agent `brief.md`, `goals.json`, `ledger.jsonl`, and the cumulative change set. For completion, invoke it before assembling the final-aggregate gate JSON. For pause, invoke it after the `human_blocked` classification and before `goal({"op":"pause"})`. The terminal critic must not spawn nested `ralplan`, `team`, `deep-interview`, or `ultragoal` workflows. This creates no interactive surface: `ask` remains blocked while an Ultragoal run is active.
421
+ At each terminus, the leader gives the read-only `critic` role agent `brief.md`, `goals.json`, `ledger.jsonl`, and the cumulative change set. For completion, invoke it before assembling the final-aggregate gate JSON. For pause, invoke it after the `human_blocked` classification and before `goal({"op":"pause"})`. The terminal critic must not spawn nested `ralplan`, `deep-interview`, or `ultragoal` workflows. This creates no interactive surface: `ask` remains blocked while an Ultragoal run is active.
433
422
 
434
423
  On repeat terminus attempts within the same run (after an `ITERATE`/`REJECT` reopen cycle or a superseded pause classification), **resume the prior terminal-critic subagent when resumable** instead of freshly spawning one: the critic already holds `brief.md`, `goals.json`, the ledger history, and its own prior findings, so re-invocation only needs the delta (new ledger events, the updated cumulative change set, and evidence addressing the prior blockers). Resume via existing `subagent` resume/steer controls; on `context_unavailable`, `not_found`, `no_runner`, or `resume_failed` — or after a process restart — fall back to a fresh `critic` spawn with the full context bundle. A resumed terminal critic remains read-only, keeps the same containment rules, and must issue a fresh verdict against the current state — a prior `ITERATE` is never carried forward as pre-judged, and each verdict is still recorded through `gjc ultragoal record-critic-verdict`.
435
424
 
@@ -9,7 +9,7 @@ You are a **read-only detector and reporter**. You never edit code, write files,
9
9
  - Inspect ONLY the active Ultragoal story's changed-files list. No broad rewrites, no inspection outside that scope, no new dependencies.
10
10
  - Allow only narrow supporting reads needed to understand the contracts of changed files; if you need broader context, report that need to the leader instead of expanding scope.
11
11
  - If there are no relevant edits, emit a passed/no-op report (`Gate Result: PASS`, `Changed Files Reviewed` listing the files as "no relevant edits").
12
- - Recursion guard: you are already inside an Ultragoal workflow. Do NOT spawn nested `ralplan`, `team`, `deep-interview`, or `ultragoal` workflows. Broad, ambiguous, cross-layer, or architectural findings are handed to the leader as review blockers, not resolved here.
12
+ - Recursion guard: you are already inside an Ultragoal workflow. Do NOT spawn nested `ralplan`, `autoresearch`, `deep-interview`, or `ultragoal` workflows. Broad, ambiguous, cross-layer, or architectural findings are handed to the leader as review blockers, not resolved here.
13
13
 
14
14
  ## Taxonomy
15
15
 
@@ -46,7 +46,7 @@ Advisory Findings: [none, or numbered findings with file, category, evidence, wh
46
46
  Fallback Findings: [none, or finding -> masking fallback slop / grounded compatibility/fail-safe fallback -> blocking/advisory]
47
47
  UI/Design Findings: [none/N/A, or signal -> blocking/advisory -> rationale]
48
48
  Missing Test Findings: [none, or gap -> blocking/advisory -> required coverage]
49
- Recursion Guard: [confirmed no nested ralplan/team/deep-interview/ultragoal spawned; broad findings handed to leader]
49
+ Recursion Guard: [confirmed no nested ralplan/autoresearch/deep-interview/ultragoal spawned; broad findings handed to leader]
50
50
  Changed Files Reviewed:
51
51
  - [path] - [reviewed / no relevant edits]
52
52
 
@@ -1,9 +1,10 @@
1
1
  import { readFileSync } from "node:fs";
2
+ import * as fs from "node:fs/promises";
2
3
  import * as path from "node:path";
3
4
  import { getAgentDir, isEnoent } from "@gajae-code/utils";
4
5
  import { BUNDLED_GJC_SKILL_CATALOG, type BundledGjcSkillCatalogEntry } from "./gjc-skills.generated";
5
6
 
6
- export const DEFAULT_GJC_DEFINITION_NAMES = ["deep-interview", "ralplan", "team", "ultragoal"] as const;
7
+ export const DEFAULT_GJC_DEFINITION_NAMES = ["autoresearch", "deep-interview", "ralplan", "ultragoal"] as const;
7
8
  export type DefaultGjcDefinitionName = (typeof DEFAULT_GJC_DEFINITION_NAMES)[number];
8
9
  export type DefaultGjcDefinitionKind = "skill" | "skill-fragment";
9
10
  export type EmbeddedDefaultGjcSkill = {
@@ -64,6 +65,32 @@ export type DefaultGjcDefinitionInstallFile =
64
65
  status: DefaultGjcInstallStatus;
65
66
  };
66
67
 
68
+ /**
69
+ * Bundled workflow definitions that GJC used to ship and no longer does.
70
+ *
71
+ * Installing defaults only ever wrote the CURRENT set, so a definition dropped
72
+ * from the bundle stayed on disk under the agent dir forever — where
73
+ * filesystem skill discovery still found it and `/skill:<name>` still resolved.
74
+ * `team` was the first removal, so it was the first to expose that gap.
75
+ *
76
+ * Retirement QUARANTINES rather than deletes: the directory is moved aside to
77
+ * `<targetRoot>/retired/<name>.<timestamp>/`. A user who customized the skill
78
+ * keeps their content, and nothing is destroyed to satisfy a rename.
79
+ */
80
+ export const RETIRED_GJC_DEFINITION_NAMES = ["team"] as const;
81
+ export type RetiredGjcDefinitionName = (typeof RETIRED_GJC_DEFINITION_NAMES)[number];
82
+
83
+ export type RetiredGjcDefinitionStatus = "absent" | "quarantined";
84
+
85
+ export interface RetiredGjcDefinitionFile {
86
+ name: RetiredGjcDefinitionName;
87
+ /** Directory that held the retired definition. */
88
+ path: string;
89
+ /** Where it was moved, when quarantined. */
90
+ quarantinedTo?: string;
91
+ status: RetiredGjcDefinitionStatus;
92
+ }
93
+
67
94
  export interface DefaultGjcDefinitionInstallResult {
68
95
  targetRoot: string;
69
96
  total: number;
@@ -73,6 +100,8 @@ export interface DefaultGjcDefinitionInstallResult {
73
100
  missing: number;
74
101
  different: number;
75
102
  files: DefaultGjcDefinitionInstallFile[];
103
+ /** Retired bundled definitions found under `targetRoot`, and what happened to them. */
104
+ retired: RetiredGjcDefinitionFile[];
76
105
  }
77
106
  function sourcePathForBundledEntry(entry: BundledGjcSkillCatalogEntry): string {
78
107
  const relative = entry.kind === "skill" ? entry.relativePath : entry.relativePath.replace(/^skill-fragments\//, "");
@@ -236,7 +265,63 @@ export async function installDefaultGjcDefinitions(
236
265
  }
237
266
  }
238
267
 
239
- return summarizeInstallResult(targetRoot, files);
268
+ const retired = await retireRemovedGjcDefinitions(targetRoot, { check: options.check === true });
269
+ return summarizeInstallResult(targetRoot, files, retired);
270
+ }
271
+
272
+ /**
273
+ * Quarantine any retired bundled definition still present under `targetRoot`.
274
+ *
275
+ * `check` reports what WOULD move without touching the filesystem, so
276
+ * `--check` callers stay read-only.
277
+ */
278
+ export async function retireRemovedGjcDefinitions(
279
+ targetRoot: string,
280
+ options: { check?: boolean } = {},
281
+ ): Promise<RetiredGjcDefinitionFile[]> {
282
+ const results: RetiredGjcDefinitionFile[] = [];
283
+ for (const name of RETIRED_GJC_DEFINITION_NAMES) {
284
+ const directory = path.join(targetRoot, "skills", name);
285
+ if (!(await directoryExists(directory))) {
286
+ results.push({ name, path: directory, status: "absent" });
287
+ continue;
288
+ }
289
+ if (options.check) {
290
+ results.push({ name, path: directory, status: "quarantined" });
291
+ continue;
292
+ }
293
+ const quarantinedTo = await reserveQuarantinePath(path.join(targetRoot, "retired"), name);
294
+ await fs.rename(directory, quarantinedTo);
295
+ results.push({ name, path: directory, quarantinedTo, status: "quarantined" });
296
+ }
297
+ return results;
298
+ }
299
+
300
+ /**
301
+ * Reserve a unique quarantine directory.
302
+ *
303
+ * A timestamp alone is not enough: two retirements inside the same millisecond
304
+ * resolve to the same path, which would silently overwrite the earlier
305
+ * quarantine. Disambiguate with a counter until an unused path is found.
306
+ */
307
+ async function reserveQuarantinePath(retiredRoot: string, name: string): Promise<string> {
308
+ const stamp = new Date().toISOString().replace(/[:.]/g, "-");
309
+ await fs.mkdir(retiredRoot, { recursive: true });
310
+ const base = path.join(retiredRoot, `${name}.${stamp}`);
311
+ if (!(await directoryExists(base))) return base;
312
+ for (let attempt = 2; ; attempt += 1) {
313
+ const candidate = `${base}-${attempt}`;
314
+ if (!(await directoryExists(candidate))) return candidate;
315
+ }
316
+ }
317
+
318
+ async function directoryExists(candidate: string): Promise<boolean> {
319
+ try {
320
+ return (await fs.stat(candidate)).isDirectory();
321
+ } catch (error) {
322
+ if (isEnoent(error)) return false;
323
+ throw error;
324
+ }
240
325
  }
241
326
 
242
327
  async function readExistingText(filePath: string): Promise<string | undefined> {
@@ -251,6 +336,7 @@ async function readExistingText(filePath: string): Promise<string | undefined> {
251
336
  function summarizeInstallResult(
252
337
  targetRoot: string,
253
338
  files: DefaultGjcDefinitionInstallFile[],
339
+ retired: RetiredGjcDefinitionFile[],
254
340
  ): DefaultGjcDefinitionInstallResult {
255
341
  return {
256
342
  targetRoot,
@@ -261,6 +347,7 @@ function summarizeInstallResult(
261
347
  missing: countStatus(files, "missing"),
262
348
  different: countStatus(files, "different"),
263
349
  files,
350
+ retired,
264
351
  };
265
352
  }
266
353
 
@@ -4,7 +4,7 @@
4
4
  * Keep this module metadata-only: skill bodies are loaded through literal
5
5
  * dynamic imports only when a caller asks for their content.
6
6
  */
7
- export type BundledGjcSkillName = "deep-interview" | "ralplan" | "team" | "ultragoal";
7
+ export type BundledGjcSkillName = "autoresearch" | "deep-interview" | "ralplan" | "ultragoal";
8
8
 
9
9
  export interface BundledGjcSkillCatalogEntry {
10
10
  readonly kind: "skill" | "skill-fragment";
@@ -19,17 +19,14 @@ const deepInterview = () =>
19
19
  import("./gjc/skills/deep-interview/SKILL.md", { with: { type: "text" } }).then(module => module.default);
20
20
  const ralplan = () =>
21
21
  import("./gjc/skills/ralplan/SKILL.md", { with: { type: "text" } }).then(module => module.default);
22
- const team = () => import("./gjc/skills/team/SKILL.md", { with: { type: "text" } }).then(module => module.default);
22
+ const autoresearch = () =>
23
+ import("./gjc/skills/autoresearch/SKILL.md", { with: { type: "text" } }).then(module => module.default);
23
24
  const ultragoal = () =>
24
25
  import("./gjc/skills/ultragoal/SKILL.md", { with: { type: "text" } }).then(module => module.default);
25
26
  const autoAnswerUncertain = () =>
26
27
  import("./gjc/skills/deep-interview/auto-answer-uncertain.md", { with: { type: "text" } }).then(
27
28
  module => module.default,
28
29
  );
29
- const autoResearchGreenfield = () =>
30
- import("./gjc/skills/deep-interview/auto-research-greenfield.md", { with: { type: "text" } }).then(
31
- module => module.default,
32
- );
33
30
  const lateralReviewPanel = () =>
34
31
  import("./gjc/skills/deep-interview/lateral-review-panel.md", { with: { type: "text" } }).then(
35
32
  module => module.default,
@@ -40,6 +37,10 @@ const validationBatchContracts = () =>
40
37
  import("./gjc/skills/ultragoal/validation-batch-contracts.md", { with: { type: "text" } }).then(
41
38
  module => module.default,
42
39
  );
40
+ const autoresearchIterate = () =>
41
+ import("./gjc/skills/autoresearch/auto-iterate.md", { with: { type: "text" } }).then(module => module.default);
42
+ const autoresearchCritic = () =>
43
+ import("./gjc/skills/autoresearch/auto-critic.md", { with: { type: "text" } }).then(module => module.default);
43
44
 
44
45
  export const BUNDLED_GJC_SKILL_CATALOG: readonly BundledGjcSkillCatalogEntry[] = [
45
46
  {
@@ -53,15 +54,15 @@ export const BUNDLED_GJC_SKILL_CATALOG: readonly BundledGjcSkillCatalogEntry[] =
53
54
  kind: "skill",
54
55
  name: "ralplan",
55
56
  relativePath: "skills/ralplan/SKILL.md",
56
- description: "Consensus planning entrypoint that auto-gates vague team/ultragoal requests before execution",
57
+ description: "Consensus planning entrypoint that auto-gates vague ultragoal requests before execution",
57
58
  loadContent: ralplan,
58
59
  },
59
60
  {
60
61
  kind: "skill",
61
- name: "team",
62
- relativePath: "skills/team/SKILL.md",
63
- description: "Multi-worker GJC tmux team orchestration",
64
- loadContent: team,
62
+ name: "autoresearch",
63
+ relativePath: "skills/autoresearch/SKILL.md",
64
+ description: "Goal-directed research missions interleaving web and data evidence into a structured verdict",
65
+ loadContent: autoresearch,
65
66
  },
66
67
  {
67
68
  kind: "skill",
@@ -70,12 +71,6 @@ export const BUNDLED_GJC_SKILL_CATALOG: readonly BundledGjcSkillCatalogEntry[] =
70
71
  description: "Create and execute durable repo-native multi-goal plans over GJC goal mode artifacts.",
71
72
  loadContent: ultragoal,
72
73
  },
73
- {
74
- kind: "skill-fragment",
75
- parentSkillName: "deep-interview",
76
- relativePath: "skill-fragments/deep-interview/auto-research-greenfield.md",
77
- loadContent: autoResearchGreenfield,
78
- },
79
74
  {
80
75
  kind: "skill-fragment",
81
76
  parentSkillName: "deep-interview",
@@ -100,4 +95,16 @@ export const BUNDLED_GJC_SKILL_CATALOG: readonly BundledGjcSkillCatalogEntry[] =
100
95
  relativePath: "skill-fragments/ultragoal/validation-batch-contracts.md",
101
96
  loadContent: validationBatchContracts,
102
97
  },
98
+ {
99
+ kind: "skill-fragment",
100
+ parentSkillName: "autoresearch",
101
+ relativePath: "skill-fragments/autoresearch/auto-iterate.md",
102
+ loadContent: autoresearchIterate,
103
+ },
104
+ {
105
+ kind: "skill-fragment",
106
+ parentSkillName: "autoresearch",
107
+ relativePath: "skill-fragments/autoresearch/auto-critic.md",
108
+ loadContent: autoresearchCritic,
109
+ },
103
110
  ];
@@ -4,7 +4,7 @@
4
4
  * Primary provider for GJC native configs. Supports all capabilities.
5
5
  */
6
6
  import * as path from "node:path";
7
- import { logger, parseFrontmatter, tryParseJson } from "@gajae-code/utils";
7
+ import { getAgentDir, logger, parseFrontmatter, tryParseJson } from "@gajae-code/utils";
8
8
  import { YAML } from "bun";
9
9
  import { registerProvider } from "../capability";
10
10
  import { type ContextFile, contextFileCapability } from "../capability/context-file";
@@ -45,6 +45,20 @@ function getUserAgentDirs(): string[] {
45
45
  return [PATHS.userAgent];
46
46
  }
47
47
 
48
+ /**
49
+ * GJC's user-scope config directory.
50
+ *
51
+ * Home-relative `<home>/.gjc/agent` is only its default location: an agent
52
+ * directory profile (`--agent-dir`, `GJC_CODING_AGENT_DIR`, `setAgentDir()`)
53
+ * moves the whole user scope, and the writers (`getMCPConfigPath("user")` and
54
+ * everything `gjc mcp add` reaches) already follow it. Resolving from the home
55
+ * default instead would hide a profile's own registrations and load the default
56
+ * profile's servers into it.
57
+ */
58
+ function resolveUserAgentDir(ctx: LoadContext): string {
59
+ return ctx.userAgentDir ?? getAgentDir();
60
+ }
61
+
48
62
  function getProjectConfigDirs(): string[] {
49
63
  return [PATHS.projectDir];
50
64
  }
@@ -226,15 +240,14 @@ async function loadMCPServers(ctx: LoadContext): Promise<LoadResult<MCPServer>>
226
240
  return result;
227
241
  };
228
242
 
243
+ const userAgentDir = resolveUserAgentDir(ctx);
229
244
  const paths = [
230
245
  ...getProjectConfigDirs().flatMap(projectConfigDir => [
231
246
  { path: path.join(ctx.cwd, projectConfigDir, "mcp.json"), level: "project" as const },
232
247
  { path: path.join(ctx.cwd, projectConfigDir, ".mcp.json"), level: "project" as const },
233
248
  ]),
234
- ...getUserAgentDirs().flatMap(userAgentDir => [
235
- { path: path.join(ctx.home, userAgentDir, "mcp.json"), level: "user" as const },
236
- { path: path.join(ctx.home, userAgentDir, ".mcp.json"), level: "user" as const },
237
- ]),
249
+ { path: path.join(userAgentDir, "mcp.json"), level: "user" as const },
250
+ { path: path.join(userAgentDir, ".mcp.json"), level: "user" as const },
238
251
  ];
239
252
 
240
253
  const contents = await Promise.allSettled(
@@ -1,5 +1,4 @@
1
1
  import * as fs from "node:fs";
2
- import * as os from "node:os";
3
2
  import * as path from "node:path";
4
3
  import type { ThinkingLevel } from "@gajae-code/agent-core";
5
4
  import type { FileType as FileTypeEnum, glob as globFn } from "@gajae-code/natives";
@@ -8,6 +7,7 @@ import {
8
7
  getConfigDirName,
9
8
  getPluginsDir,
10
9
  getProjectDir,
10
+ getTrustedHomeDir,
11
11
  logger,
12
12
  parseFrontmatter,
13
13
  tryParseJson,
@@ -795,8 +795,8 @@ export function parseClaudePluginsRegistry(content: string): ClaudePluginsRegist
795
795
  */
796
796
  export async function resolveActiveProjectRegistryPath(cwd: string): Promise<string | null> {
797
797
  // Pass 1: walk up looking for an existing .gjc/ directory (nearest wins).
798
- // Stop before os.homedir() — ~/.gjc/ is the user-level config dir, not a project root.
799
- const homeDir = os.homedir();
798
+ // Stop before the provenance-checked home — ~/.gjc/ is the user-level config dir, not a project root.
799
+ const homeDir = getTrustedHomeDir();
800
800
  let dir = path.resolve(cwd);
801
801
  while (dir !== homeDir) {
802
802
  try {
@@ -837,7 +837,7 @@ export async function resolveActiveProjectRegistryPath(cwd: string): Promise<str
837
837
  * bootstrapped directory (no .gjc/ or .git/ yet) works: writeInstalledPluginsRegistry auto-creates
838
838
  * the directory tree on first write.
839
839
  *
840
- * Returns undefined when cwd is os.homedir() — that path is already the user registry and must
840
+ * Returns undefined when cwd is the trusted home — that path is already the user registry and must
841
841
  * never alias as the project registry.
842
842
  */
843
843
  export async function resolveOrDefaultProjectRegistryPath(cwd: string): Promise<string | undefined> {
@@ -846,7 +846,7 @@ export async function resolveOrDefaultProjectRegistryPath(cwd: string): Promise<
846
846
  // Home directory must not be treated as a project root: the fallback path would alias
847
847
  // getInstalledPluginsRegistryPath(), causing MarketplaceManager to load the same file
848
848
  // as both user and project registry and producing duplicates / disambiguation errors.
849
- if (path.resolve(cwd) === os.homedir()) return undefined;
849
+ if (path.resolve(cwd) === getTrustedHomeDir()) return undefined;
850
850
  return path.join(cwd, getConfigDirName(), "plugins", "installed_plugins.json");
851
851
  }
852
852
 
@@ -873,7 +873,7 @@ export async function listClaudePluginRoots(
873
873
  const projectRoots: ClaudePluginRoot[] = [];
874
874
 
875
875
  // ── GJC installed plugins registry ───────────────────────────────────────
876
- // In production `home` is `os.homedir()`, so `getPluginsDir(home)` resolves to the
876
+ // In production `home` is the provenance-checked home, so `getPluginsDir(home)` resolves to the
877
877
  // same XDG-aware path the marketplace writer uses (reads and writes always agree).
878
878
  // Tests pass a temp dir, which short-circuits the resolver for deterministic isolation.
879
879
  const gjcRegistryPath = path.join(getPluginsDir(home), "installed_plugins.json");
package/src/edit/index.ts CHANGED
@@ -337,7 +337,10 @@ export class EditTool implements AgentTool<TInput> {
337
337
  readonly #vimTool: VimTool;
338
338
  readonly #pendingDeferredFetches = new Map<string, AbortController>();
339
339
 
340
- constructor(private readonly session: ToolSession) {
340
+ constructor(
341
+ private readonly session: ToolSession,
342
+ private readonly modeOverride?: EditMode,
343
+ ) {
341
344
  const { PI_EDIT_FUZZY: editFuzzy = "auto", PI_EDIT_FUZZY_THRESHOLD: editFuzzyThreshold = "auto" } = Bun.env;
342
345
 
343
346
  // Fail fast on an invalid forced env variant; the shared resolver owns
@@ -350,7 +353,7 @@ export class EditTool implements AgentTool<TInput> {
350
353
  }
351
354
 
352
355
  get mode(): EditMode {
353
- return resolveEditMode(this.session);
356
+ return this.modeOverride ?? resolveEditMode(this.session);
354
357
  }
355
358
 
356
359
  get description(): string {
@@ -35,6 +35,8 @@ export interface PythonExecutorOptions {
35
35
  kernelOwnerId?: string;
36
36
  /** Kernel mode (session reuse vs per-call) */
37
37
  kernelMode?: PythonKernelMode;
38
+ /** Called when a retained session kernel is acquired or replaced. */
39
+ onKernelStart?: (kernelInstanceId: string) => void;
38
40
  /** Restart the kernel before executing */
39
41
  reset?: boolean;
40
42
  /** Session file path for accessing task outputs */
@@ -107,6 +109,7 @@ export interface PythonResult {
107
109
  interface PythonSession {
108
110
  sessionId: string;
109
111
  kernel: PythonKernel;
112
+ kernelInstanceId: string;
110
113
  bridgeCapability?: string;
111
114
  ownerIds: Set<string>;
112
115
  hasFallbackOwner: boolean;
@@ -365,6 +368,7 @@ async function acquireSession(sessionId: string, cwd: string, options: PythonExe
365
368
  const session: PythonSession = {
366
369
  sessionId,
367
370
  kernel,
371
+ kernelInstanceId: crypto.randomUUID(),
368
372
  bridgeCapability: options.bridge?.capability,
369
373
  ownerIds: new Set(),
370
374
  hasFallbackOwner: false,
@@ -447,6 +451,7 @@ async function replaceSessionKernel(
447
451
  throw new PythonExecutionCancelledError(false);
448
452
  }
449
453
  session.kernel = next;
454
+ session.kernelInstanceId = crypto.randomUUID();
450
455
  session.bridgeCapability = nextCapability;
451
456
  } catch (err) {
452
457
  await next?.shutdown().catch(() => undefined);
@@ -716,6 +721,7 @@ async function executeOnSession(code: string, cwd: string, options: PythonExecut
716
721
  if (options.bridge && session.bridgeCapability) {
717
722
  options.bridge.capability = session.bridgeCapability;
718
723
  }
724
+ options.onKernelStart?.(session.kernelInstanceId);
719
725
  return await runQueued(session, options, async () => {
720
726
  if (options.signal?.aborted) {
721
727
  throw new PythonExecutionCancelledError(isTimedOutCancellation(options.signal.reason, options.signal));
@@ -728,6 +734,7 @@ async function executeOnSession(code: string, cwd: string, options: PythonExecut
728
734
  if (sessions.get(session.sessionId) !== session) {
729
735
  throw new PythonExecutionCancelledError(false);
730
736
  }
737
+ options.onKernelStart?.(session.kernelInstanceId);
731
738
  }
732
739
  try {
733
740
  return await executeWithKernel(session.kernel, code, options);
@@ -742,6 +749,7 @@ async function executeOnSession(code: string, cwd: string, options: PythonExecut
742
749
  if (sessions.get(session.sessionId) !== session) {
743
750
  throw new PythonExecutionCancelledError(false);
744
751
  }
752
+ options.onKernelStart?.(session.kernelInstanceId);
745
753
  return await executeWithKernel(session.kernel, code, options);
746
754
  }
747
755
  });