@gajae-code/coding-agent 0.19.3-nightly.20261030094347.41301593972.gf536b1010d4e → 0.19.3

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 (273) hide show
  1. package/CHANGELOG.md +238 -0
  2. package/dist/types/async/job-manager.d.ts +56 -18
  3. package/dist/types/cli/auth-token-file.d.ts +9 -0
  4. package/dist/types/cli/doctor/install-repairs.d.ts +1 -0
  5. package/dist/types/cli/doctor/types.d.ts +1 -0
  6. package/dist/types/cli/install-activation.d.ts +10 -1
  7. package/dist/types/cli/malloc-env-guard.d.ts +8 -0
  8. package/dist/types/cli/update-cli.d.ts +4 -1
  9. package/dist/types/config/atomic-yaml-patch.d.ts +34 -1
  10. package/dist/types/config/model-profile-activation.d.ts +40 -13
  11. package/dist/types/config/model-registry.d.ts +3 -0
  12. package/dist/types/config/models-config-schema.d.ts +4 -0
  13. package/dist/types/config/settings-schema.d.ts +49 -8
  14. package/dist/types/config/settings.d.ts +39 -5
  15. package/dist/types/config/task-delegation.d.ts +2 -0
  16. package/dist/types/extensibility/extensions/runner.d.ts +2 -0
  17. package/dist/types/extensibility/slash-commands.d.ts +14 -1
  18. package/dist/types/gjc-runtime/managed-owner-admission.d.ts +4 -12
  19. package/dist/types/gjc-runtime/managed-owner-binding.d.ts +164 -0
  20. package/dist/types/gjc-runtime/managed-owner-supervisor.d.ts +26 -33
  21. package/dist/types/gjc-runtime/owner-lifecycle-path.d.ts +21 -0
  22. package/dist/types/gjc-runtime/owner-lifecycle-root.d.ts +7 -0
  23. package/dist/types/gjc-runtime/session-state-sidecar.d.ts +8 -1
  24. package/dist/types/gjc-runtime/tmux-common.d.ts +10 -0
  25. package/dist/types/gjc-runtime/tmux-owner-isolation.d.ts +131 -5
  26. package/dist/types/gjc-runtime/tmux-sessions.d.ts +46 -0
  27. package/dist/types/gjc-runtime/ultragoal-owner-loss-recovery.d.ts +1 -1
  28. package/dist/types/harness-control-plane/session-lease.d.ts +29 -2
  29. package/dist/types/harness-control-plane/storage.d.ts +8 -0
  30. package/dist/types/main.d.ts +12 -0
  31. package/dist/types/memories/index.d.ts +7 -1
  32. package/dist/types/memories/storage.d.ts +1 -0
  33. package/dist/types/memory-backend/types.d.ts +6 -1
  34. package/dist/types/modes/components/model-selector.d.ts +11 -4
  35. package/dist/types/modes/components/notifications-settings-editor.d.ts +2 -166
  36. package/dist/types/modes/components/settings-defs.d.ts +2 -1
  37. package/dist/types/modes/components/settings-selector.d.ts +5 -2
  38. package/dist/types/modes/components/smart-routing-panel.d.ts +19 -14
  39. package/dist/types/modes/components/tool-execution.d.ts +6 -0
  40. package/dist/types/modes/controllers/goal-mode-controller.d.ts +5 -0
  41. package/dist/types/modes/controllers/selector-controller.d.ts +7 -59
  42. package/dist/types/plan-mode/state.d.ts +7 -0
  43. package/dist/types/runtime-mcp/config.d.ts +8 -0
  44. package/dist/types/runtime-mcp/manager.d.ts +43 -0
  45. package/dist/types/runtime-mcp/session-controls-grant.d.ts +7 -0
  46. package/dist/types/sdk/broker/broker.d.ts +33 -7
  47. package/dist/types/sdk/broker/lifecycle.d.ts +1 -0
  48. package/dist/types/sdk/broker/session-index.d.ts +2 -0
  49. package/dist/types/sdk/broker/session-scope.d.ts +31 -1
  50. package/dist/types/sdk/broker/spawn-authority.d.ts +19 -0
  51. package/dist/types/sdk/broker/spawn-substrate.d.ts +12 -1
  52. package/dist/types/sdk/bus/index.d.ts +5 -0
  53. package/dist/types/sdk/bus/notification-orchestration.d.ts +21 -3
  54. package/dist/types/sdk/bus/notification-service.d.ts +2 -1
  55. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +1 -1
  56. package/dist/types/sdk/cli/rows.d.ts +7 -0
  57. package/dist/types/sdk/extension-interaction.d.ts +108 -0
  58. package/dist/types/sdk/host/control/btw-ask.d.ts +19 -0
  59. package/dist/types/sdk/host/control/dispatch.d.ts +2 -0
  60. package/dist/types/sdk/host/control/index.d.ts +1 -0
  61. package/dist/types/sdk/host/control/operations.d.ts +7 -0
  62. package/dist/types/sdk/host/external-permissions.d.ts +47 -0
  63. package/dist/types/sdk/host/host.d.ts +8 -2
  64. package/dist/types/sdk/host/query/handlers.d.ts +1 -0
  65. package/dist/types/sdk/host/session-runtime.d.ts +13 -1
  66. package/dist/types/sdk/host/surface-policy.d.ts +2 -1
  67. package/dist/types/sdk/index.d.ts +11 -0
  68. package/dist/types/sdk/job-observation.d.ts +51 -0
  69. package/dist/types/sdk/lifecycle/service.d.ts +6 -1
  70. package/dist/types/sdk/notification-setup-contract.d.ts +169 -0
  71. package/dist/types/sdk/notification-setup.d.ts +54 -0
  72. package/dist/types/sdk/protocol/adapter-validation.d.ts +2 -0
  73. package/dist/types/sdk/router/session-router.d.ts +5 -0
  74. package/dist/types/sdk/routing-settings.d.ts +57 -0
  75. package/dist/types/sdk/session-list.d.ts +5 -0
  76. package/dist/types/sdk/session-recap.d.ts +50 -0
  77. package/dist/types/sdk/session.d.ts +14 -0
  78. package/dist/types/sdk/settings-catalog.d.ts +52 -0
  79. package/dist/types/sdk/workflow-gates.d.ts +9 -0
  80. package/dist/types/session/agent-session.d.ts +129 -15
  81. package/dist/types/session/client-bridge.d.ts +1 -0
  82. package/dist/types/session/internal/managed-session-storage.d.ts +6 -0
  83. package/dist/types/session/recap.d.ts +104 -0
  84. package/dist/types/session/session-manager.d.ts +51 -1
  85. package/dist/types/session/streaming-output.d.ts +9 -1
  86. package/dist/types/session/workflow-recovery-field-fence.d.ts +4 -0
  87. package/dist/types/session/yield-queue.d.ts +16 -0
  88. package/dist/types/task/executor.d.ts +2 -0
  89. package/dist/types/tools/auto-generated-guard.d.ts +8 -1
  90. package/dist/types/tools/bash.d.ts +1 -1
  91. package/dist/types/tools/grouped-file-tree.d.ts +21 -0
  92. package/dist/types/tools/image-gen.d.ts +6 -1
  93. package/dist/types/tools/index.d.ts +7 -0
  94. package/dist/types/tui/file-list.d.ts +0 -3
  95. package/dist/types/utils/gh.d.ts +5 -0
  96. package/dist/types/utils/herdr-core-status.d.ts +31 -0
  97. package/dist/types/utils/herdr-pane.d.ts +7 -0
  98. package/dist/types/utils/recap-generator.d.ts +41 -0
  99. package/dist/types/web/hardened-http.d.ts +41 -0
  100. package/dist/types/web/insane/url-guard.d.ts +2 -0
  101. package/package.json +7 -7
  102. package/scripts/generate-sdk-operation-inventory.ts +28 -1
  103. package/src/async/job-manager.ts +381 -41
  104. package/src/cli/auth-broker-cli.ts +11 -53
  105. package/src/cli/auth-gateway-cli.ts +13 -56
  106. package/src/cli/auth-token-file.ts +56 -0
  107. package/src/cli/customize-doctor.ts +40 -27
  108. package/src/cli/doctor/install-repairs.ts +36 -2
  109. package/src/cli/doctor/repairs.ts +1 -0
  110. package/src/cli/doctor/report.ts +2 -0
  111. package/src/cli/doctor/types.ts +1 -0
  112. package/src/cli/install-activation.ts +58 -1
  113. package/src/cli/malloc-env-guard.ts +11 -0
  114. package/src/cli/session-picker.ts +8 -2
  115. package/src/cli/setup-cli.ts +2 -0
  116. package/src/cli/update-cli.ts +48 -3
  117. package/src/cli-main.ts +2 -2
  118. package/src/cli-ordinary.ts +2 -2
  119. package/src/commands/harness.ts +16 -3
  120. package/src/config/atomic-yaml-patch.ts +439 -141
  121. package/src/config/machine-identity.ts +6 -2
  122. package/src/config/mcp-schema.json +1 -1
  123. package/src/config/model-profile-activation.ts +505 -248
  124. package/src/config/model-registry.ts +54 -2
  125. package/src/config/models-config-schema.ts +2 -0
  126. package/src/config/settings-schema.ts +52 -8
  127. package/src/config/settings.ts +640 -237
  128. package/src/config/task-delegation.ts +4 -1
  129. package/src/coordinator-mcp/question-gate-codec.ts +17 -5
  130. package/src/coordinator-mcp/server.ts +2 -0
  131. package/src/extensibility/extensions/runner.ts +6 -0
  132. package/src/extensibility/gjc-plugins/installer.ts +2 -1
  133. package/src/extensibility/plugins/marketplace/fetcher.ts +28 -119
  134. package/src/extensibility/slash-commands.ts +90 -16
  135. package/src/gjc-runtime/launch-tmux.ts +79 -23
  136. package/src/gjc-runtime/launch-worktree.ts +15 -3
  137. package/src/gjc-runtime/managed-owner-admission.ts +298 -212
  138. package/src/gjc-runtime/managed-owner-binding.ts +410 -0
  139. package/src/gjc-runtime/managed-owner-supervisor.ts +265 -112
  140. package/src/gjc-runtime/owner-lifecycle-path.ts +82 -0
  141. package/src/gjc-runtime/owner-lifecycle-root.ts +26 -0
  142. package/src/gjc-runtime/ralplan-current-final.ts +35 -15
  143. package/src/gjc-runtime/ralplan-runtime.ts +3 -0
  144. package/src/gjc-runtime/session-state-sidecar.ts +61 -28
  145. package/src/gjc-runtime/tmux-common.ts +28 -0
  146. package/src/gjc-runtime/tmux-owner-isolation.ts +1100 -111
  147. package/src/gjc-runtime/tmux-sessions.ts +293 -58
  148. package/src/gjc-runtime/ultragoal-change-set.ts +8 -1
  149. package/src/gjc-runtime/ultragoal-owner-loss-recovery.ts +1 -1
  150. package/src/harness-control-plane/finalize.ts +2 -0
  151. package/src/harness-control-plane/owner.ts +23 -1
  152. package/src/harness-control-plane/preserve.ts +7 -1
  153. package/src/harness-control-plane/session-lease.ts +357 -3
  154. package/src/harness-control-plane/storage.ts +61 -10
  155. package/src/hashline/execute.ts +13 -1
  156. package/src/internal-urls/docs-index.generated.ts +12 -12
  157. package/src/lsp/lspmux.ts +4 -0
  158. package/src/main.ts +44 -3
  159. package/src/master-mode/snapshot.ts +13 -1
  160. package/src/memories/index.ts +8 -1
  161. package/src/memories/storage.ts +1 -0
  162. package/src/memory-backend/types.ts +6 -1
  163. package/src/modes/acp/acp-agent.ts +28 -4
  164. package/src/modes/components/gjc-bundle-settings.ts +56 -14
  165. package/src/modes/components/model-selector.ts +98 -18
  166. package/src/modes/components/notifications-settings-editor.ts +68 -188
  167. package/src/modes/components/session-selector.ts +27 -5
  168. package/src/modes/components/settings-defs.ts +4 -10
  169. package/src/modes/components/settings-selector.ts +93 -66
  170. package/src/modes/components/smart-routing-panel.ts +363 -48
  171. package/src/modes/components/tool-execution.ts +388 -9
  172. package/src/modes/controllers/event-controller.ts +2 -1
  173. package/src/modes/controllers/extension-ui-controller.ts +2 -1
  174. package/src/modes/controllers/goal-mode-controller.ts +24 -0
  175. package/src/modes/controllers/plan-mode-controller.ts +11 -3
  176. package/src/modes/controllers/selector-controller.ts +127 -1242
  177. package/src/modes/interactive-mode.ts +44 -3
  178. package/src/modes/runtime-init.ts +2 -1
  179. package/src/modes/shared/agent-wire/approval-gate.ts +13 -2
  180. package/src/modes/shared/agent-wire/deep-interview-gate.ts +2 -4
  181. package/src/plan-mode/state.ts +17 -0
  182. package/src/prompts/system/master-mode.md +2 -0
  183. package/src/prompts/system/recap-system.md +5 -0
  184. package/src/prompts/system/system-prompt.md +5 -1
  185. package/src/prompts/tools/ask.md +4 -3
  186. package/src/runtime-mcp/config.ts +20 -1
  187. package/src/runtime-mcp/manager.ts +588 -45
  188. package/src/runtime-mcp/session-controls-grant.ts +24 -0
  189. package/src/sdk/acp/adapter.ts +14 -3
  190. package/src/sdk/broker/broker.ts +237 -23
  191. package/src/sdk/broker/lifecycle.ts +2 -0
  192. package/src/sdk/broker/session-index.ts +93 -19
  193. package/src/sdk/broker/session-scope.ts +81 -2
  194. package/src/sdk/broker/spawn-authority.ts +34 -5
  195. package/src/sdk/broker/spawn-substrate.ts +117 -18
  196. package/src/sdk/bus/chat-daemon-control.ts +2 -2
  197. package/src/sdk/bus/index.ts +77 -11
  198. package/src/sdk/bus/notification-orchestration.ts +141 -59
  199. package/src/sdk/bus/notification-service.ts +25 -23
  200. package/src/sdk/bus/telegram-daemon-contract.ts +1 -1
  201. package/src/sdk/cli/master-cli.ts +2 -2
  202. package/src/sdk/cli/rows.ts +9 -0
  203. package/src/sdk/cli/session-cli.ts +29 -4
  204. package/src/sdk/extension-interaction.ts +533 -0
  205. package/src/sdk/host/control/btw-ask.ts +49 -0
  206. package/src/sdk/host/control/dispatch.ts +12 -0
  207. package/src/sdk/host/control/index.ts +1 -0
  208. package/src/sdk/host/control/operations.ts +7 -0
  209. package/src/sdk/host/external-permissions.ts +332 -0
  210. package/src/sdk/host/host.ts +8 -2
  211. package/src/sdk/host/query/handlers.ts +9 -0
  212. package/src/sdk/host/sdk-surface-parity.test.ts +55 -1
  213. package/src/sdk/host/session-runtime.test.ts +142 -1
  214. package/src/sdk/host/session-runtime.ts +108 -28
  215. package/src/sdk/host/surface-policy.ts +11 -0
  216. package/src/sdk/index.ts +15 -0
  217. package/src/sdk/job-observation.ts +157 -0
  218. package/src/sdk/lifecycle/service.ts +15 -2
  219. package/src/sdk/notification-setup-contract.ts +181 -0
  220. package/src/sdk/notification-setup.ts +1151 -0
  221. package/src/sdk/protocol/adapter-validation.ts +6 -1
  222. package/src/sdk/protocol/operation-inventory.generated.json +239 -6
  223. package/src/sdk/protocol/operation-registry.ts +21 -3
  224. package/src/sdk/router/session-router.ts +12 -1
  225. package/src/sdk/routing-settings.ts +395 -0
  226. package/src/sdk/session-list.ts +37 -0
  227. package/src/sdk/session-recap.ts +121 -0
  228. package/src/sdk/session.ts +335 -23
  229. package/src/sdk/settings-catalog.ts +119 -0
  230. package/src/sdk/workflow-gates.ts +30 -0
  231. package/src/session/agent-session.ts +1880 -238
  232. package/src/session/client-bridge.ts +1 -1
  233. package/src/session/contribution-prep.ts +8 -1
  234. package/src/session/internal/managed-session-storage.ts +17 -3
  235. package/src/session/recap.ts +298 -0
  236. package/src/session/session-manager.ts +776 -121
  237. package/src/session/streaming-output.ts +69 -9
  238. package/src/session/workflow-recovery-field-fence.ts +27 -0
  239. package/src/session/yield-queue.ts +52 -1
  240. package/src/setup/provider-presets.json +3 -1
  241. package/src/slash-commands/builtin-registry.ts +124 -4
  242. package/src/ssh/connection-manager.ts +3 -2
  243. package/src/ssh/ssh-executor.ts +3 -0
  244. package/src/ssh/sshfs-mount.ts +5 -4
  245. package/src/task/executor.ts +3 -0
  246. package/src/task/index.ts +48 -19
  247. package/src/tools/ast-edit.ts +10 -47
  248. package/src/tools/ast-grep.ts +10 -45
  249. package/src/tools/auto-generated-guard.ts +21 -1
  250. package/src/tools/bash-allowed-prefixes.ts +2 -0
  251. package/src/tools/bash.ts +10 -4
  252. package/src/tools/bisect.ts +5 -0
  253. package/src/tools/browser/launch.ts +7 -2
  254. package/src/tools/browser/registry.ts +5 -0
  255. package/src/tools/grouped-file-tree.ts +86 -0
  256. package/src/tools/image-gen.ts +180 -174
  257. package/src/tools/index.ts +7 -0
  258. package/src/tools/json-tree.ts +2 -2
  259. package/src/tools/recipe/runners/cargo.ts +3 -0
  260. package/src/tools/recipe/runners/just.ts +3 -0
  261. package/src/tools/recipe/runners/task.ts +3 -0
  262. package/src/tools/search.ts +9 -48
  263. package/src/tools/tool-catalog.generated.ts +1 -1
  264. package/src/tui/file-list.ts +14 -3
  265. package/src/utils/gh.ts +14 -1
  266. package/src/utils/git.ts +1 -8
  267. package/src/utils/herdr-core-status.ts +156 -0
  268. package/src/utils/herdr-pane.ts +38 -26
  269. package/src/utils/recap-generator.ts +191 -0
  270. package/src/web/hardened-http.ts +183 -0
  271. package/src/web/insane/bridge.ts +2 -1
  272. package/src/web/insane/url-guard.ts +7 -2
  273. package/src/web/scrapers/youtube.ts +3 -0
package/CHANGELOG.md CHANGED
@@ -2,6 +2,244 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.19.3] - 2026-11-03
6
+
7
+ ### Added
8
+
9
+ - Public portable extension interactions and shared extension initialization, with explicit terminal-only refusals and session/connection/request ownership.
10
+ - Lazy session-owned job observation with owner/generation-scoped monitor controls and read-only folded work.
11
+ - Shared trusted-local notification setup operations used by the TUI and embedding SDK. These additions do not install new managed operations or establish full SDK/TUI parity.
12
+
13
+ - Add a schema-derived, read-only SDK settings catalog with layer provenance, explicit withheld values, runtime-choice gaps and unclassified application behavior. Free-form strings and compound values never enter its display snapshot; full settings UI parity remains incomplete.
14
+ - Expose canonical smart-routing preview/apply/refresh/clear/enable intents shared with the TUI, with instance-bound preview ownership, stale-source refusal, global-only refresh and explicit durability/activation outcomes.
15
+
16
+ - Peer rows in the master peer snapshot, `gjc sdk search`, `gjc sdk session list`, and `gjc sdk session inspect` now show ownership. `role: "master"` marks a session whose index row records a master role, and `spawnedBy: { masterSessionId, self }` names the master whose `gjc sdk spawn` created the session, taken from Broker spawn authority. `self` is `true` only for the viewing master's own children, so two masters in one scope no longer mistake each other's children for their own. The search table adds an `OWNER` column, and the master guidance says not to steer, interrupt, or close another master's sessions without explicit user instruction. The Bash tool in a non-master session no longer passes an inherited `GJC_MASTER_OWNER_SESSION_ID` through ([#7439](https://github.com/Yeachan-Heo/gajae-code/issues/7439)).
17
+
18
+ - `gjc setup provider --preset cloudgpu` (alias: `cloudgpu-app`): OpenAI-compatible custom provider for CloudGPU (`CLOUDGPU_API_KEY`, live `/v1/models` discovery limited to rows whose input and output modalities are text, `system` role instead of `developer`, `reasoning_content` reasoning field).
19
+ - `discovery.inputModalities` for `openai-models-list` providers: admit only catalog rows whose advertised `input_modalities` fall inside the list. Text-output filtering alone still admits transcription rows, which advertise audio input and text output.
20
+
21
+ - gjc reports its lifecycle (idle, working, blocked on `ask`) through OSC 7501 when it runs in a herdr-core (`hc`) terminal, including the Herdr desktop app, so it appears in Herdr's Agents sidebar and works with `hc wait` and `hc send`'s blocked guard. The report is retracted on exit. The herdr TUI integration (`HERDR_ENV`) is unchanged.
22
+
23
+ - Report prompt run acceptances to embedders through `PromptOptions.onRunAccepted`, including replacement handles minted for mid-run context maintenance on the same logical run, exactly once per handle and contained when the observer throws or rejects.
24
+
25
+ - `gjc setup provider --preset runcrate` (alias: `runcrate-ai`): OpenAI-compatible custom provider for Runcrate (`RUNCRATE_API_KEY`, live `/v1/models` discovery limited to text-output models, `vendor/model` model ids, `reasoning_content` reasoning field).
26
+ - `discovery.outputModalities` for `openai-models-list` providers: admit only catalog rows whose advertised `output_modalities` fall inside the list, so image, audio, video and embedding rows are not registered as chat-completion models.
27
+
28
+ - `btw.ask`: an SDK control that answers one ephemeral `/btw` side question from the live session context. It owns no turn and persists nothing to the session transcript, refuses a second concurrent question with `busy`, and refuses empty or oversized questions as invalid input.
29
+
30
+ - Expose opt-in, session-scoped external tool approvals through `permission.channel.set`, `permission.requests.list`, and `permission.respond` on native SDK-only and broker-backed session hosts and the daemon CLI raw hatch, with tool input context, rejection comments, bounded waits and fail-closed cancellation. This is the upstream prerequisite for Heyaaz/gajae-bot#165, not its desktop implementation.
31
+
32
+ - Add an internal bounded session-owned approval queue with session/request fencing, offered-option validation, expiry, cancellation, and shared host control setup. Public polling operations and host activation are deferred to follow-up changes.
33
+
34
+ - Conventional interactive root sessions can use `/mcp` to inspect, connect, disconnect, and reconnect eligible native MCP servers for the current session without changing `mcp.json`.
35
+
36
+ - Live-session-only executor/planner/critic/architect model choices without mutating shared Settings; actual dispatch, detached snapshots, eager prompts and slash status all use the same effective map. Clearing reveals the current inheritance, and a committed identity/profile replacement retires the choices.
37
+
38
+ - Opt-in `recap.enabled` (default off) writes a one-line AI recap after a normally completed turn, linked to its request and final-answer entries. Failures and over-limit output are dropped, never retried, clipped, or regenerated.
39
+ - The `/resume` picker shows and searches the latest recap, and exact SDK `session.list` lookups expose a read-only `savedSession.recap`. Reads never call a model or write the transcript.
40
+
41
+ - First-accepted-input automatic title generation with manual-name precedence and lifecycle cancellation, decoupled from prompt delivery.
42
+
43
+ ### Changed
44
+
45
+ - Clarify public SDK embedding contracts for builtin slash dispatch, routing authority and confirmation, reversible Settings receipts, canonical notifications, session-owned jobs and portable extension interactions; exercise builtin dispatch through the public package entry point.
46
+
47
+ - Model-profile activation is now expressed as a prepared transaction (prepare → commit → finish) fenced on the session identity generation: an activation superseded mid-flight rolls back only its own writes instead of publishing a half-applied projection. The new transaction ships alongside the existing activation path; the session control surface switches to it in the next layer.
48
+
49
+ - Switching the default model profile now runs as one prepared transaction (prepare → commit → finish) fenced on the session's identity generation: an activation superseded mid-flight rolls back only its own writes, so a concurrent identity or profile change no longer inherits a half-applied projection.
50
+
51
+ - The system prompt's verification rules now tell the agent that when a change alters a shared data contract (key, identifier, serialized format, schema, default), it also checks the consumers symbol search misses: persisted data, other languages, config and flags, and pinned dependency source.
52
+
53
+ - The system prompt's verification rules now tell the agent to test a shared assumption directly once a second fix built on it fails the same check, and, before attributing a measured result (speedup, regression, latency, eval score) to a change, to identify the bottleneck or confounder that bounds it, rule out that it measured something else, and label attribution it could not verify.
54
+
55
+ ### Fixed
56
+
57
+ - Apply sampling settings changes to live embedding and TUI sessions through shared settings observation, including atomic commits and CAS restores. Preserve atomic receipts and other observers when a change listener fails.
58
+ - Publish sampling adopted during ordinary saves, isolate process-global presentation hooks, and fence overlapping same-value/ABA writes across in-process settings owners without rejecting unrelated model-role changes. Cross-process ownership still uses the existing hash/exact-file checks.
59
+ - Reject forged, copied, foreign, discarded, and replayed notification provider drafts; claim Telegram setup drafts before asynchronous work to prevent concurrent commits.
60
+
61
+ - Reject ambiguous ancestor/descendant atomic batches before mutation; preserve ordered writes to one exact path.
62
+ - Return failed notification saves to fresh setup instead of retrying consumed drafts. Require portable interaction shutdown before session shutdown and settle only validated request identities.
63
+
64
+ - Redact configured notification tokens and fingerprints from recovered endpoint session IDs and all retained/debris path lists, preserving counts, cleanup authority and optional-field presence.
65
+
66
+ - Snapshot portable renderer reply addresses before the final lifecycle and ownership check, so accessor-triggered disconnects or reconnects cannot consume another renderer's pending interaction.
67
+
68
+ - Retire exact MCP grants when a loaded transcript's session ID changes at the same path, preventing stale controls from retaining authority after in-place transcript replacement.
69
+
70
+ - Report path revisions for in-memory atomic receipts and determine routing durability from the actual Settings storage capability, not a receipt-shape heuristic.
71
+ - Preserve a retained successful receipt's ownership when two or more speculative successor batches fail, without weakening same-value/ABA checks or runtime-intent invalidation.
72
+ - Cover lock-only builders that complete an external action while a newer local setter rejects nonempty writes.
73
+
74
+ - Keep descriptive layer-resolution metadata solely under `resolution`; the query-only settings catalog no longer repeats `allowedLayers` under `mutation`, where it could be mistaken for write authorization.
75
+
76
+ - Refuse active Telegram configuration for foreign or unverifiable daemon identities, require durable settings for notification mutations and external runtime actions, preserve inactive saves with session reconciliation, and report completed persistence separately from rollback or runtime failures. Protect secret-safe owner metadata and diagnostics.
77
+ - Reject unsafe paths, malformed operations and unjournaled ancestor replacements before applying atomic batches. Stage memory updates, isolate YAML builder inputs and preconditions, reject nested queue deadlocks, return independently owned inverse receipts, and preserve literal model-role keys across reload.
78
+ - Enforce portable interaction payload limits on detached data and fence reentrant request options before admitting pending interactions.
79
+ - Reject nested Settings flushes that would wait on another active YAML owner, preserving deferred writes and independent FIFO operations.
80
+ - Refuse modified or raced smart-routing previews instead of silently applying unseen generated routes. Keep preview authority inside the host while returning detached display snapshots.
81
+ - Forward the actual committed preview through the controller, model selector and panel instead of regenerating unpublished routes after a catalog change or reporting post-save preview failures as failed commits.
82
+ - Preserve newer routing writers during post-save notification failure by restoring only through the atomic receipt's CAS ownership check. Mark open panels unknown after shared invalidation or a failed post-commit UI refresh.
83
+ - Bind hand-edit confirmation to the exact guarded state and caller-owned refresh proof, with explicit cancellation; reject intervening edits or catalog drift instead of replacing them unseen.
84
+ - Keep routing drafts editable when preview regeneration fails, refuse invalid apply proofs, and distinguish pending or committed global refresh results from effective overlays.
85
+ - Prevent queued or asynchronous current-value atomic builders from overtaking newer local setters or runtime override intent, including same-value/ABA writes and setters already captured by an earlier save. Preserve completed lock-only profile deletion and durable receipt ownership; keep synchronous memory publication and ordinary queued batches correctly ordered.
86
+ - Derive catalog provenance through canonical cumulative merges, including scalar/null/array ancestor replacement, and retain real keyboard access to fresh routing review after a failed apply.
87
+
88
+ - The agent now explains a decision in visible text before opening an `ask` selector, and `ask` examples carry their premise and trade-offs in the question body, so users no longer face bare option labels with no context (#7324).
89
+
90
+ - Preserve pending SDK and ACP tool approvals when permission mode updates are invalid or unchanged; actual policy transitions still cancel pending approvals (#7426).
91
+ - Fence delegated permission providers by the parent policy epoch and cancel stale approvals after policy, permission-provider, abort, or disposal changes without cancelling approvals for filesystem-only bridge updates.
92
+ - Inherit the current parent SDK permission provider in task descendants without forwarding unrelated bridge capabilities; revoke cached grants and pending approvals across descendants when inherited authority expires.
93
+
94
+ - Master sessions inject the peer snapshot once, before the first accepted provider request, as documented. The check for an earlier snapshot looked for the wrong session entry type, so it never matched and every new prompt turn collected and injected a fresh snapshot ([#7438](https://github.com/Yeachan-Heo/gajae-code/issues/7438)).
95
+
96
+ - ACP reattachment no longer fails with `ACP session … has no current Router attachment` when the broker still reports a session live but the long-running ACP process's Router holds no attachment for it. Reattachment now falls back to `session.resume`, which re-proves the host and returns its exact endpoint authority or relaunches it.
97
+
98
+ - Fixed ACP clients attached to a session hosted by an interactive terminal receiving nothing from a turn typed in that terminal: no tool calls, no `ask`, no assistant text, only the running/idle status. Turn content now reaches any SDK connection that negotiates `turn_stream`; `session_host_observer_v1` keeps only its meaning of not keeping a detached host alive, so an ACP client still keeps a broker-launched host from being reaped.
99
+
100
+ - The helpers GJC launches during a session now start from the same filtered environment as the bash tool. This covers the configured `completion.notifyCommand` after each turn, and every browser the browser tool starts: puppeteer Chromium, an `app.path` executable, and an `app.browser: "chrome"` profile. Previously a repository `.env` declaring `NODE_OPTIONS=--require ./x.js`, `LD_PRELOAD` or another hook variable ran repository code inside them. The notify command and puppeteer Chromium spread the process environment, into which the project `.env` is copied, so they leaked in the compiled binary too; the `app.path` and `chrome` profile launches inherited Bun's autoloaded environment (source and npm installs). The `insane` web-engine bridge, which the production `read` path currently does not invoke, builds its subprocess environment the same way, so a future reactivation inherits the filter.
101
+
102
+ - The bisect tool's `run` predicate now starts with the same environment as a bash tool command: project-declared hook variables are dropped and the non-interactive overrides (`GIT_EDITOR`, `GIT_TERMINAL_PROMPT`, `SSH_ASKPASS`, pager and color settings) apply. Previously the predicate's `sh -c` inherited Bun's autoloaded environment, so on source and npm installs a repository `.env` declaring `NODE_OPTIONS=--require ./x.js`, `LD_PRELOAD`, or `GIT_CONFIG_*` ran repository code inside the predicate at every bisect step, which the same command run through the bash tool would not.
103
+
104
+ - Managed `session.spawn` no longer times out on registration: the Broker resolves the actual SDK host (the verified direct child of the pinned managed supervisor, or the headless process itself) before publishing the lifecycle marker, and binds spawn registration to that host's pid/incarnation and the lifecycle request id instead of to the supervisor proof.
105
+ - A managed `session.spawn` whose host exits on its own at its readiness cutoff while the Broker closes it after an unresolved owner now fails as `lifecycle_owner_unresolved` instead of `terminal_uncertain`, once its exact substrate proof reports it gone.
106
+
107
+ - Bundled Codex `gpt-image-*` models now post to `/codex/images/generations` instead of the Responses route when they target the bundled Codex endpoint. Custom Codex models, including ones that reuse a `gpt-image-*` id behind a custom base URL, stay on `/codex/responses` with the hosted image tool and edits. Codex route normalization works on the base URL pathname, so a trailing `/codex` or `/codex/responses` path is stripped once, query strings are preserved, and fragments are dropped.
108
+
109
+ - Compaction now moves tool-result `details` (for example an MCP tool's full raw response with base64 screenshots) and large encrypted `thinkingSignature` values out of compacted history into cold storage. They used to stay in the transcript forever, so long-lived sessions such as 5-minute cron loops hit the 128 MiB per-file cap (`near_limit_rewrite`) within days and `/compact` could not recover them. Both rehydrate unchanged when read.
110
+
111
+ - Managed tmux children on macOS pass pre-CLI admission instead of always exiting 75 with `exact_child_binding_unavailable`: the CLI now reads its private child binding through the bounded native owner-only reader, and Broker-redacted launches publish an opaque (command-free) binding instead of none.
112
+ - Managed-owner admission handoffs and supervisor bindings are only published through retained private authority; unsafe or missing lifecycle storage blocks the child with a bounded `handoff_not_persisted` diagnostic instead of a pathname write.
113
+ - Supervised managed tmux launches from a workspace reached through a symlink (including a symlinked `.gjc`) no longer fail lifecycle verification with `gjc_tmux_managed_storage_unsafe` or `managed_owner_storage_unsafe`: the derived state path names the workspace canonically.
114
+ - Managed tmux/psmux launches on Windows are rejected with `gjc_tmux_managed_launch_platform_unsupported:win32` before any lifecycle storage or supervisor allocation, since managed admission needs the owner-only reader that Windows lacks.
115
+ - A supervised root `gjc --tmux` launch with an operator `GJC_COORDINATOR_SESSION_STATE_FILE` whose directory is relative, contains `..`, or ends in whitespace is refused with `gjc_tmux_state_file_pin_unsafe` before it creates any tmux lifecycle storage or tmux session, instead of failing in (or being read trimmed by) its supervisor after the session starts. The pin itself is never lexically normalized. Planning a signed coordinator launch no longer creates its state directory (or a temporary `gjc-coordinator-bootstrap` directory) for the bootstrap placeholder, which is replaced by a loopback endpoint before launch.
116
+ - No-replace managed publication on filesystems without atomic no-replace rename (the link fallback, for example NFS) now syncs the directory after removing its staging link, so a crash cannot restore that link and leave owner evidence rejected as a hard link.
117
+
118
+ - Managed tmux shutdown works on macOS: the supervisor relays a close to its child through its own spawn handle, and `forceCloseGjcTmuxSession` closes a managed owner through a generation-fenced owner intent that succeeds only after both supervisor exit and the matching terminal verdict, instead of failing with `managed_owner_supervisor_signal_failed`.
119
+ - A macOS managed close that arrives before the supervisor has published its binding now waits, within the close deadline, for that same exact supervisor's binding instead of failing once with `managed_owner_binding_unavailable`; untrusted, ambiguous, or replaced supervisor evidence still fails closed.
120
+ - Ordinary interactive `gjc --tmux` root sessions on macOS now run under the managed owner supervisor like Linux, so `gjc session force-close` closes them through the cooperative intent instead of timing out with `managed_owner_binding_unavailable`. As on Linux, these supervised launches no longer write the diagnostic `tmux-exit.json` marker.
121
+ - Relaunching a pinned macOS session id after its supervised owner exited normally starts a fresh owner instead of failing with `managed_owner_replacement_evidence_ambiguous`; SIGABRT recovery evidence remains Linux-only.
122
+ - A macOS managed close of a pinned session that was closed and relaunched many times no longer fails with `managed_owner_binding_discovery_limit`: the close reads the current generation's supervisor index instead of scanning the shared lifecycle root.
123
+ - A macOS managed close whose earlier attempt expired because the supervisor was stopped or stalled can be retried: an expired intent that the supervisor never relayed is retired under the generation lock instead of making every later close fail with `owner_intent_replay`.
124
+ - A SIGTERM that is not the supervisor's relay of the pending close intent is no longer classified as an expected operator shutdown on macOS, so an unrelated signal during a close is recorded as owner loss rather than a completed run.
125
+ - Supervised `gjc --tmux --worktree` launches from a symlinked in-repository `.worktrees` bucket no longer fail with `managed_owner_storage_unsafe`.
126
+ - macOS root launches no longer store the child command, including prompts and `--api-key` values, in the supervisor binding.
127
+ - Supervised root `gjc --tmux` launches accept empty arguments (`gjc --tmux @prompt.txt ''`) and no longer re-encode the argv as JSON inside the tmux command, so escape-heavy prompts that fit tmux's command limit before supervision still fit. A Linux argv whose recoverable binding would exceed the 64 KiB owner-only read bound is refused with `managed_owner_command_too_large` before any tmux session is created.
128
+ - A pinned macOS session relaunched after a backward wall-clock correction can still be closed: a new owner generation is never published earlier than its predecessor or that predecessor's terminal verdict, so the genuine predecessor no longer reads as a conflicting terminal (`owner_terminal_conflict`).
129
+ - A macOS cooperative close now treats the pinned supervisor as exited only when the process table positively reports its PID absent or reused. A transient process lookup failure no longer counts as exit, so the session is never killed while owner cleanup may still be running.
130
+ - The cooperative relay publisher is injected by the supervisor, keeping managed session storage out of the MCP machine entrypoint's import graph.
131
+ - A missing supervisor index is no longer accepted as delivery evidence on macOS: an unrelated SIGTERM after a cooperative close intent stays `unexpected_owner_loss` unless the supervisor confirmed relaying that intent.
132
+ - Relaunching a pinned macOS session no longer starts a second owner while the predecessor's supervisor, or a process admitted under it, is still alive; the relaunch fails with `managed_owner_predecessor_live`, and an unobservable predecessor fails with `managed_owner_replacement_evidence_unavailable`. Each admitted process records its exact pid and start time before its generation fence, so a supervisor killed after admission can no longer hide a live child from the relaunch. A launch that crashed before publishing its generation is checked the same way, and a child of a not yet published generation is admitted only while the generation its launcher saw is still current, so a child that starts after a relaunch is refused.
133
+ - A macOS shutdown verdict is expected only when the owner-loss observation follows the supervisor's confirmed relay of a cooperative intent that was still valid when relayed. A relay committed after a wall-clock rollback is no longer rejected for predating the supervisor binding.
134
+ - A macOS child that is signaled while its supervisor is still durably publishing the relay record now waits for that record instead of ending with `owner_verdict_unavailable`.
135
+ - A macOS close that times out or sees a mismatched verdict retires its undelivered intent at once, so the supervisor cannot relay it later and a retry does not fail with `owner_intent_replay`.
136
+ - A macOS force-close measures its deadline on monotonic time, so a wall-clock step during the close neither extends the wait, nor lets an abandoned intent outlive it, nor rejects a timely verdict after the child's cleanup.
137
+ - A macOS supervisor starts a relay only while the closer that published the intent is still waiting, proven by a lock the closer holds and the OS releases when it exits, so an intent abandoned after a timeout is not newly relayed later, even after a wall-clock step.
138
+ - A macOS child classifies its SIGTERM as an operator shutdown only if the supervisor's relay record for the close intent was already visible when its postmortem began, so a signal whose postmortem started before the relay is never attributed to it.
139
+ - A managed child that dies of a fatal signal other than SIGTERM (for example SIGABRT) after the supervisor relayed a close intent is recorded as `unexpected_owner_loss` with its actual termination, instead of the supervisor publishing an expected operator shutdown for it. A macOS supervisor also refuses to relay to a child that has already terminated but is not yet reaped.
140
+ - A macOS source-mode managed launch (`bun <entry>`), both an interactive root `gjc --tmux` and a Broker-spawned session, starts the pane supervisor and its child with `--no-env-file`, so a cwd `.env` that sets `MallocStackLogging` can no longer make the malloc guard re-exec below the pinned pane PID and break `gjc session force-close` with `managed_owner_binding_untrusted`.
141
+ - A macOS managed child installs a cooperative SIGUSR2 handler before the CLI starts and announces it with a readiness record; the supervisor relays a close only to a ready child, and only through that signal. The child records which termination signal it handled first, so a SIGTERM, SIGHUP or SIGINT that began its shutdown before the relay arrived is recorded as `unexpected_owner_loss` instead of an expected operator shutdown A child whose shutdown began before the handler was installed never announces readiness.
142
+ - A macOS cooperative close succeeds only after the supervisor reconciles the child's actual exit: a child that published an expected verdict but then died of a fatal signal or exited with a failure code makes the close fail with `owner_term_child_exit_unexplained` and records an `unexpected_owner_loss` incident.
143
+ - The macOS supervisor no longer passes `MallocStackLogging` or `MallocStackLoggingNoCompact` from a project `.env` to its child.
144
+ - Relaunching a pinned managed session can no longer leave an unclosable owner: every generation publisher (relaunch, `gjc session create`, harness launch, raw publication) runs the predecessor check under the generation publication lock, and a supervised child whose published generation was replaced before its binding existed is blocked with `owner_generation_stale` instead of running behind a generation that close no longer reaches.
145
+
146
+ - The subsystems that run `git` directly instead of through GJC's git wrapper -- `gjc --worktree` launch, ultragoal checkpoints, autoresearch and harness status, plugin installs, contribution prep, ralplan, the coordinator's branch-name check, and the bash tool's worktree check -- now start git from the same filtered environment as the bash tool. Previously, on source and npm installs (Bun dotenv autoload), a repository `.env` declaring `GIT_CONFIG_*` could set `core.hooksPath` or `core.fsmonitor` and make that git run repository code; for example `gjc --worktree` ran a planted `post-checkout` hook and ultragoal checkpoints ran a planted fsmonitor.
147
+
148
+ - Disposing a session no longer hangs when an MCP tool activation is still retrying, for example after `/new` restored a session MCP server.
149
+
150
+ - `renderFileList` strips terminal controls from each entry name and its meta text before theme styling. Other find lines are unchanged.
151
+
152
+ - The `gh` calls GJC makes on its own -- the status line's PR lookup for the current branch and the star reminder's check -- now use the same environment as the github tool's `gh`: project-dotenv hook variables are dropped, `GH_PAGER` is pinned to `cat`, and `GH_FORCE_TTY` is removed. Previously, on source and npm installs, a repository `.env` declaring `NODE_OPTIONS`, `LD_PRELOAD`, `GH_PAGER`, or `GH_FORCE_TTY` reached those background `gh` processes (and the git they run) as soon as the status line showed a feature branch.
153
+
154
+ - The raw-session scripts in `scripts/gjc-session/` (`create.sh`, `postmortem.sh` and the `runner.sh`, `supervisor.py` and `monitor.sh` they generate) no longer follow a link in the owner lifecycle state tail. Before each write they refuse a state path with a link, non-directory or `..` component, walked as spelled from the filesystem root (the macOS `/tmp`, `/var` and `/etc` aliases stay accepted), and a transition lock, lock database, generated script, public marker or current alias that exists as anything but a single-link regular file. Missing state directories are created owner-only, and a failed record publication removes only a temporary file it created. An explicit `GJC_SESSION_STATE_DIR` that goes through a link is now refused at startup, as the owner isolation protocol already refuses it. These are pathname checks, so a component swapped between the check and the write is still followed.
155
+
156
+ - Hashline edits now refuse auto-generated filenames before any section is written, using the same filename guard as patch, write, vim, and ast-edit.
157
+
158
+ - The herdr-core OSC 7501 status report no longer writes into `--mode json` or `-p` output when stdout is a PTY in an `hc` terminal; only interactive sessions report (#7525).
159
+ - The status retraction on exit now writes the whole sequence when a nonblocking terminal accepts only part of it, so herdr-core does not keep a stale status (#7525).
160
+
161
+ - The root command and its tmux relaunch no longer execute a repository dotenv `HERDR_BIN_PATH`. A shell-exported path is still used when the project does not declare that name, or declares a different static path. A dynamic project declaration, or the same static text, is not used; Herdr then resolves the binary from `PATH`.
162
+
163
+ - Image provider prose in a generate_image tool result is redacted, cut at the head and the tail, then wrapped as untrusted content.
164
+
165
+ - macOS machine identity lookup invokes `/usr/sbin/ioreg` directly instead of depending on it being present in `PATH`; a missing executable now reports identity as unavailable rather than leaking a spawn `ENOENT` error.
166
+
167
+ - The lspmux status probe passes the project-safe spawn environment, so a repository dotenv cannot deliver `BASH_ENV`, `LD_PRELOAD`, or `NODE_OPTIONS` to that child. A shell value that differs from the project's static declaration is kept. The same string, or a dynamic declaration whose source is ambiguous, is removed.
168
+
169
+ - Preserve the selected credential type in session handoff and branch summarization so OpenAI OAuth bearer tokens remain on the canonical endpoint rather than an API-key proxy.
170
+ - Resolve maintenance credential types from effective registry-owned authentication, including runtime and config API-key overrides, instead of stale stored-session history.
171
+
172
+ - A repository `.env` (or `.env.local`, `.env.development`) that declares only `GJC_MANAGED_OWNER_CHILD_TOKEN` no longer makes ordinary source-mode commands, including `--version` and `--help`, exit 75 with `managed_owner_admission_blocked`. Admission now treats that token as project configuration and removes it when its value is the static project declaration and no other owner context (state directory, session id, generation, run id, incarnation, launch baseline, transcript path, redact marker, tmux server key, tmux launch marker, or any predecessor key) is present, including empty values. Each project dotenv layer that exists must be a regular file of at most 64 KiB that can be read; otherwise the token is not treated as configuration. Owner context is checked before any file is read. A dynamic declaration, a padded or different value, an unreadable layer, or any owner context keeps the existing verification and its fail-closed refusal.
173
+
174
+ - Windows `session.spawn` selects the headless substrate before any managed launch, so a Broker spawn never reaches the managed Windows rejection (`gjc_tmux_managed_launch_platform_unsupported:win32`) and that rejection is never retried as headless. Unmanaged Windows launches are unchanged.
175
+
176
+ - `/memory clear` docs and comments now say what it does: it deletes every memory row and memory job in the shared local database and removes only the current project's memory directory. Project paths that differ only in `/`, `\`, or `:` versus `-` share that directory.
177
+
178
+ - `/model` profile selection while the agent is busy now closes the selector immediately and shows that the change is queued, instead of leaving the menu open until Esc while the activation waits for the agent to go idle. The notice also covers post-prompt work such as a pending background delivery, not only a streaming turn.
179
+
180
+ - A managed tmux launch (Broker child or root `--tmux` launch) whose session state tail, or session directory, is a symbolic link no longer creates an empty owner-only `owner-lifecycle` directory inside the link target before refusing the launch. Lifecycle root preparation now checks every existing path component with `lstat` first and refuses a link or non-directory before creating anything. The macOS system aliases `/tmp`, `/var` and `/etc` stay accepted, as in the native verification.
181
+
182
+ - On Linux and macOS, the remaining TypeScript writers of a tmux owner lifecycle root no longer follow a symbolic link that is already in its path. Generation publication, terminal observation, owner intents, scoped launch attempts, unexplained child-exit incidents and the harness resident owner launch now refuse, before writing anything, a lifecycle path with a link or non-directory component (the macOS `/tmp`, `/var` and `/etc` aliases stay accepted). The main lock database must be a regular file with a single link: a missing one is created exclusively with mode `0600` instead of being opened and chmodded by pathname, and an existing one keeps its mode. These are pathname checks, so a component swapped between the check and the write is still followed, and SQLite journal and WAL side files are not checked. Windows keeps its previous behavior apart from the exclusive create. An existing root's mode is left unchanged, so roots created by the `gjc-session` scripts keep working.
183
+ - `scripts/gjc-session/create.sh` names its default state directory through the physical workspace path, so a workspace reached through a symbolic link keeps working with the stricter lifecycle writers. An explicit `GJC_SESSION_STATE_DIR` is still used as given.
184
+
185
+ - Harness owner routing dials only the private session socket, and a live owner publishes that socket only after it holds the lease so a later command can reach it from another socket directory. Looking up the owner never creates or changes the permissions of the socket directory, and a symlinked or non-private socket directory is not trusted. The socket and its record are keyed by the real path of the harness state root, so a command reaches the owner whether it names that root through a symlink or not. On Windows the socket record is never written or trusted, so cross-directory routing there needs the same socket directory.
186
+
187
+ - Session startup with plugin MCP servers that declare a `timeout` now waits at most that declared timeout for MCP connections instead of the timeout plus the startup grace, so `createAgentSession` returns within the declared timeout plus the grace. Servers still connecting continue in the background and publish their tools when they connect.
188
+
189
+ - Keep ordinary JSON keys such as `constructor`, `toString`, and `__proto__` visible in MCP tool argument previews and JSON trees while still hiding reserved argument metadata.
190
+
191
+ - The Ultragoal ask guard no longer refuses the execution approval for a reviewed ralplan final written with the bundled skill's per-pass `--stage_n`. When every stage of a pass shares one `stage_n`, the current final is now the last index row, its opener is the nearest planner/revision row before it, and its Architect/Critic verdicts are the rows between the two. A final followed by any stage, or by a stage with a higher `stage_n`, is still refused.
192
+
193
+ - The recipe tool's runner detection, which runs at session start whenever the bash tool is enabled (`cargo metadata`, `just --dump`, `task --list-all`), now starts those programs from the same filtered environment as the bash tool. Previously, on source and npm installs (Bun dotenv autoload), a repository `.env` declaring `LD_PRELOAD` or another hook variable reached them as soon as a session opened in a checkout with a `Cargo.toml`, justfile, or Taskfile, before any prompt. Recipe execution itself already ran through the bash tool and was unaffected.
194
+
195
+ - The resume picker and GJC bundle settings strip terminal control sequences from session titles, first messages, and bundle or surface names before drawing them.
196
+
197
+ - Keep keyboard input and Ctrl+C working after the initial `--resume` session picker on Windows by finishing picker teardown on the next event loop turn before starting the chat TUI.
198
+
199
+ - Reloading the current session file with `switchSession` keeps an active goal (and plan) instead of detaching the mode controllers.
200
+
201
+ - Route delegated task approvals to the parent SDK external permission queue without inheriting terminal or filesystem capabilities; cancel pending descendant approvals when the parent policy or provider changes.
202
+ - Keep the active successor's permission provider installed when a retired broker runtime finishes teardown after session identity rotation.
203
+
204
+ - Windows Broker `session.spawn` (including custom trusted hosts) selects the identity-fenced headless substrate before any multiplexer probe, so it keeps starting instead of failing on a managed tmux/psmux child that cannot pass owner admission on Windows. Its headless proof is still flushed and exclusively created on Windows, but skips the directory flush Windows cannot perform, as lifecycle storage already does. The spawn authority journal, which every fresh spawn writes before launch, now skips that directory flush on Windows too (each row is still flushed), so a Windows spawn reaches its substrate launch instead of failing with `spawn_failed`.
205
+ - Closing a Broker-spawned headless child now asks the exact registration-pinned host to close itself over its authenticated endpoint, using the Broker lifecycle marker it was launched with, and waits for that exact process to exit before any substrate signal. On Windows the substrate signal is `TerminateProcess`, so a normal close no longer skips the host's endpoint removal and `session.dispose` cleanup; a host that refuses, is unreachable, or does not exit within its cleanup deadline (measured on monotonic time) is still closed through the exact substrate escalation. A spawned child whose exact process is already gone, including one that exited after a lost close acknowledgement, now closes without any signal instead of staying retained on every retry.
206
+
207
+ - Idle yield deliveries queued behind a failing startup barrier are drained instead of retained forever. Idle admission failures that no later admission can repair (readiness rejection or disposal) now drop their entries and release any owned-completion claims, while genuinely retryable admission failures still keep the queue intact.
208
+ - A streaming output chunk error is sticky: a later successful chunk no longer hides an error that already escaped, and a pending buffered tail is flushed or failed as one unit.
209
+
210
+ - The SDK broker's session-index rejection audit (`index-audit.jsonl`) no longer grows without bound or makes every cold SDK client parse all of it under the machine-global index lock. Long-lived readers now catch up on rows other processes appended instead of re-archiving them from a once-seeded view, and an audit past 4 MiB (and past twice the current rejections) rotates to `index-audit.jsonl.1` before it is read.
211
+
212
+ - A profile switch superseded mid-activation no longer records its transient DEFAULT model in the usage order, so the model the user picked while the switch was in flight stays the MRU head.
213
+
214
+ - Switching to a different session restores a saved plan through the plan controller, and drops that plan binding if plan tool activation fails.
215
+ - Switching to a different session drops the previous session's goal and restores the selected session's saved goal only when goal mode is enabled.
216
+ - A saved plan restore is rejected before any plan model or tool change while goal mode holds the mode gate, and a saved plan path outside the session `local:` root falls back to `local://PLAN.md`.
217
+
218
+ - A verified same-owner managed-transcript relocation no longer makes the title persistence fence treat the session as stale. Ownership is judged by the committed identity generation and session id instead of the physical session file, so a legitimate rename still persists, while a real owner change is still refused.
219
+ - A title publication abandoned mid-close is now surfaced by `close()`/`closeStrict()` instead of being swallowed, without latching the successor session.
220
+
221
+ - File slash command names that contain terminal controls are not loaded, and customize doctor text strips those controls from discovery lines, surface titles, and summary labels.
222
+
223
+ - The ssh tool now starts `ssh` (control master, host probe, and the remote command), `sshfs`, `mountpoint`, and the unmount helpers from the same filtered environment as the bash tool. Previously a repository `.env` declaring `LD_PRELOAD`, `NODE_OPTIONS`, `GIT_SSH_COMMAND` or another hook variable reached them. The control master, host probe and sshfs calls spread the process environment (into which the project `.env` is copied), so they leaked in the compiled binary too.
224
+
225
+ - Tool cards strip terminal controls from untrusted tool text, including a box background and a renderer subclass. Image and Markdown rows carry their own paint check, so graphics, file links, and copy markers stay on long cards. A row that a renderer wraps with extra text, such as a custom renderer or the eval cell frame, or that comes from a Markdown or Image render captured before the first tool card, is shown as filtered text: it keeps its display text and file links but loses graphics, copy markers, and other links. A bad paint check does not fail the card. Child objects keep their identity. Bash keeps a clean SIXEL block when passthrough is on, and edit cards still use the original path.
226
+
227
+ - Workflow gate answers decode to one validated shape (`{decision}` or `{selected:[label]}`) instead of a bare string, so a remote answer can no longer satisfy a handler that skipped the compiled gate schema.
228
+
229
+ - Workflow recovery prompts clip repo goal ids and cohort source hashes to 240 characters, escape those characters, and then fence the result. A character that fits the raw cap is escaped in full, so the fenced body can be longer than 240.
230
+
231
+ - Reading a YouTube URL now runs `yt-dlp` (metadata and subtitle calls) from the same filtered environment as the bash tool. Previously, on source and npm installs (Bun dotenv autoload), a repository `.env` declaring `LD_PRELOAD` or another hook variable reached `yt-dlp` whenever the agent read a YouTube link.
232
+
233
+ ### Documentation
234
+
235
+ - Added Windows DACL requirements to install documentation: supported principals (current user, SYSTEM, Administrators), inherited ACL handling, and remediation steps for custom or sandbox-inherited ACLs.
236
+
237
+ ### Fixes
238
+
239
+ - Report ACL failures that prevent update rollback, including privacy-bounded `gjc doctor` diagnostics and guidance to inspect uncertain activation before retrying.
240
+
241
+ - Windows `gjc update` failures on inherited ACL violations now report the offending principal and explain remediation steps. Instead of a bare `acl_present` error, the user sees actionable guidance: "Remove '<PrincipalName>' ACE from %LOCALAPPDATA%\gjc (inherited from parent; disable inheritance with `icacls '<dir>' /inheritance:d` first)" (issue #7469).
242
+
5
243
  ## [0.19.2] - 2026-10-29
6
244
 
7
245
  ## [0.19.1] - 2026-10-28
@@ -131,11 +131,52 @@ export interface SubagentLiveHandle {
131
131
  fromAgentId?: string;
132
132
  }): Promise<void>;
133
133
  }
134
- /**
135
- * Canonical, stable-id-keyed record for a subagent. Survives `AsyncJob`
136
- * eviction so resume stays addressable by subagent id, and is the single source
137
- * of truth for control-plane status and identity.
138
- */
134
+ /** Detached compare-and-set target; never carries execution authority. */
135
+ export interface SubagentControlTarget {
136
+ id: string;
137
+ generation: string;
138
+ }
139
+ export interface SubagentControlCapabilities {
140
+ cancel: boolean;
141
+ pause: boolean;
142
+ resume: boolean;
143
+ }
144
+ export interface SubagentControlSnapshot {
145
+ id: string;
146
+ status: SubagentLifecycle;
147
+ currentJobId: string | null;
148
+ currentJobGeneration?: string;
149
+ terminalGeneration?: string;
150
+ requestedModel?: string;
151
+ effectiveModel?: string;
152
+ target: SubagentControlTarget;
153
+ capabilities: SubagentControlCapabilities;
154
+ }
155
+ export type SubagentControlErrorCode = "disposed" | "not_found" | "stale_generation" | "already_terminal" | "no_live_job" | "control_in_progress" | "not_running" | "no_live_handle" | "already_running" | "already_queued" | "context_unavailable" | "no_runner" | "resume_failed" | "owner_shutdown_in_progress";
156
+ export declare class SubagentControlError extends Error {
157
+ readonly code: SubagentControlErrorCode;
158
+ constructor(code: SubagentControlErrorCode);
159
+ }
160
+ export interface SubagentControlSuccess {
161
+ ok: true;
162
+ status: SubagentLifecycle;
163
+ jobId?: string;
164
+ queued?: boolean;
165
+ reason?: never;
166
+ }
167
+ export type SubagentControlResult = SubagentControlSuccess | {
168
+ ok: false;
169
+ status?: SubagentLifecycle;
170
+ jobId?: never;
171
+ queued?: never;
172
+ reason: SubagentControlErrorCode;
173
+ };
174
+ interface SubagentControlExpectation {
175
+ ownerId: string;
176
+ scope: string;
177
+ generation: string;
178
+ }
179
+ /** Canonical stable-id record, retained across pause/resume and job eviction. */
139
180
  export interface SubagentRecord {
140
181
  subagentId: string;
141
182
  ownerId?: string;
@@ -402,6 +443,12 @@ export declare class AsyncJobManager {
402
443
  found: boolean;
403
444
  status?: AsyncJob["status"];
404
445
  };
446
+ /** Captured once by a host facade; endpoint rebinds permanently invalidate it. */
447
+ getSubagentControlScope(): string;
448
+ /** Scalar-only projection; no handles, descriptors, session files, or runner authority. */
449
+ getSubagentControlSnapshot(ownerId: string, scope: string): SubagentControlSnapshot[];
450
+ /** Owner is host-captured. The final CAS is performed inside the canonical lifecycle operation. */
451
+ controlOwnedSubagent(ownerId: string, scope: string, target: SubagentControlTarget, action: "cancel" | "pause" | "resume", message?: string): SubagentControlResult;
405
452
  /** Register or replace the canonical record for a subagent. */
406
453
  registerSubagentRecord(record: SubagentRecord): void;
407
454
  /**
@@ -453,25 +500,15 @@ export declare class AsyncJobManager {
453
500
  drainResumeQueue?: boolean;
454
501
  }): void;
455
502
  /** Request a graceful safe-boundary pause of a running subagent. */
456
- pauseSubagent(subagentId: string, filter?: AsyncJobFilter): {
457
- ok: boolean;
458
- status?: SubagentLifecycle;
459
- reason?: string;
460
- };
503
+ pauseSubagent(subagentId: string, filter?: AsyncJobFilter, expected?: SubagentControlExpectation): SubagentControlResult;
461
504
  /**
462
505
  * Resume a non-running subagent from retained context: an owner-compatible
463
506
  * descriptor or a legacy session file. Workflow routing keeps `not_found`,
464
507
  * `context_unavailable`, `no_runner`, and `resume_failed` distinct.
465
508
  */
466
- resumeSubagent(subagentId: string, filter?: AsyncJobFilter, message?: string, resumeToolCallId?: string): {
467
- ok: boolean;
468
- status?: SubagentLifecycle;
469
- jobId?: string;
470
- queued?: boolean;
471
- reason?: string;
472
- };
509
+ resumeSubagent(subagentId: string, filter?: AsyncJobFilter, message?: string, resumeToolCallId?: string, expected?: SubagentControlExpectation): SubagentControlResult;
473
510
  /** Cancel a subagent by stable id across running/paused/queued states (keeps the session file). */
474
- cancelSubagent(subagentId: string, filter?: AsyncJobFilter): boolean;
511
+ cancelSubagent(subagentId: string, filter?: AsyncJobFilter, expected?: SubagentControlExpectation): boolean;
475
512
  getJob(id: string): AsyncJob | undefined;
476
513
  /**
477
514
  * The EXECUTION promise of the job record whose generation matches the
@@ -597,3 +634,4 @@ export declare class AsyncJobManager {
597
634
  awaitRetainedDisposalCompletion(): Promise<void>;
598
635
  isDeliverySuppressed(jobId: string, generation?: string): boolean;
599
636
  }
637
+ export {};
@@ -0,0 +1,9 @@
1
+ /** Per-command bearer-token file with exclusive creation and a race-safe ensure path. */
2
+ export interface AuthTokenFile {
3
+ readonly path: string;
4
+ read(): Promise<string | null>;
5
+ write(token: string): Promise<void>;
6
+ generate(): string;
7
+ ensure(): Promise<string>;
8
+ }
9
+ export declare function createAuthTokenFile(fileName: string, label: string): AuthTokenFile;
@@ -61,6 +61,7 @@ export type InstallRepairState = "verified" | "not_needed" | "pending_activation
61
61
  export interface InstallRepairResult {
62
62
  readonly state: InstallRepairState;
63
63
  readonly reason?: string;
64
+ readonly diagnostic?: string;
64
65
  readonly recordPath?: string;
65
66
  readonly sideEffectStarted: boolean;
66
67
  /** Native Windows status returned by exact replacement. */
@@ -90,6 +90,7 @@ export interface DoctorRepair {
90
90
  readonly state: RepairState;
91
91
  readonly reasonCode?: string;
92
92
  readonly sideEffectStarted?: boolean;
93
+ readonly diagnostic?: string;
93
94
  readonly outcome?: {
94
95
  readonly mutationVerified: boolean;
95
96
  readonly desiredStartupStateAchieved?: boolean;
@@ -11,7 +11,14 @@
11
11
  * retires the old target to a retained backup name instead of deleting it.
12
12
  * There is no unlink/rename-based rollback path in this module.
13
13
  */
14
- import { type NativeExactFileIdentity } from "@gajae-code/natives";
14
+ import { type NativeExactFileIdentity, type NativeExactUnlinkResult } from "@gajae-code/natives";
15
+ export declare class InstallationAclPresentError extends Error {
16
+ readonly targetPath: string;
17
+ readonly sourcePath: string;
18
+ readonly detail: Pick<NativeExactUnlinkResult, "aclFailurePrincipal" | "aclFailureInherited" | "aclFailureSide">;
19
+ readonly code = "acl_present";
20
+ constructor(targetPath: string, sourcePath: string, detail: Pick<NativeExactUnlinkResult, "aclFailurePrincipal" | "aclFailureInherited" | "aclFailureSide">, retryAfterRemediation?: boolean);
21
+ }
15
22
  export type ActivationPhase = "staged" | "published" | "verified" | "pending_activation" | "rolled_back" | "uncertain";
16
23
  /** Serialized exact regular-file identity. BigInt fields are decimal strings so the record stays plain JSON. */
17
24
  export interface FileIdentity {
@@ -136,6 +143,8 @@ export interface ReconcileResult {
136
143
  readonly reason?: string;
137
144
  /** Present only for a pre-mutation Windows exact-replacement failure. */
138
145
  readonly windowsErrorCode?: string;
146
+ readonly aclFailurePrincipal?: string;
147
+ readonly aclFailureInherited?: boolean;
139
148
  readonly detachedPath?: string;
140
149
  readonly retainedSuccessorPath?: string;
141
150
  readonly retainedPlaceholderPath?: string;
@@ -34,6 +34,14 @@ export declare const MACOS_MALLOC_ENV_VARS: readonly ["MallocStackLogging", "Mal
34
34
  export declare const MALLOC_ENV_REEXEC_GUARD = "GJC_MALLOC_ENV_REEXEC";
35
35
  /** True when at least one macOS malloc-stack-logging var is present in `env`. */
36
36
  export declare function hasMacOSMallocEnv(env: Record<string, string | undefined>): boolean;
37
+ /**
38
+ * `env(1)` unset operands for a pane command that must exec its process directly.
39
+ *
40
+ * A managed tmux pane process must stay the exact supervisor PID that managed close
41
+ * pins. The in-process guard re-execs through a child, which would put the real
42
+ * supervisor below the pane PID, so the launcher scrubs these variables instead.
43
+ */
44
+ export declare function macOSMallocEnvUnsetArgs(): string[];
37
45
  /**
38
46
  * True iff we must re-exec to escape a contaminated macOS startup snapshot:
39
47
  * darwin, not already inside the scrubbed re-exec, and at least one malloc var
@@ -10,7 +10,7 @@ import { type UpdateChannel } from "../config/update-channel";
10
10
  import { type NotificationProvider } from "../sdk/bus/config";
11
11
  import type { TelemetryDetails, TelemetryEventName } from "../telemetry";
12
12
  import { type GithubReleaseLookupOptions } from "./github-release";
13
- import { type DirectoryIdentity, type FileIdentity, type ReconcileResult } from "./install-activation";
13
+ import { type DirectoryIdentity, type FileIdentity, InstallationAclPresentError, type ReconcileResult } from "./install-activation";
14
14
  import { offerMacosCommunityApp } from "./macos-community-app";
15
15
  export interface UpdateCommandOptions {
16
16
  force: boolean;
@@ -159,12 +159,15 @@ export declare function verifyMigrationTargetAdapterForTest(options: {
159
159
  export declare function formatBinaryDownloadFailureMessageForTest(binaryName: string, url: string, status: string | number, platform?: NodeJS.Platform, registryNote?: string): string;
160
160
  export declare function buildReleaseBinaryUrlForTest(version: string, platform?: NodeJS.Platform, arch?: string): string;
161
161
  export declare function formatManualUpdateInstructionsForTest(platform?: NodeJS.Platform): string;
162
+ export declare class InstallationRollbackAclPresentError extends InstallationAclPresentError {
163
+ }
162
164
  export declare function formatVerificationFailureForTest(result: InstalledVersionVerification, expectedVersion: string): string;
163
165
  export declare function recoverWindowsUpdateJournal(journalPath: string): Promise<void>;
164
166
  /**
165
167
  * Atomically replace the installed binary and roll back if version verification fails.
166
168
  */
167
169
  export declare function replaceBinaryForUpdate(options: BinaryReplacementOptions): Promise<InstalledVersionVerification>;
170
+ export declare function formatInstallationRollbackAclError(error: unknown): string | undefined;
168
171
  export declare function runPackageManagerUpdateForTest(options: PackageManagerUpdateOptions): Promise<InstalledVersionVerification>;
169
172
  export declare function fsyncFileForTest(filePath: string): Promise<void>;
170
173
  /** Production adapter used by doctor restore: official release origin, checksum manifest, and runtime smoke. */
@@ -53,6 +53,8 @@ export interface CasReceipt {
53
53
  export interface AtomicYamlUpdate<T> {
54
54
  apply(current: Record<string, unknown>): T | Promise<T>;
55
55
  shouldWrite?(result: T): boolean;
56
+ /** Explicit mutation intent, including same-value writes; omitted means whole-document ownership. */
57
+ mutationPaths?(): readonly string[];
56
58
  committed?(current: Record<string, unknown>, result: T): void | Promise<void>;
57
59
  }
58
60
  export interface AtomicYamlPatchOptions {
@@ -68,6 +70,8 @@ export interface AtomicYamlPatchOptions {
68
70
  platform?: NodeJS.Platform;
69
71
  /** Called under the config lock before patches are applied. */
70
72
  validateRoot?: (root: unknown, patches: readonly AtomicYamlPatch[]) => void | Promise<void>;
73
+ /** Additional owner revisions checked under the config lock before CAS restoration. */
74
+ restoreConflicts?: () => readonly string[];
71
75
  /** Called under the config lock after a successful CAS restore. */
72
76
  onRestored?: (patches: readonly AtomicYamlPatch[]) => void | Promise<void>;
73
77
  }
@@ -95,6 +99,16 @@ export declare class AtomicYamlRetargetError extends Error {
95
99
  readonly code = "ATOMIC_YAML_RETARGETED";
96
100
  constructor(lexicalPath: string, expectedCanonicalPath: string, actualCanonicalPath: string);
97
101
  }
102
+ /** Whether every segment is a non-empty, safe property name. */
103
+ export declare function isSafeAtomicYamlPath(segments: readonly string[]): boolean;
104
+ /** Ancestor/descendant paths cannot share one independently restorable receipt. */
105
+ export declare function assertNonOverlappingAtomicYamlPatches(patches: readonly {
106
+ path: string;
107
+ }[]): void;
108
+ /** Reject set paths that would replace a non-record ancestor outside the receipt's scope.
109
+ * Missing ancestors may be created; unset paths do not replace ancestors.
110
+ */
111
+ export declare function assertAtomicYamlSetAncestors(value: Record<string, unknown>, segments: readonly string[]): void;
98
112
  /** Set a dotted YAML path, creating object intermediates as needed. */
99
113
  export declare function setByPath(value: Record<string, unknown>, segments: readonly string[], nextValue: unknown): void;
100
114
  /** Delete a dotted YAML path without disturbing sibling keys or parent objects. */
@@ -140,10 +154,21 @@ export interface AtomicYamlConfigTransaction {
140
154
  * callback runs, so no migration action can execute against a malformed target.
141
155
  */
142
156
  export declare function withAtomicYamlConfigTransaction<T>(configPath: string, operation: (transaction: AtomicYamlConfigTransaction) => Promise<T>): Promise<T>;
157
+ /**
158
+ * Settings may reserve a deferred save without inheriting the caller's lease.
159
+ * Reject a nested flush against an actively held file, even across independent
160
+ * roots: waiting for that save can otherwise form a cycle. A reservation alone
161
+ * is not a holder, so a nested flush of an idle different file remains valid.
162
+ * This process-local policy cannot rule out cross-process waits.
163
+ */
164
+ export declare function assertSafeAtomicYamlSettingsFlush(configPath: string): void;
143
165
  /**
144
166
  * Reserve a FIFO operation for a config file immediately. The patch supplier runs
145
167
  * only when this operation reaches the front of the in-process queue, which lets
146
- * Settings debounce/coalesce inside its already-reserved causal slot.
168
+ * Settings debounce/coalesce inside its already-reserved causal slot. Nested
169
+ * callers holding an active lease may acquire an idle different file, but cannot
170
+ * queue behind a busy file. This conservative rule also applies to detached
171
+ * callbacks that inherited the lease, even when nobody awaits their work.
147
172
  */
148
173
  export declare function enqueueAtomicYamlOperation<T>(configPath: string, operation: (canonicalConfigPath: string, lexicalConfigPath: string) => Promise<T>): Promise<T>;
149
174
  /**
@@ -156,6 +181,14 @@ export declare function reserveAtomicYamlPatchSlot(configPath: string, patches:
156
181
  * The supplier runs only when its operation reaches the front of the queue.
157
182
  */
158
183
  export declare function reserveAtomicYamlUpdateSlot<T>(configPath: string, update: () => Promise<AtomicYamlUpdate<T>> | AtomicYamlUpdate<T>, options?: AtomicYamlPatchOptions): Promise<T>;
184
+ /**
185
+ * Reserve the Settings debounce slot without inheriting the caller's queue lease.
186
+ * This is fire-and-forget admission: completion is delivered to Settings rather
187
+ * than returned to the caller that may currently hold the same file's queue.
188
+ * The update itself still runs under a fresh queue lease and lock.
189
+ * @internal
190
+ */
191
+ export declare function reserveDeferredSettingsSave<T>(configPath: string, update: () => Promise<AtomicYamlUpdate<T>> | AtomicYamlUpdate<T>, completion: Pick<PromiseWithResolvers<T>, "resolve" | "reject">): void;
159
192
  /**
160
193
  * Apply tagged patches through the one per-file in-process queue and the shared
161
194
  * cross-process file lock. Success means the temp file was fsynced and renamed.