@gajae-code/coding-agent 0.16.7 → 0.17.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 (321) hide show
  1. package/CHANGELOG.md +180 -1
  2. package/dist/types/capability/fs.d.ts +37 -4
  3. package/dist/types/capability/index.d.ts +19 -0
  4. package/dist/types/capability/types.d.ts +9 -0
  5. package/dist/types/cli/doctor/args.d.ts +36 -0
  6. package/dist/types/cli/doctor/checks.d.ts +18 -0
  7. package/dist/types/cli/doctor/config-repairs.d.ts +38 -0
  8. package/dist/types/cli/doctor/context.d.ts +89 -0
  9. package/dist/types/cli/doctor/files.d.ts +27 -0
  10. package/dist/types/cli/doctor/ids.d.ts +20 -0
  11. package/dist/types/cli/doctor/install-repairs.d.ts +94 -0
  12. package/dist/types/cli/doctor/journal.d.ts +43 -0
  13. package/dist/types/cli/doctor/managed-link.d.ts +39 -0
  14. package/dist/types/cli/doctor/native-probe.d.ts +2 -0
  15. package/dist/types/cli/doctor/permission-repairs.d.ts +25 -0
  16. package/dist/types/cli/doctor/plugin-quarantine.d.ts +77 -0
  17. package/dist/types/cli/doctor/plugin-restore.d.ts +40 -0
  18. package/dist/types/cli/doctor/plugin-targets.d.ts +11 -0
  19. package/dist/types/cli/doctor/probe-client.d.ts +9 -0
  20. package/dist/types/cli/doctor/probe-types.d.ts +18 -0
  21. package/dist/types/cli/doctor/probe.d.ts +3 -0
  22. package/dist/types/cli/doctor/projection-probe.d.ts +2 -0
  23. package/dist/types/cli/doctor/repairs.d.ts +28 -0
  24. package/dist/types/cli/doctor/report.d.ts +27 -0
  25. package/dist/types/cli/doctor/runner.d.ts +4 -0
  26. package/dist/types/cli/doctor/safety.d.ts +10 -0
  27. package/dist/types/cli/doctor/service-repairs.d.ts +8 -0
  28. package/dist/types/cli/doctor/service-targets.d.ts +41 -0
  29. package/dist/types/cli/doctor/types.d.ts +145 -0
  30. package/dist/types/cli/doctor-cli.d.ts +7 -0
  31. package/dist/types/cli/doctor-supervisor.d.ts +121 -0
  32. package/dist/types/cli/doctor-worker.d.ts +29 -0
  33. package/dist/types/cli/install-activation.d.ts +158 -0
  34. package/dist/types/cli/macos-community-app.d.ts +41 -0
  35. package/dist/types/cli/mcp-cli.d.ts +0 -11
  36. package/dist/types/cli/update-cli.d.ts +41 -4
  37. package/dist/types/cli-main.d.ts +174 -0
  38. package/dist/types/cli.d.ts +1 -171
  39. package/dist/types/commands/doctor.d.ts +7 -0
  40. package/dist/types/commands/sdk.d.ts +17 -8
  41. package/dist/types/config/autorouting-tier-map.d.ts +19 -0
  42. package/dist/types/config/file-lock.d.ts +27 -3
  43. package/dist/types/config/model-preset-registry.d.ts +1 -0
  44. package/dist/types/config/model-registry.d.ts +12 -5
  45. package/dist/types/config/model-resolver.d.ts +16 -3
  46. package/dist/types/config/models-config-schema.d.ts +2 -0
  47. package/dist/types/config/settings-schema.d.ts +1 -1
  48. package/dist/types/coordinator-mcp/question-gate-codec.d.ts +1 -1
  49. package/dist/types/coordinator-mcp/session-reaper.d.ts +15 -5
  50. package/dist/types/cursor.d.ts +9 -9
  51. package/dist/types/discovery/agents-md.d.ts +6 -1
  52. package/dist/types/discovery/helpers.d.ts +36 -7
  53. package/dist/types/discovery/index.d.ts +1 -1
  54. package/dist/types/discovery/mcp-json.d.ts +2 -0
  55. package/dist/types/extensibility/extensions/loader.d.ts +22 -1
  56. package/dist/types/extensibility/gjc-plugins/lifecycle.d.ts +14 -1
  57. package/dist/types/extensibility/gjc-plugins/paths.d.ts +2 -1
  58. package/dist/types/extensibility/gjc-plugins/types.d.ts +25 -0
  59. package/dist/types/extensibility/plugins/manager.d.ts +33 -4
  60. package/dist/types/extensibility/plugins/marketplace/cache.d.ts +6 -0
  61. package/dist/types/extensibility/plugins/marketplace/manager.d.ts +186 -0
  62. package/dist/types/extensibility/plugins/marketplace/registry.d.ts +27 -0
  63. package/dist/types/extensibility/plugins/marketplace/source-resolver.d.ts +16 -1
  64. package/dist/types/extensibility/runtime-skill-discovery.d.ts +16 -3
  65. package/dist/types/gjc-runtime/autoresearch-runtime.d.ts +6 -0
  66. package/dist/types/gjc-runtime/launch-worktree.d.ts +53 -0
  67. package/dist/types/gjc-runtime/session-layout.d.ts +8 -0
  68. package/dist/types/gjc-runtime/session-state-lock.d.ts +15 -0
  69. package/dist/types/gjc-runtime/session-state-sidecar.d.ts +13 -0
  70. package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +6 -0
  71. package/dist/types/main.d.ts +19 -1
  72. package/dist/types/modes/acp/acp-agent.d.ts +40 -0
  73. package/dist/types/modes/components/agent-dashboard.d.ts +1 -0
  74. package/dist/types/modes/components/model-selector.d.ts +2 -0
  75. package/dist/types/modes/interactive-mode.d.ts +1 -1
  76. package/dist/types/runtime-mcp/config-writer.d.ts +47 -0
  77. package/dist/types/runtime-mcp/policy-json-edit.d.ts +60 -0
  78. package/dist/types/runtime-mcp/startup-policy.d.ts +4 -0
  79. package/dist/types/runtime-mcp/types.d.ts +2 -2
  80. package/dist/types/sdk/acp/adapter.d.ts +5 -1
  81. package/dist/types/sdk/broker/broker.d.ts +51 -0
  82. package/dist/types/sdk/broker/daemon-entry.d.ts +39 -0
  83. package/dist/types/sdk/broker/discovery.d.ts +38 -0
  84. package/dist/types/sdk/broker/doctor-restart.d.ts +79 -0
  85. package/dist/types/sdk/broker/endpoint-authority.d.ts +7 -0
  86. package/dist/types/sdk/broker/ensure.d.ts +14 -0
  87. package/dist/types/sdk/broker/lifecycle.d.ts +2 -0
  88. package/dist/types/sdk/broker/process-incarnation.d.ts +50 -0
  89. package/dist/types/sdk/broker/runtime.d.ts +26 -0
  90. package/dist/types/sdk/broker/session-index.d.ts +13 -4
  91. package/dist/types/sdk/broker/worktree-occupancy.d.ts +14 -0
  92. package/dist/types/sdk/bus/chat-daemon-cli.d.ts +16 -0
  93. package/dist/types/sdk/bus/chat-daemon-control.d.ts +101 -6
  94. package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +16 -0
  95. package/dist/types/sdk/bus/daemon-startup-exclusion.d.ts +43 -0
  96. package/dist/types/sdk/bus/doctor-daemon-restart-client.d.ts +51 -0
  97. package/dist/types/sdk/bus/doctor-daemon-restart.d.ts +39 -0
  98. package/dist/types/sdk/bus/index.d.ts +2 -0
  99. package/dist/types/sdk/bus/notification-service.d.ts +3 -0
  100. package/dist/types/sdk/bus/telegram-daemon-cli.d.ts +11 -0
  101. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +1 -1
  102. package/dist/types/sdk/bus/telegram-daemon-control.d.ts +5 -0
  103. package/dist/types/sdk/bus/telegram-daemon-owner-registry.d.ts +1 -0
  104. package/dist/types/sdk/bus/telegram-daemon.d.ts +36 -5
  105. package/dist/types/sdk/cli/session-cli.d.ts +1 -0
  106. package/dist/types/sdk/host/session-runtime.d.ts +4 -0
  107. package/dist/types/sdk/host/surface-policy.d.ts +3 -1
  108. package/dist/types/sdk/lifecycle/service.d.ts +44 -10
  109. package/dist/types/sdk/prompt-deadline-lease.d.ts +6 -3
  110. package/dist/types/sdk/prompt-deadline-manager.d.ts +2 -2
  111. package/dist/types/sdk/prompt-failure.d.ts +47 -0
  112. package/dist/types/sdk/prompt-status.d.ts +19 -0
  113. package/dist/types/sdk/router/session-router.d.ts +3 -4
  114. package/dist/types/sdk/service-artifact-paths.d.ts +16 -0
  115. package/dist/types/sdk/session-authority.d.ts +9 -0
  116. package/dist/types/sdk/session.d.ts +3 -1
  117. package/dist/types/session/agent-session.d.ts +1 -1
  118. package/dist/types/session/blob-store.d.ts +1 -1
  119. package/dist/types/session/fallback-chain-controller.d.ts +3 -6
  120. package/dist/types/session/internal/managed-session-scope.d.ts +44 -0
  121. package/dist/types/session/primary-control-surface.d.ts +4 -0
  122. package/dist/types/session/session-manager.d.ts +6 -0
  123. package/dist/types/system-prompt.d.ts +6 -0
  124. package/dist/types/tools/ask.d.ts +25 -0
  125. package/dist/types/tools/image-gen.d.ts +0 -4
  126. package/dist/types/tools/skill-discovery.d.ts +7 -5
  127. package/dist/types/tools/ultragoal-ask-guard.d.ts +7 -4
  128. package/dist/types/utils/changelog.d.ts +0 -9
  129. package/dist/types/utils/mupdf-wasm.d.ts +1 -0
  130. package/package.json +9 -8
  131. package/scripts/compile-args.ts +8 -4
  132. package/src/capability/fs.ts +395 -17
  133. package/src/capability/index.ts +273 -10
  134. package/src/capability/types.ts +9 -0
  135. package/src/cli/customize-doctor.ts +18 -12
  136. package/src/cli/doctor/args.ts +236 -0
  137. package/src/cli/doctor/checks.ts +431 -0
  138. package/src/cli/doctor/config-repairs.ts +517 -0
  139. package/src/cli/doctor/context.ts +149 -0
  140. package/src/cli/doctor/files.ts +149 -0
  141. package/src/cli/doctor/ids.ts +115 -0
  142. package/src/cli/doctor/install-repairs.ts +335 -0
  143. package/src/cli/doctor/journal.ts +423 -0
  144. package/src/cli/doctor/managed-link.ts +514 -0
  145. package/src/cli/doctor/native-probe.ts +13 -0
  146. package/src/cli/doctor/permission-repairs.ts +242 -0
  147. package/src/cli/doctor/plugin-quarantine.ts +377 -0
  148. package/src/cli/doctor/plugin-restore.ts +59 -0
  149. package/src/cli/doctor/plugin-targets.ts +373 -0
  150. package/src/cli/doctor/probe-client.ts +195 -0
  151. package/src/cli/doctor/probe-types.ts +21 -0
  152. package/src/cli/doctor/probe.ts +42 -0
  153. package/src/cli/doctor/projection-probe.ts +249 -0
  154. package/src/cli/doctor/repairs.ts +1157 -0
  155. package/src/cli/doctor/report.ts +176 -0
  156. package/src/cli/doctor/runner.ts +342 -0
  157. package/src/cli/doctor/safety.ts +40 -0
  158. package/src/cli/doctor/service-repairs.ts +452 -0
  159. package/src/cli/doctor/service-targets.ts +274 -0
  160. package/src/cli/doctor/types.ts +164 -0
  161. package/src/cli/doctor-cli.ts +62 -0
  162. package/src/cli/doctor-supervisor.ts +571 -0
  163. package/src/cli/doctor-worker.ts +181 -0
  164. package/src/cli/install-activation.ts +666 -0
  165. package/src/cli/macos-community-app.ts +1449 -0
  166. package/src/cli/mcp-cli.ts +11 -21
  167. package/src/cli/nofile-limit.ts +5 -1
  168. package/src/cli/plugin-cli.ts +6 -1
  169. package/src/cli/update-cli.ts +362 -264
  170. package/src/cli-main.ts +517 -0
  171. package/src/cli.ts +64 -433
  172. package/src/commands/autoresearch.ts +11 -5
  173. package/src/commands/completion.ts +1 -1
  174. package/src/commands/doctor.ts +13 -0
  175. package/src/commands/sdk.ts +58 -10
  176. package/src/commands/ultragoal.ts +11 -5
  177. package/src/config/autorouting-tier-map.ts +7 -0
  178. package/src/config/file-lock.ts +736 -71
  179. package/src/config/mcp-schema.json +3 -3
  180. package/src/config/model-preset-registry.ts +1 -0
  181. package/src/config/model-registry.ts +80 -27
  182. package/src/config/model-resolver.ts +33 -4
  183. package/src/config/models-config-schema.ts +2 -0
  184. package/src/config/settings-schema.ts +6 -2
  185. package/src/coordinator-mcp/question-gate-codec.ts +1 -0
  186. package/src/coordinator-mcp/server.ts +534 -51
  187. package/src/coordinator-mcp/session-reaper.ts +64 -8
  188. package/src/cursor.ts +223 -53
  189. package/src/discovery/agents-md.ts +74 -8
  190. package/src/discovery/agents.ts +32 -7
  191. package/src/discovery/builtin.ts +184 -75
  192. package/src/discovery/claude-plugins.ts +85 -17
  193. package/src/discovery/cline.ts +38 -10
  194. package/src/discovery/cursor.ts +19 -6
  195. package/src/discovery/gemini.ts +62 -22
  196. package/src/discovery/github.ts +13 -3
  197. package/src/discovery/helpers.ts +483 -89
  198. package/src/discovery/index.ts +1 -0
  199. package/src/discovery/mcp-json.ts +36 -10
  200. package/src/discovery/opencode.ts +36 -19
  201. package/src/discovery/ssh.ts +11 -8
  202. package/src/discovery/windsurf.ts +12 -3
  203. package/src/exec/bash-executor.ts +10 -3
  204. package/src/exec/isolated-shell.ts +15 -2
  205. package/src/extensibility/extensions/loader.ts +88 -26
  206. package/src/extensibility/gjc-plugins/lifecycle.ts +189 -0
  207. package/src/extensibility/gjc-plugins/paths.ts +4 -1
  208. package/src/extensibility/gjc-plugins/types.ts +27 -0
  209. package/src/extensibility/plugins/manager.ts +200 -22
  210. package/src/extensibility/plugins/marketplace/cache.ts +55 -2
  211. package/src/extensibility/plugins/marketplace/manager.ts +1262 -162
  212. package/src/extensibility/plugins/marketplace/registry.ts +153 -0
  213. package/src/extensibility/plugins/marketplace/source-resolver.ts +116 -10
  214. package/src/extensibility/runtime-skill-discovery.ts +61 -9
  215. package/src/extensibility/skill-management.ts +7 -1
  216. package/src/gjc-runtime/autoresearch-runtime.ts +10 -1
  217. package/src/gjc-runtime/launch-worktree.test.ts +248 -0
  218. package/src/gjc-runtime/launch-worktree.ts +275 -38
  219. package/src/gjc-runtime/repository-binding.ts +26 -1
  220. package/src/gjc-runtime/session-layout.ts +10 -0
  221. package/src/gjc-runtime/session-state-lock.ts +330 -23
  222. package/src/gjc-runtime/session-state-sidecar.ts +328 -80
  223. package/src/gjc-runtime/ultragoal-runtime.ts +10 -1
  224. package/src/harness-control-plane/session-lease.ts +2 -2
  225. package/src/internal-urls/docs-index.generated.ts +28 -26
  226. package/src/main.ts +150 -29
  227. package/src/memories/index.ts +24 -2
  228. package/src/modes/acp/acp-agent.ts +522 -68
  229. package/src/modes/components/agent-dashboard.ts +3 -1
  230. package/src/modes/components/model-selector.ts +28 -19
  231. package/src/modes/components/plugin-settings.ts +2 -1
  232. package/src/modes/controllers/selector-controller.ts +15 -9
  233. package/src/modes/interactive-mode.ts +21 -3
  234. package/src/prompts/system/system-prompt.md +5 -1
  235. package/src/prompts/tools/browser.md +1 -1
  236. package/src/prompts/tools/move-session.md +4 -0
  237. package/src/prompts/tools/read.md +2 -1
  238. package/src/prompts/tools/skill-discovery.md +6 -5
  239. package/src/prompts/tools/task.md +1 -0
  240. package/src/runtime-mcp/config-writer.ts +228 -0
  241. package/src/runtime-mcp/oauth-discovery.ts +114 -14
  242. package/src/runtime-mcp/policy-json-edit.ts +129 -0
  243. package/src/runtime-mcp/startup-policy.ts +14 -0
  244. package/src/runtime-mcp/types.ts +2 -2
  245. package/src/sdk/acp/adapter.ts +27 -12
  246. package/src/sdk/broker/broker.ts +273 -44
  247. package/src/sdk/broker/daemon-entry.ts +119 -0
  248. package/src/sdk/broker/discovery.ts +173 -20
  249. package/src/sdk/broker/doctor-restart.ts +206 -0
  250. package/src/sdk/broker/endpoint-authority.ts +36 -0
  251. package/src/sdk/broker/ensure.ts +49 -14
  252. package/src/sdk/broker/lifecycle.ts +174 -42
  253. package/src/sdk/broker/process-incarnation.ts +86 -2
  254. package/src/sdk/broker/runtime.ts +145 -21
  255. package/src/sdk/broker/session-index.ts +136 -22
  256. package/src/sdk/broker/spawn-substrate.ts +4 -1
  257. package/src/sdk/broker/transport.ts +5 -0
  258. package/src/sdk/broker/worktree-occupancy.ts +21 -1
  259. package/src/sdk/bus/chat-daemon-cli.ts +63 -0
  260. package/src/sdk/bus/chat-daemon-control.ts +260 -64
  261. package/src/sdk/bus/chat-daemon-runtime.ts +141 -25
  262. package/src/sdk/bus/daemon-startup-exclusion.ts +119 -0
  263. package/src/sdk/bus/doctor-daemon-restart-client.ts +291 -0
  264. package/src/sdk/bus/doctor-daemon-restart.ts +92 -0
  265. package/src/sdk/bus/index.ts +252 -51
  266. package/src/sdk/bus/kind-aware-reconciliation.ts +76 -41
  267. package/src/sdk/bus/notification-service.ts +21 -3
  268. package/src/sdk/bus/reconciliation-store.ts +17 -11
  269. package/src/sdk/bus/telegram-daemon-cli.ts +91 -5
  270. package/src/sdk/bus/telegram-daemon-contract.ts +1 -1
  271. package/src/sdk/bus/telegram-daemon-control.ts +47 -0
  272. package/src/sdk/bus/telegram-daemon-owner-registry.ts +1 -1
  273. package/src/sdk/bus/telegram-daemon.ts +178 -13
  274. package/src/sdk/cli/session-cli.ts +100 -12
  275. package/src/sdk/host/host.ts +2 -7
  276. package/src/sdk/host/session-runtime.test.ts +329 -8
  277. package/src/sdk/host/session-runtime.ts +202 -50
  278. package/src/sdk/host/surface-policy.ts +8 -1
  279. package/src/sdk/lifecycle/service.ts +199 -22
  280. package/src/sdk/mcp/server.ts +1 -1
  281. package/src/sdk/prompt-deadline-lease.ts +12 -4
  282. package/src/sdk/prompt-deadline-manager.ts +5 -7
  283. package/src/sdk/prompt-failure.ts +148 -0
  284. package/src/sdk/prompt-status.ts +30 -1
  285. package/src/sdk/prompt-watchdog.ts +11 -3
  286. package/src/sdk/protocol/operation-inventory.generated.json +18 -0
  287. package/src/sdk/protocol/operation-registry.ts +20 -8
  288. package/src/sdk/router/session-router.ts +8 -3
  289. package/src/sdk/service-artifact-paths.ts +26 -0
  290. package/src/sdk/session-authority.ts +10 -0
  291. package/src/sdk/session.ts +361 -194
  292. package/src/session/agent-session.ts +398 -93
  293. package/src/session/blob-store.ts +9 -9
  294. package/src/session/fallback-chain-controller.ts +3 -7
  295. package/src/session/internal/managed-session-scope.ts +445 -29
  296. package/src/session/internal/managed-session-storage.ts +38 -6
  297. package/src/session/primary-control-surface.ts +12 -0
  298. package/src/session/session-manager.ts +11 -3
  299. package/src/session/session-storage.ts +1 -1
  300. package/src/session-import/codex.ts +6 -1
  301. package/src/session-import/redact.ts +7 -0
  302. package/src/skill-state/workflow-mutation-guard.ts +645 -39
  303. package/src/slash-commands/builtin-registry.ts +7 -3
  304. package/src/system-prompt.ts +8 -0
  305. package/src/task/executor.ts +36 -3
  306. package/src/task/types.ts +27 -5
  307. package/src/tools/ask.ts +114 -34
  308. package/src/tools/browser/actions.ts +2 -2
  309. package/src/tools/browser/tab-worker.ts +11 -8
  310. package/src/tools/descriptors.ts +6 -1
  311. package/src/tools/fetch.ts +7 -2
  312. package/src/tools/image-gen.ts +33 -34
  313. package/src/tools/read.ts +78 -32
  314. package/src/tools/skill-discovery.ts +17 -7
  315. package/src/tools/tool-catalog.generated.ts +8 -8
  316. package/src/tools/ultragoal-ask-guard.ts +16 -26
  317. package/src/utils/changelog.ts +7 -1
  318. package/src/utils/git.ts +3 -1
  319. package/src/utils/markit.ts +24 -2
  320. package/src/utils/mupdf-wasm.ts +26 -0
  321. package/src/web/search/providers/openai-compatible.ts +191 -14
@@ -83,6 +83,7 @@ interface AgentDashboardModelContext {
83
83
  modelRegistry?: ModelRegistry;
84
84
  activeModelPattern?: string;
85
85
  defaultModelPattern?: string;
86
+ credentialSessionId?: string;
86
87
  }
87
88
 
88
89
  export function resolveAgentCreationModel(
@@ -602,7 +603,7 @@ export class AgentDashboard extends Container {
602
603
  if (!modelRegistry) {
603
604
  throw new Error("Model registry unavailable in current session.");
604
605
  }
605
- await modelRegistry.refresh();
606
+ await modelRegistry.refresh("online-if-uncached", this.modelContext.credentialSessionId);
606
607
 
607
608
  const settings = this.#settingsManager ?? undefined;
608
609
  const modelPatterns = resolveConfiguredModelPatterns(
@@ -622,6 +623,7 @@ export class AgentDashboard extends Container {
622
623
  modelRegistry,
623
624
  settings,
624
625
  model: selectedModel,
626
+ credentialSessionId: this.modelContext.credentialSessionId,
625
627
  systemPrompt: [systemPrompt],
626
628
  hasUI: false,
627
629
  notificationHostModeSupported: false,
@@ -391,6 +391,7 @@ export class ModelSelectorComponent extends Container {
391
391
  #onCancelCallback = (() => {}) as CancelCallback;
392
392
  #errorMessage?: unknown;
393
393
  #tui: TUI;
394
+ #renderScope: "full" | "layout";
394
395
  #scopedModels: ReadonlyArray<ScopedModelItem>;
395
396
  #temporaryOnly: boolean;
396
397
  #currentModel?: Model;
@@ -452,6 +453,8 @@ export class ModelSelectorComponent extends Container {
452
453
  onSelect: RoleSelectCallback,
453
454
  onCancel: () => void,
454
455
  options?: {
456
+ /** Use layout only when mounted outside the viewport-anchor transcript subtree. */
457
+ renderScope?: "full" | "layout";
455
458
  temporaryOnly?: boolean;
456
459
  initialSearchInput?: string;
457
460
  sessionId?: string;
@@ -473,6 +476,7 @@ export class ModelSelectorComponent extends Container {
473
476
  super();
474
477
 
475
478
  this.#tui = tui;
479
+ this.#renderScope = options?.renderScope ?? "full";
476
480
  this.#settings = settings;
477
481
  this.#modelRegistry = modelRegistry;
478
482
  this.#scopedModels = scopedModels;
@@ -556,7 +560,7 @@ export class ModelSelectorComponent extends Container {
556
560
  this.#clampPresetCursor();
557
561
  void this.#refreshProviderAuth();
558
562
  this.#renderPresetLanding();
559
- this.#tui.requestRender();
563
+ this.#requestRender();
560
564
  return;
561
565
  }
562
566
  if (this.#viewMode === "smart-routing" && this.#smartRoutingPanel) return;
@@ -567,7 +571,7 @@ export class ModelSelectorComponent extends Container {
567
571
  void this.#initializeCatalogView();
568
572
  return;
569
573
  }
570
- if (this.#refreshCatalogView()) this.#tui.requestRender();
574
+ if (this.#refreshCatalogView()) this.#requestRender();
571
575
  });
572
576
  }
573
577
 
@@ -588,7 +592,7 @@ export class ModelSelectorComponent extends Container {
588
592
  const panel = this.#smartRoutingPanel;
589
593
  if (!panel) return;
590
594
  panel.updateProviderOrderHint(this.#providerOrderHintFor(panel.getProviderOrder()));
591
- this.#tui.requestRender();
595
+ this.#requestRender();
592
596
  });
593
597
  this.#unsubscribeAuthGeneration =
594
598
  this.#modelRegistry.authStorage?.onGenerationChanged?.(() => {
@@ -606,13 +610,18 @@ export class ModelSelectorComponent extends Container {
606
610
  } else {
607
611
  this.#listContainer.addChild(new Text(theme.fg("muted", "Loading model presets..."), 0, 0));
608
612
  }
609
- this.#tui.requestRender();
613
+ this.#requestRender();
610
614
  void this.#initializePresetLanding();
611
615
  } else {
612
616
  void this.#initializeCatalogView();
613
617
  }
614
618
  }
615
619
 
620
+ #requestRender(): void {
621
+ if (this.#renderScope === "layout") this.#tui.requestLayoutRender("model-selector");
622
+ else this.#tui.requestRender();
623
+ }
624
+
616
625
  override dispose(): void {
617
626
  if (this.#disposed) return;
618
627
  this.#disposed = true;
@@ -871,7 +880,7 @@ export class ModelSelectorComponent extends Container {
871
880
  } else {
872
881
  // Reload config and cached discovery state without blocking on live provider refresh
873
882
  if (options.refreshRegistry !== false) {
874
- await this.#modelRegistry.refresh("offline");
883
+ await this.#modelRegistry.refresh("offline", this.#authSessionId);
875
884
  }
876
885
 
877
886
  // Check for models.json errors
@@ -1054,7 +1063,7 @@ export class ModelSelectorComponent extends Container {
1054
1063
  // Cache-aware: a fresh discovery cache answers instantly instead of
1055
1064
  // forcing a provider round-trip (hundreds of ms on remote gateways)
1056
1065
  // on every provider-tab visit. Stale/missing cache still fetches.
1057
- await this.#modelRegistry.refreshProvider(providerId, "online-if-uncached");
1066
+ await this.#modelRegistry.refreshProvider(providerId, "online-if-uncached", this.#authSessionId);
1058
1067
  } catch (error) {
1059
1068
  refreshError = error;
1060
1069
  }
@@ -1084,7 +1093,7 @@ export class ModelSelectorComponent extends Container {
1084
1093
  this.#commitMaterializedCatalog(catalog);
1085
1094
  this.#updateTabBar();
1086
1095
  this.#applyTabFilter();
1087
- this.#tui.requestRender();
1096
+ this.#requestRender();
1088
1097
  } catch (presentationError) {
1089
1098
  const finalError =
1090
1099
  refreshError !== undefined
@@ -1117,7 +1126,7 @@ export class ModelSelectorComponent extends Container {
1117
1126
  void this.#refreshSelectedProvider().catch(error => {
1118
1127
  this.#errorMessage = error instanceof Error ? error.message : String(error);
1119
1128
  this.#updateList();
1120
- this.#tui.requestRender();
1129
+ this.#requestRender();
1121
1130
  });
1122
1131
  };
1123
1132
  this.#tabBar = tabBar;
@@ -1645,7 +1654,7 @@ export class ModelSelectorComponent extends Container {
1645
1654
  ) {
1646
1655
  this.#providerAuthPending = false;
1647
1656
  this.#renderPresetLanding();
1648
- this.#tui.requestRender();
1657
+ this.#requestRender();
1649
1658
  }
1650
1659
  }
1651
1660
  }
@@ -1739,7 +1748,7 @@ export class ModelSelectorComponent extends Container {
1739
1748
  }
1740
1749
  void this.#refreshProviderAuth();
1741
1750
  this.#renderPresetLanding();
1742
- this.#tui.requestRender();
1751
+ this.#requestRender();
1743
1752
  }
1744
1753
 
1745
1754
  #switchToModelMode(seed?: string, options?: { imageRoleFilter?: boolean }): void {
@@ -1766,7 +1775,7 @@ export class ModelSelectorComponent extends Container {
1766
1775
  this.#headerContainer.clear();
1767
1776
  this.#listContainer.clear();
1768
1777
  this.#listContainer.addChild(new Text(theme.fg("muted", "Loading models..."), 0, 0));
1769
- this.#tui.requestRender();
1778
+ this.#requestRender();
1770
1779
 
1771
1780
  const load = this.#loadModels().then(() => {
1772
1781
  this.#catalogLoaded = true;
@@ -1786,7 +1795,7 @@ export class ModelSelectorComponent extends Container {
1786
1795
  this.#buildProviderTabs();
1787
1796
  this.#updateTabBar();
1788
1797
  this.#updateList();
1789
- this.#tui.requestRender();
1798
+ this.#requestRender();
1790
1799
  }
1791
1800
  } finally {
1792
1801
  if (this.#catalogLoadPromise === load) this.#catalogLoadPromise = undefined;
@@ -1798,7 +1807,7 @@ export class ModelSelectorComponent extends Container {
1798
1807
  this.#updateTabBar();
1799
1808
  // Apply the latest query: input remains responsive while the catalog loads.
1800
1809
  this.#filterModels(this.#searchInput.getValue());
1801
- this.#tui.requestRender();
1810
+ this.#requestRender();
1802
1811
  }
1803
1812
 
1804
1813
  /**
@@ -1945,7 +1954,7 @@ export class ModelSelectorComponent extends Container {
1945
1954
  this.#tabBar = null;
1946
1955
  this.#listContainer.clear();
1947
1956
  this.#listContainer.addChild(this.#smartRoutingPanel);
1948
- this.#tui.requestRender();
1957
+ this.#requestRender();
1949
1958
  }
1950
1959
 
1951
1960
  #switchToPresetMode(): void {
@@ -1954,7 +1963,7 @@ export class ModelSelectorComponent extends Container {
1954
1963
  this.#presetCursor = Math.min(this.#presetCursor, Math.max(0, this.#getPresetRows().length - 1));
1955
1964
  void this.#refreshProviderAuth();
1956
1965
  this.#renderPresetLanding();
1957
- this.#tui.requestRender();
1966
+ this.#requestRender();
1958
1967
  }
1959
1968
 
1960
1969
  refreshSmartRoutingState(): void {
@@ -1971,7 +1980,7 @@ export class ModelSelectorComponent extends Container {
1971
1980
  stale: this.#smartRoutingIsStale(),
1972
1981
  preview,
1973
1982
  });
1974
- this.#tui.requestRender();
1983
+ this.#requestRender();
1975
1984
  }
1976
1985
 
1977
1986
  #renderPresetLanding(): void {
@@ -2717,7 +2726,7 @@ export class ModelSelectorComponent extends Container {
2717
2726
  this.#clampPresetCursor();
2718
2727
  }
2719
2728
  void this.#refreshProviderAuth();
2720
- this.#tui.requestRender();
2729
+ this.#requestRender();
2721
2730
  }
2722
2731
 
2723
2732
  #beginActionMenuOrSelect(item: ModelItem | CanonicalModelItem): void {
@@ -2930,7 +2939,7 @@ export class ModelSelectorComponent extends Container {
2930
2939
  async #handleTrackedAssignment(selection: Extract<ModelSelectorSelection, { kind: "assignment" }>): Promise<void> {
2931
2940
  if (this.#assignmentState !== "idle") return;
2932
2941
  this.#assignmentState = "assigning";
2933
- this.#tui.requestRender();
2942
+ this.#requestRender();
2934
2943
  try {
2935
2944
  await Promise.resolve(this.#onSelectCallback(selection));
2936
2945
  } catch {
@@ -2940,7 +2949,7 @@ export class ModelSelectorComponent extends Container {
2940
2949
  const shouldClose = this.#closeAfterAssignment;
2941
2950
  this.#closeAfterAssignment = false;
2942
2951
  if (shouldClose) this.#onCancelCallback();
2943
- else this.#tui.requestRender();
2952
+ else this.#requestRender();
2944
2953
  }
2945
2954
  }
2946
2955
 
@@ -463,7 +463,8 @@ export class PluginSettingsComponent extends Container {
463
463
 
464
464
  this.#viewComponent = new PluginDetailComponent(plugin, this.#manager, {
465
465
  onEnabledChange: async enabled => {
466
- await this.#manager.setEnabled(plugin.name, enabled);
466
+ const state = await this.#manager.getEnablementState(plugin.name, "user");
467
+ if (state.status === "ok") await this.#manager.setEnabled(plugin.name, enabled, "user", state.baseline);
467
468
  this.callbacks.onPluginChanged();
468
469
  },
469
470
  onFeatureChange: async (feature, enabled) => {
@@ -1655,7 +1655,7 @@ export class SelectorController {
1655
1655
  authStorage: this.ctx.session.modelRegistry.authStorage,
1656
1656
  trigger: "bare-login",
1657
1657
  });
1658
- await this.ctx.session.modelRegistry.refresh();
1658
+ await this.ctx.session.modelRegistry.refresh("online-if-uncached", this.ctx.session.credentialSessionId);
1659
1659
 
1660
1660
  this.ctx.chatContainer.addChild(new Spacer(1));
1661
1661
  for (const credential of summary.imported) {
@@ -1690,7 +1690,7 @@ export class SelectorController {
1690
1690
  const submit = async (input: CustomModelPresetWizardSubmit): Promise<void> => {
1691
1691
  try {
1692
1692
  const profile = await this.ctx.session.modelRegistry.saveCustomModelProfile(input.name, input.profile);
1693
- await this.ctx.session.modelRegistry.refresh("offline");
1693
+ await this.ctx.session.modelRegistry.refresh("offline", this.ctx.session.credentialSessionId);
1694
1694
  await this.ctx.notifyConfigChanged?.();
1695
1695
  this.ctx.showStatus(`Custom model preset created: ${formatModelProfileDisplayLabel(profile)}`);
1696
1696
  done();
@@ -1728,7 +1728,7 @@ export class SelectorController {
1728
1728
  }
1729
1729
  try {
1730
1730
  const renamed = await this.ctx.session.modelRegistry.renameCustomModelProfile(profileName, input);
1731
- await this.ctx.session.modelRegistry.refresh("offline");
1731
+ await this.ctx.session.modelRegistry.refresh("offline", this.ctx.session.credentialSessionId);
1732
1732
  await this.ctx.notifyConfigChanged?.();
1733
1733
  modelSelector.refreshPresetProfiles(renamed.name);
1734
1734
  this.ctx.showStatus(`Custom model preset renamed: ${formatModelProfileDisplayLabel(renamed)}`);
@@ -1774,7 +1774,7 @@ export class SelectorController {
1774
1774
  });
1775
1775
  }
1776
1776
  deletedProfile = await this.ctx.session.modelRegistry.deleteCustomModelProfile(profileName);
1777
- await this.ctx.session.modelRegistry.refresh("offline");
1777
+ await this.ctx.session.modelRegistry.refresh("offline", this.ctx.session.credentialSessionId);
1778
1778
  await this.ctx.notifyConfigChanged?.();
1779
1779
  refreshSelectorState();
1780
1780
  this.ctx.showStatus(`Custom model preset deleted: ${profileLabel}`);
@@ -1784,7 +1784,7 @@ export class SelectorController {
1784
1784
  if (deletedProfile) {
1785
1785
  try {
1786
1786
  await this.ctx.session.modelRegistry.saveCustomModelProfile(profileName, deletedProfile);
1787
- await this.ctx.session.modelRegistry.refresh("offline");
1787
+ await this.ctx.session.modelRegistry.refresh("offline", this.ctx.session.credentialSessionId);
1788
1788
  } catch (restoreErr) {
1789
1789
  presetRestoreError = restoreErr;
1790
1790
  }
@@ -1821,7 +1821,7 @@ export class SelectorController {
1821
1821
  const submit = async (input: CustomProviderWizardSubmit): Promise<void> => {
1822
1822
  try {
1823
1823
  const result = await addApiCompatibleProvider(input);
1824
- await this.ctx.session.modelRegistry.refresh("offline");
1824
+ await this.ctx.session.modelRegistry.refresh("offline", this.ctx.session.credentialSessionId);
1825
1825
  await this.ctx.notifyConfigChanged?.();
1826
1826
  this.ctx.showStatus(formatProviderSetupResult(result));
1827
1827
  wizard.complete();
@@ -2218,6 +2218,7 @@ export class SelectorController {
2218
2218
  modelRegistry: this.ctx.session.modelRegistry,
2219
2219
  activeModelPattern,
2220
2220
  defaultModelPattern: selectorHead(defaultModelPattern),
2221
+ credentialSessionId: this.ctx.session.credentialSessionId,
2221
2222
  });
2222
2223
  this.showSelector(done => {
2223
2224
  dashboard.onClose = () => {
@@ -2946,6 +2947,8 @@ export class SelectorController {
2946
2947
  },
2947
2948
  {
2948
2949
  ...options,
2950
+ // The selector replaces the composer, outside the anchored transcript.
2951
+ renderScope: "layout",
2949
2952
  sessionId: this.ctx.session.credentialSessionId,
2950
2953
  currentThinkingLevel: this.ctx.session.thinkingLevel,
2951
2954
  activeModelProfile:
@@ -3626,7 +3629,7 @@ export class SelectorController {
3626
3629
  },
3627
3630
  { manualCode },
3628
3631
  );
3629
- await this.ctx.session.modelRegistry.refresh();
3632
+ await this.ctx.session.modelRegistry.refresh("online-if-uncached", this.ctx.session.credentialSessionId);
3630
3633
  this.ctx.chatContainer.addChild(new Spacer(1));
3631
3634
  const successMessage =
3632
3635
  providerId === "opencodex"
@@ -3679,7 +3682,7 @@ export class SelectorController {
3679
3682
  return;
3680
3683
  }
3681
3684
  await clearPersistentPinForRemovedRows(this.ctx.settings, providerId, inventory, result.ids);
3682
- await this.ctx.session.modelRegistry.refresh();
3685
+ await this.ctx.session.modelRegistry.refresh("online-if-uncached", this.ctx.session.credentialSessionId);
3683
3686
  this.ctx.showStatus(
3684
3687
  `Successfully removed ${result.ids.length} stored credential${result.ids.length === 1 ? "" : "s"} from ${providerId}.`,
3685
3688
  );
@@ -3890,7 +3893,10 @@ export class SelectorController {
3890
3893
  }
3891
3894
  if (summary.imported.length > 0) {
3892
3895
  try {
3893
- await this.ctx.session.modelRegistry.refresh("offline");
3896
+ await this.ctx.session.modelRegistry.refresh(
3897
+ "offline",
3898
+ this.ctx.session.credentialSessionId,
3899
+ );
3894
3900
  } catch {
3895
3901
  logger.warn("Credential auto-import refresh failed", {
3896
3902
  classification: "refresh-failed",
@@ -45,7 +45,12 @@ import {
45
45
  starReminderLaunchGate,
46
46
  } from "../reminders/star-reminder";
47
47
  import type { NotificationSessionReconcileResult, NotificationSessionStatus } from "../sdk/bus/session-control";
48
- import type { AgentSession, AgentSessionEvent, AsyncJobSnapshotItem } from "../session/agent-session";
48
+ import {
49
+ type AgentSession,
50
+ type AgentSessionEvent,
51
+ type AsyncJobSnapshotItem,
52
+ isSessionDisposalIncompleteError,
53
+ } from "../session/agent-session";
49
54
  import type { HistoryStorage } from "../session/history-storage";
50
55
  import type { SessionContext, SessionManager } from "../session/session-manager";
51
56
  import { getRecentSessions, getSessionMessageEntryId } from "../session/session-manager";
@@ -1791,7 +1796,17 @@ export class InteractiveMode implements InteractiveModeContext {
1791
1796
 
1792
1797
  // Emit shutdown event to hooks
1793
1798
  this.session.setSdkPlanModeHandler(null);
1794
- await this.session.dispose();
1799
+ let disposalWarning: string | undefined;
1800
+ try {
1801
+ await this.session.dispose();
1802
+ } catch (error) {
1803
+ if (!isSessionDisposalIncompleteError(error)) throw error;
1804
+ // The caller deadline does not cancel the underlying persistence drain.
1805
+ // Own this expected failure here so /exit still restores the terminal and
1806
+ // enters bounded cleanup, rather than the unhandled-rejection crash path.
1807
+ disposalWarning = sanitizeText(error.message);
1808
+ logger.warn("Interactive shutdown persistence remains incomplete", { error: error.message });
1809
+ }
1795
1810
 
1796
1811
  if (this.isInitialized) {
1797
1812
  this.ui.requestRender(true);
@@ -1808,6 +1823,9 @@ export class InteractiveMode implements InteractiveModeContext {
1808
1823
  await this.petWidget?.disposeAsync();
1809
1824
  await this.#itermPetTransport?.dispose();
1810
1825
  this.stop();
1826
+ if (disposalWarning) {
1827
+ process.stderr.write(`\nShutdown incomplete: ${disposalWarning}\nPending state may not be saved.\n`);
1828
+ }
1811
1829
 
1812
1830
  // Print resumption hint if this is a persisted session
1813
1831
  const sessionId = this.sessionManager.getSessionId();
@@ -1818,7 +1836,7 @@ export class InteractiveMode implements InteractiveModeContext {
1818
1836
  );
1819
1837
  }
1820
1838
 
1821
- await postmortem.quit(0);
1839
+ await postmortem.quit(disposalWarning ? 1 : 0);
1822
1840
  }
1823
1841
 
1824
1842
  async checkShutdownRequested(): Promise<void> {
@@ -30,7 +30,11 @@ Optimize for correctness first, maintainability second, and brevity third. Prefe
30
30
  - Clear work with demonstrated architecture or sequencing risk suggests `/skill:ralplan --deliberate`; reconciliation must persist its final receipt before choosing approval or an admitted handoff. A valid non-off final runtime receipt enters the existing handoff chain; otherwise it stops pending approval.
31
31
  - Use `/skill:ultragoal` for durable goal ledgers and `/skill:autoresearch` for goal-directed research missions that end on a structured verdict rather than an implementation.
32
32
  - Delegate large implementation slices to `executor`; use `planner`, `architect`, or `critic` for bounded planning and review.
33
- - An explicit user request to use a worktree (for example, "use worktree") overrides direct editing: delegate implementation through `task` with `isolated: true`. This is the in-session counterpart of launching `gjc --worktree`; if task isolation is unavailable, report that conflict instead of editing in the parent session.
33
+ {{#if taskIsolationEnabled}}
34
+ - An explicit user request to use a worktree (for example, "use worktree") overrides direct editing: delegate implementation through `task` with `isolated: true`. This is the in-session counterpart of launching `gjc --worktree`; if a specific task cannot be delegated that way, create or select a dedicated git worktree with `git worktree add` and implement there instead of editing the parent checkout.
35
+ {{else}}
36
+ - An explicit user request to use a worktree (for example, "use worktree") overrides direct editing of the current checkout: create or select a dedicated git worktree with `git worktree add` and implement there. Task-level isolation is off in this session, so `task` does NOT accept `isolated`; NEVER refuse worktree work over that missing parameter. Mention the `task.isolation.mode` setting only if the user explicitly wants subagent-level isolation.
37
+ {{/if}}
34
38
  - Active skills are authoritative: never ignore an invoked skill; read the full skill text and follow it exactly.
35
39
  - Before explicit execution approval or a valid non-off ralplan final runtime receipt, planning and interview workflows NEVER edit product source, run mutating shell commands, commit, push, open PRs, or delegate implementation.
36
40
  </routing>
@@ -10,7 +10,7 @@ Drives a real Chromium tab with full puppeteer access via JS execution.
10
10
  - Tabs survive across `run` calls and across in-process subagents. Open once, reuse many times.
11
11
  - Browser kinds: no `app` launches headless Chromium; `app.path` reuses CDP or kills stale same-path processes before spawning — NEVER use it for a daily Chrome profile; use explicit `app.browser: "chrome"` profile mode instead. In profile mode, `path` defaults to installed Chrome/Chromium and `profile_directory` defaults to `"Default"`, but `user_data_dir` must name a separate non-default Chrome data directory: Chrome 136+ disables remote debugging for its default data directory. Only Chrome/Chromium executables are admitted; Edge, Brave, Vivaldi, Opera, unknown browser brands, and default Chrome data roots are rejected. Use `app.cdp_url` to attach to an already-authorized browser. Saved-profile/CDP automation has access to that profile's cookies and authenticated accounts. Profile mode refuses a matching non-CDP Chrome instead of killing/relaunching it, and `kill: true` can terminate only a Chrome process GJC launched; `app.cdp_url` is externally owned and disconnect-only. CDP must stay on `127.0.0.1`: it grants full browser-account access.
12
12
  - Inside `run`, `tab` exposes high-level helpers (`goto`, `observe`, `id`, `click`, `type`, `fill`, `press`, `waitFor`, `screenshot`, `extract`, …); reach for `page` (raw puppeteer Page) when they don't cover it.
13
- - Selectors accept CSS as well as puppeteer query handlers: `aria/Sign in`, `text/Continue`, `xpath/…`, `pierce/…`.
13
+ - Selectors must be non-empty strings: CSS or puppeteer query handlers (`aria/Sign in`, `text/Continue`, `xpath/…`, `pierce/…`). In `run`, click numeric observation ids with `(await tab.id(58)).click()`, not `tab.click(58)`. Omit optional selectors for unfocused `tab.press()` or page-level `tab.screenshot()`; null and blank selectors are invalid.
14
14
  - Runtime diagnostics are opt-in: pass `diagnostics: true` to `open` to subscribe the tab to page `Runtime.exceptionThrown` and `console.error` events. The next successful `act`/`run` response then includes at most 20 `runtimeDiagnostics` entries plus `runtimeDiagnosticsDropped`, then drains them. Entries contain only kind, time, origin-only URL, line/column, and a built-in error class from a fixed allowlist — never path segments, query strings, messages, console arguments, values, or stacks. Output is byte-bounded and marks truncation explicitly.
15
15
  - Full reference — helpers, browser kinds, CDP/security details, and more examples — read `gjc://tools/browser.md`.
16
16
  </instruction>
@@ -13,3 +13,7 @@ cwd from the new directory, and project-scoped plugins/capabilities reload for i
13
13
  speculatively — because the session file and caches move with the session.
14
14
  - This tool is unavailable in subagent sessions and restricted profiles; ask the top-level
15
15
  session to rescope instead.
16
+ - For an explicitly requested sibling or unrelated repository, start a new session with
17
+ `gjc --cwd <approved-worktree>` and delegate from there. A task's `repositoryBinding`
18
+ verifies the session's repository; it cannot authorize relocation. Already-created task
19
+ tools retain their original repository binding even after a user-driven cwd move.
@@ -9,7 +9,7 @@ Read files, directories, archives, SQLite databases, images, documents, internal
9
9
  ## Parameters
10
10
 
11
11
  - `path` — required. Local path, internal URI (`agent://`, `artifact://`, `rule://`, `local://`), or URL. Append `:<sel>` for line ranges, raw mode, or special modes (e.g. `src/foo.ts:50-200`, `src/foo.ts:raw`, `db.sqlite:users:42`).
12
- - `truncation` — optional `head` | `last` | `both`; selects which end of an over-budget result to retain. Configured default: {{TRUNCATION_DEFAULT}} (factory default: `last`); non-file routes such as URLs, directories and converted documents default to `head`. A line-range selector still bounds the selection — this only picks which end of that selection survives the byte/line cap. SQLite row queries page via their own `limit`/`offset` and ignore it.
12
+ - `truncation` — optional `head` | `last` | `both`; selects which end of an over-budget result to retain. Configured default: {{TRUNCATION_DEFAULT}} (factory default: `last`); structural summaries and routes such as URLs, directories and converted documents default to `head`. A line-range selector still bounds the selection — this only picks which end of that selection survives the byte/line cap. SQLite row queries page via their own `limit`/`offset` and ignore it.
13
13
  ## Selectors
14
14
  Append `:<sel>` to `path`. The bare path falls back to the default mode.
15
15
 
@@ -38,6 +38,7 @@ Append `:<sel>` to `path`. The bare path falls back to the default mode.
38
38
  `[NN lines across MM elided regions; read <path>:raw or a line range like <path>:1-9999 for verbatim content]`
39
39
 
40
40
  If the elided body is what you actually need, re-issue the **exact selector the footer names**. NEVER guess what's inside `..` / `…` — those markers carry no content.
41
+ - Structural summaries honor explicit `truncation`: `head` retains the beginning, `last` the end, and `both` both ends within the summary byte budget. Complete summary units and their original source anchors stay intact and in source order; budget omissions are marked where they occur. This does not switch to raw source. Summaries that fit are unchanged by direction.
41
42
  - Directional windows identify the retained first/last lines and the omitted range; use the `re-read <path>:1-<total>` or `:raw` hint in the footer to recover the full content.
42
43
 
43
44
  # Documents & Notebooks
@@ -1,15 +1,16 @@
1
- Discover project and user runtime skills without loading full skill content.
1
+ Discover bundled GJC workflow, project, and user runtime skills without loading full skill content.
2
2
 
3
3
  <instruction>
4
- - Searches canonical GJC skill locations in precedence order: project `.gjc/skills` (ancestors from cwd to repo root, closest first), then user locations under the home directory: canonical `<config>/agent/skills`, configured legacy `<config>/skills`, and historical legacy `.gjc/skills`. `<config>` is the home-relative directory name from `GJC_CONFIG_DIR`, then `PI_CONFIG_DIR`, then `.gjc`; even an absolute-looking configured name is joined beneath `<home>`. Project scope shadows user scope; within a scope, earlier locations above win. Bundled GJC workflow skills (`autoresearch`, `deep-interview`, `ralplan`, `ultragoal`) are always available and cannot be replaced by filesystem skills.
5
- - Returns thin metadata only: name, description, source scope, path, and use conditions when present.
4
+ - Includes the four bundled GJC workflow skills (`autoresearch`, `deep-interview`, `ralplan`, `ultragoal`) as `source: "bundled"` candidates from the generated bundled catalog; they are always available, cannot be replaced by filesystem copies, and are included for `source: "all"` but excluded by explicit `source: "project"`/`"user"` requests.
5
+ - Returns thin metadata only: name, description, source scope, path, and use conditions when present. Bundled paths are stable catalog identifiers, not filesystem paths.
6
+ - In trusted Git projects, `.gjc/skills` may be a symlink to a directory inside the same repository (for example `../.agents/skills`). Link and target identities remain checked through body loading; external targets and symlinked user/profile roots are refused. Do not replace a safe project link with copied files to make discovery work.
6
7
  - Claude Code (`.claude/skills`) and Codex (`.codex/skills`) layouts are explicit import sources into `.gjc`, never invokable candidates. They are not returned as candidates; instead, each convention skill found in a trusted scope is reported in `diagnostics` with the exact copy command that enables it (copy into `.gjc/skills`), so a skill placed in a documented convention location is discoverable in a normal session without being silently loaded.
7
- - Discovery is on by default in a normal session. When zero candidates are returned because discovery config is disabled (`skills.enabled` master switch, or `skills.trustProjectSkills` / `skills.trustUserSkills` scope trust), the result carries a `notice` explaining which setting blocked the search — an empty result without a `notice` means the searched scopes genuinely contain no matching skills.
8
+ - Discovery is on by default in a normal session. `query` matching is conjunctive substring: every whitespace-separated term must appear in a skill's name, description, source, or use conditions, unless a term equals the exact skill name — one keyword that appears nowhere in the candidate's metadata drops every candidate, so query with exact names or few terms known to appear literally, not topic keyword lists. When zero candidates are returned, the result carries a `notice` if discovery config disabled a requested scope, a non-empty query filtered out scanned skills, or diagnostics explain observed skills that were skipped or filtered. Only an empty result without a `notice` means no skills were scanned and no diagnostics were produced; never report a zero-candidate result as proof no skill exists.
8
9
  - When skills were scanned but not advertised (protected-name collision with a bundled workflow skill, include/ignore/disable policy filters, invalid frontmatter, shadowing), the result carries a bounded `diagnostics` list explaining why.
9
10
  - To load a selected skill's full `SKILL.md`, invoke it through the existing `skill` tool with the exact `name` returned here.
10
11
  </instruction>
11
12
 
12
13
  Input:
13
- - `query` (optional): words to match against skill name, description, source, or use conditions.
14
+ - `query` (optional): words to match against skill name, description, source, or use conditions. Every term must appear (conjunctive substring), or one term must equal the exact skill name.
14
15
  - `source` (optional): `all`, `project`, or `user`.
15
16
  - `limit` (optional): maximum results, 1-50.
@@ -29,6 +29,7 @@ Subagents have no conversation history. Every fact, file path, and direction the
29
29
  {{#if customSchemaEnabled}}- `schema`: JTD schema for expected structured output (do not put format rules in assignments){{/if}}
30
30
  - `spawnPlan` (optional): required before any batch with more than 4 tasks; include whyParallel, whyNotLocal, independence, expectedReceiptShape, and maxInlineTokens.
31
31
  {{#if isolationEnabled}}- `isolated`: run in an isolated environment; REQUIRED when the user explicitly requests a worktree (for example, "use worktree"), and use when tasks edit overlapping files{{/if}}
32
+ - `repositoryBinding`: optional authoritative repository/worktree identity. It must match the active session and cannot authorize a foreign repository from this session. For another approved repository, start a fresh session rooted there (for example, `gjc --cwd <approved-worktree>`); do not use `/move` because materialized tasks retain their original binding.
32
33
  </parameters>
33
34
 
34
35
  <rules>