@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.
- package/dist/agents/magic-context-prompt.d.ts +1 -1
- package/dist/agents/magic-context-prompt.d.ts.map +1 -1
- package/dist/{announcement-y35wzg2r.js → announcement-fp14dw0n.js} +3 -2
- package/dist/auto-search-worker.js +27 -30
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/mural-model-deprecation.d.ts +15 -0
- package/dist/config/mural-model-deprecation.d.ts.map +1 -0
- package/dist/config/project-security.d.ts +0 -3
- package/dist/config/project-security.d.ts.map +1 -1
- package/dist/config/schema/magic-context.d.ts +10 -6
- package/dist/config/schema/magic-context.d.ts.map +1 -1
- package/dist/{conflict-warning-hook-z44ynfz7.js → conflict-warning-hook-w8cykrnf.js} +12 -10
- package/dist/{context-wq4ffwyb.js → context-m0cy262m.js} +2690 -1903
- package/dist/{derive-budgets-ke12jnnh.js → derive-budgets-sg0xsq7s.js} +4 -3
- package/dist/embedding-activity-g1dhes6g.js +10 -0
- package/dist/embedding-backfill-9rcm1mfy.js +21 -0
- package/dist/embedding-cache-mgyr73ef.js +16 -0
- package/dist/embedding-worker.js +11 -9
- package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts +1 -0
- package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-config.d.ts +3 -3
- package/dist/features/magic-context/dreamer/task-config.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-executor.d.ts +1 -1
- package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-registry.d.ts +1 -0
- package/dist/features/magic-context/dreamer/task-registry.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
- package/dist/features/magic-context/message-index-async.d.ts +16 -3
- package/dist/features/magic-context/message-index-async.d.ts.map +1 -1
- package/dist/features/magic-context/message-index-bounded.d.ts +17 -0
- package/dist/features/magic-context/message-index-bounded.d.ts.map +1 -0
- package/dist/features/magic-context/message-index.d.ts +7 -1
- package/dist/features/magic-context/message-index.d.ts.map +1 -1
- package/dist/features/magic-context/mural/render-trigger.d.ts +7 -4
- package/dist/features/magic-context/mural/render-trigger.d.ts.map +1 -1
- package/dist/features/magic-context/pi-content-decisions.d.ts +7 -1
- package/dist/features/magic-context/pi-content-decisions.d.ts.map +1 -1
- package/dist/features/magic-context/search.d.ts +29 -0
- package/dist/features/magic-context/search.d.ts.map +1 -1
- package/dist/features/magic-context/session-activity.d.ts.map +1 -1
- package/dist/features/magic-context/smart-notes/runner.d.ts +1 -0
- package/dist/features/magic-context/smart-notes/runner.d.ts.map +1 -1
- package/dist/features/magic-context/storage-db.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-session.d.ts +6 -0
- package/dist/features/magic-context/storage-meta-session.d.ts.map +1 -1
- package/dist/features/magic-context/storage-tag-identity-revision.d.ts +30 -0
- package/dist/features/magic-context/storage-tag-identity-revision.d.ts.map +1 -0
- package/dist/features/magic-context/storage-tags.d.ts +144 -4
- package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
- package/dist/features/magic-context/subagent-token-capture.d.ts.map +1 -1
- package/dist/features/magic-context/transform-decision-log.d.ts +1 -1
- package/dist/features/magic-context/transform-decision-log.d.ts.map +1 -1
- package/dist/harness-e4avh192.js +10 -0
- package/dist/hooks/magic-context/active-anthropic-turn.d.ts +2 -0
- package/dist/hooks/magic-context/active-anthropic-turn.d.ts.map +1 -1
- package/dist/hooks/magic-context/auto-search-worker-client.d.ts +32 -3
- package/dist/hooks/magic-context/auto-search-worker-client.d.ts.map +1 -1
- package/dist/hooks/magic-context/command-handler.d.ts +1 -0
- package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-recomp.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-trigger.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook.d.ts +1 -1
- package/dist/hooks/magic-context/hook.d.ts.map +1 -1
- package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
- package/dist/hooks/magic-context/lkg-persist.d.ts +4 -3
- package/dist/hooks/magic-context/lkg-persist.d.ts.map +1 -1
- package/dist/hooks/magic-context/lkg-replay.d.ts +13 -8
- package/dist/hooks/magic-context/lkg-replay.d.ts.map +1 -1
- package/dist/hooks/magic-context/lkg-slot.d.ts +139 -2
- package/dist/hooks/magic-context/lkg-slot.d.ts.map +1 -1
- package/dist/hooks/magic-context/message-search-accepting-silent-worker.fixture.d.ts +2 -0
- package/dist/hooks/magic-context/message-search-accepting-silent-worker.fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/oc-stall-r2-warmup-worker.fixture.d.ts +2 -0
- package/dist/hooks/magic-context/oc-stall-r2-warmup-worker.fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/oc-stall-search-review.fixture.d.ts +2 -0
- package/dist/hooks/magic-context/oc-stall-search-review.fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/opencode1-to-model-messages.fixture.d.ts +63 -0
- package/dist/hooks/magic-context/opencode1-to-model-messages.fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/provider-visible-parts.d.ts +45 -0
- package/dist/hooks/magic-context/provider-visible-parts.d.ts.map +1 -0
- package/dist/hooks/magic-context/raw-ordinal-warmup-silent-worker.fixture.d.ts +2 -0
- package/dist/hooks/magic-context/raw-ordinal-warmup-silent-worker.fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/raw-ordinal-warmup-worker.d.ts +2 -0
- package/dist/hooks/magic-context/raw-ordinal-warmup-worker.d.ts.map +1 -0
- package/dist/hooks/magic-context/raw-ordinal-warmup.d.ts +87 -0
- package/dist/hooks/magic-context/raw-ordinal-warmup.d.ts.map +1 -0
- package/dist/hooks/magic-context/read-session-chunk.d.ts +12 -0
- package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-formatting.d.ts +5 -0
- package/dist/hooks/magic-context/read-session-formatting.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-raw.d.ts +83 -1
- package/dist/hooks/magic-context/read-session-raw.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-true-raw-tokens.d.ts.map +1 -1
- package/dist/hooks/magic-context/reasoning-budget.d.ts.map +1 -1
- package/dist/hooks/magic-context/sentinel.d.ts +41 -1
- package/dist/hooks/magic-context/sentinel.d.ts.map +1 -1
- package/dist/hooks/magic-context/strip-content.d.ts +14 -2
- package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
- package/dist/hooks/magic-context/system-prompt-hash.d.ts +1 -0
- package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
- package/dist/hooks/magic-context/tag-messages.d.ts +8 -0
- package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
- package/dist/hooks/magic-context/tag-owner-warmup.d.ts +6 -0
- package/dist/hooks/magic-context/tag-owner-warmup.d.ts.map +1 -0
- package/dist/hooks/magic-context/tail-hygiene-walk.d.ts.map +1 -1
- package/dist/hooks/magic-context/token-count-exact.d.ts +35 -0
- package/dist/hooks/magic-context/token-count-exact.d.ts.map +1 -0
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform.d.ts +8 -2
- package/dist/hooks/magic-context/transform.d.ts.map +1 -1
- package/dist/hooks/magic-context/wrapup-orchestrator.d.ts.map +1 -1
- package/dist/{index-w2t4ah5j.js → index-0an7742d.js} +14072 -14286
- package/dist/index-0qhce371.js +120 -0
- package/dist/{index-q6hef7fh.js → index-0sahzkwr.js} +6 -19
- package/dist/{index-k5bdx1bx.js → index-0w56v4fm.js} +3 -5
- package/dist/index-14cjxt20.js +819 -0
- package/dist/{v2/server-51dv1pr5.js → index-1qb0z7wa.js} +301 -27
- package/dist/index-2bvekkfy.js +11 -0
- package/dist/{index-sj29b3z2.js → index-2y0s2hep.js} +3 -3
- package/dist/index-4dhv7mqz.js +131 -0
- package/dist/{index-b35pxds2.js → index-58e3y90n.js} +1 -18
- package/dist/index-5zygecde.js +152 -0
- package/dist/{index-6d9e1m08.js → index-692jzy0p.js} +17775 -17450
- package/dist/index-72nhv486.js +2307 -0
- package/dist/index-7jzrrxap.js +931 -0
- package/dist/{v2/server-njt3np1k.js → index-7mx8v0pw.js} +220 -961
- package/dist/index-8ajstryz.js +18 -0
- package/dist/{index-sfpzqvdz.js → index-8cd2j99z.js} +2 -3
- package/dist/{index-hybnrwq0.js → index-8j7gqj40.js} +131 -128
- package/dist/index-bdckkfw6.js +3261 -0
- package/dist/{index-m5fe6jch.js → index-bhvjj0ys.js} +152 -2453
- package/dist/index-c43kr12f.js +3030 -0
- package/dist/index-cb7emxgj.js +984 -0
- package/dist/index-d9vfe7xq.js +16 -0
- package/dist/{index-5gq3b2ya.js → index-db7zwa3v.js} +147 -209
- package/dist/index-dhwzyd54.js +1142 -0
- package/dist/{index-8da2zjhz.js → index-eeezr5zz.js} +9 -7
- package/dist/{index-cwf6s3ay.js → index-f0h6xwqm.js} +2828 -2618
- package/dist/index-fb3zxn06.js +13 -0
- package/dist/index-fbv1dn35.js +171 -0
- package/dist/index-fr0wbhdn.js +43 -0
- package/dist/{index-mc22ayvf.js → index-ghc9f0n7.js} +11 -9
- package/dist/{index-fzbvakh0.js → index-jcbd3znx.js} +3 -3
- package/dist/{index-5a2r0p9f.js → index-k1xb52kd.js} +20 -13
- package/dist/index-k9nnwad5.js +3532 -0
- package/dist/{index-wx8a6bw3.js → index-kb9nn0a0.js} +270 -53
- package/dist/index-knh4y330.js +566 -0
- package/dist/{v2/server-fq7kq32k.js → index-mfkzp7qj.js} +1 -16
- package/dist/{index-gg8j07zz.js → index-mmyh6d8f.js} +4 -4
- package/dist/index-pavzsdc6.js +17 -0
- package/dist/{index-0c82743p.js → index-pdecwzrd.js} +17 -15
- package/dist/index-pg50n748.js +1060 -0
- package/dist/{index-92bp57hg.js → index-q2tqeqde.js} +123 -80
- package/dist/{index-rrrsepyw.js → index-q7h7csab.js} +90 -85
- package/dist/{v2/server-yr3zj7e7.js → index-qt1qqasc.js} +6 -7
- package/dist/{index-6wkcswft.js → index-ty64eqcn.js} +28 -18
- package/dist/{index-adwfkpex.js → index-yq8n9qcb.js} +23 -23
- package/dist/{index-9pk9exrb.js → index-z8e0psj8.js} +18 -18
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +586 -344
- package/dist/logger-d3wex3dz.js +20 -0
- package/dist/message-index-bounded-7ezbgddp.js +124 -0
- package/dist/{v2/message-time-backfill-1f9tzvcs.js → message-time-backfill-brbd63hv.js} +8 -6
- package/dist/migration-worker.js +25 -18
- package/dist/{model-resolution-xhfmyyvy.js → model-resolution-nx97z3x7.js} +1 -1
- package/dist/plugin/dream-timer.d.ts +1 -1
- package/dist/plugin/dream-timer.d.ts.map +1 -1
- package/dist/plugin/hooks/create-session-hooks.d.ts +1 -0
- package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
- package/dist/plugin/host-stall-profiler-report.d.ts +1 -66
- package/dist/plugin/host-stall-profiler-report.d.ts.map +1 -1
- package/dist/plugin/host-stall-profiler.d.ts +2 -95
- package/dist/plugin/host-stall-profiler.d.ts.map +1 -1
- package/dist/plugin/messages-transform.d.ts +0 -13
- package/dist/plugin/messages-transform.d.ts.map +1 -1
- package/dist/plugin/rpc-handlers.d.ts.map +1 -1
- package/dist/plugin/tool-registry.d.ts.map +1 -1
- package/dist/project-embedding-registry-7qzptcw7.js +88 -0
- package/dist/raw-ordinal-warmup-worker.js +60 -0
- package/dist/{read-session-chunk-4jey7hpt.js → read-session-chunk-6k83m4fj.js} +15 -9
- package/dist/read-session-raw-3g9qy1xa.js +58 -0
- package/dist/recomp-orchestrator-d3fp1cy0.js +57 -0
- package/dist/{v2/safe-notification-target-eb1n1vfb.js → safe-notification-target-5ffqq32m.js} +4 -2
- package/dist/search-epax1ecv.js +45 -0
- package/dist/{v2/send-session-notification-c0wtscea.js → send-session-notification-erecz4y4.js} +10 -7
- package/dist/shared/conflict-detector.d.ts.map +1 -1
- package/dist/shared/host-stall-profiler-bun.d.ts +46 -0
- package/dist/shared/host-stall-profiler-bun.d.ts.map +1 -0
- package/dist/shared/host-stall-profiler-common.d.ts +58 -0
- package/dist/shared/host-stall-profiler-common.d.ts.map +1 -0
- package/dist/shared/host-stall-profiler-node.d.ts +36 -0
- package/dist/shared/host-stall-profiler-node.d.ts.map +1 -0
- package/dist/shared/host-stall-profiler-report.d.ts +68 -0
- package/dist/shared/host-stall-profiler-report.d.ts.map +1 -0
- package/dist/shared/host-stall-profiler.d.ts +5 -0
- package/dist/shared/host-stall-profiler.d.ts.map +1 -0
- package/dist/shared/model-resolution.d.ts +2 -3
- package/dist/shared/model-resolution.d.ts.map +1 -1
- package/dist/shared/sqlite.d.ts +30 -0
- package/dist/shared/sqlite.d.ts.map +1 -1
- package/dist/shared/stable-json.d.ts.map +1 -1
- package/dist/shared/user-facing-codes.d.ts +0 -5
- package/dist/shared/user-facing-codes.d.ts.map +1 -1
- package/dist/sqlite-context-pragmas-mv9jqwjh.js +6 -0
- package/dist/sqlite-mhjkerzq.js +46 -0
- package/dist/storage-memory-07fx57k6.js +71 -0
- package/dist/storage-tags-d3b0v2ss.js +131 -0
- package/dist/{task-config-v81k8jvk.js → task-config-cgpg0nvh.js} +2 -2
- package/dist/tools/ctx-expand/tools.d.ts.map +1 -1
- package/dist/tools/ctx-note/constants.d.ts +4 -0
- package/dist/tools/ctx-note/constants.d.ts.map +1 -1
- package/dist/tools/ctx-note/tools.d.ts +1 -0
- package/dist/tools/ctx-note/tools.d.ts.map +1 -1
- package/dist/tools/ctx-search/tools.d.ts.map +1 -1
- package/dist/tools/parameter-descriptions.d.ts +2 -2
- package/dist/tools/parameter-descriptions.d.ts.map +1 -1
- package/dist/{transform-postprocess-phase-z5hzpsxv.js → transform-postprocess-phase-spcy2qre.js} +35 -20
- package/dist/transformers-node-wasm.js +18415 -18415
- package/dist/v2/auto-search-worker.js +27 -30
- package/dist/v2/{context-14v1hr8b.js → context-sf98kstd.js} +3737 -3004
- package/dist/v2/{derive-budgets-nc9avxz8.js → derive-budgets-3vc0y84t.js} +4 -3
- package/dist/v2/embedding-activity-g1dhes6g.js +10 -0
- package/dist/v2/embedding-backfill-vn8g1nh1.js +21 -0
- package/dist/v2/embedding-cache-mgyr73ef.js +16 -0
- package/dist/v2/embedding-worker.js +12 -9
- package/dist/v2/fold/host-media.d.ts +4 -0
- package/dist/v2/fold/host-media.d.ts.map +1 -1
- package/dist/v2/fold/memory-cache.d.ts +70 -0
- package/dist/v2/fold/memory-cache.d.ts.map +1 -0
- package/dist/v2/fold/native-codec.d.ts +10 -0
- package/dist/v2/fold/native-codec.d.ts.map +1 -0
- package/dist/v2/fold/native-replay.d.ts +58 -0
- package/dist/v2/fold/native-replay.d.ts.map +1 -0
- package/dist/v2/fold/policy.d.ts +24 -0
- package/dist/v2/fold/policy.d.ts.map +1 -0
- package/dist/v2/harness-e4avh192.js +10 -0
- package/dist/v2/hooks/context.d.ts +2 -2
- package/dist/v2/hooks/context.d.ts.map +1 -1
- package/dist/v2/hooks/dream-manual.d.ts +1 -1
- package/dist/v2/hooks/dream-manual.d.ts.map +1 -1
- package/dist/v2/hooks/dream-timer.d.ts.map +1 -1
- package/dist/v2/hooks/dream-trigger.d.ts +1 -2
- package/dist/v2/hooks/dream-trigger.d.ts.map +1 -1
- package/dist/v2/hooks/payload.d.ts.map +1 -1
- package/dist/v2/hooks/tools.d.ts.map +1 -1
- package/dist/v2/hooks/types.d.ts +6 -0
- package/dist/v2/hooks/types.d.ts.map +1 -1
- package/dist/v2/logger-mxd0ym09.js +19 -0
- package/dist/v2/message-index-bounded-dy3s2k1e.js +123 -0
- package/dist/{message-time-backfill-r5epkzj3.js → v2/message-time-backfill-gtx1pwk1.js} +7 -7
- package/dist/v2/migration-worker.js +24 -17
- package/dist/v2/{model-resolution-xhfmyyvy.js → model-resolution-nx97z3x7.js} +1 -1
- package/dist/v2/project-embedding-registry-1tgba5dv.js +86 -0
- package/dist/v2/raw-ordinal-warmup-worker.js +60 -0
- package/dist/v2/{read-session-chunk-gyyv7w2r.js → read-session-chunk-rh4khdkv.js} +14 -8
- package/dist/v2/read-session-raw-bsbmf0vj.js +57 -0
- package/dist/v2/recomp-orchestrator-az61rfcg.js +57 -0
- package/dist/{safe-notification-target-43r8jsxw.js → v2/safe-notification-target-73ax1p5v.js} +3 -3
- package/dist/v2/search-nzkwrc6n.js +45 -0
- package/dist/{send-session-notification-0m68ms3n.js → v2/send-session-notification-6km439kn.js} +9 -8
- package/dist/{index-5eqk6z3s.js → v2/server-1r6pmz4f.js} +301 -27
- package/dist/v2/server-2bvekkfy.js +11 -0
- package/dist/v2/server-2fbhp79z.js +3205 -0
- package/dist/v2/{server-ajzeteqw.js → server-2ra6pwf3.js} +1 -18
- package/dist/v2/server-4dhv7mqz.js +131 -0
- package/dist/v2/{server-y10vbq6y.js → server-4k748ke6.js} +11 -1053
- package/dist/v2/{server-vs5gpnd4.js → server-52awr2mw.js} +81 -145
- package/dist/v2/{server-1qbnzc80.js → server-5m3dt5r1.js} +136 -148
- package/dist/v2/server-686jg6eb.js +3508 -0
- package/dist/v2/server-7jzrrxap.js +931 -0
- package/dist/v2/server-7wwc2nga.js +3023 -0
- package/dist/v2/server-8ajstryz.js +18 -0
- package/dist/v2/{server-sfpzqvdz.js → server-8cd2j99z.js} +2 -3
- package/dist/v2/{server-d0sraw7m.js → server-8pyt7hev.js} +291 -286
- package/dist/v2/server-8tqanswc.js +984 -0
- package/dist/v2/{server-14vq4kpm.js → server-aan4q8mx.js} +3 -3
- package/dist/v2/server-d9vfe7xq.js +16 -0
- package/dist/{index-x3kwrmqk.js → v2/server-e0vdaae2.js} +35 -792
- package/dist/v2/server-ezhze64f.js +1048 -0
- package/dist/v2/server-fb3zxn06.js +13 -0
- package/dist/v2/server-fr0wbhdn.js +43 -0
- package/dist/v2/server-g5r0n3b6.js +1137 -0
- package/dist/v2/server-gjcr4w98.js +154 -0
- package/dist/v2/server-k228xhjg.js +171 -0
- package/dist/v2/{server-nf82q6pt.js → server-k8x2rbxc.js} +5946 -5602
- package/dist/v2/{server-wx8a6bw3.js → server-kb9nn0a0.js} +270 -53
- package/dist/{index-rrbbspwh.js → v2/server-mfkzp7qj.js} +1 -16
- package/dist/v2/server-pavzsdc6.js +17 -0
- package/dist/v2/{server-e0c1b7a7.js → server-psqc7e9n.js} +122 -79
- package/dist/{index-yr3zj7e7.js → v2/server-qt1qqasc.js} +6 -7
- package/dist/v2/server-qye6ykf7.js +120 -0
- package/dist/v2/{server-qdjnb2z1.js → server-r5p3b1wy.js} +11 -9
- package/dist/v2/server-sggvvzhb.js +759 -0
- package/dist/v2/{server-cpepxy2q.js → server-v06jcv0w.js} +14 -12
- package/dist/v2/server-vqpf3167.js +1048 -0
- package/dist/v2/{server-rz514f14.js → server-x2g40a71.js} +2044 -2060
- package/dist/v2/{server-vd4e7174.js → server-xdfwt6kh.js} +20 -16
- package/dist/v2/{server-efhwzx05.js → server-xxm59eww.js} +23 -23
- package/dist/v2/server-yczc713m.js +564 -0
- package/dist/v2/{server-fcdehk1s.js → server-z2037m6z.js} +4 -4
- package/dist/v2/{server-50hvkg3v.js → server-zm570tr2.js} +160 -158
- package/dist/v2/{server-6r257mf5.js → server-zxhgvsf9.js} +3 -3
- package/dist/v2/server.js +16 -14
- package/dist/v2/sqlite-context-pragmas-mv9jqwjh.js +6 -0
- package/dist/v2/sqlite-mhjkerzq.js +46 -0
- package/dist/v2/storage-memory-07fx57k6.js +71 -0
- package/dist/v2/storage-tags-w4tv77sn.js +130 -0
- package/dist/v2/store-reader.d.ts +16 -0
- package/dist/v2/store-reader.d.ts.map +1 -1
- package/dist/v2/{task-config-tbndqyny.js → task-config-x0hq3qfd.js} +2 -2
- package/dist/v2/transformers-node-wasm.js +18415 -18415
- package/dist/v2/tui/index.d.ts.map +1 -1
- package/dist/v2/tui/types.d.ts +1 -10
- package/dist/v2/tui/types.d.ts.map +1 -1
- package/dist/v2/{wrapup-orchestrator-nbz854vc.js → wrapup-orchestrator-mz7efs7w.js} +51 -30
- package/dist/wrapup-orchestrator-amzta1t4.js +44 -0
- package/package.json +4 -3
- package/src/agents/magic-context-prompt.ts +27 -2
- package/src/agents/smart-notes-enabled.test.ts +294 -0
- package/src/agents/smart-notes-on.golden.json +70 -0
- package/src/config/index.test.ts +67 -1
- package/src/config/index.ts +2 -0
- package/src/config/latch-permanence-guard.test.ts +4 -0
- package/src/config/mural-model-deprecation.ts +24 -0
- package/src/config/project-security.hostile-matrix.test.ts +4 -44
- package/src/config/project-security.test.ts +9 -14
- package/src/config/project-security.ts +13 -55
- package/src/config/schema/magic-context.test.ts +2 -2
- package/src/config/schema/magic-context.ts +16 -10
- package/src/features/magic-context/dreamer/task-registry.ts +6 -0
- package/src/shared/conflict-detector.test.ts +56 -0
- package/src/shared/conflict-detector.ts +16 -5
- package/src/shared/host-stall-profiler-bun.ts +358 -0
- package/src/shared/host-stall-profiler-common.ts +159 -0
- package/src/shared/host-stall-profiler-node.test.ts +234 -0
- package/src/shared/host-stall-profiler-node.ts +274 -0
- package/src/shared/host-stall-profiler-report.ts +248 -0
- package/src/shared/host-stall-profiler.ts +57 -0
- package/src/shared/model-resolution.test.ts +54 -17
- package/src/shared/model-resolution.ts +6 -17
- package/src/shared/sqlite.test.ts +52 -0
- package/src/shared/sqlite.ts +339 -23
- package/src/shared/stable-json-linear.test.ts +109 -0
- package/src/shared/stable-json.ts +37 -7
- package/src/shared/user-facing-codes.ts +2 -6
- package/src/shared/write-transaction-attribution.test.ts +2 -2
- package/src/v2/tui/host-contract.test.ts +41 -67
- package/src/v2/tui/index.ts +6 -214
- package/src/v2/tui/types.ts +5 -17
- package/dist/features/magic-context/checkout-claim-fake-subc.test-support.d.ts +0 -45
- package/dist/features/magic-context/checkout-claim-fake-subc.test-support.d.ts.map +0 -1
- package/dist/features/magic-context/checkout-claim.d.ts +0 -155
- package/dist/features/magic-context/checkout-claim.d.ts.map +0 -1
- package/dist/index-bb36vgr3.js +0 -6608
- package/dist/index-fnn5pjtt.js +0 -6554
- package/dist/recomp-orchestrator-rervg6q4.js +0 -42
- package/dist/v2/recomp-orchestrator-42vjba7p.js +0 -42
- package/dist/v2/server-3trjk1hx.js +0 -6360
- package/dist/v2/server-nm9n3aqq.js +0 -6461
- package/dist/wrapup-orchestrator-b2dztrar.js +0 -29
- /package/dist/{index-5prbx026.js → index-2pp04pmg.js} +0 -0
- /package/dist/v2/{index-5prbx026.js → index-2pp04pmg.js} +0 -0
package/src/shared/sqlite.ts
CHANGED
|
@@ -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
|
|
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 (
|
|
261
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
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
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
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
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
-
|
|
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
|
-
|
|
35
|
-
|
|
36
|
-
.
|
|
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
|
-
|
|
249
|
-
|
|
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: ["
|
|
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
|
-
"
|
|
152
|
+
"pi_fallback_adoption",
|
|
153
153
|
"note_nudge_trigger",
|
|
154
154
|
"user_memory_candidate_insert",
|
|
155
155
|
] as const;
|