@gajae-code/coding-agent 0.11.11 → 0.12.1

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 (344) hide show
  1. package/CHANGELOG.md +131 -4
  2. package/dist/types/async/job-manager.d.ts +17 -3
  3. package/dist/types/cli/read-cli.d.ts +1 -0
  4. package/dist/types/commands/deep-interview.d.ts +9 -0
  5. package/dist/types/commands/harness.d.ts +22 -0
  6. package/dist/types/commands/read.d.ts +6 -0
  7. package/dist/types/config/model-registry.d.ts +4 -0
  8. package/dist/types/config/provider-auth-health.d.ts +14 -0
  9. package/dist/types/config/provider-ranking.d.ts +59 -0
  10. package/dist/types/config/settings-schema.d.ts +83 -1
  11. package/dist/types/config/settings.d.ts +2 -0
  12. package/dist/types/exa/mcp-client.d.ts +10 -1
  13. package/dist/types/exec/bash-executor.d.ts +45 -12
  14. package/dist/types/extensibility/extensions/types.d.ts +38 -4
  15. package/dist/types/extensibility/gjc-plugins/index.d.ts +12 -2
  16. package/dist/types/extensibility/gjc-plugins/installer.d.ts +63 -7
  17. package/dist/types/extensibility/gjc-plugins/lifecycle-reconciliation.d.ts +55 -0
  18. package/dist/types/extensibility/gjc-plugins/lifecycle.d.ts +64 -0
  19. package/dist/types/extensibility/gjc-plugins/runtime-quarantine.d.ts +67 -0
  20. package/dist/types/extensibility/gjc-plugins/session-validation.d.ts +3 -1
  21. package/dist/types/extensibility/gjc-plugins/types.d.ts +124 -0
  22. package/dist/types/extensibility/shared-events.d.ts +6 -0
  23. package/dist/types/gjc-runtime/deep-interview-ambiguity.d.ts +5 -12
  24. package/dist/types/gjc-runtime/deep-interview-recorder.d.ts +17 -32
  25. package/dist/types/gjc-runtime/deep-interview-stage.d.ts +37 -0
  26. package/dist/types/gjc-runtime/deep-interview-state.d.ts +4 -135
  27. package/dist/types/gjc-runtime/gc-runtime.d.ts +1 -1
  28. package/dist/types/gjc-runtime/launch-tmux.d.ts +1 -0
  29. package/dist/types/gjc-runtime/memory-guard-owner-claims.d.ts +47 -0
  30. package/dist/types/gjc-runtime/ralplan-runtime.d.ts +70 -1
  31. package/dist/types/gjc-runtime/state-writer.d.ts +5 -46
  32. package/dist/types/gjc-runtime/team-launch.d.ts +1 -1
  33. package/dist/types/gjc-runtime/team-runtime.d.ts +27 -1
  34. package/dist/types/gjc-runtime/team-store.d.ts +12 -0
  35. package/dist/types/gjc-runtime/team-worker-heartbeat.d.ts +43 -0
  36. package/dist/types/gjc-runtime/team-worker-memory-guard.d.ts +92 -0
  37. package/dist/types/gjc-runtime/tmux-owner-isolation.d.ts +17 -0
  38. package/dist/types/gjc-runtime/ultragoal-receipt-freshness.d.ts +8 -0
  39. package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +31 -80
  40. package/dist/types/gjc-runtime/workflow-manifest.d.ts +3 -5
  41. package/dist/types/internal-urls/local-root-gc.d.ts +2 -0
  42. package/dist/types/main.d.ts +1 -1
  43. package/dist/types/memories/index.d.ts +2 -0
  44. package/dist/types/modes/acp/acp-agent.d.ts +10 -19
  45. package/dist/types/modes/components/assistant-message.d.ts +3 -1
  46. package/dist/types/modes/components/gjc-bundle-settings.d.ts +34 -0
  47. package/dist/types/modes/components/irc-sidebar.d.ts +41 -0
  48. package/dist/types/modes/components/notifications-settings-editor.d.ts +1 -0
  49. package/dist/types/modes/components/read-tool-group.d.ts +4 -4
  50. package/dist/types/modes/components/session-observer-overlay.d.ts +22 -0
  51. package/dist/types/modes/components/settings-selector.d.ts +11 -0
  52. package/dist/types/modes/components/status-line/gh.d.ts +5 -0
  53. package/dist/types/modes/components/tool-execution.d.ts +8 -0
  54. package/dist/types/modes/components/transcript-viewer-overlay.d.ts +18 -1
  55. package/dist/types/modes/controllers/event-controller.d.ts +3 -0
  56. package/dist/types/modes/interactive-mode.d.ts +2 -0
  57. package/dist/types/modes/irc-observation-ledger.d.ts +17 -1
  58. package/dist/types/modes/types.d.ts +2 -0
  59. package/dist/types/modes/utils/ui-helpers.d.ts +16 -0
  60. package/dist/types/reminders/star-reminder.d.ts +3 -13
  61. package/dist/types/runtime-mcp/manager.d.ts +1 -0
  62. package/dist/types/runtime-mcp/smithery-auth.d.ts +5 -0
  63. package/dist/types/sdk/acp/adapter.d.ts +3 -1
  64. package/dist/types/sdk/broker/lifecycle.d.ts +5 -0
  65. package/dist/types/sdk/broker/transport.d.ts +2 -0
  66. package/dist/types/sdk/bus/attachment-registry.d.ts +1 -0
  67. package/dist/types/sdk/bus/chat-daemon-control.d.ts +4 -1
  68. package/dist/types/sdk/bus/config.d.ts +6 -2
  69. package/dist/types/sdk/bus/control-drain-lease.d.ts +52 -0
  70. package/dist/types/sdk/bus/index.d.ts +44 -1
  71. package/dist/types/sdk/bus/kind-aware-reconciliation.d.ts +44 -0
  72. package/dist/types/sdk/bus/lifecycle-control-runtime.d.ts +4 -0
  73. package/dist/types/sdk/bus/prompt-reconciliation.d.ts +2 -1
  74. package/dist/types/sdk/bus/reconciliation-store.d.ts +69 -0
  75. package/dist/types/sdk/bus/rich-draft.d.ts +1 -0
  76. package/dist/types/sdk/bus/rich-render.d.ts +2 -0
  77. package/dist/types/sdk/bus/telegram-adoption-intent.d.ts +165 -0
  78. package/dist/types/sdk/bus/telegram-cli.d.ts +12 -0
  79. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +11 -4
  80. package/dist/types/sdk/bus/telegram-daemon.d.ts +25 -1
  81. package/dist/types/sdk/bus/telegram-reference.d.ts +11 -1
  82. package/dist/types/sdk/bus/threaded-render.d.ts +3 -2
  83. package/dist/types/sdk/bus/topic-registry.d.ts +11 -1
  84. package/dist/types/sdk/host/control/operations.d.ts +1 -1
  85. package/dist/types/sdk/host/host.d.ts +2 -0
  86. package/dist/types/sdk/host/query/handlers.d.ts +5 -0
  87. package/dist/types/sdk/host/query/revision-store.d.ts +2 -0
  88. package/dist/types/sdk/host/reverse-leases.d.ts +1 -1
  89. package/dist/types/sdk/prompt-status.d.ts +23 -3
  90. package/dist/types/sdk/session.d.ts +6 -0
  91. package/dist/types/session/agent-session.d.ts +82 -12
  92. package/dist/types/session/artifacts.d.ts +8 -0
  93. package/dist/types/session/blob-store.d.ts +57 -4
  94. package/dist/types/session/internal/managed-session-storage.d.ts +8 -1
  95. package/dist/types/session/memory-guard-checkpoint-participant.d.ts +69 -0
  96. package/dist/types/session/session-manager.d.ts +48 -19
  97. package/dist/types/session/session-storage.d.ts +4 -0
  98. package/dist/types/session/streaming-output.d.ts +96 -12
  99. package/dist/types/setup/credential-import.d.ts +12 -0
  100. package/dist/types/skill-state/active-state.d.ts +12 -4
  101. package/dist/types/skill-state/workflow-hud.d.ts +9 -0
  102. package/dist/types/task/executor.d.ts +3 -2
  103. package/dist/types/task/index.d.ts +3 -1
  104. package/dist/types/task/provider-retry-status.d.ts +8 -0
  105. package/dist/types/task/receipt.d.ts +7 -1
  106. package/dist/types/task/types.d.ts +23 -0
  107. package/dist/types/tools/ask-answer-registry.d.ts +2 -2
  108. package/dist/types/tools/bash-interactive.d.ts +4 -1
  109. package/dist/types/tools/bash.d.ts +3 -1
  110. package/dist/types/tools/browser/launch.d.ts +7 -0
  111. package/dist/types/tools/fetch.d.ts +17 -1
  112. package/dist/types/tools/image-gen.d.ts +4 -0
  113. package/dist/types/tools/index.d.ts +4 -0
  114. package/dist/types/tools/output-meta.d.ts +44 -3
  115. package/dist/types/tools/path-utils.d.ts +1 -0
  116. package/dist/types/tools/read-internals.d.ts +12 -0
  117. package/dist/types/tools/read.d.ts +45 -7
  118. package/dist/types/tools/resource-gc.d.ts +4 -0
  119. package/dist/types/tools/review.d.ts +5 -7
  120. package/dist/types/tools/subagent.d.ts +2 -0
  121. package/dist/types/tools/tool-result.d.ts +7 -1
  122. package/dist/types/utils/gh.d.ts +13 -0
  123. package/dist/types/utils/image-resize.d.ts +1 -0
  124. package/dist/types/web/search/providers/kimi.d.ts +2 -0
  125. package/dist/types/web/search/providers/searxng.d.ts +7 -0
  126. package/dist/types/web/search/providers/xai.d.ts +2 -0
  127. package/package.json +11 -13
  128. package/scripts/acp-conformance-agent.ts +218 -0
  129. package/scripts/benchmark-sticky-viewport-pr1.ts +239 -0
  130. package/scripts/capture-gjc-bundle-settings.ts +306 -0
  131. package/scripts/capture-sticky-viewport-showcase.ts +292 -0
  132. package/scripts/generate-sdk-operation-inventory.ts +5 -0
  133. package/scripts/resident-memory-bench.ts +1341 -0
  134. package/scripts/run-acp-conformance.ts +285 -0
  135. package/scripts/verify-gjc-sdk-canonicalization.ts +122 -18
  136. package/scripts/verify-sticky-viewport-showcase.ts +611 -0
  137. package/src/async/job-manager.ts +78 -20
  138. package/src/capability/index.ts +8 -0
  139. package/src/cli/fast-help.ts +1 -1
  140. package/src/cli/plugin-cli.ts +176 -18
  141. package/src/cli/read-cli.ts +2 -1
  142. package/src/cli.ts +1 -0
  143. package/src/commands/deep-interview.ts +29 -9
  144. package/src/commands/harness.ts +35 -12
  145. package/src/commands/read.ts +11 -2
  146. package/src/commands/team.ts +20 -2
  147. package/src/config/file-lock.ts +11 -2
  148. package/src/config/model-registry.ts +21 -2
  149. package/src/config/provider-auth-health.ts +42 -0
  150. package/src/config/provider-ranking.ts +119 -0
  151. package/src/config/settings-schema.ts +74 -1
  152. package/src/config/settings.ts +246 -108
  153. package/src/coordinator-mcp/question-gate-codec.ts +1 -1
  154. package/src/coordinator-mcp/server.ts +5 -12
  155. package/src/defaults/gjc/skills/deep-interview/SKILL.md +230 -82
  156. package/src/defaults/gjc/skills/ralplan/SKILL.md +77 -41
  157. package/src/defaults/gjc/skills/team/SKILL.md +3 -1
  158. package/src/defaults/gjc/skills/ultragoal/SKILL.md +62 -39
  159. package/src/defaults/gjc/skills/ultragoal/validation-batch-contracts.md +12 -0
  160. package/src/defaults/gjc-defaults.ts +4 -4
  161. package/src/eval/py/executor.ts +7 -2
  162. package/src/exa/mcp-client.ts +12 -3
  163. package/src/exec/bash-executor.ts +144 -27
  164. package/src/extensibility/extensions/runner.ts +15 -0
  165. package/src/extensibility/extensions/types.ts +46 -5
  166. package/src/extensibility/gjc-plugins/constrained-hooks.ts +8 -2
  167. package/src/extensibility/gjc-plugins/index.ts +19 -2
  168. package/src/extensibility/gjc-plugins/installer.ts +189 -50
  169. package/src/extensibility/gjc-plugins/lifecycle-reconciliation.ts +199 -0
  170. package/src/extensibility/gjc-plugins/lifecycle.ts +626 -0
  171. package/src/extensibility/gjc-plugins/observability.ts +3 -3
  172. package/src/extensibility/gjc-plugins/prompt-appendix.ts +5 -1
  173. package/src/extensibility/gjc-plugins/runtime-adapters.ts +12 -2
  174. package/src/extensibility/gjc-plugins/runtime-quarantine.ts +121 -0
  175. package/src/extensibility/gjc-plugins/schema.ts +84 -12
  176. package/src/extensibility/gjc-plugins/session-validation.ts +9 -3
  177. package/src/extensibility/gjc-plugins/types.ts +141 -0
  178. package/src/extensibility/gjc-plugins/validation.ts +9 -0
  179. package/src/extensibility/shared-events.ts +5 -0
  180. package/src/gjc-runtime/deep-interview-ambiguity.ts +47 -82
  181. package/src/gjc-runtime/deep-interview-recorder.ts +227 -310
  182. package/src/gjc-runtime/deep-interview-runtime.ts +109 -270
  183. package/src/gjc-runtime/deep-interview-stage.ts +1016 -0
  184. package/src/gjc-runtime/deep-interview-state.ts +12 -943
  185. package/src/gjc-runtime/gc-render.ts +1 -0
  186. package/src/gjc-runtime/gc-runtime.ts +11 -1
  187. package/src/gjc-runtime/launch-tmux.ts +25 -6
  188. package/src/gjc-runtime/managed-owner-admission.ts +1 -1
  189. package/src/gjc-runtime/memory-guard-owner-claims.ts +389 -0
  190. package/src/gjc-runtime/ralplan-runtime.ts +1149 -98
  191. package/src/gjc-runtime/state-runtime.ts +2 -1
  192. package/src/gjc-runtime/state-writer.ts +70 -222
  193. package/src/gjc-runtime/team-launch.ts +42 -5
  194. package/src/gjc-runtime/team-runtime.ts +1085 -40
  195. package/src/gjc-runtime/team-store.ts +32 -0
  196. package/src/gjc-runtime/team-worker-heartbeat.ts +149 -0
  197. package/src/gjc-runtime/team-worker-memory-guard.ts +363 -0
  198. package/src/gjc-runtime/team-workers.ts +1 -0
  199. package/src/gjc-runtime/tmux-owner-isolation.ts +28 -0
  200. package/src/gjc-runtime/tmux-sessions.ts +58 -13
  201. package/src/gjc-runtime/ultragoal-receipt-freshness.ts +20 -0
  202. package/src/gjc-runtime/ultragoal-runtime.ts +414 -618
  203. package/src/gjc-runtime/workflow-manifest.generated.json +105 -449
  204. package/src/gjc-runtime/workflow-manifest.ts +38 -247
  205. package/src/hooks/native-skill-hook.ts +17 -4
  206. package/src/hooks/skill-state.ts +1 -23
  207. package/src/internal-urls/docs-index.generated.ts +21 -22
  208. package/src/internal-urls/local-root-gc.ts +127 -0
  209. package/src/main.ts +9 -5
  210. package/src/memories/index.ts +10 -0
  211. package/src/modes/DESIGN.md +98 -0
  212. package/src/modes/acp/acp-agent.ts +339 -191
  213. package/src/modes/acp/acp-event-mapper.ts +14 -7
  214. package/src/modes/acp/acp-mode.ts +39 -3
  215. package/src/modes/components/assistant-message.ts +123 -22
  216. package/src/modes/components/gjc-bundle-settings.ts +508 -0
  217. package/src/modes/components/irc-sidebar.ts +176 -62
  218. package/src/modes/components/model-selector.ts +61 -4
  219. package/src/modes/components/notifications-settings-editor.ts +12 -1
  220. package/src/modes/components/oauth-selector.ts +96 -28
  221. package/src/modes/components/read-tool-group.ts +82 -14
  222. package/src/modes/components/session-observer-overlay.ts +457 -83
  223. package/src/modes/components/settings-selector.ts +116 -23
  224. package/src/modes/components/status-line/gh.ts +16 -0
  225. package/src/modes/components/tool-execution.ts +138 -27
  226. package/src/modes/components/tool-status-header.ts +3 -14
  227. package/src/modes/components/transcript-viewer-overlay.ts +99 -24
  228. package/src/modes/controllers/command-controller.ts +4 -0
  229. package/src/modes/controllers/event-controller.ts +109 -27
  230. package/src/modes/controllers/extension-ui-controller.ts +26 -2
  231. package/src/modes/controllers/input-controller.ts +18 -3
  232. package/src/modes/controllers/selector-controller.ts +127 -36
  233. package/src/modes/interactive-mode.ts +62 -3
  234. package/src/modes/irc-observation-ledger.ts +71 -15
  235. package/src/modes/runtime-init.ts +22 -2
  236. package/src/modes/types.ts +2 -0
  237. package/src/modes/utils/ui-helpers.ts +94 -1
  238. package/src/prompts/agent-fragments/ralplan-persistence.md +4 -3
  239. package/src/prompts/agents/architect.md +9 -1
  240. package/src/prompts/agents/critic.md +9 -0
  241. package/src/prompts/system/eager-todo.md +8 -4
  242. package/src/prompts/system/system-prompt.md +11 -5
  243. package/src/prompts/tools/bash.md +5 -5
  244. package/src/prompts/tools/read.md +4 -2
  245. package/src/prompts/tools/search-tool-bm25.md +5 -0
  246. package/src/prompts/tools/task.md +1 -1
  247. package/src/reminders/star-reminder.ts +4 -42
  248. package/src/runtime-mcp/manager.ts +19 -4
  249. package/src/runtime-mcp/smithery-auth.ts +17 -2
  250. package/src/runtime-mcp/smithery-connect.ts +11 -1
  251. package/src/sdk/acp/adapter.ts +22 -6
  252. package/src/sdk/broker/lifecycle.ts +25 -6
  253. package/src/sdk/broker/transport.ts +35 -3
  254. package/src/sdk/bus/attachment-registry.ts +5 -1
  255. package/src/sdk/bus/chat-daemon-cli.ts +4 -39
  256. package/src/sdk/bus/chat-daemon-control.ts +6 -3
  257. package/src/sdk/bus/config.ts +18 -2
  258. package/src/sdk/bus/control-drain-lease.ts +104 -0
  259. package/src/sdk/bus/index.ts +984 -146
  260. package/src/sdk/bus/kind-aware-reconciliation.ts +317 -0
  261. package/src/sdk/bus/lifecycle-commands.ts +4 -1
  262. package/src/sdk/bus/lifecycle-control-runtime.ts +403 -88
  263. package/src/sdk/bus/prompt-reconciliation.ts +2 -1
  264. package/src/sdk/bus/reconciliation-store.ts +303 -0
  265. package/src/sdk/bus/rich-draft.ts +1 -1
  266. package/src/sdk/bus/rich-render.ts +2 -2
  267. package/src/sdk/bus/telegram-adoption-intent.ts +574 -0
  268. package/src/sdk/bus/telegram-cli.ts +33 -8
  269. package/src/sdk/bus/telegram-daemon-cli.ts +1 -0
  270. package/src/sdk/bus/telegram-daemon-contract.ts +11 -4
  271. package/src/sdk/bus/telegram-daemon.ts +916 -23
  272. package/src/sdk/bus/telegram-reference.ts +40 -3
  273. package/src/sdk/bus/threaded-render.ts +48 -3
  274. package/src/sdk/bus/topic-registry.ts +20 -0
  275. package/src/sdk/host/control/dispatch.ts +5 -1
  276. package/src/sdk/host/control/operations.ts +1 -1
  277. package/src/sdk/host/host.ts +23 -1
  278. package/src/sdk/host/query/handlers.ts +55 -0
  279. package/src/sdk/host/query/revision-store.ts +36 -2
  280. package/src/sdk/host/reverse-leases.ts +44 -7
  281. package/src/sdk/mcp/server.ts +46 -18
  282. package/src/sdk/prompt-status.ts +16 -3
  283. package/src/sdk/protocol/operation-inventory.generated.json +51 -0
  284. package/src/sdk/protocol/operation-registry.ts +7 -2
  285. package/src/sdk/session.ts +101 -10
  286. package/src/session/agent-session.ts +1286 -220
  287. package/src/session/artifacts.ts +22 -0
  288. package/src/session/auth-broker-config.ts +10 -3
  289. package/src/session/blob-store.ts +915 -24
  290. package/src/session/internal/managed-session-scope.ts +44 -6
  291. package/src/session/internal/managed-session-storage.ts +48 -6
  292. package/src/session/memory-guard-checkpoint-participant.ts +131 -0
  293. package/src/session/session-manager.ts +2364 -438
  294. package/src/session/session-storage.ts +9 -1
  295. package/src/session/streaming-output.ts +500 -111
  296. package/src/setup/credential-import.ts +75 -13
  297. package/src/setup/provider-onboarding.ts +19 -4
  298. package/src/skill-state/active-state.ts +32 -10
  299. package/src/skill-state/workflow-hud.ts +42 -2
  300. package/src/skill-state/workflow-mutation-guard.ts +560 -8
  301. package/src/task/executor.ts +122 -39
  302. package/src/task/index.ts +23 -14
  303. package/src/task/provider-retry-status.ts +16 -0
  304. package/src/task/receipt.ts +23 -7
  305. package/src/task/render.ts +6 -2
  306. package/src/task/types.ts +108 -0
  307. package/src/tools/ask-answer-registry.ts +12 -6
  308. package/src/tools/ask.ts +169 -118
  309. package/src/tools/ast-edit.ts +1 -0
  310. package/src/tools/ast-grep.ts +1 -0
  311. package/src/tools/bash-interactive.ts +8 -3
  312. package/src/tools/bash.ts +503 -60
  313. package/src/tools/browser/launch.ts +41 -6
  314. package/src/tools/fetch.ts +114 -23
  315. package/src/tools/find.ts +1 -0
  316. package/src/tools/image-gen.ts +29 -5
  317. package/src/tools/index.ts +4 -0
  318. package/src/tools/output-meta.ts +281 -20
  319. package/src/tools/path-utils.ts +8 -3
  320. package/src/tools/read-internals.ts +44 -0
  321. package/src/tools/read.ts +1560 -310
  322. package/src/tools/resource-gc.ts +182 -18
  323. package/src/tools/review.ts +5 -7
  324. package/src/tools/search.ts +1 -0
  325. package/src/tools/subagent-render.ts +6 -2
  326. package/src/tools/subagent.ts +6 -0
  327. package/src/tools/telegram-send.ts +6 -3
  328. package/src/tools/tool-result.ts +14 -1
  329. package/src/utils/gh.ts +39 -0
  330. package/src/utils/image-resize.ts +3 -0
  331. package/src/web/search/providers/anthropic.ts +4 -4
  332. package/src/web/search/providers/codex.ts +1 -1
  333. package/src/web/search/providers/kimi.ts +15 -5
  334. package/src/web/search/providers/searxng.ts +47 -4
  335. package/src/web/search/providers/xai.ts +7 -2
  336. package/dist/types/gjc-runtime/deep-interview-draft.d.ts +0 -8
  337. package/dist/types/gjc-runtime/deep-interview-payload.d.ts +0 -41
  338. package/dist/types/gjc-runtime/deep-interview-repair.d.ts +0 -17
  339. package/dist/types/gjc-runtime/ultragoal-pipeline.d.ts +0 -23
  340. package/src/defaults/gjc/skills/ultragoal/pipeline-validation-contracts.md +0 -30
  341. package/src/gjc-runtime/deep-interview-draft.ts +0 -843
  342. package/src/gjc-runtime/deep-interview-payload.ts +0 -262
  343. package/src/gjc-runtime/deep-interview-repair.ts +0 -1674
  344. package/src/gjc-runtime/ultragoal-pipeline.ts +0 -306
@@ -33,6 +33,7 @@ import {
33
33
  ManagedSessionDescendantStore,
34
34
  type ManagedSessionSecurityPolicy,
35
35
  type ManagedStorageLock,
36
+ managedSecurityFailureClassification,
36
37
  prepareManagedDirectoryRoot,
37
38
  publishManagedFileNoReplace,
38
39
  publishManagedTombstone,
@@ -873,21 +874,44 @@ function isRecoverableOwnerOnlyModeDrift(error: unknown): boolean {
873
874
  return message === "mode_mismatch" || message.endsWith(": mode_mismatch");
874
875
  }
875
876
 
877
+ type ManagedScopePrepareStage =
878
+ | "retained_identity"
879
+ | "root_authority"
880
+ | "sessions_root"
881
+ | "scope_directory"
882
+ | "scope_identity"
883
+ | "retained_authority"
884
+ | "store"
885
+ | "binding_publish"
886
+ | "binding_read"
887
+ | "binding_validate"
888
+ | "scope_revalidate"
889
+ | "internal_directory"
890
+ | "locks_directory"
891
+ | "receipts_directory"
892
+ | "tombstones_directory";
893
+
876
894
  /** Synchronously create and validate the v2 binding before a default session writer exists. */
877
895
  export function prepareManagedSessionScopeForWriteSync(
878
896
  scope: ManagedScope,
879
897
  policy: ManagedSessionSecurityPolicy = "default",
880
898
  authority?: ManagedCandidateWriteAuthority,
881
899
  ): ManagedScopeResolution {
900
+ let stage: ManagedScopePrepareStage = "retained_identity";
882
901
  try {
883
902
  assertRetainedManagedDirectoryIdentity(scope);
903
+ stage = "root_authority";
884
904
  const root = authority?.rootAuthority ?? scopeRoot(scope, policy);
885
905
  if (authority) bindManagedWriteAuthority(scope, authority);
906
+ stage = "sessions_root";
886
907
  ensureManagedDirectory(scope.sessionsRoot, root, policy);
908
+ stage = "scope_directory";
887
909
  ensureManagedDirectory(scope.directoryPath, root, policy);
910
+ stage = "scope_identity";
888
911
  const preparedDirectory = fs.lstatSync(scope.directoryPath, { bigint: true });
889
912
  if (!preparedDirectory.isDirectory() || preparedDirectory.isSymbolicLink())
890
913
  throw new Error("Managed session directory changed");
914
+ stage = "retained_authority";
891
915
  const retainedAuthority =
892
916
  authority?.retainedAuthority &&
893
917
  authority.retainedDirectory !== undefined &&
@@ -904,6 +928,7 @@ export function prepareManagedSessionScopeForWriteSync(
904
928
  retainedAuthority ? { authority: retainedAuthority, authorityBaseDir: scope.directoryPath } : undefined,
905
929
  policy,
906
930
  );
931
+ stage = "store";
907
932
  let store: ManagedSessionDescendantStore;
908
933
  try {
909
934
  store = buildStore();
@@ -917,15 +942,19 @@ export function prepareManagedSessionScopeForWriteSync(
917
942
  store = buildStore();
918
943
  }
919
944
  const binding = new TextEncoder().encode(`${JSON.stringify(bindingFor(scope))}\n`);
945
+ stage = "binding_publish";
920
946
  try {
921
947
  store.publishNoReplaceSync(MANAGED_SESSION_BINDING_FILE, binding);
922
948
  } catch (error) {
923
949
  if ((error as Error).message !== "destination_conflict") throw error;
924
950
  }
951
+ stage = "binding_read";
925
952
  const capturedBinding = store.readExpected(MANAGED_SESSION_BINDING_FILE);
926
953
  if (!capturedBinding) throw new Error("Managed scope binding is unavailable");
954
+ stage = "binding_validate";
927
955
  const validated = validateBindingRaw(scope, capturedBinding.bytes.toString("utf8"));
928
956
  managedDirectoryAuthorities.set(scope, retainedAuthority);
957
+ stage = "scope_revalidate";
929
958
  const directoryStat = fs.lstatSync(scope.directoryPath, { bigint: true });
930
959
  if (
931
960
  !directoryStat.isDirectory() ||
@@ -935,11 +964,21 @@ export function prepareManagedSessionScopeForWriteSync(
935
964
  )
936
965
  throw new Error("Managed session directory changed");
937
966
  managedDirectoryIdentities.set(scope, { dev: preparedDirectory.dev, ino: preparedDirectory.ino });
938
- if (validated) return validated;
967
+ if (validated) {
968
+ if (validated.kind !== "error") throw new Error("Unexpected managed scope binding result");
969
+ return {
970
+ ...validated,
971
+ cause: { classification: validated.code, diagnostic: "prepare:binding_validate" },
972
+ };
973
+ }
939
974
  const internal = managedInternalDirectory(scope);
975
+ stage = "internal_directory";
940
976
  ensureManagedDirectory(internal, root, policy);
977
+ stage = "locks_directory";
941
978
  ensureManagedDirectory(path.join(internal, MANAGED_LOCKS_DIRECTORY), root, policy);
979
+ stage = "receipts_directory";
942
980
  ensureManagedDirectory(path.join(internal, MANAGED_RECEIPTS_DIRECTORY), root, policy);
981
+ stage = "tombstones_directory";
943
982
  ensureManagedDirectory(path.join(internal, MANAGED_TOMBSTONES_DIRECTORY), root, policy);
944
983
  return { kind: "resolved", scope };
945
984
  } catch (error) {
@@ -954,15 +993,14 @@ export function prepareManagedSessionScopeForWriteSync(
954
993
  message === "durability_not_provable"
955
994
  ? message
956
995
  : "binding_invalid";
996
+ const securityClassification = managedSecurityFailureClassification(error);
957
997
  return {
958
998
  kind: "error",
959
999
  code,
960
1000
  message,
961
- ...(publication
962
- ? { cause: { classification: publication.classification, diagnostic: publication.diagnostic } }
963
- : code === "binding_invalid"
964
- ? {}
965
- : { cause: { classification: code } }),
1001
+ cause: publication
1002
+ ? { classification: publication.classification, diagnostic: publication.diagnostic }
1003
+ : { classification: securityClassification ?? code, diagnostic: `prepare:${stage}` },
966
1004
  };
967
1005
  }
968
1006
  }
@@ -377,12 +377,31 @@ function managedRelativePath(root: ManagedDirectoryRoot, pathname: string): read
377
377
 
378
378
  const PROCESS_START_ID = randomUUID();
379
379
 
380
+ class ManagedSecurityError extends Error {
381
+ readonly #classification: string;
382
+
383
+ constructor(pathname: string, result: NativeSecurity) {
384
+ const classification = result.ok ? "unexpected_security_state" : result.code;
385
+ super(
386
+ result.ok
387
+ ? `Unexpected security state for ${pathname}`
388
+ : `Owner-only security rejected ${pathname}: ${classification}`,
389
+ );
390
+ this.name = "ManagedSecurityError";
391
+ this.#classification = classification;
392
+ }
393
+
394
+ getClassification(): string {
395
+ return this.#classification;
396
+ }
397
+ }
398
+
399
+ export function managedSecurityFailureClassification(error: unknown): string | undefined {
400
+ return error instanceof ManagedSecurityError ? error.getClassification() : undefined;
401
+ }
402
+
380
403
  function securityError(pathname: string, result: NativeSecurity): Error {
381
- return new Error(
382
- result.ok
383
- ? `Unexpected security state for ${pathname}`
384
- : `Owner-only security rejected ${pathname}: ${result.code}`,
385
- );
404
+ return new ManagedSecurityError(pathname, result);
386
405
  }
387
406
 
388
407
  function secure(pathname: string, kind: "directory" | "file"): void {
@@ -453,7 +472,11 @@ export class ManagedSessionDescendantStore {
453
472
  readonly #baseDir: string;
454
473
  readonly #policy: ManagedSessionSecurityPolicy;
455
474
  readonly #authority: RecoveryFsRoot | undefined;
475
+ #ownsAuthority = false;
476
+ #closed = false;
456
477
  readonly #authorityBaseDir: string;
478
+ /** Logical profile root inherited by nested managed session destinations. */
479
+ readonly #profileAgentDir: string;
457
480
  readonly #subtreeRoot: ManagedDirectoryRoot;
458
481
 
459
482
  constructor(
@@ -461,12 +484,14 @@ export class ManagedSessionDescendantStore {
461
484
  baseDir: string,
462
485
  retained?: { authority: RecoveryFsRoot; authorityBaseDir: string },
463
486
  policy?: ManagedSessionSecurityPolicy,
487
+ profileAgentDir?: string,
464
488
  ) {
465
489
  managedRelativePath(root, baseDir);
466
490
 
467
491
  this.#root = root;
468
492
  this.#baseDir = path.resolve(baseDir);
469
493
  this.#policy = policy ?? "default";
494
+ this.#profileAgentDir = profileAgentDir ?? root.canonicalPath;
470
495
  this.#authorityBaseDir = retained?.authorityBaseDir ?? this.#baseDir;
471
496
  if (retained) {
472
497
  const relative = path.relative(retained.authorityBaseDir, this.#baseDir).split(path.sep).join("/");
@@ -501,6 +526,7 @@ export class ManagedSessionDescendantStore {
501
526
  throw new Error("Managed descendant root identity changed");
502
527
  }
503
528
  this.#authority = authority;
529
+ this.#ownsAuthority = true;
504
530
  }
505
531
  }
506
532
 
@@ -520,10 +546,15 @@ export class ManagedSessionDescendantStore {
520
546
  return this.#policy;
521
547
  }
522
548
 
549
+ get profileAgentDir(): string {
550
+ return this.#profileAgentDir;
551
+ }
552
+
523
553
  deriveSubtree(relativePath: string): ManagedSessionDescendantStore {
524
554
  const child = this.ensureDirectory(relativePath);
525
555
  const resolved = this.#resolve(relativePath);
526
- if (!this.#authority) return new ManagedSessionDescendantStore(this.#root, resolved, undefined, this.#policy);
556
+ if (!this.#authority)
557
+ return new ManagedSessionDescendantStore(this.#root, resolved, undefined, this.#policy, this.#profileAgentDir);
527
558
  const retainedChild = this.#authority.retainManagedDirectory(
528
559
  this.#relative(resolved),
529
560
  child.dev.toString(),
@@ -537,6 +568,7 @@ export class ManagedSessionDescendantStore {
537
568
  authorityBaseDir: resolved,
538
569
  },
539
570
  this.#policy,
571
+ this.#profileAgentDir,
540
572
  );
541
573
  }
542
574
 
@@ -549,6 +581,16 @@ export class ManagedSessionDescendantStore {
549
581
  );
550
582
  }
551
583
 
584
+ /**
585
+ * Release an authority this store opened itself. Retained authorities are owned by
586
+ * the security context that supplied them and are never closed here. Idempotent.
587
+ */
588
+ close(): void {
589
+ if (this.#closed || !this.#ownsAuthority || !this.#authority) return;
590
+ this.#closed = true;
591
+ this.#authority.close();
592
+ }
593
+
552
594
  assertBound(): void {
553
595
  this.#assertBound();
554
596
  }
@@ -0,0 +1,131 @@
1
+ import * as crypto from "node:crypto";
2
+ import * as path from "node:path";
3
+ import type { RecoveryFsRoot } from "@gajae-code/natives";
4
+ import type {
5
+ RecoveryHydrationContext,
6
+ ResumeSessionIdentity,
7
+ SessionDestinationInput,
8
+ SessionManager,
9
+ SessionManagerCheckpointRevisionStrings,
10
+ StrictSessionOpenFailure,
11
+ } from "./session-manager";
12
+
13
+ export interface MemoryGuardTranscriptDescriptorV1 {
14
+ bytes: string;
15
+ relative_path: string;
16
+ sha256: string;
17
+ }
18
+
19
+ export interface MemoryGuardCheckpointBlobAuthorityV1 {
20
+ kind: "checkpoint_blob_tree_v1";
21
+ manifest_relative_path: string;
22
+ manifest_sha256: string;
23
+ root_relative_path: string;
24
+ }
25
+
26
+ export interface MemoryGuardCheckpointBlobManifestEntryV1 {
27
+ bytes: string;
28
+ relative_path: string;
29
+ sha256: string;
30
+ }
31
+
32
+ export interface MemoryGuardCheckpointBlobManifestV1 {
33
+ entries: MemoryGuardCheckpointBlobManifestEntryV1[];
34
+ schema_version: 1;
35
+ }
36
+
37
+ export interface MemoryGuardSessionManagerCheckpointV1 {
38
+ blob_authority: MemoryGuardCheckpointBlobAuthorityV1;
39
+ revisions: SessionManagerCheckpointRevisionStrings;
40
+ schema_version: 1;
41
+ session_id: string;
42
+ session_name: string | null;
43
+ transcript: MemoryGuardTranscriptDescriptorV1;
44
+ }
45
+
46
+ export interface MemoryGuardParticipantDescriptorV1 {
47
+ ordinal: number;
48
+ checkpoint: MemoryGuardCheckpointBlobAuthorityV1;
49
+ revisions: SessionManagerCheckpointRevisionStrings;
50
+ session_id: string;
51
+ session_name: string | null;
52
+ transcript: MemoryGuardTranscriptDescriptorV1;
53
+ }
54
+
55
+ export interface MemoryGuardParticipantIngressLease {
56
+ readonly token: symbol;
57
+ release(): void;
58
+ }
59
+
60
+ export interface MemoryGuardCreateCheckpointInput {
61
+ ingressLease: MemoryGuardParticipantIngressLease;
62
+ checkpointRoot: string;
63
+ }
64
+
65
+ export type MemoryGuardRestoreBlockedReason =
66
+ | StrictSessionOpenFailure["reason"]
67
+ | "checkpoint-mismatch"
68
+ | "participant-mismatch"
69
+ | "transcript-mismatch"
70
+ | "blob-manifest-mismatch"
71
+ | "blob-missing"
72
+ | "blob-hash-mismatch"
73
+ | "blob-authority-mismatch"
74
+ | "destination-unavailable";
75
+
76
+ export interface MemoryGuardRestoreInput {
77
+ incidentAuthority: RecoveryFsRoot;
78
+ participant: MemoryGuardParticipantDescriptorV1;
79
+ checkpoint: MemoryGuardSessionManagerCheckpointV1;
80
+ destination: SessionDestinationInput;
81
+ }
82
+
83
+ export type MemoryGuardRestoreResult =
84
+ | {
85
+ kind: "staged";
86
+ manager: SessionManager;
87
+ hydrationContext: RecoveryHydrationContext;
88
+ transcriptIdentity: ResumeSessionIdentity;
89
+ cleanup: () => Promise<void>;
90
+ }
91
+ | { kind: "blocked"; reason: MemoryGuardRestoreBlockedReason };
92
+
93
+ function sortJson(value: unknown): unknown {
94
+ if (Array.isArray(value)) return value.map(sortJson);
95
+ if (value && typeof value === "object") {
96
+ return Object.fromEntries(
97
+ Object.entries(value as Record<string, unknown>)
98
+ .sort(([left], [right]) => left.localeCompare(right))
99
+ .map(([key, child]) => [key, sortJson(child)]),
100
+ );
101
+ }
102
+ return value;
103
+ }
104
+
105
+ export function memoryGuardCanonicalJson(value: unknown): string {
106
+ return `${JSON.stringify(sortJson(value))}\n`;
107
+ }
108
+
109
+ export function memoryGuardSha256Hex(value: Uint8Array | string): string {
110
+ return crypto.createHash("sha256").update(value).digest("hex");
111
+ }
112
+
113
+ export function isMemoryGuardDecimalString(value: unknown): value is string {
114
+ return typeof value === "string" && /^(?:0|[1-9]\d*)$/.test(value);
115
+ }
116
+
117
+ export function isMemoryGuardSha256Hex(value: unknown): value is string {
118
+ return typeof value === "string" && /^[0-9a-f]{64}$/.test(value);
119
+ }
120
+
121
+ export function isMemoryGuardRelativePath(value: unknown): value is string {
122
+ if (typeof value !== "string" || value.length === 0) return false;
123
+ if (path.isAbsolute(value) || value.includes("\\")) return false;
124
+ const parts = value.split("/");
125
+ return parts.every(part => part.length > 0 && part !== "." && part !== "..");
126
+ }
127
+
128
+ export function hasOnlyKeys(value: Record<string, unknown>, allowed: readonly string[]): boolean {
129
+ const keys = Object.keys(value);
130
+ return keys.length === allowed.length && keys.every(key => allowed.includes(key));
131
+ }