@gajae-code/coding-agent 0.12.0 → 0.12.2

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 (247) hide show
  1. package/CHANGELOG.md +111 -0
  2. package/dist/types/async/job-manager.d.ts +17 -3
  3. package/dist/types/config/settings-schema.d.ts +56 -2
  4. package/dist/types/exa/mcp-client.d.ts +10 -1
  5. package/dist/types/exec/bash-executor.d.ts +45 -12
  6. package/dist/types/extensibility/extensions/types.d.ts +16 -2
  7. package/dist/types/extensibility/gjc-plugins/index.d.ts +12 -2
  8. package/dist/types/extensibility/gjc-plugins/installer.d.ts +63 -7
  9. package/dist/types/extensibility/gjc-plugins/lifecycle-reconciliation.d.ts +55 -0
  10. package/dist/types/extensibility/gjc-plugins/lifecycle.d.ts +64 -0
  11. package/dist/types/extensibility/gjc-plugins/runtime-quarantine.d.ts +67 -0
  12. package/dist/types/extensibility/gjc-plugins/session-validation.d.ts +3 -1
  13. package/dist/types/extensibility/gjc-plugins/types.d.ts +124 -0
  14. package/dist/types/gjc-runtime/launch-tmux.d.ts +1 -0
  15. package/dist/types/gjc-runtime/ralplan-review-conflicts.d.ts +114 -0
  16. package/dist/types/gjc-runtime/ralplan-runtime.d.ts +23 -3
  17. package/dist/types/gjc-runtime/team-launch.d.ts +1 -1
  18. package/dist/types/gjc-runtime/team-runtime.d.ts +25 -0
  19. package/dist/types/gjc-runtime/team-worker-heartbeat.d.ts +43 -0
  20. package/dist/types/gjc-runtime/tmux-owner-isolation.d.ts +10 -0
  21. package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +37 -80
  22. package/dist/types/modes/acp/acp-agent.d.ts +2 -19
  23. package/dist/types/modes/components/gjc-bundle-settings.d.ts +34 -0
  24. package/dist/types/modes/components/irc-sidebar.d.ts +16 -0
  25. package/dist/types/modes/components/notifications-settings-editor.d.ts +1 -0
  26. package/dist/types/modes/components/session-observer-overlay.d.ts +18 -0
  27. package/dist/types/modes/components/settings-selector.d.ts +9 -0
  28. package/dist/types/modes/components/status-line/gh.d.ts +5 -0
  29. package/dist/types/modes/components/transcript-viewer-overlay.d.ts +18 -1
  30. package/dist/types/modes/controllers/command-controller.d.ts +1 -1
  31. package/dist/types/modes/controllers/event-controller.d.ts +1 -1
  32. package/dist/types/modes/controllers/extension-ui-controller.d.ts +2 -1
  33. package/dist/types/modes/controllers/selector-controller.d.ts +1 -1
  34. package/dist/types/modes/interactive-mode.d.ts +9 -0
  35. package/dist/types/modes/theme/theme.d.ts +3 -1
  36. package/dist/types/modes/types.d.ts +32 -0
  37. package/dist/types/reminders/star-reminder.d.ts +3 -13
  38. package/dist/types/runtime-mcp/manager.d.ts +1 -0
  39. package/dist/types/sdk/acp/adapter.d.ts +3 -1
  40. package/dist/types/sdk/broker/transport.d.ts +2 -0
  41. package/dist/types/sdk/bus/attachment-registry.d.ts +1 -0
  42. package/dist/types/sdk/bus/chat-daemon-control.d.ts +5 -1
  43. package/dist/types/sdk/bus/config.d.ts +6 -2
  44. package/dist/types/sdk/bus/index.d.ts +29 -0
  45. package/dist/types/sdk/bus/kind-aware-reconciliation.d.ts +8 -1
  46. package/dist/types/sdk/bus/lifecycle-control-runtime.d.ts +4 -0
  47. package/dist/types/sdk/bus/reconciliation-store.d.ts +7 -3
  48. package/dist/types/sdk/bus/rich-draft.d.ts +1 -0
  49. package/dist/types/sdk/bus/rich-render.d.ts +2 -0
  50. package/dist/types/sdk/bus/telegram-adoption-intent.d.ts +165 -0
  51. package/dist/types/sdk/bus/telegram-cli.d.ts +12 -0
  52. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +12 -4
  53. package/dist/types/sdk/bus/telegram-daemon.d.ts +25 -1
  54. package/dist/types/sdk/bus/telegram-reference.d.ts +11 -1
  55. package/dist/types/sdk/bus/threaded-render.d.ts +3 -2
  56. package/dist/types/sdk/bus/topic-registry.d.ts +11 -1
  57. package/dist/types/sdk/host/query/revision-store.d.ts +2 -0
  58. package/dist/types/sdk/host/reverse-leases.d.ts +1 -1
  59. package/dist/types/sdk/prompt-status.d.ts +23 -3
  60. package/dist/types/sdk/session.d.ts +6 -0
  61. package/dist/types/session/agent-session.d.ts +40 -2
  62. package/dist/types/session/artifacts.d.ts +8 -0
  63. package/dist/types/session/blob-store.d.ts +57 -4
  64. package/dist/types/session/internal/managed-session-storage.d.ts +30 -4
  65. package/dist/types/session/session-manager.d.ts +23 -6
  66. package/dist/types/session/session-storage.d.ts +4 -0
  67. package/dist/types/session/streaming-output.d.ts +36 -7
  68. package/dist/types/setup/credential-import.d.ts +12 -0
  69. package/dist/types/skill-state/active-state.d.ts +12 -0
  70. package/dist/types/skill-state/workflow-hud.d.ts +6 -0
  71. package/dist/types/task/executor.d.ts +3 -2
  72. package/dist/types/task/index.d.ts +7 -1
  73. package/dist/types/task/output-manager.d.ts +1 -0
  74. package/dist/types/task/provider-retry-status.d.ts +8 -0
  75. package/dist/types/task/receipt.d.ts +9 -1
  76. package/dist/types/task/types.d.ts +23 -0
  77. package/dist/types/tools/ask-answer-registry.d.ts +2 -2
  78. package/dist/types/tools/bash-interactive.d.ts +4 -1
  79. package/dist/types/tools/bash.d.ts +3 -1
  80. package/dist/types/tools/image-gen.d.ts +4 -0
  81. package/dist/types/tools/index.d.ts +6 -0
  82. package/dist/types/tools/output-meta.d.ts +23 -2
  83. package/dist/types/tools/path-utils.d.ts +1 -0
  84. package/dist/types/tools/read.d.ts +0 -6
  85. package/dist/types/tools/review.d.ts +5 -7
  86. package/dist/types/tools/subagent.d.ts +2 -0
  87. package/dist/types/utils/gh.d.ts +13 -0
  88. package/dist/types/utils/image-resize.d.ts +1 -0
  89. package/dist/types/web/search/providers/kimi.d.ts +2 -0
  90. package/dist/types/web/search/providers/searxng.d.ts +7 -0
  91. package/dist/types/web/search/providers/xai.d.ts +2 -0
  92. package/package.json +10 -8
  93. package/scripts/acp-conformance-agent.ts +218 -0
  94. package/scripts/capture-gjc-bundle-settings.ts +306 -0
  95. package/scripts/dogfood-ralplan-review-conflicts.ts +272 -0
  96. package/scripts/generate-sdk-operation-inventory.ts +5 -0
  97. package/scripts/resident-memory-bench.ts +1341 -0
  98. package/scripts/run-acp-conformance.ts +290 -0
  99. package/src/async/job-manager.ts +99 -39
  100. package/src/cli/fast-help.ts +1 -1
  101. package/src/cli/plugin-cli.ts +176 -18
  102. package/src/commands/team.ts +19 -1
  103. package/src/config/file-lock.ts +11 -2
  104. package/src/config/settings-schema.ts +53 -2
  105. package/src/coordinator-mcp/question-gate-codec.ts +1 -1
  106. package/src/coordinator-mcp/server.ts +5 -12
  107. package/src/debug/index.ts +42 -17
  108. package/src/defaults/gjc/skills/deep-interview/SKILL.md +1 -0
  109. package/src/defaults/gjc/skills/ralplan/SKILL.md +25 -20
  110. package/src/defaults/gjc/skills/team/SKILL.md +2 -0
  111. package/src/defaults/gjc/skills/ultragoal/SKILL.md +39 -26
  112. package/src/defaults/gjc/skills/ultragoal/validation-batch-contracts.md +12 -0
  113. package/src/defaults/gjc-defaults.ts +4 -4
  114. package/src/exa/mcp-client.ts +12 -3
  115. package/src/exec/bash-executor.ts +144 -27
  116. package/src/extensibility/extensions/runner.ts +15 -0
  117. package/src/extensibility/extensions/types.ts +18 -1
  118. package/src/extensibility/gjc-plugins/constrained-hooks.ts +8 -2
  119. package/src/extensibility/gjc-plugins/index.ts +19 -2
  120. package/src/extensibility/gjc-plugins/installer.ts +189 -50
  121. package/src/extensibility/gjc-plugins/lifecycle-reconciliation.ts +199 -0
  122. package/src/extensibility/gjc-plugins/lifecycle.ts +626 -0
  123. package/src/extensibility/gjc-plugins/observability.ts +3 -3
  124. package/src/extensibility/gjc-plugins/prompt-appendix.ts +5 -1
  125. package/src/extensibility/gjc-plugins/runtime-adapters.ts +12 -2
  126. package/src/extensibility/gjc-plugins/runtime-quarantine.ts +121 -0
  127. package/src/extensibility/gjc-plugins/schema.ts +84 -12
  128. package/src/extensibility/gjc-plugins/session-validation.ts +9 -3
  129. package/src/extensibility/gjc-plugins/types.ts +141 -0
  130. package/src/extensibility/gjc-plugins/validation.ts +9 -0
  131. package/src/gjc-runtime/launch-tmux.ts +25 -6
  132. package/src/gjc-runtime/launch-worktree.ts +103 -1
  133. package/src/gjc-runtime/ledger-event-renderer.ts +1 -0
  134. package/src/gjc-runtime/managed-owner-admission.ts +1 -1
  135. package/src/gjc-runtime/ralplan-review-conflicts.ts +472 -0
  136. package/src/gjc-runtime/ralplan-runtime.ts +491 -27
  137. package/src/gjc-runtime/team-launch.ts +8 -0
  138. package/src/gjc-runtime/team-runtime.ts +140 -32
  139. package/src/gjc-runtime/team-worker-heartbeat.ts +149 -0
  140. package/src/gjc-runtime/tmux-owner-isolation.ts +10 -0
  141. package/src/gjc-runtime/tmux-sessions.ts +58 -13
  142. package/src/gjc-runtime/ultragoal-evidence.ts +6 -74
  143. package/src/gjc-runtime/ultragoal-runtime.ts +635 -612
  144. package/src/gjc-runtime/workflow-manifest.generated.json +37 -99
  145. package/src/gjc-runtime/workflow-manifest.ts +21 -70
  146. package/src/internal-urls/docs-index.generated.ts +16 -16
  147. package/src/modes/DESIGN.md +104 -0
  148. package/src/modes/acp/acp-agent.ts +298 -186
  149. package/src/modes/components/gjc-bundle-settings.ts +508 -0
  150. package/src/modes/components/irc-sidebar.ts +30 -1
  151. package/src/modes/components/notifications-settings-editor.ts +12 -1
  152. package/src/modes/components/oauth-selector.ts +68 -30
  153. package/src/modes/components/session-observer-overlay.ts +305 -86
  154. package/src/modes/components/settings-selector.ts +56 -5
  155. package/src/modes/components/status-line/gh.ts +16 -0
  156. package/src/modes/components/tool-status-header.ts +3 -15
  157. package/src/modes/components/transcript-viewer-overlay.ts +99 -24
  158. package/src/modes/controllers/command-controller.ts +42 -34
  159. package/src/modes/controllers/event-controller.ts +27 -16
  160. package/src/modes/controllers/extension-ui-controller.ts +193 -34
  161. package/src/modes/controllers/selector-controller.ts +160 -22
  162. package/src/modes/interactive-mode.ts +189 -62
  163. package/src/modes/jobs-observer.ts +1 -1
  164. package/src/modes/runtime-init.ts +3 -0
  165. package/src/modes/theme/theme.ts +11 -9
  166. package/src/modes/types.ts +88 -0
  167. package/src/prompts/agent-fragments/ralplan-persistence.md +4 -3
  168. package/src/prompts/system/eager-todo.md +8 -4
  169. package/src/prompts/system/system-prompt.md +11 -4
  170. package/src/prompts/tools/bash.md +5 -5
  171. package/src/prompts/tools/search-tool-bm25.md +5 -0
  172. package/src/prompts/tools/task.md +1 -1
  173. package/src/reminders/star-reminder.ts +4 -42
  174. package/src/runtime-mcp/manager.ts +19 -4
  175. package/src/sdk/acp/adapter.ts +22 -6
  176. package/src/sdk/broker/lifecycle.ts +18 -13
  177. package/src/sdk/broker/transport.ts +35 -3
  178. package/src/sdk/bus/attachment-registry.ts +5 -1
  179. package/src/sdk/bus/chat-daemon-cli.ts +4 -39
  180. package/src/sdk/bus/chat-daemon-control.ts +7 -3
  181. package/src/sdk/bus/config.ts +18 -2
  182. package/src/sdk/bus/index.ts +661 -126
  183. package/src/sdk/bus/kind-aware-reconciliation.ts +148 -73
  184. package/src/sdk/bus/lifecycle-commands.ts +4 -1
  185. package/src/sdk/bus/lifecycle-control-runtime.ts +403 -88
  186. package/src/sdk/bus/reconciliation-store.ts +95 -16
  187. package/src/sdk/bus/rich-draft.ts +1 -1
  188. package/src/sdk/bus/rich-render.ts +2 -2
  189. package/src/sdk/bus/telegram-adoption-intent.ts +574 -0
  190. package/src/sdk/bus/telegram-cli.ts +33 -8
  191. package/src/sdk/bus/telegram-daemon-cli.ts +1 -0
  192. package/src/sdk/bus/telegram-daemon-contract.ts +12 -4
  193. package/src/sdk/bus/telegram-daemon.ts +916 -23
  194. package/src/sdk/bus/telegram-reference.ts +40 -3
  195. package/src/sdk/bus/threaded-render.ts +48 -3
  196. package/src/sdk/bus/topic-registry.ts +20 -0
  197. package/src/sdk/host/query/revision-store.ts +36 -2
  198. package/src/sdk/host/reverse-leases.ts +44 -7
  199. package/src/sdk/prompt-status.ts +16 -3
  200. package/src/sdk/protocol/operation-inventory.generated.json +33 -0
  201. package/src/sdk/session.ts +89 -9
  202. package/src/session/agent-session.ts +844 -173
  203. package/src/session/artifacts.ts +22 -0
  204. package/src/session/auth-broker-config.ts +10 -3
  205. package/src/session/blob-store.ts +915 -24
  206. package/src/session/internal/managed-session-scope.ts +200 -111
  207. package/src/session/internal/managed-session-storage.ts +492 -62
  208. package/src/session/session-manager.ts +1614 -435
  209. package/src/session/session-storage.ts +38 -45
  210. package/src/session/streaming-output.ts +238 -68
  211. package/src/setup/credential-import.ts +75 -13
  212. package/src/skill-state/active-state.ts +32 -0
  213. package/src/skill-state/workflow-hud.ts +17 -0
  214. package/src/skill-state/workflow-mutation-guard.ts +496 -2
  215. package/src/task/executor.ts +122 -39
  216. package/src/task/index.ts +280 -45
  217. package/src/task/output-manager.ts +24 -14
  218. package/src/task/provider-retry-status.ts +16 -0
  219. package/src/task/receipt.ts +34 -8
  220. package/src/task/render.ts +6 -2
  221. package/src/task/types.ts +108 -0
  222. package/src/tools/ask-answer-registry.ts +12 -6
  223. package/src/tools/ask.ts +86 -55
  224. package/src/tools/ast-edit.ts +1 -0
  225. package/src/tools/ast-grep.ts +1 -0
  226. package/src/tools/bash-interactive.ts +8 -3
  227. package/src/tools/bash.ts +503 -60
  228. package/src/tools/find.ts +1 -0
  229. package/src/tools/image-gen.ts +29 -5
  230. package/src/tools/index.ts +6 -0
  231. package/src/tools/output-meta.ts +108 -14
  232. package/src/tools/path-utils.ts +3 -2
  233. package/src/tools/read.ts +18 -0
  234. package/src/tools/review.ts +5 -7
  235. package/src/tools/search.ts +1 -0
  236. package/src/tools/subagent-render.ts +6 -2
  237. package/src/tools/subagent.ts +6 -0
  238. package/src/tools/telegram-send.ts +6 -3
  239. package/src/utils/gh.ts +39 -0
  240. package/src/utils/image-resize.ts +3 -0
  241. package/src/web/search/providers/anthropic.ts +4 -4
  242. package/src/web/search/providers/kimi.ts +15 -5
  243. package/src/web/search/providers/searxng.ts +47 -4
  244. package/src/web/search/providers/xai.ts +7 -2
  245. package/dist/types/gjc-runtime/ultragoal-pipeline.d.ts +0 -23
  246. package/src/defaults/gjc/skills/ultragoal/pipeline-validation-contracts.md +0 -30
  247. package/src/gjc-runtime/ultragoal-pipeline.ts +0 -306
package/CHANGELOG.md CHANGED
@@ -2,13 +2,106 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.12.2] - 2026-07-30
6
+
7
+ ### Added
8
+
9
+ - `gjc ultragoal quality-gate init` scaffolds a multi-surface quality-gate template (`--surface` repeatable, `--out` required) so agents can fill evidence once and use read-only `quality-gate validate` multi-error diagnostics instead of discovering missing fields one checkpoint at a time (#3474).
10
+ - Ralplan can persist a typed `disposition` stage (`ralplan.review_conflicts.v1`) when Architect and Critic prescribe incompatible actions on the same plan target. Writes fail closed until every conflict has an explicit disposition, and source receipts must resolve against the same-pass Architect/Critic rows in the run index (#2902).
11
+ - Published bounded, redacted, hash-bound sealed perf-corpus memory evidence and an output-free replay notebook. The authenticated analysis identifies sustained heap growth on the `agent-session` and `tui` surfaces while keeping RSS/native allocation and p95 claims explicitly out of scope.
12
+ - The interactive terminal’s responsive IRC/todo work-lane contract now covers exact narrow/wide geometry, requested versus effective IRC visibility, direct-root pin ordering, todo lane bounds, remapped IRC toggles, and live composer shortcut hints.
13
+ - Managed-session startup now preserves bounded Windows ACL and identity failure classifications in path-redacted recovery guidance without broadening permissions, elevation, or unsafe fallback.
14
+
15
+ ### Fixed
16
+
17
+ - Terminal input now normalizes Option/Meta navigation and psmux modified-Enter encodings through the native key parser, keeping legacy, Kitty CSI-u, and modifyOtherKeys behavior consistent.
18
+ - Ultragoal CLI replay evidence now accepts any argv `command` instead of a small conservative executable allowlist. Proving a CLI-surface change with the project's own test runner (e.g. `bun test <file>`) was impossible: the allowlist only permitted `--version` probes, `bun/node -e "console.log(...)"` literals, read-only `git`, and `gjc read|status`, so real verification commands were rejected and forced agents into `replayExempt` metadata that additionally demanded a screenshot/automation/PTY fallback artifact. `replaySafe: true` is now the gating attestation, backed by the existing sandbox (subprocess isolation with explicit argv and no shell, timeout kill, 1 MiB output cap, env scrubbing). Every other rail is unchanged and still fails closed: shell-string commands, `replaySafe` not true, dangerous env vars, stdout/`recordedStdout` mismatch, and unexpected exit codes are all still rejected (#3533).
19
+ - Ultragoal CLI replay evidence now reads the replay file referenced by an `executorQa.artifactRefs` entry whose `kind` is `cli-replay`. Such a row short-circuited as an *inline* replay record, so its `path` was never read and validation failed with a confusing `schemaVersion must be 1` diagnostic pointing at the ref instead of the file — forcing an undocumented workaround of renaming the ref's `kind`. A row is now treated as inline only when it actually carries replay fields (#3533).
20
+ - Broker artifact cleanup no longer promotes a non-empty `cleanup_pending` quarantine to transcript-phase completion. The broker advances only when the retained quarantine is root-only/empty or when the lower layer returns `artifacts_removed`, so artifact bytes cannot vanish behind a success receipt (#3489).
21
+ - `gjc --worktree` / `gjc -w` launch no longer crashes with a raw uncaught `EEXIST` when the worktree bucket directory (`<repo>.gajae-code-worktrees`) is a broken symbolic link to unmounted or offloaded cold storage. The launch distinguishes dangling links and non-directory entries from valid directory symlinks or Windows junctions, reclassifies mkdir races, avoids disclosing raw link targets or unsafe shell commands, and never deletes or replaces an obstructing entry.
22
+ - POSIX parent identity reproof/fsync is now centralized before every promotable artifact-phase result, preventing a crash-window where a rename is lost after durable retirement is recorded (#3489).
23
+ - Artifact retirement, planned paths, retained authority, and transcript retry in both managed reconciliation and deletion now bind to the newest published `pendingEvidence` attempt, preventing stranded detached transcripts at paths absent from the newest receipt after a crash (#3489).
24
+ - Detached task receipts for in-memory parent sessions no longer advertise dead `agent://` output URIs. TaskTool allocates a session-lifetime durable artifact root under the process temp directory, persists child outputs there, authorizes parent and same-session descendants for scoped resolution, and omits the URI entirely when durable allocation fails (#3471).
25
+ - Managed-session replacement and cleanup now bind Windows destination mutation to exact native identity, keep lock acquisition/release retryable without reviving lost ownership, and report retained artifact payloads as `cleanup_pending` until only the verified root remains.
26
+ - Resuming a session no longer crashes with an unhandled rejection when another session transition is already running. The session picker dispatches resume through a void-returning callback, and `handleResumeSession` had no re-entrancy guard, so a second selection (or a resume issued while compaction, handoff, or a fork was in flight) reached `switchSession` and the `{ code: "busy" }` transition error rejected a promise nobody awaited. Resume now ignores an overlapping request with a status message, reports a busy transition as status, and still propagates every other failure. The progress lease is released on all paths.
27
+ - The interactive `Working…` indicator now remains visible and explicitly labels owner-scoped detached background work across foreground completion, provider errors, pending-submission aborts, and job completion, without resurrecting after TUI disposal (#3479).
28
+ - Activity-indicator suspension now detaches and restores the exact owned loader instead of stopping foreign transition UI; optimistic pre-init prompts still show and clear their spinner, context clear retains its eager teardown contract, and resume cancellation preserves transient state until session mutation actually begins.
29
+ - Activity-indicator stop and suspension helpers now fail safely for lightweight controller contexts with absent or partial status rails, while full interactive contexts retain exact loader detach/restore ownership.
30
+
31
+ ## [0.12.1] - 2026-07-29
32
+
33
+ ### Fixed
34
+
35
+ - Provider retry classification prefers the typed `stream_first_event_timeout` transport fact when present, falling back to error-message regex for message-only callers (#3496).
36
+ - Team Linux worker memory-guard replacement no longer holds the team task-mutation fence across the successor startup-ack wait, so concurrent `worker-startup-ack` can publish and selector-replacement no longer hangs under CI contention.
37
+ - Kitty/Ghostty inline images no longer remain visually pinned when transcript, pinned, or overlay rows are replaced, removed, scrolled, resized, or fully repainted. The TUI now parses only bounded named placements, soft-deletes overwritten placements from the previously committed physical frame, retains transmitted pixels, and restores placements from application scrollback without retransmitting image data.
38
+ - Reviewer `report_finding` evidence is no longer injected into caller-owned strict JTD completion data; full findings are published separately through a bounded artifact reference, and failed evidence publication now fails the task closed (#2893).
39
+ - Managed-session startup failures now include their bounded preparation classification (and path-free native durability diagnostic when available), so Windows launch crashes no longer collapse to an unactionable generic error while filesystem paths and raw OS messages remain redacted (#3383).
40
+ - Single-model sessions now rotate immediately to another stored provider credential after a content-free quota or rate-limit failure, without requiring a synthetic model fallback chain. Credential rotation is replay-safe for content-free failures regardless of extension lifecycle participation, and traverses the full credential pool independent of `retry.maxRetries` (#3491).
41
+ - External credential discovery now follows `CLAUDE_CONFIG_DIR` and `CODEX_HOME` instead of always reading `~/.claude` and `~/.codex`, so importing from an account switcher (or any relocated Claude Code / Codex CLI config root) picks up the account the launching shell selected. Both variables resolve through the credential env trust boundary and must be absolute; redacted summaries name the variable, never the resolved path.
42
+ - The `acp_conformance` CI job runs again. The pinned upstream `acpx` checkout resolves its own imports (`@agentclientprotocol/sdk`, `zod`) from its own tree, but its dependencies were never installed, so the corpus runner aborted with `Cannot find module 'zod/v4'` before executing a single case. The checkout is now installed after provenance verification, and the reused warm cache still skips the reinstall.
43
+
44
+ ### Added
45
+
46
+ - User-created Telegram forum topics can now start a GJC session by selecting the home folder, choosing a verified recent work folder, or entering an explicit folder path. The selected topic is adopted by the new session without creating or deleting a separate Telegram topic.
47
+
48
+ ### Fixed
49
+
50
+ - Detached subagents spawned by the `task` tool are resumable again. The resume gate treated a missing record-level `sessionFile` as missing context even though task and managed-persistence sessions retain the descriptor consumed by the resume runner, so persisted role agents always fell back with `context_unavailable`. Resume eligibility now accepts an owner-compatible retained descriptor while preserving `not_found`, explicit `context_unavailable`, missing-runner `no_runner`, and `resume_failed` outcomes.
51
+ - Ralplan supports opt-in automatic handoff to ultragoal or team through a durable runtime-owned final receipt, with read-only team preflight and PLANNING-STUCK dominance.
52
+ - Subagent setup failures now retain a bounded, redacted cause through live progress, async snapshots, inspect/await, and terminal receipts instead of reporting an empty generic failure.
53
+ - Telegram notification sound can be set to all, important, or none; the reference CLI exposes this with `--sound <all|important|none>`, defaulting to all. Important (ask/idle only) and none are explicit opt-ins for quieter notifications.
54
+ - First-event provider timeouts are configurable and replayed only by AgentSession with a bounded attempt budget, progress-aware safety checks, and measured exhaustion details.
55
+ ### Fixed
56
+ - Telegram image delivery now converts WebP and other decodable image formats to Telegram-compatible JPEG or PNG photos, preserves MIME types for files sent with `telegram_send`, and falls back to named document uploads when conversion is unsupported or invalid.
57
+ - `bun run install:dev` now removes only Bun launchers that resolve to the current checkout's CLI wrapper before validating the managed source link, preventing `bun link` from leaving `~/.bun/bin/gjc` ahead of the new `~/.local/bin/gjc` link on `PATH`.
58
+ - A same-tree detached/resumed subagent could not read a verified `agent://`/`artifact://` reference its parent could read (`No session - agent outputs unavailable`), even though parent/child/sibling tree reads are an explicit acceptance criterion of #326: the runtime never supplied `ToolSession.getAuthorizedArtifactsDirs`, so an adopted subagent (whose own `getArtifactsDir()` intentionally collapses to `null`) reached the scoped resolver with zero authorized directories. `ToolSession` now exposes `getAuthorizedArtifactsDirs`, derived only from the session's own explicitly adopted/shared `ArtifactManager` directory, and it is threaded through `read`, `find`, `search`, `ast_grep`, and `ast_edit`'s internal-URL resolution. No registry-wide session enumeration was added; unrelated sessions, missing metadata, and integrity failures remain denied and fail-closed exactly as before (#3302).
59
+ - The auth-broker connection (`GJC_AUTH_BROKER_URL` / `GJC_AUTH_BROKER_TOKEN`) is now resolved from trusted environment sources only. `discoverAuthStorage()` turns that configuration into the `AuthStorage` used for every provider, so reading it through the merged view that includes the caller's `cwd/.env` let a repository replace the agent's credential store wholesale — serving the credentials it authenticates with and receiving the ones it writes back. Resolution now uses the non-project resolver; shell, config-file and token-file configuration is unchanged.
60
+ - Image generation now resolves its OpenAI base URL and its `GOOGLE_API_KEY` fallback from trusted environment sources only. Both were read through the merged view that includes the caller's `cwd/.env`, so a repository could plant a `.env` choosing where authenticated image requests go, or supplying the credential they authenticate with. They now use the non-project resolver; shell and user-level configuration is unchanged, and the trusted `getEnvApiKey("google")` lookup still takes precedence over the fallback.
61
+ - GJC-managed tmux sessions work on macOS again. `gjc session create` failed with `gjc_tmux_profile_tag_failed_cleanup_failed` and leaked the session it had just created, and every close path failed with `gjc_tmux_owner_unverifiable` or `managed_owner_supervisor_signal_failed`. Three non-Linux gaps fed each other: guarded mutations pinned `#{pid}` to the placeholder PID that non-Linux server probes report (which no live tmux server can match), the owner start-time proof only read `/proc`, and SIGTERM dispatch only used the pidfd/handle-backed native signal that deliberately fails closed on macOS. Guards now emit the `#{pid}` clause only for a proven PID, the start-time proof falls back to the natives process incarnation off Linux, and macOS delivers SIGTERM to the already-proved owner PID. Session identity is still pinned by session id, session name and owner generation, and Linux behaviour is unchanged.
62
+
63
+ ### Changed
64
+
65
+ - Session Observer now incrementally projects append-only session messages and narrowly patches late tool results, avoiding repeated full-history transcript projection while preserving eager output parity and safe full-projection fallback for ambiguous source changes.
66
+ - Compaction now publishes complete pruned tool outputs as session artifacts transactionally, carries active goal/workflow/todo state into summaries, and skips synthetic auto-continue when no unfinished work remains.
67
+
68
+ ### Fixed
69
+
70
+ - Explicit `--mcp-config` sessions now honor each server's configured connection timeout during startup instead of aborting otherwise healthy tools-only servers at the ordinary 1.75-second startup ceiling; sessions without an explicit config retain the existing bounded startup policy.
71
+
72
+ ### Resume fixes
73
+
74
+ - Eager todo initialization now gives the model the actual phased `todo_write` payload shape (`ops` → `init` → `list` → `phase`/`items`) instead of instructing it to send unsupported `content`, `details`, and status fields, preventing the first forced todo call from failing validation (#3403).
75
+
76
+ ### Fixed
77
+ - Fast CLI help now advertises the active `search` built-in tool instead of the retired `grep` name.
78
+ - `bun run restart:sdk-broker` no longer crashes with an uncaught `unknown broker operation` error when the live broker predates the `broker.shutdown` operation; the restart now falls back to an identity-fenced `SIGTERM` on the published broker pid, which stops that process through the same rollback path before the replacement is started.
79
+ - `bun run restart:sdk-broker --close-session-hosts` closes the broker-hosted sessions before replacing the broker, so ACP clients no longer reattach to session hosts that keep serving the source they were spawned with. Only sessions served by a `sdk session-host-internal` process are selected, and each one is closed through the live broker's verified-identity teardown.
80
+
81
+ - Coordinator MCP now reconciles canonical structured questions from every workflow stage without misclassifying row-level gate diagnostics as malformed pagination, and unwraps accepted SDK gate-answer envelopes before reporting the terminal resolution.
82
+ - Queued named tool choices are revalidated against the live model and active tool set before each request, preventing first-turn eager todo, resolve, or yield flows from sending a stale forced choice after preflight tool changes.
83
+ - Ralplan role-agent writes now resolve an existing run's immutable owner session instead of creating workflow state and artifacts under each Planner/Architect/Critic transcript session; conflicting explicit session ids fail closed, and receipts expose the owner `session_id`.
84
+ - Subagent task panels now show the fast-mode glyph for the resolved provider in both live and completed states (#3402).
85
+ - Auto-retry now strips the whole trailing run of failed assistant attempts before continuing. A turn wedged by an `invalid_prompt` repair leaves two error assistant messages behind, and dropping only the last one left an assistant tail that `agent.continue()` refuses, so the retry died with "Retry continuation failed to start" and the turn was lost.
86
+
87
+ - Session Observer now receives persisted subagent session paths on lifecycle and progress events, so active ralplan reviewer transcripts render instead of remaining at `No transcript entries yet`.
88
+ ### Changed
89
+
90
+ - Bash tool output now keeps only the last 1 KiB when it exceeds the inline capture budget, reducing noisy model input and nudging callers toward focused commands and dedicated search tools. Users who explicitly configure `tools.artifactTailBytes` or `tools.artifactHeadBytes` can set the tail budget or opt into head+tail middle elision. Complete streams received by the Bash tool remain artifact-backed when storage is available; client-truncated ACP tails stay explicitly marked incomplete and cannot be reconstructed locally. Direct user `!` commands retain the existing shared executor window.
91
+
5
92
  ## [0.12.0] - 2026-07-28
6
93
  ### Resume fixes
7
94
 
95
+ - Status-line pull-request discovery no longer lets the background `gh pr view` process inherit the interactive TUI's stdin, preventing a misconfigured or prompting `gh` executable from stealing keystrokes; the lookup now also fails closed when `gh` is unavailable and terminates after a bounded timeout (#3354).
96
+ - Completed `!` shell commands issued during an active agent turn now leave the bottom-pinned pending surface immediately instead of obscuring the live status area until the next prompt; the completed command is still retained for normal transcript insertion.
8
97
  - 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.
98
+ - `gjc team` workers now publish their own heartbeat while a turn or owned background job is active, so a worker inside a single long tool call is no longer reported stale and stripped of its task claim. Liveness was published only when the model remembered to call `gjc team api update-worker-heartbeat` between turns, so any tool call longer than `GJC_TEAM_HEARTBEAT_STALE_MS` (default 120s) — a build, a test suite, a large read — caused the claim file to be deleted, the `in_progress` task to be reset to `pending`, and the worker to be refused re-claim with `worker_not_live:<worker>:stale_heartbeat` while it was still running, all against a 30-minute claim lease. The worker session now publishes at a third of the stale window (minimum 1ms, capped at 30s) from the top-level session only, and `gjc team` exports the configured window into worker panes so a tightened window applies to the workers policing it too. Recovery semantics are unchanged: a worker that publishes nothing is still recovered exactly as before.
99
+ - With all-tool discovery enabled, `task.eager` now keeps the `task` tool active so its delegation instruction can actually be followed; discovery guidance now distinguishes activating a tool from executing it and directs explicit parallel/delegation requests to discover the subagent capability before claiming workers started.
100
+ - Unknown `gjc team api` operations now fail as normal CLI usage errors instead of invoking the global uncaught-exception crash reporter. JSON mode returns a compact typed receipt with the invalid operation and suggestions; text mode prints one actionable line. Common mistakes such as `heartbeat` now point to `read-worker-heartbeat` or `update-worker-heartbeat`, and operation validation runs before team-state lookup so a missing `team_name` cannot hide the actual command error.
9
101
  - 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
102
  - 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
103
  - 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.
104
+ - Session resident-cache directories are now swept when the process exits abnormally. `EphemeralBlobStore` removed its directory only in `dispose()`, and the directory name embeds the pid, so a terminated run's cache could never be collected by a later run. A developer machine held seven of them from dead pids, up to 26 days old, totalling 13.4 MB of externalized session text.
12
105
  - 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
106
  - 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
107
  - 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.
@@ -18,6 +111,14 @@
18
111
  - 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
112
  - `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
113
  - 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.
114
+ - Web-search provider endpoints and keys are now resolved from trusted environment sources only: `KIMI_SEARCH_BASE_URL` / `MOONSHOT_SEARCH_BASE_URL`, `KIMI_SEARCH_API_KEY` / `MOONSHOT_SEARCH_API_KEY`, `XAI_SEARCH_BASE_URL`, and `ANTHROPIC_SEARCH_BASE_URL` / `ANTHROPIC_SEARCH_API_KEY`. Each provider sends its credential to the endpoint it resolves, so reading them through the merged view that includes the caller's `cwd/.env` let a repository redirect search traffic and collect the user's search credentials. Shell and user-level configuration is unchanged.
115
+ - The Exa MCP API key (`EXA_API_KEY`) is now resolved from trusted environment sources only. The key authenticates every Exa MCP call and travels in the request URL, so reading it through the merged view that includes the caller's `cwd/.env` let a repository decide which account the agent's searches run through — and therefore who could see those queries. `findApiKey()` also now returns `null` rather than `undefined` when nothing supplies a key, matching its declared type.
116
+ - The notifications channel switch and the Telegram reference client's bot credentials are now resolved from trusted environment sources only. `notificationsEnabled()` read `GJC_NOTIFICATIONS` / `GJC_NOTIFICATIONS_TOKEN` straight from the merged view that includes the caller's `cwd/.env` — unlike its siblings in `config.ts` and `session-control.ts`, which already read an injected env record — so a repository could open the session control/answer channel. The Telegram client's `GJC_TG_BOT_TOKEN` / `GJC_TG_CHAT_ID` fallbacks had the same exposure, and that client is normally run from inside a repository, so a planted bot token would have routed the session's notifications and the operator's replies to a bot the repository chose.
117
+ - SearXNG search configuration (`SEARXNG_ENDPOINT`, `SEARXNG_TOKEN`, `SEARXNG_BASIC_USERNAME`, `SEARXNG_BASIC_PASSWORD`) is now resolved from trusted environment sources only, completing the web-search provider family. The endpoint receives the `Authorization: Basic`/`Bearer` header, so reading these through the merged view that includes the caller's `cwd/.env` let a repository redirect the search and hand over the credential. An intentionally empty username or password remains meaningful for basic auth and is still honoured when it comes from a trusted source, while an empty value planted by the project `.env` is rejected.
118
+ - The `natives-*` architecture docs no longer describe native APIs that were removed. `countTokens`, `PhotonImage.parse/resize/encode` and `projfsOverlayProbe/Start/Stop` are absent from the addon's JS surface, and `tokens.rs`, `image.rs` and `projfs_overlay.rs` are not in the crate. ProjFS now reaches users through the iso backend (`isoProbe`/`isoStart`/`isoStop` with `IsoBackendKind.Projfs`, implemented in the `pi-iso` crate), and image decode/transform/encode moved to `Bun.Image` in TypeScript.
119
+ - `docs/ooo-bridge-extension-contract.md` no longer inverts the scope of the two directory overrides. `GJC_CONFIG_DIR` is a home-relative name (`<home>/<name>`, default `~/.gjc`), not a project directory name, and `GJC_CODING_AGENT_DIR` overrides the agent directory path through `path.resolve` rather than naming a directory under `$HOME`.
120
+ - Telegram deep-interview multi-select prompts now mark each option as checked or unchecked after every selection while preserving canonical option values and numeric callback routing.
121
+ - SDK revision-store spill directories are now removed when the process exits abnormally. `close()` already removed them, but a terminated session never reaches `close()`, so the spilled snapshot payload stayed in the system temp directory — unlike the sibling `shell-snapshot` and `python-runner-artifact` caches, which already registered a postmortem sweep. Only `mkdtemp` spill directories are tracked; a caller-supplied `storageDir` is durable session storage and is never swept.
21
122
  - 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
123
  - 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
124
  - 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.
@@ -29,10 +130,20 @@
29
130
  - 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
131
  - 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
132
  - 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).
133
+ - ACP prompt completion no longer hangs clients: terminal prompt outcomes are now projected through ACP after the SDK finalizes them.
134
+ - Prompt terminalization now exposes exactly one normalized outcome per accepted prompt, preserving the terminal reason or controlled failure code across SDK and ACP clients.
135
+ - ACP clients can reconnect to a live session while replaying their MCP server declarations. The live session keeps its immutable MCP configuration instead of rejecting the reconnect as a configuration mutation.
136
+ - ACP `AskUserQuestion` now routes through the registered SDK UI provider as a schema-valid form elicitation, including selector, free-text, and navigation-control responses for Air.
137
+ - Telegram `/session_create` and cold resume no longer route macOS or other non-Linux hosts through the Linux-only managed-owner supervisor. Non-Linux launches now bind success and cleanup to the exact tmux server, native session, and live pane process identities, scrub inherited managed-owner authority, and reject children that die during launch stabilization; Linux keeps its existing owner-isolation transaction.
138
+
139
+ ### Changed
140
+
141
+ - Session Observer and the main transcript viewer no longer re-project and re-layout their full transcript on every paint. Source changes still refresh through registry/session-event notifications, while navigation rebuilds only affected layout variants; deterministic counters and replacement-safety coverage preserve selection, follow-tail, raw, expanded, fullscreen, mouse, theme, width, and source-replacement behavior.
32
142
 
33
143
  ### Added
34
144
 
35
145
  - 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).
146
+ - Added `bun run restart:sdk-broker` for authenticated, identity-checked SDK broker replacement during local Air/ACP testing.
36
147
  - 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
148
  - 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
149
  - `/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).
@@ -16,6 +16,8 @@ export interface AsyncJob {
16
16
  promise: Promise<void>;
17
17
  resultText?: string;
18
18
  errorText?: string;
19
+ /** Safe, bounded cause when session setup failed before the LLM began work. */
20
+ setupFailureSummary?: string;
19
21
  metadata?: AsyncJobMetadata;
20
22
  /**
21
23
  * Registry id of the agent that registered the job (e.g. "0-Main",
@@ -48,11 +50,15 @@ export interface AsyncJobMetadata {
48
50
  * non-terminal and non-delivering: the run suspended at a safe boundary and the
49
51
  * subagent can be resumed from its persisted sessionFile. `completed` always
50
52
  * wins a race with a late pause because the run returns it once it has actually
51
- * finished.
53
+ * finished. A `failed` outcome retains a safe setup diagnostic for receipt rendering.
52
54
  */
53
55
  export type SubagentRunOutcome = {
54
56
  kind: "completed";
55
57
  text: string;
58
+ } | {
59
+ kind: "failed";
60
+ text: string;
61
+ setupFailureSummary?: string;
56
62
  } | {
57
63
  kind: "paused";
58
64
  note?: string;
@@ -110,7 +116,11 @@ export interface SubagentRecord {
110
116
  historicalJobIds: string[];
111
117
  status: SubagentLifecycle;
112
118
  sessionFile: string | null;
113
- /** False for ephemeral sessions (no persistent artifacts dir). */
119
+ /**
120
+ * Explicit veto, not a complete availability result. False always denies;
121
+ * true still requires an owner-compatible descriptor or non-blank session
122
+ * file, followed by a separately available runner (`no_runner` otherwise).
123
+ */
114
124
  resumable: boolean;
115
125
  queued?: {
116
126
  ownerId?: string;
@@ -287,7 +297,11 @@ export declare class AsyncJobManager {
287
297
  status?: SubagentLifecycle;
288
298
  reason?: string;
289
299
  };
290
- /** Resume a non-running subagent from its sessionFile, optionally injecting a message first. */
300
+ /**
301
+ * Resume a non-running subagent from retained context: an owner-compatible
302
+ * descriptor or a legacy session file. Workflow routing keeps `not_found`,
303
+ * `context_unavailable`, `no_runner`, and `resume_failed` distinct.
304
+ */
291
305
  resumeSubagent(subagentId: string, filter?: AsyncJobFilter, message?: string): {
292
306
  ok: boolean;
293
307
  status?: SubagentLifecycle;
@@ -133,6 +133,12 @@ export declare const SETTINGS_SCHEMA: {
133
133
  readonly values: readonly ["copy-retain", "disabled"];
134
134
  readonly default: "copy-retain";
135
135
  };
136
+ readonly "sdk.promptDeadlineMs": {
137
+ readonly type: "number";
138
+ readonly default: 1800000;
139
+ readonly description: "SDK-owned prompt deadline; ACP has no separate timeout.";
140
+ readonly validate: (value: number) => boolean;
141
+ };
136
142
  readonly "notifications.enabled": {
137
143
  readonly type: "boolean";
138
144
  readonly default: false;
@@ -158,6 +164,17 @@ export declare const SETTINGS_SCHEMA: {
158
164
  readonly type: "boolean";
159
165
  readonly default: true;
160
166
  };
167
+ readonly "notifications.telegram.sound": {
168
+ readonly type: "enum";
169
+ readonly values: readonly ["all", "important", "none"];
170
+ readonly default: "all";
171
+ readonly ui: {
172
+ readonly tab: "notifications";
173
+ readonly label: "Telegram Notification Sounds";
174
+ readonly description: "Choose which Telegram notifications play a sound.";
175
+ readonly editing: "notification-atomic";
176
+ };
177
+ };
161
178
  readonly "notifications.telegram.rich.enabled": {
162
179
  readonly type: "boolean";
163
180
  readonly default: true;
@@ -406,6 +423,26 @@ export declare const SETTINGS_SCHEMA: {
406
423
  readonly options: "runtime";
407
424
  };
408
425
  };
426
+ readonly "session.resumeModelBehavior": {
427
+ readonly type: "enum";
428
+ readonly values: readonly ["keepSessionModel", "useCurrentDefault", "ask"];
429
+ readonly default: "keepSessionModel";
430
+ readonly ui: {
431
+ readonly tab: "model";
432
+ readonly label: "Resume Model Behavior";
433
+ readonly description: "When resuming a session: keep the model that session last used, switch to the currently configured default model, or ask (TUI only; falls back to keeping the session's model in headless/CLI resume).";
434
+ readonly options: readonly [{
435
+ readonly value: "keepSessionModel";
436
+ readonly label: "Keep session's saved model";
437
+ }, {
438
+ readonly value: "useCurrentDefault";
439
+ readonly label: "Use current default model";
440
+ }, {
441
+ readonly value: "ask";
442
+ readonly label: "Ask on resume (TUI only)";
443
+ }];
444
+ };
445
+ };
409
446
  readonly modelTags: {
410
447
  readonly type: "record";
411
448
  readonly default: ModelTagsSettings;
@@ -423,6 +460,11 @@ export declare const SETTINGS_SCHEMA: {
423
460
  readonly default: 0.05;
424
461
  readonly validate: (value: number) => boolean;
425
462
  };
463
+ readonly "gjc.ralplan.autoHandoff": {
464
+ readonly type: "enum";
465
+ readonly values: readonly ["off", "ultragoal", "team"];
466
+ readonly default: "off";
467
+ };
426
468
  readonly "gjc.ralplan.maxIterations": {
427
469
  readonly type: "number";
428
470
  readonly default: 5;
@@ -952,8 +994,8 @@ export declare const SETTINGS_SCHEMA: {
952
994
  readonly default: true;
953
995
  readonly ui: {
954
996
  readonly tab: "appearance";
955
- readonly label: "Status Line Action Hints";
956
- readonly description: "Show contextual keyboard shortcuts in the status line";
997
+ readonly label: "Composer Shortcut Hints";
998
+ readonly description: "Show contextual keyboard shortcuts in the composer placeholder";
957
999
  };
958
1000
  };
959
1001
  readonly "statusLine.leftSegments": {
@@ -1442,6 +1484,16 @@ export declare const SETTINGS_SCHEMA: {
1442
1484
  readonly description: "Maximum provider stream replay retries for replay-safe transient stream failures. Counts retries, not the first attempt. Set to 0 to disable provider stream retries.";
1443
1485
  };
1444
1486
  };
1487
+ readonly "retry.streamFirstEventTimeoutMs": {
1488
+ readonly type: "number";
1489
+ readonly default: 100000;
1490
+ readonly validate: (value: number) => boolean;
1491
+ readonly ui: {
1492
+ readonly tab: "model";
1493
+ readonly label: "First Event Timeout";
1494
+ readonly description: "Maximum wait for the first provider stream event, in ms. Set to 0 to disable the watchdog.";
1495
+ };
1496
+ };
1445
1497
  readonly "retry.fallbackChains": {
1446
1498
  readonly type: "record";
1447
1499
  readonly default: Record<string, string[]>;
@@ -4209,6 +4261,7 @@ export interface RetrySettings {
4209
4261
  maxDelayMs: number;
4210
4262
  requestMaxRetries: number;
4211
4263
  streamMaxRetries: number;
4264
+ streamFirstEventTimeoutMs: number;
4212
4265
  }
4213
4266
  export interface MemoriesSettings {
4214
4267
  enabled: boolean;
@@ -4314,6 +4367,7 @@ export interface NotificationsSettings {
4314
4367
  telegram: {
4315
4368
  botToken: string | undefined;
4316
4369
  chatId: string | undefined;
4370
+ sound: "all" | "important" | "none";
4317
4371
  btw: {
4318
4372
  enabled: boolean;
4319
4373
  };
@@ -1,7 +1,16 @@
1
1
  import type { TSchema } from "@gajae-code/ai";
2
2
  import type { CustomTool, CustomToolResult } from "../extensibility/custom-tools/types";
3
3
  import type { ExaRenderDetails, ExaSearchResponse, MCPTool, MCPToolWrapperConfig } from "./types";
4
- /** Find EXA_API_KEY from Bun.env or .env files */
4
+ /**
5
+ * Find `EXA_API_KEY` from trusted environment sources.
6
+ *
7
+ * The key authenticates every Exa MCP call and travels in the request URL, so
8
+ * whatever can set it decides which account the agent's searches run through —
9
+ * and therefore who can see those queries. `$env` merges the caller's `cwd/.env`
10
+ * into `process.env`, so reading it there would let repository content supply
11
+ * that account. Resolve it the same way provider credentials are: launching
12
+ * shell plus GJC/user-owned `.env` files, never the project `.env`.
13
+ */
5
14
  export declare function findApiKey(): string | null;
6
15
  /** Fetch available tools from Exa MCP */
7
16
  export declare function fetchExaTools(apiKey: string | null, toolNames: string[]): Promise<MCPTool[]>;
@@ -1,6 +1,43 @@
1
1
  import { type MinimizerOptions } from "@gajae-code/natives";
2
2
  import { type ShellMinimizerSettings } from "../config/settings";
3
+ import { type TerminalArtifactPublisher } from "../session/streaming-output";
4
+ export interface BashArtifactSaveSummary {
5
+ artifactId: string;
6
+ complete: boolean;
7
+ omittedBytes?: number;
8
+ }
9
+ export type BashMinimizedSaveReturn = BashArtifactSaveResult | BashArtifactSaveSummary | string | undefined;
10
+ export type BashArtifactSaveResult = {
11
+ status: "saved";
12
+ artifactId: string;
13
+ complete: true;
14
+ omittedBytes?: undefined;
15
+ } | {
16
+ status: "saved";
17
+ artifactId: string;
18
+ complete: false;
19
+ omittedBytes: number;
20
+ } | {
21
+ status: "unavailable";
22
+ } | {
23
+ status: "failed";
24
+ diagnostic: string;
25
+ };
26
+ export declare function normalizeMinimizedSaveResultForTests(value: BashMinimizedSaveReturn, originalText: string): BashArtifactSaveResult;
3
27
  export interface BashExecutorOptions {
28
+ /**
29
+ * Invoked when the native minimizer rewrote the command's output, giving
30
+ * the caller a chance to persist the lossless original capture (typically
31
+ * via the session's `ArtifactManager`). Complete saves preserve the
32
+ * historical `[raw output: artifact://<id>]` footer; capped saves carry an
33
+ * honest retained/omitted reference. A legacy string id is still accepted
34
+ * for non-tool callers and is classified from the original UTF-8 byte count.
35
+ */
36
+ onMinimizedSave?: (originalText: string, info: {
37
+ filter: string;
38
+ inputBytes: number;
39
+ outputBytes: number;
40
+ }) => Promise<BashMinimizedSaveReturn>;
4
41
  cwd?: string;
5
42
  timeout?: number | null;
6
43
  onChunk?: (chunk: string) => void;
@@ -19,24 +56,18 @@ export interface BashExecutorOptions {
19
56
  /** Artifact path/id for full output storage */
20
57
  artifactPath?: string;
21
58
  artifactId?: string;
59
+ /** Optional terminal publisher for managed artifacts without writable paths. */
60
+ artifactPublisher?: TerminalArtifactPublisher;
61
+ /** Optional Bash-specific retained tail budget in bytes. */
62
+ spillThreshold?: number;
63
+ /** Optional Bash-specific retained head budget in bytes. */
64
+ headBytes?: number;
22
65
  /** Execute without retaining a native Shell in the persistent session registry. */
23
66
  oneShot?: boolean;
24
67
  /** Ignore user-configured shell command prefixes. Used by constrained read-only shells. */
25
68
  ignoreShellPrefix?: boolean;
26
69
  /** Skip sourced shell snapshots. Used by constrained read-only shells. */
27
70
  disableShellSnapshot?: boolean;
28
- /**
29
- * Invoked when the native minimizer rewrote the command's output, giving
30
- * the caller a chance to persist the lossless original capture (typically
31
- * via the session's `ArtifactManager`). The returned id is spliced into
32
- * the sink output as `artifact://<id>` so the agent can retrieve the raw
33
- * bytes. Return `undefined` to skip the footer.
34
- */
35
- onMinimizedSave?: (originalText: string, info: {
36
- filter: string;
37
- inputBytes: number;
38
- outputBytes: number;
39
- }) => Promise<string | undefined>;
40
71
  }
41
72
  export interface BashResult {
42
73
  output: string;
@@ -48,6 +79,8 @@ export interface BashResult {
48
79
  outputLines: number;
49
80
  outputBytes: number;
50
81
  artifactId?: string;
82
+ artifactTruncatedBytes?: number;
83
+ artifactFailureDiagnostic?: string;
51
84
  }
52
85
  /** Number of persistent shell sessions currently retained (owner gauge). */
53
86
  export declare function getShellSessionCount(): number;
@@ -7,7 +7,7 @@
7
7
  * - Register commands, keyboard shortcuts, and CLI flags
8
8
  * - Interact with the user via UI primitives
9
9
  */
10
- import type { AgentMessage, AgentToolResult, AgentToolUpdateCallback, ThinkingLevel } from "@gajae-code/agent-core";
10
+ import type { AgentMessage, AgentToolResult, AgentToolUpdateCallback, RunSettlementProof, ThinkingLevel } from "@gajae-code/agent-core";
11
11
  import type { CompactionResult } from "@gajae-code/agent-core/compaction";
12
12
  import type { Api, AssistantMessageEvent, AssistantMessageEventStream, Context, ImageContent, Model, ProviderResponseMetadata, SimpleStreamOptions, Static, TextContent, Tool, TSchema, UsageReport } from "@gajae-code/ai";
13
13
  import type { OAuthCredentials, OAuthLoginCallbacks } from "@gajae-code/ai/utils/oauth/types";
@@ -22,7 +22,7 @@ import type { ExecOptions, ExecResult } from "../../exec/exec";
22
22
  import type { CustomEditor } from "../../modes/components/custom-editor";
23
23
  import type { WorkflowGateEmitter } from "../../modes/shared/agent-wire/workflow-gate-broker";
24
24
  import type { Theme } from "../../modes/theme/theme";
25
- import type { ClientBridgePermissionOption, ClientBridgePermissionOutcome, ClientBridgePermissionToolCall } from "../../session/client-bridge";
25
+ import type { ClientBridge, ClientBridgePermissionOption, ClientBridgePermissionOutcome, ClientBridgePermissionToolCall } from "../../session/client-bridge";
26
26
  import type { CustomMessage } from "../../session/messages";
27
27
  import type { ReadonlySessionManager, SessionManager } from "../../session/session-manager";
28
28
  import type { BashToolDetails, BashToolInput, FindToolDetails, FindToolInput, ReadToolDetails, ReadToolInput, SearchToolDetails, SearchToolInput, WriteToolInput } from "../../tools";
@@ -249,8 +249,14 @@ export interface ExtensionContext {
249
249
  model: Model | undefined;
250
250
  /** Whether the agent is idle (not streaming) */
251
251
  isIdle(): boolean;
252
+ /** Stable resource ownership identifier for the active prompt run. */
253
+ getActivePromptHandle(): string | undefined;
252
254
  /** Abort the current agent operation */
253
255
  abort(): void;
256
+ /** Abort and prove whether resources for a specific prompt settled. */
257
+ abortPromptAndWait?(handle: string, options: {
258
+ graceMs: number;
259
+ }): Promise<RunSettlementProof>;
254
260
  /** Whether there are queued messages waiting */
255
261
  hasPendingMessages(): boolean;
256
262
  /** Typed pending-message counts per queue (steering, follow-up, next-turn). */
@@ -307,6 +313,8 @@ export interface ExtensionContext {
307
313
  sdkControl?(operation: string, input: Record<string, unknown>): unknown | Promise<unknown>;
308
314
  /** Install a permission callback backed by a live SDK reverse provider lease. */
309
315
  setSdkPermissionProvider?(provider: ((toolCall: ClientBridgePermissionToolCall, options: ClientBridgePermissionOption[], signal?: AbortSignal) => Promise<ClientBridgePermissionOutcome>) | undefined): void;
316
+ /** Install a client bridge backed by a live SDK reverse provider lease. */
317
+ setSdkClientBridge?(bridge: ClientBridge | undefined): void;
310
318
  /** Names of session SDK seams actually installed by the active runtime. */
311
319
  sdkBindings?(): readonly string[];
312
320
  /** Gracefully shutdown and exit. */
@@ -1001,7 +1009,12 @@ export interface ExtensionActions {
1001
1009
  export interface ExtensionContextActions {
1002
1010
  getModel: () => Model | undefined;
1003
1011
  isIdle: () => boolean;
1012
+ /** Stable resource ownership identifier for the active prompt run. */
1013
+ getActivePromptHandle?: () => string | undefined;
1004
1014
  abort: () => void;
1015
+ abortPromptAndWait?: (handle: string, options: {
1016
+ graceMs: number;
1017
+ }) => Promise<RunSettlementProof>;
1005
1018
  hasPendingMessages: () => boolean;
1006
1019
  /** Typed pending-message counts per queue; optional for embedders without a counted queue. */
1007
1020
  getPendingMessageCounts?: () => {
@@ -1047,6 +1060,7 @@ export interface ExtensionContextActions {
1047
1060
  } | undefined>;
1048
1061
  getJobs?: () => unknown;
1049
1062
  setSdkPermissionProvider?: (provider: ((toolCall: ClientBridgePermissionToolCall, options: ClientBridgePermissionOption[], signal?: AbortSignal) => Promise<ClientBridgePermissionOutcome>) | undefined) => void;
1063
+ setSdkClientBridge?: (bridge: ClientBridge | undefined) => void;
1050
1064
  sdkControl?: (operation: string, input: Record<string, unknown>) => unknown | Promise<unknown>;
1051
1065
  invokeSkill?: (name: string, args?: string, options?: {
1052
1066
  onPreflightAccepted?: () => void;
@@ -2,14 +2,24 @@ export * from "./activation";
2
2
  export * from "./compiler";
3
3
  export * from "./constrained-hooks";
4
4
  export * from "./injection";
5
- export * from "./installer";
5
+ /**
6
+ * Public barrel. Mutation primitives are deliberately NOT re-exported here:
7
+ * `lifecycle.ts` is the sole policy and persistence writer, so the installer
8
+ * transaction and the registry writers stay reachable only through their own
9
+ * modules. Re-exporting them would let a caller commit a replacement and
10
+ * bypass the create-only rule.
11
+ */
12
+ export { isGjcPluginBundleSource, isGjcPluginSourceShape } from "./installer";
13
+ export * from "./lifecycle";
14
+ export * from "./lifecycle-reconciliation";
6
15
  export * from "./loader";
7
16
  export * from "./mcp-policy";
8
17
  export * from "./observability";
9
18
  export * from "./paths";
10
19
  export * from "./prompt-appendix";
11
- export * from "./registry";
20
+ export { loadEffectiveGjcPluginRegistry, readRegistry, registryEntryFingerprint, registryPathForScope, registryRootForScope, sortRegistryEntries, } from "./registry";
12
21
  export * from "./runtime-adapters";
22
+ export * from "./runtime-quarantine";
13
23
  export * from "./schema";
14
24
  export * from "./session-validation";
15
25
  export * from "./state";
@@ -1,13 +1,69 @@
1
- import { type GjcPluginRegistryEntry, type GjcPluginScope } from "./types";
2
- export interface InstallGjcPluginOptions {
1
+ import { type GjcLifecycleError, type GjcPluginRegistry, type GjcPluginRegistryEntry, type GjcPluginRegistrySource, type GjcPluginScope, type NormalizedGjcPluginBundle } from "./types";
2
+ export interface GjcBundleTransactionOptions {
3
3
  scope: GjcPluginScope;
4
4
  cwd: string;
5
- force?: boolean;
5
+ /**
6
+ * Policy hook evaluated while both scope locks are held. It decides whether
7
+ * to commit the candidate, report an already-satisfied no-op, or abort with
8
+ * a typed lifecycle error. Only the lifecycle service supplies this.
9
+ */
10
+ decide: (input: GjcBundleTransactionContext) => Promise<GjcBundleTransactionDecision>;
6
11
  }
7
- export interface InstallGjcPluginResult {
8
- status: "installed" | "updated" | "unchanged";
9
- entry: GjcPluginRegistryEntry;
12
+ export interface GjcBundleTransactionContext {
13
+ targetRegistry: GjcPluginRegistry;
14
+ /** Both scopes, deterministically sorted, for cross-scope decisions. */
15
+ effective: GjcPluginRegistryEntry[];
16
+ existing: GjcPluginRegistryEntry | undefined;
17
+ bundle: NormalizedGjcPluginBundle;
18
+ /** Entry the candidate would produce if committed as-is. */
19
+ candidate: GjcPluginRegistryEntry;
10
20
  }
11
- export declare function installGjcPluginBundle(source: string, options: InstallGjcPluginOptions): Promise<InstallGjcPluginResult>;
21
+ export type GjcBundleTransactionDecision = {
22
+ kind: "commit";
23
+ entry: GjcPluginRegistryEntry;
24
+ } | {
25
+ kind: "noop";
26
+ entry: GjcPluginRegistryEntry;
27
+ } | {
28
+ kind: "abort";
29
+ error: GjcLifecycleError;
30
+ };
31
+ export type GjcBundleTransactionResult = {
32
+ status: "committed";
33
+ entry: GjcPluginRegistryEntry;
34
+ remnants: string[];
35
+ } | {
36
+ status: "noop";
37
+ entry: GjcPluginRegistryEntry;
38
+ remnants: string[];
39
+ } | {
40
+ status: "aborted";
41
+ error: GjcLifecycleError;
42
+ remnants: string[];
43
+ };
44
+ /**
45
+ * Serialized bundle transaction: prepare outside the locks, then hold the
46
+ * user->project locks in a fixed order so the decision sees a consistent
47
+ * cross-scope view. Only the target scope is ever committed.
48
+ */
49
+ export declare function runGjcBundleTransaction(source: string, options: GjcBundleTransactionOptions): Promise<GjcBundleTransactionResult>;
50
+ /** Compile a source into a validated candidate bundle without touching disk state. */
51
+ export declare function resolveGjcBundleCandidate<T>(source: string, fn: (input: {
52
+ bundle: NormalizedGjcPluginBundle;
53
+ source: GjcPluginRegistrySource;
54
+ }) => Promise<T>): Promise<T>;
55
+ /** Build the registry entry a candidate bundle would produce at a target path. */
56
+ export declare function candidateRegistryEntry(bundle: NormalizedGjcPluginBundle, scope: GjcPluginScope, cwd: string, source: GjcPluginRegistrySource, now: string): GjcPluginRegistryEntry;
57
+ /**
58
+ * True when a spec has the SHAPE of a GJC bundle source: a filesystem path, a
59
+ * git locator, or a tarball. This is a pure string test that never touches the
60
+ * filesystem or the network, so a deleted or unreachable source is still
61
+ * recognised as GJC-intent and can reach the lifecycle's typed refusal instead
62
+ * of falling through to npm.
63
+ *
64
+ * npm and marketplace specs are never path/git/tarball shaped, so this cleanly
65
+ * separates the two install worlds.
66
+ */
67
+ export declare function isGjcPluginSourceShape(source: string): boolean;
12
68
  /** True only when the source actually resolves to a GJC plugin bundle (root gajae-plugin.json). */
13
69
  export declare function isGjcPluginBundleSource(source: string): Promise<boolean>;