@cortexkit/opencode-magic-context 0.40.1 → 0.41.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 (194) hide show
  1. package/README.md +1 -1
  2. package/dist/{announcement-5eg4t64s.js → announcement-3g9xg433.js} +2 -2
  3. package/dist/config/schema/magic-context.d.ts +15 -0
  4. package/dist/config/schema/magic-context.d.ts.map +1 -1
  5. package/dist/{conflict-warning-hook-f406ggbw.js → conflict-warning-hook-rf17b6et.js} +4 -4
  6. package/dist/{derive-budgets-xk8cy5e6.js → derive-budgets-bb7mrpzs.js} +3 -3
  7. package/dist/features/builtin-commands/commands.d.ts +35 -2
  8. package/dist/features/builtin-commands/commands.d.ts.map +1 -1
  9. package/dist/features/magic-context/compartment-chunk-embedding.d.ts +12 -16
  10. package/dist/features/magic-context/compartment-chunk-embedding.d.ts.map +1 -1
  11. package/dist/features/magic-context/context-authority.d.ts +10 -0
  12. package/dist/features/magic-context/context-authority.d.ts.map +1 -1
  13. package/dist/features/magic-context/dreamer/classify.d.ts +1 -0
  14. package/dist/features/magic-context/dreamer/classify.d.ts.map +1 -1
  15. package/dist/features/magic-context/dreamer/lease.d.ts +12 -27
  16. package/dist/features/magic-context/dreamer/lease.d.ts.map +1 -1
  17. package/dist/features/magic-context/dreamer/map-memories-prompt.d.ts +1 -1
  18. package/dist/features/magic-context/dreamer/map-memories-prompt.d.ts.map +1 -1
  19. package/dist/features/magic-context/dreamer/map-memories.d.ts +2 -0
  20. package/dist/features/magic-context/dreamer/map-memories.d.ts.map +1 -1
  21. package/dist/features/magic-context/dreamer/memory-claim-safety.d.ts +9 -0
  22. package/dist/features/magic-context/dreamer/memory-claim-safety.d.ts.map +1 -0
  23. package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
  24. package/dist/features/magic-context/dreamer/task-registry.d.ts +2 -0
  25. package/dist/features/magic-context/dreamer/task-registry.d.ts.map +1 -1
  26. package/dist/features/magic-context/dreamer/verify-prompt.d.ts +7 -2
  27. package/dist/features/magic-context/dreamer/verify-prompt.d.ts.map +1 -1
  28. package/dist/features/magic-context/dreamer/verify.d.ts +13 -10
  29. package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
  30. package/dist/features/magic-context/memory/embedding-failure.d.ts +1 -1
  31. package/dist/features/magic-context/memory/embedding-failure.d.ts.map +1 -1
  32. package/dist/features/magic-context/memory/embedding-local.d.ts +12 -2
  33. package/dist/features/magic-context/memory/embedding-local.d.ts.map +1 -1
  34. package/dist/features/magic-context/memory/embedding-synapse.d.ts +10 -1
  35. package/dist/features/magic-context/memory/embedding-synapse.d.ts.map +1 -1
  36. package/dist/features/magic-context/memory/embedding.d.ts.map +1 -1
  37. package/dist/features/magic-context/memory/project-identity.d.ts +4 -0
  38. package/dist/features/magic-context/memory/project-identity.d.ts.map +1 -1
  39. package/dist/features/magic-context/memory/storage-memory-verifications.d.ts +5 -1
  40. package/dist/features/magic-context/memory/storage-memory-verifications.d.ts.map +1 -1
  41. package/dist/features/magic-context/memory/storage-memory.d.ts.map +1 -1
  42. package/dist/features/magic-context/memory/transformers-web-entry.d.ts +2 -0
  43. package/dist/features/magic-context/memory/transformers-web-entry.d.ts.map +1 -0
  44. package/dist/features/magic-context/message-index.d.ts.map +1 -1
  45. package/dist/features/magic-context/migrations.d.ts.map +1 -1
  46. package/dist/features/magic-context/project-embedding-registry.d.ts +3 -0
  47. package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
  48. package/dist/features/magic-context/search.d.ts +18 -0
  49. package/dist/features/magic-context/search.d.ts.map +1 -1
  50. package/dist/features/magic-context/storage-db.d.ts +1 -1
  51. package/dist/features/magic-context/storage-db.d.ts.map +1 -1
  52. package/dist/features/magic-context/storage-identity-merge.d.ts.map +1 -1
  53. package/dist/features/magic-context/storage-meta-persisted.d.ts +29 -3
  54. package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
  55. package/dist/features/magic-context/storage-meta-session.d.ts.map +1 -1
  56. package/dist/features/magic-context/storage-meta.d.ts +1 -1
  57. package/dist/features/magic-context/storage-meta.d.ts.map +1 -1
  58. package/dist/features/magic-context/storage-ops.d.ts +2 -0
  59. package/dist/features/magic-context/storage-ops.d.ts.map +1 -1
  60. package/dist/features/magic-context/storage-tags.d.ts +7 -0
  61. package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
  62. package/dist/features/magic-context/storage.d.ts +2 -2
  63. package/dist/features/magic-context/storage.d.ts.map +1 -1
  64. package/dist/hooks/magic-context/boundary-execution.d.ts +3 -0
  65. package/dist/hooks/magic-context/boundary-execution.d.ts.map +1 -1
  66. package/dist/hooks/magic-context/channel2-delivery.d.ts +2 -4
  67. package/dist/hooks/magic-context/channel2-delivery.d.ts.map +1 -1
  68. package/dist/hooks/magic-context/command-handler.d.ts +7 -0
  69. package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
  70. package/dist/hooks/magic-context/compaction-marker-manager.d.ts.map +1 -1
  71. package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
  72. package/dist/hooks/magic-context/compartment-runner-recomp.d.ts.map +1 -1
  73. package/dist/hooks/magic-context/compartment-trigger.d.ts +1 -0
  74. package/dist/hooks/magic-context/compartment-trigger.d.ts.map +1 -1
  75. package/dist/hooks/magic-context/ctx-reduce-nudge.d.ts +15 -14
  76. package/dist/hooks/magic-context/ctx-reduce-nudge.d.ts.map +1 -1
  77. package/dist/hooks/magic-context/emergency-drop.d.ts +6 -8
  78. package/dist/hooks/magic-context/emergency-drop.d.ts.map +1 -1
  79. package/dist/hooks/magic-context/event-resolvers.d.ts +2 -2
  80. package/dist/hooks/magic-context/execute-status.d.ts +4 -1
  81. package/dist/hooks/magic-context/execute-status.d.ts.map +1 -1
  82. package/dist/hooks/magic-context/format-embed-failure.d.ts.map +1 -1
  83. package/dist/hooks/magic-context/heuristic-cleanup.d.ts +6 -0
  84. package/dist/hooks/magic-context/heuristic-cleanup.d.ts.map +1 -1
  85. package/dist/hooks/magic-context/hook-handlers.d.ts +21 -8
  86. package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
  87. package/dist/hooks/magic-context/hook.d.ts +13 -0
  88. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  89. package/dist/hooks/magic-context/inject-compartments.d.ts +6 -16
  90. package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
  91. package/dist/hooks/magic-context/maintenance-authority.d.ts +3 -0
  92. package/dist/hooks/magic-context/maintenance-authority.d.ts.map +1 -0
  93. package/dist/hooks/magic-context/module-transport.d.ts.map +1 -1
  94. package/dist/hooks/magic-context/module-wire.d.ts.map +1 -1
  95. package/dist/hooks/magic-context/protected-tail-boundary.d.ts.map +1 -1
  96. package/dist/hooks/magic-context/read-session-true-raw-tokens.d.ts +1 -0
  97. package/dist/hooks/magic-context/read-session-true-raw-tokens.d.ts.map +1 -1
  98. package/dist/hooks/magic-context/rust-mode-transform.d.ts +9 -0
  99. package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
  100. package/dist/hooks/magic-context/strip-content.d.ts +8 -0
  101. package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
  102. package/dist/hooks/magic-context/stripped-command.d.ts +19 -0
  103. package/dist/hooks/magic-context/stripped-command.d.ts.map +1 -0
  104. package/dist/hooks/magic-context/supersession-reclaim.d.ts +11 -0
  105. package/dist/hooks/magic-context/supersession-reclaim.d.ts.map +1 -1
  106. package/dist/hooks/magic-context/tag-messages.d.ts +6 -0
  107. package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
  108. package/dist/hooks/magic-context/tail-hygiene-walk.d.ts +11 -0
  109. package/dist/hooks/magic-context/tail-hygiene-walk.d.ts.map +1 -1
  110. package/dist/hooks/magic-context/transform-operations.d.ts +1 -1
  111. package/dist/hooks/magic-context/transform-operations.d.ts.map +1 -1
  112. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +8 -1
  113. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  114. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  115. package/dist/{index-mg1yx1ph.js → index-2d4kf2ve.js} +2 -2
  116. package/dist/{index-mmrhhk9a.js → index-37yzyeca.js} +36 -8
  117. package/dist/index-4x691bz5.js +369 -0
  118. package/dist/{index-3dkzzh0t.js → index-9j3tx8hy.js} +1 -1
  119. package/dist/{index-sw8gnq34.js → index-b9j85d29.js} +2 -2
  120. package/dist/{index-ehpzdy0v.js → index-d1mxrd3p.js} +7 -1
  121. package/dist/{index-x64cmpej.js → index-dh0vfghk.js} +817 -438
  122. package/dist/{index-qf20mv7e.js → index-dmvy29z0.js} +1 -1
  123. package/dist/{index-1h9t9xb5.js → index-eq9wr75c.js} +2 -2
  124. package/dist/{index-pck9vadr.js → index-vnz6jvdc.js} +1 -1
  125. package/dist/{index-rw0qrkvq.js → index-z893kjyt.js} +17 -4
  126. package/dist/{index-btj2qhmc.js → index-zwjhba2r.js} +3 -3
  127. package/dist/index.d.ts.map +1 -1
  128. package/dist/index.js +3230 -2422
  129. package/dist/{model-resolution-r9jbcz86.js → model-resolution-6w6wzw18.js} +3 -1
  130. package/dist/plugin/dream-timer.d.ts.map +1 -1
  131. package/dist/plugin/embedding-routing.d.ts.map +1 -1
  132. package/dist/plugin/hooks/create-session-hooks.d.ts +14 -0
  133. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  134. package/dist/plugin/rpc-handlers.d.ts +10 -0
  135. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  136. package/dist/{recomp-orchestrator-dtgww0f0.js → recomp-orchestrator-w7xg48e3.js} +7 -7
  137. package/dist/{safe-notification-target-tepzc2xa.js → safe-notification-target-2a8py95v.js} +3 -3
  138. package/dist/{send-session-notification-6v5b72b4.js → send-session-notification-bw7eex6w.js} +4 -4
  139. package/dist/shared/data-path.d.ts +12 -3
  140. package/dist/shared/data-path.d.ts.map +1 -1
  141. package/dist/shared/logger.d.ts.map +1 -1
  142. package/dist/shared/model-resolution.d.ts +1 -0
  143. package/dist/shared/model-resolution.d.ts.map +1 -1
  144. package/dist/shared/rpc-types.d.ts +5 -0
  145. package/dist/shared/rpc-types.d.ts.map +1 -1
  146. package/dist/shared/rust-mode-status.d.ts +3 -0
  147. package/dist/shared/rust-mode-status.d.ts.map +1 -0
  148. package/dist/shared/status-detail-text.d.ts.map +1 -1
  149. package/dist/shared/subagent-runner.d.ts +4 -0
  150. package/dist/shared/subagent-runner.d.ts.map +1 -1
  151. package/dist/shared/test-temp-dir.d.ts +40 -0
  152. package/dist/shared/test-temp-dir.d.ts.map +1 -0
  153. package/dist/shared/write-transaction-timing.d.ts +11 -0
  154. package/dist/shared/write-transaction-timing.d.ts.map +1 -0
  155. package/dist/{storage-meta-session-yvtbaw7c.js → storage-meta-session-gr4zn7sq.js} +4 -4
  156. package/dist/{task-config-a1qmj9bx.js → task-config-gv6s04fp.js} +2 -2
  157. package/dist/tools/ctx-expand/tools.d.ts.map +1 -1
  158. package/dist/tools/ctx-memory/tools.d.ts.map +1 -1
  159. package/dist/tools/ctx-search/tools.d.ts.map +1 -1
  160. package/dist/transformers-web.js +24570 -0
  161. package/dist/transformers.node-b1wa0hgx.js +28808 -0
  162. package/dist/tui/data/context-db.d.ts +10 -3
  163. package/dist/tui/data/context-db.d.ts.map +1 -1
  164. package/dist/tui-compiled/data/context-db.d.ts +10 -3
  165. package/dist/tui-compiled/data/context-db.d.ts.map +1 -1
  166. package/package.json +7 -3
  167. package/src/config/index.test.ts +47 -4
  168. package/src/config/schema/magic-context.test.ts +20 -0
  169. package/src/config/schema/magic-context.ts +8 -0
  170. package/src/features/magic-context/dreamer/task-registry.ts +2 -0
  171. package/src/shared/conflict-detector.test.ts +6 -19
  172. package/src/shared/conflict-fixer.test.ts +5 -8
  173. package/src/shared/data-path.test.ts +44 -4
  174. package/src/shared/data-path.ts +54 -11
  175. package/src/shared/logger.test.ts +145 -35
  176. package/src/shared/logger.ts +124 -6
  177. package/src/shared/model-resolution.test.ts +37 -0
  178. package/src/shared/model-resolution.ts +7 -0
  179. package/src/shared/redaction.ts +2 -2
  180. package/src/shared/rpc-types.ts +5 -0
  181. package/src/shared/rust-mode-status.ts +3 -0
  182. package/src/shared/status-detail-text.test.ts +13 -0
  183. package/src/shared/status-detail-text.ts +2 -0
  184. package/src/shared/subagent-runner.ts +4 -0
  185. package/src/shared/test-temp-dir.test.ts +57 -0
  186. package/src/shared/test-temp-dir.ts +165 -0
  187. package/src/shared/write-transaction-timing.ts +25 -0
  188. package/src/tui/data/context-db.test.ts +31 -1
  189. package/src/tui/data/context-db.ts +17 -61
  190. package/src/tui/index.tsx +36 -5
  191. package/src/tui-compiled/data/context-db.ts +17 -61
  192. package/src/tui-compiled/index.tsx +229 -191
  193. package/dist/index-8pqfcghm.js +0 -81
  194. /package/dist/{index-rpgg35ms.js → index-8sseka65.js} +0 -0
@@ -11,8 +11,15 @@ export declare function getRpcClient(): MagicContextRpcClient | null;
11
11
  export declare function closeRpc(): void;
12
12
  /** Fetch sidebar snapshot from the server via RPC. */
13
13
  export declare function loadSidebarSnapshot(sessionId: string, directory: string): Promise<SidebarSnapshot>;
14
- /** Fetch full status detail from the server via RPC. */
15
- export declare function loadStatusDetail(sessionId: string, directory: string, modelKey?: string): Promise<StatusDetail>;
14
+ export type StatusDetailResult = {
15
+ ok: true;
16
+ detail: StatusDetail;
17
+ } | {
18
+ ok: false;
19
+ error: string;
20
+ };
21
+ /** Fetch full status detail without presenting transport failure as an empty session. */
22
+ export declare function loadStatusDetail(sessionId: string, directory: string, modelKey?: string): Promise<StatusDetailResult>;
16
23
  /** Fetch embedding coverage status for `/ctx-embed` via RPC. */
17
24
  export declare function loadEmbedDetail(sessionId: string, directory: string): Promise<EmbedDetail>;
18
25
  export type CompartmentCountResult = {
@@ -23,7 +30,7 @@ export type CompartmentCountResult = {
23
30
  error: string;
24
31
  };
25
32
  /** Get compartment count without making transport failure look like a real zero. */
26
- export declare function getCompartmentCount(sessionId: string): Promise<CompartmentCountResult>;
33
+ export declare function getCompartmentCount(sessionId: string, directory?: string): Promise<CompartmentCountResult>;
27
34
  /** Send recomp request to server via RPC. */
28
35
  export declare function requestRecomp(sessionId: string): Promise<boolean>;
29
36
  /** Run `/ctx-session-upgrade` for the session (full recomp + once-per-project
@@ -1 +1 @@
1
- {"version":3,"file":"context-db.d.ts","sourceRoot":"","sources":["../../../src/tui/data/context-db.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEzF,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC;AAc3D,2DAA2D;AAC3D,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAOrD;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED;sCACsC;AACtC,wBAAgB,YAAY,IAAI,qBAAqB,GAAG,IAAI,CAE3D;AAED,+BAA+B;AAC/B,wBAAgB,QAAQ,IAAI,IAAI,CAM/B;AAwFD,sDAAsD;AACtD,wBAAsB,mBAAmB,CACrC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAClB,OAAO,CAAC,eAAe,CAAC,CA8B1B;AAED,wDAAwD;AACxD,wBAAsB,gBAAgB,CAClC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,YAAY,CAAC,CAqDvB;AAYD,gEAAgE;AAChE,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAchG;AAED,MAAM,MAAM,sBAAsB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhG,oFAAoF;AACpF,wBAAsB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAe5F;AAED,6CAA6C;AAC7C,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQvE;AAED;mFACmF;AACnF,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQxE;AAED;;iDAEiD;AACjD,wBAAsB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAUhF;AAED,gEAAgE;AAChE,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,MAAM,CAAC,CAQ3D;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAkBrE;AAED,wEAAwE;AACxE,wBAAsB,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC,CAQtD"}
1
+ {"version":3,"file":"context-db.d.ts","sourceRoot":"","sources":["../../../src/tui/data/context-db.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEzF,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC;AAK3D,2DAA2D;AAC3D,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAOrD;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED;sCACsC;AACtC,wBAAgB,YAAY,IAAI,qBAAqB,GAAG,IAAI,CAE3D;AAED,+BAA+B;AAC/B,wBAAgB,QAAQ,IAAI,IAAI,CAM/B;AAwFD,sDAAsD;AACtD,wBAAsB,mBAAmB,CACrC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAClB,OAAO,CAAC,eAAe,CAAC,CA8B1B;AAED,MAAM,MAAM,kBAAkB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnG,yFAAyF;AACzF,wBAAsB,gBAAgB,CAClC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,kBAAkB,CAAC,CAc7B;AAYD,gEAAgE;AAChE,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAchG;AAED,MAAM,MAAM,sBAAsB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhG,oFAAoF;AACpF,wBAAsB,mBAAmB,CACrC,SAAS,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,sBAAsB,CAAC,CAejC;AAED,6CAA6C;AAC7C,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQvE;AAED;mFACmF;AACnF,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQxE;AAED;;iDAEiD;AACjD,wBAAsB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAUhF;AAED,gEAAgE;AAChE,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,MAAM,CAAC,CAQ3D;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAkBrE;AAED,wEAAwE;AACxE,wBAAsB,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC,CAQtD"}
@@ -11,8 +11,15 @@ export declare function getRpcClient(): MagicContextRpcClient | null;
11
11
  export declare function closeRpc(): void;
12
12
  /** Fetch sidebar snapshot from the server via RPC. */
13
13
  export declare function loadSidebarSnapshot(sessionId: string, directory: string): Promise<SidebarSnapshot>;
14
- /** Fetch full status detail from the server via RPC. */
15
- export declare function loadStatusDetail(sessionId: string, directory: string, modelKey?: string): Promise<StatusDetail>;
14
+ export type StatusDetailResult = {
15
+ ok: true;
16
+ detail: StatusDetail;
17
+ } | {
18
+ ok: false;
19
+ error: string;
20
+ };
21
+ /** Fetch full status detail without presenting transport failure as an empty session. */
22
+ export declare function loadStatusDetail(sessionId: string, directory: string, modelKey?: string): Promise<StatusDetailResult>;
16
23
  /** Fetch embedding coverage status for `/ctx-embed` via RPC. */
17
24
  export declare function loadEmbedDetail(sessionId: string, directory: string): Promise<EmbedDetail>;
18
25
  export type CompartmentCountResult = {
@@ -23,7 +30,7 @@ export type CompartmentCountResult = {
23
30
  error: string;
24
31
  };
25
32
  /** Get compartment count without making transport failure look like a real zero. */
26
- export declare function getCompartmentCount(sessionId: string): Promise<CompartmentCountResult>;
33
+ export declare function getCompartmentCount(sessionId: string, directory?: string): Promise<CompartmentCountResult>;
27
34
  /** Send recomp request to server via RPC. */
28
35
  export declare function requestRecomp(sessionId: string): Promise<boolean>;
29
36
  /** Run `/ctx-session-upgrade` for the session (full recomp + once-per-project
@@ -1 +1 @@
1
- {"version":3,"file":"context-db.d.ts","sourceRoot":"","sources":["../../../src/tui-compiled/data/context-db.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEzF,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC;AAc3D,2DAA2D;AAC3D,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAOrD;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED;sCACsC;AACtC,wBAAgB,YAAY,IAAI,qBAAqB,GAAG,IAAI,CAE3D;AAED,+BAA+B;AAC/B,wBAAgB,QAAQ,IAAI,IAAI,CAM/B;AAwFD,sDAAsD;AACtD,wBAAsB,mBAAmB,CACrC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAClB,OAAO,CAAC,eAAe,CAAC,CA8B1B;AAED,wDAAwD;AACxD,wBAAsB,gBAAgB,CAClC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,YAAY,CAAC,CAqDvB;AAYD,gEAAgE;AAChE,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAchG;AAED,MAAM,MAAM,sBAAsB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhG,oFAAoF;AACpF,wBAAsB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAe5F;AAED,6CAA6C;AAC7C,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQvE;AAED;mFACmF;AACnF,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQxE;AAED;;iDAEiD;AACjD,wBAAsB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAUhF;AAED,gEAAgE;AAChE,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,MAAM,CAAC,CAQ3D;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAkBrE;AAED,wEAAwE;AACxE,wBAAsB,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC,CAQtD"}
1
+ {"version":3,"file":"context-db.d.ts","sourceRoot":"","sources":["../../../src/tui-compiled/data/context-db.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEzF,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC;AAK3D,2DAA2D;AAC3D,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAOrD;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED;sCACsC;AACtC,wBAAgB,YAAY,IAAI,qBAAqB,GAAG,IAAI,CAE3D;AAED,+BAA+B;AAC/B,wBAAgB,QAAQ,IAAI,IAAI,CAM/B;AAwFD,sDAAsD;AACtD,wBAAsB,mBAAmB,CACrC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAClB,OAAO,CAAC,eAAe,CAAC,CA8B1B;AAED,MAAM,MAAM,kBAAkB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnG,yFAAyF;AACzF,wBAAsB,gBAAgB,CAClC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,kBAAkB,CAAC,CAc7B;AAYD,gEAAgE;AAChE,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAchG;AAED,MAAM,MAAM,sBAAsB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhG,oFAAoF;AACpF,wBAAsB,mBAAmB,CACrC,SAAS,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,sBAAsB,CAAC,CAejC;AAED,6CAA6C;AAC7C,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQvE;AAED;mFACmF;AACnF,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQxE;AAED;;iDAEiD;AACjD,wBAAsB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAUhF;AAED,gEAAgE;AAChE,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,MAAM,CAAC,CAQ3D;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAkBrE;AAED,wEAAwE;AACxE,wBAAsB,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC,CAQtD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cortexkit/opencode-magic-context",
3
- "version": "0.40.1",
3
+ "version": "0.41.1",
4
4
  "type": "module",
5
5
  "description": "OpenCode plugin for Magic Context — cross-session memory and context management",
6
6
  "main": "dist/index.js",
@@ -35,7 +35,7 @@
35
35
  "README.md"
36
36
  ],
37
37
  "scripts": {
38
- "build": "tsc -p ../retina-local-fs/tsconfig.build.json && bun run build:tui && rm -f dist/index.js dist/*-*.js && bun build src/index.ts --outdir dist --target node --format esm --splitting --external @opencode-ai/plugin --external @huggingface/transformers --external onnxruntime-web --external bun:sqlite --external node:sqlite && tsc --emitDeclarationOnly",
38
+ "build": "tsc -p ../retina-local-fs/tsconfig.build.json && bun run build:tui && rm -f dist/index.js dist/transformers-web.js dist/*-*.js && bun build src/features/magic-context/memory/transformers-web-entry.ts --outfile dist/transformers-web.js --target browser --format esm --external onnxruntime-web && bun build src/index.ts --outdir dist --target node --format esm --splitting --external @opencode-ai/plugin --external onnxruntime-node --external onnxruntime-web --external sharp --external bun:sqlite --external node:sqlite && tsc --emitDeclarationOnly",
39
39
  "build:tui": "bun scripts/build-tui.ts",
40
40
  "check:tui-compiled": "bun run build:tui && git diff --exit-code -- src/tui-compiled && test -z \"$(git status --porcelain -- src/tui-compiled)\"",
41
41
  "typecheck": "tsc -p ../retina-local-fs/tsconfig.build.json && tsc --noEmit && tsc -p tsconfig.scripts.json",
@@ -51,7 +51,6 @@
51
51
  },
52
52
  "dependencies": {
53
53
  "@cortexkit/subc-client": "0.4.1",
54
- "@huggingface/transformers": "^4.1.0",
55
54
  "@jitl/quickjs-singlefile-cjs-release-asyncify": "0.32.0",
56
55
  "@opencode-ai/plugin": "^1.17.11",
57
56
  "@opencode-ai/sdk": "^1.17.11",
@@ -65,8 +64,13 @@
65
64
  "solid-js": "1.9.12",
66
65
  "zod": "^4.1.8"
67
66
  },
67
+ "optionalDependencies": {
68
+ "onnxruntime-node": "1.24.3",
69
+ "sharp": "^0.34.5"
70
+ },
68
71
  "devDependencies": {
69
72
  "@ai-sdk/anthropic": "3.0.82",
73
+ "@huggingface/transformers": "^4.1.0",
70
74
  "@ai-sdk/openai-compatible": "2.0.41",
71
75
  "@biomejs/biome": "^2.5.1",
72
76
  "@types/better-sqlite3": "^7.6.13",
@@ -2,9 +2,12 @@ import { describe, expect, it } from "bun:test";
2
2
  import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
3
3
  import { tmpdir } from "node:os";
4
4
  import { join } from "node:path";
5
+
5
6
  import { resolveHistorianModel } from "../shared/model-resolution";
7
+ import { createTestTempDir } from "../shared/test-temp-dir";
6
8
  import { loadPluginConfig, loadPluginConfigDetailed } from "./index";
7
9
  import { resolveConfigProfile } from "./profiles";
10
+ import { DEFAULT_LOCAL_EMBEDDING_MODEL } from "./schema/magic-context";
8
11
  import { RUST_COMPACTION_OFF_WARNING } from "./transform-mode";
9
12
 
10
13
  /**
@@ -110,6 +113,44 @@ function loadWithUserAndProjectConfig(
110
113
  }
111
114
  }
112
115
 
116
+ describe("loadPluginConfig — preload user-config isolation", () => {
117
+ it("resolves schema-default embedding config for a fixture with no config (#388)", () => {
118
+ const projectDir = mkdtempSync(join(tmpdir(), "mc-config-preload-fixture-"));
119
+ try {
120
+ // The test preload owns this default. A per-test XDG_CONFIG_HOME assignment
121
+ // still overrides it through loadWithUserConfig below.
122
+ expect(process.env.XDG_CONFIG_HOME).toContain("mc-plugin-test-xdg-pid-");
123
+ expect(loadPluginConfig(projectDir).embedding).toEqual({
124
+ provider: "local",
125
+ model: DEFAULT_LOCAL_EMBEDDING_MODEL,
126
+ local_runtime: "auto",
127
+ });
128
+ } finally {
129
+ rmSync(projectDir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 });
130
+ }
131
+ });
132
+
133
+ it("allows a test-scoped XDG_CONFIG_HOME to override the preload default", () => {
134
+ const preloadConfigHome = process.env.XDG_CONFIG_HOME;
135
+ const result = loadWithUserConfig(
136
+ JSON.stringify({
137
+ embedding: {
138
+ provider: "openai-compatible",
139
+ endpoint: "https://fixture.example/v1",
140
+ model: "fixture-model",
141
+ },
142
+ }),
143
+ );
144
+
145
+ expect(result.embedding).toMatchObject({
146
+ provider: "openai-compatible",
147
+ endpoint: "https://fixture.example/v1",
148
+ model: "fixture-model",
149
+ });
150
+ expect(process.env.XDG_CONFIG_HOME).toBe(preloadConfigHome);
151
+ });
152
+ });
153
+
113
154
  describe("loadPluginConfig — graduated mural config", () => {
114
155
  it("adopts legacy experimental.mural at the top-level and warns once", () => {
115
156
  const result = loadWithUserConfig(
@@ -655,7 +696,8 @@ describe("loadPluginConfig — legacy agent enabled migration", () => {
655
696
 
656
697
  describe("loadPluginConfig — variable expansion scope", () => {
657
698
  it("keeps {env:} and {file:} expansion enabled for user config", () => {
658
- const secretFile = join(mkdtempSync(join(tmpdir(), "mc-config-secret-")), "secret.txt");
699
+ const { dir: secretDir, cleanup } = createTestTempDir("mc-config-secret-");
700
+ const secretFile = join(secretDir, "secret.txt");
659
701
  writeFileSync(secretFile, "file-secret", "utf-8");
660
702
 
661
703
  try {
@@ -677,12 +719,13 @@ describe("loadPluginConfig — variable expansion scope", () => {
677
719
  }
678
720
  expect(result.configWarnings).toBeUndefined();
679
721
  } finally {
680
- rmSync(secretFile, { force: true });
722
+ cleanup();
681
723
  }
682
724
  });
683
725
 
684
726
  it("leaves {env:} and {file:} tokens literal in project config and warns", () => {
685
- const secretFile = join(mkdtempSync(join(tmpdir(), "mc-config-secret-")), "secret.txt");
727
+ const { dir: secretDir, cleanup } = createTestTempDir("mc-config-secret-");
728
+ const secretFile = join(secretDir, "secret.txt");
686
729
  writeFileSync(secretFile, "project-file-secret", "utf-8");
687
730
 
688
731
  try {
@@ -705,7 +748,7 @@ describe("loadPluginConfig — variable expansion scope", () => {
705
748
  expect(warnings).toContain("security reasons");
706
749
  expect(warnings).toContain("embedding.endpoint/provider");
707
750
  } finally {
708
- rmSync(secretFile, { force: true });
751
+ cleanup();
709
752
  }
710
753
  });
711
754
 
@@ -30,6 +30,7 @@ describe("MagicContextConfigSchema", () => {
30
30
  embedding: {
31
31
  provider: "local",
32
32
  model: DEFAULT_LOCAL_EMBEDDING_MODEL,
33
+ local_runtime: "auto",
33
34
  },
34
35
  memory: {
35
36
  enabled: true,
@@ -654,17 +655,35 @@ describe("MagicContextConfigSchema", () => {
654
655
  ).toThrow();
655
656
  });
656
657
 
658
+ it("defaults local embedding runtime to auto and accepts explicit overrides", () => {
659
+ expect(
660
+ MagicContextConfigSchema.parse({ embedding: { provider: "local" } }).embedding,
661
+ ).toMatchObject({ local_runtime: "auto" });
662
+ expect(
663
+ MagicContextConfigSchema.parse({
664
+ embedding: { provider: "local", local_runtime: "wasm" },
665
+ }).embedding,
666
+ ).toMatchObject({ local_runtime: "wasm" });
667
+ expect(
668
+ MagicContextConfigSchema.safeParse({
669
+ embedding: { provider: "local", local_runtime: "unsafe" },
670
+ }).success,
671
+ ).toBe(false);
672
+ });
673
+
657
674
  it("accepts a configured local embedding dtype", () => {
658
675
  const result = MagicContextConfigSchema.parse({
659
676
  embedding: {
660
677
  provider: "local",
661
678
  model: "Xenova/paraphrase-multilingual-MiniLM-L12-v2",
679
+ local_runtime: "auto",
662
680
  local_dtype: "q8",
663
681
  },
664
682
  });
665
683
  expect(result.embedding).toEqual({
666
684
  provider: "local",
667
685
  model: "Xenova/paraphrase-multilingual-MiniLM-L12-v2",
686
+ local_runtime: "auto",
668
687
  local_dtype: "q8",
669
688
  });
670
689
  });
@@ -676,6 +695,7 @@ describe("MagicContextConfigSchema", () => {
676
695
  expect(result.embedding).toEqual({
677
696
  provider: "local",
678
697
  model: DEFAULT_LOCAL_EMBEDDING_MODEL,
698
+ local_runtime: "auto",
679
699
  });
680
700
  expect("local_dtype" in result.embedding).toBe(false);
681
701
  });
@@ -619,6 +619,12 @@ const BaseEmbeddingConfigSchema = z
619
619
  .describe(
620
620
  "Optional maximum input tokens for chunk embeddings. Defaults conservatively to 512 when omitted.",
621
621
  ),
622
+ local_runtime: z
623
+ .enum(["auto", "native", "wasm"])
624
+ .default("auto")
625
+ .describe(
626
+ "Local provider only: ONNX runtime selection. 'auto' uses native under Node and uses WASM under Bun versions before 1.4.0, where Bun's NAPI teardown race can panic on quit; native is restored automatically on Bun 1.4.0+. Set 'native' only to prefer speed while accepting that pre-1.4.0 Bun crash risk, or 'wasm' to avoid loading the native addon.",
627
+ ),
622
628
  local_dtype: z
623
629
  .enum([
624
630
  "auto",
@@ -685,6 +691,7 @@ export const EmbeddingConfigSchema = BaseEmbeddingConfigSchema.transform((data)
685
691
  return {
686
692
  provider: "local" as const,
687
693
  model: data.model?.trim() || DEFAULT_LOCAL_EMBEDDING_MODEL,
694
+ local_runtime: data.local_runtime,
688
695
  ...(data.max_input_tokens ? { max_input_tokens: data.max_input_tokens } : {}),
689
696
  // local_dtype is spread CONDITIONALLY: omitting it when unset keeps
690
697
  // the identity byte-identical for the common no-dtype config, so
@@ -1161,6 +1168,7 @@ export const MagicContextConfigSchema = z
1161
1168
  embedding: EmbeddingConfigSchema.default({
1162
1169
  provider: "local",
1163
1170
  model: DEFAULT_LOCAL_EMBEDDING_MODEL,
1171
+ local_runtime: "auto",
1164
1172
  }).describe("Embedding provider configuration"),
1165
1173
  subc: z
1166
1174
  .object({
@@ -58,6 +58,8 @@ export interface DreamTaskProgress {
58
58
  processed: number;
59
59
  total: number;
60
60
  startedAt: number;
61
+ /** Update/archive verdicts refused by host-side verification safety gates during the current run. */
62
+ refused?: number;
61
63
  }
62
64
 
63
65
  /** Persisted per-task run counts used by dream-run history and summaries. */
@@ -1,10 +1,11 @@
1
1
  /// <reference types="bun-types" />
2
2
 
3
3
  import { afterEach, beforeEach, describe, expect, it } from "bun:test";
4
- import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
5
- import { tmpdir } from "node:os";
4
+ import { mkdirSync, writeFileSync } from "node:fs";
6
5
  import { join } from "node:path";
6
+
7
7
  import { detectConflicts, resolveCompactionForBoot } from "./conflict-detector";
8
+ import { cleanupTestTempDir, createTestTempDir } from "./test-temp-dir";
8
9
 
9
10
  /**
10
11
  * Regression tests for plugin-conflict detection. The previous substring-
@@ -13,13 +14,14 @@ import { detectConflicts, resolveCompactionForBoot } from "./conflict-detector";
13
14
  * a false-positive conflict warning. See issue #43.
14
15
  */
15
16
  describe("detectConflicts", () => {
17
+ let root: string;
16
18
  let projectDir: string;
17
19
  let userConfigDir: string;
18
20
  let homeDir: string;
19
21
  let originalEnv: Record<string, string | undefined>;
20
22
 
21
23
  beforeEach(() => {
22
- const root = mkdtempSync(join(tmpdir(), "mc-conflict-"));
24
+ root = createTestTempDir("mc-conflict-").dir;
23
25
  projectDir = join(root, "project");
24
26
  mkdirSync(projectDir, { recursive: true });
25
27
  userConfigDir = join(root, "user-config", "opencode");
@@ -50,22 +52,7 @@ describe("detectConflicts", () => {
50
52
  if (v === undefined) delete process.env[k];
51
53
  else process.env[k] = v;
52
54
  }
53
- // Test directories live under tmpdir(); cleanup is best-effort.
54
- try {
55
- rmSync(projectDir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 });
56
- } catch {
57
- /* Ignore EBUSY on Windows */
58
- }
59
- try {
60
- rmSync(userConfigDir, {
61
- recursive: true,
62
- force: true,
63
- maxRetries: 10,
64
- retryDelay: 100,
65
- });
66
- } catch {
67
- /* Ignore EBUSY on Windows */
68
- }
55
+ cleanupTestTempDir(root);
69
56
  });
70
57
 
71
58
  function writeProjectConfig(plugins: Array<string | [string, unknown]>): void {
@@ -1,12 +1,13 @@
1
1
  /// <reference types="bun-types" />
2
2
 
3
3
  import { afterEach, beforeEach, describe, expect, it } from "bun:test";
4
- import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
5
- import { tmpdir } from "node:os";
4
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
6
5
  import { join } from "node:path";
7
6
  import { parse as parseJsonc } from "comment-json";
7
+
8
8
  import { detectConflicts } from "./conflict-detector";
9
9
  import { fixConflicts } from "./conflict-fixer";
10
+ import { cleanupTestTempDir, createTestTempDir } from "./test-temp-dir";
10
11
 
11
12
  const noOmoConflicts = {
12
13
  omoPreemptiveCompaction: false,
@@ -22,7 +23,7 @@ describe("fixConflicts", () => {
22
23
  let originalEnv: Record<string, string | undefined>;
23
24
 
24
25
  beforeEach(() => {
25
- root = mkdtempSync(join(tmpdir(), "mc-conflict-fixer-"));
26
+ root = createTestTempDir("mc-conflict-fixer-").dir;
26
27
  projectDir = join(root, "project");
27
28
  userConfigDir = join(root, "user-config", "opencode");
28
29
  homeDir = join(root, "home");
@@ -44,11 +45,7 @@ describe("fixConflicts", () => {
44
45
  if (value === undefined) delete process.env[key];
45
46
  else process.env[key] = value;
46
47
  }
47
- try {
48
- rmSync(root, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 });
49
- } catch {
50
- /* Ignore EBUSY on Windows */
51
- }
48
+ cleanupTestTempDir(root);
52
49
  });
53
50
 
54
51
  it("preserves JSONC comments and tuple plugin entries while removing canonical DCP", () => {
@@ -9,6 +9,7 @@ import {
9
9
  getLegacyOpenCodeMagicContextStorageDir,
10
10
  getMagicContextLogPath,
11
11
  getMagicContextStorageDir,
12
+ getMagicContextStorageResolution,
12
13
  getOpenCodeCacheDir,
13
14
  getOpenCodeStorageDir,
14
15
  getProjectMagicContextDir,
@@ -18,6 +19,7 @@ import {
18
19
  const savedEnv = {
19
20
  XDG_CACHE_HOME: process.env.XDG_CACHE_HOME,
20
21
  XDG_DATA_HOME: process.env.XDG_DATA_HOME,
22
+ MAGIC_CONTEXT_STORAGE_DIR: process.env.MAGIC_CONTEXT_STORAGE_DIR,
21
23
  LOCALAPPDATA: process.env.LOCALAPPDATA,
22
24
  MAGIC_CONTEXT_LOG_PATH: process.env.MAGIC_CONTEXT_LOG_PATH,
23
25
  MAGIC_CONTEXT_TEST_DATA_DIR: process.env.MAGIC_CONTEXT_TEST_DATA_DIR,
@@ -28,11 +30,14 @@ describe("data-path", () => {
28
30
  beforeEach(() => {
29
31
  process.env.XDG_CACHE_HOME = undefined;
30
32
  process.env.XDG_DATA_HOME = undefined;
33
+ delete process.env.MAGIC_CONTEXT_TEST_DATA_DIR;
34
+ delete process.env.NODE_ENV;
31
35
  process.env.LOCALAPPDATA = undefined;
32
36
  process.env.MAGIC_CONTEXT_LOG_PATH = undefined;
33
37
  // Bun's env handling: explicit delete for unset
34
38
  delete process.env.XDG_CACHE_HOME;
35
39
  delete process.env.XDG_DATA_HOME;
40
+ delete process.env.MAGIC_CONTEXT_STORAGE_DIR;
36
41
  delete process.env.LOCALAPPDATA;
37
42
  delete process.env.MAGIC_CONTEXT_LOG_PATH;
38
43
  });
@@ -140,17 +145,52 @@ describe("data-path", () => {
140
145
  );
141
146
  });
142
147
 
143
- test("getMagicContextStorageDir prefers XDG_DATA_HOME over MAGIC_CONTEXT_TEST_DATA_DIR", () => {
144
- // A test managing its own per-test data home is already controlled, and
145
- // several suites depend on that dir being honored.
148
+ test("test storage isolation takes precedence over MAGIC_CONTEXT_STORAGE_DIR", () => {
149
+ process.env.MAGIC_CONTEXT_TEST_DATA_DIR = "/tmp/mc-test-isolation";
150
+ process.env.MAGIC_CONTEXT_STORAGE_DIR = "/tmp/production-shared-data";
151
+ expect(getMagicContextStorageDir()).toBe(
152
+ path.join("/tmp/mc-test-isolation", "cortexkit", "magic-context"),
153
+ );
154
+ });
155
+
156
+ test("a per-test XDG_DATA_HOME overrides the preload root without escaping test isolation", () => {
146
157
  process.env.MAGIC_CONTEXT_TEST_DATA_DIR = "/tmp/mc-test-isolation";
158
+ process.env.XDG_DATA_HOME = "/tmp/custom-test-data";
159
+ process.env.MAGIC_CONTEXT_STORAGE_DIR = "/tmp/production-shared-data";
160
+ expect(getMagicContextStorageResolution()).toEqual({
161
+ path: path.join("/tmp/custom-test-data", "cortexkit", "magic-context"),
162
+ source: "test isolation",
163
+ });
164
+ });
165
+
166
+ test("getMagicContextStorageDir honors XDG_DATA_HOME", () => {
147
167
  process.env.XDG_DATA_HOME = "/tmp/custom-data";
148
168
  expect(getMagicContextStorageDir()).toBe(
149
169
  path.join("/tmp/custom-data", "cortexkit", "magic-context"),
150
170
  );
151
171
  });
152
172
 
153
- test("getMagicContextStorageDir honors XDG_DATA_HOME", () => {
173
+ test("getMagicContextStorageDir honors MAGIC_CONTEXT_STORAGE_DIR", () => {
174
+ process.env.XDG_DATA_HOME = "/tmp/private-agent-data";
175
+ process.env.MAGIC_CONTEXT_STORAGE_DIR = "/tmp/shared-magic-context";
176
+ expect(getMagicContextStorageDir()).toBe("/tmp/shared-magic-context");
177
+ });
178
+
179
+ test("MAGIC_CONTEXT_STORAGE_DIR takes precedence over XDG_DATA_HOME", () => {
180
+ process.env.XDG_DATA_HOME = "/tmp/private-agent-data";
181
+ process.env.MAGIC_CONTEXT_STORAGE_DIR = "/tmp/shared-magic-context";
182
+ expect(getMagicContextStorageDir()).toBe("/tmp/shared-magic-context");
183
+ });
184
+
185
+ test("relative MAGIC_CONTEXT_STORAGE_DIR is rejected", () => {
186
+ process.env.MAGIC_CONTEXT_STORAGE_DIR = "./shared-magic-context";
187
+ expect(() => getMagicContextStorageDir()).toThrow(
188
+ "MAGIC_CONTEXT_STORAGE_DIR must be an absolute path",
189
+ );
190
+ });
191
+
192
+ test("blank MAGIC_CONTEXT_STORAGE_DIR falls back to XDG_DATA_HOME", () => {
193
+ process.env.MAGIC_CONTEXT_STORAGE_DIR = " ";
154
194
  process.env.XDG_DATA_HOME = "/tmp/custom-data";
155
195
  expect(getMagicContextStorageDir()).toBe(
156
196
  path.join("/tmp/custom-data", "cortexkit", "magic-context"),
@@ -166,7 +166,9 @@ export function getOpenCodeStorageDir(): string {
166
166
  * - Shared Dreamer runs (one per project per machine)
167
167
  * - Future cross-harness session migration
168
168
  *
169
- * Layout: <XDG_DATA_HOME>/cortexkit/magic-context/
169
+ * Resolution precedence: test isolation, MAGIC_CONTEXT_STORAGE_DIR, XDG data
170
+ * home, then the platform default. The explicit override is a complete storage
171
+ * directory and must be absolute so every process on a host selects one store.
170
172
  *
171
173
  * TEST-ISOLATION GUARD. `openDatabase()` has been guarded in
172
174
  * `resolveDatabasePath()` since the 2026-06-01 (v26) and 2026-06-19 (v41)
@@ -192,20 +194,61 @@ export function getOpenCodeStorageDir(): string {
192
194
  * `PRAGMA integrity_check`, announcements, the models.dev cache) are covered
193
195
  * too — they never go through the DB resolver.
194
196
  *
195
- * XDG_DATA_HOME still wins over both: a test that manages its own data home is
196
- * already controlled, and production has no test dir set at all.
197
+ * In production, MAGIC_CONTEXT_STORAGE_DIR takes precedence over XDG_DATA_HOME.
198
+ * Test isolation remains authoritative so an ambient override cannot redirect
199
+ * a test into a user's real shared database.
197
200
  */
198
- export function getMagicContextStorageDir(): string {
199
- if (!process.env.XDG_DATA_HOME) {
200
- const testDataDir = process.env.MAGIC_CONTEXT_TEST_DATA_DIR;
201
- if (testDataDir) {
202
- return path.join(testDataDir, "cortexkit", "magic-context");
201
+ export type MagicContextStorageSource =
202
+ | "test isolation"
203
+ | "environment override"
204
+ | "XDG_DATA_HOME"
205
+ | "platform default";
206
+
207
+ export interface MagicContextStorageResolution {
208
+ path: string;
209
+ source: MagicContextStorageSource;
210
+ }
211
+
212
+ export function getMagicContextStorageResolution(): MagicContextStorageResolution {
213
+ const testDataDir = process.env.MAGIC_CONTEXT_TEST_DATA_DIR?.trim();
214
+ if (testDataDir) {
215
+ const perTestDataHome = process.env.XDG_DATA_HOME?.trim();
216
+ if (perTestDataHome && path.resolve(perTestDataHome) !== path.resolve(testDataDir)) {
217
+ return {
218
+ path: path.join(perTestDataHome, "cortexkit", "magic-context"),
219
+ source: "test isolation",
220
+ };
203
221
  }
204
- if (process.env.NODE_ENV === "test") {
205
- return getTestBackstopStorageDir();
222
+ return {
223
+ path: path.join(testDataDir, "cortexkit", "magic-context"),
224
+ source: "test isolation",
225
+ };
226
+ }
227
+ if (process.env.NODE_ENV === "test") {
228
+ return { path: getTestBackstopStorageDir(), source: "test isolation" };
229
+ }
230
+ const explicitStorageDir = process.env.MAGIC_CONTEXT_STORAGE_DIR?.trim();
231
+ if (explicitStorageDir) {
232
+ if (!path.isAbsolute(explicitStorageDir)) {
233
+ throw new Error("MAGIC_CONTEXT_STORAGE_DIR must be an absolute path");
206
234
  }
235
+ return { path: explicitStorageDir, source: "environment override" };
236
+ }
237
+ const xdgDataHome = process.env.XDG_DATA_HOME?.trim();
238
+ if (xdgDataHome) {
239
+ return {
240
+ path: path.join(xdgDataHome, "cortexkit", "magic-context"),
241
+ source: "XDG_DATA_HOME",
242
+ };
207
243
  }
208
- return path.join(getDataDir(), "cortexkit", "magic-context");
244
+ return {
245
+ path: path.join(os.homedir(), ".local", "share", "cortexkit", "magic-context"),
246
+ source: "platform default",
247
+ };
248
+ }
249
+
250
+ export function getMagicContextStorageDir(): string {
251
+ return getMagicContextStorageResolution().path;
209
252
  }
210
253
 
211
254
  let testBackstopStorageDir: string | null = null;