@gajae-code/coding-agent 0.16.3 → 0.16.6

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 (277) hide show
  1. package/CHANGELOG.md +113 -0
  2. package/dist/types/capability/types.d.ts +4 -0
  3. package/dist/types/cli/args.d.ts +2 -2
  4. package/dist/types/cli/customize-doctor.d.ts +22 -0
  5. package/dist/types/cli/root-flags.d.ts +4 -2
  6. package/dist/types/cli.d.ts +1 -1
  7. package/dist/types/commands/launch.d.ts +1 -1
  8. package/dist/types/config/autorouting-tier-map.d.ts +3 -0
  9. package/dist/types/config/file-lock.d.ts +31 -3
  10. package/dist/types/config/model-registry.d.ts +4 -0
  11. package/dist/types/config/model-resolver.d.ts +9 -0
  12. package/dist/types/config/settings-schema.d.ts +29 -1
  13. package/dist/types/coordinator-mcp/question-state.d.ts +7 -0
  14. package/dist/types/coordinator-mcp/server.d.ts +7 -0
  15. package/dist/types/discovery/claude-plugins.d.ts +3 -1
  16. package/dist/types/discovery/helpers.d.ts +35 -0
  17. package/dist/types/exec/bash-executor.d.ts +17 -1
  18. package/dist/types/exec/bash-shell-guardian.d.ts +15 -0
  19. package/dist/types/exec/bash-shell-runtime-entry.d.ts +2 -0
  20. package/dist/types/exec/bash-shell-signals.d.ts +2 -0
  21. package/dist/types/exec/bash-shell-supervisor-entry.d.ts +1 -0
  22. package/dist/types/exec/bash-shell-supervisor.d.ts +10 -0
  23. package/dist/types/exec/bash-shell-worker-entry.d.ts +2 -0
  24. package/dist/types/exec/bash-shell-worker-protocol.d.ts +63 -0
  25. package/dist/types/exec/bash-shell-worker.d.ts +1 -0
  26. package/dist/types/exec/isolated-shell.d.ts +19 -0
  27. package/dist/types/extensibility/extensions/function-hooks-internal.d.ts +9 -0
  28. package/dist/types/extensibility/extensions/function-hooks.d.ts +169 -0
  29. package/dist/types/extensibility/extensions/index.d.ts +1 -0
  30. package/dist/types/extensibility/extensions/runner.d.ts +46 -6
  31. package/dist/types/extensibility/extensions/types.d.ts +16 -0
  32. package/dist/types/extensibility/extensions/wrapper.d.ts +3 -1
  33. package/dist/types/extensibility/gjc-plugins/constrained-hooks.d.ts +35 -2
  34. package/dist/types/extensibility/gjc-plugins/mcp-policy.d.ts +16 -0
  35. package/dist/types/extensibility/gjc-plugins/paths.d.ts +2 -0
  36. package/dist/types/extensibility/gjc-plugins/types.d.ts +25 -0
  37. package/dist/types/extensibility/hooks/types.d.ts +4 -0
  38. package/dist/types/extensibility/runtime-skill-discovery.d.ts +5 -2
  39. package/dist/types/extensibility/shared-events.d.ts +1 -1
  40. package/dist/types/extensibility/skill-management.d.ts +9 -4
  41. package/dist/types/extensibility/skills.d.ts +2 -0
  42. package/dist/types/gjc-runtime/empty-delete-gc.d.ts +4 -1
  43. package/dist/types/gjc-runtime/linux-proc.d.ts +2 -0
  44. package/dist/types/gjc-runtime/session-state-lock.d.ts +14 -0
  45. package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +41 -3
  46. package/dist/types/gjc-runtime/ultragoal-succession.d.ts +251 -0
  47. package/dist/types/modes/components/assistant-message.d.ts +1 -2
  48. package/dist/types/modes/components/bash-execution.d.ts +1 -0
  49. package/dist/types/modes/components/execution-shared.d.ts +1 -0
  50. package/dist/types/modes/components/settings-selector.d.ts +6 -1
  51. package/dist/types/modes/components/status-line/command.d.ts +35 -0
  52. package/dist/types/modes/components/status-line/index.d.ts +1 -0
  53. package/dist/types/modes/components/status-line/types.d.ts +5 -0
  54. package/dist/types/modes/components/tool-status-header.d.ts +14 -0
  55. package/dist/types/modes/controllers/event-controller.d.ts +6 -0
  56. package/dist/types/modes/interactive-mode.d.ts +3 -0
  57. package/dist/types/modes/types.d.ts +7 -0
  58. package/dist/types/runtime-mcp/client.d.ts +9 -1
  59. package/dist/types/runtime-mcp/manager.d.ts +7 -1
  60. package/dist/types/runtime-mcp/pool.d.ts +22 -3
  61. package/dist/types/runtime-mcp/transports/stdio.d.ts +0 -4
  62. package/dist/types/runtime-mcp/types.d.ts +22 -0
  63. package/dist/types/sdk/broker/ensure.d.ts +32 -0
  64. package/dist/types/sdk/broker/lifecycle-ledger.d.ts +0 -1
  65. package/dist/types/sdk/broker/lifecycle.d.ts +6 -0
  66. package/dist/types/sdk/broker/startup-failure.d.ts +4 -1
  67. package/dist/types/sdk/bus/chat-daemon-control.d.ts +2 -0
  68. package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +12 -0
  69. package/dist/types/sdk/bus/chat-effect-journal.d.ts +17 -2
  70. package/dist/types/sdk/bus/conversation-store.d.ts +11 -0
  71. package/dist/types/sdk/bus/lifecycle-commands.d.ts +8 -8
  72. package/dist/types/sdk/bus/slack-daemon.d.ts +1 -1
  73. package/dist/types/sdk/bus/slack-live-provider.d.ts +6 -0
  74. package/dist/types/sdk/bus/slack-provider.d.ts +12 -0
  75. package/dist/types/sdk/bus/topic-registry.d.ts +8 -0
  76. package/dist/types/sdk/client/client.d.ts +6 -0
  77. package/dist/types/sdk/host/host.d.ts +3 -1
  78. package/dist/types/sdk/host/session-runtime.d.ts +26 -1
  79. package/dist/types/sdk/lifecycle/service.d.ts +1 -0
  80. package/dist/types/sdk/router/session-router.d.ts +10 -2
  81. package/dist/types/sdk/session-api-key.d.ts +26 -0
  82. package/dist/types/sdk/session.d.ts +5 -1
  83. package/dist/types/sdk/transport/serve-cli.d.ts +1 -1
  84. package/dist/types/session/agent-session.d.ts +11 -0
  85. package/dist/types/session/fallback-chain-controller.d.ts +15 -0
  86. package/dist/types/session/internal/managed-session-storage.d.ts +7 -0
  87. package/dist/types/session/messages.d.ts +1 -0
  88. package/dist/types/session/session-manager.d.ts +3 -1
  89. package/dist/types/setup/paseo/announce.d.ts +112 -0
  90. package/dist/types/setup/paseo/setup-deps.d.ts +2 -1
  91. package/dist/types/skill-state/canonical-skills.d.ts +4 -0
  92. package/dist/types/system-prompt.d.ts +10 -0
  93. package/dist/types/task/executor.d.ts +5 -1
  94. package/dist/types/tools/bash.d.ts +1 -0
  95. package/dist/types/tools/fetch.d.ts +7 -0
  96. package/dist/types/tools/github-cache.d.ts +2 -1
  97. package/dist/types/tools/index.d.ts +10 -0
  98. package/dist/types/tools/path-utils.d.ts +2 -0
  99. package/dist/types/tools/search.d.ts +6 -0
  100. package/package.json +9 -7
  101. package/scripts/capture-status-line-custom-editor-showcase.ts +151 -0
  102. package/scripts/generate-sdk-operation-inventory.ts +11 -0
  103. package/scripts/verify-status-line-custom-editor-showcase.ts +309 -0
  104. package/src/capability/index.ts +14 -2
  105. package/src/capability/types.ts +4 -0
  106. package/src/cli/args.ts +20 -9
  107. package/src/cli/customize-doctor.ts +155 -12
  108. package/src/cli/root-flags.ts +5 -3
  109. package/src/cli.ts +22 -0
  110. package/src/commands/sdk.ts +74 -31
  111. package/src/config/autorouting-tier-map.ts +1 -0
  112. package/src/config/file-lock-gc.ts +40 -2
  113. package/src/config/file-lock.ts +379 -31
  114. package/src/config/model-preset-registry.ts +120 -19
  115. package/src/config/model-profiles.ts +40 -0
  116. package/src/config/model-registry.ts +73 -23
  117. package/src/config/model-resolver.ts +48 -0
  118. package/src/config/settings-schema.ts +33 -1
  119. package/src/config/settings.ts +1 -0
  120. package/src/coordinator-mcp/question-state.ts +33 -2
  121. package/src/coordinator-mcp/server.ts +477 -101
  122. package/src/crash/sanitize.ts +1 -1
  123. package/src/defaults/gjc/extensions/grok-cli-vendor/src/models/catalog.ts +11 -11
  124. package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/register.ts +13 -2
  125. package/src/defaults/gjc/skills/ultragoal/SKILL.md +22 -0
  126. package/src/discovery/builtin.ts +52 -55
  127. package/src/discovery/claude-plugins.ts +12 -4
  128. package/src/discovery/helpers.ts +307 -34
  129. package/src/exec/bash-executor.ts +330 -50
  130. package/src/exec/bash-shell-guardian.ts +388 -0
  131. package/src/exec/bash-shell-runtime-entry.ts +5 -0
  132. package/src/exec/bash-shell-signals.ts +29 -0
  133. package/src/exec/bash-shell-supervisor-entry.ts +3 -0
  134. package/src/exec/bash-shell-supervisor.ts +359 -0
  135. package/src/exec/bash-shell-worker-entry.ts +5 -0
  136. package/src/exec/bash-shell-worker-protocol.ts +36 -0
  137. package/src/exec/bash-shell-worker.ts +116 -0
  138. package/src/exec/isolated-shell.ts +393 -0
  139. package/src/extensibility/extensions/function-hooks-internal.ts +73 -0
  140. package/src/extensibility/extensions/function-hooks.ts +959 -0
  141. package/src/extensibility/extensions/index.ts +22 -0
  142. package/src/extensibility/extensions/loader.ts +53 -2
  143. package/src/extensibility/extensions/runner.ts +895 -264
  144. package/src/extensibility/extensions/types.ts +42 -0
  145. package/src/extensibility/extensions/wrapper.ts +56 -15
  146. package/src/extensibility/gjc-plugins/compiler.ts +228 -60
  147. package/src/extensibility/gjc-plugins/constrained-hooks.ts +321 -23
  148. package/src/extensibility/gjc-plugins/installer.ts +13 -12
  149. package/src/extensibility/gjc-plugins/mcp-policy.ts +81 -52
  150. package/src/extensibility/gjc-plugins/paths.ts +13 -0
  151. package/src/extensibility/gjc-plugins/registry.ts +113 -1
  152. package/src/extensibility/gjc-plugins/runtime-adapters.ts +758 -16
  153. package/src/extensibility/gjc-plugins/runtime-quarantine.ts +20 -2
  154. package/src/extensibility/gjc-plugins/schema.ts +121 -4
  155. package/src/extensibility/gjc-plugins/types.ts +25 -0
  156. package/src/extensibility/hooks/loader.ts +133 -16
  157. package/src/extensibility/hooks/types.ts +28 -0
  158. package/src/extensibility/runtime-skill-discovery.ts +149 -190
  159. package/src/extensibility/shared-events.ts +1 -1
  160. package/src/extensibility/skill-management.ts +200 -52
  161. package/src/extensibility/skills.ts +73 -25
  162. package/src/gjc-runtime/empty-delete-gc.ts +94 -4
  163. package/src/gjc-runtime/gc-runtime.ts +29 -0
  164. package/src/gjc-runtime/linux-proc.ts +14 -0
  165. package/src/gjc-runtime/repository-binding.ts +1 -1
  166. package/src/gjc-runtime/session-state-lock.ts +143 -10
  167. package/src/gjc-runtime/session-state-sidecar.ts +27 -11
  168. package/src/gjc-runtime/state-writer.ts +30 -29
  169. package/src/gjc-runtime/ultragoal-runtime.ts +189 -47
  170. package/src/gjc-runtime/ultragoal-succession.ts +1667 -0
  171. package/src/gjc-runtime/workflow-manifest.generated.json +52 -1
  172. package/src/gjc-runtime/workflow-manifest.ts +16 -0
  173. package/src/harness-control-plane/session-lease.ts +2 -2
  174. package/src/internal-urls/docs-index.generated.ts +12 -12
  175. package/src/lsp/config.ts +10 -3
  176. package/src/lsp/index.ts +1 -1
  177. package/src/lsp/path-trust.ts +69 -14
  178. package/src/main.ts +78 -35
  179. package/src/modes/DESIGN.md +54 -0
  180. package/src/modes/acp/acp-agent.ts +16 -3
  181. package/src/modes/components/assistant-message.ts +22 -9
  182. package/src/modes/components/bash-execution.ts +4 -1
  183. package/src/modes/components/execution-shared.ts +4 -1
  184. package/src/modes/components/model-selector.ts +166 -33
  185. package/src/modes/components/session-observer-overlay.ts +1 -1
  186. package/src/modes/components/settings-selector.ts +1075 -235
  187. package/src/modes/components/status-line/command.ts +190 -0
  188. package/src/modes/components/status-line/index.ts +1 -0
  189. package/src/modes/components/status-line/segments.ts +32 -5
  190. package/src/modes/components/status-line/types.ts +5 -0
  191. package/src/modes/components/tool-status-header.ts +396 -22
  192. package/src/modes/controllers/command-controller.ts +3 -0
  193. package/src/modes/controllers/event-controller.ts +151 -7
  194. package/src/modes/controllers/extension-ui-controller.ts +1 -0
  195. package/src/modes/controllers/input-controller.ts +6 -3
  196. package/src/modes/controllers/selector-controller.ts +21 -0
  197. package/src/modes/interactive-mode.ts +53 -6
  198. package/src/modes/print-mode.ts +5 -1
  199. package/src/modes/prompt-action-autocomplete.ts +54 -27
  200. package/src/modes/runtime-init.ts +2 -0
  201. package/src/modes/types.ts +17 -3
  202. package/src/modes/utils/ui-helpers.ts +2 -0
  203. package/src/prompts/system/system-prompt.md +8 -0
  204. package/src/prompts/tools/search.md +2 -0
  205. package/src/prompts/tools/subagent.md +1 -0
  206. package/src/runtime-mcp/client.ts +60 -17
  207. package/src/runtime-mcp/manager.ts +189 -14
  208. package/src/runtime-mcp/pool.test.ts +218 -0
  209. package/src/runtime-mcp/pool.ts +224 -23
  210. package/src/runtime-mcp/transports/stdio.ts +158 -24
  211. package/src/runtime-mcp/types.ts +24 -0
  212. package/src/sdk/broker/broker.ts +124 -32
  213. package/src/sdk/broker/ensure.ts +248 -41
  214. package/src/sdk/broker/lifecycle-ledger.ts +7 -17
  215. package/src/sdk/broker/lifecycle.ts +56 -6
  216. package/src/sdk/broker/startup-failure.ts +15 -6
  217. package/src/sdk/bus/chat-daemon-control.ts +3 -1
  218. package/src/sdk/bus/chat-daemon-runtime.ts +72 -6
  219. package/src/sdk/bus/chat-effect-journal.ts +132 -7
  220. package/src/sdk/bus/conversation-store.ts +29 -0
  221. package/src/sdk/bus/lifecycle-commands.ts +17 -11
  222. package/src/sdk/bus/slack-conversation.ts +1 -0
  223. package/src/sdk/bus/slack-daemon.ts +478 -49
  224. package/src/sdk/bus/slack-live-provider.ts +12 -0
  225. package/src/sdk/bus/slack-provider.ts +5 -0
  226. package/src/sdk/bus/telegram-daemon.ts +16 -2
  227. package/src/sdk/bus/topic-registry.ts +19 -0
  228. package/src/sdk/cli/master-cli.ts +1 -1
  229. package/src/sdk/cli/session-cli.ts +11 -8
  230. package/src/sdk/client/client.ts +66 -17
  231. package/src/sdk/host/host.ts +29 -9
  232. package/src/sdk/host/query/revision-store.ts +19 -13
  233. package/src/sdk/host/reverse-leases.ts +7 -4
  234. package/src/sdk/host/session-runtime.test.ts +52 -10
  235. package/src/sdk/host/session-runtime.ts +383 -44
  236. package/src/sdk/lifecycle/service.ts +4 -0
  237. package/src/sdk/protocol/operation-inventory.generated.json +77 -0
  238. package/src/sdk/router/session-router.ts +89 -38
  239. package/src/sdk/session-api-key.ts +94 -0
  240. package/src/sdk/session.ts +228 -55
  241. package/src/sdk/transport/relay.ts +35 -13
  242. package/src/sdk/transport/serve-cli.ts +3 -3
  243. package/src/session/agent-session.ts +240 -90
  244. package/src/session/contribution-prep.ts +214 -21
  245. package/src/session/fallback-chain-controller.ts +38 -0
  246. package/src/session/internal/managed-session-storage.ts +19 -5
  247. package/src/session/messages.ts +5 -0
  248. package/src/session/session-manager.ts +29 -5
  249. package/src/session-import/redact.ts +5 -1
  250. package/src/setup/paseo/announce.ts +456 -0
  251. package/src/setup/paseo/setup-deps.ts +15 -3
  252. package/src/skill-state/canonical-skills.ts +12 -0
  253. package/src/skills/skills.test.ts +41 -21
  254. package/src/slash-commands/builtin-registry.ts +1 -0
  255. package/src/system-prompt.ts +29 -3
  256. package/src/task/executor.ts +7 -1
  257. package/src/task/index.ts +21 -4
  258. package/src/tools/bash.ts +63 -19
  259. package/src/tools/cron.ts +1 -1
  260. package/src/tools/fetch.ts +29 -1
  261. package/src/tools/gh.ts +26 -3
  262. package/src/tools/github-cache.ts +68 -16
  263. package/src/tools/index.ts +10 -0
  264. package/src/tools/job.ts +21 -4
  265. package/src/tools/monitor.ts +8 -2
  266. package/src/tools/path-utils.ts +7 -0
  267. package/src/tools/read.ts +14 -2
  268. package/src/tools/render-utils.ts +1 -3
  269. package/src/tools/resource-gc.ts +28 -8
  270. package/src/tools/search.ts +116 -58
  271. package/src/tools/skill-discovery.ts +5 -0
  272. package/src/tools/skill.ts +37 -2
  273. package/src/tools/subagent.ts +6 -3
  274. package/src/tools/tool-catalog.generated.ts +10 -3
  275. package/src/tools/ultragoal-ask-guard.ts +2 -2
  276. package/src/web/insane/bridge.ts +113 -23
  277. package/src/web/search/providers/perplexity.ts +102 -41
package/CHANGELOG.md CHANGED
@@ -2,6 +2,119 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.16.6] - 2026-09-07
6
+ ### Fixed
7
+
8
+ - `gjc --smoke-test` no longer fails on a cold or loaded host. The isolated-shell smoke wrote its descendant marker empty while the in-shell wait loop tested for a non-empty file, so the probe command could never reach its parked `sleep` and always burned the full 5s budget, leaving the 5s readiness poll no slack; the 1s descendant-reap window was equally tight. The marker now carries content, readiness and reaping use explicit 30s/15s deadlines, and the probe gets a 60s budget it still never needs. This failed the darwin-x64 release binary check on v0.16.5, which published nothing.
9
+ - SDK lifecycle replay no longer rejects a live endpoint as replaced because of sub-millisecond filesystem metadata drift. The ready authority re-derived the endpoint mtime from a fresh `stat` while every other field came from the indexed record, so the two floats could differ in their last digits and replay hashing reported `endpoint_stale` for the endpoint it had just validated. Replacement fencing is unchanged: the on-disk file must still match the indexed record before that authority exists.
10
+
11
+ ## [0.16.5] - 2026-09-07
12
+ ### Added
13
+
14
+ - `gjc ultragoal succession offer|adopt|status` gives an approved Ultragoal an explicit, audited path from the repository it was planned in to the repository its implementation belongs to (#5353). Previously the repository-binding guard correctly refused to execute the plan from the second repository and the only ways forward — editing `repositoryBinding` or copying the runtime directory — both defeated that boundary and laundered verification provenance. `offer` records the source repository/session, the selected unfinished goal ids, verified source artifact digests, and the complete carryover (the source brief and each objective verbatim, plus the unresolved obligations recorded against those goals), then installs a durable outgoing ownership fence: the source run immediately refuses to schedule or checkpoint the handed-off goals, while goals outside the selection stay schedulable. The source `brief.md`, `goals.json` and `ledger.jsonl` are never written — not even appended to — so their recorded digests stay verifiable, and adoption performs no write to the source repository at all. `adopt` starts a fresh run under the target repository's own binding with new pending goals and no inherited receipts, quality gates, validation batches, steering, owner identity or activated objective; historical statuses, reviews and approvals travel as provenance only. Digests are integrity evidence, never authorization: adoption additionally requires the source fence, a bounded `--authorize`/`--authorized-by` statement, and an explicit goal selection. Because the fence deliberately leaves unselected goals schedulable, admission compares a snapshot of the offered work — the brief plus each selected goal's record and unresolved obligations — rather than whole-file digests, so ordinary source progress cannot permanently strand the handed-off work; whole-file digests remain recorded as provenance and observed drift is written into the adoption record. A selection that takes only part of a validation batch, or splits a review blocker from the goal it still blocks, is rejected rather than silently dropping that obligation, and dependency groups travel as explicit obligations with source-to-target id mapping while the source's batch metadata and receipts stay behind. Terminal-critic blockers are carried as unmet requirements even though the verdict itself is not inherited. Exclusion is a single repository-wide `O_EXCL` claim per operation rather than a directory scan, so two simultaneous sessions cannot both become owners, and adoption is pinned to the exact worktree the offer named because linked worktrees keep separate `.gjc` state. Until publication completes the target refuses to execute — a visible `goals.json` is not admission evidence, the adoption record is. Adoption fails closed on changed offered work, an altered or unfenced offer, an offer path that escapes the source worktree, a target the offer does not name, an occupied target session, and any duplicate or simultaneous adoption in the target repository. A retry reconciles only this operation's own partial bytes: a matching operation id is never authority to overwrite target work it did not write, and a published plan whose files have disappeared is refused rather than reconstructed. There is deliberately no `revoke` verb, because any read-then-delete of the fence races a concurrent adoption and could revive the source while the target is starting.
15
+
16
+ ### Fixed
17
+
18
+ - Concurrent print-mode resumes rejected by the managed transcript append fence now exit with one retry diagnostic instead of crashing during disposal, including failures while persisting startup model overrides before print mode begins. A pre-write identity mismatch disowns the stale transcript without rewriting another process's successor; genuinely uncertain I/O closure still fails closed.
19
+ - Disk artifact GC and `gjc gc --empty-delete-receipts` now reclaim empty artifact `.removing` directories left by interrupted session deletion, including projects with no remaining transcripts. Only the two generated quarantine-name shapes qualify; no-follow directory snapshots prove emptiness, and non-recursive removal retains non-empty, symlinked, or raced entries with explicit reasons.
20
+ - SDK `session.spawn` now publishes the child PID/incarnation-bound lifecycle marker before waiting for host registration, so headless and managed-tmux children can become ready. Incomplete substrate proofs are rejected and released before seed handoff; registration failures include validated startup phase/reason diagnostics without task text.
21
+ - File-lock acquisition and GC now reclaim orphaned `.lock.pending.<pid>.<uuid>` directories after their owner dies, with a bounded acquisition sweep and exact-identity deletion. Live, unknown, in-process, malformed, symlinked, and host-qualified owners remain protected; cleanup failures cannot block acquisition (related #5198).
22
+ - File-lock acquisition timeouts now expose a typed error with the lock path, retry count, and holder description. Lease mutation and SDK shutdown classify contention without depending on operator-facing wording, and unrelated shutdown failures still propagate.
23
+ - Broker `session.list` pagination cursors now evict the oldest entry when the 32-cursor budget is full instead of failing new paginations with `cursor capacity is exhausted` (#5370). Abandoned or partial paginations degrade gracefully (the evicted cursor reports `cursor is expired or invalid` on next use) so unrelated session ops never fail once the index exceeds one page; the obsolete capacity-exhausted path is removed.
24
+ - `session.delete` uncertain-cleanup fences are now identity-scoped: an unbound `terminal_uncertain` ledger entry no longer blanket-fences deletes for every other session id, and a delete refusal records its own target session so the fence it leaves is scoped to that session. Existing poisoned ledgers need no migration — unbound rows are ignored in place on the next read and stop amplifying (#5364).
25
+ - Runtime state persistence now identifies contradictory `ready_for_input`/`live` fields with their lifecycle state and expected value instead of reporting only a generic invalid/unreadable marker error. Invalid markers remain untouched; this does not migrate or repair old session state.
26
+ - LSP auto-discovery now launches trusted executable symlinks through their discovered paths instead of canonicalizing them to their targets, preserving proxy invocation names such as `rust-analyzer` when installed through rustup. The LSP status action now labels these entries as configured rather than active, since a client has not necessarily started (#5354).
27
+ - SDK snapshot pages now read and integrity-check one contiguous span instead of rereading chunks per row. Reverse-provider disconnects discard connection-scoped registration receipts; relay shutdown releases backpressure listeners without destroying caller-owned sinks, and fragmented request frames are assembled once per newline.
28
+
29
+ - The TUI working spinner and tool intent remain visible when a run continues after automatic context compaction, a compaction-hook veto, or a successful managed model retry. Temporary status replacement no longer marks the foreground run as finished; actual completion and cancellation still clear it.
30
+ - Coordinator delegates recover a creation-WAL crash before the initial prompt claim without recreating the session or replaying compacted requests. Recurring pin cleanup bounds each readiness pass to 32 session WALs and 32 pinned receipts, skips live caller-key locks, and revisits the namespace after clean scans so surviving coordinators discover later peer crashes as well as previously skipped pins.
31
+ - Session import no longer stalls on large credential-free content. The import redactor's URL-credential rule accepted an unbounded scheme before the literal `://`, so a long alphabetic run re-tried every prefix and scanning cost grew quadratically with the input (50k/100k/200k characters took 0.7s/2.7s/10.6s on text containing no credential at all). Every imported string crosses this fail-closed redactor, so one large transcript message was enough to stall an import of Claude Code or Codex history. The scheme is now length-bounded, which restores linear scanning while `https://`, `postgres://`, and `git+ssh://` credentials are still redacted.
32
+ - SDK saved-session resume now enforces a supplied transcript `sessionIdentity` for both live reattach and cold launch instead of silently replacing it with the broker's current snapshot. Lifecycle create/resume results also expose the opaque `endpointIncarnation`, and same-key replay refuses an endpoint replacement rather than refreshing success by session ID when a numeric generation is reused.
33
+ - An ACP client that declares no MCP servers no longer loses `session/new`, `session/load`, and `session/fork` to the broker's bare readiness default. Only the MCP branch asked for a readiness budget, so an MCP-less launch kept the 10s default while a host cold start measurably crosses it whenever a second host starts alongside the first: the broker then returned `terminal_uncertain` ("Lifecycle startup could not be proven"), which Paseo recorded as a failed provider snapshot and left the GJC provider reading `error` instead of `available`, so imported terminal sessions attached to nothing and showed no transcript. Every ACP launch now requests the same budget the MCP path already used, independent of whether the client declared servers.
34
+ - `subagent await` now accepts integer heartbeat intervals up to 60,000 ms, including 10,000 ms, instead of rejecting them at an undocumented 5,000 ms schema limit. Zero still disables heartbeat updates and the default cadence is unchanged.
35
+ - Coordinator delegates recover a creation-WAL crash before the initial prompt claim without recreating the session or replaying compacted requests. Startup pin cleanup skips live observations without waiting on their caller-key locks, and revisits skipped pins so a surviving coordinator can clean up after a peer commits its response and crashes.
36
+ - Interrupted standalone-binary installs now reclaim an installer lock only when its recorded process ID is no longer running. Live or malformed locks remain protected and fail closed, so a cancelled `gjc update` no longer permanently blocks the next update while concurrent installers remain serialized.
37
+ - Disconnecting an MCP server during its initial connection now returns after cancelling the acquisition instead of waiting forever when an uncooperative transport ignores abort. The pool still owns and closes any late connection, retains cleanup failures for retry, and releases the manager's pending-cleanup fence after successful settlement (#5329).
38
+ - SDK session routing now uses the Broker's endpoint timestamp comparison, accepting sub-millisecond representation differences while retaining device/inode and exact file-replacement checks. Valid live sessions no longer become unavailable solely because timestamp conversions round differently.
39
+ - Paseo announcement now honors `PASEO_LISTEN` ahead of daemon pid metadata, uses `$PASEO_HOME` consistently in default path construction, and removes redundant target-selection and SDK frame-delivery indirection.
40
+ - When every auto-compaction candidate fails, the reported error now leads with the first candidate's failure and lists each candidate that was tried with its own error. The chain starts at the session model and ends on a same-provider largest-context fallback, so surfacing only the final error named a model the user never chose (e.g. `openai-codex/gpt-5.4` on an `astra` preset session) and hid that their own model had already failed the same way.
41
+ - Registry fingerprints now enforce the existing regular-file and 32 MiB admission limits with bounded reads. Model activation, thinking overlay lookup, transcript navigation, slash autocomplete, and observer digest updates avoid repeated allocations; status lines without a git segment no longer request git status.
42
+ - Telegram `/session_recent` now distinguishes sessions currently connected to the notification daemon from saved history and prints a ready-to-copy resume command. Inside a session's existing topic, `/session_resume` and `/session_close` can omit the session ID, including after that topic became inactive.
43
+ - POSIX bash tool sessions now run the embedded persistent brush shell behind a guardian, supervisor, and runtime boundary. Shell self-signals such as `kill -TRAP $$`, external self-signals, process-group signals, and runtime/supervisor death terminate only the owned boundary, reap ordinary and new-session descendants, authenticate control records, return and persist signal-derived status metadata, retire the affected session, and leave the GJC host available for subsequent commands.
44
+ - Memory-guard samples finishing after disable/re-enable or session re-registration no longer restore stale GC latches or restart-advisory windows that suppress the next lifecycle's pressure response.
45
+ - Added ordered, capability-scoped Function Hooks middleware to the canonical extension event runner, with monotonic grant attenuation, target-aware transforms and denials, bounded timeout/abort behavior, redacted provenance-aware audit evidence, and activation-generation fencing. Plugin-bundle Function Hook declarations are validated and hashed but fail closed before host-realm import until a genuine capability-enforcing isolate is available; legacy constrained plugin hooks remain compatible.
46
+ - Coordinator MCP delegation now releases the session transition lock after durable admission so force/queue prompts can dispatch during bounded completion observation. New and reused delegates persist and replay the complete bounded response, including timeout and waiting snapshots, while receipt-first crash recovery preserves accepted prompt identity and successor terminal fences without redispatch. Pending delegate responses pin their source prompt/turn through age and size compaction until final response commit; resumed keys with missing live authority remain unsealed and fail closed instead of redispatching or sealing a busy error.
47
+ - Concurrent SDK CLI cold starts now single-flight broker spawning through an atomically published, process-incarnation-bound lock. Coordination owners use a machine identity keyed from the shared agent root, so separate config profiles recover one another's dead claims without allowing another machine to reclaim a live generation. Every discovery probe is bounded by the startup deadline, and a dedicated bootstrap watchdog terminates a child that outlives its startup fence. A crashed spawner is reclaimed without letting simultaneous healers delete a successor claim; retained legacy broker-lock quarantines no longer collide with takeover; incomplete owner records fail closed; and PID reuse no longer wedges broker startup. (#5198)
48
+ - Skill discovery now reports project `.claude/skills` / `.codex/skills` import candidates before user-home ones, so a populated operator home (hundreds of convention skills is ordinary) can no longer spend the bounded diagnostic budget before the project's own convention skill is named.
49
+
50
+ ### Fixed
51
+
52
+ - SDK submissions that reject during post-turn cleanup no longer publish a contradictory second terminal after their correlation has already settled.
53
+ - Paseo session imports discard unused CLI stdout instead of leaving an unread pipe.
54
+ - SDK live-attach streams preserve producer order across text deltas, final messages, and tool events even when asynchronous extension handlers are slow, without replaying or broadcasting turn content. Content observed while the correlated `agent_start` is still being durably recorded is held and released after the start frame, so no consumer sees turn content before the turn it belongs to; held content is delivered only to the owners that held the run when it was produced, and the hold is bounded (256 events, oldest dropped with one warning) so a wedged start write can neither invert the start/content boundary nor accumulate a whole response in memory.
55
+ - SDK prompts consumed together after queued steering is interrupted now each receive correlated starts, streamed content, and one terminal, without adopting unrelated pending submissions.
56
+
57
+ - Tool hot paths avoid overlap-table allocations for equal/append-only ACP output, redundant UTF-8 tail previews, repeated diagnostics suffix scans, and duplicate background GitHub-cache refreshes. Job polling now releases watches and timers when a progress callback throws.
58
+
59
+ ## [0.16.4] - 2026-09-05
60
+ ### Added
61
+
62
+ - Added selectable `astra-lite`, `astra-default`, and `astra-heavy` CODEX presets with `ASTRA-` labels, plus `astra-fable` and `astra-fable-opus` cross-family review combinations. Existing presets and automatic provider recommendations remain unchanged.
63
+ - An interactive `gjc` now shows up inside [Paseo](https://paseo.sh) by itself, controllable from the desktop and mobile apps, instead of only being reachable when Paseo started it. Every terminal session already registered its SDK endpoint with the broker, and GJC's ACP surface already resolves a `live` index entry straight to the running host — a `session/load` attaches to it rather than resuming a second copy — so the only thing missing was telling the Paseo daemon the session exists. That is now done at interactive startup with `paseo import --provider <key> --cwd <cwd> <session-id>`, which makes the terminal session and the Paseo agent the same live session rather than two transcripts. The announcement is gated so it costs nothing when it cannot apply: an absent `$PASEO_HOME/config.json` (default `~/.paseo/config.json`), no enabled GJC ACP provider entry, no `paseo` on PATH, a daemon that is not listening, or a session the broker does not yet report as live each stop it before anything is spawned. The daemon check is a plain socket probe rather than a CLI invocation because the Paseo CLI blocks indefinitely when its daemon is down (measured: no output and no exit after two minutes), and the liveness check exists because importing a not-yet-registered id would make `session/load` fork a second host for a session that is already running. While the daemon is merely not up yet, the probe retries every 30 seconds for approximately ten minutes on unref'd timers, so launching Paseo after the terminal still works; the loaded opt-in can cancel its own pending or active announcement, changes made by another process apply on the next launch, and Paseo's own duplicate-import refusal is read as success. Interactive-only by construction — a `gjc acp` provider process never builds the interactive mode, so an imported session cannot announce itself back. Create-only by construction too: GJC adds an entry and never deletes, archives, or rewrites one, so it can never remove an agent you still wanted. The consequence is yours to manage — every interactive start gets a fresh session id (including `gjc -c`), so each launch adds one row, and ending a session leaves its row listed as `idle` until a send fails with `SDK session attachment is stale` and Paseo marks it `error`; prune with `paseo delete <agent-id>`. Opt-in: the new operator-owned `paseo.autoImport` setting is **off by default**, so a repository cannot enable it and an installation that never asks for it never reads a Paseo file, probes a socket, or spawns the CLI; enable it with `gjc config set paseo.autoImport true` (Settings → Interaction → "Announce Sessions to Paseo"). See [`docs/terminal-app-integrations.md`](../../docs/terminal-app-integrations.md#announcing-interactive-sessions).
64
+ - Corrected a stale claim in [`docs/external-control-readiness.md`](../../docs/external-control-readiness.md): interactive `gjc` sessions *are* broker-registered and *are* listed by ACP clients, and an ACP `session/load` against a live entry attaches to the running host instead of resuming a copy.
65
+ - An externally submitted prompt against a session on the SDK-only host runtime no longer hangs forever after its turn has already finished. That runtime published the lifecycle boundary as a bare `{ type, sessionId }` frame: it computed each ended invocation's `commandId`/`turnId` for durable reconciliation and then discarded them at publication, and it never carried a normalized outcome at all — only the `agent_failed` diagnostic was published per invocation with its correlation. An ACP client matches a terminal against the correlation it was acknowledged under and requires the outcome, so a real `agent_end` was rejected as `acp_prompt_terminal_dropped` / `incomplete_correlation`, `session/prompt` never settled, and the client sat in `working` until the 30-minute prompt deadline (reproduced against Paseo 0.6.1 attached to a live interactive session: the terminal rendered the full answer while Paseo showed the agent `running` indefinitely). An owned `agent_end` is now published once per ended invocation carrying that invocation's correlation and a normalized `stopped` outcome, mirroring the existing `agent_failed` shape. Frames that terminalize nothing are unchanged and stay uncorrelated: `agent_start`, a host-originated run with no owning invocation (autonomous continuation, cron, monitor), and a continuing maintenance checkpoint (`pruned`/`compacted`/`promoted`) — which is published but is deliberately not a terminal boundary, so stamping it would settle a client's prompt mid-turn. The ACP ownership gate is untouched.
66
+ - An ACP client attached to a *live interactive* session now receives the turn it submitted: assistant text, thinking, and tool calls stream as they happen instead of arriving as an empty completed turn. The SDK-only host runtime subscribed to lifecycle and watchdog events only — its two `tool_execution_*` handlers just renewed a deadline watchdog and it never subscribed to `message_update`/`message_end` at all — so it published no agent wire events and an attached client could drive the session and watch the turn settle without receiving a single word of the answer (measured against Paseo 0.6.1: `paseo logs` showed the prompt and nothing else, with `--filter tools` and `--filter text` both reporting no activity). It now streams the same five events the notifications runtime does (`message_update`, `message_end`, `tool_execution_start`/`update`/`end`), built with the same shared `toAgentWireEventPayload` producer so the wire shape cannot drift from what ACP maps. Delivery matches the notifications runtime too: one frame per owning invocation, sent directly to the connection that submitted the turn and carrying that invocation's correlation. It deliberately does **not** go through the session event ring — that ring is bounded by frame count with no byte ceiling, so streaming high-frequency chunks through it would evict the lifecycle events clients depend on (including the `agent_end` that settles their prompt) and would broadcast a turn's content to every authenticated subscriber rather than the one that asked for it. A turn nobody submitted over the SDK (an ordinary terminal prompt, an autonomous continuation, cron, monitor) has no owning connection and streams nothing.
67
+ - `gjc` no longer reports an error at every interactive launch when the Paseo daemon requires a password. `paseo import` refuses with `Cannot connect to daemon ...: Password required`, which the socket probe cannot anticipate because the TCP connect succeeds; that refusal is now read as a quiet skip instead of a failed announcement. GJC has no credential setting and reads no Paseo credential file: `paseo import` runs with the session's own environment, so an exported `PASEO_PASSWORD` is used and an absent one simply skips.
68
+
69
+ - Status-line settings now include a draft-local spatial custom editor with exact-slot keyboard reordering, hidden-segment palette management, command text configuration, persisted Confirm/Exit semantics, live multi-row preview compatibility, narrow/Unicode rendering, and deterministic visual evidence.
70
+ - Added opt-in `reasoningLanguage: english` guidance for technical work while preserving the user's requested response language; the default remains off.
71
+
72
+ ### Changed
73
+
74
+ - Interactive assistant `text_delta` presentation now coalesces eligible updates into the latest message projection before the existing TUI frame while preserving ordered event processing, immediate non-text updates, and authoritative final output. Session/transcript replacement and disposal cancel stale presentation; temporary TUI stop/start rearms current live text before the first restarted frame without invalidating live historical image callbacks.
75
+
76
+ ### Fixed
77
+
78
+ - Credential replacement lookups now propagate the owning request's cancellation through scoped and allowed unscoped retries, preventing aborted turns from continuing OAuth preparation or selecting another key.
79
+ - Removing the committed status-line command segment or clearing its trusted command now cancels the running process and clears stale output; draft-only previews remain side-effect-free.
80
+ - Slack inbound acknowledgment reactions now use bounded, abortable, tracked provider work that drains on shutdown or attachment retirement without delaying accepted turns; rejected or timed-out reactions emit sanitized diagnostics.
81
+ - Task repository bindings now accept explicit `relativeSubdir: "."` as the already-bound worktree root, avoiding unnecessary launch retries while retaining traversal, absolute-path, symlink-escape, and sibling-repository rejection.
82
+ - Blank optional task output schemas now inherit the configured agent/session schema instead of failing successful subagents at completion; malformed nonempty schemas and required-field validation remain fail-closed.
83
+ - The read-URL cache is now bounded (FIFO, 64 keys), so long-lived TUI and SDK-host processes no longer retain every fetched page's full output and image payload for the process lifetime; an evicted entry simply refetches on the next read, and unpersisted sessions sharing a working directory remain isolated by session identity.
84
+ - The insane-search web bridge now kills the engine's whole process group instead of only the `python3` process. `killChild` promised a group kill but the engine was not spawned detached, so when the bridge timeout fired mid-flight (25s default vs the engine's internal 90s playwright budget), `node` and headless `chromium` children survived as orphans. The engine now leads its own POSIX process group and receives group-wide SIGTERM→SIGKILL escalation even when the group leader exits during the grace period, with a direct child-kill fallback on Windows.
85
+ - Contribution-prep outbound artifacts now redact complete AWS credentials, including AKIA/ASIA access-key IDs and SecretAccessKey/SessionToken values in shell-style and escaped JSON forms, while preserving structured output and existing GitHub, Slack, authorization-header, and cookie redaction.
86
+ - Model preset registry URL and disable overrides now resolve only from explicitly inherited or user-owned environment sources, so a checkout `.env` cannot suppress updates or redirect signed-registry polling while dependency injection, HTTPS validation, signatures, ETags, cache, and offline behavior remain unchanged (#5300).
87
+ - OpenCode Go's provider conversation identity now remains distinct from generic cache affinity across normal turns and maintenance calls, so the required session header reuses the session manager's opaque lifecycle without accepting auth-gateway prompt-derived cache keys (#5295).
88
+ - Perplexity web search now clamps upstream search breadth to the API's 3–100 contract, retries one structurally empty completion, rejects malformed or ungrounded success payloads through the provider fallback path, and preserves valid grounded responses.
89
+ - Architect/task subagents now retry API-key lookup without the parent session id after a scoped miss, so broker OAuth that works for `gjc -p --no-session` is not thrown away as `Agent run failed` / 0 tokens (#5081 follow-up). Failures still throw `provider_unavailable` without leaking the token.
90
+ - Python work that completes after strict session disposal now returns its result without attempting to append to the closed session transcript.
91
+ - SDK-hosted workflow tools now retain the logical session id for ask, skill, deep-interview, and ultragoal state paths while job, monitor, bash, cron, task, and subagent ownership routes through a separate opaque async endpoint key. Explicit provider session identities no longer create encoded duplicate workflow trees or redirect endpoint-owned work to another live session.
92
+ - Explicit root startup `--thinking off` and `--thinking=off` now override a configured higher startup default while leaving the provider `Effort` catalog unchanged.
93
+ - Skills installed from marketplace plugins are now enumerated into sessions instead of only resolving by exact name. `loadSkills` asked the `native` provider alone, so every installed plugin skill was absent from `/` autocomplete and from the `skill` tool's `Available:` list while `gjc skill list` reported it and the discovery fallback still loaded it — 46 installed skills presented as 5. The already-registered marketplace provider is now loaded alongside `native`, keeping `<plugin>:<skill>` namespacing and per-item scope trust.
94
+ - File-content search now has a call-wide timeout (`timeout`, default 5 seconds, range 0.5–60) that is forwarded through internal-URL resolution and native grep together with cancellation. Native scans poll cancellation around each bounded file, and the tool joins cancellation cleanup before returning instead of leaving scope resolution, archive scratch, or grep workers running after a timeout. Timeout failures tell callers to narrow the scope or explicitly increase the budget, while user cancellation remains a distinct tool abort.
95
+ - `restart:sdk-broker -- --close-session-hosts` now continues replacing the broker when its pre-restart session-host listing fails, reports the partial teardown with exit code 1, tolerates another authenticated restart caller retiring the same exact broker identity, and catches other top-level failures instead of emitting an unhandled-rejection crash record.
96
+ - `install:dev` now builds the workspace native addon before linking the source CLI, preventing fresh or cleaned development checkouts from failing startup with a missing or stale addon. The installer also supports the local `--dev` binary shortcut.
97
+ - Plain and explicit-model launches now refresh a missing provider's cached dynamic catalog before resolving a qualified startup selector, so configured models such as `glm-zcode/glm-5.3` no longer open in `no-model` state while preserving cache-only startup for already available models.
98
+ - The explicit thinking-choice gate for xAI models now derives from the parsed grok generation (4.5+) shared with `@gajae-code/ai`, instead of the exact ids `grok-4.5`/`grok-4.6`. A future grok release failed the id list, so `supportsReasoningEffort` stayed `false` and the user's thinking level was silently dropped from requests; reseller-hosted grok routes (OpenRouter & co.) keep their existing audited-transport behavior.
99
+
100
+ - The status-line usage segment now paints only the active model's provider, so switching to Grok no longer keeps a stale Claude 5h/7d pair. Canonical Grok Build reports render only their authoritative weekly window, while monthly credits are omitted instead of being mislabeled as `7d`.
101
+
102
+ - Bundled plugin MCP launchers now execute Node `.mjs` entrypoints on Linux from startup-authenticated interpreter bytes and a complete copied-file snapshot. Runtime options cannot precede the entrypoint, path-qualified/shebang commands fail closed, unexpected post-install files quarantine the bundle, and canonical registry identity plus the complete copied-file manifest are rebound before every spawn. Runtime captures the interpreter and authenticated bundle files through bounded stable handles into a unique owner-only launch capsule; the Node loader returns authenticated captured module bytes while preserving file-URL relative imports and blocking package/CommonJS/native escapes. Concurrent connections use separate authority. Capsule cleanup failures retain ownership and fence reconnect until cleanup succeeds. Bun, macOS, and Windows bundled stdio launch fail closed pending equivalent loader and owner/process-tree authority; capsules do not provide hostile-same-UID process isolation.
103
+
104
+ - Moving the `/model` preset cursor now reuses the authentication snapshot produced by catalog and credential refreshes instead of resolving every profile against the full model catalog on each Up/Down keypress; auth-dependent preset actions remain blocked until the initial static refresh and the availability snapshot are complete.
105
+ - Bundled Grok Build models now explicitly declare `reasoning_effort` support only for catalog-supported models, so `grok-build/grok-4.6:xhigh` reaches the Responses request while unsupported Grok models remain fail-closed. (#5264)
106
+ - Mid-run OpenAI remote-compaction fallback failures now stop before another provider request, surface the local summarization error through ACP/SDK terminal handling, and leave the uncompacted context unsubmitted. Successful local fallback still commits the compaction and resumes normally.
107
+ - Opening `/model` now renders the preset landing before constructing the full model browser catalog. Canonical search indexing, sorting, and the redundant offline registry refresh are deferred until the user searches or chooses a browse action, while the lightweight preset-availability check remains immediate and scoped or direct-search selectors still load immediately.
108
+ - Slack lean notifications now publish only finalized assistant answers and actionable states instead of the internal lifecycle, identity, and activity frame stream. Final answer delivery uses the message reference as a durable publication identity, so repeated unpositioned SDK frames no longer post duplicate replies; accepted inbound Slack messages receive a 👀 reaction while GJC awaits the agent's answer.
109
+ - `/model` provider-tab refreshes now reuse the already loaded static catalog and update only the selected provider's discovery state, avoiding repeated signed preset registry work while retaining full-catalog refresh behavior for static configuration changes.
110
+ - Added the `command` status-line segment for user-produced HUD content. It runs
111
+ configured user/global shell commands in the background with scheduled cached
112
+ refreshes, bounded timeout/output, ANSI sanitization, placeholder degradation,
113
+ disposal cancellation, and custom-editor configuration while preserving
114
+ synchronous TUI rendering; project-scoped settings cannot trigger execution.
115
+
116
+ - Business/Enterprise/Team ChatGPT accounts can bind GPT-5.6 Sol again. The Codex entitlement preflight treated only `plan_type` values containing `"pro"` as eligible, so an `openai-codex` OAuth account on a Business/Enterprise/Team plan was rejected at model-binding/subagent setup time with a spurious entitlement error even though the backend accepts the request. Exact Pro/Business/Enterprise/Team tiers are now recognized as entitled, Plus/Free remain rejected, and unfamiliar plan names are deferred to the provider rather than guessed locally.
117
+
5
118
  ## [0.16.3] - 2026-09-04
6
119
 
7
120
  ## [0.16.2] - 2026-09-04
@@ -28,6 +28,8 @@ export interface LoadContext {
28
28
  * produced. This includes MCP registrations and user-installed skills.
29
29
  */
30
30
  userAgentDir?: string;
31
+ /** Resolver-owned classification for the selected user agent directory. */
32
+ profileAuthority?: "default" | "custom";
31
33
  /** Git repository root (directory containing .git), or null if not in a repo */
32
34
  repoRoot: string | null;
33
35
  /** Owning session settings for provider policy decisions. */
@@ -81,6 +83,8 @@ export interface LoadOptions {
81
83
  * process-wide one (`createAgentSession({ agentDir })`).
82
84
  */
83
85
  agentDir?: string;
86
+ /** Resolver-owned classification for `agentDir`; preserve it across HOME/config refreshes. */
87
+ profileAuthority?: "default" | "custom";
84
88
  /** Include items even if they fail validation. Default: false */
85
89
  includeInvalid?: boolean;
86
90
  /** Include items disabled via settings. Default: false */
@@ -1,4 +1,4 @@
1
- import { type Effort } from "@gajae-code/ai/core";
1
+ import { type RootThinkingLevel } from "./root-flags";
2
2
  export type Mode = "text" | "json" | "acp";
3
3
  export type ParseArgsAuthority = "local" | "acp" | "deferred";
4
4
  export interface Args {
@@ -21,7 +21,7 @@ export interface Args {
21
21
  mcpConfig?: string;
22
22
  /** Opt a standalone session out of conventional MCP autoload (mutually exclusive with --mcp-config). */
23
23
  noMcp?: boolean;
24
- thinking?: Effort;
24
+ thinking?: RootThinkingLevel;
25
25
  continue?: boolean;
26
26
  resume?: string | true;
27
27
  help?: boolean;
@@ -89,6 +89,28 @@ export interface CustomizeDoctorItem {
89
89
  mcp?: McpSafeSummary;
90
90
  /** Present only for quarantined plugin-bundle surfaces. */
91
91
  quarantineCode?: string;
92
+ /** Metadata-only Function Hook policy projection; hook code is never executed. */
93
+ functionHooks?: CustomizeFunctionHookSummary[];
94
+ }
95
+ export interface CustomizeFunctionHookSummary {
96
+ extensionId: string;
97
+ order: number;
98
+ event: string;
99
+ target?: string;
100
+ phase?: "before" | "after";
101
+ scope: "user" | "project";
102
+ plugin: string;
103
+ relativePath: string;
104
+ status: "disabled" | "quarantined" | "blocked-isolate" | "legacy-active";
105
+ requestedCapabilities: string[];
106
+ effectiveCapabilities: string[];
107
+ attenuateDownstream: string[];
108
+ networkDestinations: string[];
109
+ filesystemRoots: string[];
110
+ capabilityHash?: string;
111
+ implementationHash?: string;
112
+ quarantineCode?: string;
113
+ remediation: string;
92
114
  }
93
115
  export interface CustomizeDoctorSurface {
94
116
  kind: CustomizeSurfaceKind;
@@ -1,4 +1,6 @@
1
1
  import { type FlagDescriptor } from "@gajae-code/utils/cli";
2
+ export declare const ROOT_THINKING_LEVELS: readonly ["off", ...import("@gajae-code/ai").Effort[]];
3
+ export type RootThinkingLevel = (typeof ROOT_THINKING_LEVELS)[number];
2
4
  /** Public launch flags shared by root help, completion, and the launch command. */
3
5
  export declare const ROOT_LAUNCH_FLAGS: {
4
6
  model: FlagDescriptor<"string"> & {
@@ -104,7 +106,7 @@ export declare const ROOT_LAUNCH_FLAGS: {
104
106
  };
105
107
  thinking: FlagDescriptor<"string"> & {
106
108
  description: string;
107
- options: readonly ["minimal", "low", "medium", "high", "xhigh", "max"];
109
+ options: readonly ["off", ...import("@gajae-code/ai").Effort[]];
108
110
  };
109
111
  "no-rules": FlagDescriptor<"boolean"> & {
110
112
  description: string;
@@ -239,7 +241,7 @@ export declare const LAUNCH_PARSE_FLAGS: {
239
241
  };
240
242
  thinking: FlagDescriptor<"string"> & {
241
243
  description: string;
242
- options: readonly ["minimal", "low", "medium", "high", "xhigh", "max"];
244
+ options: readonly ["off", ...import("@gajae-code/ai").Effort[]];
243
245
  };
244
246
  "no-rules": FlagDescriptor<"boolean"> & {
245
247
  description: string;
@@ -127,7 +127,7 @@ export declare class RootHelpCommand extends Command {
127
127
  };
128
128
  thinking: import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
129
129
  description: string;
130
- options: readonly ["minimal", "low", "medium", "high", "xhigh", "max"];
130
+ options: readonly ["off", ...import("@gajae-code/ai").Effort[]];
131
131
  };
132
132
  "no-rules": import("@gajae-code/utils/cli").FlagDescriptor<"boolean"> & {
133
133
  description: string;
@@ -120,7 +120,7 @@ export default class Index extends Command {
120
120
  };
121
121
  thinking: import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
122
122
  description: string;
123
- options: readonly ["minimal", "low", "medium", "high", "xhigh", "max"];
123
+ options: readonly ["off", ...import("@gajae-code/ai").Effort[]];
124
124
  };
125
125
  "no-rules": import("@gajae-code/utils/cli").FlagDescriptor<"boolean"> & {
126
126
  description: string;
@@ -781,6 +781,9 @@ export declare const TIER_MAP_SKIP_LIST: {
781
781
  readonly "nvidia/upstage/solar-10.7b-instruct": {
782
782
  readonly rationale: "post-rebase catalog addition from dev; not yet curated";
783
783
  };
784
+ readonly "openai-codex/gpt-6-astra": {
785
+ readonly rationale: "GPT-6 Astra catalog addition (2026-09-03 release); not yet curated";
786
+ };
784
787
  readonly "openai-codex/gpt-daybreak-blue-latest": {
785
788
  readonly rationale: "post-rebase catalog addition from dev; not yet curated";
786
789
  };
@@ -11,9 +11,17 @@ export interface FileLockOptions {
11
11
  /** Previous local host identities accepted only when deciding stale-owner reclamation. */
12
12
  previousOwnerHostIds?: readonly string[];
13
13
  }
14
- /** Release retries cover transient Windows/Dropbox handle denial without extending the lock indefinitely. */
15
- export declare const FILE_LOCK_RELEASE_RETRY_ATTEMPTS = 5;
16
- export declare const FILE_LOCK_RELEASE_RETRY_DELAY_MS = 10;
14
+ export declare class FileLockAcquireError extends Error {
15
+ readonly filePath: string;
16
+ readonly lockPath: string;
17
+ readonly attempts: number;
18
+ readonly holder: string;
19
+ readonly code = "acquire_timeout";
20
+ constructor(filePath: string, lockPath: string, attempts: number, holder: string);
21
+ }
22
+ /** Release retries cover transient handle denial and a competing exact-removal quarantine cleanup. */
23
+ export declare const FILE_LOCK_RELEASE_RETRY_ATTEMPTS = 20;
24
+ export declare const FILE_LOCK_RELEASE_RETRY_DELAY_MS = 25;
17
25
  export declare const FileLockTestHooks: {
18
26
  afterParentMkdir?: (lockPath: string) => void | Promise<void>;
19
27
  nativePublicationBindings?: () => {
@@ -47,6 +55,8 @@ export declare function readFileLockInfoForGc(lockDir: string): Promise<FileLock
47
55
  /** Owner identity stamped into a `<file>.lock/info` record. */
48
56
  export interface FileLockOwnerToken {
49
57
  pid: number;
58
+ /** Kernel-derived identity for the exact process generation owning `pid`. */
59
+ process_incarnation?: string;
50
60
  start_time?: string;
51
61
  /** Encoding marker for the canonical UTC process-start identity. */
52
62
  start_time_format?: string;
@@ -93,6 +103,7 @@ export type GenericFileLockDirStaleVerdict = {
93
103
  * but the reclaim-after-stale scenario the issue describes is now guarded.
94
104
  */
95
105
  export declare function removeFileLockDirForGc(lockDir: string, expected: FileLockOwnerToken, preVerdictIdentity?: GenericFileLockDirIdentity): Promise<FileLockGcRemoval>;
106
+ type OwnerLiveness = "alive" | "dead" | "unknown";
96
107
  /**
97
108
  * @internal
98
109
  * READ-ONLY verdict on an EXISTING generic `<file>.lock/` directory that another lock
@@ -122,6 +133,7 @@ type NativeFileLockBindings = {
122
133
  snapshotDirectoryTree(lockPath: string): NativeDirectoryTreeResult;
123
134
  exactRemoveDirectoryTree(lockPath: string, snapshot: NonNullable<NativeDirectoryTreeResult["snapshot"]>): NativeExactUnlinkResult;
124
135
  };
136
+ export declare function acquireFileLock(filePath: string, options?: FileLockOptions): Promise<() => Promise<void>>;
125
137
  /**
126
138
  * Serializes all contenders, including callers in the same process. Because this
127
139
  * API exposes no ownership token, recursive acquisition is indistinguishable
@@ -129,4 +141,20 @@ type NativeFileLockBindings = {
129
141
  * that fact through its own `lockHeld` path instead of acquiring it again.
130
142
  */
131
143
  export declare function withFileLock<T>(filePath: string, fn: () => Promise<T>, options?: FileLockOptions): Promise<T>;
144
+ /** Strictly recognize the staging names emitted by tryAcquireLock. */
145
+ export declare function fileLockStagingOwnerPid(name: string): number | null;
146
+ export interface FileLockStagingResult {
147
+ path: string;
148
+ pid?: number;
149
+ status: OwnerLiveness;
150
+ removed: boolean;
151
+ reason: string;
152
+ }
153
+ /** Observe identity before probing; neither a replacement nor a symlink inherits the verdict. */
154
+ export declare function inspectFileLockStagingDir(stagingPath: string, probe?: (pid: number) => OwnerLiveness, remove?: boolean): Promise<FileLockStagingResult>;
155
+ /** Bounded opportunistic cleanup; the acquisition caller treats failures as diagnostic only. */
156
+ export declare function reapOrphanedLockStagingDirs(lockPath: string): Promise<{
157
+ removed: string[];
158
+ retained: FileLockStagingResult[];
159
+ }>;
132
160
  export {};
@@ -368,6 +368,10 @@ export declare class ModelRegistry {
368
368
  /**
369
369
  * Reload models from disk (embedded + accepted registry + custom from models.yml).
370
370
  */
371
+ refreshStatic(): Promise<void>;
372
+ /**
373
+ * Reload models from disk and refresh runtime provider discovery state.
374
+ */
371
375
  refresh(strategy?: ModelRefreshStrategy): Promise<void>;
372
376
  refreshInBackground(strategy?: ModelRefreshStrategy): void;
373
377
  refreshProvider(providerId: string, strategy?: ModelRefreshStrategy): Promise<void>;
@@ -33,6 +33,15 @@ export declare function parseModelString(modelStr: string): {
33
33
  id: string;
34
34
  thinkingLevel?: ThinkingLevel;
35
35
  } | undefined;
36
+ export declare function resolveStartupModelRefreshSelectors(options: {
37
+ model?: string;
38
+ provider?: string;
39
+ credential?: string;
40
+ continue?: boolean;
41
+ resume?: string | boolean;
42
+ hasStartupProfile: boolean;
43
+ }, settings: ModelRoleSettings): ModelSelectorValue | undefined;
44
+ export declare function refreshMissingQualifiedModelProviders(selectors: ModelSelectorValue | undefined, modelRegistry: Pick<ModelRegistry, "getAvailable" | "getDiscoverableProviders" | "refreshProvider">): Promise<boolean>;
36
45
  /**
37
46
  * Format a model as "provider/modelId" string.
38
47
  */
@@ -27,7 +27,7 @@ export declare const TAB_METADATA: Record<SettingTab, {
27
27
  icon: `tab.${string}`;
28
28
  }>;
29
29
  /** Status line segment identifiers */
30
- export type StatusLineSegmentId = "gajae" | "pi" | "model" | "mode" | "path" | "git" | "pr" | "subagents" | "jobs" | "token_in" | "token_out" | "token_total" | "token_rate" | "cost" | "context_pct" | "context_total" | "time_spent" | "time" | "session" | "hostname" | "cache_read" | "cache_write" | "session_name" | "usage";
30
+ export type StatusLineSegmentId = "gajae" | "pi" | "model" | "mode" | "path" | "git" | "pr" | "subagents" | "jobs" | "token_in" | "token_out" | "token_total" | "token_rate" | "cost" | "context_pct" | "context_total" | "time_spent" | "time" | "session" | "hostname" | "cache_read" | "cache_write" | "session_name" | "usage" | "command";
31
31
  /** Submenu choice metadata. */
32
32
  export type SubmenuOption<V extends string = string> = {
33
33
  value: V;
@@ -1306,6 +1306,25 @@ export declare const SETTINGS_SCHEMA: {
1306
1306
  readonly options: readonly import("../thinking-metadata").ThinkingLevelMetadata[];
1307
1307
  };
1308
1308
  };
1309
+ readonly reasoningLanguage: {
1310
+ readonly type: "enum";
1311
+ readonly values: readonly ["off", "english"];
1312
+ readonly default: "off";
1313
+ readonly ui: {
1314
+ readonly tab: "model";
1315
+ readonly label: "Reasoning Language";
1316
+ readonly description: "Optionally reason through development work in English while preserving the user's response language";
1317
+ readonly options: readonly [{
1318
+ readonly value: "off";
1319
+ readonly label: "Off";
1320
+ readonly description: "Do not add reasoning-language guidance";
1321
+ }, {
1322
+ readonly value: "english";
1323
+ readonly label: "English";
1324
+ readonly description: "Reason through technical work in English and answer in the user's language";
1325
+ }];
1326
+ };
1327
+ };
1309
1328
  readonly hideThinkingBlock: {
1310
1329
  readonly type: "boolean";
1311
1330
  readonly default: false;
@@ -1915,6 +1934,15 @@ export declare const SETTINGS_SCHEMA: {
1915
1934
  readonly description: "Show the interactive GitHub star reminder when gh is authenticated";
1916
1935
  };
1917
1936
  };
1937
+ readonly "paseo.autoImport": {
1938
+ readonly type: "boolean";
1939
+ readonly default: false;
1940
+ readonly ui: {
1941
+ readonly tab: "interaction";
1942
+ readonly label: "Announce Sessions to Paseo";
1943
+ readonly description: "Global-only operator opt-in. When enabled, and only when a GJC ACP provider is already registered in Paseo and its daemon is already running, import each interactive session into Paseo so it can be driven from there. Project settings cannot enable it. Never starts the Paseo daemon or removes imported entries; stale entries must be pruned in Paseo. Never runs when Paseo is absent.";
1944
+ };
1945
+ };
1918
1946
  readonly "crashReport.nudge": {
1919
1947
  readonly type: "boolean";
1920
1948
  readonly default: true;
@@ -187,6 +187,8 @@ export interface PromptRequestV1 {
187
187
  turn_id: string;
188
188
  };
189
189
  coordinator_turn_id?: string;
190
+ /** Retain prompt and source turn until the delegate's outer response is durable. */
191
+ delegate_response_pending?: boolean;
190
192
  safe_response?: Record<string, unknown>;
191
193
  error_code?: PublicReason | "idempotency_conflict";
192
194
  created_at: string;
@@ -275,6 +277,11 @@ export interface CoordinatorSessionTransactionV1 {
275
277
  recovery: {
276
278
  prompt_watermark_at: string | null;
277
279
  last_repaired_at: string | null;
280
+ /** One-shot authority for the initial delegate prompt, consumed atomically with its claim. */
281
+ initial_delegate_request?: {
282
+ key_digest: string;
283
+ request_digest: string;
284
+ };
278
285
  };
279
286
  }
280
287
  export type CanonicalCreateIntentV1 = {
@@ -72,6 +72,13 @@ interface CoordinatorServices {
72
72
  afterCanonicalReportCommit?: (sessionId: string) => void | Promise<void>;
73
73
  /** Test barrier invoked after a canonical report safe response is durable and before outer idempotency completion. */
74
74
  afterCanonicalReportSafeResponse?: (sessionId: string, response: Record<string, unknown>) => void | Promise<void>;
75
+ /** Test barriers around delegate admission and outer response durability. */
76
+ afterDelegateAdmission?: (sessionId: string) => void | Promise<void>;
77
+ afterDelegateCreationWalCommitted?: (sessionId: string) => void | Promise<void>;
78
+ afterDelegateCreationCompleted?: () => void | Promise<void>;
79
+ beforeDelegateResponseCommit?: () => void | Promise<void>;
80
+ afterDelegateResponseCommit?: () => void | Promise<void>;
81
+ readCoordinatorSessionEntries?: (directory: string) => Promise<string[]>;
75
82
  }
76
83
  type CoordinatorModelResolution = {
77
84
  ok: true;
@@ -1 +1,3 @@
1
- export {};
1
+ import { type Skill } from "../capability/skill";
2
+ import type { LoadContext, LoadResult } from "../capability/types";
3
+ export declare function loadMarketplaceSkills(ctx: LoadContext, allowedLevels?: ReadonlySet<"user" | "project">): Promise<LoadResult<Skill>>;
@@ -59,11 +59,34 @@ export declare const SOURCE_PATHS: {
59
59
  readonly projectDir: ".vscode";
60
60
  };
61
61
  };
62
+ /** Ancestors from `cwd` through `stopAt`, excluding one normalized authority boundary. */
63
+ export declare function getAncestorDirs(cwd: string, stopAt?: string | null, excludeDir?: string): Array<{
64
+ dir: string;
65
+ depth: number;
66
+ }>;
62
67
  export type SourceId = keyof typeof SOURCE_PATHS;
68
+ export type ProfileAuthority = "default" | "custom";
63
69
  /**
64
70
  * Get user-level path for a source.
65
71
  */
66
72
  export declare function getUserPath(ctx: LoadContext, source: SourceId, subpath: string): string | null;
73
+ /**
74
+ * Deterministic user-scope skill scan directories, highest precedence first.
75
+ *
76
+ * The canonical root is the agent directory (`getAgentDir()`, moved by
77
+ * `--agent-dir` / `GJC_CODING_AGENT_DIR` / `setAgentDir()`) — the target of
78
+ * every user-scope skill writer (`gjc migrate`, `gjc skill`). An agent-directory
79
+ * profile is a *separate* user scope, the same contract as MCP user config
80
+ * (#4768): its legacy home-relative roots are not scanned, so a profile cannot
81
+ * pick up the default profile's skills (and vice versa). The resolver-owned
82
+ * `profileAuthority` classification is authoritative when supplied, so a
83
+ * custom profile remains isolated even if a later HOME/config-root refresh
84
+ * makes its path look like the current default. In the default profile the
85
+ * agent directory is `<home>/<configDir>/agent` and the configured legacy roots
86
+ * below it are still honored, exactly as before.
87
+ */
88
+ export declare function resolveUserAgentDir(home: string, userAgentDir?: string): string;
89
+ export declare function getUserSkillScanDirs(home: string, userAgentDir?: string, profileAuthority?: ProfileAuthority): string[];
67
90
  /**
68
91
  * Get project-level path for a source (cwd only).
69
92
  */
@@ -115,6 +138,8 @@ export interface ParsedAgentFields {
115
138
  export declare function parseAgentFields(frontmatter: Record<string, unknown>): ParsedAgentFields | null;
116
139
  export interface ScanSkillsFromDirOptions {
117
140
  dir: string;
141
+ /** Selected authority root whose own identity must not be a symlink. */
142
+ authorityRoot?: string;
118
143
  providerId: string;
119
144
  level: "user" | "project";
120
145
  requireDescription?: boolean;
@@ -124,7 +149,15 @@ export declare function compareSkillOrder(aName: string, aPath: string, bName: s
124
149
  export declare const SKILL_FRONTMATTER_SCAN_BYTES: number;
125
150
  /** Maximum total bytes read while seeking the frontmatter closing delimiter. */
126
151
  export declare const SKILL_FRONTMATTER_SCAN_TOTAL_BYTES: number;
152
+ export declare const SkillDiscoveryTestHooks: {
153
+ afterCandidateValidated?: (candidatePath: string) => void | Promise<void>;
154
+ afterAuthorityRootValidated?: (root: string) => void | Promise<void>;
155
+ afterAuthorityRootMissing?: (root: string) => void | Promise<void>;
156
+ afterContainedRootValidated?: (root: string) => void | Promise<void>;
157
+ };
127
158
  export declare function scanSkillsFromDir(_ctx: LoadContext, options: ScanSkillsFromDirOptions): Promise<LoadResult<Skill>>;
159
+ /** Read a regular single-link file that remains contained by its configured root. */
160
+ export declare function readContainedFile(root: string, filePath: string): Promise<string | null>;
128
161
  /**
129
162
  * Recursively expand environment variables in an object.
130
163
  */
@@ -236,6 +269,8 @@ export declare function resolveActiveProjectRegistryPath(cwd: string): Promise<s
236
269
  * never alias as the project registry.
237
270
  */
238
271
  export declare function resolveOrDefaultProjectRegistryPath(cwd: string): Promise<string | undefined>;
272
+ /** Invalidate the exact user/project registry pair and their resolved-root cache entry. */
273
+ export declare function invalidateClaudePluginRoots(home: string, cwd?: string): Promise<void>;
239
274
  /**
240
275
  * List installed GJC plugin roots from the GJC plugin registry and, when present,
241
276
  * the nearest project-scoped registry resolved from `cwd`.
@@ -1,6 +1,19 @@
1
- import type { MinimizerOptions } from "@gajae-code/natives";
1
+ import type { MinimizerOptions, ShellOptions, ShellRunOptions, ShellRunResult } from "@gajae-code/natives";
2
2
  import { Settings, type ShellMinimizerSettings } from "../config/settings";
3
3
  import { type TerminalArtifactPublisher } from "../session/streaming-output";
4
+ type BashShellRunResult = ShellRunResult & {
5
+ signal?: string;
6
+ };
7
+ type Shell = {
8
+ run(options: ShellRunOptions, onChunk?: (error: Error | null, chunk: string) => void): Promise<BashShellRunResult>;
9
+ abort(): Promise<void>;
10
+ close(): Promise<void>;
11
+ isTerminal?(): boolean;
12
+ ready?(): Promise<void>;
13
+ isRunSignalActive?(signal: AbortSignal): boolean;
14
+ };
15
+ type ShellFactory = (options?: ShellOptions) => Shell | Promise<Shell>;
16
+ export declare function setShellFactoryForTests(factory: ShellFactory | undefined): void;
4
17
  export interface BashArtifactSaveSummary {
5
18
  artifactId: string;
6
19
  complete: boolean;
@@ -74,6 +87,8 @@ export interface BashExecutorOptions {
74
87
  export interface BashResult {
75
88
  output: string;
76
89
  exitCode: number | undefined;
90
+ /** POSIX signal that terminated the isolated shell execution boundary. */
91
+ signal?: string;
77
92
  cancelled: boolean;
78
93
  truncated: boolean;
79
94
  totalLines: number;
@@ -97,3 +112,4 @@ export declare function disposeAllShellSessions(): Promise<void>;
97
112
  /** Translate `ShellMinimizerSettings` into native `MinimizerOptions`, or `undefined` when disabled. */
98
113
  export declare function buildMinimizerOptions(group: ShellMinimizerSettings): MinimizerOptions | undefined;
99
114
  export declare function executeBash(command: string, options?: BashExecutorOptions): Promise<BashResult>;
115
+ export {};
@@ -0,0 +1,15 @@
1
+ import type { Process as NativeProcess } from "@gajae-code/natives";
2
+ type OwnershipRecord = {
3
+ pid: number;
4
+ incarnation: string;
5
+ darwinUniqueId?: string | null;
6
+ signature: string;
7
+ };
8
+ export declare function parseOwnershipRecord(line: string): OwnershipRecord | undefined;
9
+ export declare function retainOwnedProcess<T extends Pick<NativeProcess, "pid" | "incarnation">>(owned: Map<string, T>, processRef: T, guardianPid?: number): boolean;
10
+ export declare function extendOwnedDarwinAncestry<T extends {
11
+ uniqueId: bigint;
12
+ parentUniqueId: bigint;
13
+ }>(knownUniqueIds: Set<bigint>, candidates: ReadonlyMap<number, T>): number[];
14
+ export declare function runBashShellGuardian(): Promise<void>;
15
+ export {};
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env bun
2
+ export {};
@@ -0,0 +1,2 @@
1
+ export declare function fatalCatchableSignals(): NodeJS.Signals[];
2
+ export declare function signalExitCode(signal: NodeJS.Signals): number | undefined;
@@ -0,0 +1 @@
1
+ export {};