@cortexkit/opencode-magic-context 0.41.4 → 0.42.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 (358) hide show
  1. package/README.md +21 -3
  2. package/dist/agents/hidden-agent-registrations.d.ts +1 -3
  3. package/dist/agents/hidden-agent-registrations.d.ts.map +1 -1
  4. package/dist/agents/magic-context-prompt.d.ts +1 -1
  5. package/dist/agents/magic-context-prompt.d.ts.map +1 -1
  6. package/dist/agents/permissions.d.ts +1 -22
  7. package/dist/agents/permissions.d.ts.map +1 -1
  8. package/dist/config/agent-disable.d.ts +0 -5
  9. package/dist/config/agent-disable.d.ts.map +1 -1
  10. package/dist/config/index.d.ts +5 -0
  11. package/dist/config/index.d.ts.map +1 -1
  12. package/dist/config/migrate-config-location.d.ts.map +1 -1
  13. package/dist/config/project-security.d.ts +20 -2
  14. package/dist/config/project-security.d.ts.map +1 -1
  15. package/dist/config/removed-agent-config.d.ts +8 -0
  16. package/dist/config/removed-agent-config.d.ts.map +1 -0
  17. package/dist/config/schema/magic-context.d.ts +43 -201
  18. package/dist/config/schema/magic-context.d.ts.map +1 -1
  19. package/dist/{conflict-warning-hook-ejkc9sjn.js → conflict-warning-hook-6p3xqeac.js} +3 -3
  20. package/dist/{derive-budgets-bc366cz8.js → derive-budgets-s2pgnnm4.js} +1 -1
  21. package/dist/features/builtin-commands/commands.d.ts +0 -4
  22. package/dist/features/builtin-commands/commands.d.ts.map +1 -1
  23. package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
  24. package/dist/features/magic-context/compartment-chunk-embedding.d.ts +15 -4
  25. package/dist/features/magic-context/compartment-chunk-embedding.d.ts.map +1 -1
  26. package/dist/features/magic-context/compartment-storage.d.ts.map +1 -1
  27. package/dist/features/magic-context/context-authority.d.ts +31 -4
  28. package/dist/features/magic-context/context-authority.d.ts.map +1 -1
  29. package/dist/features/magic-context/dreamer/classify.d.ts.map +1 -1
  30. package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts.map +1 -1
  31. package/dist/features/magic-context/dreamer/map-memories.d.ts.map +1 -1
  32. package/dist/features/magic-context/dreamer/open-opencode-db.d.ts.map +1 -1
  33. package/dist/features/magic-context/dreamer/refresh-primers.d.ts.map +1 -1
  34. package/dist/features/magic-context/dreamer/retrospective-orphan-sweep.d.ts +19 -9
  35. package/dist/features/magic-context/dreamer/retrospective-orphan-sweep.d.ts.map +1 -1
  36. package/dist/features/magic-context/dreamer/storage-dream-runs.d.ts.map +1 -1
  37. package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
  38. package/dist/features/magic-context/dreamer/task-scheduler.d.ts +4 -0
  39. package/dist/features/magic-context/dreamer/task-scheduler.d.ts.map +1 -1
  40. package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
  41. package/dist/features/magic-context/fail-closed-block.d.ts.map +1 -1
  42. package/dist/features/magic-context/git-commits/sweep-coordinator.d.ts.map +1 -1
  43. package/dist/features/magic-context/index.d.ts +0 -1
  44. package/dist/features/magic-context/index.d.ts.map +1 -1
  45. package/dist/features/magic-context/memory/embedding-identity.d.ts.map +1 -1
  46. package/dist/features/magic-context/memory/embedding-local.d.ts +13 -0
  47. package/dist/features/magic-context/memory/embedding-local.d.ts.map +1 -1
  48. package/dist/features/magic-context/memory/embedding-model-match.d.ts +41 -0
  49. package/dist/features/magic-context/memory/embedding-model-match.d.ts.map +1 -0
  50. package/dist/features/magic-context/memory/embedding-openai.d.ts +7 -20
  51. package/dist/features/magic-context/memory/embedding-openai.d.ts.map +1 -1
  52. package/dist/features/magic-context/memory/embedding-provider.d.ts +2 -2
  53. package/dist/features/magic-context/memory/embedding-provider.d.ts.map +1 -1
  54. package/dist/features/magic-context/memory/embedding-synapse.d.ts +48 -14
  55. package/dist/features/magic-context/memory/embedding-synapse.d.ts.map +1 -1
  56. package/dist/features/magic-context/memory/embedding.d.ts +1 -1
  57. package/dist/features/magic-context/memory/embedding.d.ts.map +1 -1
  58. package/dist/features/magic-context/memory/memory-migration.d.ts.map +1 -1
  59. package/dist/features/magic-context/memory/project-identity.d.ts +1 -0
  60. package/dist/features/magic-context/memory/project-identity.d.ts.map +1 -1
  61. package/dist/features/magic-context/memory/promotion.d.ts +7 -1
  62. package/dist/features/magic-context/memory/promotion.d.ts.map +1 -1
  63. package/dist/features/magic-context/merged-reasoning-decisions.d.ts +6 -0
  64. package/dist/features/magic-context/merged-reasoning-decisions.d.ts.map +1 -0
  65. package/dist/features/magic-context/message-fts-rowid-map.d.ts.map +1 -1
  66. package/dist/features/magic-context/message-index-async.d.ts +12 -0
  67. package/dist/features/magic-context/message-index-async.d.ts.map +1 -1
  68. package/dist/features/magic-context/message-index.d.ts.map +1 -1
  69. package/dist/features/magic-context/migrations.d.ts.map +1 -1
  70. package/dist/features/magic-context/mural/compress-cues.d.ts.map +1 -1
  71. package/dist/features/magic-context/mural/render-trigger.d.ts +6 -0
  72. package/dist/features/magic-context/mural/render-trigger.d.ts.map +1 -1
  73. package/dist/features/magic-context/no-content-compartment.d.ts +12 -0
  74. package/dist/features/magic-context/no-content-compartment.d.ts.map +1 -0
  75. package/dist/features/magic-context/pi-content-decisions.d.ts +9 -0
  76. package/dist/features/magic-context/pi-content-decisions.d.ts.map +1 -0
  77. package/dist/features/magic-context/project-docs-hash.d.ts +4 -0
  78. package/dist/features/magic-context/project-docs-hash.d.ts.map +1 -1
  79. package/dist/features/magic-context/project-embedding-registry.d.ts +13 -4
  80. package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
  81. package/dist/features/magic-context/protection-window.d.ts +79 -0
  82. package/dist/features/magic-context/protection-window.d.ts.map +1 -0
  83. package/dist/features/magic-context/search.d.ts.map +1 -1
  84. package/dist/features/magic-context/session-project-backfill.d.ts.map +1 -1
  85. package/dist/features/magic-context/shadow-backfill-state.d.ts +26 -0
  86. package/dist/features/magic-context/shadow-backfill-state.d.ts.map +1 -0
  87. package/dist/features/magic-context/smart-notes/compiler.d.ts.map +1 -1
  88. package/dist/features/magic-context/smart-notes/sandbox-runner.d.ts +4 -0
  89. package/dist/features/magic-context/smart-notes/sandbox-runner.d.ts.map +1 -1
  90. package/dist/features/magic-context/smart-notes/storage.d.ts.map +1 -1
  91. package/dist/features/magic-context/storage-clone.d.ts.map +1 -1
  92. package/dist/features/magic-context/storage-db.d.ts +1 -1
  93. package/dist/features/magic-context/storage-db.d.ts.map +1 -1
  94. package/dist/features/magic-context/storage-embedding-measurements.d.ts +2 -2
  95. package/dist/features/magic-context/storage-embedding-measurements.d.ts.map +1 -1
  96. package/dist/features/magic-context/storage-historian-runs.d.ts +4 -0
  97. package/dist/features/magic-context/storage-historian-runs.d.ts.map +1 -1
  98. package/dist/features/magic-context/storage-memory-mutation-log.d.ts +1 -0
  99. package/dist/features/magic-context/storage-memory-mutation-log.d.ts.map +1 -1
  100. package/dist/features/magic-context/storage-meta-persisted.d.ts +79 -13
  101. package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
  102. package/dist/features/magic-context/storage-meta.d.ts +1 -1
  103. package/dist/features/magic-context/storage-meta.d.ts.map +1 -1
  104. package/dist/features/magic-context/storage-native-replay.d.ts +29 -0
  105. package/dist/features/magic-context/storage-native-replay.d.ts.map +1 -0
  106. package/dist/features/magic-context/storage-notes.d.ts +6 -0
  107. package/dist/features/magic-context/storage-notes.d.ts.map +1 -1
  108. package/dist/features/magic-context/storage-replay-document.d.ts +33 -0
  109. package/dist/features/magic-context/storage-replay-document.d.ts.map +1 -0
  110. package/dist/features/magic-context/storage-subagent-invocations.d.ts +1 -1
  111. package/dist/features/magic-context/storage-subagent-invocations.d.ts.map +1 -1
  112. package/dist/features/magic-context/storage-tags.d.ts +19 -11
  113. package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
  114. package/dist/features/magic-context/storage.d.ts +3 -3
  115. package/dist/features/magic-context/storage.d.ts.map +1 -1
  116. package/dist/features/magic-context/subagent-token-capture.d.ts.map +1 -1
  117. package/dist/features/magic-context/tagger.d.ts +13 -0
  118. package/dist/features/magic-context/tagger.d.ts.map +1 -1
  119. package/dist/features/magic-context/tool-owner-backfill.d.ts.map +1 -1
  120. package/dist/features/magic-context/user-memory/review-user-memories.d.ts.map +1 -1
  121. package/dist/features/magic-context/user-memory/storage-user-memory.d.ts.map +1 -1
  122. package/dist/features/magic-context/workspaces.d.ts.map +1 -1
  123. package/dist/hooks/magic-context/apply-operations.d.ts +11 -5
  124. package/dist/hooks/magic-context/apply-operations.d.ts.map +1 -1
  125. package/dist/hooks/magic-context/auto-search-runner.d.ts.map +1 -1
  126. package/dist/hooks/magic-context/cache-busting-signals.d.ts +9 -1
  127. package/dist/hooks/magic-context/cache-busting-signals.d.ts.map +1 -1
  128. package/dist/hooks/magic-context/caveman-cleanup.d.ts +1 -1
  129. package/dist/hooks/magic-context/caveman-cleanup.d.ts.map +1 -1
  130. package/dist/hooks/magic-context/channel2-delivery.d.ts.map +1 -1
  131. package/dist/hooks/magic-context/child-session-spawn.d.ts +3 -3
  132. package/dist/hooks/magic-context/child-session-spawn.d.ts.map +1 -1
  133. package/dist/hooks/magic-context/command-handler.d.ts +1 -10
  134. package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
  135. package/dist/hooks/magic-context/compaction-marker-manager.d.ts.map +1 -1
  136. package/dist/hooks/magic-context/compartment-runner-drop-queue.d.ts +10 -21
  137. package/dist/hooks/magic-context/compartment-runner-drop-queue.d.ts.map +1 -1
  138. package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
  139. package/dist/hooks/magic-context/compartment-runner-partial-recomp.d.ts.map +1 -1
  140. package/dist/hooks/magic-context/compartment-runner-recomp.d.ts.map +1 -1
  141. package/dist/hooks/magic-context/compartment-runner-validation.d.ts +1 -1
  142. package/dist/hooks/magic-context/compartment-runner-validation.d.ts.map +1 -1
  143. package/dist/hooks/magic-context/ctx-reduce-nudge.d.ts +26 -2
  144. package/dist/hooks/magic-context/ctx-reduce-nudge.d.ts.map +1 -1
  145. package/dist/hooks/magic-context/decay-render.d.ts.map +1 -1
  146. package/dist/hooks/magic-context/dropped-input-guard.d.ts +9 -0
  147. package/dist/hooks/magic-context/dropped-input-guard.d.ts.map +1 -0
  148. package/dist/hooks/magic-context/embed-session-state.d.ts +1 -1
  149. package/dist/hooks/magic-context/embed-session-state.d.ts.map +1 -1
  150. package/dist/hooks/magic-context/emergency-drop.d.ts +6 -1
  151. package/dist/hooks/magic-context/emergency-drop.d.ts.map +1 -1
  152. package/dist/hooks/magic-context/event-handler.d.ts +0 -1
  153. package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
  154. package/dist/hooks/magic-context/event-payloads.d.ts +7 -6
  155. package/dist/hooks/magic-context/event-payloads.d.ts.map +1 -1
  156. package/dist/hooks/magic-context/event-resolvers.d.ts +1 -1
  157. package/dist/hooks/magic-context/event-resolvers.d.ts.map +1 -1
  158. package/dist/hooks/magic-context/execute-status.d.ts +3 -1
  159. package/dist/hooks/magic-context/execute-status.d.ts.map +1 -1
  160. package/dist/hooks/magic-context/format-embed-failure.d.ts +2 -1
  161. package/dist/hooks/magic-context/format-embed-failure.d.ts.map +1 -1
  162. package/dist/hooks/magic-context/format-embed-status.d.ts.map +1 -1
  163. package/dist/hooks/magic-context/heuristic-cleanup.d.ts +7 -1
  164. package/dist/hooks/magic-context/heuristic-cleanup.d.ts.map +1 -1
  165. package/dist/hooks/magic-context/hook-handlers.d.ts +3 -1
  166. package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
  167. package/dist/hooks/magic-context/hook.d.ts +13 -4
  168. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  169. package/dist/hooks/magic-context/inject-compartments.d.ts +14 -1
  170. package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
  171. package/dist/hooks/magic-context/live-session-state.d.ts +1 -1
  172. package/dist/hooks/magic-context/lkg-slot.d.ts +34 -0
  173. package/dist/hooks/magic-context/lkg-slot.d.ts.map +1 -1
  174. package/dist/hooks/magic-context/maintenance-authority.d.ts +2 -2
  175. package/dist/hooks/magic-context/maintenance-authority.d.ts.map +1 -1
  176. package/dist/hooks/magic-context/module-state-sync-timing.d.ts +21 -0
  177. package/dist/hooks/magic-context/module-state-sync-timing.d.ts.map +1 -0
  178. package/dist/hooks/magic-context/module-state-sync.d.ts +21 -7
  179. package/dist/hooks/magic-context/module-state-sync.d.ts.map +1 -1
  180. package/dist/hooks/magic-context/module-transport.d.ts +12 -0
  181. package/dist/hooks/magic-context/module-transport.d.ts.map +1 -1
  182. package/dist/hooks/magic-context/module-wire.d.ts +8 -0
  183. package/dist/hooks/magic-context/module-wire.d.ts.map +1 -1
  184. package/dist/hooks/magic-context/note-nudger.d.ts.map +1 -1
  185. package/dist/hooks/magic-context/persist-filtered-noise.d.ts +5 -0
  186. package/dist/hooks/magic-context/persist-filtered-noise.d.ts.map +1 -0
  187. package/dist/hooks/magic-context/protected-tail-boundary.d.ts +6 -0
  188. package/dist/hooks/magic-context/protected-tail-boundary.d.ts.map +1 -1
  189. package/dist/hooks/magic-context/read-session-chunk.d.ts +18 -18
  190. package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
  191. package/dist/hooks/magic-context/read-session-db.d.ts +22 -12
  192. package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
  193. package/dist/hooks/magic-context/read-session-formatting.d.ts +8 -0
  194. package/dist/hooks/magic-context/read-session-formatting.d.ts.map +1 -1
  195. package/dist/hooks/magic-context/read-session-raw.d.ts +10 -1
  196. package/dist/hooks/magic-context/read-session-raw.d.ts.map +1 -1
  197. package/dist/hooks/magic-context/recomp-orchestrator.d.ts.map +1 -1
  198. package/dist/hooks/magic-context/reference-retrieval.d.ts.map +1 -1
  199. package/dist/hooks/magic-context/rust-mode-transform.d.ts +74 -9
  200. package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
  201. package/dist/hooks/magic-context/send-session-notification.d.ts +11 -10
  202. package/dist/hooks/magic-context/send-session-notification.d.ts.map +1 -1
  203. package/dist/hooks/magic-context/strip-content.d.ts +7 -0
  204. package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
  205. package/dist/hooks/magic-context/supersession-reclaim.d.ts +13 -0
  206. package/dist/hooks/magic-context/supersession-reclaim.d.ts.map +1 -1
  207. package/dist/hooks/magic-context/system-prompt-hash.d.ts +2 -3
  208. package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
  209. package/dist/hooks/magic-context/tail-hygiene-walk.d.ts +8 -3
  210. package/dist/hooks/magic-context/tail-hygiene-walk.d.ts.map +1 -1
  211. package/dist/hooks/magic-context/tool-drop-target.d.ts.map +1 -1
  212. package/dist/hooks/magic-context/transform-compartment-phase.d.ts.map +1 -1
  213. package/dist/hooks/magic-context/transform-context-state.d.ts +7 -1
  214. package/dist/hooks/magic-context/transform-context-state.d.ts.map +1 -1
  215. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +11 -4
  216. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  217. package/dist/hooks/magic-context/transform.d.ts +7 -2
  218. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  219. package/dist/hooks/magic-context/upgrade-reminder.d.ts +7 -9
  220. package/dist/hooks/magic-context/upgrade-reminder.d.ts.map +1 -1
  221. package/dist/hooks/magic-context/wrapup-orchestrator.d.ts.map +1 -1
  222. package/dist/index-1974jvn3.js +783 -0
  223. package/dist/{index-0y2mcg5y.js → index-1q9kay7n.js} +18717 -16197
  224. package/dist/{index-4avmwfp5.js → index-36wd1d6k.js} +6 -29
  225. package/dist/{index-fz104x1j.js → index-jmtjh2d3.js} +3 -3
  226. package/dist/{index-q264erdp.js → index-nqgjwfzn.js} +70 -38
  227. package/dist/{index-mjv9je4e.js → index-xdtge3y2.js} +45 -7
  228. package/dist/index.d.ts.map +1 -1
  229. package/dist/index.js +6457 -5190
  230. package/dist/plugin/conflict-warning-hook.d.ts +5 -6
  231. package/dist/plugin/conflict-warning-hook.d.ts.map +1 -1
  232. package/dist/plugin/dream-timer.d.ts +1 -0
  233. package/dist/plugin/dream-timer.d.ts.map +1 -1
  234. package/dist/plugin/embedding-bootstrap-helpers.d.ts.map +1 -1
  235. package/dist/plugin/embedding-routing.d.ts +4 -1
  236. package/dist/plugin/embedding-routing.d.ts.map +1 -1
  237. package/dist/plugin/hooks/create-session-hooks.d.ts +16 -2
  238. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  239. package/dist/plugin/rpc-handlers.d.ts +31 -1
  240. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  241. package/dist/plugin/rust-tool-backends.d.ts +1 -0
  242. package/dist/plugin/rust-tool-backends.d.ts.map +1 -1
  243. package/dist/plugin/tool-registry.d.ts.map +1 -1
  244. package/dist/{recomp-orchestrator-q98r6rga.js → recomp-orchestrator-m33b3rk9.js} +5 -5
  245. package/dist/{send-session-notification-hdh02wy9.js → send-session-notification-1qeqkswb.js} +6 -4
  246. package/dist/shared/child-session-teardown.d.ts +34 -0
  247. package/dist/shared/child-session-teardown.d.ts.map +1 -0
  248. package/dist/shared/keep-subagents.d.ts +1 -1
  249. package/dist/shared/keep-subagents.d.ts.map +1 -1
  250. package/dist/shared/model-suggestion-retry.d.ts +1 -1
  251. package/dist/shared/opencode-db-path.d.ts +24 -0
  252. package/dist/shared/opencode-db-path.d.ts.map +1 -0
  253. package/dist/shared/prompt-surface-runtime.d.ts +10 -5
  254. package/dist/shared/prompt-surface-runtime.d.ts.map +1 -1
  255. package/dist/shared/resolve-fallbacks.d.ts +1 -1
  256. package/dist/shared/rpc-types.d.ts +121 -0
  257. package/dist/shared/rpc-types.d.ts.map +1 -1
  258. package/dist/shared/sqlite.d.ts +42 -0
  259. package/dist/shared/sqlite.d.ts.map +1 -1
  260. package/dist/shared/status-detail-text.d.ts +3 -1
  261. package/dist/shared/status-detail-text.d.ts.map +1 -1
  262. package/dist/shared/status-summary.d.ts +30 -0
  263. package/dist/shared/status-summary.d.ts.map +1 -0
  264. package/dist/shared/subagent-runner.d.ts +17 -10
  265. package/dist/shared/subagent-runner.d.ts.map +1 -1
  266. package/dist/shared/tag-transcript.d.ts.map +1 -1
  267. package/dist/shared/tail-hygiene-status.d.ts +1 -0
  268. package/dist/shared/tail-hygiene-status.d.ts.map +1 -1
  269. package/dist/shared/transcript.d.ts +6 -0
  270. package/dist/shared/transcript.d.ts.map +1 -1
  271. package/dist/shared/user-facing-codes.d.ts +191 -0
  272. package/dist/shared/user-facing-codes.d.ts.map +1 -0
  273. package/dist/shared/window-geometry.d.ts +23 -0
  274. package/dist/shared/window-geometry.d.ts.map +1 -1
  275. package/dist/shared/write-transaction-timing.d.ts +1 -1
  276. package/dist/shared/write-transaction-timing.d.ts.map +1 -1
  277. package/dist/{storage-meta-session-dvwfw778.js → storage-meta-session-e6g0mmec.js} +2 -2
  278. package/dist/tools/ctx-memory/tools.d.ts.map +1 -1
  279. package/dist/tools/ctx-memory/verification-recording.d.ts.map +1 -1
  280. package/dist/tools/ctx-note/constants.d.ts +1 -1
  281. package/dist/tools/ctx-note/constants.d.ts.map +1 -1
  282. package/dist/tools/ctx-note/tools.d.ts.map +1 -1
  283. package/dist/tools/ctx-note/types.d.ts +1 -0
  284. package/dist/tools/ctx-note/types.d.ts.map +1 -1
  285. package/dist/tools/ctx-reduce/tools.d.ts +10 -1
  286. package/dist/tools/ctx-reduce/tools.d.ts.map +1 -1
  287. package/dist/tools/ctx-search/constants.d.ts +1 -1
  288. package/dist/tools/ctx-search/constants.d.ts.map +1 -1
  289. package/dist/tools/light-descriptions.d.ts +2 -2
  290. package/dist/tools/light-descriptions.d.ts.map +1 -1
  291. package/package.json +2 -3
  292. package/src/agents/hidden-agent-registrations.ts +3 -15
  293. package/src/agents/magic-context-prompt.test.ts +7 -5
  294. package/src/agents/magic-context-prompt.ts +22 -30
  295. package/src/agents/permissions.test.ts +1 -42
  296. package/src/agents/permissions.ts +1 -24
  297. package/src/config/agent-disable.ts +5 -22
  298. package/src/config/index.test.ts +126 -15
  299. package/src/config/index.ts +41 -6
  300. package/src/config/latch-permanence-guard.test.ts +4 -0
  301. package/src/config/migrate-config-location.test.ts +39 -6
  302. package/src/config/migrate-config-location.ts +18 -31
  303. package/src/config/profiles.ts +1 -1
  304. package/src/config/project-security.hostile-matrix.test.ts +0 -8
  305. package/src/config/project-security.test.ts +21 -24
  306. package/src/config/project-security.ts +115 -14
  307. package/src/config/protected-tokens.test.ts +235 -0
  308. package/src/config/removed-agent-config.ts +45 -0
  309. package/src/config/removed-agent-source-fence.test.ts +56 -0
  310. package/src/config/schema/magic-context.test.ts +50 -42
  311. package/src/config/schema/magic-context.ts +70 -37
  312. package/src/shared/child-session-teardown.test.ts +218 -0
  313. package/src/shared/child-session-teardown.ts +66 -0
  314. package/src/shared/keep-subagents.ts +9 -14
  315. package/src/shared/model-suggestion-retry.ts +1 -1
  316. package/src/shared/opencode-db-path.test.ts +196 -0
  317. package/src/shared/opencode-db-path.ts +215 -0
  318. package/src/shared/prompt-surface-a1-golden.md +50 -35
  319. package/src/shared/prompt-surface-runtime.test.ts +28 -0
  320. package/src/shared/prompt-surface-runtime.ts +22 -5
  321. package/src/shared/resolve-fallbacks.ts +1 -1
  322. package/src/shared/rpc-types.ts +128 -0
  323. package/src/shared/session-messages-bounded.test.ts +1 -1
  324. package/src/shared/sqlite-import-fence.test.ts +19 -0
  325. package/src/shared/sqlite.test.ts +27 -1
  326. package/src/shared/sqlite.ts +204 -1
  327. package/src/shared/status-detail-text.test.ts +92 -20
  328. package/src/shared/status-detail-text.ts +24 -2
  329. package/src/shared/status-summary.ts +167 -0
  330. package/src/shared/subagent-runner.ts +17 -10
  331. package/src/shared/tag-transcript.ts +33 -21
  332. package/src/shared/tail-hygiene-status.ts +8 -0
  333. package/src/shared/transcript.ts +7 -0
  334. package/src/shared/user-facing-codes.test.ts +140 -0
  335. package/src/shared/user-facing-codes.ts +276 -0
  336. package/src/shared/window-geometry.test.ts +44 -0
  337. package/src/shared/window-geometry.ts +89 -11
  338. package/src/shared/write-transaction-attribution.test.ts +241 -0
  339. package/src/shared/write-transaction-timing.ts +2 -1
  340. package/src/tui/index.tsx +44 -11
  341. package/src/tui/slots/sidebar-content.tsx +12 -7
  342. package/src/tui-compiled/index.tsx +662 -649
  343. package/src/tui-compiled/slots/sidebar-content.tsx +301 -305
  344. package/dist/agents/sidekick.d.ts +0 -2
  345. package/dist/agents/sidekick.d.ts.map +0 -1
  346. package/dist/features/magic-context/defaults.d.ts +0 -2
  347. package/dist/features/magic-context/defaults.d.ts.map +0 -1
  348. package/dist/features/magic-context/sidekick/agent.d.ts +0 -14
  349. package/dist/features/magic-context/sidekick/agent.d.ts.map +0 -1
  350. package/dist/features/magic-context/sidekick/core.d.ts +0 -38
  351. package/dist/features/magic-context/sidekick/core.d.ts.map +0 -1
  352. package/dist/features/magic-context/sidekick/index.d.ts +0 -3
  353. package/dist/features/magic-context/sidekick/index.d.ts.map +0 -1
  354. package/dist/hooks/magic-context/boundary-execution.d.ts +0 -27
  355. package/dist/hooks/magic-context/boundary-execution.d.ts.map +0 -1
  356. package/dist/index-raatkvw5.js +0 -360
  357. package/src/agents/sidekick.ts +0 -1
  358. package/src/features/magic-context/defaults.ts +0 -1
@@ -1,7 +1,6 @@
1
1
  import { homedir } from "node:os";
2
2
  import { z } from "zod";
3
3
  import { isValidLanguageCode } from "../../agents/language-directive";
4
- import { DEFAULT_PROTECTED_TAGS } from "../../features/magic-context/defaults";
5
4
  import { isValidCron } from "../../features/magic-context/dreamer/cron";
6
5
  import type {
7
6
  AGENTIC_DREAM_TASKS,
@@ -446,27 +445,15 @@ const ProfileDreamerSchema = z
446
445
  omp: ProfileOmpModelBlockSchema.optional(),
447
446
  })
448
447
  .strict();
449
- const ProfileSidekickSchema = AgentOverrideConfigSchema.pick({
450
- model: true,
451
- fallback_models: true,
452
- variant: true,
453
- })
454
- .extend({
455
- thinking_level: PiThinkingLevelSchema.describe(
456
- "Pi thinking level for the sidekick model selection.",
457
- ),
458
- })
459
- .strict();
460
448
 
461
449
  export const ConfigProfileSchema = z
462
450
  .object({
463
451
  historian: ProfileHistorianSchema.optional(),
464
452
  dreamer: ProfileDreamerSchema.optional(),
465
- sidekick: ProfileSidekickSchema.optional(),
466
453
  })
467
454
  .strict()
468
455
  .describe(
469
- "User-owned model-selection overlay. Only historian/dreamer harness model blocks and sidekick model-selection fields are allowed.",
456
+ "User-owned model-selection overlay. Only historian/dreamer harness model blocks are allowed.",
470
457
  );
471
458
  export type ConfigProfile = z.infer<typeof ConfigProfileSchema>;
472
459
 
@@ -626,15 +613,6 @@ export const DreamerConfigSchema = AgentMetadataSchema.extend({
626
613
  });
627
614
  export type DreamerConfig = z.infer<typeof DreamerConfigSchema>;
628
615
 
629
- export const SidekickConfigSchema = AgentOverrideConfigSchema.extend({
630
- timeout_ms: z.number().default(30000).describe("Timeout for sidekick calls in milliseconds"),
631
- system_prompt: z.string().optional().describe("Custom system prompt for sidekick"),
632
- thinking_level: PiThinkingLevelSchema.describe(
633
- "Pi only: explicit thinking level for sidekick subagent invocations. See historian.pi.thinking_level.",
634
- ),
635
- }).optional();
636
- export type SidekickConfig = NonNullable<z.infer<typeof SidekickConfigSchema>>;
637
-
638
616
  /**
639
617
  * Historian metadata remains harness-independent. Only model resolution moves to
640
618
  * the strict opencode, pi, and omp blocks; two_pass and disallowed_tools stay here.
@@ -699,6 +677,18 @@ const BaseEmbeddingConfigSchema = z
699
677
  .describe(
700
678
  "Optional input_type for query (search) embeddings on asymmetric models (e.g. NVIDIA NIM 'query'). When unset, query embeddings use embedding.input_type. Passage/stored content always uses embedding.input_type.",
701
679
  ),
680
+ query_instruction: z
681
+ .union([z.string(), z.literal(false)])
682
+ .optional()
683
+ .describe(
684
+ "OpenAI-compatible query prefix override. A string is prepended verbatim to search queries; false disables the built-in model-family instruction. Qwen3-Embedding, gte-Qwen instruct, e5 instruct, and Nomic families have built-in recipes. Query-only changes do not re-embed stored content. User-level only; project values are ignored.",
685
+ ),
686
+ document_prefix: z
687
+ .string()
688
+ .optional()
689
+ .describe(
690
+ "OpenAI-compatible stored-document prefix override, prepended verbatim. Defaults to the model-family recipe (empty for Qwen3/gte/e5 instruct; 'search_document: ' for Nomic). Changing it changes stored vectors and triggers re-embedding. User-level only; project values are ignored.",
691
+ ),
702
692
  truncate: z
703
693
  .string()
704
694
  .optional()
@@ -776,6 +766,12 @@ export const EmbeddingConfigSchema = BaseEmbeddingConfigSchema.transform((data)
776
766
  ...(apiKey ? { api_key: apiKey } : {}),
777
767
  ...(inputType ? { input_type: inputType } : {}),
778
768
  ...(queryInputType ? { query_input_type: queryInputType } : {}),
769
+ ...(data.query_instruction !== undefined
770
+ ? { query_instruction: data.query_instruction }
771
+ : {}),
772
+ ...(data.document_prefix !== undefined
773
+ ? { document_prefix: data.document_prefix }
774
+ : {}),
779
775
  ...(truncate ? { truncate } : {}),
780
776
  ...(data.max_input_tokens ? { max_input_tokens: data.max_input_tokens } : {}),
781
777
  };
@@ -809,6 +805,12 @@ export const EmbeddingConfigSchema = BaseEmbeddingConfigSchema.transform((data)
809
805
  ...(apiKey ? { api_key: apiKey } : {}),
810
806
  ...(inputType ? { input_type: inputType } : {}),
811
807
  ...(queryInputType ? { query_input_type: queryInputType } : {}),
808
+ ...(data.query_instruction !== undefined
809
+ ? { query_instruction: data.query_instruction }
810
+ : {}),
811
+ ...(data.document_prefix !== undefined
812
+ ? { document_prefix: data.document_prefix }
813
+ : {}),
812
814
  ...(truncate ? { truncate } : {}),
813
815
  ...(data.max_input_tokens ? { max_input_tokens: data.max_input_tokens } : {}),
814
816
  };
@@ -871,7 +873,8 @@ export interface MagicContextConfig {
871
873
  * this overrides `execute_threshold_percentage` for that model. Useful for hard caps
872
874
  * matching provider input limits. Values above 90% × context_limit are clamped with a warning. */
873
875
  execute_threshold_tokens?: { default?: number; [modelKey: string]: number | undefined };
874
- protected_tags: number;
876
+ protected_tokens?: number;
877
+ protected_tags?: number;
875
878
  clear_reasoning_age: number;
876
879
  history_budget_percentage: number;
877
880
  historian_timeout_ms: number;
@@ -917,10 +920,12 @@ export interface MagicContextConfig {
917
920
  * Graduated from `experimental.temporal_awareness`; default: true. */
918
921
  temporal_awareness: boolean;
919
922
  /** Debug: when true, keep the child sessions Magic Context spawns for its
920
- * own subagents (historian, dreamer, sidekick, memory-migration) instead
923
+ * own subagents (historian, dreamer, memory-migration) instead
921
924
  * of deleting them on success. For short-term inspection/data collection;
922
925
  * kept sessions accumulate until manually cleared. Default false. */
923
926
  keep_subagents: boolean;
927
+ /** Enable loopback-only diagnostic RPCs that expose memory usage and heap snapshots. */
928
+ debug_rpc?: boolean;
924
929
  /**
925
930
  * When true (default), deterministic inoperability (schema fence, storage
926
931
  * open/migration failure) blocks the primary-session transform with a loud
@@ -1011,7 +1016,6 @@ export interface MagicContextConfig {
1011
1016
  max_commits: number;
1012
1017
  };
1013
1018
  };
1014
- sidekick?: SidekickConfig;
1015
1019
  }
1016
1020
 
1017
1021
  export const MagicContextConfigSchema = z
@@ -1063,7 +1067,7 @@ export const MagicContextConfigSchema = z
1063
1067
  .describe(
1064
1068
  "Output language for Magic Context's generated content and guidance, as a " +
1065
1069
  '2-letter ISO 639-1 code (e.g. "tr", "es", "de", "ja", "pt"). When set, the ' +
1066
- "historian, dreamer, sidekick, and the agent-guidance block instruct the model to " +
1070
+ "historian, dreamer, and the agent-guidance block instruct the model to " +
1067
1071
  "write its PROSE in this language while keeping all structural tokens (XML tags, " +
1068
1072
  "the five memory category names, code identifiers, file paths) in English. " +
1069
1073
  "USER-LEVEL ONLY (ignored in project config for security). Unset = today's " +
@@ -1080,7 +1084,7 @@ export const MagicContextConfigSchema = z
1080
1084
  "Select a named user-owned model profile. A valid project name overrides this user default; an empty string, null, or other non-string project value is ignored with a warning so the user selection still applies. Unknown names warn and use the base configuration.",
1081
1085
  ),
1082
1086
  profiles: ConfigProfilesSchema.optional().describe(
1083
- "User-level named model profiles. A profile may contain only historian/dreamer model, fallback_models, OpenCode variant, and Pi/OMP thinking_level fields plus sidekick model-selection fields; task execution policy (including timeout_minutes) is excluded. Project configs may select a name but cannot define profiles.",
1087
+ "User-level named model profiles. A profile may contain only historian/dreamer model, fallback_models, OpenCode variant, and Pi/OMP thinking_level fields; task execution policy (including timeout_minutes) is excluded. Project configs may select a name but cannot define profiles.",
1084
1088
  ),
1085
1089
  historian: HistorianConfigSchema.describe(
1086
1090
  "Historian metadata plus independent strict OpenCode, Pi, and OMP execution blocks. Retained metadata stays at historian; model, fallback_models, variant, and thinking_level belong only in historian.opencode, historian.pi, or historian.omp.",
@@ -1153,14 +1157,22 @@ export const MagicContextConfigSchema = z
1153
1157
  .describe(
1154
1158
  "Absolute token thresholds per model. When matched, overrides execute_threshold_percentage for that model. Accepts `default` for all models or per-model keys. Values above 90% × context_limit are clamped with a warning log. Min 5_000, max 2_000_000.",
1155
1159
  ),
1156
- protected_tags: z
1160
+ protected_tokens: z
1157
1161
  .number()
1158
- .min(1)
1159
- .max(100)
1162
+ .int()
1163
+ .min(4000)
1164
+ .max(1_000_000)
1160
1165
  .optional()
1161
1166
  .describe(
1162
- "Number of recent tags to protect from dropping (min: 1, max: 100, default: 20)",
1167
+ "Positive integer token floor to protect from automatic reclaim (min: 4_000, max: 1_000_000). When omitted, the derived default is clamp(round(0.05 × usableSoft), min(16_000, round(0.08 × usableSoft)), 64_000).",
1163
1168
  ),
1169
+ protected_tags: z
1170
+ .unknown()
1171
+ .optional()
1172
+ .describe(
1173
+ "Deprecated: number of recent tags to protect. Ignored for behaviour; use protected_tokens instead.",
1174
+ )
1175
+ .meta({ deprecated: true }),
1164
1176
  clear_reasoning_age: z
1165
1177
  .number()
1166
1178
  .min(10)
@@ -1294,7 +1306,13 @@ export const MagicContextConfigSchema = z
1294
1306
  .boolean()
1295
1307
  .default(false)
1296
1308
  .describe(
1297
- "Debug: keep the child sessions Magic Context spawns for its own subagents (historian, dreamer, sidekick, memory-migration) instead of deleting them on success. Useful for short-term inspection/data collection — their full transcript (prompt, tool calls, token usage, output) stays in the host session store. Kept sessions accumulate until manually cleared; leave false for normal use. Requires a restart to take effect.",
1309
+ "Debug: keep the child sessions Magic Context spawns for its own subagents (historian, dreamer, memory-migration) instead of deleting them on success. Useful for short-term inspection/data collection — their full transcript (prompt, tool calls, token usage, output) stays in the host session store. Kept sessions accumulate until manually cleared; leave false for normal use. Requires a restart to take effect.",
1310
+ ),
1311
+ debug_rpc: z
1312
+ .boolean()
1313
+ .default(false)
1314
+ .describe(
1315
+ "Developer-only: enable authenticated loopback RPCs for memory counters and heap snapshots. Disabled by default. USER-LEVEL ONLY and requires a restart.",
1298
1316
  ),
1299
1317
  fail_closed_blocking: z
1300
1318
  .boolean()
@@ -1459,13 +1477,28 @@ export const MagicContextConfigSchema = z
1459
1477
  git_commit_indexing: { enabled: false, since_days: 365, max_commits: 2000 },
1460
1478
  })
1461
1479
  .describe("Cross-session memory configuration"),
1462
- sidekick: SidekickConfigSchema.describe(
1463
- "Optional sidekick agent configuration for session-start memory retrieval",
1464
- ),
1465
1480
  })
1466
1481
  .transform((data): MagicContextConfig => {
1467
1482
  return {
1468
1483
  ...data,
1469
- protected_tags: data.protected_tags ?? DEFAULT_PROTECTED_TAGS,
1484
+ protected_tags: data.protected_tags as number | undefined,
1470
1485
  };
1471
1486
  });
1487
+
1488
+ /**
1489
+ * Derived default protected_tokens formula:
1490
+ * clamp(round(0.05 × usableSoft), min(16000, round(0.08 × usableSoft)), 64000)
1491
+ *
1492
+ * Sizing table:
1493
+ * 100k -> 8,000
1494
+ * 200k -> 16,000
1495
+ * 372k -> 18,600
1496
+ * 872k -> 43,600
1497
+ * 1M -> 50,000
1498
+ */
1499
+ export function deriveDefaultProtectedTokens(usableSoft: number): number {
1500
+ const clampedUsable = Math.max(0, usableSoft);
1501
+ const lowerBound = Math.min(16_000, Math.round(0.08 * clampedUsable));
1502
+ const target = Math.round(0.05 * clampedUsable);
1503
+ return Math.min(64_000, Math.max(lowerBound, target));
1504
+ }
@@ -0,0 +1,218 @@
1
+ /// <reference types="bun-types" />
2
+
3
+ import { afterEach, describe, expect, mock, test } from "bun:test";
4
+ import { readdirSync, readFileSync } from "node:fs";
5
+ import { join, relative } from "node:path";
6
+ import ts from "typescript";
7
+
8
+ import { sweepOrphanedRetrospectiveChildren } from "../features/magic-context/dreamer/retrospective-orphan-sweep";
9
+ import { teardownChildSession } from "./child-session-teardown";
10
+ import { _resetKeepSubagentsForTesting, setKeepSubagents } from "./keep-subagents";
11
+ import { Database } from "./sqlite";
12
+ import { closeQuietly } from "./sqlite-helpers";
13
+
14
+ interface TeardownFixture {
15
+ client: {
16
+ session: {
17
+ delete: ReturnType<typeof mock>;
18
+ update: ReturnType<typeof mock>;
19
+ };
20
+ };
21
+ calls: string[];
22
+ deleted: string[];
23
+ archived: string[];
24
+ messages: string[];
25
+ }
26
+
27
+ function teardownFixture(): TeardownFixture {
28
+ const calls: string[] = [];
29
+ const deleted: string[] = [];
30
+ const archived: string[] = [];
31
+ const messages: string[] = [];
32
+ return {
33
+ calls,
34
+ deleted,
35
+ archived,
36
+ messages,
37
+ client: {
38
+ session: {
39
+ update: mock(async ({ path }: { path: { id: string } }) => {
40
+ calls.push("archive");
41
+ archived.push(path.id);
42
+ return {};
43
+ }),
44
+ delete: mock(async ({ path }: { path: { id: string } }) => {
45
+ calls.push("delete");
46
+ deleted.push(path.id);
47
+ return {};
48
+ }),
49
+ },
50
+ },
51
+ };
52
+ }
53
+
54
+ afterEach(() => {
55
+ _resetKeepSubagentsForTesting();
56
+ mock.restore();
57
+ });
58
+
59
+ describe("teardownChildSession", () => {
60
+ test("deletes an ordinary child only after its prompt settles", async () => {
61
+ const fixture = teardownFixture();
62
+ await teardownChildSession({
63
+ client: fixture.client,
64
+ sessionId: "settled-ordinary",
65
+ sessionDirectory: "/repo",
66
+ promptSettled: true,
67
+ privacySensitive: false,
68
+ context: "ordinary",
69
+ log: (message) => fixture.messages.push(message),
70
+ });
71
+
72
+ expect(fixture.deleted).toEqual(["settled-ordinary"]);
73
+ expect(fixture.archived).toEqual([]);
74
+ });
75
+
76
+ test("keeps a settled ordinary child but deletes a settled privacy child under keep_subagents", async () => {
77
+ setKeepSubagents(true);
78
+ const ordinary = teardownFixture();
79
+ await teardownChildSession({
80
+ client: ordinary.client,
81
+ sessionId: "kept-ordinary",
82
+ promptSettled: true,
83
+ privacySensitive: false,
84
+ context: "ordinary",
85
+ log: (message) => ordinary.messages.push(message),
86
+ });
87
+ expect(ordinary.deleted).toEqual([]);
88
+
89
+ const privacy = teardownFixture();
90
+ await teardownChildSession({
91
+ client: privacy.client,
92
+ sessionId: "deleted-private",
93
+ promptSettled: true,
94
+ privacySensitive: true,
95
+ context: "private",
96
+ log: (message) => privacy.messages.push(message),
97
+ });
98
+ expect(privacy.deleted).toEqual(["deleted-private"]);
99
+ });
100
+
101
+ test("archives an unsettled child before logging, leaves it intact, then the age gate reaps it", async () => {
102
+ const fixture = teardownFixture();
103
+ const db = new Database(":memory:");
104
+ db.exec(`
105
+ CREATE TABLE session (
106
+ id TEXT PRIMARY KEY,
107
+ title TEXT,
108
+ directory TEXT,
109
+ time_created INTEGER
110
+ );
111
+ INSERT INTO session VALUES (
112
+ 'unsettled-private',
113
+ 'magic-context-dream-map-memories',
114
+ '/repo',
115
+ 1
116
+ );
117
+ `);
118
+ try {
119
+ await teardownChildSession({
120
+ client: fixture.client,
121
+ sessionId: "unsettled-private",
122
+ sessionDirectory: "/repo",
123
+ promptSettled: false,
124
+ privacySensitive: true,
125
+ context: "[dreamer] map-memories",
126
+ log: (message) => {
127
+ fixture.calls.push("log");
128
+ fixture.messages.push(message);
129
+ },
130
+ });
131
+
132
+ expect(fixture.calls).toEqual(["archive", "log"]);
133
+ expect(fixture.deleted).toEqual([]);
134
+ expect(fixture.messages).toEqual([
135
+ "[dreamer] map-memories: prompt unsettled — session unsettled-private left to the age-gated sweep",
136
+ ]);
137
+ expect(
138
+ db.prepare("SELECT id FROM session WHERE id = ?").get("unsettled-private"),
139
+ ).toEqual({
140
+ id: "unsettled-private",
141
+ });
142
+
143
+ const swept = await sweepOrphanedRetrospectiveChildren({
144
+ opencodeDb: db,
145
+ client: fixture.client as never,
146
+ sessionDirectory: "/repo",
147
+ staleMs: 1_000,
148
+ now: 1_002,
149
+ });
150
+ expect(swept).toBe(1);
151
+ expect(fixture.deleted).toEqual(["unsettled-private"]);
152
+ } finally {
153
+ closeQuietly(db);
154
+ }
155
+ });
156
+ });
157
+
158
+ function productionTypeScriptFiles(directory: string): string[] {
159
+ const files: string[] = [];
160
+ for (const entry of readdirSync(directory, { withFileTypes: true })) {
161
+ const path = join(directory, entry.name);
162
+ if (entry.isDirectory()) files.push(...productionTypeScriptFiles(path));
163
+ else if (entry.name.endsWith(".ts") && !entry.name.endsWith(".test.ts")) files.push(path);
164
+ }
165
+ return files;
166
+ }
167
+
168
+ function clientSessionDeleteOffsets(path: string, source: string): number[] {
169
+ const sourceFile = ts.createSourceFile(path, source, ts.ScriptTarget.Latest, true);
170
+ const offsets: number[] = [];
171
+ const visit = (node: ts.Node): void => {
172
+ if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression)) {
173
+ const deleteAccess = node.expression;
174
+ const sessionAccess = deleteAccess.expression;
175
+ if (
176
+ deleteAccess.name.text === "delete" &&
177
+ ts.isPropertyAccessExpression(sessionAccess) &&
178
+ sessionAccess.name.text === "session" &&
179
+ (ts.isIdentifier(sessionAccess.expression)
180
+ ? sessionAccess.expression.text === "client"
181
+ : ts.isPropertyAccessExpression(sessionAccess.expression) &&
182
+ sessionAccess.expression.name.text === "client")
183
+ ) {
184
+ offsets.push(node.getStart(sourceFile));
185
+ }
186
+ }
187
+ ts.forEachChild(node, visit);
188
+ };
189
+ visit(sourceFile);
190
+ return offsets;
191
+ }
192
+
193
+ describe("child-session delete source fence", () => {
194
+ test("every client.session.delete call is the age-gated sweep or promptSettled-gated teardown", () => {
195
+ const sourceRoot = join(import.meta.dir, "..");
196
+ const sites: string[] = [];
197
+ for (const path of productionTypeScriptFiles(sourceRoot)) {
198
+ const source = readFileSync(path, "utf8");
199
+ for (const offset of clientSessionDeleteOffsets(path, source)) {
200
+ const line = source.slice(0, offset).split("\n").length;
201
+ sites.push(`${relative(sourceRoot, path)}:${line}`);
202
+ }
203
+ }
204
+
205
+ // Directory walk order differs between macOS and Linux; the fence is a set.
206
+ expect(sites.map((site) => site.replace(/:\d+$/, "")).sort()).toEqual([
207
+ "features/magic-context/dreamer/retrospective-orphan-sweep.ts",
208
+ "shared/child-session-teardown.ts",
209
+ ]);
210
+ const teardownSource = readFileSync(
211
+ join(sourceRoot, "shared/child-session-teardown.ts"),
212
+ "utf8",
213
+ );
214
+ expect(teardownSource).toMatch(
215
+ /if\s*\(\s*promptSettled[\s\S]{0,200}client\.session\.delete\s*\(/,
216
+ );
217
+ });
218
+ });
@@ -0,0 +1,66 @@
1
+ import { shouldKeepSubagents } from "./keep-subagents";
2
+
3
+ interface ChildSessionRequest {
4
+ path: { id: string };
5
+ query?: { directory: string };
6
+ }
7
+
8
+ interface ArchiveChildSessionRequest extends ChildSessionRequest {
9
+ body: { time: { archived: number } };
10
+ }
11
+
12
+ export interface ChildSessionTeardownClient {
13
+ session: {
14
+ delete(request: ChildSessionRequest): Promise<unknown>;
15
+ };
16
+ }
17
+
18
+ export interface TeardownChildSessionArgs {
19
+ client: ChildSessionTeardownClient;
20
+ sessionId: string | null;
21
+ sessionDirectory?: string;
22
+ promptSettled: boolean;
23
+ privacySensitive: boolean;
24
+ context: string;
25
+ log: (message: string) => void;
26
+ }
27
+
28
+ /**
29
+ * Retire a child only after its prompt helper resolves. An unresolved client call
30
+ * can leave OpenCode's server loop writing, so that row is archived for immediate
31
+ * UI hiding and retained until the age-gated sweep can delete it safely.
32
+ *
33
+ * OpenCode's generated v2 SDK models archival as `session.update` with
34
+ * `time.archived`; the plugin's legacy path/body client reaches the same PATCH
35
+ * endpoint, although its generated TypeScript body type does not yet expose time.
36
+ */
37
+ export async function teardownChildSession(args: TeardownChildSessionArgs): Promise<void> {
38
+ const { client, sessionId, sessionDirectory, promptSettled, privacySensitive, context, log } =
39
+ args;
40
+ if (!sessionId) return;
41
+
42
+ const request: ChildSessionRequest = {
43
+ path: { id: sessionId },
44
+ ...(sessionDirectory ? { query: { directory: sessionDirectory } } : {}),
45
+ };
46
+
47
+ if (promptSettled && (privacySensitive || !shouldKeepSubagents())) {
48
+ await client.session.delete(request).catch((error: unknown) => {
49
+ log(`${context}: session cleanup failed: ${String(error)}`);
50
+ });
51
+ return;
52
+ }
53
+
54
+ if (!promptSettled) {
55
+ const archiveSession = client.session as unknown as {
56
+ update?: (request: ArchiveChildSessionRequest) => Promise<unknown>;
57
+ };
58
+ await archiveSession
59
+ .update?.({
60
+ ...request,
61
+ body: { time: { archived: Date.now() } },
62
+ })
63
+ .catch(() => {});
64
+ log(`${context}: prompt unsettled — session ${sessionId} left to the age-gated sweep`);
65
+ }
66
+ }
@@ -1,19 +1,14 @@
1
1
  /**
2
- * Debug / data-collection switch: when enabled, Magic Context does NOT delete
3
- * the child sessions it spawns for its own subagents (historian, dreamer,
4
- * sidekick, memory-migration, key-files, user-memory review, recomp).
2
+ * Debug / data-collection switch for settled ordinary child sessions
3
+ * (historian and memory migration). Privacy-sensitive Dreamer and
4
+ * smart-note children are still deleted after their prompts settle.
5
5
  *
6
- * By default these child sessions are deleted on success (only FAILED ones are
7
- * kept for debugging). With `keep_subagents: true` ALL of them are retained, so
8
- * their full transcript — prompt, tool calls, token usage, model output — stays
9
- * inspectable in OpenCode's session store / the dashboard. Intended for
10
- * short-term data collection (e.g. profiling what the dreamer actually does)
11
- * before the dreamer v2 overhaul, NOT for steady-state use — kept sessions
12
- * accumulate in the host's session DB until manually cleared.
6
+ * Unsettled children are never deleted inline because OpenCode's server loop may
7
+ * still be writing after a client timeout or abort. They remain for the
8
+ * age-gated sweep; privacy-sensitive rows are swept even when this switch is on.
13
9
  *
14
- * Process-global, set once at boot from config (mirrors `harness.ts`). A
15
- * config change requires a restart to take effect. NEVER thread this through
16
- * per-call args — it's a coarse, boot-time debug toggle.
10
+ * Process-global, set once at boot from config (mirrors `harness.ts`). A config
11
+ * change requires a restart to take effect.
17
12
  */
18
13
  let keepSubagents = false;
19
14
 
@@ -22,7 +17,7 @@ export function setKeepSubagents(value: boolean): void {
22
17
  keepSubagents = value === true;
23
18
  }
24
19
 
25
- /** True when subagent child sessions should be retained (not deleted). */
20
+ /** True when settled ordinary child sessions should be retained. */
26
21
  export function shouldKeepSubagents(): boolean {
27
22
  return keepSubagents;
28
23
  }
@@ -71,7 +71,7 @@ export interface PromptRetryOptions {
71
71
  fallbackModels?: readonly ModelInput[];
72
72
  /**
73
73
  * Identifier for structured logging (e.g. "dreamer:consolidate",
74
- * "historian", "compressor", "sidekick"). Helps correlate fallback
74
+ * "historian", "compressor", "dreamer"). Helps correlate fallback
75
75
  * attempts to a specific call site in `magic-context.log`. Defaults to
76
76
  * "subagent" if not provided.
77
77
  */