@cortexkit/opencode-magic-context 0.48.0 → 0.49.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 (304) hide show
  1. package/dist/{announcement-fp14dw0n.js → announcement-hdbkt8v5.js} +1 -1
  2. package/dist/auto-search-worker.js +3 -3
  3. package/dist/config/{mural-model-deprecation.d.ts → deprecated-config.d.ts} +4 -1
  4. package/dist/config/deprecated-config.d.ts.map +1 -0
  5. package/dist/config/index.d.ts.map +1 -1
  6. package/dist/config/project-security.d.ts +2 -2
  7. package/dist/config/schema/magic-context.d.ts +4 -4
  8. package/dist/config/schema/magic-context.d.ts.map +1 -1
  9. package/dist/{conflict-warning-hook-w8cykrnf.js → conflict-warning-hook-asnt6hfc.js} +7 -7
  10. package/dist/{context-m0cy262m.js → context-tfyhtdcs.js} +187 -68
  11. package/dist/{derive-budgets-sg0xsq7s.js → derive-budgets-j4ry8j8n.js} +2 -2
  12. package/dist/embedding-backfill-wyc3ykyf.js +21 -0
  13. package/dist/embedding-worker-process.js +30 -0
  14. package/dist/embedding-worker.js +6 -6
  15. package/dist/features/magic-context/dreamer/task-registry.d.ts +2 -3
  16. package/dist/features/magic-context/dreamer/task-registry.d.ts.map +1 -1
  17. package/dist/features/magic-context/git-commits/search-git-commits.d.ts +2 -0
  18. package/dist/features/magic-context/git-commits/search-git-commits.d.ts.map +1 -1
  19. package/dist/features/magic-context/memory/embedding-worker-client.d.ts +8 -1
  20. package/dist/features/magic-context/memory/embedding-worker-client.d.ts.map +1 -1
  21. package/dist/features/magic-context/memory/embedding-worker-process.d.ts +2 -0
  22. package/dist/features/magic-context/memory/embedding-worker-process.d.ts.map +1 -0
  23. package/dist/features/magic-context/memory/onnx-telemetry.d.ts +3 -0
  24. package/dist/features/magic-context/memory/onnx-telemetry.d.ts.map +1 -0
  25. package/dist/features/magic-context/message-index.d.ts.map +1 -1
  26. package/dist/features/magic-context/overflow-detection.d.ts +1 -2
  27. package/dist/features/magic-context/overflow-detection.d.ts.map +1 -1
  28. package/dist/features/magic-context/pi-content-decisions.d.ts +1 -1
  29. package/dist/features/magic-context/pi-content-decisions.d.ts.map +1 -1
  30. package/dist/features/magic-context/search-rerank.d.ts +35 -0
  31. package/dist/features/magic-context/search-rerank.d.ts.map +1 -0
  32. package/dist/features/magic-context/search.d.ts +11 -0
  33. package/dist/features/magic-context/search.d.ts.map +1 -1
  34. package/dist/features/magic-context/storage-meta-persisted.d.ts +13 -2
  35. package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
  36. package/dist/features/magic-context/storage-meta-session.d.ts +1 -1
  37. package/dist/features/magic-context/storage-meta-session.d.ts.map +1 -1
  38. package/dist/features/magic-context/storage-meta.d.ts +1 -1
  39. package/dist/features/magic-context/storage-meta.d.ts.map +1 -1
  40. package/dist/features/magic-context/storage-session-tables.d.ts +2 -0
  41. package/dist/features/magic-context/storage-session-tables.d.ts.map +1 -1
  42. package/dist/features/magic-context/storage-tag-identity-revision.d.ts +29 -9
  43. package/dist/features/magic-context/storage-tag-identity-revision.d.ts.map +1 -1
  44. package/dist/features/magic-context/storage-tags.d.ts +9 -0
  45. package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
  46. package/dist/features/magic-context/storage.d.ts +1 -1
  47. package/dist/features/magic-context/storage.d.ts.map +1 -1
  48. package/dist/features/magic-context/tagger.d.ts +2 -0
  49. package/dist/features/magic-context/tagger.d.ts.map +1 -1
  50. package/dist/features/magic-context/transform-decision-log.d.ts +4 -1
  51. package/dist/features/magic-context/transform-decision-log.d.ts.map +1 -1
  52. package/dist/features/magic-context/user-memory/storage-user-memory.d.ts +1 -0
  53. package/dist/features/magic-context/user-memory/storage-user-memory.d.ts.map +1 -1
  54. package/dist/hooks/magic-context/auto-search-deadline.d.ts.map +1 -1
  55. package/dist/hooks/magic-context/auto-search-replay.fixture.d.ts +24 -0
  56. package/dist/hooks/magic-context/auto-search-replay.fixture.d.ts.map +1 -0
  57. package/dist/hooks/magic-context/auto-search-runner.d.ts +1 -1
  58. package/dist/hooks/magic-context/auto-search-runner.d.ts.map +1 -1
  59. package/dist/hooks/magic-context/auto-search-worker-client.d.ts +2 -0
  60. package/dist/hooks/magic-context/auto-search-worker-client.d.ts.map +1 -1
  61. package/dist/hooks/magic-context/command-handler.d.ts +2 -0
  62. package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
  63. package/dist/hooks/magic-context/emergency-fail-closed.d.ts +28 -0
  64. package/dist/hooks/magic-context/emergency-fail-closed.d.ts.map +1 -1
  65. package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
  66. package/dist/hooks/magic-context/final-wire-token-estimate.d.ts +1 -0
  67. package/dist/hooks/magic-context/final-wire-token-estimate.d.ts.map +1 -1
  68. package/dist/hooks/magic-context/historian-host-runner.d.ts +8 -0
  69. package/dist/hooks/magic-context/historian-host-runner.d.ts.map +1 -1
  70. package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
  71. package/dist/hooks/magic-context/hook.d.ts +3 -1
  72. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  73. package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
  74. package/dist/hooks/magic-context/latest-thinking-recovery.d.ts +7 -0
  75. package/dist/hooks/magic-context/latest-thinking-recovery.d.ts.map +1 -1
  76. package/dist/hooks/magic-context/lkg-measured-request.d.ts +3 -1
  77. package/dist/hooks/magic-context/lkg-measured-request.d.ts.map +1 -1
  78. package/dist/hooks/magic-context/lkg-persist.d.ts +8 -14
  79. package/dist/hooks/magic-context/lkg-persist.d.ts.map +1 -1
  80. package/dist/hooks/magic-context/lkg-recovery-fence.d.ts +62 -0
  81. package/dist/hooks/magic-context/lkg-recovery-fence.d.ts.map +1 -0
  82. package/dist/hooks/magic-context/lkg-recovery-prefix.d.ts +38 -0
  83. package/dist/hooks/magic-context/lkg-recovery-prefix.d.ts.map +1 -0
  84. package/dist/hooks/magic-context/lkg-replay.d.ts +3 -1
  85. package/dist/hooks/magic-context/lkg-replay.d.ts.map +1 -1
  86. package/dist/hooks/magic-context/lkg-slot.d.ts.map +1 -1
  87. package/dist/hooks/magic-context/opaque-thinking.d.ts +12 -0
  88. package/dist/hooks/magic-context/opaque-thinking.d.ts.map +1 -0
  89. package/dist/hooks/magic-context/pass-outcome.d.ts +3 -2
  90. package/dist/hooks/magic-context/pass-outcome.d.ts.map +1 -1
  91. package/dist/hooks/magic-context/pending-materialization.d.ts +8 -0
  92. package/dist/hooks/magic-context/pending-materialization.d.ts.map +1 -0
  93. package/dist/hooks/magic-context/read-session-chunk.d.ts +7 -1
  94. package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
  95. package/dist/hooks/magic-context/read-session-db.d.ts +3 -0
  96. package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
  97. package/dist/hooks/magic-context/read-session-raw.d.ts +35 -0
  98. package/dist/hooks/magic-context/read-session-raw.d.ts.map +1 -1
  99. package/dist/hooks/magic-context/recomp-orchestrator.d.ts.map +1 -1
  100. package/dist/hooks/magic-context/rust-mode-transform.d.ts +37 -0
  101. package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
  102. package/dist/hooks/magic-context/shared-compartment-boundaries.d.ts +8 -1
  103. package/dist/hooks/magic-context/shared-compartment-boundaries.d.ts.map +1 -1
  104. package/dist/hooks/magic-context/strict-thinking-prefix.d.ts +8 -0
  105. package/dist/hooks/magic-context/strict-thinking-prefix.d.ts.map +1 -0
  106. package/dist/hooks/magic-context/strip-content.d.ts +5 -2
  107. package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
  108. package/dist/hooks/magic-context/system-date-refresh.d.ts +29 -0
  109. package/dist/hooks/magic-context/system-date-refresh.d.ts.map +1 -0
  110. package/dist/hooks/magic-context/system-prompt-dates.d.ts +6 -0
  111. package/dist/hooks/magic-context/system-prompt-dates.d.ts.map +1 -0
  112. package/dist/hooks/magic-context/system-prompt-delivery.d.ts +47 -0
  113. package/dist/hooks/magic-context/system-prompt-delivery.d.ts.map +1 -0
  114. package/dist/hooks/magic-context/system-prompt-hash.d.ts +4 -0
  115. package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
  116. package/dist/hooks/magic-context/tag-messages.d.ts +8 -0
  117. package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
  118. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +15 -0
  119. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  120. package/dist/hooks/magic-context/transform.d.ts +7 -0
  121. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  122. package/dist/{index-ty64eqcn.js → index-0pjvpfkf.js} +24 -4
  123. package/dist/{index-db7zwa3v.js → index-1bt88epp.js} +93 -9
  124. package/dist/{index-2y0s2hep.js → index-4mjhqadz.js} +1 -1
  125. package/dist/index-6m7rdv7y.js +733 -0
  126. package/dist/{index-k1xb52kd.js → index-6tfxmc4n.js} +11 -11
  127. package/dist/{index-fbv1dn35.js → index-7w18gg78.js} +26 -2
  128. package/dist/{index-7mx8v0pw.js → index-att4bfan.js} +4 -4
  129. package/dist/{index-mmyh6d8f.js → index-eypn4ba6.js} +11 -6
  130. package/dist/{index-q2tqeqde.js → index-fdtkt5r1.js} +1229 -78
  131. package/dist/{index-c43kr12f.js → index-fg00p1cg.js} +42 -40
  132. package/dist/{v2/server-1bc61ans.js → index-fvnzcnww.js} +44 -1
  133. package/dist/index-gbmqa9x9.js +1170 -0
  134. package/dist/{index-knh4y330.js → index-gzky5rva.js} +31 -49
  135. package/dist/{index-0qhce371.js → index-h2wc01qk.js} +2 -2
  136. package/dist/{index-dhwzyd54.js → index-h5zfkjyk.js} +160 -25
  137. package/dist/{index-bhvjj0ys.js → index-k6xvbj2e.js} +255 -1075
  138. package/dist/{index-0w56v4fm.js → index-mw7c950g.js} +1 -1
  139. package/dist/{index-8j7gqj40.js → index-nsjyysj0.js} +6 -2
  140. package/dist/{index-k9nnwad5.js → index-nydv6g8r.js} +44 -7
  141. package/dist/{index-f0h6xwqm.js → index-p0n5ryq8.js} +304 -960
  142. package/dist/{index-pg50n748.js → index-p1hnwfd8.js} +4 -4
  143. package/dist/{index-1qb0z7wa.js → index-qx53vezw.js} +1 -1
  144. package/dist/{index-5zygecde.js → index-r2zcs71c.js} +8 -6
  145. package/dist/{index-cb7emxgj.js → index-rafsaxac.js} +336 -6
  146. package/dist/{index-z8e0psj8.js → index-s7fc0fkn.js} +3 -3
  147. package/dist/{index-14cjxt20.js → index-sfhndpcb.js} +505 -11
  148. package/dist/index-sv0bb7vg.js +6972 -0
  149. package/dist/{index-jcbd3znx.js → index-tqf7yg27.js} +1 -1
  150. package/dist/{index-72nhv486.js → index-vkbqdnkj.js} +2 -2
  151. package/dist/{index-pdecwzrd.js → index-w23dh319.js} +18 -259
  152. package/dist/{index-yq8n9qcb.js → index-xgrwmj82.js} +4 -4
  153. package/dist/{index-0an7742d.js → index-xnanvj3w.js} +1364 -2278
  154. package/dist/{index-eeezr5zz.js → index-z1tjp257.js} +1 -1
  155. package/dist/{index-692jzy0p.js → index-zfzdpeq2.js} +2279 -4061
  156. package/dist/{index-q7h7csab.js → index-zg8yq4ya.js} +34 -749
  157. package/dist/index.d.ts.map +1 -1
  158. package/dist/index.js +241 -76
  159. package/dist/{logger-d3wex3dz.js → logger-ewak5q1s.js} +1 -1
  160. package/dist/{message-index-bounded-7ezbgddp.js → message-index-bounded-hqktkhdy.js} +15 -14
  161. package/dist/{message-time-backfill-brbd63hv.js → message-time-backfill-8x06r9kx.js} +2 -2
  162. package/dist/migration-worker.js +11 -10
  163. package/dist/plugin/hooks/create-session-hooks.d.ts +5 -1
  164. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  165. package/dist/plugin/messages-transform.d.ts.map +1 -1
  166. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  167. package/dist/plugin/tool-registry.d.ts.map +1 -1
  168. package/dist/{project-embedding-registry-7qzptcw7.js → project-embedding-registry-0gv3h6y8.js} +10 -10
  169. package/dist/raw-ordinal-warmup-worker.js +4 -4
  170. package/dist/{read-session-chunk-6k83m4fj.js → read-session-chunk-5mh0bh8y.js} +12 -9
  171. package/dist/{read-session-raw-3g9qy1xa.js → read-session-raw-8sjbc9h0.js} +5 -3
  172. package/dist/{recomp-orchestrator-d3fp1cy0.js → recomp-orchestrator-kpkhkjhq.js} +28 -27
  173. package/dist/{safe-notification-target-5ffqq32m.js → safe-notification-target-q0cyrx3x.js} +2 -2
  174. package/dist/{search-epax1ecv.js → search-p9w39qv4.js} +22 -21
  175. package/dist/{send-session-notification-erecz4y4.js → send-session-notification-xffh3bbe.js} +5 -5
  176. package/dist/shared/auto-search-lifecycle.d.ts +14 -0
  177. package/dist/shared/auto-search-lifecycle.d.ts.map +1 -1
  178. package/dist/shared/logger.d.ts.map +1 -1
  179. package/dist/shared/models-dev-cache.d.ts.map +1 -1
  180. package/dist/shared/models-dev-temperature.d.ts +18 -0
  181. package/dist/shared/models-dev-temperature.d.ts.map +1 -0
  182. package/dist/shared/project-directory-key.d.ts +16 -0
  183. package/dist/shared/project-directory-key.d.ts.map +1 -1
  184. package/dist/shared/storage-file-mutex.d.ts +9 -0
  185. package/dist/shared/storage-file-mutex.d.ts.map +1 -0
  186. package/dist/shared/storage-permissions.d.ts +6 -0
  187. package/dist/shared/storage-permissions.d.ts.map +1 -1
  188. package/dist/shared/subagent-temperature.d.ts +46 -0
  189. package/dist/shared/subagent-temperature.d.ts.map +1 -0
  190. package/dist/shared/window-geometry.d.ts +9 -66
  191. package/dist/shared/window-geometry.d.ts.map +1 -1
  192. package/dist/standalone-plugin-marker.d.ts +8 -0
  193. package/dist/standalone-plugin-marker.d.ts.map +1 -0
  194. package/dist/{storage-tags-d3b0v2ss.js → storage-tags-k0pda32s.js} +6 -4
  195. package/dist/tools/ctx-reduce/constants.d.ts +1 -2
  196. package/dist/tools/ctx-reduce/constants.d.ts.map +1 -1
  197. package/dist/tools/ctx-reduce/tools.d.ts +1 -1
  198. package/dist/tools/ctx-reduce/tools.d.ts.map +1 -1
  199. package/dist/tools/ctx-search/tools.d.ts.map +1 -1
  200. package/dist/tools/ctx-search/types.d.ts +1 -0
  201. package/dist/tools/ctx-search/types.d.ts.map +1 -1
  202. package/dist/{transform-postprocess-phase-spcy2qre.js → transform-postprocess-phase-481j5a7z.js} +28 -27
  203. package/dist/v2/auto-search-worker.js +3 -3
  204. package/dist/v2/{context-sf98kstd.js → context-gsdtha5v.js} +1619 -3111
  205. package/dist/v2/{derive-budgets-3vc0y84t.js → derive-budgets-enckmg7y.js} +3 -3
  206. package/dist/v2/embedding-backfill-dbvjbcmm.js +20 -0
  207. package/dist/v2/embedding-worker-process.js +29 -0
  208. package/dist/v2/embedding-worker.js +6 -7
  209. package/dist/v2/hidden-child-native.d.ts.map +1 -1
  210. package/dist/v2/hidden-completion.d.ts +7 -0
  211. package/dist/v2/hidden-completion.d.ts.map +1 -1
  212. package/dist/v2/hooks/context.d.ts.map +1 -1
  213. package/dist/v2/hooks/copied-tag-notation.d.ts +19 -0
  214. package/dist/v2/hooks/copied-tag-notation.d.ts.map +1 -0
  215. package/dist/v2/hooks/dream-trigger.d.ts +4 -1
  216. package/dist/v2/hooks/dream-trigger.d.ts.map +1 -1
  217. package/dist/v2/hooks/generate.d.ts +9 -2
  218. package/dist/v2/hooks/generate.d.ts.map +1 -1
  219. package/dist/v2/hooks/payload.d.ts.map +1 -1
  220. package/dist/v2/hooks/system-prompt-response.d.ts +5 -0
  221. package/dist/v2/hooks/system-prompt-response.d.ts.map +1 -0
  222. package/dist/v2/{logger-mxd0ym09.js → logger-pj02s7sr.js} +1 -1
  223. package/dist/v2/{message-index-bounded-dy3s2k1e.js → message-index-bounded-p6v0n8qh.js} +15 -14
  224. package/dist/v2/{message-time-backfill-gtx1pwk1.js → message-time-backfill-cje68egj.js} +2 -2
  225. package/dist/v2/migration-worker.js +11 -10
  226. package/dist/v2/{project-embedding-registry-1tgba5dv.js → project-embedding-registry-nyq7z8y6.js} +11 -12
  227. package/dist/v2/raw-ordinal-warmup-worker.js +4 -4
  228. package/dist/v2/{read-session-chunk-rh4khdkv.js → read-session-chunk-fhyfe4qa.js} +12 -9
  229. package/dist/v2/{read-session-raw-bsbmf0vj.js → read-session-raw-j8dvp7f4.js} +5 -3
  230. package/dist/v2/recomp-orchestrator-5xy7w136.js +57 -0
  231. package/dist/v2/{safe-notification-target-73ax1p5v.js → safe-notification-target-y3p1hce9.js} +2 -2
  232. package/dist/v2/{search-nzkwrc6n.js → search-j7bakcwa.js} +23 -23
  233. package/dist/v2/{send-session-notification-6km439kn.js → send-session-notification-f6v698r5.js} +5 -5
  234. package/dist/v2/{server-7wwc2nga.js → server-1fszbabv.js} +32 -32
  235. package/dist/v2/{server-k228xhjg.js → server-2htmbqbv.js} +26 -2
  236. package/dist/v2/{server-aan4q8mx.js → server-3t0q2cqx.js} +1 -1
  237. package/dist/v2/{server-686jg6eb.js → server-4c7jt8gq.js} +68 -7
  238. package/dist/v2/{server-xxm59eww.js → server-4enr7s6x.js} +4 -4
  239. package/dist/v2/{server-zxhgvsf9.js → server-676xw7at.js} +1 -1
  240. package/dist/v2/{server-52awr2mw.js → server-6byqfbqf.js} +93 -9
  241. package/dist/v2/{server-e0vdaae2.js → server-6tcrjfw8.js} +4 -4
  242. package/dist/v2/{server-qye6ykf7.js → server-7ekna9zs.js} +2 -2
  243. package/dist/v2/{server-g5r0n3b6.js → server-7h861yms.js} +160 -25
  244. package/dist/v2/{server-k8x2rbxc.js → server-7spkq1y6.js} +3457 -5192
  245. package/dist/v2/{server-8pyt7hev.js → server-7vkj6zhb.js} +34 -749
  246. package/dist/v2/{server-yczc713m.js → server-8xmq9h3f.js} +31 -49
  247. package/dist/v2/{server-sggvvzhb.js → server-bgzy0phk.js} +505 -11
  248. package/dist/v2/server-c7n2ftng.js +6860 -0
  249. package/dist/v2/server-cvgn49tr.js +733 -0
  250. package/dist/v2/{server-zm570tr2.js → server-cw6521wn.js} +232 -7
  251. package/dist/v2/{server-xdfwt6kh.js → server-czb2rkpk.js} +23 -3
  252. package/dist/v2/{server-x2g40a71.js → server-d6g4whc2.js} +21 -15
  253. package/dist/{index-1bc61ans.js → v2/server-fvnzcnww.js} +44 -1
  254. package/dist/v2/{server-4k748ke6.js → server-hb6xhh9q.js} +2 -2
  255. package/dist/v2/{server-gjcr4w98.js → server-kh958yj8.js} +5 -5
  256. package/dist/v2/{server-1r6pmz4f.js → server-kzns2hbz.js} +1 -1
  257. package/dist/v2/{server-psqc7e9n.js → server-mqvtz7wz.js} +1227 -78
  258. package/dist/v2/{server-vqpf3167.js → server-ras2sxnc.js} +135 -15
  259. package/dist/v2/{server-ezhze64f.js → server-s2st631p.js} +4 -4
  260. package/dist/v2/{server-5m3dt5r1.js → server-t4k4qexw.js} +6 -2
  261. package/dist/v2/{server-z2037m6z.js → server-t528t8qm.js} +2 -2
  262. package/dist/v2/{server-v06jcv0w.js → server-vb7pbd9p.js} +18 -259
  263. package/dist/v2/{server-8tqanswc.js → server-zbxjj2mz.js} +331 -4
  264. package/dist/v2/server.d.ts.map +1 -1
  265. package/dist/v2/server.js +150 -6
  266. package/dist/v2/{storage-tags-w4tv77sn.js → storage-tags-5yxrvkaf.js} +6 -4
  267. package/dist/v2/store-reader.d.ts +8 -2
  268. package/dist/v2/store-reader.d.ts.map +1 -1
  269. package/dist/v2/{wrapup-orchestrator-mz7efs7w.js → wrapup-orchestrator-yem5422s.js} +36 -36
  270. package/dist/wrapup-orchestrator-xvrr27ws.js +45 -0
  271. package/package.json +4 -4
  272. package/src/config/{mural-model-deprecation.ts → deprecated-config.ts} +19 -0
  273. package/src/config/index.test.ts +15 -37
  274. package/src/config/index.ts +2 -3
  275. package/src/config/project-security.ts +3 -3
  276. package/src/config/schema/magic-context.ts +11 -7
  277. package/src/features/magic-context/dreamer/task-registry.ts +2 -3
  278. package/src/shared/auto-search-lifecycle.ts +43 -0
  279. package/src/shared/logger.test.ts +38 -0
  280. package/src/shared/logger.ts +10 -2
  281. package/src/shared/models-dev-cache.ts +1 -7
  282. package/src/shared/models-dev-temperature.ts +107 -0
  283. package/src/shared/project-directory-key.test.ts +59 -0
  284. package/src/shared/project-directory-key.ts +20 -0
  285. package/src/shared/sqlite-640-review.test.ts +5 -1
  286. package/src/shared/storage-file-mutex-review.test.ts +162 -0
  287. package/src/shared/storage-file-mutex.ts +130 -0
  288. package/src/shared/storage-permissions.ts +46 -0
  289. package/src/shared/subagent-temperature.test.ts +270 -0
  290. package/src/shared/subagent-temperature.ts +110 -0
  291. package/src/shared/window-geometry.test.ts +102 -236
  292. package/src/shared/window-geometry.ts +23 -413
  293. package/dist/config/mural-model-deprecation.d.ts.map +0 -1
  294. package/dist/embedding-backfill-9rcm1mfy.js +0 -21
  295. package/dist/index-bdckkfw6.js +0 -3261
  296. package/dist/index-mfkzp7qj.js +0 -229
  297. package/dist/v2/embedding-backfill-vn8g1nh1.js +0 -21
  298. package/dist/v2/recomp-orchestrator-az61rfcg.js +0 -57
  299. package/dist/v2/server-2fbhp79z.js +0 -3205
  300. package/dist/v2/server-mfkzp7qj.js +0 -229
  301. package/dist/wrapup-orchestrator-amzta1t4.js +0 -44
  302. package/src/shared/__fixtures__/window-overlay.v1.json +0 -337
  303. /package/dist/{index-2pp04pmg.js → index-69vas84q.js} +0 -0
  304. /package/dist/v2/{index-2pp04pmg.js → index-69vas84q.js} +0 -0
@@ -13,6 +13,7 @@ import {
13
13
  __setCanonicalDirectoryRealpathForTests,
14
14
  canonicalProjectDirectory,
15
15
  projectDirectoryKey,
16
+ sameProjectDirectory,
16
17
  } from "./project-directory-key";
17
18
  import { projectHash, rpcPortDirsForLookup } from "./rpc-utils";
18
19
  import { createTestTempDirFromPath } from "./test-temp-dir";
@@ -109,3 +110,61 @@ describe("one discovery directory per project directory", () => {
109
110
  expect(dirs[0]).toBe(join("/storage", "rpc", projectHash("C:\\Users\\A\\Proj\\")));
110
111
  });
111
112
  });
113
+
114
+ /**
115
+ * Background-session code compares a session's recorded directory with the
116
+ * plugin's own. OpenCode 2 on Windows records `D:/coding/app` while the plugin
117
+ * knows `D:\coding\app`; both must count as one directory, and a different
118
+ * directory must never be taken for this one.
119
+ */
120
+ describe("sameProjectDirectory", () => {
121
+ for (const [name, left, right] of WINDOWS_PAIRS) {
122
+ test(`Windows ${name} is the same directory`, () => {
123
+ expect(sameProjectDirectory(left, right)).toBe(true);
124
+ expect(sameProjectDirectory(right, left)).toBe(true);
125
+ });
126
+ }
127
+
128
+ test("Windows forward slashes against backslashes, as OpenCode 2 stores them", () => {
129
+ expect(
130
+ sameProjectDirectory(
131
+ "D:/coding/siac/wt/migracion-asincrona",
132
+ "D:\\coding\\siac\\wt\\migracion-asincrona",
133
+ ),
134
+ ).toBe(true);
135
+ });
136
+
137
+ test("Windows `.` and `..` segments and a trailing forward slash", () => {
138
+ expect(
139
+ sameProjectDirectory("C:\\Users\\dev\\.\\work\\tmp\\..\\app", "C:/Users/dev/work/app/"),
140
+ ).toBe(true);
141
+ });
142
+
143
+ test("POSIX trailing slash and `..` segments", () => {
144
+ expect(sameProjectDirectory("/work/app/", "/work/app")).toBe(true);
145
+ expect(sameProjectDirectory("/work/tmp/../app", "/work/app")).toBe(true);
146
+ });
147
+
148
+ test("different directories are refused", () => {
149
+ expect(
150
+ sameProjectDirectory(
151
+ "D:/coding/siac/wt/notificaciones-pui",
152
+ "D:\\coding\\siac\\wt\\migracion-asincrona",
153
+ ),
154
+ ).toBe(false);
155
+ // A sibling whose name extends this one, a parent, and another drive.
156
+ expect(sameProjectDirectory("C:/Users/dev/app-worktree", "C:\\Users\\dev\\app")).toBe(
157
+ false,
158
+ );
159
+ expect(sameProjectDirectory("C:/Users/dev", "C:\\Users\\dev\\app")).toBe(false);
160
+ expect(sameProjectDirectory("D:/Users/dev/app", "C:\\Users\\dev\\app")).toBe(false);
161
+ // POSIX paths are case-sensitive.
162
+ expect(sameProjectDirectory("/work/App", "/work/app")).toBe(false);
163
+ });
164
+
165
+ test("an empty directory matches nothing, not even the process's working directory", () => {
166
+ expect(sameProjectDirectory("", process.cwd())).toBe(false);
167
+ expect(sameProjectDirectory(process.cwd(), "")).toBe(false);
168
+ expect(sameProjectDirectory("", "")).toBe(false);
169
+ });
170
+ });
@@ -20,6 +20,26 @@ export function projectDirectoryKey(directory: string): string {
20
20
  return path.resolve(directory);
21
21
  }
22
22
 
23
+ /**
24
+ * Whether two spellings name the same directory, judged by spelling alone.
25
+ *
26
+ * Hosts and the plugin do not agree on how to write a directory: OpenCode 2 on
27
+ * Windows stores a session's directory as `D:/work/app` while the plugin's own
28
+ * location is `D:\work\app`, and a drive letter can arrive in either case.
29
+ * Both sides go through `projectDirectoryKey`, so separators, Windows case,
30
+ * `\\?\` prefixes, trailing separators and `.`/`..` segments cannot make one
31
+ * directory look like two. POSIX paths keep their case. Symlinks are not
32
+ * resolved here; callers that must follow them use `canonicalProjectDirectory`.
33
+ *
34
+ * An empty spelling never matches anything: `path.resolve("")` is the process's
35
+ * working directory, and a session with no recorded directory must not be
36
+ * taken for one in the directory the process happens to run in.
37
+ */
38
+ export function sameProjectDirectory(a: string, b: string): boolean {
39
+ if (a.length === 0 || b.length === 0) return false;
40
+ return projectDirectoryKey(a) === projectDirectoryKey(b);
41
+ }
42
+
23
43
  let realpathForCanonicalDirectory: (directory: string) => string = (directory) =>
24
44
  realpathSync.native(directory);
25
45
 
@@ -2,9 +2,10 @@ import { expect, spyOn, test } from "bun:test";
2
2
  import { openDatabase } from "../features/magic-context/storage-db";
3
3
  import { getOrCreateSessionMeta, updateSessionMeta } from "../features/magic-context/storage-meta";
4
4
  import { recordToolDefinition } from "../features/magic-context/tool-definition-tokens";
5
+ import { saveLkgSlotToDb } from "../hooks/magic-context/lkg-persist";
5
6
  import { captureLkgSlot } from "../hooks/magic-context/lkg-replay";
6
7
  import { lkgReplayFits } from "../hooks/magic-context/lkg-replay-fit";
7
- import { resetLkgSlotsForTest } from "../hooks/magic-context/lkg-slot";
8
+ import { getSlot, resetLkgSlotsForTest } from "../hooks/magic-context/lkg-slot";
8
9
  import type { MessageLike } from "../hooks/magic-context/transform-operations";
9
10
  import { createMessagesTransformHandler } from "../plugin/messages-transform";
10
11
  import { refreshModelLimitsFromApi } from "./models-dev-cache";
@@ -141,6 +142,9 @@ test("review: OpenCode tries a valid saved request before backed-off writer retr
141
142
  providerKey: "openai",
142
143
  }),
143
144
  ).toBe(true);
145
+ expect(saveLkgSlotToDb(db, sessionId, getSlot(sessionId)!, undefined, { rebuild: true })).toBe(
146
+ true,
147
+ );
144
148
  expect(
145
149
  lkgReplayFits({
146
150
  db,
@@ -0,0 +1,162 @@
1
+ import { expect, test } from "bun:test";
2
+ import { spawnSync } from "node:child_process";
3
+ import { readdirSync, readFileSync, writeFileSync } from "node:fs";
4
+ import { join } from "node:path";
5
+ import { __resetRpcIdentityTestHooks, __setRpcIdentityTestHooks } from "./rpc-utils";
6
+ import { withStorageFileMutex } from "./storage-file-mutex";
7
+ import { createTestTempDir } from "./test-temp-dir";
8
+
9
+ const mutex = join(import.meta.dir, "storage-file-mutex.ts");
10
+
11
+ async function holder(root: string) {
12
+ const script = `
13
+ import { existsSync } from 'node:fs';
14
+ import { withStorageFileMutex } from ${JSON.stringify(mutex)};
15
+ withStorageFileMutex(${JSON.stringify(join(root, "locks"))}, () => {
16
+ console.log('HELD');
17
+ const pause = new Int32Array(new SharedArrayBuffer(4));
18
+ while (!existsSync(${JSON.stringify(join(root, "release"))})) Atomics.wait(pause, 0, 0, 10);
19
+ });`;
20
+ const child = Bun.spawn([process.execPath, "--eval", script], {
21
+ env: {
22
+ ...process.env,
23
+ XDG_DATA_HOME: root,
24
+ XDG_CONFIG_HOME: root,
25
+ MAGIC_CONTEXT_STORAGE_DIR: root,
26
+ MAGIC_CONTEXT_TEST_DATA_DIR: root,
27
+ },
28
+ stdout: "pipe",
29
+ stderr: "pipe",
30
+ windowsHide: true,
31
+ });
32
+ const reader = child.stdout.getReader();
33
+ const first = await reader.read();
34
+ expect(new TextDecoder().decode(first.value)).toContain("HELD");
35
+ reader.releaseLock();
36
+ if (process.platform === "darwin") {
37
+ const files = spawnSync("/usr/sbin/lsof", ["-p", String(child.pid), "-Fn"], {
38
+ encoding: "utf8",
39
+ windowsHide: true,
40
+ });
41
+ expect(files.status).toBe(0);
42
+ const names = files.stdout.split("\n").filter((line) => line.startsWith("n"));
43
+ expect(
44
+ names.some((line) =>
45
+ /\/(?:\.local\/share\/opencode|\.local\/share\/cortexkit\/magic-context|\.config\/(?:opencode|cortexkit))\//.test(
46
+ line,
47
+ ),
48
+ ),
49
+ ).toBe(false);
50
+ console.log(`REVIEW_LSOF pid=${child.pid} paths=${names.length} forbidden=0`);
51
+ }
52
+ return child;
53
+ }
54
+
55
+ test.skipIf(process.platform === "win32")(
56
+ "independent mutex: paused live holder is not taken over, dead holder is reclaimed",
57
+ async () => {
58
+ const { dir: root, cleanup } = createTestTempDir("mc-mutex-review-");
59
+ const child = await holder(root);
60
+ try {
61
+ process.kill(child.pid, "SIGSTOP");
62
+ const start = performance.now();
63
+ expect(() =>
64
+ withStorageFileMutex(
65
+ join(root, "locks"),
66
+ () => {
67
+ throw new Error("LIVE HOLDER WAS TAKEN OVER");
68
+ },
69
+ 200,
70
+ ),
71
+ ).toThrow("Storage safety publication lock is unavailable");
72
+ expect(performance.now() - start).toBeLessThan(2500);
73
+ process.kill(child.pid, "SIGKILL");
74
+ await child.exited;
75
+ let reached = false;
76
+ withStorageFileMutex(
77
+ join(root, "locks"),
78
+ () => {
79
+ reached = true;
80
+ },
81
+ 200,
82
+ );
83
+ expect(reached).toBe(true);
84
+ expect(readdirSync(join(root, "locks"))).toEqual([]);
85
+ } finally {
86
+ if (child.exitCode === null) {
87
+ child.kill("SIGKILL");
88
+ await child.exited;
89
+ }
90
+ cleanup();
91
+ }
92
+ },
93
+ 15000,
94
+ );
95
+
96
+ test.skipIf(process.platform === "win32")(
97
+ "independent mutex: corrupt live-owner identity refuses within a bound",
98
+ async () => {
99
+ const { dir: root, cleanup } = createTestTempDir("mc-mutex-review-");
100
+ const child = await holder(root);
101
+ try {
102
+ const locks = join(root, "locks");
103
+ const ticket = join(locks, readdirSync(locks)[0]!);
104
+ expect(JSON.parse(readFileSync(ticket, "utf8")).birth).toBeString();
105
+ writeFileSync(ticket, "inconclusive owner identity", { mode: 0o600 });
106
+ const start = performance.now();
107
+ let entered = false;
108
+ expect(() =>
109
+ withStorageFileMutex(
110
+ locks,
111
+ () => {
112
+ entered = true;
113
+ },
114
+ 200,
115
+ ),
116
+ ).toThrow("Storage safety publication lock is unavailable");
117
+ expect(entered).toBe(false);
118
+ expect(performance.now() - start).toBeLessThan(2500);
119
+ expect(readdirSync(locks)).toHaveLength(1);
120
+ } finally {
121
+ child.kill("SIGKILL");
122
+ await child.exited;
123
+ cleanup();
124
+ }
125
+ },
126
+ 15000,
127
+ );
128
+
129
+ test.skipIf(process.platform === "win32")(
130
+ "independent mutex: denied PID probe is inconclusive and refuses within a bound",
131
+ async () => {
132
+ const { dir: root, cleanup } = createTestTempDir("mc-mutex-inconclusive-review-");
133
+ const child = await holder(root);
134
+ try {
135
+ __setRpcIdentityTestHooks({
136
+ processKill: () => {
137
+ throw Object.assign(new Error("Denied PID probe"), { code: "EPERM" });
138
+ },
139
+ });
140
+ const start = performance.now();
141
+ let entered = false;
142
+ expect(() =>
143
+ withStorageFileMutex(
144
+ join(root, "locks"),
145
+ () => {
146
+ entered = true;
147
+ },
148
+ 200,
149
+ ),
150
+ ).toThrow("Storage safety publication lock is unavailable");
151
+ expect(entered).toBe(false);
152
+ expect(performance.now() - start).toBeLessThan(2500);
153
+ expect(readdirSync(join(root, "locks"))).toHaveLength(1);
154
+ } finally {
155
+ __resetRpcIdentityTestHooks();
156
+ child.kill("SIGKILL");
157
+ await child.exited;
158
+ cleanup();
159
+ }
160
+ },
161
+ 15000,
162
+ );
@@ -0,0 +1,130 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import { createHash, randomUUID } from "node:crypto";
3
+ import { readdirSync, readFileSync, rmSync } from "node:fs";
4
+ import { join } from "node:path";
5
+ import { isPidAlive, readProcessStartTime } from "./rpc-utils";
6
+ import {
7
+ ensurePrivateStorageDirectorySync,
8
+ writeStorageFileAtomicSync,
9
+ writeStorageFileSync,
10
+ } from "./storage-permissions";
11
+
12
+ interface Ticket {
13
+ choosing: boolean;
14
+ number: number;
15
+ birth: string | null;
16
+ checksum: string;
17
+ }
18
+ const ticketChecksum = (name: string, ticket: Ticket) =>
19
+ createHash("sha256")
20
+ .update(JSON.stringify([name, ticket.choosing, ticket.number, ticket.birth]))
21
+ .digest("hex");
22
+ function processBirth(pid: number): string | null {
23
+ if (process.platform === "linux") {
24
+ try {
25
+ const stat = readFileSync(`/proc/${pid}/stat`, "utf8");
26
+ const ticks = stat
27
+ .slice(stat.lastIndexOf(")") + 2)
28
+ .trim()
29
+ .split(/\s+/)[19];
30
+ if (!ticks || !/^\d+$/.test(ticks)) return null;
31
+ return `${readFileSync("/proc/sys/kernel/random/boot_id", "utf8").trim()}:${ticks}`;
32
+ } catch {
33
+ return null;
34
+ }
35
+ }
36
+ if (process.platform === "darwin") {
37
+ try {
38
+ return (
39
+ execFileSync("ps", ["-p", String(pid), "-o", "lstart="], {
40
+ encoding: "utf8",
41
+ timeout: 1000,
42
+ windowsHide: true,
43
+ env: { ...process.env, TZ: "UTC", LC_ALL: "C" },
44
+ stdio: ["ignore", "pipe", "pipe"],
45
+ }).trim() || null
46
+ );
47
+ } catch {
48
+ return null;
49
+ }
50
+ }
51
+ const start = readProcessStartTime(pid);
52
+ return start === null ? null : String(start);
53
+ }
54
+ const pause = new Int32Array(new SharedArrayBuffer(4));
55
+
56
+ /**
57
+ * Lamport's bakery mutex using unique contender files on a local filesystem.
58
+ * Exclusive creation and atomic replacement work on POSIX and Windows. A dead
59
+ * owner is removed by PID/start-time evidence, never by age: a paused live
60
+ * publisher must not lose its lock. Uncertain liveness refuses after the budget.
61
+ * Unique names mean reclaiming a dead ticket cannot unlink a successor's lock.
62
+ */
63
+ export function withStorageFileMutex<T>(directory: string, work: () => T, timeoutMs = 1000): T {
64
+ ensurePrivateStorageDirectorySync(directory);
65
+ const name = `${process.pid}-${randomUUID()}.lock`;
66
+ const ownPath = join(directory, name);
67
+ const birth = processBirth(process.pid);
68
+ const ticket: Ticket = { choosing: true, number: 0, birth, checksum: "" };
69
+ const encodedTicket = () =>
70
+ JSON.stringify({ ...ticket, checksum: ticketChecksum(name, ticket) });
71
+ writeStorageFileSync(ownPath, encodedTicket(), { flag: "wx", forcePrivate: true });
72
+ const deadline = performance.now() + timeoutMs;
73
+ const peers = (): [string, Ticket | null][] => {
74
+ const found: [string, Ticket | null][] = [];
75
+ for (const other of readdirSync(directory)) {
76
+ if (other === name || !/^\d+-[\da-f-]+\.lock$/.test(other)) continue;
77
+ const pid = Number(other.split("-")[0]);
78
+ const otherPath = join(directory, other);
79
+ let value: Ticket | null = null;
80
+ try {
81
+ const parsed = JSON.parse(readFileSync(otherPath, "utf8")) as Ticket;
82
+ if (
83
+ typeof parsed.choosing === "boolean" &&
84
+ Number.isSafeInteger(parsed.number) &&
85
+ parsed.number >= 0 &&
86
+ (parsed.birth === null || typeof parsed.birth === "string") &&
87
+ parsed.checksum === ticketChecksum(other, parsed)
88
+ )
89
+ value = parsed;
90
+ } catch (error) {
91
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") continue;
92
+ }
93
+ const alive = isPidAlive(pid);
94
+ const actualBirth = alive === "alive" && value?.birth ? processBirth(pid) : null;
95
+ if (
96
+ alive === "dead" ||
97
+ (actualBirth !== null && value?.birth && actualBirth !== value.birth)
98
+ ) {
99
+ rmSync(otherPath, { force: true });
100
+ continue;
101
+ }
102
+ found.push([other, value]);
103
+ }
104
+ return found;
105
+ };
106
+ try {
107
+ ticket.number = 1 + Math.max(0, ...peers().map(([, value]) => value?.number ?? 0));
108
+ ticket.choosing = false;
109
+ writeStorageFileAtomicSync(ownPath, encodedTicket(), true);
110
+ while (
111
+ peers().some(
112
+ ([other, value]) =>
113
+ !value ||
114
+ value.choosing ||
115
+ value.number < ticket.number ||
116
+ (value.number === ticket.number && other < name),
117
+ )
118
+ ) {
119
+ if (performance.now() >= deadline)
120
+ throw new Error("Storage safety publication lock is unavailable");
121
+ Atomics.wait(pause, 0, 0, 10);
122
+ }
123
+ const result = work();
124
+ if (result && typeof (result as { then?: unknown }).then === "function")
125
+ throw new TypeError("Storage publication mutex requires synchronous work");
126
+ return result;
127
+ } finally {
128
+ rmSync(ownPath, { force: true });
129
+ }
130
+ }
@@ -10,6 +10,7 @@ import {
10
10
  chmodSync,
11
11
  closeSync,
12
12
  createWriteStream,
13
+ fsyncSync,
13
14
  lstatSync,
14
15
  mkdirSync,
15
16
  openSync,
@@ -54,6 +55,15 @@ export function ensureStorageDirectorySync(
54
55
  });
55
56
  }
56
57
 
58
+ /** Replay-authorizing files require a private real directory, even after a permissive restore. */
59
+ export function ensurePrivateStorageDirectorySync(directory: string): void {
60
+ ensureStorageDirectorySync(directory, true);
61
+ const stat = lstatSync(directory);
62
+ if (!stat.isDirectory() || stat.isSymbolicLink())
63
+ throw new Error("Private storage directory is not a real directory");
64
+ if (process.platform !== "win32") chmodSync(directory, 0o700);
65
+ }
66
+
57
67
  /** Create or replace a storage file using a private mode from the first byte. */
58
68
  export function writeStorageFileSync(
59
69
  filePath: string,
@@ -85,6 +95,42 @@ export function writeStorageFileAtomicSync(
85
95
  }
86
96
  }
87
97
 
98
+ /** Flush the namespace containing a safety-critical sidecar (POSIX only). */
99
+ export function syncStorageDirectorySync(directory: string): void {
100
+ const fd = openSync(directory, "r");
101
+ try {
102
+ fsyncSync(fd);
103
+ } finally {
104
+ closeSync(fd);
105
+ }
106
+ }
107
+
108
+ /** Publish a safety record only after both its bytes and directory entry are durable. */
109
+ export function writeStorageFileDurableAtomicSync(
110
+ filePath: string,
111
+ content: string,
112
+ afterTempSync?: () => void,
113
+ ): void {
114
+ const directory = dirname(filePath);
115
+ ensurePrivateStorageDirectorySync(directory);
116
+ const tempPath = `${filePath}.${process.pid}.${randomBytes(12).toString("hex")}.tmp`;
117
+ let fd: number | undefined;
118
+ try {
119
+ fd = openStorageFileSync(tempPath, "wx", true);
120
+ writeFileSync(fd, content, "utf8");
121
+ fsyncSync(fd);
122
+ closeSync(fd);
123
+ fd = undefined;
124
+ afterTempSync?.();
125
+ renameSync(tempPath, filePath);
126
+ syncStorageDirectorySync(directory);
127
+ syncStorageDirectorySync(dirname(directory));
128
+ } finally {
129
+ if (fd !== undefined) closeSync(fd);
130
+ rmSync(tempPath, { force: true });
131
+ }
132
+ }
133
+
88
134
  export function copyStorageFileSync(
89
135
  sourcePath: string,
90
136
  destinationPath: string,