@gajae-code/coding-agent 0.18.10 → 0.18.12

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 (270) hide show
  1. package/CHANGELOG.md +295 -0
  2. package/dist/types/async/job-manager.d.ts +7 -3
  3. package/dist/types/async/result-formatting.d.ts +2 -0
  4. package/dist/types/autoresearch/git.d.ts +1 -1
  5. package/dist/types/capability/fs.d.ts +2 -2
  6. package/dist/types/cli/accounts-cli.d.ts +2 -2
  7. package/dist/types/cli/doctor/install-repairs.d.ts +4 -1
  8. package/dist/types/cli/install-activation.d.ts +10 -4
  9. package/dist/types/cli/public-command-errors.d.ts +1 -0
  10. package/dist/types/cli/update-cli.d.ts +14 -1
  11. package/dist/types/cli-ordinary.d.ts +2 -2
  12. package/dist/types/commands/accounts.d.ts +2 -1
  13. package/dist/types/commands/migrate.d.ts +1 -1
  14. package/dist/types/commands/sdk.d.ts +5 -0
  15. package/dist/types/commit/changelog/index.d.ts +1 -0
  16. package/dist/types/config/autorouting-tier-map.d.ts +30 -0
  17. package/dist/types/config/config-hot-reload-trust.d.ts +12 -0
  18. package/dist/types/config/config-hot-reload.d.ts +39 -0
  19. package/dist/types/config/file-lock.d.ts +8 -1
  20. package/dist/types/config/model-discovery-manager.d.ts +2 -0
  21. package/dist/types/config/model-profile-activation.d.ts +62 -6
  22. package/dist/types/config/model-registry.d.ts +56 -5
  23. package/dist/types/config/model-resolver.d.ts +2 -0
  24. package/dist/types/config/models-config-schema.d.ts +10 -0
  25. package/dist/types/config/settings-schema.d.ts +46 -3
  26. package/dist/types/config/settings.d.ts +33 -1
  27. package/dist/types/dap/config.d.ts +8 -4
  28. package/dist/types/debug/system-info.d.ts +6 -1
  29. package/dist/types/discovery/mcp-compat.d.ts +3 -1
  30. package/dist/types/edit/modes/patch.d.ts +5 -0
  31. package/dist/types/edit/modes/replace.d.ts +3 -0
  32. package/dist/types/exec/bash-executor.d.ts +12 -0
  33. package/dist/types/gjc-runtime/managed-owner-admission.d.ts +3 -0
  34. package/dist/types/gjc-runtime/session-state-lock.d.ts +2 -0
  35. package/dist/types/gjc-runtime/state-runtime.d.ts +0 -2
  36. package/dist/types/migrate/adapters/codex.d.ts +2 -1
  37. package/dist/types/migrate/adapters/index.d.ts +10 -1
  38. package/dist/types/migrate/executor.d.ts +3 -1
  39. package/dist/types/migrate/types.d.ts +15 -3
  40. package/dist/types/modes/components/settings-selector.d.ts +6 -0
  41. package/dist/types/modes/controllers/selector-controller.d.ts +2 -0
  42. package/dist/types/modes/theme/theme.d.ts +1 -0
  43. package/dist/types/runtime-mcp/content-limits.d.ts +4 -0
  44. package/dist/types/runtime-mcp/manager.d.ts +7 -0
  45. package/dist/types/runtime-mcp/plugin-mcp-name-filter.d.ts +22 -0
  46. package/dist/types/runtime-mcp/tool-bridge.d.ts +4 -0
  47. package/dist/types/sdk/broker/broker-exit.d.ts +2 -2
  48. package/dist/types/sdk/broker/broker.d.ts +7 -1
  49. package/dist/types/sdk/broker/daemon-entry.d.ts +11 -1
  50. package/dist/types/sdk/broker/doctor-restart.d.ts +1 -1
  51. package/dist/types/sdk/broker/ensure.d.ts +136 -7
  52. package/dist/types/sdk/broker/hop.d.ts +36 -0
  53. package/dist/types/sdk/broker/lifecycle-ledger.d.ts +18 -10
  54. package/dist/types/sdk/broker/lock-host-identity.d.ts +5 -0
  55. package/dist/types/sdk/broker/session-index.d.ts +4 -1
  56. package/dist/types/sdk/bus/chat-command-policy.d.ts +2 -1
  57. package/dist/types/sdk/bus/index.d.ts +23 -0
  58. package/dist/types/sdk/bus/reconciliation-store.d.ts +10 -0
  59. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +3 -1
  60. package/dist/types/sdk/cli/session-cli.d.ts +0 -1
  61. package/dist/types/sdk/host/session-runtime.d.ts +32 -0
  62. package/dist/types/sdk/prompt-deadline-flush.d.ts +42 -4
  63. package/dist/types/sdk/prompt-deadline-manager.d.ts +2 -0
  64. package/dist/types/sdk/protocol/adapter-validation.d.ts +10 -4
  65. package/dist/types/sdk/reconciliation-extensions.d.ts +1 -1
  66. package/dist/types/sdk/session-list.d.ts +1 -1
  67. package/dist/types/session/agent-session.d.ts +58 -2
  68. package/dist/types/session/internal/managed-session-scope.d.ts +2 -2
  69. package/dist/types/session/internal/managed-session-storage.d.ts +1 -1
  70. package/dist/types/session/internal/native-publish-outcome.d.ts +1 -1
  71. package/dist/types/session/messages.d.ts +5 -1
  72. package/dist/types/session/session-manager.d.ts +13 -3
  73. package/dist/types/session/startup-auth-config.d.ts +24 -2
  74. package/dist/types/session/streaming-output.d.ts +11 -0
  75. package/dist/types/session/terminal-abort.d.ts +3 -1
  76. package/dist/types/session-import/service.d.ts +1 -1
  77. package/dist/types/skill-state/workflow-mutation-guard.d.ts +7 -3
  78. package/dist/types/slash-commands/helpers/provider-auth-status.d.ts +8 -0
  79. package/dist/types/task/executor.d.ts +19 -2
  80. package/dist/types/tools/ast-edit-write-path.d.ts +10 -0
  81. package/dist/types/tools/atomic-file-write.d.ts +9 -7
  82. package/dist/types/tools/bash-allowed-prefixes.d.ts +11 -0
  83. package/dist/types/tools/descriptors.d.ts +2 -0
  84. package/dist/types/tools/fetch.d.ts +1 -1
  85. package/dist/types/tools/index.d.ts +2 -0
  86. package/dist/types/tools/python.d.ts +1 -1
  87. package/dist/types/tools/report-issue.d.ts +41 -0
  88. package/dist/types/tools/subagent.d.ts +23 -0
  89. package/dist/types/web/scrapers/types.d.ts +8 -1
  90. package/dist/types/web/search/providers/insane.d.ts +7 -1
  91. package/dist/types/web/search/providers/searxng.d.ts +5 -0
  92. package/package.json +8 -8
  93. package/scripts/build-binary.ts +2 -1
  94. package/scripts/capture-subagent-compact-panel-showcase.ts +105 -0
  95. package/scripts/generate-docs-index.ts +8 -1
  96. package/scripts/generate-sdk-operation-inventory.ts +22 -4
  97. package/src/async/job-manager.ts +356 -56
  98. package/src/async/result-formatting.ts +40 -0
  99. package/src/autoresearch/git.ts +9 -2
  100. package/src/autoresearch/prompts/prompt-setup.md +1 -1
  101. package/src/capability/fs.ts +27 -19
  102. package/src/capability/index.ts +2 -2
  103. package/src/cli/accounts-cli.ts +176 -8
  104. package/src/cli/auth-broker-cli.ts +21 -11
  105. package/src/cli/doctor/install-repairs.ts +35 -5
  106. package/src/cli/fast-help.ts +1 -1
  107. package/src/cli/install-activation.ts +47 -4
  108. package/src/cli/migrate-cli.ts +7 -5
  109. package/src/cli/public-command-errors.ts +4 -0
  110. package/src/cli/root-flags.ts +2 -2
  111. package/src/cli/stats-cli.ts +9 -5
  112. package/src/cli/update-cli.ts +224 -7
  113. package/src/cli-ordinary.ts +7 -2
  114. package/src/commands/accounts.ts +10 -5
  115. package/src/commands/migrate.ts +3 -3
  116. package/src/commands/sdk.ts +199 -42
  117. package/src/commands/ultragoal.ts +16 -8
  118. package/src/commit/changelog/index.ts +39 -1
  119. package/src/commit/message.ts +10 -3
  120. package/src/config/autorouting-tier-map.ts +30 -0
  121. package/src/config/config-hot-reload-trust.ts +148 -0
  122. package/src/config/config-hot-reload.ts +734 -0
  123. package/src/config/file-lock.ts +216 -56
  124. package/src/config/model-bindings-applier.ts +85 -47
  125. package/src/config/model-discovery-manager.ts +10 -0
  126. package/src/config/model-profile-activation.ts +716 -113
  127. package/src/config/model-registry.ts +1334 -158
  128. package/src/config/model-resolver.ts +3 -1
  129. package/src/config/models-config-schema.ts +6 -0
  130. package/src/config/settings-schema.ts +60 -3
  131. package/src/config/settings.ts +458 -24
  132. package/src/coordinator-mcp/policy.ts +26 -1
  133. package/src/crash/sanitize.ts +4 -0
  134. package/src/customization/import.ts +3 -1
  135. package/src/dap/config.ts +31 -11
  136. package/src/dap/defaults.json +1 -1
  137. package/src/debug/crash-diagnostics.ts +2 -1
  138. package/src/debug/report-bundle.ts +19 -0
  139. package/src/debug/system-info.ts +8 -3
  140. package/src/defaults/gjc/extensions/grok-cli-vendor/src/shared/base-url.ts +21 -7
  141. package/src/discovery/agents-md.ts +1 -1
  142. package/src/discovery/helpers.ts +1 -2
  143. package/src/discovery/mcp-compat.ts +120 -17
  144. package/src/edit/apply-patch/index.ts +12 -1
  145. package/src/edit/index.ts +13 -17
  146. package/src/edit/modes/patch.ts +187 -8
  147. package/src/edit/modes/replace.ts +136 -0
  148. package/src/eval/js/context-manager.ts +29 -3
  149. package/src/eval/js/worker-entry.ts +51 -18
  150. package/src/eval/py/executor.ts +14 -4
  151. package/src/eval/py/runner.py +144 -5
  152. package/src/exec/bash-executor.ts +81 -4
  153. package/src/exec/bash-shell-guardian.ts +4 -1
  154. package/src/exec/bash-shell-supervisor.ts +8 -4
  155. package/src/exec/isolated-shell.ts +5 -1
  156. package/src/export/html/index.ts +46 -6
  157. package/src/extensibility/custom-tools/wrapper.ts +3 -1
  158. package/src/extensibility/extensions/loader.ts +8 -1
  159. package/src/extensibility/plugins/marketplace/fetcher.ts +2 -2
  160. package/src/gjc-runtime/gc-runtime.ts +33 -6
  161. package/src/gjc-runtime/launch-tmux.ts +7 -2
  162. package/src/gjc-runtime/launch-worktree.test.ts +148 -0
  163. package/src/gjc-runtime/launch-worktree.ts +101 -14
  164. package/src/gjc-runtime/managed-owner-admission.ts +46 -2
  165. package/src/gjc-runtime/session-resolution.ts +38 -6
  166. package/src/gjc-runtime/session-state-lock.ts +59 -14
  167. package/src/gjc-runtime/state-runtime.ts +23 -19
  168. package/src/hooks/native-skill-hook.ts +14 -11
  169. package/src/internal-urls/docs-index.generated.ts +14 -13
  170. package/src/internal-urls/local-protocol.ts +142 -8
  171. package/src/lsp/index.ts +29 -0
  172. package/src/lsp/workspace-path.ts +23 -0
  173. package/src/migrate/action-planner.ts +57 -0
  174. package/src/migrate/adapters/claude-code.ts +23 -4
  175. package/src/migrate/adapters/codex.ts +22 -4
  176. package/src/migrate/adapters/index.ts +22 -4
  177. package/src/migrate/adapters/opencode.ts +6 -1
  178. package/src/migrate/executor.ts +84 -7
  179. package/src/migrate/report.ts +19 -2
  180. package/src/migrate/types.ts +14 -4
  181. package/src/modes/DESIGN.md +51 -0
  182. package/src/modes/acp/permission-mode.ts +18 -1
  183. package/src/modes/components/assistant-message.ts +55 -1
  184. package/src/modes/components/settings-selector.ts +103 -37
  185. package/src/modes/controllers/command-controller.ts +38 -2
  186. package/src/modes/controllers/plan-mode-controller.ts +17 -7
  187. package/src/modes/controllers/selector-controller.ts +62 -6
  188. package/src/modes/interactive-mode.ts +68 -0
  189. package/src/modes/theme/theme.ts +15 -0
  190. package/src/prompts/tools/debug.md +1 -1
  191. package/src/prompts/tools/read.md +1 -1
  192. package/src/prompts/tools/report-issue.md +13 -0
  193. package/src/prompts/tools/task.md +1 -1
  194. package/src/runtime-credential-selector.ts +2 -2
  195. package/src/runtime-mcp/content-limits.ts +7 -0
  196. package/src/runtime-mcp/manager-pool.test.ts +5 -4
  197. package/src/runtime-mcp/manager.ts +32 -0
  198. package/src/runtime-mcp/oauth-flow.ts +32 -6
  199. package/src/runtime-mcp/plugin-mcp-name-filter.ts +62 -0
  200. package/src/runtime-mcp/render.ts +16 -1
  201. package/src/runtime-mcp/tool-bridge.ts +126 -17
  202. package/src/sdk/broker/broker-exit.ts +8 -5
  203. package/src/sdk/broker/broker.ts +342 -82
  204. package/src/sdk/broker/daemon-entry.ts +338 -116
  205. package/src/sdk/broker/doctor-restart.ts +2 -1
  206. package/src/sdk/broker/ensure.ts +1143 -265
  207. package/src/sdk/broker/hop.ts +274 -0
  208. package/src/sdk/broker/lifecycle-ledger.ts +35 -11
  209. package/src/sdk/broker/lock-host-identity.ts +29 -0
  210. package/src/sdk/broker/session-index.ts +62 -12
  211. package/src/sdk/bus/chat-command-policy.ts +16 -3
  212. package/src/sdk/bus/index.ts +52 -21
  213. package/src/sdk/bus/reconciliation-store.ts +201 -8
  214. package/src/sdk/bus/telegram-daemon-contract.ts +3 -1
  215. package/src/sdk/cli/session-cli.ts +21 -6
  216. package/src/sdk/host/session-runtime.test.ts +118 -23
  217. package/src/sdk/host/session-runtime.ts +352 -47
  218. package/src/sdk/lifecycle/service.ts +1 -0
  219. package/src/sdk/prompt-deadline-flush.ts +78 -5
  220. package/src/sdk/prompt-deadline-manager.ts +68 -14
  221. package/src/sdk/protocol/adapter-validation.ts +53 -11
  222. package/src/sdk/protocol/operation-inventory.generated.json +101 -2
  223. package/src/sdk/reconciliation-extensions.ts +1 -0
  224. package/src/sdk/session-list.ts +1 -0
  225. package/src/sdk/session.ts +114 -61
  226. package/src/session/agent-session.ts +1043 -81
  227. package/src/session/internal/managed-session-scope.ts +126 -39
  228. package/src/session/internal/managed-session-storage.ts +14 -11
  229. package/src/session/internal/native-publish-outcome.ts +5 -1
  230. package/src/session/messages.ts +47 -6
  231. package/src/session/session-manager.ts +236 -14
  232. package/src/session/startup-auth-config.ts +116 -8
  233. package/src/session/streaming-output.ts +262 -4
  234. package/src/session/terminal-abort.ts +14 -2
  235. package/src/session-import/service.ts +1 -0
  236. package/src/skill-state/workflow-mutation-guard.ts +491 -32
  237. package/src/slash-commands/builtin-registry.ts +15 -3
  238. package/src/slash-commands/helpers/credential-switch.ts +10 -5
  239. package/src/slash-commands/helpers/provider-auth-status.ts +456 -0
  240. package/src/task/executor.ts +103 -12
  241. package/src/task/index.ts +389 -175
  242. package/src/tools/ast-edit-write-path.ts +64 -0
  243. package/src/tools/ast-edit.ts +18 -1
  244. package/src/tools/atomic-file-write.ts +46 -15
  245. package/src/tools/auto-generated-guard.ts +3 -0
  246. package/src/tools/bash-allowed-prefixes.ts +153 -5
  247. package/src/tools/bash-interactive.ts +14 -2
  248. package/src/tools/bash.ts +14 -0
  249. package/src/tools/debug.ts +7 -6
  250. package/src/tools/descriptors.test.ts +44 -0
  251. package/src/tools/descriptors.ts +34 -2
  252. package/src/tools/fetch.ts +3 -2
  253. package/src/tools/index.ts +2 -0
  254. package/src/tools/output-meta.ts +23 -2
  255. package/src/tools/python.ts +1 -1
  256. package/src/tools/read.ts +17 -35
  257. package/src/tools/report-issue.ts +184 -0
  258. package/src/tools/subagent-render.ts +114 -12
  259. package/src/tools/subagent.ts +108 -1
  260. package/src/tools/todo-write.ts +41 -3
  261. package/src/tools/tool-catalog.generated.ts +31 -3
  262. package/src/tools/write.ts +35 -3
  263. package/src/utils/commit-message-generator.ts +9 -2
  264. package/src/utils/file-mentions.ts +29 -1
  265. package/src/utils/title-generator.ts +7 -2
  266. package/src/web/scrapers/index.ts +3 -1
  267. package/src/web/scrapers/types.ts +8 -0
  268. package/src/web/scrapers/youtube.ts +3 -2
  269. package/src/web/search/providers/insane.ts +91 -28
  270. package/src/web/search/providers/searxng.ts +62 -10
@@ -12,12 +12,14 @@ import {
12
12
  } from "@gajae-code/natives";
13
13
  import { getAgentDir, logger, postmortem } from "@gajae-code/utils";
14
14
  import { CliParseError, Command } from "@gajae-code/utils/cli";
15
+ import { projectEnvSnapshot } from "@gajae-code/utils/env-file";
15
16
  import type { Args as ParsedArgs } from "../cli/args";
16
17
  import { isSafeSdkInternalAgentDir, scanPublicCommand } from "../cli/public-command-entry";
17
18
  import { PublicCommandFailure } from "../cli/public-command-errors";
18
19
  import { FileLockAcquireError } from "../config/file-lock";
19
20
  import { parseModelString } from "../config/model-resolver";
20
21
  import { Settings } from "../config/settings";
22
+ import { trustedCoordinatorEnv } from "../gjc-runtime/sidecar-bootstrap-env";
21
23
  import { usePostmortemSignalExitAuthority } from "../lsp/client";
22
24
  import { applyStartupModelProfiles, createSessionManager } from "../main";
23
25
  import { initializeExtensions } from "../modes/runtime-init";
@@ -29,15 +31,21 @@ import {
29
31
  type BrokerStartupExitWriteStatus,
30
32
  writeBrokerStartupExitRecordBounded,
31
33
  } from "../sdk/broker/broker-exit";
32
- import { readBrokerDiscovery } from "../sdk/broker/discovery";
34
+ import {
35
+ type BrokerRestartIntentWithIdentity,
36
+ readBrokerDiscovery,
37
+ readBrokerRestartIntent,
38
+ } from "../sdk/broker/discovery";
33
39
  import { type EndpointFileRead, readEndpointFile } from "../sdk/broker/endpoint-authority";
34
40
  import {
35
41
  BROKER_DISCOVERY_BUDGET,
36
42
  emitBrokerStartupTestSignal,
43
+ reapBrokerTrampolineChild,
37
44
  reconcileBrokerGenerationForStartup,
38
45
  SDK_BROKER_AUTOSTART_ENV,
39
46
  withBrokerStartupLock,
40
47
  } from "../sdk/broker/ensure";
48
+ import { waitForBrokerHandoffAcknowledgement, waitForBrokerHandoffDecision } from "../sdk/broker/hop";
41
49
  import {
42
50
  LifecycleFailurePublicationCleanupError,
43
51
  LifecycleReadinessCleanupError,
@@ -88,11 +96,17 @@ export async function lifecycleArgs(
88
96
  if (targetScope.kind !== "resolved") throw new Error(`Lifecycle session scope is invalid: ${targetScope.message}`);
89
97
  const forkSessionDir =
90
98
  request.operation === "session.fork" ? SessionManager.getDefaultSessionDir(cwd, agentDir) : undefined;
99
+ // Bun has already copied the project dotenv into process.env. A matching or
100
+ // dynamic declaration must not select an in-memory session. The exact "1"
101
+ // check stays; an operator value the project does not declare is still honored.
102
+ const inMemorySession =
103
+ process.env.GJC_SDK_TEST_IN_MEMORY_SESSION === "1" &&
104
+ trustedCoordinatorEnv("GJC_SDK_TEST_IN_MEMORY_SESSION", process.env, projectEnvSnapshot(cwd)) === "1";
91
105
  return {
92
106
  messages: [],
93
107
  fileArgs: [],
94
108
  unknownFlags: new Map(),
95
- ...(process.env.GJC_SDK_TEST_IN_MEMORY_SESSION === "1" ? { noSession: true } : {}),
109
+ ...(inMemorySession ? { noSession: true } : {}),
96
110
  ...(request.operation === "session.resume" ? { resume: request.sessionPath } : {}),
97
111
  ...(request.modelPreset ? { mpreset: request.modelPreset } : {}),
98
112
  // Explicit model pin (#4707): coordinator-resolved `provider/model`
@@ -1713,6 +1727,34 @@ export default class Sdk extends Command {
1713
1727
  }
1714
1728
  }
1715
1729
 
1730
+ /** Captures and removes one-shot restart credentials before the broker forks descendants. */
1731
+ export function consumeBrokerRestartEnvironment(environment: NodeJS.ProcessEnv): {
1732
+ requestIdEnv: string | undefined;
1733
+ restartDeadlineAt: number | undefined;
1734
+ } {
1735
+ const restartRequestEnv = environment.GJC_BROKER_RESTART_REQUEST;
1736
+ const restartDeadlineEnv = environment.GJC_BROKER_RESTART_DEADLINE;
1737
+ delete environment.GJC_BROKER_RESTART_REQUEST;
1738
+ delete environment.GJC_BROKER_RESTART_DEADLINE;
1739
+ const requestIdEnv =
1740
+ typeof restartRequestEnv === "string" && /^[A-Za-z0-9_-]{1,256}$/.test(restartRequestEnv)
1741
+ ? restartRequestEnv
1742
+ : undefined;
1743
+ let restartDeadlineAt: number | undefined;
1744
+ if (restartDeadlineEnv !== undefined) {
1745
+ const parsedDeadlineAt = Number(restartDeadlineEnv);
1746
+ if (
1747
+ requestIdEnv === undefined ||
1748
+ !/^[0-9]{1,16}$/.test(restartDeadlineEnv) ||
1749
+ !Number.isSafeInteger(parsedDeadlineAt) ||
1750
+ parsedDeadlineAt <= Date.now()
1751
+ )
1752
+ throw new Error("Invalid SDK broker restart deadline; refusing successor startup.");
1753
+ restartDeadlineAt = parsedDeadlineAt;
1754
+ }
1755
+ return { requestIdEnv, restartDeadlineAt };
1756
+ }
1757
+
1716
1758
  /**
1717
1759
  * Runs one parsed SDK internal entry point. `publicBrokerRun` is set only by
1718
1760
  * the stable `gjc sdk broker run` contract, which must report a lost ownership
@@ -1722,13 +1764,16 @@ export default class Sdk extends Command {
1722
1764
  async function runSdkInternal(internal: SdkInternalArgv, publicBrokerRun = false): Promise<void> {
1723
1765
  if (internal.action === "broker-trampoline-internal") {
1724
1766
  if (process.platform === "win32") throw new CliParseError("Broker trampoline is unavailable on Windows.");
1767
+ const retainChildUntilPublication = process.env.GJC_BROKER_TRAMPOLINE_RETAIN_UNTIL_PUBLICATION === "1";
1725
1768
  const command = resolveSdkInternalSpawnCommand("broker-internal");
1769
+ const brokerEnvironment = { ...command.env };
1770
+ delete brokerEnvironment.GJC_BROKER_TRAMPOLINE_RETAIN_UNTIL_PUBLICATION;
1726
1771
  let child: ChildProcess;
1727
1772
  try {
1728
1773
  child = spawn(command.file, [...command.args, "--agent-dir", internal.agentDir], {
1729
1774
  detached: true,
1730
1775
  stdio: ["ignore", "ignore", "inherit"],
1731
- env: command.env,
1776
+ env: brokerEnvironment,
1732
1777
  ...(command.kind === "bun-source" ? { cwd: command.cwd } : {}),
1733
1778
  });
1734
1779
  } catch (error) {
@@ -1741,11 +1786,7 @@ async function runSdkInternal(internal: SdkInternalArgv, publicBrokerRun = false
1741
1786
  if (child.pid === undefined) throw new Error("Broker trampoline could not start broker.");
1742
1787
  const incarnation = processIncarnation(child.pid);
1743
1788
  if (!incarnation) {
1744
- try {
1745
- child.kill("SIGKILL");
1746
- } catch {
1747
- // The child may already have exited; either way identity was not established.
1748
- }
1789
+ await reapBrokerTrampolineChild(child, child.pid);
1749
1790
  throw new Error("Broker trampoline could not observe broker identity.");
1750
1791
  }
1751
1792
  if (spawnError) throw new Error("Broker trampoline could not start broker.", { cause: spawnError });
@@ -1757,13 +1798,19 @@ async function runSdkInternal(internal: SdkInternalArgv, publicBrokerRun = false
1757
1798
  try {
1758
1799
  await stdoutWrite.promise;
1759
1800
  } catch (error) {
1760
- try {
1761
- child.kill("SIGKILL");
1762
- } catch {
1763
- // The child may already have exited; reporting failure remains authoritative.
1764
- }
1801
+ await reapBrokerTrampolineChild(child, child.pid, incarnation);
1765
1802
  throw error;
1766
1803
  }
1804
+ if (retainChildUntilPublication) {
1805
+ const decision = await waitForBrokerHandoffDecision(process.stdin);
1806
+ if (decision === "abort") {
1807
+ await reapBrokerTrampolineChild(child, child.pid, incarnation);
1808
+ return;
1809
+ }
1810
+ } else if (!(await waitForBrokerHandoffAcknowledgement(process.stdin))) {
1811
+ await reapBrokerTrampolineChild(child, child.pid, incarnation);
1812
+ throw new Error("Broker trampoline handoff was not acknowledged; its direct child was reaped.");
1813
+ }
1767
1814
  child.unref();
1768
1815
  return;
1769
1816
  }
@@ -1846,7 +1893,13 @@ async function runSdkInternal(internal: SdkInternalArgv, publicBrokerRun = false
1846
1893
  if (startupExitLogged) return;
1847
1894
  startupExitLogged = true;
1848
1895
  const level = record.exitCode === 1 ? "error" : "warn";
1849
- if (record.exitCode === 1) logger.error("sdk broker: startup watchdog forcing exit", record);
1896
+ if (record.exitCode === 1)
1897
+ logger.error(
1898
+ record.reason === "startup-deadline"
1899
+ ? "sdk broker: startup watchdog forcing exit"
1900
+ : "sdk broker: startup refused",
1901
+ record,
1902
+ );
1850
1903
  else logger.warn("sdk broker: startup interrupted", record);
1851
1904
  process.stderr.write(`${JSON.stringify({ level, message, ...record })}\n`);
1852
1905
  };
@@ -1866,9 +1919,11 @@ async function runSdkInternal(internal: SdkInternalArgv, publicBrokerRun = false
1866
1919
  const message =
1867
1920
  reason === "startup-lock-blocked" && blockingLockPath
1868
1921
  ? `SDK broker startup blocked by retained removal transition ${blockingLockPath}.`
1869
- : reason === "startup-deadline"
1870
- ? `SDK broker startup exceeded its ${timeoutMs}ms fence deadline.`
1871
- : `SDK broker startup interrupted by ${signal} before readiness.`;
1922
+ : reason === "startup-lock-unavailable"
1923
+ ? `SDK broker startup could not acquire ${blockingLockPath ?? "a required lock"}.`
1924
+ : reason === "startup-deadline"
1925
+ ? `SDK broker startup exceeded its ${timeoutMs}ms fence deadline.`
1926
+ : `SDK broker startup interrupted by ${signal} before readiness.`;
1872
1927
  writeStartupExitLog(exitRecord, message);
1873
1928
  startupExitTask = (async () => {
1874
1929
  const exitRecordWrite = await beginStartupExitRecordWrite(exitRecord);
@@ -1922,33 +1977,125 @@ async function runSdkInternal(internal: SdkInternalArgv, publicBrokerRun = false
1922
1977
  await exitDuringStartup("startup-signal", startupSignalExitCode(signal), signal);
1923
1978
  return true;
1924
1979
  };
1980
+ let startupFenceAcquired = false;
1925
1981
  try {
1982
+ const { requestIdEnv, restartDeadlineAt } = consumeBrokerRestartEnvironment(process.env);
1983
+ const MAX_SESSION_INDEX_TIMEOUT_RETRIES = 2;
1984
+ let sessionIndexTimeoutRetries = 0;
1985
+ let activeStartupDeadlineAt = 0;
1926
1986
  const startupOperation = async (deadline: number): Promise<Broker | undefined> => {
1987
+ for (;;) {
1988
+ activeStartupDeadlineAt = deadline;
1989
+ try {
1990
+ return await singleStartupAttempt(deadline);
1991
+ } catch (error) {
1992
+ if (
1993
+ !(error instanceof FileLockAcquireError) ||
1994
+ !startupFenceAcquired ||
1995
+ error.code !== "acquire_timeout" ||
1996
+ path.resolve(error.filePath) !==
1997
+ path.resolve(path.join(agentDir, "sdk", "sessions", "index.jsonl")) ||
1998
+ sessionIndexTimeoutRetries >= MAX_SESSION_INDEX_TIMEOUT_RETRIES
1999
+ )
2000
+ throw error;
2001
+ sessionIndexTimeoutRetries++;
2002
+ const backoffMs = 100 * 2 ** (sessionIndexTimeoutRetries - 1);
2003
+ if (Date.now() + backoffMs >= activeStartupDeadlineAt) throw error;
2004
+ const failedBroker = broker;
2005
+ if (failedBroker) {
2006
+ try {
2007
+ await failedBroker.stop({ kind: "startup-failure" });
2008
+ } catch (cleanupError) {
2009
+ throw new AggregateError(
2010
+ [error, cleanupError],
2011
+ "Session-index startup retry could not clean up the failed broker candidate.",
2012
+ );
2013
+ }
2014
+ if (broker === failedBroker) broker = undefined;
2015
+ if (runningBroker === failedBroker) runningBroker = undefined;
2016
+ }
2017
+ candidateStartTask = undefined;
2018
+ logger.debug("sdk broker: session-index lock timeout, retrying startup", {
2019
+ reason: "session-index-timeout-retry",
2020
+ attempt: sessionIndexTimeoutRetries,
2021
+ backoffMs,
2022
+ });
2023
+ await Bun.sleep(backoffMs);
2024
+ }
2025
+ }
2026
+ };
2027
+ const singleStartupAttempt = async (deadline: number): Promise<Broker | undefined> => {
1927
2028
  const remainingMs = Math.max(1, deadline - Date.now());
1928
2029
  const testWatchdogMs = Number(process.env.GJC_SDK_TEST_BROKER_STARTUP_WATCHDOG_MS ?? 0);
1929
- const watchdogMs =
2030
+ const ordinaryWatchdogMs =
1930
2031
  Number.isSafeInteger(testWatchdogMs) && testWatchdogMs > 0 && testWatchdogMs <= remainingMs
1931
2032
  ? testWatchdogMs
1932
2033
  : remainingMs;
1933
- const startupCheckpointDeadline = performance.now() + watchdogMs - 1_000;
1934
- const startupWatchdog = setTimeout(() => {
1935
- startupAbortController.abort();
1936
- void exitDuringStartup("startup-deadline", 1, null, watchdogMs).then(async started => {
1937
- if (!started) {
1938
- // A prior startup signal owns the exit cause; its postmortem callback
1939
- // returns after bounded cleanup and preserves the signal status.
1940
- return;
1941
- }
1942
- await waitForStartupAbortCleanup();
1943
- process.exit(1);
1944
- });
1945
- }, watchdogMs);
2034
+ let restartRequestId: string | undefined;
2035
+ let startupDeadlineAt = deadline;
2036
+ let effectiveWatchdogMs = ordinaryWatchdogMs;
2037
+ let startupCheckpointDeadline = performance.now() + Math.max(1, effectiveWatchdogMs - 1_000);
2038
+ const armStartupWatchdog = (): NodeJS.Timeout =>
2039
+ setTimeout(() => {
2040
+ startupAbortController.abort();
2041
+ void exitDuringStartup("startup-deadline", 1, null, effectiveWatchdogMs).then(async started => {
2042
+ if (!started) {
2043
+ // A prior startup signal owns the exit cause; its postmortem callback
2044
+ // returns after bounded cleanup and preserves the signal status.
2045
+ return;
2046
+ }
2047
+ await waitForStartupAbortCleanup();
2048
+ process.exit(1);
2049
+ });
2050
+ }, effectiveWatchdogMs);
2051
+ let startupWatchdog = armStartupWatchdog();
1946
2052
  try {
2053
+ let restartIntent: BrokerRestartIntentWithIdentity | null;
2054
+ try {
2055
+ restartIntent = await readBrokerRestartIntent(agentDir);
2056
+ } catch (error) {
2057
+ throw new Error("Could not validate SDK broker restart intent; refusing untagged startup.", {
2058
+ cause: error,
2059
+ });
2060
+ }
2061
+ // A committed request survives the prior owner's exit. Ordinary or
2062
+ // mismatched starts must not publish ahead of its exact successor.
2063
+ if (
2064
+ restartIntent?.phase === "committed" &&
2065
+ restartIntent.expiresAt > Date.now() &&
2066
+ restartIntent.requestId !== requestIdEnv
2067
+ )
2068
+ throw new Error("A committed SDK broker restart is active; startup requires its exact request ID.");
2069
+ if (
2070
+ restartDeadlineAt !== undefined &&
2071
+ (restartIntent?.phase !== "committed" ||
2072
+ restartIntent.requestId !== requestIdEnv ||
2073
+ restartIntent.expiresAt !== restartDeadlineAt)
2074
+ )
2075
+ throw new Error("Could not validate SDK broker restart deadline; refusing successor startup.");
2076
+ if (requestIdEnv !== undefined && restartIntent?.requestId === requestIdEnv) {
2077
+ if (restartIntent.phase !== "committed")
2078
+ throw new Error("SDK broker restart intent is not committed; refusing successor startup.");
2079
+ const remainingSuccessorMs = restartIntent.expiresAt - Date.now();
2080
+ if (remainingSuccessorMs <= 0)
2081
+ throw new Error("SDK broker restart intent expired; refusing untagged startup.");
2082
+ restartRequestId = requestIdEnv;
2083
+ startupDeadlineAt = restartDeadlineAt ?? restartIntent.expiresAt;
2084
+ activeStartupDeadlineAt = startupDeadlineAt;
2085
+ effectiveWatchdogMs =
2086
+ Number.isSafeInteger(testWatchdogMs) && testWatchdogMs > 0 && testWatchdogMs <= remainingSuccessorMs
2087
+ ? testWatchdogMs
2088
+ : remainingSuccessorMs;
2089
+ clearTimeout(startupWatchdog);
2090
+ startupCheckpointDeadline = performance.now() + Math.max(1, effectiveWatchdogMs - 1_000);
2091
+ startupWatchdog = armStartupWatchdog();
2092
+ }
2093
+ if (startupAbortController.signal.aborted) return undefined;
1947
2094
  // `gjc sdk broker run` never retires another owner, even one this generation cannot
1948
2095
  // reuse: any live incumbent is a refusal. Autostart repairs unusable generations.
1949
2096
  const existing = publicBrokerRun
1950
2097
  ? ((await readBrokerDiscovery(agentDir)) ?? undefined)
1951
- : await reconcileBrokerGenerationForStartup({ agentDir }, deadline);
2098
+ : await reconcileBrokerGenerationForStartup({ agentDir }, startupDeadlineAt);
1952
2099
  if (startupAbortController.signal.aborted) return undefined;
1953
2100
  if (existing) {
1954
2101
  logger.info("sdk broker: startup reused an existing owner", {
@@ -1985,11 +2132,9 @@ async function runSdkInternal(internal: SdkInternalArgv, publicBrokerRun = false
1985
2132
  // launcher-supplied environment variable; it is validated here and handed
1986
2133
  // to Broker as a typed setting, never read a second time inside broker.ts
1987
2134
  // from process.env directly.
1988
- const restartRequestEnv = process.env.GJC_BROKER_RESTART_REQUEST;
1989
- const restartRequestId =
1990
- typeof restartRequestEnv === "string" && /^[A-Za-z0-9_-]{1,256}$/.test(restartRequestEnv)
1991
- ? restartRequestEnv
1992
- : undefined;
2135
+ // Restart authorization is revalidated before constructing the broker; the
2136
+ // watchdog was already armed before any intent-file I/O.
2137
+ const effectiveCheckpointDeadline = startupCheckpointDeadline;
1993
2138
  const testPostPublicationDelayMs = Number(process.env.GJC_SDK_TEST_BROKER_POST_PUBLICATION_DELAY_MS ?? 0);
1994
2139
  const startupPostPublicationDelayMs =
1995
2140
  Number.isSafeInteger(testPostPublicationDelayMs) &&
@@ -2030,7 +2175,7 @@ async function runSdkInternal(internal: SdkInternalArgv, publicBrokerRun = false
2030
2175
  const candidate = new Broker({
2031
2176
  agentDir,
2032
2177
  startupAbortSignal: startupAbortController.signal,
2033
- startupCheckpointDeadline,
2178
+ startupCheckpointDeadline: effectiveCheckpointDeadline,
2034
2179
  onStartupReady: () => clearTimeout(startupWatchdog),
2035
2180
  masterOrphanGraceMs: (await Settings.loadForScope({ cwd: process.cwd(), agentDir })).get(
2036
2181
  "sdk.masterOrphanGraceMs",
@@ -2066,7 +2211,11 @@ async function runSdkInternal(internal: SdkInternalArgv, publicBrokerRun = false
2066
2211
  }
2067
2212
  };
2068
2213
  broker = await withBrokerStartupLock(agentDir, startupOperation, {
2069
- onAcquired: () => void emitBrokerStartupTestSignal("fence-acquired"),
2214
+ ...(restartDeadlineAt === undefined ? {} : { deadlineAt: restartDeadlineAt }),
2215
+ onAcquired: () => {
2216
+ startupFenceAcquired = true;
2217
+ void emitBrokerStartupTestSignal("fence-acquired");
2218
+ },
2070
2219
  onContended: () => void emitBrokerStartupTestSignal("fence-contended"),
2071
2220
  });
2072
2221
  } catch (error) {
@@ -2074,9 +2223,14 @@ async function runSdkInternal(internal: SdkInternalArgv, publicBrokerRun = false
2074
2223
  await finishPendingStartupSignal();
2075
2224
  return;
2076
2225
  }
2077
- // A retained removal transition is an explicit acquire failure, not only
2078
- // an exhausted ordinary contention timeout.
2079
- if (error instanceof FileLockAcquireError && error.orphanPath) {
2226
+ // Only a retained transition on the outer startup fence gets its own
2227
+ // blocked reason. Nested resource-lock failures are retryable unavailability.
2228
+ if (
2229
+ error instanceof FileLockAcquireError &&
2230
+ !startupFenceAcquired &&
2231
+ error.code === "orphan_transition" &&
2232
+ error.orphanPath
2233
+ ) {
2080
2234
  await exitDuringStartup(
2081
2235
  "startup-lock-blocked",
2082
2236
  1,
@@ -2084,6 +2238,9 @@ async function runSdkInternal(internal: SdkInternalArgv, publicBrokerRun = false
2084
2238
  BROKER_DISCOVERY_BUDGET.startupLockWaitMs,
2085
2239
  error.orphanPath,
2086
2240
  );
2241
+ } else if (error instanceof FileLockAcquireError) {
2242
+ // Nested lock failures or non-orphan-transition errors
2243
+ await exitDuringStartup("startup-lock-unavailable", 1, null, undefined, error.orphanPath ?? error.lockPath);
2087
2244
  }
2088
2245
  if (broker) {
2089
2246
  try {
@@ -8,6 +8,7 @@ import {
8
8
  writeCurrentSessionGoalModeState,
9
9
  writePendingGoalModeRequest,
10
10
  } from "../gjc-runtime/goal-mode-request";
11
+ import { trustedCoordinatorEnv } from "../gjc-runtime/sidecar-bootstrap-env";
11
12
  import { isUltragoalHelpInvocation, runNativeUltragoalCommand } from "../gjc-runtime/ultragoal-runtime";
12
13
 
13
14
  export default class Ultragoal extends Command {
@@ -44,16 +45,23 @@ export default class Ultragoal extends Command {
44
45
  const { objective, goalsPath, provenance } = await readUltragoalGjcObjective(cwd);
45
46
 
46
47
  await writeCurrentSessionGoalModeState({
47
- sessionFile: process.env[GJC_SESSION_FILE_ENV],
48
+ // Bun has already copied the project dotenv into the environment. A
49
+ // value that matches that snapshot must not select the transcript.
50
+ sessionFile: trustedCoordinatorEnv(GJC_SESSION_FILE_ENV),
48
51
  objective,
49
52
  provenance,
50
53
  });
51
- await writePendingGoalModeRequest({
52
- cwd,
53
- objective,
54
- goalsPath,
55
- provenance,
56
- sessionId: process.env[GJC_SESSION_ID_ENV],
57
- });
54
+ // A matching or dynamic project declaration must not select the session.
55
+ // Skip the write in that case: the helper falls back to the same env value.
56
+ const sessionId = trustedCoordinatorEnv(GJC_SESSION_ID_ENV);
57
+ if (sessionId !== undefined || !process.env[GJC_SESSION_ID_ENV]?.trim()) {
58
+ await writePendingGoalModeRequest({
59
+ cwd,
60
+ objective,
61
+ goalsPath,
62
+ provenance,
63
+ sessionId,
64
+ });
65
+ }
58
66
  }
59
67
  }
@@ -168,11 +168,49 @@ function applyChangelogEntries(
168
168
  if (deletions) {
169
169
  base = applyDeletions(base, deletions);
170
170
  }
171
- const merged = mergeEntries(base, entries);
171
+ const merged = mergeEntries(base, redactPersistedEntries(entries));
172
172
  const sectionLines = renderUnreleasedSections(merged);
173
173
  return [...before, ...sectionLines, ...after].join("\n");
174
174
  }
175
175
 
176
+ function redactPersistedEntries(entries: Record<string, string[]>): Record<string, string[]> {
177
+ const redacted: Record<string, string[]> = {};
178
+ for (const [section, items] of Object.entries(entries)) {
179
+ redacted[section] = items.map(item => redactChangelogEntry(item));
180
+ }
181
+ return redacted;
182
+ }
183
+
184
+ const AWS_LABELED_KEY =
185
+ "(?:(?:aws[_-]?)?secret[_-]?access[_-]?key|(?:aws[_-]?)?session[_-]?token|x[_-]?amz[_-]?security[_-]?token)";
186
+
187
+ export function redactChangelogEntry(text: string): string {
188
+ let redacted = text.replace(/(^|[^0-9A-Za-z])(?:AKIA|ASIA)[0-9A-Z]{16}(?![0-9A-Za-z])/g, "$1[REDACTED_AWS_KEY_ID]");
189
+ redacted = redacted.replace(
190
+ new RegExp(
191
+ `(^|[^A-Za-z0-9_-])(["']?${AWS_LABELED_KEY}["']?\\s*[=:]\\s*)(\\$?)(["'\`])([^"'\`\\r\\n]{8,})\\4`,
192
+ "gi",
193
+ ),
194
+ "$1$2$3$4[REDACTED_SECRET]$4",
195
+ );
196
+ redacted = redacted.replace(
197
+ new RegExp(`(^|[^A-Za-z0-9_-])(["']?${AWS_LABELED_KEY}["']?\\s*[=:]\\s*)[^\\s"'\`,;{}[\\]()&<>#]{8,}`, "gi"),
198
+ "$1$2[REDACTED_SECRET]",
199
+ );
200
+ redacted = redacted.replace(/\b(?:sk|pk|rk|xox[baprs])-[-_A-Za-z0-9]{12,}\b/g, "[REDACTED_TOKEN]");
201
+ redacted = redacted.replace(/(?<![A-Za-z0-9_-])AIza[0-9A-Za-z_-]{35}(?![A-Za-z0-9_-])/g, "[REDACTED_TOKEN]");
202
+ redacted = redacted.replace(/\b(?:gh[opsur]_[A-Za-z0-9_]{12,}|github_pat_[A-Za-z0-9_]{12,})\b/g, "[REDACTED_TOKEN]");
203
+ redacted = redacted.replace(
204
+ /\b((?:ANTHROPIC|OPENAI|GITHUB|GOOGLE|GEMINI|KAGI|TAVILY|EXA|PERPLEXITY|ZAI|KIMI|BRAVE|SEARXNG|AWS)_[A-Z0-9_]*(?:KEY|TOKEN|SECRET|COOKIE|PASSWORD))\s*=\s*[^\s\n]+/gi,
205
+ "$1=[REDACTED_SECRET]",
206
+ );
207
+ redacted = redacted.replace(
208
+ /\b(Authorization|Proxy-Authorization)\s*:\s*(?:Bearer|Basic|Token)\s+[^\s\n]+/gi,
209
+ "$1: [REDACTED_AUTH_HEADER]",
210
+ );
211
+ return redacted.replace(/\b(Cookie|Set-Cookie)\s*:\s*[^\n]+/gi, "$1: [REDACTED_COOKIE]");
212
+ }
213
+
176
214
  function applyDeletions(
177
215
  existing: Record<string, string[]>,
178
216
  deletions: Record<string, string[]>,
@@ -1,9 +1,16 @@
1
+ import { redactCrashSecrets } from "@gajae-code/utils";
2
+ import { redactChangelogEntry } from "./changelog";
1
3
  import type { ConventionalAnalysis } from "./types";
2
4
 
5
+ /** Same order as generated task messages, so a second pass stays stable. */
6
+ function redactCommitText(text: string): string {
7
+ return redactCrashSecrets(redactChangelogEntry(text));
8
+ }
9
+
3
10
  export function formatCommitMessage(analysis: ConventionalAnalysis, summary: string): string {
4
- const scopePart = analysis.scope ? `(${analysis.scope})` : "";
5
- const header = `${analysis.type}${scopePart}: ${summary}`;
6
- const bodyLines = analysis.details.map(detail => `- ${detail.text.trim()}`);
11
+ const scopePart = analysis.scope ? `(${redactCommitText(analysis.scope)})` : "";
12
+ const header = `${analysis.type}${scopePart}: ${redactCommitText(summary)}`;
13
+ const bodyLines = analysis.details.map(detail => `- ${redactCommitText(detail.text.trim())}`);
7
14
  if (bodyLines.length === 0) {
8
15
  return header;
9
16
  }
@@ -80,12 +80,42 @@ export const TIER_MAP_SKIP_LIST = {
80
80
  "amazon-bedrock/au.anthropic.claude-sonnet-5-5": {
81
81
  rationale: "Sonnet 5.5 catalog addition (#6111); not yet curated",
82
82
  },
83
+ "amazon-bedrock/in.anthropic.claude-haiku-4-5-20251001-v1:0": {
84
+ rationale: "India-region Bedrock Anthropic catalog addition (#6731); not yet curated",
85
+ },
86
+ "amazon-bedrock/in.anthropic.claude-opus-5": {
87
+ rationale: "India-region Bedrock Anthropic catalog addition (#6731); not yet curated",
88
+ },
89
+ "amazon-bedrock/in.anthropic.claude-sonnet-5": {
90
+ rationale: "India-region Bedrock Anthropic catalog addition (#6731); not yet curated",
91
+ },
83
92
  "amazon-bedrock/jp.anthropic.claude-sonnet-5-5": {
84
93
  rationale: "Sonnet 5.5 catalog addition (#6111); not yet curated",
85
94
  },
86
95
  "amazon-bedrock/us.anthropic.claude-sonnet-5-5": {
87
96
  rationale: "Sonnet 5.5 catalog addition (#6111); not yet curated",
88
97
  },
98
+ "github-copilot/gemini-4-argon": {
99
+ rationale: "Gemini 4 Argon provider catalog addition (#6731); not yet curated",
100
+ },
101
+ "google/gemini-4-argon": {
102
+ rationale: "Gemini 4 Argon catalog addition (#6731); tier ordering not yet reviewed",
103
+ },
104
+ "kilo/google/gemini-4-argon": {
105
+ rationale: "Gemini 4 Argon provider catalog addition (#6731); not yet curated",
106
+ },
107
+ "opencode-zen/gemini-4-argon": {
108
+ rationale: "Gemini 4 Argon provider catalog addition (#6731); not yet curated",
109
+ },
110
+ "openrouter/google/gemini-4-argon": {
111
+ rationale: "Gemini 4 Argon provider catalog addition (#6731); not yet curated",
112
+ },
113
+ "openrouter/google/gemini-4-argon:batch": {
114
+ rationale: "Gemini 4 Argon batch provider catalog addition (#6731); not yet curated",
115
+ },
116
+ "vercel-ai-gateway/google/gemini-4-argon": {
117
+ rationale: "Gemini 4 Argon provider catalog addition (#6731); not yet curated",
118
+ },
89
119
  "kiro/claude-opus-5-5": { rationale: "post-rebase catalog addition from dev; not yet curated" },
90
120
  "kiro/claude-opus-5.5": { rationale: "post-rebase catalog addition from dev; not yet curated" },
91
121
  "alibaba-token-plan/qwen3.8-flash": { rationale: "post-rebase catalog addition from dev; not yet curated" },