@gajae-code/coding-agent 0.18.6 → 0.18.8

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 (302) hide show
  1. package/CHANGELOG.md +318 -1
  2. package/dist/types/async/job-manager.d.ts +1 -1
  3. package/dist/types/capability/mcp.d.ts +2 -0
  4. package/dist/types/capability/skill.d.ts +2 -0
  5. package/dist/types/capability/types.d.ts +6 -0
  6. package/dist/types/cli/public-command-errors.d.ts +3 -1
  7. package/dist/types/cli/setup-cli.d.ts +1 -1
  8. package/dist/types/commands/deep-interview.d.ts +3 -0
  9. package/dist/types/config/autorouting-tier-map.d.ts +348 -9
  10. package/dist/types/config/file-lock.d.ts +1 -0
  11. package/dist/types/config/model-bindings-applier.d.ts +2 -0
  12. package/dist/types/config/model-profile-activation.d.ts +11 -3
  13. package/dist/types/config/model-registry.d.ts +4 -9
  14. package/dist/types/config/settings.d.ts +4 -0
  15. package/dist/types/config/skill-settings-defaults.d.ts +2 -0
  16. package/dist/types/cursor-delete-path.d.ts +1 -0
  17. package/dist/types/cursor-mcp-name.d.ts +8 -0
  18. package/dist/types/customization/inventory.d.ts +2 -0
  19. package/dist/types/debug/report-bundle-parent.d.ts +2 -0
  20. package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/provider/stream.d.ts +1 -0
  21. package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/provider/version-manager.d.ts +31 -0
  22. package/dist/types/defaults/gjc-skills.generated.d.ts +5 -6
  23. package/dist/types/discovery/helpers.d.ts +8 -3
  24. package/dist/types/export/html/css-color.d.ts +2 -0
  25. package/dist/types/export/html/template.generated.d.ts +1 -1
  26. package/dist/types/extensibility/extensions/types.d.ts +7 -0
  27. package/dist/types/extensibility/gjc-plugins/runtime-adapters.d.ts +14 -1
  28. package/dist/types/extensibility/plugins/marketplace/cache.d.ts +2 -0
  29. package/dist/types/extensibility/plugins/plugin-link-path.d.ts +2 -0
  30. package/dist/types/extensibility/runtime-skill-discovery.d.ts +3 -1
  31. package/dist/types/extensibility/skill-management.d.ts +3 -1
  32. package/dist/types/extensibility/skills.d.ts +2 -0
  33. package/dist/types/gjc-runtime/deep-interview-crystallize.d.ts +74 -0
  34. package/dist/types/gjc-runtime/deep-interview-runtime.d.ts +11 -0
  35. package/dist/types/gjc-runtime/gc-runtime.d.ts +5 -0
  36. package/dist/types/gjc-runtime/ralplan-runtime.d.ts +0 -5
  37. package/dist/types/gjc-runtime/state-argv.d.ts +1 -1
  38. package/dist/types/gjc-runtime/state-migrations.d.ts +8 -0
  39. package/dist/types/gjc-runtime/state-runtime.d.ts +95 -0
  40. package/dist/types/gjc-runtime/state-writer.d.ts +11 -1
  41. package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +8 -0
  42. package/dist/types/internal-urls/skill-path.d.ts +1 -0
  43. package/dist/types/lsp/workspace-path.d.ts +1 -0
  44. package/dist/types/modes/acp/acp-agent.d.ts +7 -0
  45. package/dist/types/modes/components/custom-editor.d.ts +6 -0
  46. package/dist/types/modes/components/customization/customization-dashboard.d.ts +1 -0
  47. package/dist/types/modes/components/extensions/state-manager.d.ts +4 -3
  48. package/dist/types/modes/controllers/input-controller.d.ts +9 -0
  49. package/dist/types/modes/interactive-mode.d.ts +1 -0
  50. package/dist/types/modes/utils/interrupt-ownership.d.ts +3 -0
  51. package/dist/types/modes/utils/keybinding-matchers.d.ts +1 -0
  52. package/dist/types/modes/utils/macos-option-forwarding.d.ts +17 -0
  53. package/dist/types/progress/collect-project-progress.d.ts +38 -0
  54. package/dist/types/progress/progress-contract.d.ts +154 -0
  55. package/dist/types/progress/progress-snapshot.d.ts +11 -0
  56. package/dist/types/progress/project-progress.d.ts +141 -0
  57. package/dist/types/progress/render-progress.d.ts +28 -0
  58. package/dist/types/runtime-mcp/elicitation.d.ts +12 -0
  59. package/dist/types/runtime-mcp/oauth-public-url.d.ts +1 -0
  60. package/dist/types/runtime-mcp/plugin-network-boundary.d.ts +1 -0
  61. package/dist/types/runtime-mcp/smithery-registry.d.ts +24 -0
  62. package/dist/types/runtime-mcp/types.d.ts +6 -0
  63. package/dist/types/sdk/acp/adapter.d.ts +1 -1
  64. package/dist/types/sdk/broker/broker-exit.d.ts +6 -2
  65. package/dist/types/sdk/broker/broker.d.ts +18 -1
  66. package/dist/types/sdk/broker/lifecycle.d.ts +9 -0
  67. package/dist/types/sdk/broker/session-index.d.ts +12 -6
  68. package/dist/types/sdk/broker/task-artifact-owner-validation.d.ts +55 -0
  69. package/dist/types/sdk/bus/index.d.ts +12 -1
  70. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +6 -1
  71. package/dist/types/sdk/bus/telegram-daemon.d.ts +3 -2
  72. package/dist/types/sdk/client/client.d.ts +2 -0
  73. package/dist/types/sdk/host/host.d.ts +6 -0
  74. package/dist/types/sdk/host/query/handlers.d.ts +3 -0
  75. package/dist/types/sdk/index.d.ts +1 -0
  76. package/dist/types/sdk/router/session-router.d.ts +9 -0
  77. package/dist/types/sdk/session-list.d.ts +1 -1
  78. package/dist/types/sdk/session.d.ts +8 -0
  79. package/dist/types/session/agent-session.d.ts +38 -9
  80. package/dist/types/session/artifacts.d.ts +2 -2
  81. package/dist/types/session/internal/managed-gc-retirement-codec.d.ts +32 -0
  82. package/dist/types/session/internal/managed-session-scope.d.ts +79 -2
  83. package/dist/types/session/internal/managed-session-storage.d.ts +36 -1
  84. package/dist/types/session/internal/managed-task-owner-cleanup.d.ts +62 -0
  85. package/dist/types/session/internal/task-artifact-owner-access.d.ts +19 -0
  86. package/dist/types/session/internal/task-artifact-owner-transcript.d.ts +11 -0
  87. package/dist/types/session/session-manager.d.ts +31 -5
  88. package/dist/types/session/session-retirement.d.ts +71 -0
  89. package/dist/types/session/session-storage.d.ts +62 -48
  90. package/dist/types/session/session-transcript-header.d.ts +2 -0
  91. package/dist/types/session/task-artifact-owner-codec.d.ts +109 -0
  92. package/dist/types/session/task-artifact-owner-retirement.d.ts +7 -0
  93. package/dist/types/session/task-artifact-owner.d.ts +10 -0
  94. package/dist/types/setup/credential-auto-import.d.ts +1 -1
  95. package/dist/types/setup/credential-import.d.ts +6 -4
  96. package/dist/types/skill-state/active-state.d.ts +38 -0
  97. package/dist/types/slash-commands/helpers/progress-report.d.ts +8 -0
  98. package/dist/types/task/executor.d.ts +3 -0
  99. package/dist/types/tools/bash-skill-urls.d.ts +1 -1
  100. package/dist/types/tools/index.d.ts +3 -0
  101. package/dist/types/tools/python.d.ts +9 -1
  102. package/dist/types/tools/recipe/recipe-guard.d.ts +7 -0
  103. package/dist/types/tools/restricted-cwd.d.ts +1 -0
  104. package/dist/types/tools/todo-write.d.ts +6 -0
  105. package/dist/types/utils/tools-checksum.d.ts +7 -0
  106. package/package.json +7 -7
  107. package/scripts/generate-sdk-operation-inventory.ts +21 -0
  108. package/scripts/resident-memory-bench.ts +174 -20
  109. package/scripts/verify-managed-empty-stop.ts +28 -0
  110. package/src/async/job-manager.ts +228 -122
  111. package/src/capability/index.ts +18 -0
  112. package/src/capability/mcp.ts +2 -0
  113. package/src/capability/skill.ts +2 -0
  114. package/src/capability/types.ts +6 -0
  115. package/src/cli/auth-broker-cli.ts +1 -1
  116. package/src/cli/config-cli.ts +8 -18
  117. package/src/cli/customize-doctor.ts +15 -2
  118. package/src/cli/public-command-errors.ts +21 -1
  119. package/src/cli/setup-cli.ts +4 -4
  120. package/src/cli/skills-cli.ts +5 -0
  121. package/src/cli-main.ts +7 -8
  122. package/src/commands/deep-interview.ts +47 -8
  123. package/src/commands/sdk.ts +140 -29
  124. package/src/config/autorouting-tier-map.ts +117 -7
  125. package/src/config/file-lock.ts +307 -68
  126. package/src/config/mcp-schema.json +4 -0
  127. package/src/config/model-bindings-applier.ts +20 -0
  128. package/src/config/model-profile-activation.ts +240 -46
  129. package/src/config/model-registry.ts +47 -153
  130. package/src/config/settings.ts +44 -4
  131. package/src/config/skill-settings-defaults.ts +7 -0
  132. package/src/coordinator-mcp/policy.ts +3 -2
  133. package/src/cursor-delete-path.ts +10 -0
  134. package/src/cursor-mcp-name.ts +15 -0
  135. package/src/cursor.ts +13 -2
  136. package/src/customization/inventory.ts +3 -0
  137. package/src/debug/report-bundle-parent.ts +22 -0
  138. package/src/debug/report-bundle.ts +3 -0
  139. package/src/debug/system-info.ts +13 -1
  140. package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/stream.ts +67 -4
  141. package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/version-manager.ts +80 -0
  142. package/src/defaults/gjc/skills/deep-interview/SKILL.md +105 -10
  143. package/src/defaults/gjc/skills/ralplan/SKILL.md +6 -4
  144. package/src/defaults/gjc-defaults.test.ts +18 -1
  145. package/src/defaults/gjc-defaults.ts +3 -0
  146. package/src/defaults/gjc-skills.generated.ts +58 -36
  147. package/src/discovery/agents.ts +6 -1
  148. package/src/discovery/builtin.ts +10 -0
  149. package/src/discovery/helpers.ts +168 -23
  150. package/src/discovery/mcp-json.ts +6 -0
  151. package/src/discovery/ssh.ts +9 -4
  152. package/src/discovery/substitute-plugin-root.ts +3 -1
  153. package/src/edit/file-read-cache.ts +1 -1
  154. package/src/eval/py/executor.ts +380 -120
  155. package/src/export/html/css-color.ts +9 -0
  156. package/src/export/html/index.ts +5 -4
  157. package/src/export/html/template.generated.ts +1 -1
  158. package/src/extensibility/extensions/runner.ts +4 -0
  159. package/src/extensibility/extensions/types.ts +7 -0
  160. package/src/extensibility/gjc-plugins/runtime-adapters.ts +73 -8
  161. package/src/extensibility/plugins/manager.ts +3 -2
  162. package/src/extensibility/plugins/marketplace/cache.ts +15 -0
  163. package/src/extensibility/plugins/marketplace/manager.ts +11 -3
  164. package/src/extensibility/plugins/plugin-link-path.ts +12 -0
  165. package/src/extensibility/runtime-skill-discovery.ts +20 -2
  166. package/src/extensibility/skill-management.ts +6 -2
  167. package/src/extensibility/skills.ts +6 -1
  168. package/src/gjc-runtime/deep-interview-crystallize.ts +1814 -0
  169. package/src/gjc-runtime/deep-interview-recorder.ts +20 -2
  170. package/src/gjc-runtime/deep-interview-runtime.ts +1415 -13
  171. package/src/gjc-runtime/deep-interview-stage.ts +98 -21
  172. package/src/gjc-runtime/gc-runtime.ts +206 -8
  173. package/src/gjc-runtime/launch-worktree.ts +14 -4
  174. package/src/gjc-runtime/ralplan-runtime.ts +447 -52
  175. package/src/gjc-runtime/state-argv.ts +2 -0
  176. package/src/gjc-runtime/state-migrations.ts +91 -29
  177. package/src/gjc-runtime/state-runtime.ts +3716 -135
  178. package/src/gjc-runtime/state-writer.ts +83 -8
  179. package/src/gjc-runtime/ultragoal-runtime.ts +16 -4
  180. package/src/gjc-runtime/workflow-manifest.generated.json +70 -42
  181. package/src/gjc-runtime/workflow-manifest.ts +54 -21
  182. package/src/harness-control-plane/operate.ts +12 -4
  183. package/src/harness-control-plane/owner.ts +5 -1
  184. package/src/hashline/parser.ts +48 -9
  185. package/src/hashline/recovery.ts +13 -4
  186. package/src/hindsight/config.ts +9 -3
  187. package/src/internal-urls/docs-index.generated.ts +19 -18
  188. package/src/internal-urls/skill-path.ts +19 -0
  189. package/src/internal-urls/skill-protocol.ts +2 -0
  190. package/src/lsp/edits.ts +6 -0
  191. package/src/lsp/workspace-path.ts +51 -0
  192. package/src/main.ts +195 -31
  193. package/src/modes/acp/acp-agent.ts +163 -7
  194. package/src/modes/components/custom-editor.ts +14 -0
  195. package/src/modes/components/customization/customization-dashboard.ts +12 -0
  196. package/src/modes/components/extensions/extension-dashboard.ts +2 -2
  197. package/src/modes/components/extensions/state-manager.ts +15 -5
  198. package/src/modes/components/model-selector.ts +1 -4
  199. package/src/modes/components/provider-onboarding-selector.ts +1 -1
  200. package/src/modes/components/status-line/segments.ts +4 -0
  201. package/src/modes/controllers/event-controller.ts +11 -4
  202. package/src/modes/controllers/input-controller.ts +74 -29
  203. package/src/modes/controllers/runtime-mcp-command-controller.ts +8 -3
  204. package/src/modes/controllers/selector-controller.ts +28 -15
  205. package/src/modes/interactive-mode.ts +4 -0
  206. package/src/modes/runtime-init.ts +4 -0
  207. package/src/modes/utils/abort-message.ts +3 -1
  208. package/src/modes/utils/interrupt-ownership.ts +12 -0
  209. package/src/modes/utils/keybinding-matchers.ts +4 -0
  210. package/src/modes/utils/macos-option-forwarding.ts +80 -0
  211. package/src/progress/collect-project-progress.ts +153 -0
  212. package/src/progress/progress-contract.ts +172 -0
  213. package/src/progress/progress-snapshot.ts +140 -0
  214. package/src/progress/project-progress.ts +446 -0
  215. package/src/progress/render-progress.ts +209 -0
  216. package/src/prompts/system/master-mode.md +1 -0
  217. package/src/prompts/tools/skill-discovery.md +1 -1
  218. package/src/runtime-mcp/client.ts +13 -4
  219. package/src/runtime-mcp/config-writer.ts +10 -6
  220. package/src/runtime-mcp/config.ts +1 -0
  221. package/src/runtime-mcp/elicitation.ts +142 -0
  222. package/src/runtime-mcp/oauth-flow.ts +5 -0
  223. package/src/runtime-mcp/oauth-public-url.ts +8 -0
  224. package/src/runtime-mcp/plugin-network-boundary.ts +4 -0
  225. package/src/runtime-mcp/smithery-registry.ts +22 -3
  226. package/src/runtime-mcp/transports/http.ts +2 -2
  227. package/src/runtime-mcp/types.ts +6 -0
  228. package/src/sdk/acp/adapter.ts +93 -8
  229. package/src/sdk/broker/broker-exit.ts +52 -23
  230. package/src/sdk/broker/broker.ts +83 -7
  231. package/src/sdk/broker/ensure.ts +2 -0
  232. package/src/sdk/broker/lifecycle.ts +820 -73
  233. package/src/sdk/broker/session-index.ts +191 -81
  234. package/src/sdk/broker/task-artifact-owner-validation.ts +259 -0
  235. package/src/sdk/bus/chat-daemon-cli.ts +38 -1
  236. package/src/sdk/bus/chat-daemon-control.ts +2 -2
  237. package/src/sdk/bus/chat-daemon-runtime.ts +3 -0
  238. package/src/sdk/bus/index.ts +241 -46
  239. package/src/sdk/bus/telegram-daemon-contract.ts +6 -1
  240. package/src/sdk/bus/telegram-daemon.ts +4 -2
  241. package/src/sdk/cli/session-cli.ts +17 -3
  242. package/src/sdk/client/client.ts +28 -8
  243. package/src/sdk/host/host.ts +6 -0
  244. package/src/sdk/host/query/handlers.ts +9 -1
  245. package/src/sdk/host/session-runtime.test.ts +2805 -411
  246. package/src/sdk/host/session-runtime.ts +428 -111
  247. package/src/sdk/host/surface-policy.ts +1 -0
  248. package/src/sdk/index.ts +8 -0
  249. package/src/sdk/lifecycle-session.ts +3 -1
  250. package/src/sdk/mcp/server.ts +15 -3
  251. package/src/sdk/prompt-deadline-manager.ts +15 -0
  252. package/src/sdk/protocol/operation-inventory.generated.json +146 -0
  253. package/src/sdk/protocol/operation-registry.ts +9 -2
  254. package/src/sdk/router/session-router.ts +94 -14
  255. package/src/sdk/session-list.ts +1 -0
  256. package/src/sdk/session.ts +81 -38
  257. package/src/session/agent-session.ts +674 -224
  258. package/src/session/artifacts.ts +174 -70
  259. package/src/session/internal/managed-gc-retirement-codec.ts +319 -0
  260. package/src/session/internal/managed-session-scope.ts +3457 -462
  261. package/src/session/internal/managed-session-storage.ts +482 -61
  262. package/src/session/internal/managed-task-owner-cleanup.ts +473 -0
  263. package/src/session/internal/task-artifact-owner-access.ts +245 -0
  264. package/src/session/internal/task-artifact-owner-transcript.ts +614 -0
  265. package/src/session/session-manager.ts +939 -133
  266. package/src/session/session-retirement.ts +714 -0
  267. package/src/session/session-storage.ts +418 -174
  268. package/src/session/session-transcript-header.ts +17 -0
  269. package/src/session/task-artifact-owner-codec.ts +641 -0
  270. package/src/session/task-artifact-owner-retirement.ts +477 -0
  271. package/src/session/task-artifact-owner.ts +289 -0
  272. package/src/setup/credential-auto-import.ts +12 -3
  273. package/src/setup/credential-import.ts +176 -5
  274. package/src/setup/paseo/announce.ts +6 -1
  275. package/src/skill-state/active-state.ts +132 -2
  276. package/src/slash-commands/builtin-registry.ts +39 -9
  277. package/src/slash-commands/helpers/progress-report.ts +23 -0
  278. package/src/stt/setup.ts +3 -5
  279. package/src/task/commands.ts +3 -1
  280. package/src/task/executor.ts +4 -0
  281. package/src/task/index.ts +6 -0
  282. package/src/tools/ask.ts +205 -6
  283. package/src/tools/ast-edit.ts +4 -0
  284. package/src/tools/bash-allowed-prefixes.ts +15 -0
  285. package/src/tools/bash-skill-urls.ts +56 -3
  286. package/src/tools/bash.ts +48 -79
  287. package/src/tools/descriptors.ts +5 -1
  288. package/src/tools/eval.ts +56 -36
  289. package/src/tools/image-gen.ts +1 -1
  290. package/src/tools/index.ts +3 -0
  291. package/src/tools/python.ts +187 -66
  292. package/src/tools/recipe/index.ts +9 -0
  293. package/src/tools/recipe/recipe-guard.ts +19 -0
  294. package/src/tools/restricted-cwd.ts +10 -0
  295. package/src/tools/skill-discovery.ts +5 -0
  296. package/src/tools/skill.ts +28 -1
  297. package/src/tools/todo-write.ts +10 -1
  298. package/src/tools/tool-catalog.generated.ts +1 -1
  299. package/src/tools/write.ts +1 -0
  300. package/src/utils/tools-checksum.ts +34 -0
  301. package/src/utils/tools-manager.ts +24 -6
  302. package/src/web/search/providers/codex.ts +3 -2
@@ -2,12 +2,18 @@ import type {
2
2
  Api,
3
3
  AssistantMessageEventStream,
4
4
  Context,
5
+ FetchImpl,
5
6
  Model,
6
7
  SimpleStreamOptions,
7
8
  } from '@gajae-code/ai/core';
8
9
  import { streamOpenAIResponses } from '@gajae-code/ai/providers/openai-responses';
10
+ import {
11
+ getGrokCliVersion,
12
+ parseMinimumVersionFrom426,
13
+ updateVersionFromError,
14
+ } from './version-manager';
9
15
 
10
- const GROK_CLI_VERSION = '0.2.33';
16
+ type FetchInput = Parameters<FetchImpl>[0];
11
17
 
12
18
  /**
13
19
  * Stream function that adds Grok CLI-specific headers to requests.
@@ -16,6 +22,7 @@ const GROK_CLI_VERSION = '0.2.33';
16
22
  * - x-grok-conv-id: <session/conversation ID>
17
23
  * - x-grok-model-override: <model ID>
18
24
  * - x-xai-token-auth: xai-grok-cli
25
+ * - x-grok-client-version: learned from HTTP 426 responses; defaults to 1.0.13 and retries once on upgrade
19
26
  */
20
27
  export function streamGrokCli(
21
28
  model: Model<Api>,
@@ -23,10 +30,14 @@ export function streamGrokCli(
23
30
  options?: SimpleStreamOptions,
24
31
  ): AssistantMessageEventStream {
25
32
  const sessionId = options?.sessionId;
33
+
34
+ // Get the Grok CLI version: learned from 426 responses or fallback
35
+ const grokCliVersion = getGrokCliVersion();
36
+
26
37
  const headers: Record<string, string> = {
27
38
  ...options?.headers,
28
39
  'x-grok-client-identifier': 'gjc-grok-cli',
29
- 'x-grok-client-version': GROK_CLI_VERSION,
40
+ 'x-grok-client-version': grokCliVersion,
30
41
  'x-xai-token-auth': 'xai-grok-cli',
31
42
  'x-grok-model-override': model.id,
32
43
  };
@@ -40,11 +51,63 @@ export function streamGrokCli(
40
51
  api: 'openai-responses',
41
52
  } as Model<'openai-responses'>;
42
53
 
54
+ // Wrap fetch to intercept 426 errors and extract version info
55
+ const baseFetch = options?.fetch ?? (globalThis.fetch.bind(globalThis) as FetchImpl);
56
+ const wrappedFetch = wrapFetchForVersionHandling(baseFetch);
57
+
43
58
  return streamOpenAIResponses(responsesModel, context, {
44
59
  ...options,
45
60
  headers,
46
- onResponse(response) {
47
- options?.onResponse?.(response, model);
61
+ fetch: wrappedFetch,
62
+ onResponse(response, _responseModel, scope, signal) {
63
+ return options?.onResponse?.(response, model, scope, signal);
48
64
  },
49
65
  });
50
66
  }
67
+
68
+ /**
69
+ * Wraps a fetch function to learn from HTTP 426 responses and retry once with a newer version.
70
+ */
71
+ function wrapFetchForVersionHandling(baseFetch: FetchImpl): FetchImpl {
72
+ return Object.assign(
73
+ async (input: FetchInput, init?: RequestInit): Promise<Response> => {
74
+ const firstInput =
75
+ input instanceof Request ? (input.clone() as unknown as FetchInput) : input;
76
+ const response = await baseFetch(firstInput, init);
77
+
78
+ if (response.status !== 426) return response;
79
+
80
+ let errorText: string;
81
+ try {
82
+ errorText = await response.clone().text();
83
+ } catch {
84
+ return response;
85
+ }
86
+
87
+ if (!parseMinimumVersionFrom426(errorText)) return response;
88
+
89
+ const retryHeaders = new Headers(
90
+ init?.headers ?? (input instanceof Request ? input.headers : undefined),
91
+ );
92
+ const requestedVersion = retryHeaders.get('x-grok-client-version');
93
+ const learnedVersion = updateVersionFromError(errorText);
94
+ if (!requestedVersion || learnedVersion === requestedVersion) return response;
95
+
96
+ retryHeaders.set('x-grok-client-version', learnedVersion);
97
+ const retryInput =
98
+ input instanceof Request ? (input.clone() as unknown as FetchInput) : input;
99
+ const retryResponse = await baseFetch(retryInput, { ...init, headers: retryHeaders });
100
+
101
+ if (retryResponse.status === 426) {
102
+ try {
103
+ updateVersionFromError(await retryResponse.clone().text());
104
+ } catch {
105
+ // Keep the retry response intact if its body cannot be inspected.
106
+ }
107
+ }
108
+
109
+ return retryResponse;
110
+ },
111
+ { preconnect: baseFetch.preconnect },
112
+ ) as FetchImpl;
113
+ }
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Grok CLI version manager with 426 error handling.
3
+ *
4
+ * Learns the minimum required Grok CLI version from xAI HTTP 426 "version outdated" responses.
5
+ * Falls back to a hardcoded version if no 426 has been received.
6
+ * Version updates are monotonic: learned versions never downgrade.
7
+ */
8
+
9
+ const FALLBACK_VERSION = '1.0.13';
10
+
11
+ // Minimum version xAI demanded in its latest HTTP 426 response.
12
+ // A server-stated minimum never becomes less true, so it has no expiry.
13
+ let learnedVersion: string | null = null;
14
+
15
+ /**
16
+ * Get the current Grok CLI version: learned from 426 responses (never downgrades),
17
+ * otherwise the fallback version.
18
+ */
19
+ export function getGrokCliVersion(): string {
20
+ return learnedVersion ?? FALLBACK_VERSION;
21
+ }
22
+
23
+ /**
24
+ * Parse a minimum version from an HTTP 426 error response body.
25
+ * Expected format: "Your Grok CLI version (X.Y.Z) is outdated. Please update to version A.B.C or later"
26
+ */
27
+ export function parseMinimumVersionFrom426(errorBody: string): string | null {
28
+ const versionMatch = errorBody.match(/update to version (\d+\.\d+\.\d+) or later\b/i);
29
+ return versionMatch?.[1] ?? null;
30
+ }
31
+
32
+ /**
33
+ * Update the learned version from a 426 error response.
34
+ * Versions are monotonic: a learned version never downgrades.
35
+ * Returns the version to use for the next request.
36
+ */
37
+ export function updateVersionFromError(errorBody: string): string {
38
+ const minVersion = parseMinimumVersionFrom426(errorBody);
39
+ if (!minVersion) {
40
+ return getGrokCliVersion();
41
+ }
42
+
43
+ // Compare against the active value so an older minimum cannot downgrade the fallback.
44
+ if (isVersionGreater(minVersion, getGrokCliVersion())) {
45
+ learnedVersion = minVersion;
46
+ }
47
+
48
+ return getGrokCliVersion();
49
+ }
50
+
51
+ /**
52
+ * Determine if version1 is greater than version2 (naive semver comparison).
53
+ * Prevents learned versions from downgrading due to out-of-order 426 responses.
54
+ */
55
+ function isVersionGreater(version1: string, version2: string): boolean {
56
+ const parts1 = version1.split('.').map((x) => parseInt(x, 10) || 0);
57
+ const parts2 = version2.split('.').map((x) => parseInt(x, 10) || 0);
58
+
59
+ for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
60
+ const p1 = parts1[i] ?? 0;
61
+ const p2 = parts2[i] ?? 0;
62
+ if (p1 > p2) return true;
63
+ if (p1 < p2) return false;
64
+ }
65
+ return false;
66
+ }
67
+
68
+ /**
69
+ * Reset the learned version (mainly for testing).
70
+ */
71
+ export function resetVersionCache(): void {
72
+ learnedVersion = null;
73
+ }
74
+
75
+ /**
76
+ * Get the fallback version (mainly for testing).
77
+ */
78
+ export function getFallbackVersion(): string {
79
+ return FALLBACK_VERSION;
80
+ }
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: deep-interview
3
3
  description: Socratic deep interview with mathematical ambiguity gating before explicit execution approval
4
- argument-hint: "[--trace] [--quick|--standard|--deep] <idea or vague description>"
4
+ argument-hint: "[--crystallize --input <json-or-@file> --slug <slug>] [--trace] [--json] [--quick|--standard|--deep] <idea or vague description>"
5
5
  pipeline: [deep-interview, ralplan]
6
6
  handoff-policy: approval-required
7
7
  handoff: .gjc/_session-{sessionid}/specs/deep-interview-{slug}.md
@@ -74,6 +74,52 @@ source: "forked from upstream deep-interview skill and rebranded for GJC"
74
74
  - After 3 consecutive agent-resolved answers (accepted auto-answers), route the next question to the user (dialectic rhythm guard)
75
75
  - Run an independent closure audit and a one-sentence goal restatement, each requiring explicit user confirmation, before crystallizing the spec
76
76
  - When `--trace` is active, use the bounded trace evidence summary as pre-question context; never dump raw logs, raw files, or unbounded search output into questions, scoring, specs, or handoffs
77
+
78
+ **Native kickoff contract.** Seed the interviewing phase with `gjc deep-interview [--trace] [--json] [--quick|--standard|--deep] <idea or vague description>`. `--trace` enables the bounded evidence pre-step and `--json` selects machine-readable output; neither flag changes the approval gate. The generic workflow API retains `api --input <json-or-@file>` for bounded payloads and does not authorize execution.
79
+
80
+ **Native spec-write contract.** Persist a final specification with `gjc deep-interview --write --stage final --slug <slug> --spec <markdown-or-path> [--force] [--json]`. The `--force` option is limited to overwriting corrupt deep-interview state and never grants execution approval; use the separate approval transition before any execution handoff.
81
+
82
+ ### Crystallize sub-mode
83
+
84
+ `--crystallize` is a bounded shortcut on this skill, not a new workflow or an execution path. It is the sanctioned `interviewing` → `handoff` transition for a ready Crystal and must remain non-authorizing. Use it only when the current conversation already contains material requirements and decisions. Before any state write, capture a deterministic conversation snapshot with an explicit message range, source revision, and digest. Extract each item into exactly one of `confirmed`, `inferred`, or `disputed`; every confirmed goal, constraint, decision, and acceptance criterion MUST retain a verbatim source anchor. Do not treat inferred or disputed text as confirmed.
85
+
86
+ Submit the bounded snapshot and extraction through the native crystallize writer. The writer is the sole promoter into the existing deep-interview state/spec shape; exploration remains non-canonical. A sufficient snapshot creates a versioned Crystal/spec without replaying interview rounds. One or two blocking gaps may be asked through `ask`; unresolved consequential choices use the existing lateral/adversarial review hook. Broad ambiguity MUST fall back to the ordinary full interview flow. Never create a Crystal when the snapshot revision or digest is stale or mismatched.
87
+
88
+ When a prior Crystal exists, compare only evidence after its bound revision. Preserve unchanged confirmed material and record a versioned delta: additive requirements create the next version, changed constraints or decisions reopen affected fields and invalidate execution approval, changed goals supersede the prior Crystal, and conflicting later evidence marks it stale rather than overwriting it. Every promoted Crystal records `spec_version`, source range/revision/digest, classifications, anchors, open gaps, and `execution_approval: not-approved` unless a separate existing approval gate later records approval. Crystallization MUST NOT invoke implementation, `run`, `ralplan`, or any automatic handoff.
89
+
90
+ **Native CLI contract.** Invoke this sub-mode as `gjc deep-interview --crystallize --input <json-or-@file> --slug <slug> [--session-id <id>] [--json]`; both `--input` and `--slug` are required. The `--input` value is either inline JSON or an `@file` and is bounded to 1 MiB. It must have this required object shape (the listed arrays are optional when empty):
91
+
92
+ ```json
93
+ {
94
+ "snapshot": {
95
+ "revision": 1,
96
+ "start": 0,
97
+ "end": 0,
98
+ "digest": "<64 lowercase hex SHA-256>",
99
+ "messages": [
100
+ { "index": 0, "role": "user", "content": "Build audit reports" }
101
+ ]
102
+ },
103
+ "current_revision": 1,
104
+ "items": [
105
+ {
106
+ "id": "goal:reports",
107
+ "kind": "goal",
108
+ "classification": "confirmed",
109
+ "statement": "Build audit reports",
110
+ "anchor": { "message_index": 0, "quote": "Build audit reports" }
111
+ }
112
+ ],
113
+ "open_gaps": [],
114
+ "conflicts": []
115
+ }
116
+ ```
117
+
118
+ `snapshot.messages` MUST be ordered, unique, contiguous, and cover every index from `start` through `end`; the range and message list are capped at 200 messages, `items` at 128 entries, and each text field at 10,000 characters. `snapshot.end` MUST be the live transcript tail, `current_revision` MUST equal `snapshot.revision`, and `digest` MUST be the SHA-256 digest of the normalized snapshot. For a prior Crystal, include every message after its stored boundary; never skip a range or reuse stale evidence. Items use exactly one of `goal`, `constraint`, `decision`, `acceptance_criterion`, or `non_goal` and exactly one of `confirmed`, `inferred`, or `disputed`; confirmed items require a verbatim user `anchor` and inferred/disputed items never count as confirmed requirements.
119
+
120
+ For the first Crystal, `snapshot.start` MUST be 0 and the full authenticated transcript MUST fit within 200 messages (exactly 200 is valid). If it exceeds that bound, continue the ordinary interview flow; never submit only the last 200 messages or replace authenticated evidence with a summary. With a canonical stored prior Crystal preserving the prefix, a contiguous delta of at most 200 messages may start after its stored boundary even when the full transcript is longer than 200 messages.
121
+
122
+ The ordinary state writer has a separate required shape: `gjc deep-interview write --input '{"state":{...}}'` and `stage --for <transition> --input '{"state":{...}}'`; stage transitions are incremental deltas, not whole-transcript replacements. A Crystal is ready only when ambiguity/readiness evidence has no unresolved gaps, conflicts, or disputed requirements; `needs-questions`, `stale`, and `superseded` results do not publish a spec and return to the ordinary interview/resolution path. A ready result persists the versioned artifact `.gjc/_session-{sessionid}/specs/deep-interview-{slug}-v{spec_version}.md`. Every Crystal starts with `execution_approval: not-approved`; only the separate `gjc deep-interview approve-execution --json` action records explicit user execution approval for a ready canonical Crystal, and handoff never grants that approval.
77
123
  </Execution_Policy>
78
124
 
79
125
  <Internal_Auto_Mode_Protocol>
@@ -669,7 +715,7 @@ When ambiguity ≤ threshold (or hard cap / early exit):
669
715
  - Apply the self-proofread once (DIPP-5) to newly generated spec prose before persistence, including generated natural-language table cells such as coverage notes, while preserving transcript answers, quoted/source text, code identifiers, file paths, commands, JSON/settings keys, table structure/fixed labels, and `.gjc/_session-{sessionid}/specs/deep-interview-{slug}.md` unchanged.
670
716
  2. **Write the final spec through the workflow CLI**: persist the artifact at `.gjc/_session-{sessionid}/specs/deep-interview-{slug}.md`
671
717
  - Always use this exact final spec path. Prefer passing the spec markdown **inline** as the `--spec` value; only when it is too large to pass inline, stage it as a file in a system temp directory (`os.tmpdir()`/`$TMPDIR`, `/tmp`, `/var/tmp`) outside the project tree and pass that path — never write scratch specs to the repo root, the project tree, or `.gjc/`.
672
- - Use the native deep-interview write command with `--write --stage final --slug {slug} --spec <markdown-or-path> [--json]` for artifact and state persistence; direct `.gjc/` file edits are forbidden unless an explicit force override is active.
718
+ - Use the native deep-interview write command with `--write --stage final --slug {slug} --spec <markdown-or-path> [--force] [--json]` for artifact and state persistence; `--force` only permits recovery from corrupt deep-interview state and direct `.gjc/` file edits remain forbidden.
673
719
  - Persist the final `spec_path` in state when available so downstream skills and resumed sessions can pass the artifact path explicitly.
674
720
  - If the user preselected the deliberate ralplan path, use the native deep-interview write command with `--write --stage final --slug {slug} --spec <markdown-or-path> --deliberate [--json]` so the final spec is persisted before deep-interview hands off to ralplan.
675
721
 
@@ -789,6 +835,27 @@ After the spec is written, mark it `pending approval` and present execution opti
789
835
 
790
836
  **Question:** "Your spec is ready (ambiguity: {score}%). How would you like to proceed?"
791
837
 
838
+ The actual Phase 5 `ask` question MUST include `workflowGate: { stage: "deep-interview", kind: "execution" }`. Keep the recognized ultragoal option label so an explicit selection creates the user-origin pending approval record. Concrete `ask` input:
839
+
840
+ ```json
841
+ {
842
+ "questions": [{
843
+ "id": "deep-interview-execution",
844
+ "question": "Your spec is ready (ambiguity: {score}%). How would you like to proceed?",
845
+ "workflowGate": { "stage": "deep-interview", "kind": "execution" },
846
+ "options": [
847
+ { "label": "Refine with ralplan consensus (Recommended — default for almost all specs)" },
848
+ { "label": "Execute with ultragoal (only when spec is already implementation-ready and really simple)" },
849
+ { "label": "Continue research with autoresearch (research continuation, not execution)" },
850
+ { "label": "Refine further" }
851
+ ],
852
+ "multi": false
853
+ }]
854
+ }
855
+ ```
856
+
857
+ This tagged question does not itself authorize or automatically start implementation. Only an explicit ultragoal selection may be consumed by the separate `gjc deep-interview approve-execution --json` action; require that action to succeed before invoking `/skill:ultragoal`. Research/refinement choices, custom responses, cancellation, timeout, and untagged asks do not grant execution approval.
858
+
792
859
  **Options:**
793
860
 
794
861
  1. **Refine with ralplan consensus (Recommended — default for almost all specs)**
@@ -798,7 +865,7 @@ After the spec is written, mark it `pending approval` and present execution opti
798
865
 
799
866
  2. **Execute with ultragoal (only when spec is already implementation-ready and really simple)**
800
867
  - Description: "Goal-tracked autonomous execution — drives the spec to completion with verification. Skip ralplan refinement only when the spec is concrete, low-risk, and trivially small."
801
- - Action: Invoke `/skill:ultragoal` with the spec file path as context only after the user explicitly selects this execution option. The spec replaces ultragoal planning input. Recommend this only when the spec needs no further planning; otherwise route through ralplan refinement first.
868
+ - Action: Only after the user explicitly selects this execution option, record that distinct approval through `gjc deep-interview approve-execution --json`, then invoke `/skill:ultragoal` with the spec file path as context. The handoff itself never grants approval and rejects an unapproved Crystal. The spec replaces ultragoal planning input. Recommend this only when the spec needs no further planning; otherwise route through ralplan refinement first.
802
869
 
803
870
  3. **Continue research with autoresearch (research continuation, not execution)**
804
871
  - Description: "Feed the crystallized spec into an autoresearch mission to deepen research grounding before any implementation planning. This is not an execution path and implements nothing."
@@ -808,24 +875,23 @@ After the spec is written, mark it `pending approval` and present execution opti
808
875
  - Description: "Continue interviewing to improve clarity (current: {score}%)"
809
876
  - Action: Return to Phase 2 interview loop.
810
877
 
811
- **IMPORTANT:** On explicit execution selection, **MUST** use the chosen bundled GJC workflow skill entrypoint (`/skill:ralplan` or `/skill:ultragoal`) inside the agent session. `gjc ralplan` is a native CLI that accepts the documented skill flags and seeds local `.gjc/_session-{sessionid}/state` receipts; agent sessions should still drive the consensus loop through `/skill:ralplan`. Implementation handoff defaults to `/skill:ultragoal`. The autoresearch option is a research continuation only and never an execution path. Do NOT implement directly. The deep-interview agent is a requirements agent, not an execution agent. If oversized initial context was summarized, pass the spec and prompt-safe summary forward, not the raw oversized source material. Without explicit execution selection, stop with the spec marked `pending approval`.
878
+ **IMPORTANT:** On explicit execution selection, **MUST** use the chosen bundled GJC workflow skill entrypoint (`/skill:ralplan` or `/skill:ultragoal`) inside the agent session. Before an approved Crystal can enter `/skill:ultragoal`, persist the user's separate execution decision with `gjc deep-interview approve-execution --json`; never attach approval to the handoff command. `gjc ralplan` is a native CLI that accepts the documented skill flags and seeds local `.gjc/_session-{sessionid}/state` receipts; agent sessions should still drive the consensus loop through `/skill:ralplan`. Implementation handoff defaults to `/skill:ultragoal`. The autoresearch option is a research continuation only and never an execution path. Do NOT implement directly. The deep-interview agent is a requirements agent, not an execution agent. If oversized initial context was summarized, pass the spec and prompt-safe summary forward, not the raw oversized source material. Without explicit execution selection, stop with the spec marked `pending approval`.
812
879
 
813
880
  ### Phase 5b: Handoff before chain
814
881
 
815
- Before invoking `/skill:ralplan` or `/skill:ultragoal`, the final spec must already be persisted through the native deep-interview write command (`gjc deep-interview --write --stage final …`). That command itself moves the workflow to the `handoff` phase, so no separate state write is needed for the skill tool's chain guard. Verify readiness with:
882
+ Before invoking `/skill:ralplan` or `/skill:ultragoal`, the ready Crystal must already expose its canonical versioned `spec_path`. Crystallization itself publishes that artifact and moves the workflow to the `handoff` phase; never issue a second direct spec write after Crystal publication. Verify readiness and reuse the returned `spec_path` with:
816
883
 
817
884
  ```
818
885
  gjc deep-interview read --json
819
886
  ```
820
887
 
821
- For a preselected deliberate ralplan path, prefer the single sanctioned bridge command instead:
888
+ For a selected ralplan refinement path, hand off the already-published Crystal state without rewriting its spec:
822
889
 
823
890
  ```
824
- gjc \
825
- deep-interview --write --stage final --slug {slug} --spec <markdown-or-path> --deliberate --json
891
+ gjc state handoff --mode deep-interview --to ralplan --json
826
892
  ```
827
893
 
828
- That command persists `.gjc/_session-{sessionid}/specs/deep-interview-{slug}.md`, seeds ralplan in deliberate mode, and performs the safe deep-interview → ralplan state handoff. Skipping spec persistence leaves the Phase 5 chain blocked by design.
894
+ Pass the canonical `spec_path` from `gjc deep-interview read --json` into `/skill:ralplan`. The state handoff is non-executing and does not grant execution approval. `/skill:ultragoal` still requires the separate `approve-execution` transition before its handoff.
829
895
 
830
896
  ### Approval-Gated Refinement Path (Recommended)
831
897
 
@@ -870,6 +936,31 @@ Skipping any stage is possible but reduces quality assurance:
870
936
  </Tool_Usage>
871
937
 
872
938
  <Examples>
939
+ <Good>
940
+ Kickoff with bounded trace evidence and machine-readable output:
941
+ ```
942
+ gjc deep-interview --trace --standard "<idea>" --json
943
+ ```
944
+ </Good>
945
+
946
+ <Good>
947
+ Final spec persistence with explicit corrupt-state recovery override:
948
+ ```
949
+ gjc deep-interview --write --stage final --slug my-feature --spec ./final-spec.md --force --json
950
+ ```
951
+ </Good>
952
+
953
+ <Good>
954
+ Bounded crystallization with an explicit slug and authenticated snapshot:
955
+ ```
956
+ gjc deep-interview --crystallize --input '{"snapshot":{"revision":1,"start":0,"end":0,"digest":"<64 lowercase hex SHA-256>","messages":[{"index":0,"role":"user","content":"Build audit reports"}]},"current_revision":1,"items":[{"id":"goal:reports","kind":"goal","classification":"confirmed","statement":"Build audit reports","anchor":{"message_index":0,"quote":"Build audit reports"}}],"open_gaps":[],"conflicts":[]}' --slug audit-reports --json
957
+ ```
958
+ The input is bounded and must cover the declared snapshot range exactly. A successful `ready`
959
+ result writes `deep-interview-audit-reports-v1.md` (or the next `spec_version`), while unresolved
960
+ gaps/conflicts remain non-ready and do not publish a spec. Execution still requires the separate
961
+ `gjc deep-interview approve-execution --json` action after the user chooses an execution path.
962
+ </Good>
963
+
873
964
  <Good>
874
965
  Targeting weakest dimension:
875
966
  ```
@@ -973,8 +1064,12 @@ Why bad: 45% ambiguity means nearly half the requirements are unclear. The mathe
973
1064
  - [ ] Free-text answers passed the Refine gate; dialectic rhythm guard forced a user question after 3 agent-resolved answers; any auto-answer threshold crossing explicitly confirmed
974
1065
  - [ ] Closure / Acceptance Guard and the one-sentence Restate gate both passed before crystallization
975
1066
  - [ ] Interview reached ambiguity ≤ threshold OR an explicit early exit with warning
1067
+ - [ ] Kickoff flags matched the native contract: `--trace` and `--json` remained optional, bounded, and non-authorizing
976
1068
  - [ ] Ordinary answered rounds auto-continued to the next weakest-dimension question with no generic continue/cancel/clear ask; any stop matched a legitimate terminal condition (threshold + closure gates, explicit user exit, invocation/resume suitability, or bounded safety recovery)
977
- - [ ] Spec persisted to `.gjc/_session-{sessionid}/specs/deep-interview-{slug}.md` exactly via the GJC CLI (no direct `.gjc/` edits without force override), covering every active topology component plus goal/constraints/acceptance criteria/clarity/ontology/transcript
1069
+ - [ ] Spec persisted to `.gjc/_session-{sessionid}/specs/deep-interview-{slug}.md` exactly via the GJC CLI (use `--force` only for corrupt-state recovery; no direct `.gjc/` edits), covering every active topology component plus goal/constraints/acceptance criteria/clarity/ontology/transcript
1070
+ - [ ] `--crystallize` received required `--input <json-or-@file>` and `--slug <slug>`; its snapshot is bounded, contiguous, digest-bound, and matched to the live transcript revision
1071
+ - [ ] A ready Crystal persisted the versioned `.gjc/_session-{sessionid}/specs/deep-interview-{slug}-v{spec_version}.md` artifact; `needs-questions`, `stale`, and `superseded` results did not publish a spec
1072
+ - [ ] Every Crystal recorded `execution_approval: not-approved`; only a separate explicit `gjc deep-interview approve-execution --json` transition can authorize execution, never crystallization or handoff
978
1073
  - [ ] Spec metadata includes the auto/lateral counters (`auto_answered_rounds`, `lateral_reviews`, `refined_rounds`, `architect_failures`, `lateral_panel_failures`)
979
1074
  - [ ] Execution bridge presented via `ask`; execution invoked only after explicit approval through a public workflow entrypoint (never direct implementation); state cleaned up after handoff
980
1075
  </Final_Checklist>
@@ -33,9 +33,9 @@ For corrupt, tampered, unreadable, or stale current-session ralplan state, run `
33
33
 
34
34
  ## Planning/Execution Boundary
35
35
 
36
- Ralplan is planning only. It may inspect context and draft plan/spec/proposal artifacts, but those remain `pending approval` until explicit current-turn or structured-UI execution approval, or a valid non-off final receipt's runtime-owned `auto_handoff.effectiveTarget` admits the existing handoff chain. Before either admission, do not mutate product source, run mutation-oriented shell, commit, push, open PRs, invoke execution skills, or delegate implementation.
36
+ Ralplan is planning only. It may inspect context and draft plan/spec/proposal artifacts, but those remain `pending approval` until tagged structured-UI execution approval for the current final artifact, or a valid non-off final receipt's runtime-owned `auto_handoff.effectiveTarget` admits the existing handoff chain. Before either admission, do not mutate product source, run mutation-oriented shell, commit, push, open PRs, invoke execution skills, or delegate implementation.
37
37
 
38
- Except for a terminal `planning_stuck` final receipt, explicitly naming `ultragoal` (including `/skill:` and `gjc` forms) counts as opting into execution for that skill — do not re-ask for the same consent.
38
+ Explicitly naming `ultragoal` (including `/skill:` and `gjc` forms) selects the desired execution target; it does not replace structured approval for the current final artifact when `auto_handoff.effectiveTarget` is `off`. Never invent a direct approval record or infer execution consent from the skill name.
39
39
 
40
40
  Persist planning artifacts and handoffs through the ralplan CLI writer, never direct `.gjc/` edits:
41
41
  Direct `write`, `edit`, or `ast_edit` calls against `.gjc/_session-{sessionid}/specs`, `.gjc/_session-{sessionid}/plans`, `.gjc/_session-{sessionid}/state`, or any other `.gjc/` path are forbidden unless an explicit force override is active.
@@ -107,12 +107,14 @@ The consensus workflow:
107
107
  - For every confirmed open item, embed the resolved outcome into the final plan under an **## Intent Reconciliation** section so the `pending approval` artifact records each decision; record any item the user explicitly defers as an open confirmation under that same section.
108
108
  d. Persist the reconciliation with `gjc ralplan --write --worktree-root <repository_binding.worktreeRoot> --stage post-interview --stage_n <N> --artifact-env GJC_RALPLAN_ARTIFACT --json`, then return the receipt/path plus a compact status (reconciled-clean / reconciled-with-revision / open-confirmations-pending) instead of pasting the full body.
109
109
  7. On reconciliation completion, re-check the review join gate (Critic `OKAY` plus Architect `CLEAR`/`APPROVE` for the same Planner artifact/pass), mark the plan `pending approval` unless execution is already authorized by the resolved handoff admission, then persist the ADR/final plan via `gjc ralplan --write --worktree-root <repository_binding.worktreeRoot> --stage final --stage_n <N> --artifact-env GJC_RALPLAN_ARTIFACT --json`. Read the successful receipt's `auto_handoff` object; its ledger-backed `effectiveTarget` is runtime-owned and is the only automatic-routing decision; do not directly edit `.gjc/_session-{sessionid}/plans`. Final plan must include ADR (Decision, Drivers, Alternatives considered, Why chosen, Consequences, Follow-ups) and, when present, the **## Intent Reconciliation** section.
110
- 8. **Final admission and approval gate:** Reconciliation must first reach the successful final receipt from step 7. If that receipt has `auto_handoff.degradationReason: "planning_stuck"`, it is terminal: retain the `pending approval` artifact and **never dispatch**, including for an explicitly named execution skill; do not issue an approval `ask`. Otherwise, if its runtime-owned `auto_handoff.effectiveTarget` is `ultragoal`, that valid non-off receipt is explicit operator admission for same-turn execution through that target; proceed to step 9 without an `ask`. If it is `off`, including ordinary `off`, preserve the ordinary approval flow: if the user already explicitly named an execution skill in the current turn or via the structured approval UI (`ultragoal`, `/skill:ultragoal`, `gjc ultragoal`, or "Approve execution via ultragoal"), that is execution approval — skip the re-ask and proceed to step 9 with that skill. Otherwise, present the finalized plan via the `ask` tool (regardless of `--interactive`) with `workflowGate: { stage: "ralplan", kind: "approval" }` on the final question so RPC/headless clients receive a `ralplan`/`approval` workflow gate, not a deep-interview question gate. Use these options:
110
+ 8. **Final admission and approval gate:** Reconciliation must first reach the successful final receipt from step 7. If that receipt has `auto_handoff.degradationReason: "planning_stuck"`, it is terminal: retain the `pending approval` artifact and **never dispatch**, including for an explicitly named execution skill; do not issue an approval `ask`. Otherwise, if its runtime-owned `auto_handoff.effectiveTarget` is `ultragoal`, that valid non-off receipt is explicit operator admission for same-turn execution through that target; proceed to step 9 without an `ask`. If it is `off`, including ordinary `off`, require an accepted tagged structured approval for the current final artifact even if the user already named an execution skill. Unless that current final artifact already has that approval, present the finalized plan via the `ask` tool (regardless of `--interactive`) with `workflowGate: { stage: "ralplan", kind: "approval" }` on the final question so RPC/headless clients receive a `ralplan`/`approval` workflow gate, not a deep-interview question gate. Identify the current final receipt/path in the question. A revised final artifact requires a fresh structured approval; approval of a previous final artifact does not carry over. Use these options:
111
111
  - **Refine further** — re-run the consensus loop / request changes, then return here
112
112
  - **Approve execution via ultragoal (Recommended)** — goal-tracked autonomous execution
113
113
  - **Stop here** — keep the plan as `pending approval` and make no further changes
114
114
 
115
115
  Always include a free-text option for the ordinary `off` approval flow. Do not stop with plain text and no `ask` in that flow; its terminal action is this `ask`.
116
+
117
+ Example: a request to "plan this, then use `/skill:ultragoal`" still requires the tagged final approval `ask` after step 7 when the receipt resolves to `off`. Only an accepted **Approve execution via ultragoal** choice for that current final artifact admits step 9. Free text, refinement, cancellation, timeout, and **Stop here** do not authorize execution.
116
118
  9. On valid automatic admission or explicit approval, invoke the admitted/approved `/skill:ultragoal` target by default. On **Refine further**, return to the step 5 re-review loop. On **Stop here**, leave the `pending approval` artifact and stop. A `planning_stuck` final receipt never reaches this step. Never implement directly.
117
119
 
118
120
  Before invoking `/skill:ultragoal`, mark ralplan ready for handoff so the skill tool's chain guard permits the transition:
@@ -221,4 +223,4 @@ Gate auto-pass signals: file path, issue/PR number, camelCase/PascalCase/snake_c
221
223
  On consensus approval, choose:
222
224
  - **ultragoal**: goal-tracked autonomous execution with verification (recommended default)
223
225
 
224
- A redirected request proceeds only through the structured approval option or an explicit execution-skill choice; `just do it` / `skip planning` alone leaves the plan `pending approval`.
226
+ A redirected request proceeds only through the tagged structured approval for the current final artifact or a valid non-off final receipt's automatic admission; naming an execution skill or saying `just do it` / `skip planning` alone leaves the plan `pending approval`.
@@ -1,6 +1,6 @@
1
1
  import { describe, expect, test } from "bun:test";
2
2
  import { BundledDefaultContentError, readBundledContentSync } from "./gjc-defaults";
3
- import type { BundledGjcSkillCatalogEntry } from "./gjc-skills.generated";
3
+ import { BUNDLED_GJC_SKILL_CATALOG, type BundledGjcSkillCatalogEntry } from "./gjc-skills.generated";
4
4
 
5
5
  describe("bundled default content", () => {
6
6
  test("unreadable source throws a typed contextual error", () => {
@@ -20,4 +20,21 @@ describe("bundled default content", () => {
20
20
  expect((error as Error).message).toContain("Unable to read bundled GJC definition");
21
21
  }
22
22
  });
23
+
24
+ test("every catalog entry carries an embedded source path that matches its lazy import", async () => {
25
+ for (const entry of BUNDLED_GJC_SKILL_CATALOG) {
26
+ expect(entry.sourcePath, entry.relativePath).toBeString();
27
+ expect(readBundledContentSync(entry)).toBe(await entry.loadContent());
28
+ }
29
+ });
30
+
31
+ test("sync reads use the embedded source path, not import.meta.dir (compiled binaries, #6421)", () => {
32
+ const autoresearch = BUNDLED_GJC_SKILL_CATALOG.find(entry => entry.name === "autoresearch")!;
33
+ const entry = {
34
+ ...autoresearch,
35
+ relativePath: "skills/not-laid-out-under-import-meta-dir/SKILL.md",
36
+ } as BundledGjcSkillCatalogEntry;
37
+
38
+ expect(readBundledContentSync(entry)).toContain("name: autoresearch");
39
+ });
23
40
  });
@@ -104,6 +104,9 @@ export interface DefaultGjcDefinitionInstallResult {
104
104
  retired: RetiredGjcDefinitionFile[];
105
105
  }
106
106
  function sourcePathForBundledEntry(entry: BundledGjcSkillCatalogEntry): string {
107
+ // Prefer the embedded asset path: `import.meta.dir` is `/$bunfs/root` in a
108
+ // compiled binary, where the `gjc/` tree is not laid out as files.
109
+ if (entry.sourcePath) return entry.sourcePath;
107
110
  const relative = entry.kind === "skill" ? entry.relativePath : entry.relativePath.replace(/^skill-fragments\//, "");
108
111
  return entry.kind === "skill"
109
112
  ? path.join(import.meta.dir, "gjc", relative)