@gajae-code/coding-agent 0.11.11 → 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 (182) hide show
  1. package/CHANGELOG.md +49 -3
  2. package/dist/types/cli/read-cli.d.ts +1 -0
  3. package/dist/types/commands/deep-interview.d.ts +9 -0
  4. package/dist/types/commands/harness.d.ts +22 -0
  5. package/dist/types/commands/read.d.ts +6 -0
  6. package/dist/types/config/model-registry.d.ts +4 -0
  7. package/dist/types/config/provider-auth-health.d.ts +14 -0
  8. package/dist/types/config/provider-ranking.d.ts +59 -0
  9. package/dist/types/config/settings-schema.d.ts +29 -1
  10. package/dist/types/config/settings.d.ts +2 -0
  11. package/dist/types/extensibility/extensions/types.d.ts +22 -2
  12. package/dist/types/extensibility/shared-events.d.ts +6 -0
  13. package/dist/types/gjc-runtime/deep-interview-ambiguity.d.ts +5 -12
  14. package/dist/types/gjc-runtime/deep-interview-recorder.d.ts +17 -32
  15. package/dist/types/gjc-runtime/deep-interview-stage.d.ts +37 -0
  16. package/dist/types/gjc-runtime/deep-interview-state.d.ts +4 -135
  17. package/dist/types/gjc-runtime/gc-runtime.d.ts +1 -1
  18. package/dist/types/gjc-runtime/memory-guard-owner-claims.d.ts +47 -0
  19. package/dist/types/gjc-runtime/ralplan-runtime.d.ts +52 -1
  20. package/dist/types/gjc-runtime/state-writer.d.ts +5 -46
  21. package/dist/types/gjc-runtime/team-launch.d.ts +1 -1
  22. package/dist/types/gjc-runtime/team-runtime.d.ts +2 -1
  23. package/dist/types/gjc-runtime/team-store.d.ts +12 -0
  24. package/dist/types/gjc-runtime/team-worker-memory-guard.d.ts +92 -0
  25. package/dist/types/gjc-runtime/tmux-owner-isolation.d.ts +7 -0
  26. package/dist/types/gjc-runtime/ultragoal-receipt-freshness.d.ts +8 -0
  27. package/dist/types/gjc-runtime/workflow-manifest.d.ts +3 -5
  28. package/dist/types/internal-urls/local-root-gc.d.ts +2 -0
  29. package/dist/types/main.d.ts +1 -1
  30. package/dist/types/memories/index.d.ts +2 -0
  31. package/dist/types/modes/acp/acp-agent.d.ts +8 -0
  32. package/dist/types/modes/components/assistant-message.d.ts +3 -1
  33. package/dist/types/modes/components/irc-sidebar.d.ts +41 -0
  34. package/dist/types/modes/components/read-tool-group.d.ts +4 -4
  35. package/dist/types/modes/components/session-observer-overlay.d.ts +4 -0
  36. package/dist/types/modes/components/settings-selector.d.ts +2 -0
  37. package/dist/types/modes/components/tool-execution.d.ts +8 -0
  38. package/dist/types/modes/controllers/event-controller.d.ts +3 -0
  39. package/dist/types/modes/interactive-mode.d.ts +2 -0
  40. package/dist/types/modes/irc-observation-ledger.d.ts +17 -1
  41. package/dist/types/modes/types.d.ts +2 -0
  42. package/dist/types/modes/utils/ui-helpers.d.ts +16 -0
  43. package/dist/types/runtime-mcp/smithery-auth.d.ts +5 -0
  44. package/dist/types/sdk/broker/lifecycle.d.ts +5 -0
  45. package/dist/types/sdk/bus/control-drain-lease.d.ts +52 -0
  46. package/dist/types/sdk/bus/index.d.ts +15 -1
  47. package/dist/types/sdk/bus/kind-aware-reconciliation.d.ts +37 -0
  48. package/dist/types/sdk/bus/prompt-reconciliation.d.ts +2 -1
  49. package/dist/types/sdk/bus/reconciliation-store.d.ts +65 -0
  50. package/dist/types/sdk/host/control/operations.d.ts +1 -1
  51. package/dist/types/sdk/host/host.d.ts +2 -0
  52. package/dist/types/sdk/host/query/handlers.d.ts +5 -0
  53. package/dist/types/session/agent-session.d.ts +44 -10
  54. package/dist/types/session/memory-guard-checkpoint-participant.d.ts +69 -0
  55. package/dist/types/session/session-manager.d.ts +25 -13
  56. package/dist/types/session/streaming-output.d.ts +60 -5
  57. package/dist/types/skill-state/active-state.d.ts +0 -4
  58. package/dist/types/skill-state/workflow-hud.d.ts +3 -0
  59. package/dist/types/tools/browser/launch.d.ts +7 -0
  60. package/dist/types/tools/fetch.d.ts +17 -1
  61. package/dist/types/tools/output-meta.d.ts +21 -1
  62. package/dist/types/tools/read-internals.d.ts +12 -0
  63. package/dist/types/tools/read.d.ts +45 -1
  64. package/dist/types/tools/resource-gc.d.ts +4 -0
  65. package/dist/types/tools/tool-result.d.ts +7 -1
  66. package/package.json +9 -13
  67. package/scripts/benchmark-sticky-viewport-pr1.ts +239 -0
  68. package/scripts/capture-sticky-viewport-showcase.ts +292 -0
  69. package/scripts/generate-sdk-operation-inventory.ts +2 -0
  70. package/scripts/verify-gjc-sdk-canonicalization.ts +122 -18
  71. package/scripts/verify-sticky-viewport-showcase.ts +611 -0
  72. package/src/capability/index.ts +8 -0
  73. package/src/cli/read-cli.ts +2 -1
  74. package/src/cli.ts +1 -0
  75. package/src/commands/deep-interview.ts +29 -9
  76. package/src/commands/harness.ts +35 -12
  77. package/src/commands/read.ts +11 -2
  78. package/src/commands/team.ts +1 -1
  79. package/src/config/model-registry.ts +21 -2
  80. package/src/config/provider-auth-health.ts +42 -0
  81. package/src/config/provider-ranking.ts +119 -0
  82. package/src/config/settings-schema.ts +23 -1
  83. package/src/config/settings.ts +246 -108
  84. package/src/defaults/gjc/skills/deep-interview/SKILL.md +229 -82
  85. package/src/defaults/gjc/skills/ralplan/SKILL.md +58 -25
  86. package/src/defaults/gjc/skills/team/SKILL.md +1 -1
  87. package/src/defaults/gjc/skills/ultragoal/SKILL.md +25 -15
  88. package/src/eval/py/executor.ts +7 -2
  89. package/src/extensibility/extensions/types.ts +28 -4
  90. package/src/extensibility/shared-events.ts +5 -0
  91. package/src/gjc-runtime/deep-interview-ambiguity.ts +47 -82
  92. package/src/gjc-runtime/deep-interview-recorder.ts +227 -310
  93. package/src/gjc-runtime/deep-interview-runtime.ts +109 -270
  94. package/src/gjc-runtime/deep-interview-stage.ts +1016 -0
  95. package/src/gjc-runtime/deep-interview-state.ts +12 -943
  96. package/src/gjc-runtime/gc-render.ts +1 -0
  97. package/src/gjc-runtime/gc-runtime.ts +11 -1
  98. package/src/gjc-runtime/memory-guard-owner-claims.ts +389 -0
  99. package/src/gjc-runtime/ralplan-runtime.ts +742 -85
  100. package/src/gjc-runtime/state-runtime.ts +2 -1
  101. package/src/gjc-runtime/state-writer.ts +70 -222
  102. package/src/gjc-runtime/team-launch.ts +34 -5
  103. package/src/gjc-runtime/team-runtime.ts +970 -33
  104. package/src/gjc-runtime/team-store.ts +32 -0
  105. package/src/gjc-runtime/team-worker-memory-guard.ts +363 -0
  106. package/src/gjc-runtime/team-workers.ts +1 -0
  107. package/src/gjc-runtime/tmux-owner-isolation.ts +18 -0
  108. package/src/gjc-runtime/ultragoal-receipt-freshness.ts +20 -0
  109. package/src/gjc-runtime/ultragoal-runtime.ts +13 -7
  110. package/src/gjc-runtime/workflow-manifest.generated.json +97 -350
  111. package/src/gjc-runtime/workflow-manifest.ts +34 -179
  112. package/src/hooks/native-skill-hook.ts +17 -4
  113. package/src/hooks/skill-state.ts +1 -23
  114. package/src/internal-urls/docs-index.generated.ts +8 -9
  115. package/src/internal-urls/local-root-gc.ts +127 -0
  116. package/src/main.ts +9 -5
  117. package/src/memories/index.ts +10 -0
  118. package/src/modes/DESIGN.md +47 -0
  119. package/src/modes/acp/acp-agent.ts +43 -7
  120. package/src/modes/acp/acp-event-mapper.ts +14 -7
  121. package/src/modes/acp/acp-mode.ts +39 -3
  122. package/src/modes/components/assistant-message.ts +123 -22
  123. package/src/modes/components/irc-sidebar.ts +176 -62
  124. package/src/modes/components/model-selector.ts +61 -4
  125. package/src/modes/components/oauth-selector.ts +42 -12
  126. package/src/modes/components/read-tool-group.ts +82 -14
  127. package/src/modes/components/session-observer-overlay.ts +187 -32
  128. package/src/modes/components/settings-selector.ts +60 -18
  129. package/src/modes/components/tool-execution.ts +138 -27
  130. package/src/modes/controllers/event-controller.ts +109 -27
  131. package/src/modes/controllers/extension-ui-controller.ts +19 -2
  132. package/src/modes/controllers/input-controller.ts +18 -3
  133. package/src/modes/controllers/selector-controller.ts +83 -37
  134. package/src/modes/interactive-mode.ts +62 -3
  135. package/src/modes/irc-observation-ledger.ts +71 -15
  136. package/src/modes/runtime-init.ts +19 -2
  137. package/src/modes/types.ts +2 -0
  138. package/src/modes/utils/ui-helpers.ts +94 -1
  139. package/src/prompts/agents/architect.md +9 -1
  140. package/src/prompts/agents/critic.md +9 -0
  141. package/src/prompts/system/system-prompt.md +0 -1
  142. package/src/prompts/tools/read.md +4 -2
  143. package/src/runtime-mcp/smithery-auth.ts +17 -2
  144. package/src/runtime-mcp/smithery-connect.ts +11 -1
  145. package/src/sdk/broker/lifecycle.ts +25 -6
  146. package/src/sdk/bus/control-drain-lease.ts +104 -0
  147. package/src/sdk/bus/index.ts +341 -38
  148. package/src/sdk/bus/kind-aware-reconciliation.ts +242 -0
  149. package/src/sdk/bus/prompt-reconciliation.ts +2 -1
  150. package/src/sdk/bus/reconciliation-store.ts +224 -0
  151. package/src/sdk/host/control/dispatch.ts +5 -1
  152. package/src/sdk/host/control/operations.ts +1 -1
  153. package/src/sdk/host/host.ts +23 -1
  154. package/src/sdk/host/query/handlers.ts +55 -0
  155. package/src/sdk/mcp/server.ts +46 -18
  156. package/src/sdk/protocol/operation-inventory.generated.json +29 -0
  157. package/src/sdk/protocol/operation-registry.ts +7 -2
  158. package/src/sdk/session.ts +13 -1
  159. package/src/session/agent-session.ts +466 -50
  160. package/src/session/memory-guard-checkpoint-participant.ts +131 -0
  161. package/src/session/session-manager.ts +764 -17
  162. package/src/session/streaming-output.ts +262 -43
  163. package/src/setup/provider-onboarding.ts +19 -4
  164. package/src/skill-state/active-state.ts +0 -10
  165. package/src/skill-state/workflow-hud.ts +25 -2
  166. package/src/skill-state/workflow-mutation-guard.ts +65 -7
  167. package/src/tools/ask.ts +89 -69
  168. package/src/tools/browser/launch.ts +41 -6
  169. package/src/tools/fetch.ts +114 -23
  170. package/src/tools/output-meta.ts +176 -9
  171. package/src/tools/path-utils.ts +5 -1
  172. package/src/tools/read-internals.ts +44 -0
  173. package/src/tools/read.ts +1542 -310
  174. package/src/tools/resource-gc.ts +182 -18
  175. package/src/tools/tool-result.ts +14 -1
  176. package/src/web/search/providers/codex.ts +1 -1
  177. package/dist/types/gjc-runtime/deep-interview-draft.d.ts +0 -8
  178. package/dist/types/gjc-runtime/deep-interview-payload.d.ts +0 -41
  179. package/dist/types/gjc-runtime/deep-interview-repair.d.ts +0 -17
  180. package/src/gjc-runtime/deep-interview-draft.ts +0 -843
  181. package/src/gjc-runtime/deep-interview-payload.ts +0 -262
  182. package/src/gjc-runtime/deep-interview-repair.ts +0 -1674
package/CHANGELOG.md CHANGED
@@ -2,11 +2,49 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.12.0] - 2026-07-28
6
+ ### Resume fixes
7
+
8
+ - The typed deep-interview repair CLI (#3040 and its follow-ups) was reverted and replaced with a minimal staged-transition surface: `gjc deep-interview stage --for <transition> --input '<json>'` (or `@file`), `check`, `apply`, and `discard`. The payload is one JSON document merged losslessly into current state — no per-field flag grammar. The session resolves from `GJC_SESSION_ID`, exactly one pending draft exists per session (no `--draft-id`), and the draft records the state revision it was staged against so `apply` CAS-checks it runtime-side; a stale draft is auto-invalidated with typed recovery guidance. `check` dry-runs the identical merge `apply` performs. Validation is core-schema only (envelope shape, bounded input sizes, locked intent-contract immutability); free-form interview fields pass through untouched.
9
+ - Memory consolidation redacts GitHub tokens. The scrubber covered AWS ids, JWTs and keyword-prefixed keys, but GitHub tokens carry none of those keywords, so they reached `MEMORY.md` and `memory_summary.md` verbatim — and the summary is injected into every later session. Now covers the same three prefixes the contribution-prep scrubber already handled.
10
+ - The native skill hook resolves its config paths through the trusted directory helpers. It read `GJC_CODING_AGENT_DIR` / `GJC_CONFIG_DIR` straight from `process.env`, which Bun populates from `cwd/.env` before any module runs, so a repository could point the hook at a directory it ships and inject its own `skills.customDirectories` — bypassing the escalation guards that already exist for exactly this.
11
+ - Workflow settings are read from the config root under home. `GJC_CONFIG_DIR` is documented as a dirname under home and `dirs.ts` implements it that way, but the ralplan, ultragoal and deep-interview settings readers used the value as a full path, so setting it to the documented form made them look under the current working directory and silently fall back to built-in defaults.
12
+ - Align managed fallback abort-after-exhaustion expectations with #3257 ownership release: a subscriber abort at terminal `message_end` no longer expects a second `requestRunTerminal(cancelled)` because the logical-run owner is already cleared.
13
+ - Python eval timeout annotations now prefer the caller-configured `timeoutMs` over remaining wall-clock budget so async setup cannot flake second formatting in CI.
14
+ - Overflow maintenance now stops cleanly when no-op compaction would replay the same oversized request; the runtime status explains that `/clear` preserves the current session ID before retrying.
15
+ - The Smithery origin, API base and API key (`SMITHERY_URL`, `SMITHERY_API_URL`, `SMITHERY_API_KEY`) are now resolved from trusted environment sources only. The origin serves the CLI auth session the user is sent to, the API base receives `Authorization: Bearer <apiKey>` on every call and returns the connection records the agent consumes, and the key is that credential — all three were read through the merged view that includes the caller's `cwd/.env`. Shell, config and stored-credential paths are unchanged.
16
+ - `gjc gc` now reports and prunes stale session local roots. Every session gets its own `<tmp>/gjc-local/<session-id>` directory seeded with a migration marker, and nothing ever removed them, so machines accumulated one per session indefinitely. Only marker-only directories past a 24h grace window are eligible, so a root holding real content or belonging to a session that just started is never touched, and prune re-validates immediately before removing.
17
+ - `docs/environment-variables.md` now describes the `$env` loading order as implemented. The login shell rc files (`~/.zshenv`, `~/.zprofile`, `~/.zshrc`, `~/.bash_profile`, `~/.bashrc`) are a real sixth source and were missing from the list, and the page claimed `.env` files mirror `GJC_*` keys to `GJC_*` keys — a rule that is self-referential and that no code implements in either direction.
18
+ - The package no longer advertises `./extensibility/custom-commands/bundled/review`. That module was deleted when the bundled agents were trimmed to four canonical role agents (#922), but its `exports` entry stayed, so the published surface declared a subpath that fails to resolve. A test now checks every declared `exports` / `main` / `module` / `types` / `bin` target resolves to a file that exists.
19
+ - `docs/fs-scan-cache-architecture.md` now points at files that exist. It referenced a `packages/natives/src/` tree that the package does not have (its JS surface is the generated `native/index.js` / `native/index.d.ts`), the grep tool as `tools/grep.ts` when it is `tools/search.ts`, and a `src/patch/index.ts` for the hashline flows that live in `tools/ast-edit.ts`.
20
+ - Provider base URLs resolved from the environment by the model registry are now read from trusted sources only. `resolveProviderBaseUrlFromEnv()` used the merged view that includes the caller's `cwd/.env`, and it is generic — `<PROVIDER>_BASE_URL` is derived for any provider on top of the explicit `ANTHROPIC_BASE_URL` / `OPENAI_BASE_URL` / `GOOGLE_BASE_URL` / `GEMINI_BASE_URL` aliases — so a repository could plant a `.env` that redirected authenticated traffic for every provider, including re-admitting a redirect the provider-level resolvers reject. It now uses the non-project resolver; shell and user-level configuration is unchanged.
21
+ - The `ask` tool no longer rejects a JSON-string-encoded single-sided Round 0 payload before coercion; only the retired contract+review pair stays terminal, so a provider that serializes `questions` as a string no longer drives the model into an unbounded retry loop.
22
+ - Browser launch overrides (`PUPPETEER_EXECUTABLE_PATH`, `PUPPETEER_PROXY`, `PUPPETEER_PROXY_BYPASS_LOOPBACK`, `PUPPETEER_PROXY_IGNORE_CERT_ERRORS`) are now resolved from trusted environment sources only. `Bun.env` is `process.env` and the env module merges the caller's `cwd/.env` into it, so a repository could previously plant a `.env` that chose the browser binary, routed every request through its own proxy, and disabled certificate validation. Resolution now goes through the non-project resolver (launching shell plus GJC/user-owned `.env` files); shell-level configuration is unchanged.
23
+ - The tab-worker native-free import contract no longer invents import edges: its re-export scanner matched a bare `export` declaration followed anywhere later in the file by ` from "…"`, so a `from` inside a comment or string produced a phantom dependency. It now matches real re-export syntax (`export * from`, `export * as ns from`, `export { … } from`) only, and still fails on genuine barrel imports and re-exports.
24
+ - The spawned command overrides `GJC_SDK_SESSION_COMMAND` (broker session host) and `GJC_HARNESS_PROCESS_START_COMMAND` (harness process-start probe) are now resolved from trusted environment sources only. `Bun.env` is `process.env` and the env module merges the caller's `cwd/.env` into it, so a repository could previously plant a `.env` choosing which binary those paths execute. Resolution now goes through the non-project resolver (launching shell plus GJC/user-owned `.env` files); operator and test usage is unchanged, and a malformed harness override stays fatal rather than falling back to `ps`.
25
+ - macOS screenshot paths now recover the narrow no-break space before `AM`/`PM` for any following separator, so IDE-attached files such as `Screenshot … 11.23.30 PM-1785075812409.png` resolve instead of failing with `ENOENT`; word continuations like ` PMX` are left untouched.
26
+ - ACP failures now reach the client with a real JSON-RPC code instead of collapsing to an opaque `-32603 Internal error`: internal string codes with an ACP counterpart map onto auth-required, resource-not-found, and invalid-params, the rest keep their discriminator in `data`, and translation happens once at the connection boundary. An unrecognized `extMethod` now returns `-32601` rather than a resolved `{ok:false}` payload.
27
+ - ACP `Diff.path` is emitted absolute as the schema specifies, `ResourceLink.size` is forwarded only when it is a safe non-negative integer, and a failed tool update no longer overwrites `kind` with `other`, so clients keep the category they use for icons while failure stays carried by `status`.
28
+ - Interactive `/resume` no longer awaits ordinary notification-endpoint rotation after predecessor fencing when the transition is stamped `interactive_selector_resume`; lifecycle/SDK identity-control paths still await readiness and use a fail-closed control-drain orchestration that sends terminal control outcomes only after successor readiness, while uncertain predecessor stop no longer starts the successor (#2914).
29
+ - Interactive TUI `/resume` commits a status-container progress lease before inspect/migration/switch work and clears it on every exit path, with generation-scoped render-commit wait that fails open when the terminal is stopped or unavailable (#2914).
30
+ - Interactive `/resume` progress lease fails open when `statusContainer` or UI lacks child-mutation/render-commit surface, preserving headless/minimal controller contexts without weakening full TUI progress-before-switch (#3234 post-merge).
31
+ - The documented `GJC_OPENAI_CODE_WEB_SEARCH_MODEL` environment variable now overrides the OpenAI-code web-search model; it is resolved GJC-first ahead of the legacy `PI_CODEX_WEB_SEARCH_MODEL` name (previously only the legacy name was read, so the documented name was a silent no-op).
32
+
33
+ ### Added
34
+
35
+ - Deterministic tests for session_switch await policy (selector defer vs default/branch await), control-drain ordering, host pre-response readiness gating, and resume progress lease-before-switch behavior (#2914).
36
+ - Added an isolated Bun memory-baseline corpus with short/soak profiles across CLI, AgentSession, blob buffers, workers, Telegram, TUI, and shared/native boundaries; reports keep RSS, heap, external buffers, process-tree endpoints, active resources, throughput, and teardown evidence separate and advisory until variance is characterized.
37
+ - Telegram per-tool activity is now opt-in and remains durably controllable with `/toolactivity on|off` or the Notifications preferences UI; disabling it suppresses tool start/completion success and error bubbles without hiding assistant, ask, or session notifications.
38
+ - `/model`, `/login`, and `/provider` now order providers through one shared ranking: providers you already have (valid auth, in-flight validation, or a configured non-OAuth provider) come first, then providers whose stored credentials failed validation, then a curated list of well-known providers with regional and device variants grouped behind their primary, then everything else by display name. In `/model` rows, role/default rank and recent usage still take precedence over provider order (#3243).
39
+ - Ralplan now bounds architect and critic re-review lanes independently through `gjc.ralplan.maxReviewPassesPerLane` (integer 1–10; default 1). Per-lane budget exhaustion emits a lane-specific `PLANNING-STUCK` exit 3, fails closed against on-disk artifact floors, and repairs crash-gap retries. Architect and critic `gjc ralplan --write` calls can optionally pass `--lane-verdict`, which drives HUD lane pass counts and the latest verdict; critic/architect prompts and the ralplan SKILL workflow now ratchet re-reviews through persisted receipts.
40
+ - Ralplan consensus review lanes now persist same-session Architect and Critic subagent metadata (`--architect-id` / `--architect-resumable`, `--critic-id` / `--critic-resumable`) and resume those reviewers by default on pass 2+ with the mandatory re-review context bundle. Unavailable reviewer context falls back to a fresh lane spawn with role-scoped fallback metadata, preserving the existing sequential re-review cadence and receipt-only contract.
41
+
5
42
  ## [0.11.11] - 2026-07-26
6
43
 
7
44
  ### Added
8
45
 
9
46
  - Added cross-platform memory-pressure observability with effective host/cgroup limits, configurable GC and restart advisory thresholds, typed Linux process probes, and a Windows Job Object native probe; unsupported lifecycle actions remain advisory-only.
47
+ - Added versioned memory-guard checkpoints with strict transcript/blob validation and fail-closed cross-process writer/TTY ownership claims for future graceful restart activation.
10
48
  - Ralplan consensus planning now enforces a finite planner/revision iteration budget at the native write path (default 5, configurable via `gjc.ralplan.maxIterations`). Opening another planner/revision pass past the cap fails closed with exit code 3 and an operator-visible `PLANNING-STUCK` marker instead of silent unbounded re-review; `final`/post-interview escalation remains allowed without auto-implementation. The cap also floors against on-disk `stage-*-{planner,revision}.md` artifacts so a wiped, truncated, or malformed `index.jsonl` cannot fail open after prior openers (#3165).
11
49
  - Added `grok-45-eco`, `grok-45-medium`, and `grok-45-pro` built-in xAI presets for `grok-4.5`; every role stays within the model's `high` reasoning cap, while the `xai` provider recommendation remains `grok-medium` to preserve existing defaults (#3177).
12
50
  - JetBrains Air ACP sessions now preserve final answers across fast prompt completion, expose tool/retry/goal/notices and session title updates, apply Air's legacy `session/set_model` preset changes through the canonical session configuration path, accept client-supplied stdio/HTTP/SSE MCP servers, reject unsupported additional directories, and reject unavailable model presets before provider dispatch.
@@ -15,10 +53,15 @@
15
53
 
16
54
  ### Changed
17
55
 
56
+ - When GJC owns mouse input (`mouse.enabled: true`), mouse-wheel scrolling moves the session viewport by three rows per notch instead of a full page. PageUp/PageDown keep page-sized transcript-lane steps.
57
+ - While reviewing transcript history, the status line and composer stay fixed at the bottom. Semantic assistant/tool output and visible capped-sidebar changes show `New output — type to follow`; duplicate, elided, hidden, geometry-only, and theme-only changes do not. Ordinary typing or paste returns to live output before editing without changing editor focus.
18
58
  - Telegram per-tool activity is now opt-in and remains durably controllable with `/toolactivity on|off` or the Notifications preferences UI; disabling it suppresses tool start/completion success and error bubbles without hiding assistant, ask, or session notifications.
19
59
  - Model preset landing now shows explicit `Enter: apply` and `d: set as default` hints; pressing `d` applies the highlighted profile as the default while Enter keeps the session-only apply path (#3161).
20
60
 
21
61
  ### Fixed
62
+
63
+ - Session Observer now reads stable source snapshots, publishes only complete JSONL appends, validates replacement candidates, and clears stale transcript/model/tool content on source replacement, truncation, deletion, unreadability, or malformed candidates. Its transcript projection remains eager full-history work; this does not add virtualization or bounded full-history memory.
64
+ - Session-manager fork/moveTo failure-injection tests now use a platform-aware hermetic seam: retained `RecoveryFsRoot` prototype spies on Linux and the direct native/fs fallbacks off Linux, with a required hit counter so a dead injection fails closed (#3209).
22
65
  - The #3216 win32 cleanup-producer regression no longer hardcodes divergent directory size `4096`; it injects `nativeRoot.size + 1` so the test stays hermetic when Linux directory size is already `4096` (post-merge Dev CI red on `79f0de870`).
23
66
 
24
67
  - The synchronous `local://` resolver now accepts a `cleanup_pending` legacy-migration marker instead of rejecting it as unsafe. The async gate already treats that state as settled — entries are installed and content-verified, and only retirement of the legacy source is outstanding — so a managed session whose migration ended in `cleanup_pending` previously failed closed with "Unsafe local:// migration marker" on every `local://` read even though `initializeLocalRoot()` had succeeded. Both marker checks now share one settled-state definition; unrecognized marker values are still rejected. Follow-up to #3080; the asymmetry has been reachable since #2797.
@@ -34,12 +77,14 @@
34
77
  - Workflow intent routing now requires a leading `/skill:ultragoal` for slash-command escalation and recognizes Korean object-particle requests such as `ultragoal을 사용해줘` without routing questions that merely mention the command.
35
78
  - Aligned the startup GJC Forge splash border with the composer trailing gutter, including the one-row constrained fallback.
36
79
  - `gjc resume` and delete no longer pay a durable (fsync-backed) lock acquisition for managed session tombstones that have nothing left to reconcile; a scope with many accumulated already-completed tombstones opens noticeably faster (#3067).
37
- - `gjc deep-interview apply-round-result` no longer fails with `DI_INTERNAL_ERROR` on every call, which made the deep-interview workflow unable to score a single round. Three defects stacked: the Round-0 topology gate is recorded as a permanently unscorable `answered` shell (`--round` must be >= 1) yet counted toward the "earlier rounds must be scored" precondition, deadlocking every later round; the round-result decoder materializes omitted optional keys as `undefined`, which canonical JSON rejected outright, so any request omitting `targeting`/`ontology`/`bookkeeping` could not be digested; and `scoreToUnits` tested the raw float product, so ordinary scores whose scaling misses the integer grid (`0.69 * 10_000` is `6900.000000000001`) were rejected as non-integral 1e-4 units. Round-0 gate shells are now excluded from the ordering precondition, canonical JSON drops `undefined` object properties like `JSON.stringify` (array elements and the top-level value stay strict), and 1e-4 unit conversion is decided from the shortest round-trip decimal so genuinely off-grid precision such as `0.00005` and `0.05000000000000001` is still rejected.
38
80
  - Task output-limit environment overrides now accept only complete positive decimal safe integers; malformed, fractional, exponent-form, whitespace-padded, and precision-losing values fall back to the documented defaults instead of being partially parsed (#3175).
39
81
  - Task output-limit environment overrides now honor values loaded from agent, config-root, and home dotenv files through the shared utils env loader while retaining strict positive safe-integer validation and canonical GJC-first alias precedence.
40
82
  - `--thinking` now advertises the supported Effort levels and fails closed with a usage error for invalid, missing, empty, or flag-adjacent values, rather than silently ignoring a token or consuming another flag.
41
83
  - MCP servers configured with a large `timeout` no longer widen the startup hang window for every consumer. The long startup ceiling now applies only to ACP lifecycle launches that supply their own MCP servers, derived from the session readiness deadline with reserved headroom; ordinary CLI/SDK `mcpConfigPath`, project, user, and plugin-bundle consumers keep the short default. An ACP launch that reaches the readiness cutoff before MCP startup now fails fast as a pending startup instead of silently falling back to the ordinary ceiling.
42
84
 
85
+ - SDK MCP stdio (`gjc mcp-serve sdk`) now awaits in-flight JSON-RPC handlers after stdin EOF so tools/call responses finish and WebSocket clients close before process exit; the entrypoint e2e fixture bounds child/server/temp cleanup on success and failure so the suite cannot hang for the full 60s on a stuck server.
86
+ - Shared kind-aware durable invocation reconciliation substrate for `turn.prompt` and `skill.invoke` (#3031/#3032/#3035): private `.sdk-reconciliation` store, awaitable preflight accept fence, non-hanging skill early-accept with optional `clientRef`.
87
+ - AD-L-G02 daemon session CLI e2e is less flaky under CI load: mock WebSocket servers defer `server_hello` one tick, and query failures report stdout/stderr so a non-zero exit surfaces the real SDK error instead of only `exitCode`.
43
88
  ## [0.11.10] - 2026-07-25
44
89
  ### Changed
45
90
 
@@ -52,7 +97,7 @@
52
97
  - Restricted role-agent `bash` now accepts literal mid-word tildes, so git revision syntax such as `git diff HEAD~1` no longer has to be quoted. Bash performs tilde expansion only at the start of a word, so word-initial forms (`~`, `~/path`, `~user`) remain blocked.
53
98
  - Restricted role-agent `bash` now rejects unquoted tildes at every bash expansion position inside assignment words, including the compound `name+=value` form, so `A=~`, `A+=~`, `foo=~root/bar`, `A=x:~`, `A+=x:~`, and repeated colon segments such as `a=x:~:y:~` fail closed. Tildes bash does not expand — mid-word git revisions (`HEAD~1`), non-assignment words (`--opt=~`, `1abc=~`, `a++=~`, `a+b=~`), and quoted forms — remain allowed (#3117).
54
99
  - Read-only role agents (`architect`, `planner`, `critic`) now receive the `irc` coordination tool and a read-only git prefix set (`status`, `log`, `show`, `diff`, `blame`, `rev-parse`, `ls-files`) in restricted bash; mutating git and arbitrary shell stay blocked. `irc` also stays in the initial active tool set for subagents whenever the parent runtime reports IRC availability, instead of costing a discovery round-trip (#3109).
55
- - The restricted-bash workflow guard now allows `/dev/null` redirects (so `cmd 2>/dev/null` is no longer treated as a repository write during planning phases) while keeping `/dev/stdout`, `/dev/stderr`, and `/dev/fd/<n>` blocked, failing closed on `exec` redirections, and recognizing `>|`, `>&path`, `<>`, path-qualified writers, and every `dd of=` operand. Hook-seeded deep-interview state is now gated on `isNativeDeepInterviewV1` and seeded as a native v1 envelope, so typed operations no longer fail with `DI_STATE_SCHEMA_INVALID` and run the interview manually (#3127).
100
+ - The restricted-bash workflow guard now allows `/dev/null` redirects (so `cmd 2>/dev/null` is no longer treated as a repository write during planning phases) while keeping `/dev/stdout`, `/dev/stderr`, and `/dev/fd/<n>` blocked, failing closed on `exec` redirections, and recognizing `>|`, `>&path`, `<>`, path-qualified writers, and every `dd of=` operand (#3127).
56
101
  - The vendored `insane-search` engine no longer treats a `429` as terminal: rate-limited probe and grid candidates back off (linear escalation honoring `Retry-After`, hard-capped at 30s) and continue through grid diversity and browser fallback. The backoff base from `INSANE_RATE_LIMIT_BACKOFF_S` is validated and clamped, so non-numeric, `NaN`, infinite, negative, or huge values can no longer raise, hang, or defeat a per-attempt deadline, and sleeps stay short enough to honor cancellation (#3131).
57
102
  - ACP sessions now apply execution permission decisions to eval calls and to tools invoked from JavaScript or Python eval contexts, while non-ACP session behavior remains unchanged.
58
103
  - Interactive prompt cancellation now reaches API-key preflight through `ModelRegistry`, allowing aborted submissions to clear immediately even while a shared credential-usage request continues in the background.
@@ -71,6 +116,7 @@
71
116
  - Rejected subagent schema payloads now retain their complete structured data in canonical output artifacts; inline results remain bounded while `agent://` output stays lossless (#2894).
72
117
  - Managed legacy-session artifact migration now validates Windows directory roots from the native tree snapshot, tolerates only lazy metadata on plain Windows directories, and replays both clean and cleanup-pending detaches while retaining fail-closed receipt validation. Canonical binding durability sync uses a writable no-follow handle on Windows NTFS stacks that reject `FlushFileBuffers` on read-only handles (#3015, #2913).
73
118
  - A single managed session tombstone that fails to reconcile (e.g. an artifact directory identity mismatch) no longer blocks resume or delete of every other session in the same managed scope; the failure is isolated to that tombstone and logged, unless it belongs to the session currently being opened, which still fails closed.
119
+ - Added Linux-only team worker memory-pressure replacement with checkpoint classification, bounded retries, deterministic target selection, and fail-closed blocked tasks; Windows and macOS remain advisory-only.
74
120
 
75
121
  ## [0.11.8] - 2026-07-23
76
122
  ### Added
@@ -341,11 +387,11 @@
341
387
 
342
388
  ## [0.10.1] - 2026-07-13
343
389
 
344
- - Deep-interview bundled guidance now uses the typed native setup, topology, answer-recovery, round-result, selective inspection, and sanity-check commands for normal workflow state changes. Generic `gjc state` remains limited to documented compatibility/recovery handoff paths; ambiguity, receipts, revisions, topology persistence, and diagnosis/repair remain runtime-owned.
345
390
  ### Added
346
391
 
347
392
  - Added an owner-proof idle session reaper and `gjc_coordinator_stop_session` for ephemeral (delegate-created) coordinator sessions. Termination goes exclusively through the canonical SDK broker `session.close` lifecycle (durable process identity verified before close) — never a raw `process.kill` or tmux control. The reaper re-validates ephemeral and no-active-turn state at close time under the same per-session mutation lock as delegate reuse, and purges coordinator metadata only after SDK closure is verified, retaining it when closure cannot be confirmed (#2080).
348
393
 
394
+ - Added an owner-proof idle session reaper and `gjc_coordinator_stop_session` for ephemeral (delegate-created) coordinator sessions. Termination goes exclusively through the owner-proof `forceCloseGjcTmuxSession` path (pid, native session id, owner generation, server key, and start time all verified before SIGTERM) — never a raw `process.kill`. The reaper binds each close to the persisted runtime-state file, re-validates ephemeral and no-active-turn at kill time under the same per-session mutation lock as delegate reuse, and purges state only on verified termination (#2080).
349
395
  - SDK clients can now pass an explicit thinking level to `model.set`, atomically applying the effective model and thinking level to the active session and the machine-global default for future sessions, while project policy and resumed session history retain precedence.
350
396
  - Context-usage tokens/% now use provider-reported usage as the single source of truth on every surface. `AgentSession.getContextUsage()` returns a source-tagged snapshot (`source: "provider_anchor" | "heuristic" | "unknown"`), and the status-line `context_pct` segment, inline model percentage, and `/context` totals consume that snapshot instead of recomputing an independent heuristic sum — so footer, status line, `/context`, ACP, and RPC can no longer disagree about the same session state. Heuristic estimation now applies only when no provider anchor exists (session start, aborted/error-only turns), and that fallback now includes the fixed system-prompt/tool/skill context it previously omitted. The pre-prompt compaction estimate honors the latest-compaction boundary (never anchors on stale pre-compaction usage totals), unknown post-compaction usage stays unknown (status line renders `?`; ACP omits the `usage_update` instead of reporting `used: 0`), and `/context` labels its total by provenance with a reconciliation line when the estimated category composition diverges from the provider-reported total.
351
397
  - Post-durable default-model-selection failures now expose a stable SDK error with bounded `restored`, `partial`, or `unknown` rollback state; preflight and validation errors remain unchanged.
@@ -1,4 +1,5 @@
1
1
  export interface ReadCommandArgs {
2
2
  path: string;
3
+ truncation?: "head" | "last" | "both";
3
4
  }
4
5
  export declare function runReadCommand(cmd: ReadCommandArgs): Promise<void>;
@@ -24,6 +24,15 @@ export default class DeepInterview extends Command {
24
24
  "session-id": import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
25
25
  description: string;
26
26
  };
27
+ input: import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
28
+ description: string;
29
+ };
30
+ for: import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
31
+ description: string;
32
+ };
33
+ reset: import("@gajae-code/utils/cli").FlagDescriptor<"boolean"> & {
34
+ description: string;
35
+ };
27
36
  write: import("@gajae-code/utils/cli").FlagDescriptor<"boolean"> & {
28
37
  description: string;
29
38
  };
@@ -1,4 +1,25 @@
1
1
  import { Command } from "@gajae-code/utils/cli";
2
+ /**
3
+ * Operator override for the process-start probe command, resolved from trusted
4
+ * environment sources only.
5
+ *
6
+ * The result is spawned, so whatever can set it chooses which binary runs.
7
+ * `$env` merges the caller's `cwd/.env` into `process.env`, so reading it there
8
+ * would let repository content pick the command; resolve it the same way
9
+ * provider credentials are (launching shell plus GJC/user-owned `.env` files,
10
+ * never the project `.env`). A malformed override stays fatal rather than
11
+ * silently falling back to `ps`, matching the previous behavior.
12
+ */
13
+ type ProcessStartCommandOverride = {
14
+ kind: "none";
15
+ } | {
16
+ kind: "invalid";
17
+ } | {
18
+ kind: "command";
19
+ command: string[];
20
+ };
21
+ /** Test seam: the process-start command override as resolved from trusted env. */
22
+ export declare function processStartCommandOverrideForTest(): ProcessStartCommandOverride;
2
23
  export default class Harness extends Command {
3
24
  #private;
4
25
  static description: string;
@@ -41,3 +62,4 @@ export default class Harness extends Command {
41
62
  static examples: string[];
42
63
  run(): Promise<void>;
43
64
  }
65
+ export {};
@@ -10,6 +10,12 @@ export default class Read extends Command {
10
10
  required: true;
11
11
  };
12
12
  };
13
+ static flags: {
14
+ truncation: import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
15
+ options: string[];
16
+ description: string;
17
+ };
18
+ };
13
19
  static examples: string[];
14
20
  run(): Promise<void>;
15
21
  }
@@ -370,6 +370,10 @@ export declare class ModelRegistry {
370
370
  * as providers with stored credentials. See issue #993.
371
371
  */
372
372
  hasConfiguredAuth(model: Model<Api>): boolean;
373
+ /**
374
+ * Check whether auth is configured for a provider.
375
+ */
376
+ hasConfiguredProviderAuth(provider: string): boolean;
373
377
  getDiscoverableProviders(): string[];
374
378
  getProviderDiscoveryState(provider: string): ProviderDiscoveryState | undefined;
375
379
  /**
@@ -0,0 +1,14 @@
1
+ import type { AuthStorage } from "@gajae-code/ai/auth-storage";
2
+ /**
3
+ * Most recent OAuth validation outcome per provider, used only as an ordering
4
+ * hint so `/model` can rank a provider whose stored credentials failed
5
+ * validation below one that is healthy, without re-running validation itself.
6
+ *
7
+ * Entries are scoped to the `AuthStorage` that produced them and to its
8
+ * credential generation, so any login, logout, import, or deletion discards the
9
+ * stale result instead of overriding current auth state.
10
+ */
11
+ export type ProviderAuthHealth = "valid" | "invalid";
12
+ export declare function recordProviderAuthHealth(authStorage: AuthStorage, providerId: string, health: ProviderAuthHealth): void;
13
+ export declare function getProviderAuthHealth(authStorage: AuthStorage, providerId: string): ProviderAuthHealth | undefined;
14
+ export declare function clearProviderAuthHealth(authStorage: AuthStorage): void;
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Shared provider ordering used by every provider-facing selector (`/login`,
3
+ * `/model`, `/provider`).
4
+ *
5
+ * Providers the user already has come first, then a curated list of well-known
6
+ * providers, then everything else alphabetically. This is the single source of
7
+ * truth for that order — surfaces must not keep their own famous-provider list.
8
+ */
9
+ /**
10
+ * Auth/config state of a provider as seen by the calling surface.
11
+ *
12
+ * - `valid` — stored credentials that validated successfully.
13
+ * - `checking` — stored credentials whose async validation is still in flight.
14
+ * Ranked with `valid` so rows do not reflow when validation resolves.
15
+ * - `configured` — no OAuth record, but the provider is present in the model
16
+ * registry with a working API key (custom/API-compatible providers).
17
+ * - `invalid` — stored credentials that failed validation (problematic login).
18
+ * - `none` — nothing stored and nothing configured.
19
+ */
20
+ export type ProviderAuthState = "valid" | "checking" | "configured" | "invalid" | "none";
21
+ export declare const PROVIDER_RANK_TIER: {
22
+ readonly existing: 0;
23
+ readonly problematic: 1;
24
+ readonly famous: 2;
25
+ readonly other: 3;
26
+ };
27
+ export type ProviderRankTier = (typeof PROVIDER_RANK_TIER)[keyof typeof PROVIDER_RANK_TIER];
28
+ /**
29
+ * Curated provider order for the famous tier. Regional and device variants sit
30
+ * immediately behind their primary so related entries stay grouped.
31
+ */
32
+ export declare const FAMOUS_PROVIDER_ORDER: readonly string[];
33
+ /** A provider as ranked by a surface. `label` is what the user sees. */
34
+ export interface RankableProvider {
35
+ id: string;
36
+ label: string;
37
+ authState: ProviderAuthState;
38
+ }
39
+ /** A provider's position in the ordering: its tier plus its rank inside that tier. */
40
+ export interface ProviderRank {
41
+ tier: ProviderRankTier;
42
+ intraTierRank: number;
43
+ }
44
+ /**
45
+ * The single ranking result for a provider. `intraTierRank` is the curated
46
+ * famous-list position, or `Number.MAX_SAFE_INTEGER` for providers that are not
47
+ * on the list and therefore order by display label.
48
+ */
49
+ export declare function rankProvider(provider: RankableProvider): ProviderRank;
50
+ export declare function providerRankTier(authState: ProviderAuthState, id: string): ProviderRankTier;
51
+ /** Position within the famous list, or `undefined` for providers not on it. */
52
+ export declare function famousProviderIndex(id: string): number | undefined;
53
+ /**
54
+ * Total order over providers: tier, then famous-list position, then display
55
+ * label, then id. The trailing id comparison guarantees no ties.
56
+ */
57
+ export declare function compareRankedProviders(left: RankableProvider, right: RankableProvider): number;
58
+ /** Convenience wrapper returning a new array in ranked order. */
59
+ export declare function sortRankedProviders<T extends RankableProvider>(providers: readonly T[]): T[];
@@ -428,6 +428,11 @@ export declare const SETTINGS_SCHEMA: {
428
428
  readonly default: 5;
429
429
  readonly validate: (value: number) => boolean;
430
430
  };
431
+ readonly "gjc.ralplan.maxReviewPassesPerLane": {
432
+ readonly type: "number";
433
+ readonly default: 1;
434
+ readonly validate: (value: number) => boolean;
435
+ };
431
436
  readonly "theme.dark": {
432
437
  readonly type: "string";
433
438
  readonly default: "red-claw";
@@ -2464,7 +2469,7 @@ export declare const SETTINGS_SCHEMA: {
2464
2469
  readonly ui: {
2465
2470
  readonly tab: "editing";
2466
2471
  readonly label: "Default Read Limit";
2467
- readonly description: "Default number of lines returned when agent calls read without a limit";
2472
+ readonly description: "Default collection/selection limit for read operations; bare local receipts use the separate 50-line / 10 KiB receipt budgets";
2468
2473
  readonly options: readonly [{
2469
2474
  readonly value: "200";
2470
2475
  readonly label: "200 lines";
@@ -2532,6 +2537,29 @@ export declare const SETTINGS_SCHEMA: {
2532
2537
  }];
2533
2538
  };
2534
2539
  };
2540
+ readonly "read.truncation": {
2541
+ readonly type: "enum";
2542
+ readonly values: readonly ["head", "last", "both"];
2543
+ readonly default: "last";
2544
+ readonly ui: {
2545
+ readonly tab: "editing";
2546
+ readonly label: "Read Truncation";
2547
+ readonly description: "Configured default direction for routes that support directional truncation; bare local and archive reads use this value (factory default: last), while explicit truncation always wins";
2548
+ readonly options: readonly [{
2549
+ readonly value: "head";
2550
+ readonly label: "Head";
2551
+ readonly description: "Keep the first N lines";
2552
+ }, {
2553
+ readonly value: "last";
2554
+ readonly label: "Last";
2555
+ readonly description: "Keep the last N lines (default)";
2556
+ }, {
2557
+ readonly value: "both";
2558
+ readonly label: "Both";
2559
+ readonly description: "Keep the start and the end, elide the middle";
2560
+ }];
2561
+ };
2562
+ };
2535
2563
  readonly "read.summaryMaxBytes": {
2536
2564
  readonly type: "number";
2537
2565
  readonly default: 20;
@@ -90,6 +90,8 @@ export declare class Settings implements NotificationSettingsReader {
90
90
  /** Diagnostics from schema reconciliation during the most recent load. */
91
91
  getSchemaReport(): SettingsSchemaReport;
92
92
  onChanged(listener: (path: SettingPath) => void): () => void;
93
+ /** Whether durable settings mutations are permitted for the loaded configuration. */
94
+ canWriteDurableConfig(): boolean;
93
95
  /**
94
96
  * Set a setting value (sync).
95
97
  * Updates global settings and reserves its background persistence slot before
@@ -291,7 +291,16 @@ export interface ExtensionContext {
291
291
  } | undefined>;
292
292
  getJobs(): unknown;
293
293
  /** Typed skill and mode controls exposed to the SDK host. */
294
- invokeSkill?(name: string, args?: string): Promise<unknown>;
294
+ invokeSkill?(name: string, args?: string, options?: {
295
+ onPreflightAccepted?: () => void;
296
+ onPreflightAcceptCommit?: () => void | Promise<void>;
297
+ onSkillPrepared?: (meta: {
298
+ name: string;
299
+ path: string;
300
+ lineCount?: number;
301
+ cleanedArgs?: string;
302
+ }) => void;
303
+ }): Promise<unknown>;
295
304
  setPlanMode?(on: boolean): unknown;
296
305
  operateGoal?(op: "create" | "get" | "resume" | "pause" | "complete" | "drop", objective?: string): Promise<unknown>;
297
306
  /** Typed nonvisual session controls exposed to the SDK host. */
@@ -760,6 +769,7 @@ export interface ExtensionAPI {
760
769
  sendUserMessage(content: string | (TextContent | ImageContent)[], options?: {
761
770
  deliverAs?: "steer" | "followUp";
762
771
  onPreflightAccepted?: () => void;
772
+ onPreflightAcceptCommit?: () => void | Promise<void>;
763
773
  }): Promise<void>;
764
774
  /** Append a custom entry to the session for state persistence (not sent to LLM). */
765
775
  appendEntry<T = unknown>(customType: string, data?: T): void;
@@ -933,6 +943,7 @@ options?: {
933
943
  export type SendUserMessageHandler = (content: string | (TextContent | ImageContent)[], options?: {
934
944
  deliverAs?: "steer" | "followUp";
935
945
  onPreflightAccepted?: () => void;
946
+ onPreflightAcceptCommit?: () => void | Promise<void>;
936
947
  }) => void | Promise<void>;
937
948
  export type AppendEntryHandler = <T = unknown>(customType: string, data?: T) => void;
938
949
  export type GetActiveToolsHandler = () => string[];
@@ -1037,7 +1048,16 @@ export interface ExtensionContextActions {
1037
1048
  getJobs?: () => unknown;
1038
1049
  setSdkPermissionProvider?: (provider: ((toolCall: ClientBridgePermissionToolCall, options: ClientBridgePermissionOption[], signal?: AbortSignal) => Promise<ClientBridgePermissionOutcome>) | undefined) => void;
1039
1050
  sdkControl?: (operation: string, input: Record<string, unknown>) => unknown | Promise<unknown>;
1040
- invokeSkill?: (name: string, args?: string) => Promise<unknown>;
1051
+ invokeSkill?: (name: string, args?: string, options?: {
1052
+ onPreflightAccepted?: () => void;
1053
+ onPreflightAcceptCommit?: () => void | Promise<void>;
1054
+ onSkillPrepared?: (meta: {
1055
+ name: string;
1056
+ path: string;
1057
+ lineCount?: number;
1058
+ cleanedArgs?: string;
1059
+ }) => void;
1060
+ }) => Promise<unknown>;
1041
1061
  setPlanMode?: (on: boolean) => unknown;
1042
1062
  operateGoal?: (op: "create" | "get" | "resume" | "pause" | "complete" | "drop", objective?: string) => Promise<unknown>;
1043
1063
  }
@@ -31,6 +31,8 @@ export interface SessionBeforeSwitchEvent {
31
31
  /** Session file we're switching to (only for "resume") */
32
32
  targetSessionFile?: string;
33
33
  }
34
+ /** Origin used when an interactive session selector resumes a session. */
35
+ export declare const INTERACTIVE_SELECTOR_RESUME_ORIGIN = "interactive_selector_resume";
34
36
  /** Fired after switching to another session */
35
37
  export interface SessionSwitchEvent {
36
38
  type: "session_switch";
@@ -38,6 +40,10 @@ export interface SessionSwitchEvent {
38
40
  reason: "new" | "resume" | "fork";
39
41
  /** Session file we came from */
40
42
  previousSessionFile: string | undefined;
43
+ /** Optional provenance for this session transition. */
44
+ transition?: {
45
+ origin: string;
46
+ };
41
47
  }
42
48
  /** Fired before branching a session (can be cancelled) */
43
49
  export interface SessionBeforeBranchEvent {
@@ -9,13 +9,15 @@ export interface AmbiguityClampResult {
9
9
  effective: number;
10
10
  clamped: boolean;
11
11
  }
12
- /** Compute the deterministic floor from integer units of persisted evidence. */
12
+ /** Compute the deterministic floor from the inner deep-interview `state` object. */
13
13
  export declare function computeAmbiguityFloor(inner: unknown): AmbiguityFloorBreakdown;
14
14
  /** Clamp an LLM-reported ambiguity to the deterministic floor: `max(reported, floor)`. */
15
15
  export declare function clampReportedAmbiguity(reported: number, floor: number): AmbiguityClampResult;
16
16
  /**
17
- * Legacy pure utility for migrations and explicit repair flows. The recorder does
18
- * not dispute facts when an answer is retracted: scored evidence is immutable.
17
+ * Mark every established fact recorded in `retractedRound` as disputed. This is the
18
+ * mechanical contradiction signal for answer retraction: when the user replaces an
19
+ * already-scored answer (A -> B pivot), the facts that answer established can no
20
+ * longer be trusted, so they raise the floor until re-confirmed or superseded.
19
21
  * Returns new arrays/objects; never mutates the input.
20
22
  */
21
23
  export declare function disputeFactsFromRetractedRound(facts: readonly unknown[], retractedRound: number): {
@@ -35,12 +37,3 @@ export interface AppliedAmbiguityFloor {
35
37
  * (state CLI write/reconcile, recorder) applies this immediately before persisting.
36
38
  */
37
39
  export declare function applyAmbiguityFloorToEnvelope(value: unknown): AppliedAmbiguityFloor;
38
- export type DeepInterviewAmbiguityMilestone = "initial" | "progress" | "refined" | "ready";
39
- export declare function deriveAmbiguityMilestone(effectiveUnits: number, thresholdUnits: number): DeepInterviewAmbiguityMilestone;
40
- export declare function scoreToUnits(score: number): number;
41
- export declare function weightedAmbiguityUnits(scores: {
42
- goal: number;
43
- constraints: number;
44
- criteria: number;
45
- context?: number;
46
- }, type: "greenfield" | "brownfield"): number;
@@ -1,4 +1,4 @@
1
- import { type DeepInterviewEstablishedFact, type DeepInterviewIntentItem, type DeepInterviewIntentSubstitution, type DeepInterviewRoundRecord, type DeepInterviewRoundResultV1, type DeepInterviewStateEnvelope, type DeepInterviewTriggerMetadata } from "./deep-interview-state";
1
+ import { type DeepInterviewEstablishedFact, type DeepInterviewIntentItem, type DeepInterviewIntentSubstitution, type DeepInterviewRoundRecord, type DeepInterviewStateEnvelope, type DeepInterviewTriggerMetadata } from "./deep-interview-state";
2
2
  export * from "./deep-interview-ambiguity";
3
3
  export * from "./deep-interview-state";
4
4
  /**
@@ -40,8 +40,6 @@ export interface DeepInterviewScoringInput {
40
40
  scores: Record<string, number>;
41
41
  ambiguity: number;
42
42
  triggers?: DeepInterviewTriggerMetadata[];
43
- /** Complete native round result for typed callers. */
44
- roundResult?: DeepInterviewRoundResultV1;
45
43
  }
46
44
  export type AppendOrMergeAction = "created" | "noop" | "replaced";
47
45
  export interface AppendOrMergeResult {
@@ -69,9 +67,11 @@ export interface TransitionValidationResult {
69
67
  }
70
68
  export declare function buildAnswerShell(input: DeepInterviewAnswerInput, now?: string): DeepInterviewRoundRecord;
71
69
  /**
72
- * Append-or-merge by `round_key`. An answer is a no-op only when its complete
73
- * canonical shell identity matches; a scored record is immutable evidence and
74
- * cannot be replaced by a late answer.
70
+ * Append-or-merge by `round_key`. Exactly one record per key:
71
+ * - no existing record -> append (`created`);
72
+ * - identical question_hash + answer_hash -> deterministic no-op (`noop`);
73
+ * - same key, different hashes -> deterministic replacement of the prior shell
74
+ * (`replaced`); the prior answer for that key is superseded and lifecycle resets.
75
75
  */
76
76
  export declare function appendOrMergeRound(rounds: readonly DeepInterviewRoundRecord[], shell: DeepInterviewRoundRecord): AppendOrMergeResult;
77
77
  /**
@@ -94,43 +94,28 @@ export declare function ensureDeepInterviewStateShape(value: unknown): DeepInter
94
94
  export declare function projectCompactState(value: unknown, options?: {
95
95
  lastN?: number;
96
96
  }): DeepInterviewCompactState;
97
- interface RecorderMutationOptions {
98
- sessionId?: string;
99
- expectedRevision?: number;
100
- }
101
- export interface DeepInterviewPostCommitWarning {
102
- code: "DI_POST_COMMIT_AUDIT_FAILED" | "DI_POST_COMMIT_ACTIVITY_FAILED" | "DI_POST_COMMIT_HUD_FAILED";
103
- message: string;
104
- }
105
- export declare function runDeepInterviewPostCommitEffects(options: {
106
- cwd: string;
107
- statePath: string;
108
- sessionId: string;
109
- envelope: Record<string, unknown>;
110
- revision: number;
111
- writer: string;
112
- auditWarnings?: readonly {
113
- code: "DI_POST_COMMIT_AUDIT_FAILED";
114
- message: string;
115
- }[];
116
- }): Promise<DeepInterviewPostCommitWarning[]>;
117
97
  /** Refresh the best-effort HUD cache from persisted deep-interview state. */
118
98
  export declare function syncDeepInterviewRecorderHud(cwd: string, statePath: string, sessionId: string | undefined): Promise<void>;
119
99
  /**
120
100
  * Record an `answered` shell for one round (append-or-merge by durable key).
121
101
  *
122
- * Replacing an already-scored answer is rejected with
123
- * `DI_ANSWER_LIFECYCLE_CONFLICT`; scored evidence is immutable.
102
+ * Retraction dynamics: replacing an already-`scored` answer is a mechanical
103
+ * contradiction signal (the user pivoted). The facts that round established are
104
+ * marked disputed, which raises the deterministic ambiguity floor immediately —
105
+ * without waiting for the LLM scorer to self-report a trigger.
124
106
  */
125
- export declare function appendOrMergeDeepInterviewRound(cwd: string, statePath: string, input: DeepInterviewAnswerInput, options?: RecorderMutationOptions): Promise<{
107
+ export declare function appendOrMergeDeepInterviewRound(cwd: string, statePath: string, input: DeepInterviewAnswerInput, options?: {
108
+ sessionId?: string;
109
+ }): Promise<{
126
110
  action: AppendOrMergeAction;
127
111
  record: DeepInterviewRoundRecord;
128
- warnings: DeepInterviewPostCommitWarning[];
112
+ disputedFactIds?: string[];
129
113
  }>;
130
114
  /** Merge scoring output into the same round record, transitioning to `scored`. */
131
- export declare function enrichDeepInterviewRoundScoring(cwd: string, statePath: string, input: DeepInterviewScoringInput, options?: RecorderMutationOptions): Promise<{
115
+ export declare function enrichDeepInterviewRoundScoring(cwd: string, statePath: string, input: DeepInterviewScoringInput, options?: {
116
+ sessionId?: string;
117
+ }): Promise<{
132
118
  record: DeepInterviewRoundRecord;
133
- warnings: DeepInterviewPostCommitWarning[];
134
119
  }>;
135
120
  /** Compact projection so callers read a slice instead of the full transcript. */
136
121
  export declare function readDeepInterviewStateCompact(statePath: string, options?: {
@@ -0,0 +1,37 @@
1
+ import { CommandError } from "./workflow-cli-common";
2
+ export declare const DEEP_INTERVIEW_STAGE_TRANSITIONS: readonly ["initialize-context", "record-round", "update-facts", "merge-state"];
3
+ export type DeepInterviewStageTransition = (typeof DEEP_INTERVIEW_STAGE_TRANSITIONS)[number];
4
+ declare const DRAFT_VERSION = 1;
5
+ export type DeepInterviewStageErrorCode = "DI_STAGE_USAGE" | "DI_STAGE_INPUT_INVALID" | "DI_STAGE_SESSION_REQUIRED" | "DI_STAGE_DRAFT_EXISTS" | "DI_STAGE_NO_DRAFT" | "DI_STAGE_DRAFT_CORRUPT" | "DI_STAGE_STATE_MISSING" | "DI_STAGE_STATE_CORRUPT" | "DI_STAGE_REVISION_CONFLICT" | "DI_STAGE_MERGE_REJECTED";
6
+ export declare class DeepInterviewStageError extends CommandError {
7
+ readonly code: DeepInterviewStageErrorCode;
8
+ readonly recovery?: string | undefined;
9
+ constructor(code: DeepInterviewStageErrorCode, message: string, recovery?: string | undefined);
10
+ }
11
+ export interface DeepInterviewStageDraft {
12
+ version: typeof DRAFT_VERSION;
13
+ draft_id: string;
14
+ session_id: string;
15
+ transition: DeepInterviewStageTransition;
16
+ /** State revision the draft was staged against; `apply` CAS-checks this. */
17
+ staged_against_revision: number;
18
+ /**
19
+ * Canonical content SHA-256 of the state the draft was staged against. Revision
20
+ * alone cannot catch sanctioned writers that do not bump `state_revision`
21
+ * (seed/spec-persistence), so `apply` requires BOTH to match.
22
+ */
23
+ staged_against_sha256: string;
24
+ payload: Record<string, unknown>;
25
+ created_at: string;
26
+ }
27
+ export interface DeepInterviewStageCommandResult {
28
+ status: number;
29
+ stdout?: string;
30
+ stderr?: string;
31
+ }
32
+ export declare function deepInterviewDraftPath(cwd: string, sessionId: string): string;
33
+ export declare const DEEP_INTERVIEW_STAGE_VERBS: readonly ["stage", "check", "apply", "discard", "read", "write", "clear", "handoff"];
34
+ export type DeepInterviewStageVerb = (typeof DEEP_INTERVIEW_STAGE_VERBS)[number];
35
+ export declare function isDeepInterviewStageVerb(value: string | undefined): value is DeepInterviewStageVerb;
36
+ export declare function runDeepInterviewStageCommand(verb: DeepInterviewStageVerb, args: readonly string[], cwd?: string): Promise<DeepInterviewStageCommandResult>;
37
+ export {};