@gajae-code/coding-agent 0.11.10 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (249) hide show
  1. package/CHANGELOG.md +86 -2
  2. package/dist/types/cli/read-cli.d.ts +1 -0
  3. package/dist/types/cli.d.ts +8 -1
  4. package/dist/types/commands/deep-interview.d.ts +9 -0
  5. package/dist/types/commands/harness.d.ts +22 -0
  6. package/dist/types/commands/read.d.ts +6 -0
  7. package/dist/types/config/model-profile-activation.d.ts +1 -0
  8. package/dist/types/config/model-profile-contract.d.ts +2 -0
  9. package/dist/types/config/model-registry.d.ts +4 -0
  10. package/dist/types/config/provider-auth-health.d.ts +14 -0
  11. package/dist/types/config/provider-ranking.d.ts +59 -0
  12. package/dist/types/config/settings-schema.d.ts +86 -3
  13. package/dist/types/config/settings.d.ts +3 -0
  14. package/dist/types/extensibility/extensions/types.d.ts +43 -2
  15. package/dist/types/extensibility/shared-events.d.ts +6 -0
  16. package/dist/types/gjc-runtime/deep-interview-ambiguity.d.ts +5 -12
  17. package/dist/types/gjc-runtime/deep-interview-recorder.d.ts +17 -32
  18. package/dist/types/gjc-runtime/deep-interview-stage.d.ts +37 -0
  19. package/dist/types/gjc-runtime/deep-interview-state.d.ts +4 -135
  20. package/dist/types/gjc-runtime/gc-runtime.d.ts +1 -1
  21. package/dist/types/gjc-runtime/linux-proc.d.ts +22 -14
  22. package/dist/types/gjc-runtime/memory-guard-owner-claims.d.ts +47 -0
  23. package/dist/types/gjc-runtime/ralplan-runtime.d.ts +112 -1
  24. package/dist/types/gjc-runtime/state-runtime.d.ts +3 -1
  25. package/dist/types/gjc-runtime/state-writer.d.ts +5 -46
  26. package/dist/types/gjc-runtime/team-launch.d.ts +1 -1
  27. package/dist/types/gjc-runtime/team-runtime.d.ts +2 -1
  28. package/dist/types/gjc-runtime/team-store.d.ts +12 -0
  29. package/dist/types/gjc-runtime/team-worker-memory-guard.d.ts +92 -0
  30. package/dist/types/gjc-runtime/tmux-owner-isolation.d.ts +7 -0
  31. package/dist/types/gjc-runtime/ultragoal-receipt-freshness.d.ts +8 -0
  32. package/dist/types/gjc-runtime/workflow-manifest.d.ts +3 -5
  33. package/dist/types/internal-urls/local-root-gc.d.ts +2 -0
  34. package/dist/types/main.d.ts +1 -1
  35. package/dist/types/memories/index.d.ts +2 -0
  36. package/dist/types/modes/acp/acp-agent.d.ts +22 -9
  37. package/dist/types/modes/components/assistant-message.d.ts +3 -1
  38. package/dist/types/modes/components/irc-sidebar.d.ts +41 -0
  39. package/dist/types/modes/components/queue-pane.d.ts +8 -0
  40. package/dist/types/modes/components/queued-message-selector.d.ts +6 -0
  41. package/dist/types/modes/components/read-tool-group.d.ts +4 -4
  42. package/dist/types/modes/components/session-observer-overlay.d.ts +4 -0
  43. package/dist/types/modes/components/settings-selector.d.ts +2 -0
  44. package/dist/types/modes/components/tool-execution.d.ts +8 -0
  45. package/dist/types/modes/components/welcome.d.ts +1 -0
  46. package/dist/types/modes/controllers/event-controller.d.ts +3 -0
  47. package/dist/types/modes/interactive-mode.d.ts +7 -1
  48. package/dist/types/modes/irc-observation-ledger.d.ts +17 -1
  49. package/dist/types/modes/types.d.ts +2 -0
  50. package/dist/types/modes/utils/ui-helpers.d.ts +16 -0
  51. package/dist/types/runtime/memory-domain.d.ts +9 -0
  52. package/dist/types/runtime/memory-guard-contract.d.ts +71 -0
  53. package/dist/types/runtime/memory-guard.d.ts +39 -0
  54. package/dist/types/runtime/memory-limit.d.ts +11 -0
  55. package/dist/types/runtime-mcp/manager.d.ts +8 -0
  56. package/dist/types/runtime-mcp/smithery-auth.d.ts +5 -0
  57. package/dist/types/sdk/acp/final-text.d.ts +19 -0
  58. package/dist/types/sdk/acp/mcp.d.ts +23 -0
  59. package/dist/types/sdk/broker/lifecycle.d.ts +7 -0
  60. package/dist/types/sdk/bus/chat-daemon-control.d.ts +2 -1
  61. package/dist/types/sdk/bus/control-drain-lease.d.ts +52 -0
  62. package/dist/types/sdk/bus/index.d.ts +18 -2
  63. package/dist/types/sdk/bus/kind-aware-reconciliation.d.ts +37 -0
  64. package/dist/types/sdk/bus/prompt-reconciliation.d.ts +2 -1
  65. package/dist/types/sdk/bus/rate-limit-pool.d.ts +2 -0
  66. package/dist/types/sdk/bus/reconciliation-store.d.ts +65 -0
  67. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +6 -4
  68. package/dist/types/sdk/bus/telegram-daemon.d.ts +23 -3
  69. package/dist/types/sdk/host/control/operations.d.ts +2 -1
  70. package/dist/types/sdk/host/host.d.ts +2 -0
  71. package/dist/types/sdk/host/query/handlers.d.ts +5 -0
  72. package/dist/types/sdk/lifecycle-session.d.ts +10 -1
  73. package/dist/types/sdk/startup-capability.d.ts +6 -0
  74. package/dist/types/session/agent-session.d.ts +51 -19
  75. package/dist/types/session/fallback-chain-controller.d.ts +18 -2
  76. package/dist/types/session/internal/managed-session-scope.d.ts +27 -0
  77. package/dist/types/session/memory-guard-checkpoint-participant.d.ts +69 -0
  78. package/dist/types/session/session-manager.d.ts +59 -13
  79. package/dist/types/session/streaming-output.d.ts +60 -5
  80. package/dist/types/skill-state/active-state.d.ts +0 -4
  81. package/dist/types/skill-state/workflow-hud.d.ts +3 -0
  82. package/dist/types/task/executor.d.ts +6 -0
  83. package/dist/types/task/types.d.ts +36 -0
  84. package/dist/types/task/ultragoal-redteam-activation.d.ts +33 -0
  85. package/dist/types/tools/browser/launch.d.ts +7 -0
  86. package/dist/types/tools/fetch.d.ts +17 -1
  87. package/dist/types/tools/output-meta.d.ts +21 -1
  88. package/dist/types/tools/read-internals.d.ts +12 -0
  89. package/dist/types/tools/read.d.ts +45 -1
  90. package/dist/types/tools/resource-gc.d.ts +23 -0
  91. package/dist/types/tools/tool-result.d.ts +7 -1
  92. package/package.json +9 -13
  93. package/scripts/benchmark-sticky-viewport-pr1.ts +239 -0
  94. package/scripts/capture-sticky-viewport-showcase.ts +292 -0
  95. package/scripts/generate-sdk-operation-inventory.ts +4 -0
  96. package/scripts/run-test-manifest.ts +6 -4
  97. package/scripts/verify-gjc-sdk-canonicalization.ts +122 -18
  98. package/scripts/verify-sticky-viewport-showcase.ts +611 -0
  99. package/src/capability/index.ts +8 -0
  100. package/src/cli/args.ts +14 -8
  101. package/src/cli/fast-help.ts +1 -1
  102. package/src/cli/read-cli.ts +2 -1
  103. package/src/cli.ts +49 -2
  104. package/src/commands/deep-interview.ts +29 -9
  105. package/src/commands/harness.ts +35 -12
  106. package/src/commands/read.ts +11 -2
  107. package/src/commands/sdk.ts +91 -7
  108. package/src/commands/team.ts +1 -1
  109. package/src/config/model-profile-activation.ts +1 -0
  110. package/src/config/model-profile-contract.ts +13 -0
  111. package/src/config/model-profiles.ts +24 -0
  112. package/src/config/model-registry.ts +21 -2
  113. package/src/config/provider-auth-health.ts +42 -0
  114. package/src/config/provider-ranking.ts +119 -0
  115. package/src/config/settings-schema.ts +84 -3
  116. package/src/config/settings.ts +254 -108
  117. package/src/defaults/gjc/skills/deep-interview/SKILL.md +229 -82
  118. package/src/defaults/gjc/skills/ralplan/SKILL.md +78 -26
  119. package/src/defaults/gjc/skills/team/SKILL.md +1 -1
  120. package/src/defaults/gjc/skills/ultragoal/SKILL.md +26 -16
  121. package/src/eval/py/executor.ts +7 -2
  122. package/src/extensibility/extensions/runner.ts +4 -0
  123. package/src/extensibility/extensions/types.ts +42 -4
  124. package/src/extensibility/shared-events.ts +5 -0
  125. package/src/gjc-runtime/deep-interview-ambiguity.ts +47 -68
  126. package/src/gjc-runtime/deep-interview-recorder.ts +227 -310
  127. package/src/gjc-runtime/deep-interview-runtime.ts +109 -270
  128. package/src/gjc-runtime/deep-interview-stage.ts +1016 -0
  129. package/src/gjc-runtime/deep-interview-state.ts +12 -921
  130. package/src/gjc-runtime/gc-render.ts +1 -0
  131. package/src/gjc-runtime/gc-runtime.ts +11 -1
  132. package/src/gjc-runtime/linux-proc.ts +70 -36
  133. package/src/gjc-runtime/memory-guard-owner-claims.ts +389 -0
  134. package/src/gjc-runtime/ralplan-runtime.ts +979 -71
  135. package/src/gjc-runtime/state-runtime.ts +50 -12
  136. package/src/gjc-runtime/state-writer.ts +70 -222
  137. package/src/gjc-runtime/team-launch.ts +34 -5
  138. package/src/gjc-runtime/team-runtime.ts +970 -33
  139. package/src/gjc-runtime/team-store.ts +32 -0
  140. package/src/gjc-runtime/team-worker-memory-guard.ts +363 -0
  141. package/src/gjc-runtime/team-workers.ts +1 -0
  142. package/src/gjc-runtime/tmux-owner-isolation.ts +18 -0
  143. package/src/gjc-runtime/ultragoal-receipt-freshness.ts +20 -0
  144. package/src/gjc-runtime/ultragoal-runtime.ts +13 -7
  145. package/src/gjc-runtime/workflow-manifest.generated.json +97 -350
  146. package/src/gjc-runtime/workflow-manifest.ts +34 -179
  147. package/src/hooks/native-skill-hook.ts +17 -4
  148. package/src/hooks/skill-state.ts +1 -23
  149. package/src/internal-urls/docs-index.generated.ts +10 -11
  150. package/src/internal-urls/local-protocol.ts +23 -4
  151. package/src/internal-urls/local-root-gc.ts +127 -0
  152. package/src/main.ts +9 -5
  153. package/src/memories/index.ts +10 -0
  154. package/src/modes/DESIGN.md +47 -0
  155. package/src/modes/acp/acp-agent.ts +597 -67
  156. package/src/modes/acp/acp-event-mapper.ts +106 -12
  157. package/src/modes/acp/acp-mode.ts +39 -3
  158. package/src/modes/components/assistant-message.ts +123 -22
  159. package/src/modes/components/irc-sidebar.ts +176 -62
  160. package/src/modes/components/model-selector.ts +76 -5
  161. package/src/modes/components/notifications-settings-editor.ts +1 -1
  162. package/src/modes/components/oauth-selector.ts +42 -12
  163. package/src/modes/components/queue-pane.ts +55 -9
  164. package/src/modes/components/queued-message-selector.ts +53 -10
  165. package/src/modes/components/read-tool-group.ts +82 -14
  166. package/src/modes/components/session-observer-overlay.ts +187 -32
  167. package/src/modes/components/settings-selector.ts +60 -18
  168. package/src/modes/components/tool-execution.ts +138 -27
  169. package/src/modes/components/tool-status-header.ts +1 -4
  170. package/src/modes/components/welcome.ts +18 -3
  171. package/src/modes/controllers/command-controller.ts +4 -0
  172. package/src/modes/controllers/event-controller.ts +109 -27
  173. package/src/modes/controllers/extension-ui-controller.ts +23 -12
  174. package/src/modes/controllers/input-controller.ts +62 -6
  175. package/src/modes/controllers/selector-controller.ts +83 -37
  176. package/src/modes/interactive-mode.ts +127 -29
  177. package/src/modes/irc-observation-ledger.ts +71 -15
  178. package/src/modes/runtime-init.ts +20 -2
  179. package/src/modes/types.ts +2 -0
  180. package/src/modes/utils/ui-helpers.ts +94 -1
  181. package/src/prompts/agents/architect.md +9 -1
  182. package/src/prompts/agents/critic.md +9 -0
  183. package/src/prompts/agents/executor.md +1 -1
  184. package/src/prompts/system/system-prompt.md +0 -1
  185. package/src/prompts/tools/read.md +4 -2
  186. package/src/runtime/memory-domain.ts +66 -0
  187. package/src/runtime/memory-guard-contract.ts +73 -0
  188. package/src/runtime/memory-guard.ts +292 -0
  189. package/src/runtime/memory-limit.ts +50 -0
  190. package/src/runtime-mcp/manager.ts +26 -6
  191. package/src/runtime-mcp/smithery-auth.ts +17 -2
  192. package/src/runtime-mcp/smithery-connect.ts +11 -1
  193. package/src/sdk/acp/adapter.ts +8 -1
  194. package/src/sdk/acp/final-text.ts +40 -0
  195. package/src/sdk/acp/mcp.ts +26 -0
  196. package/src/sdk/broker/lifecycle.ts +107 -7
  197. package/src/sdk/bus/chat-daemon-cli.ts +2 -2
  198. package/src/sdk/bus/chat-daemon-control.ts +4 -3
  199. package/src/sdk/bus/config.ts +1 -1
  200. package/src/sdk/bus/control-drain-lease.ts +104 -0
  201. package/src/sdk/bus/index.ts +503 -60
  202. package/src/sdk/bus/kind-aware-reconciliation.ts +242 -0
  203. package/src/sdk/bus/prompt-reconciliation.ts +2 -1
  204. package/src/sdk/bus/rate-limit-pool.ts +8 -0
  205. package/src/sdk/bus/reconciliation-store.ts +224 -0
  206. package/src/sdk/bus/telegram-daemon-contract.ts +6 -4
  207. package/src/sdk/bus/telegram-daemon.ts +531 -53
  208. package/src/sdk/host/control/dispatch.ts +7 -1
  209. package/src/sdk/host/control/operations.ts +2 -1
  210. package/src/sdk/host/host.ts +25 -3
  211. package/src/sdk/host/query/handlers.ts +55 -0
  212. package/src/sdk/lifecycle-session.ts +19 -3
  213. package/src/sdk/mcp/server.ts +46 -18
  214. package/src/sdk/protocol/operation-inventory.generated.json +76 -0
  215. package/src/sdk/protocol/operation-registry.ts +8 -2
  216. package/src/sdk/session.ts +25 -2
  217. package/src/sdk/startup-capability.ts +6 -0
  218. package/src/session/agent-session.ts +720 -190
  219. package/src/session/fallback-chain-controller.ts +47 -8
  220. package/src/session/internal/managed-session-scope.ts +40 -10
  221. package/src/session/internal/native-publish-outcome.ts +8 -3
  222. package/src/session/memory-guard-checkpoint-participant.ts +131 -0
  223. package/src/session/session-manager.ts +1372 -42
  224. package/src/session/streaming-output.ts +262 -43
  225. package/src/setup/provider-onboarding.ts +19 -4
  226. package/src/skill-state/active-state.ts +0 -10
  227. package/src/skill-state/workflow-hud.ts +25 -2
  228. package/src/skill-state/workflow-mutation-guard.ts +65 -7
  229. package/src/task/executor.ts +11 -3
  230. package/src/task/index.ts +2 -0
  231. package/src/task/types.ts +22 -11
  232. package/src/task/ultragoal-redteam-activation.ts +75 -0
  233. package/src/tools/ask.ts +89 -69
  234. package/src/tools/browser/launch.ts +41 -6
  235. package/src/tools/fetch.ts +114 -23
  236. package/src/tools/output-meta.ts +176 -9
  237. package/src/tools/path-utils.ts +5 -1
  238. package/src/tools/read-internals.ts +44 -0
  239. package/src/tools/read.ts +1542 -310
  240. package/src/tools/resource-gc.ts +665 -125
  241. package/src/tools/tool-result.ts +14 -1
  242. package/src/web/search/providers/codex.ts +1 -1
  243. package/src/workflow/workflow-intent-diff.ts +4 -1
  244. package/dist/types/gjc-runtime/deep-interview-draft.d.ts +0 -8
  245. package/dist/types/gjc-runtime/deep-interview-payload.d.ts +0 -41
  246. package/dist/types/gjc-runtime/deep-interview-repair.d.ts +0 -17
  247. package/src/gjc-runtime/deep-interview-draft.ts +0 -843
  248. package/src/gjc-runtime/deep-interview-payload.ts +0 -262
  249. package/src/gjc-runtime/deep-interview-repair.ts +0 -1674
@@ -1,13 +1,12 @@
1
1
  import { createHash, randomBytes } from "node:crypto";
2
2
  import * as fs from "node:fs/promises";
3
- import * as os from "node:os";
4
3
  import * as path from "node:path";
4
+ import { getConfigRootDir } from "@gajae-code/utils";
5
5
  import { YAML } from "bun";
6
+ import { syncSkillActiveState } from "../skill-state/active-state";
7
+ import { deriveDeepInterviewHud } from "../skill-state/workflow-hud";
6
8
  import { WORKFLOW_STATE_VERSION } from "../skill-state/workflow-state-contract";
7
- import { scoreToUnits } from "./deep-interview-ambiguity";
8
- import { runDeepInterviewDraftCommand } from "./deep-interview-draft";
9
- import { runDeepInterviewPostCommitEffects } from "./deep-interview-recorder";
10
- import { isDeepInterviewRepairVerb, runDeepInterviewRepairCommand } from "./deep-interview-repair";
9
+ import { isDeepInterviewStageVerb, runDeepInterviewStageCommand } from "./deep-interview-stage";
11
10
  import {
12
11
  assertDeepInterviewInputWithinLimit,
13
12
  assertDeepInterviewIntentReview,
@@ -19,20 +18,12 @@ import {
19
18
  MAX_INITIAL_CONTEXT_LENGTH,
20
19
  normalizeDeepInterviewEnvelope,
21
20
  reviewDeepInterviewIntent,
22
- validateDeepInterviewV1Envelope,
23
21
  } from "./deep-interview-state";
24
22
  import { runNativeRalplanCommand } from "./ralplan-runtime";
25
23
  import { modeStatePath, sessionSpecsDir } from "./session-layout";
26
- import { resolveGjcSessionForWrite } from "./session-resolution";
24
+ import { resolveGjcSessionForWrite, writeSessionActivityMarker } from "./session-resolution";
27
25
  import { runNativeStateCommand } from "./state-runtime";
28
- import {
29
- appendJsonl,
30
- readExistingStateForMutation,
31
- verifyWorkflowEnvelopeReceiptValue,
32
- withWorkflowStateLock,
33
- writeArtifact,
34
- writeWorkflowEnvelopeAtomic,
35
- } from "./state-writer";
26
+ import { appendJsonl, readExistingStateForMutation, writeArtifact, writeWorkflowEnvelopeAtomic } from "./state-writer";
36
27
  import { assertSafePathComponent, CommandError, flagValue, hasFlag } from "./workflow-cli-common";
37
28
 
38
29
  export * from "./deep-interview-recorder";
@@ -364,7 +355,7 @@ async function readSettingsAmbiguityThreshold(
364
355
  } catch (error) {
365
356
  const err = error as NodeJS.ErrnoException;
366
357
  if (err.code === "ENOENT") return undefined;
367
- throw new Error(`failed to read deep-interview threshold config ${settingsPath}: ${err.message}`);
358
+ return undefined;
368
359
  }
369
360
  let parsed: unknown;
370
361
  try {
@@ -374,7 +365,7 @@ async function readSettingsAmbiguityThreshold(
374
365
  }
375
366
  const candidate = (parsed as { gjc?: { deepInterview?: { ambiguityThreshold?: unknown } } })?.gjc?.deepInterview
376
367
  ?.ambiguityThreshold;
377
- if (typeof candidate !== "number" || !isIntegralScore(candidate) || candidate <= 0) {
368
+ if (typeof candidate !== "number" || !Number.isFinite(candidate) || candidate <= 0 || candidate > 1) {
378
369
  return undefined;
379
370
  }
380
371
  return { threshold: candidate, source: settingsPath };
@@ -383,30 +374,21 @@ async function readSettingsAmbiguityThreshold(
383
374
  function modernSettingsPath(): string {
384
375
  const configDir = process.env.GJC_CODING_AGENT_DIR?.trim() || process.env.PI_CODING_AGENT_DIR?.trim();
385
376
  if (configDir) return path.join(configDir, "config.yml");
386
- const configRoot = process.env.GJC_CONFIG_DIR?.trim() || process.env.PI_CONFIG_DIR?.trim();
387
- if (configRoot) return path.join(configRoot, "agent", "config.yml");
388
- return path.join(os.homedir(), ".gjc", "agent", "config.yml");
377
+ return path.join(getConfigRootDir(), "agent", "config.yml");
389
378
  }
390
379
 
391
380
  async function readModernSettingsAmbiguityThreshold(): Promise<{ threshold: number; source: string } | undefined> {
392
381
  const modernConfigPath = modernSettingsPath();
393
- let raw: string;
394
- try {
395
- raw = await fs.readFile(modernConfigPath, "utf-8");
396
- } catch (error) {
397
- const err = error as NodeJS.ErrnoException;
398
- if (err.code === "ENOENT") return undefined;
399
- throw new Error(`failed to read deep-interview threshold config ${modernConfigPath}: ${err.message}`);
400
- }
401
382
  let parsed: unknown;
402
383
  try {
403
- parsed = YAML.parse(raw);
384
+ parsed = YAML.parse(await fs.readFile(modernConfigPath, "utf-8"));
404
385
  } catch {
405
386
  return undefined;
406
387
  }
407
388
  const candidate = (parsed as { gjc?: { deepInterview?: { ambiguityThreshold?: unknown } } })?.gjc?.deepInterview
408
389
  ?.ambiguityThreshold;
409
- if (typeof candidate !== "number" || !isIntegralScore(candidate) || candidate <= 0) return undefined;
390
+ if (typeof candidate !== "number" || !Number.isFinite(candidate) || candidate <= 0 || candidate > 1)
391
+ return undefined;
410
392
  return { threshold: candidate, source: modernConfigPath };
411
393
  }
412
394
 
@@ -418,8 +400,7 @@ async function resolveConfiguredAmbiguityThreshold(
418
400
  const projectSettings = path.join(cwd, ".gjc", "settings.json");
419
401
  const projectValue = await readSettingsAmbiguityThreshold(projectSettings);
420
402
  if (projectValue) return projectValue;
421
- const configDir = process.env.GJC_CONFIG_DIR?.trim() || path.join(os.homedir(), ".gjc");
422
- const userSettings = path.join(configDir, "settings.json");
403
+ const userSettings = path.join(getConfigRootDir(), "settings.json");
423
404
  return await readSettingsAmbiguityThreshold(userSettings);
424
405
  }
425
406
 
@@ -521,15 +502,6 @@ async function resolveSpecWriteArgs(args: readonly string[], cwd: string): Promi
521
502
  };
522
503
  }
523
504
 
524
- function isIntegralScore(value: number): boolean {
525
- try {
526
- scoreToUnits(value);
527
- return true;
528
- } catch {
529
- return false;
530
- }
531
- }
532
-
533
505
  async function resolveDeepInterviewArgs(args: readonly string[], cwd: string): Promise<ResolvedDeepInterviewArgs> {
534
506
  const session = resolveGjcSessionForWrite(cwd, {
535
507
  flagValue: flagValue(args, "--session-id"),
@@ -550,10 +522,10 @@ async function resolveDeepInterviewArgs(args: readonly string[], cwd: string): P
550
522
  const thresholdOverride = flagValue(args, "--threshold");
551
523
  if (thresholdOverride !== undefined) {
552
524
  const parsed = Number(thresholdOverride);
553
- if (!isIntegralScore(parsed) || parsed <= 0) {
525
+ if (!Number.isFinite(parsed) || parsed <= 0 || parsed > 1) {
554
526
  throw new DeepInterviewCommandError(
555
527
  2,
556
- `invalid --threshold: ${thresholdOverride}. Expected integral 1e-4 units in (0, 1].`,
528
+ `invalid --threshold: ${thresholdOverride}. Expected 0 < threshold <= 1.`,
557
529
  );
558
530
  }
559
531
  threshold = parsed;
@@ -571,16 +543,7 @@ async function resolveDeepInterviewArgs(args: readonly string[], cwd: string): P
571
543
 
572
544
  const ideaParts: string[] = [];
573
545
  let skipNext = false;
574
- let positionalOnly = false;
575
546
  for (const arg of args) {
576
- if (positionalOnly) {
577
- ideaParts.push(arg);
578
- continue;
579
- }
580
- if (arg === "--") {
581
- positionalOnly = true;
582
- continue;
583
- }
584
547
  if (skipNext) {
585
548
  skipNext = false;
586
549
  continue;
@@ -754,13 +717,13 @@ export async function persistDeepInterviewSpec(
754
717
  forced: resolved.force,
755
718
  },
756
719
  });
757
- await runDeepInterviewPostCommitEffects({
720
+ await writeSessionActivityMarker(cwd, resolved.sessionId, { writer: "deep-interview-runtime", path: statePath });
721
+ await syncDeepInterviewHud({
758
722
  cwd,
759
- statePath,
760
- sessionId: resolved.sessionId ?? "",
761
- envelope: normalizeDeepInterviewEnvelope(payload),
762
- revision: 0,
763
- writer: "deep-interview-runtime",
723
+ sessionId: resolved.sessionId,
724
+ payload,
725
+ phase: "handoff",
726
+ specStatus: "persisted",
764
727
  });
765
728
 
766
729
  return {
@@ -773,169 +736,91 @@ export async function persistDeepInterviewSpec(
773
736
  };
774
737
  }
775
738
 
776
- function isEmptyPendingTopology(value: unknown): boolean {
777
- if (!value || typeof value !== "object" || Array.isArray(value)) return false;
778
- const topology = value as Record<string, unknown>;
779
- return (
780
- topology.status === "pending" &&
781
- Array.isArray(topology.components) &&
782
- topology.components.length === 0 &&
783
- Array.isArray(topology.deferred_components) &&
784
- topology.deferred_components.length === 0
785
- );
786
- }
787
- function isUnresolvedNativeSetup(value: unknown): boolean {
788
- if (!value || typeof value !== "object" || Array.isArray(value)) return false;
789
- const state = value as Record<string, unknown>;
790
- return (
791
- state.setup !== null &&
792
- typeof state.setup === "object" &&
793
- !Array.isArray(state.setup) &&
794
- (state.setup as Record<string, unknown>).status === "unresolved"
795
- );
796
- }
797
- async function seedDeepInterviewState(
798
- cwd: string,
799
- resolved: ResolvedDeepInterviewArgs,
800
- ): Promise<{ statePath: string; warnings: unknown[] }> {
739
+ async function seedDeepInterviewState(cwd: string, resolved: ResolvedDeepInterviewArgs): Promise<string> {
801
740
  const statePath = deepInterviewStatePath(cwd, resolved.sessionId);
802
- return withWorkflowStateLock(
803
- `${statePath}.kickoff`,
804
- async () => {
805
- const existing = await readExistingStateForMutation(statePath);
806
- if (existing.kind === "valid") {
807
- try {
808
- if (verifyWorkflowEnvelopeReceiptValue(existing.value, statePath) !== "native-valid")
809
- throw new Error("invalid receipt");
810
- validateDeepInterviewV1Envelope(existing.value);
811
- } catch {
812
- throw new DeepInterviewCommandError(3, "DI_STATE_CORRUPT");
813
- }
814
- const phase =
815
- typeof existing.value.current_phase === "string" ? existing.value.current_phase : "interviewing";
816
- if (phase === "complete" || phase === "handoff" || existing.value.active === false)
817
- throw new DeepInterviewCommandError(3, "DI_PHASE_NOT_REPAIRABLE");
818
- const priorState =
819
- existing.value.state && typeof existing.value.state === "object" && !Array.isArray(existing.value.state)
820
- ? (existing.value.state as Record<string, unknown>)
821
- : {};
822
- const exactEmptyNativeSeed =
823
- isUnresolvedNativeSetup(priorState) &&
824
- priorState.type === (resolved.trace ? "brownfield" : "greenfield") &&
825
- existing.value.skill === "deep-interview" &&
826
- existing.value.active === true &&
827
- phase === "interviewing" &&
828
- existing.value.resolution === resolved.resolution &&
829
- existing.value.threshold === resolved.threshold &&
830
- existing.value.threshold_source === resolved.thresholdSource &&
831
- priorState.initial_idea === resolved.idea &&
832
- priorState.intent_contract_required === true &&
833
- Array.isArray(priorState.rounds) &&
834
- priorState.rounds.length === 0 &&
835
- Array.isArray(priorState.established_facts) &&
836
- priorState.established_facts.length === 0 &&
837
- Array.isArray(priorState.ontology_snapshots) &&
838
- priorState.ontology_snapshots.length === 0 &&
839
- Array.isArray(priorState.auto_researched_rounds) &&
840
- priorState.auto_researched_rounds.length === 0 &&
841
- Array.isArray(priorState.auto_answered_rounds) &&
842
- priorState.auto_answered_rounds.length === 0 &&
843
- isEmptyPendingTopology(priorState.topology) &&
844
- priorState.architect_failures === 0 &&
845
- priorState.current_ambiguity === 1 &&
846
- JSON.stringify(existing.value.trace) === JSON.stringify(resolved.trace) &&
847
- JSON.stringify(existing.value.language) === JSON.stringify(resolved.language);
848
- if (exactEmptyNativeSeed) return { statePath, warnings: [] };
849
- throw new DeepInterviewCommandError(2, "DI_INTERVIEW_ALREADY_ACTIVE");
850
- }
851
- if (existing.kind === "corrupt") throw new DeepInterviewCommandError(3, "DI_STATE_CORRUPT");
852
- const now = new Date().toISOString();
853
- const type = resolved.trace ? "brownfield" : "greenfield";
854
- const payload: Record<string, unknown> = {
855
- active: true,
856
- current_phase: "interviewing",
857
- schema_version: 1,
858
- skill: "deep-interview",
859
- version: WORKFLOW_STATE_VERSION,
860
- resolution: resolved.resolution,
861
- threshold: resolved.threshold,
862
- threshold_units: scoreToUnits(resolved.threshold),
863
- threshold_source: resolved.thresholdSource,
864
- state: {
865
- setup: { status: "unresolved" },
866
- type,
867
- initial_idea: resolved.idea,
868
- intent_contract_required: true,
869
- rounds: [],
870
- established_facts: [],
871
- topology: { status: "pending", components: [], deferred_components: [] },
872
- ontology_snapshots: [],
873
- auto_researched_rounds: [],
874
- auto_answered_rounds: [],
875
- architect_failures: 0,
876
- current_ambiguity: 1.0,
877
- threshold: resolved.threshold,
878
- threshold_units: scoreToUnits(resolved.threshold),
879
- threshold_source: resolved.thresholdSource,
880
- },
881
- updated_at: now,
882
- };
883
- validateDeepInterviewV1Envelope(payload);
884
- if (resolved.trace) {
885
- payload.trace = resolved.trace;
886
- (payload.state as Record<string, unknown>).trace = resolved.trace;
887
- (payload.state as Record<string, unknown>).trace_summary = resolved.trace;
888
- (payload.state as Record<string, unknown>).codebase_context = {
889
- source: "trace",
890
- summary: resolved.trace.findings,
891
- relevant_paths: resolved.trace.relevant_paths,
892
- project_hints: resolved.trace.project_hints,
893
- };
894
- }
895
- if (resolved.language) {
896
- payload.language = resolved.language;
897
- (payload.state as Record<string, unknown>).language = resolved.language;
898
- }
899
- if (resolved.sessionId) payload.session_id = resolved.sessionId;
900
- await writeWorkflowEnvelopeAtomic(statePath, payload, {
901
- cwd,
902
- receipt: {
903
- cwd,
904
- skill: "deep-interview",
905
- owner: "gjc-runtime",
906
- command: "gjc deep-interview seed",
907
- sessionId: resolved.sessionId,
908
- nowIso: now,
909
- },
910
- audit: {
911
- category: "state",
912
- verb: "write",
913
- owner: "gjc-runtime",
914
- skill: "deep-interview",
915
- sessionId: resolved.sessionId,
916
- },
917
- });
918
- const stamped = await readExistingStateForMutation(statePath);
919
- if (stamped.kind !== "valid") throw new DeepInterviewCommandError(3, "DI_STATE_CORRUPT");
920
- try {
921
- if (verifyWorkflowEnvelopeReceiptValue(stamped.value, statePath) !== "native-valid")
922
- throw new Error("invalid receipt");
923
- validateDeepInterviewV1Envelope(stamped.value);
924
- } catch {
925
- throw new DeepInterviewCommandError(3, "DI_STATE_CORRUPT");
926
- }
927
- const warnings = await runDeepInterviewPostCommitEffects({
928
- cwd,
929
- statePath,
930
- sessionId: resolved.sessionId ?? "",
931
- envelope: normalizeDeepInterviewEnvelope(stamped.value),
932
- revision: typeof stamped.value.state_revision === "number" ? stamped.value.state_revision : 0,
933
- writer: "deep-interview-runtime",
934
- });
935
- return { statePath, warnings };
741
+ assertDeepInterviewInputWithinLimit(resolved.idea, MAX_INITIAL_CONTEXT_LENGTH, "initial_idea");
742
+ const now = new Date().toISOString();
743
+ const payload: Record<string, unknown> = {
744
+ active: true,
745
+ current_phase: "interviewing",
746
+ skill: "deep-interview",
747
+ version: WORKFLOW_STATE_VERSION,
748
+ resolution: resolved.resolution,
749
+ threshold: resolved.threshold,
750
+ threshold_source: resolved.thresholdSource,
751
+ state: {
752
+ initial_idea: resolved.idea,
753
+ intent_contract_required: true,
754
+ rounds: [],
755
+ established_facts: [],
756
+ current_ambiguity: 1.0,
757
+ threshold: resolved.threshold,
758
+ threshold_source: resolved.thresholdSource,
936
759
  },
937
- { cwd },
938
- );
760
+ updated_at: now,
761
+ };
762
+ if (resolved.trace) {
763
+ payload.trace = resolved.trace;
764
+ (payload.state as Record<string, unknown>).trace = resolved.trace;
765
+ (payload.state as Record<string, unknown>).trace_summary = resolved.trace;
766
+ (payload.state as Record<string, unknown>).codebase_context = {
767
+ source: "trace",
768
+ summary: resolved.trace.findings,
769
+ relevant_paths: resolved.trace.relevant_paths,
770
+ project_hints: resolved.trace.project_hints,
771
+ };
772
+ }
773
+ if (resolved.language) {
774
+ payload.language = resolved.language;
775
+ (payload.state as Record<string, unknown>).language = resolved.language;
776
+ }
777
+ if (resolved.sessionId) payload.session_id = resolved.sessionId;
778
+ await writeWorkflowEnvelopeAtomic(statePath, payload, {
779
+ cwd,
780
+ receipt: {
781
+ cwd,
782
+ skill: "deep-interview",
783
+ owner: "gjc-runtime",
784
+ command: "gjc deep-interview seed",
785
+ sessionId: resolved.sessionId,
786
+ nowIso: now,
787
+ },
788
+ audit: {
789
+ category: "state",
790
+ verb: "write",
791
+ owner: "gjc-runtime",
792
+ skill: "deep-interview",
793
+ sessionId: resolved.sessionId,
794
+ },
795
+ });
796
+ await writeSessionActivityMarker(cwd, resolved.sessionId, { writer: "deep-interview-runtime", path: statePath });
797
+ await syncDeepInterviewHud({ cwd, sessionId: resolved.sessionId, payload, phase: "interviewing" });
798
+ return statePath;
799
+ }
800
+
801
+ async function syncDeepInterviewHud(options: {
802
+ cwd: string;
803
+ sessionId?: string;
804
+ payload: Record<string, unknown>;
805
+ phase?: string;
806
+ specStatus?: string;
807
+ }): Promise<void> {
808
+ try {
809
+ const phase =
810
+ options.phase ??
811
+ (typeof options.payload.current_phase === "string" ? options.payload.current_phase : "interviewing");
812
+ await syncSkillActiveState({
813
+ cwd: options.cwd,
814
+ skill: "deep-interview",
815
+ active: phase !== "complete",
816
+ phase,
817
+ sessionId: options.sessionId,
818
+ source: "gjc-deep-interview-native",
819
+ hud: deriveDeepInterviewHud(options.payload, { phase, specStatus: options.specStatus }),
820
+ });
821
+ } catch {
822
+ // HUD sync is best-effort and must not change command semantics.
823
+ }
939
824
  }
940
825
 
941
826
  async function handleSpecWrite(args: readonly string[], cwd: string): Promise<DeepInterviewCommandResult> {
@@ -1001,68 +886,23 @@ async function handleSpecWrite(args: readonly string[], cwd: string): Promise<De
1001
886
  .join("\n");
1002
887
  return { status: 0, stdout };
1003
888
  }
1004
- function isDeepInterviewRepairInvocation(args: readonly string[]): boolean {
1005
- const separator = args.indexOf("--");
1006
- return (separator === -1 || separator > 0) && isDeepInterviewRepairVerb(args[0] ?? "");
1007
- }
1008
- function isDeepInterviewDraftInvocation(args: readonly string[]): boolean {
1009
- const separator = args.indexOf("--");
1010
- return (separator === -1 || separator > 0) && args[0] === "draft";
1011
- }
1012
- function draftCommandArgs(args: readonly string[]): string[] {
1013
- const normalized: string[] = [];
1014
- for (let index = 1; index < args.length; index++) {
1015
- const argument = args[index];
1016
- if (argument === "--for") {
1017
- normalized.push("--kind", args[++index] ?? "");
1018
- continue;
1019
- }
1020
- normalized.push(argument);
1021
- if (argument === "--json" && !args[index + 1]?.startsWith("--")) continue;
1022
- if (argument === "--json") normalized.push("true");
1023
- }
1024
- return normalized;
1025
- }
1026
889
 
1027
890
  export async function runNativeDeepInterviewCommand(
1028
891
  args: string[],
1029
892
  cwd = process.cwd(),
1030
893
  ): Promise<DeepInterviewCommandResult> {
1031
894
  try {
895
+ const [firstArg, ...restArgs] = args;
896
+ if (isDeepInterviewStageVerb(firstArg)) return await runDeepInterviewStageCommand(firstArg, restArgs, cwd);
1032
897
  if (isDeepInterviewSpecWriteInvocation(args)) return await handleSpecWrite(args, cwd);
1033
- if (isDeepInterviewRepairInvocation(args)) return await runDeepInterviewRepairCommand(args, cwd);
1034
- if (isDeepInterviewDraftInvocation(args)) return await runDeepInterviewDraftCommand(draftCommandArgs(args), cwd);
1035
898
  const resolved = await resolveDeepInterviewArgs(args, cwd);
1036
899
  if (!resolved.idea) {
1037
- const existing = await readExistingStateForMutation(deepInterviewStatePath(cwd, resolved.sessionId));
1038
- if (existing.kind === "valid") {
1039
- const phase =
1040
- typeof existing.value.current_phase === "string" ? existing.value.current_phase : "interviewing";
1041
- if (phase === "complete" || existing.value.active === false)
1042
- throw new DeepInterviewCommandError(
1043
- 2,
1044
- "deep-interview session is terminal; start a new session to kick off another interview.",
1045
- );
1046
- const state = existing.value.state as Record<string, unknown> | undefined;
1047
- return {
1048
- status: 0,
1049
- stdout: `${JSON.stringify({
1050
- skill: "deep-interview",
1051
- resumed: true,
1052
- session_id: resolved.sessionId ?? null,
1053
- state_path: deepInterviewStatePath(cwd, resolved.sessionId),
1054
- state_revision: existing.value.state_revision ?? 0,
1055
- idea: typeof state?.initial_idea === "string" ? state.initial_idea : null,
1056
- handoff: "/skill:deep-interview",
1057
- })}\n`,
1058
- };
1059
- }
1060
900
  throw new DeepInterviewCommandError(
1061
901
  2,
1062
902
  'gjc deep-interview requires an idea, e.g. `gjc deep-interview "<idea>"`.',
1063
903
  );
1064
904
  }
1065
- const seeded = await seedDeepInterviewState(cwd, resolved);
905
+ const statePath = await seedDeepInterviewState(cwd, resolved);
1066
906
 
1067
907
  const summary = {
1068
908
  skill: "deep-interview",
@@ -1072,14 +912,13 @@ export async function runNativeDeepInterviewCommand(
1072
912
  idea: resolved.idea,
1073
913
  language: resolved.language,
1074
914
  trace: resolved.trace,
1075
- state_path: seeded.statePath,
1076
- warnings: seeded.warnings,
915
+ state_path: statePath,
1077
916
  handoff: "/skill:deep-interview",
1078
917
  };
1079
918
  const stdout = resolved.json
1080
919
  ? `${JSON.stringify(summary)}\n`
1081
920
  : [
1082
- `deep-interview seed state_path=${seeded.statePath}`,
921
+ `deep-interview seed state_path=${statePath}`,
1083
922
  `resolution=${resolved.resolution} threshold=${resolved.threshold} threshold_source=${resolved.thresholdSource}`,
1084
923
  resolved.trace ? `trace=enabled bounded_paths=${resolved.trace.relevant_paths.length}` : undefined,
1085
924
  "handoff=/skill:deep-interview",