@cortexkit/opencode-magic-context 0.47.0 → 0.48.0

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 (366) hide show
  1. package/dist/agents/magic-context-prompt.d.ts +1 -1
  2. package/dist/agents/magic-context-prompt.d.ts.map +1 -1
  3. package/dist/{announcement-y35wzg2r.js → announcement-fp14dw0n.js} +3 -2
  4. package/dist/auto-search-worker.js +27 -30
  5. package/dist/config/index.d.ts.map +1 -1
  6. package/dist/config/mural-model-deprecation.d.ts +15 -0
  7. package/dist/config/mural-model-deprecation.d.ts.map +1 -0
  8. package/dist/config/project-security.d.ts +0 -3
  9. package/dist/config/project-security.d.ts.map +1 -1
  10. package/dist/config/schema/magic-context.d.ts +10 -6
  11. package/dist/config/schema/magic-context.d.ts.map +1 -1
  12. package/dist/{conflict-warning-hook-z44ynfz7.js → conflict-warning-hook-w8cykrnf.js} +12 -10
  13. package/dist/{context-wq4ffwyb.js → context-m0cy262m.js} +2690 -1903
  14. package/dist/{derive-budgets-ke12jnnh.js → derive-budgets-sg0xsq7s.js} +4 -3
  15. package/dist/embedding-activity-g1dhes6g.js +10 -0
  16. package/dist/embedding-backfill-9rcm1mfy.js +21 -0
  17. package/dist/embedding-cache-mgyr73ef.js +16 -0
  18. package/dist/embedding-worker.js +11 -9
  19. package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
  20. package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts +1 -0
  21. package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts.map +1 -1
  22. package/dist/features/magic-context/dreamer/task-config.d.ts +3 -3
  23. package/dist/features/magic-context/dreamer/task-config.d.ts.map +1 -1
  24. package/dist/features/magic-context/dreamer/task-executor.d.ts +1 -1
  25. package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
  26. package/dist/features/magic-context/dreamer/task-registry.d.ts +1 -0
  27. package/dist/features/magic-context/dreamer/task-registry.d.ts.map +1 -1
  28. package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
  29. package/dist/features/magic-context/message-index-async.d.ts +16 -3
  30. package/dist/features/magic-context/message-index-async.d.ts.map +1 -1
  31. package/dist/features/magic-context/message-index-bounded.d.ts +17 -0
  32. package/dist/features/magic-context/message-index-bounded.d.ts.map +1 -0
  33. package/dist/features/magic-context/message-index.d.ts +7 -1
  34. package/dist/features/magic-context/message-index.d.ts.map +1 -1
  35. package/dist/features/magic-context/mural/render-trigger.d.ts +7 -4
  36. package/dist/features/magic-context/mural/render-trigger.d.ts.map +1 -1
  37. package/dist/features/magic-context/pi-content-decisions.d.ts +7 -1
  38. package/dist/features/magic-context/pi-content-decisions.d.ts.map +1 -1
  39. package/dist/features/magic-context/search.d.ts +29 -0
  40. package/dist/features/magic-context/search.d.ts.map +1 -1
  41. package/dist/features/magic-context/session-activity.d.ts.map +1 -1
  42. package/dist/features/magic-context/smart-notes/runner.d.ts +1 -0
  43. package/dist/features/magic-context/smart-notes/runner.d.ts.map +1 -1
  44. package/dist/features/magic-context/storage-db.d.ts.map +1 -1
  45. package/dist/features/magic-context/storage-meta-session.d.ts +6 -0
  46. package/dist/features/magic-context/storage-meta-session.d.ts.map +1 -1
  47. package/dist/features/magic-context/storage-tag-identity-revision.d.ts +30 -0
  48. package/dist/features/magic-context/storage-tag-identity-revision.d.ts.map +1 -0
  49. package/dist/features/magic-context/storage-tags.d.ts +144 -4
  50. package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
  51. package/dist/features/magic-context/subagent-token-capture.d.ts.map +1 -1
  52. package/dist/features/magic-context/transform-decision-log.d.ts +1 -1
  53. package/dist/features/magic-context/transform-decision-log.d.ts.map +1 -1
  54. package/dist/harness-e4avh192.js +10 -0
  55. package/dist/hooks/magic-context/active-anthropic-turn.d.ts +2 -0
  56. package/dist/hooks/magic-context/active-anthropic-turn.d.ts.map +1 -1
  57. package/dist/hooks/magic-context/auto-search-worker-client.d.ts +32 -3
  58. package/dist/hooks/magic-context/auto-search-worker-client.d.ts.map +1 -1
  59. package/dist/hooks/magic-context/command-handler.d.ts +1 -0
  60. package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
  61. package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
  62. package/dist/hooks/magic-context/compartment-runner-recomp.d.ts.map +1 -1
  63. package/dist/hooks/magic-context/compartment-trigger.d.ts.map +1 -1
  64. package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
  65. package/dist/hooks/magic-context/hook.d.ts +1 -1
  66. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  67. package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
  68. package/dist/hooks/magic-context/lkg-persist.d.ts +4 -3
  69. package/dist/hooks/magic-context/lkg-persist.d.ts.map +1 -1
  70. package/dist/hooks/magic-context/lkg-replay.d.ts +13 -8
  71. package/dist/hooks/magic-context/lkg-replay.d.ts.map +1 -1
  72. package/dist/hooks/magic-context/lkg-slot.d.ts +139 -2
  73. package/dist/hooks/magic-context/lkg-slot.d.ts.map +1 -1
  74. package/dist/hooks/magic-context/message-search-accepting-silent-worker.fixture.d.ts +2 -0
  75. package/dist/hooks/magic-context/message-search-accepting-silent-worker.fixture.d.ts.map +1 -0
  76. package/dist/hooks/magic-context/oc-stall-r2-warmup-worker.fixture.d.ts +2 -0
  77. package/dist/hooks/magic-context/oc-stall-r2-warmup-worker.fixture.d.ts.map +1 -0
  78. package/dist/hooks/magic-context/oc-stall-search-review.fixture.d.ts +2 -0
  79. package/dist/hooks/magic-context/oc-stall-search-review.fixture.d.ts.map +1 -0
  80. package/dist/hooks/magic-context/opencode1-to-model-messages.fixture.d.ts +63 -0
  81. package/dist/hooks/magic-context/opencode1-to-model-messages.fixture.d.ts.map +1 -0
  82. package/dist/hooks/magic-context/provider-visible-parts.d.ts +45 -0
  83. package/dist/hooks/magic-context/provider-visible-parts.d.ts.map +1 -0
  84. package/dist/hooks/magic-context/raw-ordinal-warmup-silent-worker.fixture.d.ts +2 -0
  85. package/dist/hooks/magic-context/raw-ordinal-warmup-silent-worker.fixture.d.ts.map +1 -0
  86. package/dist/hooks/magic-context/raw-ordinal-warmup-worker.d.ts +2 -0
  87. package/dist/hooks/magic-context/raw-ordinal-warmup-worker.d.ts.map +1 -0
  88. package/dist/hooks/magic-context/raw-ordinal-warmup.d.ts +87 -0
  89. package/dist/hooks/magic-context/raw-ordinal-warmup.d.ts.map +1 -0
  90. package/dist/hooks/magic-context/read-session-chunk.d.ts +12 -0
  91. package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
  92. package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
  93. package/dist/hooks/magic-context/read-session-formatting.d.ts +5 -0
  94. package/dist/hooks/magic-context/read-session-formatting.d.ts.map +1 -1
  95. package/dist/hooks/magic-context/read-session-raw.d.ts +83 -1
  96. package/dist/hooks/magic-context/read-session-raw.d.ts.map +1 -1
  97. package/dist/hooks/magic-context/read-session-true-raw-tokens.d.ts.map +1 -1
  98. package/dist/hooks/magic-context/reasoning-budget.d.ts.map +1 -1
  99. package/dist/hooks/magic-context/sentinel.d.ts +41 -1
  100. package/dist/hooks/magic-context/sentinel.d.ts.map +1 -1
  101. package/dist/hooks/magic-context/strip-content.d.ts +14 -2
  102. package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
  103. package/dist/hooks/magic-context/system-prompt-hash.d.ts +1 -0
  104. package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
  105. package/dist/hooks/magic-context/tag-messages.d.ts +8 -0
  106. package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
  107. package/dist/hooks/magic-context/tag-owner-warmup.d.ts +6 -0
  108. package/dist/hooks/magic-context/tag-owner-warmup.d.ts.map +1 -0
  109. package/dist/hooks/magic-context/tail-hygiene-walk.d.ts.map +1 -1
  110. package/dist/hooks/magic-context/token-count-exact.d.ts +35 -0
  111. package/dist/hooks/magic-context/token-count-exact.d.ts.map +1 -0
  112. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  113. package/dist/hooks/magic-context/transform.d.ts +8 -2
  114. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  115. package/dist/hooks/magic-context/wrapup-orchestrator.d.ts.map +1 -1
  116. package/dist/{index-w2t4ah5j.js → index-0an7742d.js} +14072 -14286
  117. package/dist/index-0qhce371.js +120 -0
  118. package/dist/{index-q6hef7fh.js → index-0sahzkwr.js} +6 -19
  119. package/dist/{index-k5bdx1bx.js → index-0w56v4fm.js} +3 -5
  120. package/dist/index-14cjxt20.js +819 -0
  121. package/dist/{v2/server-51dv1pr5.js → index-1qb0z7wa.js} +301 -27
  122. package/dist/index-2bvekkfy.js +11 -0
  123. package/dist/{index-sj29b3z2.js → index-2y0s2hep.js} +3 -3
  124. package/dist/index-4dhv7mqz.js +131 -0
  125. package/dist/{index-b35pxds2.js → index-58e3y90n.js} +1 -18
  126. package/dist/index-5zygecde.js +152 -0
  127. package/dist/{index-6d9e1m08.js → index-692jzy0p.js} +17775 -17450
  128. package/dist/index-72nhv486.js +2307 -0
  129. package/dist/index-7jzrrxap.js +931 -0
  130. package/dist/{v2/server-njt3np1k.js → index-7mx8v0pw.js} +220 -961
  131. package/dist/index-8ajstryz.js +18 -0
  132. package/dist/{index-sfpzqvdz.js → index-8cd2j99z.js} +2 -3
  133. package/dist/{index-hybnrwq0.js → index-8j7gqj40.js} +131 -128
  134. package/dist/index-bdckkfw6.js +3261 -0
  135. package/dist/{index-m5fe6jch.js → index-bhvjj0ys.js} +152 -2453
  136. package/dist/index-c43kr12f.js +3030 -0
  137. package/dist/index-cb7emxgj.js +984 -0
  138. package/dist/index-d9vfe7xq.js +16 -0
  139. package/dist/{index-5gq3b2ya.js → index-db7zwa3v.js} +147 -209
  140. package/dist/index-dhwzyd54.js +1142 -0
  141. package/dist/{index-8da2zjhz.js → index-eeezr5zz.js} +9 -7
  142. package/dist/{index-cwf6s3ay.js → index-f0h6xwqm.js} +2828 -2618
  143. package/dist/index-fb3zxn06.js +13 -0
  144. package/dist/index-fbv1dn35.js +171 -0
  145. package/dist/index-fr0wbhdn.js +43 -0
  146. package/dist/{index-mc22ayvf.js → index-ghc9f0n7.js} +11 -9
  147. package/dist/{index-fzbvakh0.js → index-jcbd3znx.js} +3 -3
  148. package/dist/{index-5a2r0p9f.js → index-k1xb52kd.js} +20 -13
  149. package/dist/index-k9nnwad5.js +3532 -0
  150. package/dist/{index-wx8a6bw3.js → index-kb9nn0a0.js} +270 -53
  151. package/dist/index-knh4y330.js +566 -0
  152. package/dist/{v2/server-fq7kq32k.js → index-mfkzp7qj.js} +1 -16
  153. package/dist/{index-gg8j07zz.js → index-mmyh6d8f.js} +4 -4
  154. package/dist/index-pavzsdc6.js +17 -0
  155. package/dist/{index-0c82743p.js → index-pdecwzrd.js} +17 -15
  156. package/dist/index-pg50n748.js +1060 -0
  157. package/dist/{index-92bp57hg.js → index-q2tqeqde.js} +123 -80
  158. package/dist/{index-rrrsepyw.js → index-q7h7csab.js} +90 -85
  159. package/dist/{v2/server-yr3zj7e7.js → index-qt1qqasc.js} +6 -7
  160. package/dist/{index-6wkcswft.js → index-ty64eqcn.js} +28 -18
  161. package/dist/{index-adwfkpex.js → index-yq8n9qcb.js} +23 -23
  162. package/dist/{index-9pk9exrb.js → index-z8e0psj8.js} +18 -18
  163. package/dist/index.d.ts.map +1 -1
  164. package/dist/index.js +586 -344
  165. package/dist/logger-d3wex3dz.js +20 -0
  166. package/dist/message-index-bounded-7ezbgddp.js +124 -0
  167. package/dist/{v2/message-time-backfill-1f9tzvcs.js → message-time-backfill-brbd63hv.js} +8 -6
  168. package/dist/migration-worker.js +25 -18
  169. package/dist/{model-resolution-xhfmyyvy.js → model-resolution-nx97z3x7.js} +1 -1
  170. package/dist/plugin/dream-timer.d.ts +1 -1
  171. package/dist/plugin/dream-timer.d.ts.map +1 -1
  172. package/dist/plugin/hooks/create-session-hooks.d.ts +1 -0
  173. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  174. package/dist/plugin/host-stall-profiler-report.d.ts +1 -66
  175. package/dist/plugin/host-stall-profiler-report.d.ts.map +1 -1
  176. package/dist/plugin/host-stall-profiler.d.ts +2 -95
  177. package/dist/plugin/host-stall-profiler.d.ts.map +1 -1
  178. package/dist/plugin/messages-transform.d.ts +0 -13
  179. package/dist/plugin/messages-transform.d.ts.map +1 -1
  180. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  181. package/dist/plugin/tool-registry.d.ts.map +1 -1
  182. package/dist/project-embedding-registry-7qzptcw7.js +88 -0
  183. package/dist/raw-ordinal-warmup-worker.js +60 -0
  184. package/dist/{read-session-chunk-4jey7hpt.js → read-session-chunk-6k83m4fj.js} +15 -9
  185. package/dist/read-session-raw-3g9qy1xa.js +58 -0
  186. package/dist/recomp-orchestrator-d3fp1cy0.js +57 -0
  187. package/dist/{v2/safe-notification-target-eb1n1vfb.js → safe-notification-target-5ffqq32m.js} +4 -2
  188. package/dist/search-epax1ecv.js +45 -0
  189. package/dist/{v2/send-session-notification-c0wtscea.js → send-session-notification-erecz4y4.js} +10 -7
  190. package/dist/shared/conflict-detector.d.ts.map +1 -1
  191. package/dist/shared/host-stall-profiler-bun.d.ts +46 -0
  192. package/dist/shared/host-stall-profiler-bun.d.ts.map +1 -0
  193. package/dist/shared/host-stall-profiler-common.d.ts +58 -0
  194. package/dist/shared/host-stall-profiler-common.d.ts.map +1 -0
  195. package/dist/shared/host-stall-profiler-node.d.ts +36 -0
  196. package/dist/shared/host-stall-profiler-node.d.ts.map +1 -0
  197. package/dist/shared/host-stall-profiler-report.d.ts +68 -0
  198. package/dist/shared/host-stall-profiler-report.d.ts.map +1 -0
  199. package/dist/shared/host-stall-profiler.d.ts +5 -0
  200. package/dist/shared/host-stall-profiler.d.ts.map +1 -0
  201. package/dist/shared/model-resolution.d.ts +2 -3
  202. package/dist/shared/model-resolution.d.ts.map +1 -1
  203. package/dist/shared/sqlite.d.ts +30 -0
  204. package/dist/shared/sqlite.d.ts.map +1 -1
  205. package/dist/shared/stable-json.d.ts.map +1 -1
  206. package/dist/shared/user-facing-codes.d.ts +0 -5
  207. package/dist/shared/user-facing-codes.d.ts.map +1 -1
  208. package/dist/sqlite-context-pragmas-mv9jqwjh.js +6 -0
  209. package/dist/sqlite-mhjkerzq.js +46 -0
  210. package/dist/storage-memory-07fx57k6.js +71 -0
  211. package/dist/storage-tags-d3b0v2ss.js +131 -0
  212. package/dist/{task-config-v81k8jvk.js → task-config-cgpg0nvh.js} +2 -2
  213. package/dist/tools/ctx-expand/tools.d.ts.map +1 -1
  214. package/dist/tools/ctx-note/constants.d.ts +4 -0
  215. package/dist/tools/ctx-note/constants.d.ts.map +1 -1
  216. package/dist/tools/ctx-note/tools.d.ts +1 -0
  217. package/dist/tools/ctx-note/tools.d.ts.map +1 -1
  218. package/dist/tools/ctx-search/tools.d.ts.map +1 -1
  219. package/dist/tools/parameter-descriptions.d.ts +2 -2
  220. package/dist/tools/parameter-descriptions.d.ts.map +1 -1
  221. package/dist/{transform-postprocess-phase-z5hzpsxv.js → transform-postprocess-phase-spcy2qre.js} +35 -20
  222. package/dist/transformers-node-wasm.js +18415 -18415
  223. package/dist/v2/auto-search-worker.js +27 -30
  224. package/dist/v2/{context-14v1hr8b.js → context-sf98kstd.js} +3737 -3004
  225. package/dist/v2/{derive-budgets-nc9avxz8.js → derive-budgets-3vc0y84t.js} +4 -3
  226. package/dist/v2/embedding-activity-g1dhes6g.js +10 -0
  227. package/dist/v2/embedding-backfill-vn8g1nh1.js +21 -0
  228. package/dist/v2/embedding-cache-mgyr73ef.js +16 -0
  229. package/dist/v2/embedding-worker.js +12 -9
  230. package/dist/v2/fold/host-media.d.ts +4 -0
  231. package/dist/v2/fold/host-media.d.ts.map +1 -1
  232. package/dist/v2/fold/memory-cache.d.ts +70 -0
  233. package/dist/v2/fold/memory-cache.d.ts.map +1 -0
  234. package/dist/v2/fold/native-codec.d.ts +10 -0
  235. package/dist/v2/fold/native-codec.d.ts.map +1 -0
  236. package/dist/v2/fold/native-replay.d.ts +58 -0
  237. package/dist/v2/fold/native-replay.d.ts.map +1 -0
  238. package/dist/v2/fold/policy.d.ts +24 -0
  239. package/dist/v2/fold/policy.d.ts.map +1 -0
  240. package/dist/v2/harness-e4avh192.js +10 -0
  241. package/dist/v2/hooks/context.d.ts +2 -2
  242. package/dist/v2/hooks/context.d.ts.map +1 -1
  243. package/dist/v2/hooks/dream-manual.d.ts +1 -1
  244. package/dist/v2/hooks/dream-manual.d.ts.map +1 -1
  245. package/dist/v2/hooks/dream-timer.d.ts.map +1 -1
  246. package/dist/v2/hooks/dream-trigger.d.ts +1 -2
  247. package/dist/v2/hooks/dream-trigger.d.ts.map +1 -1
  248. package/dist/v2/hooks/payload.d.ts.map +1 -1
  249. package/dist/v2/hooks/tools.d.ts.map +1 -1
  250. package/dist/v2/hooks/types.d.ts +6 -0
  251. package/dist/v2/hooks/types.d.ts.map +1 -1
  252. package/dist/v2/logger-mxd0ym09.js +19 -0
  253. package/dist/v2/message-index-bounded-dy3s2k1e.js +123 -0
  254. package/dist/{message-time-backfill-r5epkzj3.js → v2/message-time-backfill-gtx1pwk1.js} +7 -7
  255. package/dist/v2/migration-worker.js +24 -17
  256. package/dist/v2/{model-resolution-xhfmyyvy.js → model-resolution-nx97z3x7.js} +1 -1
  257. package/dist/v2/project-embedding-registry-1tgba5dv.js +86 -0
  258. package/dist/v2/raw-ordinal-warmup-worker.js +60 -0
  259. package/dist/v2/{read-session-chunk-gyyv7w2r.js → read-session-chunk-rh4khdkv.js} +14 -8
  260. package/dist/v2/read-session-raw-bsbmf0vj.js +57 -0
  261. package/dist/v2/recomp-orchestrator-az61rfcg.js +57 -0
  262. package/dist/{safe-notification-target-43r8jsxw.js → v2/safe-notification-target-73ax1p5v.js} +3 -3
  263. package/dist/v2/search-nzkwrc6n.js +45 -0
  264. package/dist/{send-session-notification-0m68ms3n.js → v2/send-session-notification-6km439kn.js} +9 -8
  265. package/dist/{index-5eqk6z3s.js → v2/server-1r6pmz4f.js} +301 -27
  266. package/dist/v2/server-2bvekkfy.js +11 -0
  267. package/dist/v2/server-2fbhp79z.js +3205 -0
  268. package/dist/v2/{server-ajzeteqw.js → server-2ra6pwf3.js} +1 -18
  269. package/dist/v2/server-4dhv7mqz.js +131 -0
  270. package/dist/v2/{server-y10vbq6y.js → server-4k748ke6.js} +11 -1053
  271. package/dist/v2/{server-vs5gpnd4.js → server-52awr2mw.js} +81 -145
  272. package/dist/v2/{server-1qbnzc80.js → server-5m3dt5r1.js} +136 -148
  273. package/dist/v2/server-686jg6eb.js +3508 -0
  274. package/dist/v2/server-7jzrrxap.js +931 -0
  275. package/dist/v2/server-7wwc2nga.js +3023 -0
  276. package/dist/v2/server-8ajstryz.js +18 -0
  277. package/dist/v2/{server-sfpzqvdz.js → server-8cd2j99z.js} +2 -3
  278. package/dist/v2/{server-d0sraw7m.js → server-8pyt7hev.js} +291 -286
  279. package/dist/v2/server-8tqanswc.js +984 -0
  280. package/dist/v2/{server-14vq4kpm.js → server-aan4q8mx.js} +3 -3
  281. package/dist/v2/server-d9vfe7xq.js +16 -0
  282. package/dist/{index-x3kwrmqk.js → v2/server-e0vdaae2.js} +35 -792
  283. package/dist/v2/server-ezhze64f.js +1048 -0
  284. package/dist/v2/server-fb3zxn06.js +13 -0
  285. package/dist/v2/server-fr0wbhdn.js +43 -0
  286. package/dist/v2/server-g5r0n3b6.js +1137 -0
  287. package/dist/v2/server-gjcr4w98.js +154 -0
  288. package/dist/v2/server-k228xhjg.js +171 -0
  289. package/dist/v2/{server-nf82q6pt.js → server-k8x2rbxc.js} +5946 -5602
  290. package/dist/v2/{server-wx8a6bw3.js → server-kb9nn0a0.js} +270 -53
  291. package/dist/{index-rrbbspwh.js → v2/server-mfkzp7qj.js} +1 -16
  292. package/dist/v2/server-pavzsdc6.js +17 -0
  293. package/dist/v2/{server-e0c1b7a7.js → server-psqc7e9n.js} +122 -79
  294. package/dist/{index-yr3zj7e7.js → v2/server-qt1qqasc.js} +6 -7
  295. package/dist/v2/server-qye6ykf7.js +120 -0
  296. package/dist/v2/{server-qdjnb2z1.js → server-r5p3b1wy.js} +11 -9
  297. package/dist/v2/server-sggvvzhb.js +759 -0
  298. package/dist/v2/{server-cpepxy2q.js → server-v06jcv0w.js} +14 -12
  299. package/dist/v2/server-vqpf3167.js +1048 -0
  300. package/dist/v2/{server-rz514f14.js → server-x2g40a71.js} +2044 -2060
  301. package/dist/v2/{server-vd4e7174.js → server-xdfwt6kh.js} +20 -16
  302. package/dist/v2/{server-efhwzx05.js → server-xxm59eww.js} +23 -23
  303. package/dist/v2/server-yczc713m.js +564 -0
  304. package/dist/v2/{server-fcdehk1s.js → server-z2037m6z.js} +4 -4
  305. package/dist/v2/{server-50hvkg3v.js → server-zm570tr2.js} +160 -158
  306. package/dist/v2/{server-6r257mf5.js → server-zxhgvsf9.js} +3 -3
  307. package/dist/v2/server.js +16 -14
  308. package/dist/v2/sqlite-context-pragmas-mv9jqwjh.js +6 -0
  309. package/dist/v2/sqlite-mhjkerzq.js +46 -0
  310. package/dist/v2/storage-memory-07fx57k6.js +71 -0
  311. package/dist/v2/storage-tags-w4tv77sn.js +130 -0
  312. package/dist/v2/store-reader.d.ts +16 -0
  313. package/dist/v2/store-reader.d.ts.map +1 -1
  314. package/dist/v2/{task-config-tbndqyny.js → task-config-x0hq3qfd.js} +2 -2
  315. package/dist/v2/transformers-node-wasm.js +18415 -18415
  316. package/dist/v2/tui/index.d.ts.map +1 -1
  317. package/dist/v2/tui/types.d.ts +1 -10
  318. package/dist/v2/tui/types.d.ts.map +1 -1
  319. package/dist/v2/{wrapup-orchestrator-nbz854vc.js → wrapup-orchestrator-mz7efs7w.js} +51 -30
  320. package/dist/wrapup-orchestrator-amzta1t4.js +44 -0
  321. package/package.json +4 -3
  322. package/src/agents/magic-context-prompt.ts +27 -2
  323. package/src/agents/smart-notes-enabled.test.ts +294 -0
  324. package/src/agents/smart-notes-on.golden.json +70 -0
  325. package/src/config/index.test.ts +67 -1
  326. package/src/config/index.ts +2 -0
  327. package/src/config/latch-permanence-guard.test.ts +4 -0
  328. package/src/config/mural-model-deprecation.ts +24 -0
  329. package/src/config/project-security.hostile-matrix.test.ts +4 -44
  330. package/src/config/project-security.test.ts +9 -14
  331. package/src/config/project-security.ts +13 -55
  332. package/src/config/schema/magic-context.test.ts +2 -2
  333. package/src/config/schema/magic-context.ts +16 -10
  334. package/src/features/magic-context/dreamer/task-registry.ts +6 -0
  335. package/src/shared/conflict-detector.test.ts +56 -0
  336. package/src/shared/conflict-detector.ts +16 -5
  337. package/src/shared/host-stall-profiler-bun.ts +358 -0
  338. package/src/shared/host-stall-profiler-common.ts +159 -0
  339. package/src/shared/host-stall-profiler-node.test.ts +234 -0
  340. package/src/shared/host-stall-profiler-node.ts +274 -0
  341. package/src/shared/host-stall-profiler-report.ts +248 -0
  342. package/src/shared/host-stall-profiler.ts +57 -0
  343. package/src/shared/model-resolution.test.ts +54 -17
  344. package/src/shared/model-resolution.ts +6 -17
  345. package/src/shared/sqlite.test.ts +52 -0
  346. package/src/shared/sqlite.ts +339 -23
  347. package/src/shared/stable-json-linear.test.ts +109 -0
  348. package/src/shared/stable-json.ts +37 -7
  349. package/src/shared/user-facing-codes.ts +2 -6
  350. package/src/shared/write-transaction-attribution.test.ts +2 -2
  351. package/src/v2/tui/host-contract.test.ts +41 -67
  352. package/src/v2/tui/index.ts +6 -214
  353. package/src/v2/tui/types.ts +5 -17
  354. package/dist/features/magic-context/checkout-claim-fake-subc.test-support.d.ts +0 -45
  355. package/dist/features/magic-context/checkout-claim-fake-subc.test-support.d.ts.map +0 -1
  356. package/dist/features/magic-context/checkout-claim.d.ts +0 -155
  357. package/dist/features/magic-context/checkout-claim.d.ts.map +0 -1
  358. package/dist/index-bb36vgr3.js +0 -6608
  359. package/dist/index-fnn5pjtt.js +0 -6554
  360. package/dist/recomp-orchestrator-rervg6q4.js +0 -42
  361. package/dist/v2/recomp-orchestrator-42vjba7p.js +0 -42
  362. package/dist/v2/server-3trjk1hx.js +0 -6360
  363. package/dist/v2/server-nm9n3aqq.js +0 -6461
  364. package/dist/wrapup-orchestrator-b2dztrar.js +0 -29
  365. /package/dist/{index-5prbx026.js → index-2pp04pmg.js} +0 -0
  366. /package/dist/v2/{index-5prbx026.js → index-2pp04pmg.js} +0 -0
@@ -41,6 +41,7 @@
41
41
 
42
42
  import { AsyncLocalStorage } from "node:async_hooks";
43
43
  import { statSync } from "node:fs";
44
+
44
45
  // Type import only — runtime is loaded dynamically below. @types/better-sqlite3
45
46
  // has the richest definitions and is a structural superset of the API surface
46
47
  // we use, so calls typed against BetterSqlite3 work under bun:sqlite and
@@ -169,13 +170,51 @@ export class SqliteRuntimeUnavailableError extends Error {
169
170
  }
170
171
  }
171
172
 
173
+ // Node requests this warning during node:sqlite's module evaluation, although
174
+ // warning delivery happens later. Intercept only the request while importing;
175
+ // replacing warning listeners would not suppress the default stderr output.
176
+ function isNodeSqliteExperimentalWarning(args: unknown[]): boolean {
177
+ const [warning, options] = args;
178
+ const message = warning instanceof Error ? warning.message : warning;
179
+ const type =
180
+ typeof options === "string"
181
+ ? options
182
+ : options && typeof options === "object"
183
+ ? (options as { type?: unknown }).type
184
+ : undefined;
185
+ return (
186
+ type === "ExperimentalWarning" &&
187
+ typeof message === "string" &&
188
+ message.startsWith("SQLite is an experimental feature")
189
+ );
190
+ }
191
+
192
+ async function importSqliteModuleForRuntime(
193
+ runtime: SqliteRuntime,
194
+ specifier: string,
195
+ importer: (specifier: string) => Promise<SqliteModule>,
196
+ ): Promise<SqliteModule> {
197
+ if (runtime !== "Node.js") return importer(specifier);
198
+
199
+ const originalEmitWarning = process.emitWarning;
200
+ process.emitWarning = function (this: unknown, ...args: unknown[]): void {
201
+ if (isNodeSqliteExperimentalWarning(args)) return;
202
+ Reflect.apply(originalEmitWarning, this, args);
203
+ } as typeof process.emitWarning;
204
+ try {
205
+ return await importer(specifier);
206
+ } finally {
207
+ process.emitWarning = originalEmitWarning;
208
+ }
209
+ }
210
+
172
211
  export async function loadSqliteModule(
173
212
  runtime: SqliteRuntime = detectSqliteRuntime(),
174
213
  importer: (specifier: string) => Promise<SqliteModule> = importSqliteModule,
175
214
  ): Promise<SqliteModule> {
176
215
  const specifier = runtime === "Bun" ? bunSpec : nodeSpec;
177
216
  try {
178
- return await importer(specifier);
217
+ return await importSqliteModuleForRuntime(runtime, specifier, importer);
179
218
  } catch (error) {
180
219
  if (isModuleNotFoundError(error, specifier)) {
181
220
  throw new SqliteRuntimeUnavailableError(runtime, specifier, error);
@@ -234,6 +273,110 @@ export interface SqliteMemoryStats {
234
273
  const trackedSqliteConnections = new Map<number, TrackedSqliteConnection>();
235
274
  let nextSqliteConnectionSequence = 1;
236
275
 
276
+ /**
277
+ * Columns of Magic Context's `tags` table (context.db) that never decide which
278
+ * message a tag belongs to, its number, its type, or its reasoning token estimate.
279
+ */
280
+ const TAG_COLUMNS_OUTSIDE_IDENTITY = new Set([
281
+ "status",
282
+ "drop_mode",
283
+ "byte_size",
284
+ "input_byte_size",
285
+ "reasoning_byte_size",
286
+ "token_count",
287
+ "input_token_count",
288
+ "caveman_depth",
289
+ "entry_fingerprint",
290
+ "tool_name",
291
+ "harness",
292
+ ]);
293
+
294
+ let tagIdentityWriteGeneration = 0;
295
+
296
+ /**
297
+ * Whether a write statement may change an existing `tags` row's identity
298
+ * (session, number, type, owner message, reasoning token count) or remove a
299
+ * row. Plain appends without an explicit `id`, and updates that assign only
300
+ * columns in {@link TAG_COLUMNS_OUTSIDE_IDENTITY}, cannot; everything else that
301
+ * names the table is treated as if it could, including DDL and multi-statement
302
+ * scripts. Erring towards true only costs a cache rebuild.
303
+ */
304
+ export function mayChangeTagIdentity(sql: string): boolean {
305
+ if (!/\btags\b/i.test(sql) || /^\s*(?:SELECT|EXPLAIN|PRAGMA)\b/i.test(sql)) return false;
306
+ if (/^\s*WITH\b/i.test(sql) && !/\b(?:INSERT|UPDATE|DELETE|REPLACE)\b/i.test(sql)) return false;
307
+ // One statement only: a script can hide a DELETE behind a harmless first statement.
308
+ if (/;\s*\S/.test(sql) || /\bREPLACE\b/i.test(sql) || /\bON\s+CONFLICT\b/i.test(sql))
309
+ return true;
310
+ const insert = /^\s*INSERT\s+INTO\s+(?:main\.)?["`]?tags["`]?\s*\(([^)]*)\)/i.exec(sql);
311
+ if (insert) {
312
+ const columns = (insert[1] ?? "").split(",").map((column) =>
313
+ column
314
+ .trim()
315
+ .replace(/["`[\]]/g, "")
316
+ .toLowerCase(),
317
+ );
318
+ return columns.includes("id") || columns.includes("rowid");
319
+ }
320
+ const update = /^\s*UPDATE\s+(?:main\.)?["`]?tags["`]?\s+SET\s+([\s\S]*?)\bWHERE\b/i.exec(sql);
321
+ if (update && !/\bSELECT\b/i.test(sql)) {
322
+ // Provably identity-free only when every top-level assignment is a plain
323
+ // `column = ...` naming an allowed column. A tuple assignment such as
324
+ // `(tag_number, reasoning_token_count) = (...)`, or anything this cannot
325
+ // read, counts as an identity write.
326
+ const assignments = topLevelCommaSegments(update[1] ?? "");
327
+ if (!assignments) return true;
328
+ return !assignments.every((assignment) => {
329
+ const column = /^\s*["`]?(\w+)["`]?\s*=(?!=)/.exec(assignment)?.[1];
330
+ return column !== undefined && TAG_COLUMNS_OUTSIDE_IDENTITY.has(column.toLowerCase());
331
+ });
332
+ }
333
+ return true;
334
+ }
335
+
336
+ /**
337
+ * Split SQL text at commas outside parentheses and quotes. Returns null when
338
+ * the parentheses or quotes do not balance.
339
+ */
340
+ function topLevelCommaSegments(text: string): string[] | null {
341
+ const segments: string[] = [];
342
+ let depth = 0;
343
+ let quote: string | null = null;
344
+ let start = 0;
345
+ for (let index = 0; index < text.length; index += 1) {
346
+ const char = text[index];
347
+ if (quote) {
348
+ // A doubled quote inside a quoted run is an escaped quote.
349
+ if (char === quote) {
350
+ if (text[index + 1] === quote) index += 1;
351
+ else quote = null;
352
+ }
353
+ continue;
354
+ }
355
+ if (char === "'" || char === '"' || char === "`") quote = char;
356
+ else if (char === "(") depth += 1;
357
+ else if (char === ")") {
358
+ depth -= 1;
359
+ if (depth < 0) return null;
360
+ } else if (char === "," && depth === 0) {
361
+ segments.push(text.slice(start, index));
362
+ start = index + 1;
363
+ }
364
+ }
365
+ if (quote || depth !== 0) return null;
366
+ segments.push(text.slice(start));
367
+ return segments;
368
+ }
369
+
370
+ /**
371
+ * Counts executions, on any connection this process opened, of statements for
372
+ * which {@link mayChangeTagIdentity} is true. A cache built from `tags` stays
373
+ * valid for this process's own writes while the count is unchanged; commits by
374
+ * other connections show up in `PRAGMA data_version` instead.
375
+ */
376
+ export function getTagIdentityWriteGeneration(): number {
377
+ return tagIdentityWriteGeneration;
378
+ }
379
+
237
380
  /** Route native Bun and Node transaction entry through the same acquisition retry.
238
381
  * Native Bun transaction wrappers execute BEGIN internally, bypassing an exec override,
239
382
  * so both runtimes use this small synchronous wrapper instead. Writable handles
@@ -257,8 +400,15 @@ function installTransactionRouting(db: BetterSqlite3.Database, readonly: boolean
257
400
  }
258
401
  if (WRITER_TRANSACTION_END.test(sql) && openWriterTransactions.has(db))
259
402
  return endWriterTransaction(db, () => nativeExec(sql), sql);
260
- if (!/^\s*(?:SELECT|EXPLAIN|PRAGMA|COMMIT|END|ROLLBACK|SAVEPOINT|RELEASE)\b/i.test(sql))
261
- return withAutocommitTimeout(db, () => nativeExec(sql));
403
+ if (
404
+ !/^\s*(?:SELECT|EXPLAIN|PRAGMA|COMMIT|END|ROLLBACK|SAVEPOINT|RELEASE)\b/i.test(sql)
405
+ ) {
406
+ try {
407
+ return withAutocommitTimeout(db, () => nativeExec(sql));
408
+ } finally {
409
+ if (mayChangeTagIdentity(sql)) tagIdentityWriteGeneration += 1;
410
+ }
411
+ }
262
412
  return nativeExec(sql);
263
413
  },
264
414
  });
@@ -271,15 +421,22 @@ function installTransactionRouting(db: BetterSqlite3.Database, readonly: boolean
271
421
  // SELECT/EXPLAIN cannot acquire a writer. Treat CTEs conservatively:
272
422
  // WITH can introduce INSERT/UPDATE/DELETE as well as a read query.
273
423
  if (!readonly && !/^\s*(?:SELECT|EXPLAIN|PRAGMA)\b/i.test(sql)) {
424
+ const changesTagIdentity = mayChangeTagIdentity(sql);
274
425
  for (const method of ["run", "get", "all"] as const) {
275
426
  const execute = statement[method].bind(statement);
276
427
  Object.defineProperty(statement, method, {
277
428
  configurable: true,
278
429
  // biome-ignore lint/suspicious/noExplicitAny: retain SQLite's native binding overloads.
279
- value: (...args: any[]) =>
280
- withAutocommitTimeout(db, () => execute(...args)),
430
+ value: (...args: any[]) => {
431
+ try {
432
+ return withAutocommitTimeout(db, () => execute(...args));
433
+ } finally {
434
+ if (changesTagIdentity) tagIdentityWriteGeneration += 1;
435
+ }
436
+ },
281
437
  });
282
438
  }
439
+ if (changesTagIdentity) wrapRemainingTagWriteForms(statement);
283
440
  }
284
441
  return statement;
285
442
  },
@@ -330,6 +487,43 @@ function installTransactionRouting(db: BetterSqlite3.Database, readonly: boolean
330
487
  });
331
488
  }
332
489
 
490
+ /**
491
+ * Count tag identity writes made through the statement forms the transaction
492
+ * routing does not wrap. `iterate()` runs the statement while its result is
493
+ * consumed, so the generation moves both when iteration starts and when it
494
+ * ends: a summary read in between is then rebuilt on its next read.
495
+ */
496
+ // biome-ignore lint/suspicious/noExplicitAny: statements from both backends share these method names.
497
+ function wrapRemainingTagWriteForms(statement: any): void {
498
+ if (typeof statement.iterate === "function") {
499
+ const iterate = statement.iterate.bind(statement);
500
+ Object.defineProperty(statement, "iterate", {
501
+ configurable: true,
502
+ value: function* (...args: unknown[]) {
503
+ tagIdentityWriteGeneration += 1;
504
+ try {
505
+ yield* iterate(...args);
506
+ } finally {
507
+ tagIdentityWriteGeneration += 1;
508
+ }
509
+ },
510
+ });
511
+ }
512
+ if (typeof statement.values === "function") {
513
+ const values = statement.values.bind(statement);
514
+ Object.defineProperty(statement, "values", {
515
+ configurable: true,
516
+ value: (...args: unknown[]) => {
517
+ try {
518
+ return values(...args);
519
+ } finally {
520
+ tagIdentityWriteGeneration += 1;
521
+ }
522
+ },
523
+ });
524
+ }
525
+ }
526
+
333
527
  function trackSqliteConnection(
334
528
  db: BetterSqlite3.Database,
335
529
  filename: unknown,
@@ -440,6 +634,11 @@ export function getSqliteDatabasePath(db: Database): string | null {
440
634
  : connection.filename;
441
635
  }
442
636
  }
637
+ // Native Bun/better-sqlite3 handles can reach readers without our constructor
638
+ // wrapper. Their filename is still available without a SQLite query.
639
+ const native = db as unknown as { filename?: unknown; name?: unknown };
640
+ const path = native.filename ?? native.name;
641
+ if (typeof path === "string" && path !== ":memory:" && path !== "") return path;
443
642
  return null;
444
643
  }
445
644
 
@@ -569,6 +768,33 @@ interface StatementOwner {
569
768
  const statementOwners = new WeakMap<Database, StatementOwner>();
570
769
  const FIRST_PRUNE_AT = 256;
571
770
 
771
+ /**
772
+ * Bun's default close (`sqlite3_close_v2`) only releases the native connection
773
+ * once every statement created by prepare() is finalized. The close override
774
+ * in ownPreparedStatement can finalize only statements that are still
775
+ * reachable. Once the garbage collector
776
+ * has marked a one-shot statement dead, its weak reference is already cleared,
777
+ * but the statement is finalized only when its memory is later swept. Until
778
+ * then the closed connection keeps the database, WAL and shared-memory files
779
+ * open, for an unbounded time.
780
+ *
781
+ * `close(true)` finalizes every outstanding statement, reachable or not, and
782
+ * releases the connection immediately. When the caller did not ask for errors
783
+ * and that close fails, fall back to the caller's own close so a teardown path
784
+ * never starts throwing; the fallback can defer the release as before.
785
+ */
786
+ function closeReleasingStatements(
787
+ close: (...args: unknown[]) => unknown,
788
+ args: unknown[],
789
+ ): unknown {
790
+ if (args[0] === true) return close(true);
791
+ try {
792
+ return close(true);
793
+ } catch {
794
+ return close(...args);
795
+ }
796
+ }
797
+
572
798
  function ownPreparedStatement(db: Database, statement: Statement): Statement {
573
799
  const finalizable = statement as FinalizableStatement;
574
800
  // Node finalizes its statements on close and exposes no finalize() method.
@@ -592,7 +818,7 @@ function ownPreparedStatement(db: Database, statement: Statement): Statement {
592
818
  }
593
819
  }
594
820
  references.clear();
595
- const result = close(...args);
821
+ const result = closeReleasingStatements(close, args);
596
822
  if (failure) throw failure;
597
823
  return result;
598
824
  },
@@ -650,22 +876,31 @@ export function withSqliteBackgroundWriter<T>(operation: () => T): T {
650
876
  export function withSqliteTransformPass<T>(operation: () => T): T {
651
877
  const existing = transformPassScope.getStore();
652
878
  if (existing?.active) return operation();
653
- const lease = { active: true, remainingWaitMs: FOREGROUND_IN_PASS_BUSY_TIMEOUT_MS };
654
- return transformPassScope.run(lease, () => {
655
- try {
656
- const result = operation();
657
- if (result && typeof (result as { then?: unknown }).then === "function") {
658
- return Promise.resolve(result).finally(() => {
659
- lease.active = false;
660
- }) as T;
879
+ const reservation = reserveForegroundSqliteTurn();
880
+ const run = (release: () => void): T => {
881
+ const lease = { active: true, remainingWaitMs: FOREGROUND_IN_PASS_BUSY_TIMEOUT_MS };
882
+ return transformPassScope.run(lease, () => {
883
+ try {
884
+ const result = operation();
885
+ if (result && typeof (result as { then?: unknown }).then === "function") {
886
+ return Promise.resolve(result).finally(() => {
887
+ lease.active = false;
888
+ release();
889
+ }) as T;
890
+ }
891
+ lease.active = false;
892
+ release();
893
+ return result;
894
+ } catch (error) {
895
+ lease.active = false;
896
+ release();
897
+ throw error;
661
898
  }
662
- lease.active = false;
663
- return result;
664
- } catch (error) {
665
- lease.active = false;
666
- throw error;
667
- }
668
- });
899
+ });
900
+ };
901
+ // Foreground callers racing maintenance are awaited transforms. Idle
902
+ // synchronous callers keep the existing immediate return/throw behavior.
903
+ return typeof reservation === "function" ? run(reservation) : (reservation.then(run) as T);
669
904
  }
670
905
 
671
906
  /** Start detached maintenance work without borrowing a foreground pass's budget. */
@@ -836,16 +1071,20 @@ function acquireShort(db: Database, acquire: () => unknown, site: string): void
836
1071
  * `acquireShort`, then report how long the writer waited for the lock
837
1072
  * (`acquire_ms`) and how long it then held it (`hold_ms`) when either crosses
838
1073
  * the threshold. A long hold blocks every other process's writer, so it is
839
- * worth seeing even when the lock itself came quickly.
1074
+ * worth seeing even when the lock itself came quickly. The native end statement's
1075
+ * `end_ms` is reported separately, so a slow FTS merge or checkpoint at COMMIT
1076
+ * is not mistaken for acquisition time.
840
1077
  */
841
1078
  function endWriterTransaction(db: Database, end: () => unknown, sql: string): unknown {
842
1079
  let ended = false;
1080
+ const endStarted = performance.now();
843
1081
  try {
844
1082
  const result = end();
845
1083
  ended = true;
846
1084
  return result;
847
1085
  } finally {
848
1086
  const open = openWriterTransactions.get(db);
1087
+ const endMs = performance.now() - endStarted;
849
1088
  // A COMMIT that failed with the transaction still open has not ended it.
850
1089
  if (open && !isInTransaction(db)) {
851
1090
  openWriterTransactions.delete(db);
@@ -857,7 +1096,7 @@ function endWriterTransaction(db: Database, end: () => unknown, sql: string): un
857
1096
  ? "committed"
858
1097
  : "failed";
859
1098
  reportSqliteDiagnostic(
860
- `sqlite writer site=${open.site} lane=${open.lane} acquire_ms=${Math.round(open.acquireMs)} hold_ms=${Math.round(holdMs)} attempts=${open.attempts} outcome=${outcome}`,
1099
+ `sqlite writer site=${open.site} lane=${open.lane} acquire_ms=${Math.round(open.acquireMs)} hold_ms=${Math.round(holdMs)} end_ms=${Math.round(endMs)} attempts=${open.attempts} outcome=${outcome}`,
861
1100
  );
862
1101
  }
863
1102
  }
@@ -1056,3 +1295,80 @@ export function withPrivilegedWriter<T>(db: Database, operation: () => T): T {
1056
1295
  throw error;
1057
1296
  }
1058
1297
  }
1298
+
1299
+ // Process-local admission only; SQLite remains the cross-process writer arbiter.
1300
+ const indexCoordinationKey = Symbol.for("magic-context.index-foreground-coordination.v1");
1301
+ const indexCoordinationHeap = globalThis as unknown as Record<
1302
+ symbol,
1303
+ SharedArrayBuffer | undefined
1304
+ >;
1305
+ const indexCoordinationBuffer =
1306
+ indexCoordinationHeap[indexCoordinationKey] ??
1307
+ new SharedArrayBuffer(3 * Int32Array.BYTES_PER_ELEMENT);
1308
+ indexCoordinationHeap[indexCoordinationKey] = indexCoordinationBuffer;
1309
+ const indexCoordinationState = new Int32Array(indexCoordinationBuffer);
1310
+ // Slots: foreground interest, current maintenance owner, next owner token.
1311
+
1312
+ export function indexCoordinationInput(): {
1313
+ indexCoordination: SharedArrayBuffer;
1314
+ indexOwner: number;
1315
+ } {
1316
+ return {
1317
+ indexCoordination: indexCoordinationBuffer,
1318
+ indexOwner: Atomics.add(indexCoordinationState, 2, 1) + 1,
1319
+ };
1320
+ }
1321
+
1322
+ const yieldIndexTurn = () => new Promise<void>((resolve) => setTimeout(resolve, 1));
1323
+
1324
+ /** Announce interest before waiting, so no maintenance chunk overtakes a foreground turn. */
1325
+ function reserveForegroundSqliteTurn(): (() => void) | Promise<() => void> {
1326
+ Atomics.add(indexCoordinationState, 0, 1);
1327
+ const release = () => {
1328
+ Atomics.sub(indexCoordinationState, 0, 1);
1329
+ Atomics.notify(indexCoordinationState, 0);
1330
+ };
1331
+ if (Atomics.load(indexCoordinationState, 1) === 0) return release;
1332
+ return (async () => {
1333
+ while (Atomics.load(indexCoordinationState, 1) !== 0) await yieldIndexTurn();
1334
+ return release;
1335
+ })();
1336
+ }
1337
+
1338
+ export function releaseIndexOwner(input: {
1339
+ indexCoordination?: SharedArrayBuffer;
1340
+ indexOwner?: number;
1341
+ }): void {
1342
+ if (!input.indexCoordination || !input.indexOwner) return;
1343
+ const shared = new Int32Array(input.indexCoordination);
1344
+ Atomics.compareExchange(shared, 1, input.indexOwner, 0);
1345
+ Atomics.notify(shared, 1);
1346
+ }
1347
+
1348
+ /** One synchronous transaction per permit; release the permit before yielding. */
1349
+ export async function withIndexChunk<T>(
1350
+ input: { indexCoordination?: SharedArrayBuffer; indexOwner?: number },
1351
+ operation: () => T,
1352
+ ): Promise<T> {
1353
+ if (!input.indexCoordination || !input.indexOwner) return operation();
1354
+ const shared = new Int32Array(input.indexCoordination);
1355
+ for (;;) {
1356
+ if (
1357
+ Atomics.load(shared, 0) === 0 &&
1358
+ Atomics.compareExchange(shared, 1, 0, input.indexOwner) === 0
1359
+ ) {
1360
+ if (Atomics.load(shared, 0) === 0) break;
1361
+ releaseIndexOwner(input);
1362
+ }
1363
+ await yieldIndexTurn();
1364
+ }
1365
+ try {
1366
+ return await operation();
1367
+ } finally {
1368
+ releaseIndexOwner(input);
1369
+ }
1370
+ }
1371
+
1372
+ export async function yieldIndexChunk(): Promise<void> {
1373
+ await yieldIndexTurn();
1374
+ }
@@ -0,0 +1,109 @@
1
+ /// <reference types="bun-types" />
2
+
3
+ import { describe, expect, it } from "bun:test";
4
+ import { stableStringify } from "./stable-json";
5
+
6
+ /** stableStringify as it was before it collected pieces: joins at every level. */
7
+ function frozenStableStringify(value: unknown, seen = new WeakSet<object>()): string {
8
+ if (value === undefined) return "undefined";
9
+ if (value === null || typeof value !== "object") return JSON.stringify(value) ?? String(value);
10
+ if (seen.has(value)) return '"[Circular]"';
11
+ seen.add(value);
12
+ if (Array.isArray(value)) {
13
+ return `[${value.map((item) => frozenStableStringify(item, seen)).join(",")}]`;
14
+ }
15
+ const entries = Object.entries(value as Record<string, unknown>).sort(([a], [b]) => {
16
+ if (a < b) return -1;
17
+ if (a > b) return 1;
18
+ return 0;
19
+ });
20
+ return `{${entries
21
+ .map(([key, child]) => `${JSON.stringify(key)}:${frozenStableStringify(child, seen)}`)
22
+ .join(",")}}`;
23
+ }
24
+
25
+ function rng(seed: number): () => number {
26
+ let state = seed >>> 0 || 1;
27
+ return () => {
28
+ state ^= state << 13;
29
+ state >>>= 0;
30
+ state ^= state >>> 17;
31
+ state ^= state << 5;
32
+ state >>>= 0;
33
+ return state / 0x100000000;
34
+ };
35
+ }
36
+
37
+ function randomValue(random: () => number, depth: number, shared: object[]): unknown {
38
+ const roll = random();
39
+ if (depth > 4 || roll < 0.35) {
40
+ const leaves: unknown[] = [
41
+ "plain",
42
+ 'quote " and \\ backslash',
43
+ "ünï 日本 😀 \u2028",
44
+ 0,
45
+ -0,
46
+ 1.5,
47
+ Number.NaN,
48
+ Number.POSITIVE_INFINITY,
49
+ true,
50
+ false,
51
+ null,
52
+ undefined,
53
+ () => 1,
54
+ Symbol("s"),
55
+ ];
56
+ return leaves[Math.floor(random() * leaves.length)];
57
+ }
58
+ if (roll < 0.45 && shared.length > 0) return shared[Math.floor(random() * shared.length)];
59
+ if (roll < 0.7) {
60
+ const array: unknown[] = [];
61
+ const length = Math.floor(random() * 5);
62
+ for (let index = 0; index < length; index += 1) {
63
+ if (random() < 0.15) continue; // leaves a hole
64
+ array[index] = randomValue(random, depth + 1, shared);
65
+ }
66
+ array.length = length;
67
+ if (random() < 0.2) shared.push(array);
68
+ return array;
69
+ }
70
+ const object: Record<string, unknown> = {};
71
+ for (let index = Math.floor(random() * 5); index > 0; index -= 1) {
72
+ const key = ["b", "a", "10", "2", "é", "Z", "key with space"][
73
+ Math.floor(random() * 7)
74
+ ] as string;
75
+ object[key] = randomValue(random, depth + 1, shared);
76
+ }
77
+ if (random() < 0.2) shared.push(object);
78
+ if (random() < 0.1) object.self = object;
79
+ return object;
80
+ }
81
+
82
+ describe("stableStringify", () => {
83
+ it("writes exactly what it wrote when it joined at every level", () => {
84
+ const random = rng(653);
85
+ let circular = 0;
86
+ let holes = 0;
87
+ for (let sample = 0; sample < 2_000; sample += 1) {
88
+ const value = randomValue(random, 0, []);
89
+ const text = stableStringify(value);
90
+ expect(text).toBe(frozenStableStringify(value));
91
+ if (text.includes('"[Circular]"')) circular += 1;
92
+ if (/\[,|,,|,\]/.test(text)) holes += 1;
93
+ }
94
+ // Shared and cyclic references and array holes were among the samples.
95
+ expect(circular).toBeGreaterThan(50);
96
+ expect(holes).toBeGreaterThan(50);
97
+ });
98
+
99
+ it("copies a deeply nested value once, not once per level", () => {
100
+ // 3,000 levels around a 2 MB string: joining at every level copied about
101
+ // 6 GB of text (over a second); one copy takes a few milliseconds.
102
+ let node: unknown = { body: "x".repeat(2_000_000) };
103
+ for (let depth = 0; depth < 3_000; depth += 1) node = { child: node, depth };
104
+ const started = performance.now();
105
+ const text = stableStringify(node);
106
+ expect(text.length).toBeGreaterThan(2_000_000);
107
+ expect(performance.now() - started).toBeLessThan(300);
108
+ }, 30_000);
109
+ });
@@ -18,12 +18,38 @@
18
18
  * signing), build a separate utility — do NOT widen this contract.
19
19
  */
20
20
  export function stableStringify(value: unknown, seen = new WeakSet<object>()): string {
21
- if (value === undefined) return "undefined";
22
- if (value === null || typeof value !== "object") return JSON.stringify(value) ?? String(value);
23
- if (seen.has(value)) return '"[Circular]"';
21
+ // Collect pieces and join once. Joining at every level copied each nested
22
+ // value's text once per enclosing level, so a large value N levels deep cost
23
+ // N copies of itself.
24
+ const pieces: string[] = [];
25
+ writeStable(value, seen, pieces);
26
+ return pieces.join("");
27
+ }
28
+
29
+ function writeStable(value: unknown, seen: WeakSet<object>, pieces: string[]): void {
30
+ if (value === undefined) {
31
+ pieces.push("undefined");
32
+ return;
33
+ }
34
+ if (value === null || typeof value !== "object") {
35
+ pieces.push(JSON.stringify(value) ?? String(value));
36
+ return;
37
+ }
38
+ // Any object met a second time, shared or cyclic, is written as "[Circular]".
39
+ if (seen.has(value)) {
40
+ pieces.push('"[Circular]"');
41
+ return;
42
+ }
24
43
  seen.add(value);
25
44
  if (Array.isArray(value)) {
26
- return `[${value.map((item) => stableStringify(item, seen)).join(",")}]`;
45
+ pieces.push("[");
46
+ for (let index = 0; index < value.length; index += 1) {
47
+ if (index > 0) pieces.push(",");
48
+ // A hole writes nothing between its commas, as joining a mapped array did.
49
+ if (index in value) writeStable(value[index], seen, pieces);
50
+ }
51
+ pieces.push("]");
52
+ return;
27
53
  }
28
54
  // Code-point sort (NOT localeCompare). Stable across runtimes/locales.
29
55
  const entries = Object.entries(value as Record<string, unknown>).sort(([a], [b]) => {
@@ -31,7 +57,11 @@ export function stableStringify(value: unknown, seen = new WeakSet<object>()): s
31
57
  if (a > b) return 1;
32
58
  return 0;
33
59
  });
34
- return `{${entries
35
- .map(([key, child]) => `${JSON.stringify(key)}:${stableStringify(child, seen)}`)
36
- .join(",")}}`;
60
+ pieces.push("{");
61
+ entries.forEach(([key, child], index) => {
62
+ if (index > 0) pieces.push(",");
63
+ pieces.push(JSON.stringify(key), ":");
64
+ writeStable(child, seen, pieces);
65
+ });
66
+ pieces.push("}");
37
67
  }
@@ -245,12 +245,8 @@ export const USER_FACING_FAILURES = {
245
245
  sentence: "Magic Context has no context.db.",
246
246
  action: "Run `npx @cortexkit/magic-context doctor store init`, then restart ck-mc.",
247
247
  },
248
- checkout_claim_held_elsewhere: {
249
- code: "MC-C16",
250
- sentence:
251
- "This request was not sent: this agent is checked out on another machine, so Magic Context will not work on its sessions here.",
252
- action: "Move the agent back to this machine, then send your message again.",
253
- },
248
+ // MC-C16 is retired: released builds showed it when a turn was refused because
249
+ // another machine held the session's agent. Do not reuse it for a new failure.
254
250
  single_store_migration_required: {
255
251
  code: "MC-C14",
256
252
  sentence: "Magic Context's Rust mode needs a one-time migration of its store.",
@@ -87,7 +87,7 @@ const fencedSources: Array<{ path: string; sites: string[]; reporterCalls?: stri
87
87
  },
88
88
  {
89
89
  path: "packages/pi-plugin/src/context-handler.ts",
90
- sites: ["pi_compaction_queue"],
90
+ sites: ["pi_fallback_adoption"],
91
91
  },
92
92
  ];
93
93
 
@@ -149,7 +149,7 @@ const newlyCoveredSites = [
149
149
  "pi_materialize_cache",
150
150
  "pi_soft_refresh_cache",
151
151
  "pi_historian_publish",
152
- "pi_compaction_queue",
152
+ "pi_fallback_adoption",
153
153
  "note_nudge_trigger",
154
154
  "user_memory_candidate_insert",
155
155
  ] as const;