@cortexkit/opencode-magic-context 0.49.10 → 0.49.12

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 (237) hide show
  1. package/README.md +1 -1
  2. package/dist/agents/smart-notes-dreamer-gate.fixture.d.ts +28 -0
  3. package/dist/agents/smart-notes-dreamer-gate.fixture.d.ts.map +1 -0
  4. package/dist/{announcement-hdbkt8v5.js → announcement-g789dmt6.js} +2 -2
  5. package/dist/auto-search-worker.js +4 -4
  6. package/dist/{compaction-marker-candidates-xxz35vwp.js → compaction-marker-candidates-v5c6997n.js} +3 -3
  7. package/dist/compaction-marker-candidates-worker.js +1 -1
  8. package/dist/config/agent-disable.d.ts +14 -0
  9. package/dist/config/agent-disable.d.ts.map +1 -1
  10. package/dist/config/dependency-notes.d.ts +34 -0
  11. package/dist/config/dependency-notes.d.ts.map +1 -0
  12. package/dist/config/schema/magic-context.d.ts.map +1 -1
  13. package/dist/{conflict-warning-hook-w3crzrar.js → conflict-warning-hook-f4x5wed7.js} +8 -8
  14. package/dist/{context-ey3ap3cc.js → context-dam8p201.js} +306 -119
  15. package/dist/{derive-budgets-3nbxsyss.js → derive-budgets-5306b1jt.js} +3 -3
  16. package/dist/embedding-backfill-qbfcbp87.js +21 -0
  17. package/dist/embedding-worker-process.js +2 -2
  18. package/dist/embedding-worker.js +6 -6
  19. package/dist/features/magic-context/compartment-chunk-embedding.d.ts +12 -1
  20. package/dist/features/magic-context/compartment-chunk-embedding.d.ts.map +1 -1
  21. package/dist/features/magic-context/dreamer/task-config.d.ts +22 -4
  22. package/dist/features/magic-context/dreamer/task-config.d.ts.map +1 -1
  23. package/dist/features/magic-context/dreamer/task-registry.d.ts +22 -0
  24. package/dist/features/magic-context/dreamer/task-registry.d.ts.map +1 -1
  25. package/dist/features/magic-context/dreamer/task-scheduler.d.ts +4 -1
  26. package/dist/features/magic-context/dreamer/task-scheduler.d.ts.map +1 -1
  27. package/dist/features/magic-context/memory/embedding-openai.d.ts +32 -0
  28. package/dist/features/magic-context/memory/embedding-openai.d.ts.map +1 -1
  29. package/dist/features/magic-context/memory/project-identity.d.ts +1 -0
  30. package/dist/features/magic-context/memory/project-identity.d.ts.map +1 -1
  31. package/dist/features/magic-context/memory/unborn-head.d.ts +34 -0
  32. package/dist/features/magic-context/memory/unborn-head.d.ts.map +1 -0
  33. package/dist/features/magic-context/memory-enabled.d.ts +5 -0
  34. package/dist/features/magic-context/memory-enabled.d.ts.map +1 -0
  35. package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
  36. package/dist/features/magic-context/search-pool-fixture.d.ts +39 -0
  37. package/dist/features/magic-context/search-pool-fixture.d.ts.map +1 -0
  38. package/dist/features/magic-context/search.d.ts.map +1 -1
  39. package/dist/features/magic-context/storage-tags.d.ts +2 -0
  40. package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
  41. package/dist/features/magic-context/transform-decision-log.d.ts +57 -2
  42. package/dist/features/magic-context/transform-decision-log.d.ts.map +1 -1
  43. package/dist/{history-owner-ty29fz0f.js → history-owner-xp3pngv7.js} +3 -3
  44. package/dist/hooks/magic-context/apply-operations.d.ts.map +1 -1
  45. package/dist/hooks/magic-context/compartment-prompt.d.ts +6 -0
  46. package/dist/hooks/magic-context/compartment-prompt.d.ts.map +1 -1
  47. package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
  48. package/dist/hooks/magic-context/compartment-runner-types.d.ts +3 -0
  49. package/dist/hooks/magic-context/compartment-runner-types.d.ts.map +1 -1
  50. package/dist/hooks/magic-context/compartment-trigger-error.d.ts +12 -0
  51. package/dist/hooks/magic-context/compartment-trigger-error.d.ts.map +1 -0
  52. package/dist/hooks/magic-context/historian-prompt-fit.d.ts +14 -2
  53. package/dist/hooks/magic-context/historian-prompt-fit.d.ts.map +1 -1
  54. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  55. package/dist/hooks/magic-context/pending-materialization.d.ts +2 -0
  56. package/dist/hooks/magic-context/pending-materialization.d.ts.map +1 -1
  57. package/dist/hooks/magic-context/producer-window-guard.d.ts.map +1 -1
  58. package/dist/hooks/magic-context/protected-tail-boundary.d.ts +12 -0
  59. package/dist/hooks/magic-context/protected-tail-boundary.d.ts.map +1 -1
  60. package/dist/hooks/magic-context/raw-exact-ordinal-read.d.ts +58 -0
  61. package/dist/hooks/magic-context/raw-exact-ordinal-read.d.ts.map +1 -0
  62. package/dist/hooks/magic-context/raw-ordinal-warmup.d.ts +7 -0
  63. package/dist/hooks/magic-context/raw-ordinal-warmup.d.ts.map +1 -1
  64. package/dist/hooks/magic-context/read-session-db.d.ts +5 -0
  65. package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
  66. package/dist/hooks/magic-context/read-session-raw.d.ts +19 -0
  67. package/dist/hooks/magic-context/read-session-raw.d.ts.map +1 -1
  68. package/dist/hooks/magic-context/recomp-orchestrator.d.ts +2 -0
  69. package/dist/hooks/magic-context/recomp-orchestrator.d.ts.map +1 -1
  70. package/dist/hooks/magic-context/render-options.d.ts +21 -0
  71. package/dist/hooks/magic-context/render-options.d.ts.map +1 -0
  72. package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
  73. package/dist/hooks/magic-context/tag-messages.d.ts +4 -0
  74. package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
  75. package/dist/hooks/magic-context/transform-compartment-phase.d.ts +2 -0
  76. package/dist/hooks/magic-context/transform-compartment-phase.d.ts.map +1 -1
  77. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  78. package/dist/hooks/magic-context/transform.d.ts +5 -7
  79. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  80. package/dist/hooks/magic-context/wrapup-orchestrator.d.ts.map +1 -1
  81. package/dist/{index-21919gcq.js → index-05n6ykca.js} +4 -4
  82. package/dist/{index-q76br5zn.js → index-1d289pq2.js} +26 -21
  83. package/dist/{index-w28y7d0z.js → index-1sarmj9z.js} +15 -15
  84. package/dist/{index-x57ep4fp.js → index-1wwh38fk.js} +323 -121
  85. package/dist/{index-pgy3h49n.js → index-2pgxcncf.js} +4 -4
  86. package/dist/{index-ffa8x2as.js → index-6sytd5w3.js} +18 -13
  87. package/dist/{index-16vwdyy5.js → index-6sz25c3s.js} +3 -3
  88. package/dist/{index-4hb8nt93.js → index-7h8a1xpc.js} +3 -3
  89. package/dist/{index-rg1cezmj.js → index-7zd5asz9.js} +140 -17
  90. package/dist/{index-jw4gbfkv.js → index-8ketfacn.js} +2 -2
  91. package/dist/{index-nenz4gpb.js → index-95s8xaj1.js} +6 -5
  92. package/dist/{index-bmwfzz28.js → index-9vqb5p1s.js} +4 -4
  93. package/dist/{index-0jz47061.js → index-a8bvhwqs.js} +190 -30
  94. package/dist/{index-wpwpn7nj.js → index-b16gpywn.js} +9 -9
  95. package/dist/{index-g7jkrz0x.js → index-bp5083x2.js} +1 -1
  96. package/dist/{index-mp2kghkv.js → index-dyvbsvga.js} +1 -1
  97. package/dist/{index-s178h9z8.js → index-f71thw8j.js} +1 -1
  98. package/dist/{index-kvw6xew3.js → index-fkx2qnvw.js} +2 -2
  99. package/dist/{index-f8cn4xqa.js → index-fwefky9w.js} +18 -5
  100. package/dist/{index-a43xq1pg.js → index-fx90bvjd.js} +5 -5
  101. package/dist/{index-0sahzkwr.js → index-g2q4htwp.js} +46 -2
  102. package/dist/{index-7bjgyaj1.js → index-gf0psee3.js} +243 -135
  103. package/dist/{index-mw7c950g.js → index-gp3kcpc4.js} +1 -1
  104. package/dist/{index-gjvjh960.js → index-hqkczed7.js} +1 -1
  105. package/dist/{index-mvvephtj.js → index-j75v2476.js} +1 -1
  106. package/dist/{index-150zz6fh.js → index-k29z4aqh.js} +1 -1
  107. package/dist/{index-b64n4d0h.js → index-kee4kn5j.js} +1 -1
  108. package/dist/index-ksdyrrav.js +52 -0
  109. package/dist/{index-angx1s0k.js → index-mmfa86mt.js} +16 -6
  110. package/dist/{index-9jvab89d.js → index-n6m03s3n.js} +2 -2
  111. package/dist/{index-q28hsbpg.js → index-nj7yykkx.js} +1 -1
  112. package/dist/{index-ghc9f0n7.js → index-p5y3k4g7.js} +29 -1
  113. package/dist/{index-6k86es2p.js → index-qtbdx42g.js} +54 -25
  114. package/dist/{index-a865mj02.js → index-tdn0zkw4.js} +4 -4
  115. package/dist/{index-0x9cn9w1.js → index-wqs4q74r.js} +8 -8
  116. package/dist/{index-swgpe402.js → index-x2xjyq8f.js} +11 -11
  117. package/dist/{index-a4b0gbyg.js → index-y9f76s3f.js} +1 -1
  118. package/dist/{index-3403gbzj.js → index-yx5kgp2x.js} +288 -127
  119. package/dist/index.d.ts.map +1 -1
  120. package/dist/index.js +97 -76
  121. package/dist/{logger-wn328tfg.js → logger-jm3sqqzr.js} +2 -2
  122. package/dist/{message-index-bounded-fskdyc81.js → message-index-bounded-nq6rp8xa.js} +16 -16
  123. package/dist/{message-index-6r1x9cqh.js → message-index-df7swgy1.js} +16 -16
  124. package/dist/{message-time-backfill-nb5hhnrt.js → message-time-backfill-qjge9044.js} +3 -3
  125. package/dist/migration-worker.js +11 -11
  126. package/dist/plugin/dream-timer.d.ts.map +1 -1
  127. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  128. package/dist/plugin/tool-registry.d.ts.map +1 -1
  129. package/dist/{project-embedding-registry-vy7sv9jt.js → project-embedding-registry-q0ysjyzc.js} +11 -11
  130. package/dist/raw-ordinal-warmup-worker.js +12 -7
  131. package/dist/{read-session-chunk-zgpvs423.js → read-session-chunk-ax05f7gr.js} +11 -11
  132. package/dist/{read-session-raw-gm6xj30v.js → read-session-raw-m56hc7v2.js} +7 -3
  133. package/dist/{recomp-orchestrator-77xc8wpe.js → recomp-orchestrator-a0mvby4e.js} +29 -29
  134. package/dist/{safe-notification-target-jdynm677.js → safe-notification-target-1szv1k5k.js} +3 -3
  135. package/dist/{search-72fkjwk2.js → search-fm002702.js} +23 -23
  136. package/dist/{send-session-notification-q8ngbap3.js → send-session-notification-y2wg3fkh.js} +6 -6
  137. package/dist/shared/data-path.d.ts +4 -0
  138. package/dist/shared/data-path.d.ts.map +1 -1
  139. package/dist/shared/prompt-surface-runtime.d.ts +5 -0
  140. package/dist/shared/prompt-surface-runtime.d.ts.map +1 -1
  141. package/dist/{storage-tags-35m4gms2.js → storage-tags-yygfb9c8.js} +7 -5
  142. package/dist/{task-config-cgpg0nvh.js → task-config-x3qmayd2.js} +6 -2
  143. package/dist/tools/ctx-note/tools.d.ts.map +1 -1
  144. package/dist/{transform-postprocess-phase-r8d406j0.js → transform-postprocess-phase-s84rdf32.js} +29 -29
  145. package/dist/v2/auto-search-worker.js +4 -4
  146. package/dist/v2/{compaction-marker-candidates-a15w3mqh.js → compaction-marker-candidates-1vqwr3s5.js} +2 -2
  147. package/dist/v2/compaction-marker-candidates-worker.js +1 -1
  148. package/dist/v2/{context-z2yagwy4.js → context-x60fa16g.js} +758 -286
  149. package/dist/v2/{derive-budgets-0rmpmxjw.js → derive-budgets-z25jw3py.js} +3 -3
  150. package/dist/v2/embedding-backfill-mbjyza2a.js +20 -0
  151. package/dist/v2/embedding-worker-process.js +1 -1
  152. package/dist/v2/embedding-worker.js +5 -5
  153. package/dist/v2/{history-owner-2cr9py37.js → history-owner-42e16w0n.js} +2 -2
  154. package/dist/v2/hooks/context.d.ts.map +1 -1
  155. package/dist/v2/hooks/dream-manual.d.ts +1 -0
  156. package/dist/v2/hooks/dream-manual.d.ts.map +1 -1
  157. package/dist/v2/hooks/dream-timer.d.ts +3 -1
  158. package/dist/v2/hooks/dream-timer.d.ts.map +1 -1
  159. package/dist/v2/hooks/dream-trigger.d.ts +6 -1
  160. package/dist/v2/hooks/dream-trigger.d.ts.map +1 -1
  161. package/dist/v2/hooks/payload.d.ts +1 -1
  162. package/dist/v2/hooks/payload.d.ts.map +1 -1
  163. package/dist/v2/hooks/transform-decision-binding.d.ts +15 -0
  164. package/dist/v2/hooks/transform-decision-binding.d.ts.map +1 -0
  165. package/dist/v2/hooks/transform-features.d.ts +40 -0
  166. package/dist/v2/hooks/transform-features.d.ts.map +1 -0
  167. package/dist/v2/{logger-te6e1j72.js → logger-7qt02bnb.js} +1 -1
  168. package/dist/v2/{message-index-9ezq6wze.js → message-index-5nayhm1r.js} +15 -15
  169. package/dist/v2/{message-index-bounded-rqc603f2.js → message-index-bounded-pgv1ndpb.js} +15 -15
  170. package/dist/v2/{message-time-backfill-rz1pnpaj.js → message-time-backfill-bsteyc4d.js} +2 -2
  171. package/dist/v2/migration-worker.js +10 -10
  172. package/dist/v2/{project-embedding-registry-ja23aygk.js → project-embedding-registry-jbmjc0p4.js} +12 -10
  173. package/dist/v2/raw-ordinal-warmup-worker.js +12 -7
  174. package/dist/v2/{read-session-chunk-7f87tg2q.js → read-session-chunk-hr3w5bjk.js} +10 -10
  175. package/dist/v2/{read-session-raw-h4azh85b.js → read-session-raw-b3tf6ra1.js} +6 -2
  176. package/dist/v2/recomp-orchestrator-8w3449eb.js +59 -0
  177. package/dist/v2/{safe-notification-target-936374xx.js → safe-notification-target-qg7n2s77.js} +2 -2
  178. package/dist/v2/{search-2td1b1wy.js → search-mhmxgq0e.js} +22 -22
  179. package/dist/v2/{send-session-notification-6n7chhyp.js → send-session-notification-jevgj9fe.js} +5 -5
  180. package/dist/v2/{server-npm52h2q.js → server-05xjtq6c.js} +1 -1
  181. package/dist/v2/{server-s6jqh8bj.js → server-0ppsweh6.js} +1 -1
  182. package/dist/v2/server-0s95v3en.js +49 -0
  183. package/dist/v2/{server-2hxypdx5.js → server-25tg45b4.js} +17 -12
  184. package/dist/v2/{server-44ryn9rb.js → server-2x42esxd.js} +3 -3
  185. package/dist/v2/{server-4qr18rfg.js → server-37ngj8qw.js} +10 -51
  186. package/dist/v2/{server-4zwx20yg.js → server-4c10404h.js} +3 -3
  187. package/dist/v2/{server-23znwjqk.js → server-50mkkhy1.js} +14 -11
  188. package/dist/v2/{server-c9w52qss.js → server-5gvkzzrf.js} +290 -76
  189. package/dist/v2/{server-7dv9wt9r.js → server-6pmqg9m4.js} +1 -1
  190. package/dist/v2/{server-ak7w74j9.js → server-83ygfha2.js} +4 -4
  191. package/dist/v2/{server-4rs8sm06.js → server-9ewkzqgd.js} +5 -5
  192. package/dist/v2/{server-kmapq3v0.js → server-bxpwy6fy.js} +18 -5
  193. package/dist/v2/{server-zrwaj29a.js → server-d8tj10db.js} +25 -20
  194. package/dist/v2/{server-cxsr0ng6.js → server-da07v4xp.js} +1 -1
  195. package/dist/v2/{server-9e5r8y60.js → server-f2xf5gcb.js} +46 -2
  196. package/dist/v2/{server-hn9fb3v0.js → server-f7jfmrrz.js} +2 -2
  197. package/dist/v2/{server-f27he3j1.js → server-fa75w6gp.js} +4 -4
  198. package/dist/v2/{server-njnx39q2.js → server-gvkm8xaj.js} +189 -29
  199. package/dist/v2/{server-ckrb5rm8.js → server-h0410h0v.js} +1 -1
  200. package/dist/v2/{server-nveratm5.js → server-kn9n2qgd.js} +1 -1
  201. package/dist/v2/{server-gc8x2xdb.js → server-m97brnat.js} +9 -9
  202. package/dist/v2/{server-z0rjemg1.js → server-nmrm2rjy.js} +8 -8
  203. package/dist/v2/{server-bx59ezg6.js → server-prg55b7k.js} +16 -6
  204. package/dist/v2/{server-89fcbe37.js → server-pwv4ezb0.js} +1 -1
  205. package/dist/v2/{server-r5p3b1wy.js → server-qd11g795.js} +29 -1
  206. package/dist/v2/{server-988cqjme.js → server-rrqpvwqd.js} +2 -2
  207. package/dist/v2/{server-4easnf78.js → server-sz8jj92q.js} +150 -18
  208. package/dist/v2/{server-7e087rvk.js → server-th4y11y7.js} +16 -16
  209. package/dist/v2/{server-9a6bwc12.js → server-vknbt0gq.js} +255 -135
  210. package/dist/v2/{server-63ha7f0f.js → server-yrvqaswb.js} +1 -1
  211. package/dist/v2/{server-xqf2d2mg.js → server-zs8d0s3b.js} +2 -2
  212. package/dist/v2/server.d.ts.map +1 -1
  213. package/dist/v2/server.js +13 -6
  214. package/dist/v2/{storage-tags-c4zfcxv4.js → storage-tags-a2gq6dw7.js} +6 -4
  215. package/dist/v2/store-reader.d.ts +4 -0
  216. package/dist/v2/store-reader.d.ts.map +1 -1
  217. package/dist/v2/{task-config-x0hq3qfd.js → task-config-nvz8mapa.js} +6 -2
  218. package/dist/v2/{wrapup-orchestrator-wg8dmmm9.js → wrapup-orchestrator-r82y780v.js} +30 -29
  219. package/dist/wrapup-orchestrator-vmt6z3q5.js +47 -0
  220. package/package.json +1 -1
  221. package/src/agents/smart-notes-dreamer-gate.fixture.ts +171 -0
  222. package/src/agents/smart-notes-dreamer-gate.golden.json +245 -0
  223. package/src/agents/smart-notes-dreamer-gate.test.ts +161 -0
  224. package/src/config/agent-disable.ts +13 -0
  225. package/src/config/dependency-notes.test.ts +114 -0
  226. package/src/config/dependency-notes.ts +80 -0
  227. package/src/config/schema/magic-context.ts +23 -14
  228. package/src/features/magic-context/dreamer/task-registry.ts +40 -0
  229. package/src/shared/chunk-vector-writer-guard.test.ts +72 -0
  230. package/src/shared/data-path.test.ts +35 -1
  231. package/src/shared/data-path.ts +57 -1
  232. package/src/shared/prompt-surface-runtime.test.ts +15 -0
  233. package/src/shared/prompt-surface-runtime.ts +12 -0
  234. package/dist/embedding-backfill-3h2m5n0q.js +0 -21
  235. package/dist/v2/embedding-backfill-vr7wdtrf.js +0 -20
  236. package/dist/v2/recomp-orchestrator-s5tdpsbs.js +0 -59
  237. package/dist/wrapup-orchestrator-b1z99yg5.js +0 -47
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  estimateTokens
3
- } from "./server-s6jqh8bj.js";
3
+ } from "./server-0ppsweh6.js";
4
4
  import {
5
5
  getHarness2
6
6
  } from "./server-pavzsdc6.js";
7
7
  import {
8
8
  log2
9
- } from "./server-9e5r8y60.js";
9
+ } from "./server-f2xf5gcb.js";
10
10
  import {
11
11
  inRootAsyncContext2
12
12
  } from "./server-wafzvyhg.js";
@@ -6,11 +6,11 @@ import {
6
6
  } from "./server-wafzvyhg.js";
7
7
  import {
8
8
  DEFAULT_LOCAL_EMBEDDING_MODEL
9
- } from "./server-7e087rvk.js";
9
+ } from "./server-th4y11y7.js";
10
10
  import {
11
11
  isUserHomeDirectory,
12
12
  setBootQuietPeriodForTests
13
- } from "./server-njnx39q2.js";
13
+ } from "./server-gvkm8xaj.js";
14
14
  import {
15
15
  isEmbeddingHostBusy2
16
16
  } from "./server-qt1qqasc.js";
@@ -20,17 +20,18 @@ import {
20
20
  import {
21
21
  sanitizeDiagnosticText,
22
22
  log2
23
- } from "./server-9e5r8y60.js";
23
+ } from "./server-f2xf5gcb.js";
24
24
  import {
25
25
  estimateTokens
26
- } from "./server-s6jqh8bj.js";
26
+ } from "./server-0ppsweh6.js";
27
27
  import {
28
28
  SYNAPSE_DEFAULT_MODEL,
29
29
  isSynapseEmbeddingTruncated,
30
30
  getSynapseBatchRequestKey,
31
31
  SynapseEmbeddingProvider
32
- } from "./server-988cqjme.js";
32
+ } from "./server-rrqpvwqd.js";
33
33
  import {
34
+ DEFAULT_COMPARTMENT_CHUNK_MAX_INPUT_TOKENS,
34
35
  CHUNK_WINDOW_SAFETY_RATIO,
35
36
  normalizeCompartmentChunkMaxInputTokens,
36
37
  buildCanonicalChunkTextFromFts,
@@ -44,8 +45,9 @@ import {
44
45
  chunkWindowSourceKey,
45
46
  loadUnembeddedSessionChunkCandidatesPolite,
46
47
  countSessionCompartmentEmbedCoverage,
48
+ countSessionCompartmentEmbedCoveragePolite,
47
49
  countUnembeddedSessionCompartmentsPolite
48
- } from "./server-9a6bwc12.js";
50
+ } from "./server-vknbt0gq.js";
49
51
  import {
50
52
  saveEmbeddingIfHashMatches,
51
53
  getMemoryEmbedCoverage,
@@ -57,10 +59,10 @@ import {
57
59
  resolveEmbeddingTextPrefixes,
58
60
  getEmbeddingProviderIdentity,
59
61
  LocalEmbeddingProvider
60
- } from "./server-44ryn9rb.js";
62
+ } from "./server-2x42esxd.js";
61
63
  import {
62
64
  logSlowWriteTransaction
63
- } from "./server-7dv9wt9r.js";
65
+ } from "./server-6pmqg9m4.js";
64
66
 
65
67
  // src/shared/background-batch-drain.ts
66
68
  async function drainBackgroundBatches(step, options = {}) {
@@ -141,7 +143,7 @@ function pruneSynapseBatchLedgerForProject(db, projectIdentity, ttlMs = SYNAPSE_
141
143
  }
142
144
 
143
145
  // src/features/magic-context/project-embedding-registry.ts
144
- import { createHash as createHash2, randomUUID } from "node:crypto";
146
+ import { createHash as createHash3, randomUUID } from "node:crypto";
145
147
 
146
148
  // src/features/magic-context/git-commits/storage-git-commit-embeddings.ts
147
149
  var saveStatements = new WeakMap;
@@ -461,6 +463,9 @@ function releaseGitSweepLease(db, projectPath, holderId) {
461
463
  });
462
464
  }
463
465
 
466
+ // src/features/magic-context/memory/embedding-openai.ts
467
+ import { createHash as createHash2 } from "node:crypto";
468
+
464
469
  // src/features/magic-context/memory/embedding-ssrf.ts
465
470
  var METADATA_HOSTNAMES = new Set(["metadata.google.internal", "metadata.goog"]);
466
471
  var IPV6_METADATA_HOSTS = new Set(["fd00:ec2::254"]);
@@ -560,6 +565,55 @@ var FAILURE_THRESHOLD = 3;
560
565
  var FAILURE_WINDOW_MS = 60000;
561
566
  var OPEN_DURATION_MS = 5 * 60000;
562
567
  var FETCH_TIMEOUT_MS = 30000;
568
+ var RETRY_AFTER_CAP_MS = 60000;
569
+ var RATE_LIMIT_BACKOFF_BASE_MS = 1000;
570
+ var RATE_LIMIT_BACKOFF_CAP_MS = 30000;
571
+ var RATE_LIMIT_BACKOFF_JITTER = 0.25;
572
+ var rateLimitStates = new Map;
573
+ function rateLimitStateKey(endpoint, apiKey) {
574
+ const keyHash = apiKey ? createHash2("sha256").update(apiKey).digest("hex").slice(0, 16) : "";
575
+ return `${endpoint}\x00${keyHash}`;
576
+ }
577
+ function parseRetryAfterMs(value, nowMs) {
578
+ const trimmed = value?.trim() ?? "";
579
+ if (!trimmed)
580
+ return null;
581
+ let delayMs;
582
+ if (/^\d+(?:\.\d+)?$/.test(trimmed)) {
583
+ delayMs = Number(trimmed) * 1000;
584
+ } else {
585
+ const at = Date.parse(trimmed);
586
+ if (!Number.isFinite(at))
587
+ return null;
588
+ delayMs = at - nowMs;
589
+ }
590
+ if (!(delayMs > 0))
591
+ return null;
592
+ return Math.min(Math.ceil(delayMs), RETRY_AFTER_CAP_MS);
593
+ }
594
+ function rateLimitBackoffMs(consecutive, random = Math.random) {
595
+ const exponent = Math.min(Math.max(0, Math.floor(consecutive)), 30);
596
+ const nominal = Math.min(RATE_LIMIT_BACKOFF_CAP_MS, RATE_LIMIT_BACKOFF_BASE_MS * 2 ** exponent);
597
+ const jitter = Math.min(1, Math.max(0, random())) * RATE_LIMIT_BACKOFF_JITTER;
598
+ return Math.min(RATE_LIMIT_BACKOFF_CAP_MS, Math.round(nominal * (1 + jitter)));
599
+ }
600
+ function sleepUnlessAborted(ms, signal) {
601
+ if (signal?.aborted)
602
+ return Promise.resolve(false);
603
+ return new Promise((resolve) => {
604
+ const onAbort = () => {
605
+ clearTimeout(timer);
606
+ resolve(false);
607
+ };
608
+ const timer = setTimeout(() => {
609
+ signal?.removeEventListener("abort", onAbort);
610
+ resolve(true);
611
+ }, ms);
612
+ signal?.addEventListener("abort", onAbort, { once: true });
613
+ });
614
+ }
615
+ var RATE_LIMITED = Symbol("rate-limited");
616
+ var maxInputTokensWarnings = new Set;
563
617
 
564
618
  class OpenAICompatibleEmbeddingProvider {
565
619
  modelId;
@@ -580,6 +634,7 @@ class OpenAICompatibleEmbeddingProvider {
580
634
  lastFailureReason = null;
581
635
  halfOpenProbeInFlight = false;
582
636
  queryTruncationLogged = false;
637
+ rateLimitKey;
583
638
  constructor(options) {
584
639
  this.endpoint = normalizeEndpoint(options.endpoint);
585
640
  this.model = options.model?.trim() ?? "";
@@ -590,7 +645,16 @@ class OpenAICompatibleEmbeddingProvider {
590
645
  this.queryPrefix = prefixes.queryPrefix;
591
646
  this.documentPrefix = prefixes.documentPrefix;
592
647
  this.truncate = options.truncate?.trim() ?? "";
593
- this.maxInputTokens = typeof options.maxInputTokens === "number" && Number.isFinite(options.maxInputTokens) ? Math.max(1, Math.floor(options.maxInputTokens)) : 512;
648
+ this.rateLimitKey = rateLimitStateKey(this.endpoint, this.apiKey);
649
+ const maxInputTokensSet = typeof options.maxInputTokens === "number" && Number.isFinite(options.maxInputTokens);
650
+ this.maxInputTokens = maxInputTokensSet ? Math.max(1, Math.floor(options.maxInputTokens)) : DEFAULT_COMPARTMENT_CHUNK_MAX_INPUT_TOKENS;
651
+ if (!maxInputTokensSet && this.endpoint && this.model) {
652
+ const warningKey = `${this.endpoint}\x00${this.model}`;
653
+ if (!maxInputTokensWarnings.has(warningKey)) {
654
+ maxInputTokensWarnings.add(warningKey);
655
+ log2(`[magic-context] embedding.max_input_tokens is not set for openai-compatible model "${sanitizeDiagnosticText(this.model)}"; chunk embeddings use the ${DEFAULT_COMPARTMENT_CHUNK_MAX_INPUT_TOKENS}-token default, which is sized for the bundled local model and splits history into small pieces. Set embedding.max_input_tokens to the model's input limit (changing it re-embeds stored chunks once).`);
656
+ }
657
+ }
594
658
  this.modelId = getEmbeddingProviderIdentity({
595
659
  provider: "openai-compatible",
596
660
  endpoint: this.endpoint,
@@ -648,6 +712,23 @@ class OpenAICompatibleEmbeddingProvider {
648
712
  if (signal?.aborted) {
649
713
  return Array.from({ length: texts.length }, () => null);
650
714
  }
715
+ const isQuery = purpose === "query";
716
+ for (;; ) {
717
+ if (Date.now() < this.rateLimit.until) {
718
+ if (isQuery)
719
+ return Array.from({ length: texts.length }, () => null);
720
+ if (!await this.waitForRateLimitCooldown(signal)) {
721
+ return Array.from({ length: texts.length }, () => null);
722
+ }
723
+ }
724
+ const outcome = await this.requestOnce(texts, requestTexts, signal, purpose);
725
+ if (outcome !== RATE_LIMITED)
726
+ return outcome;
727
+ if (isQuery)
728
+ return Array.from({ length: texts.length }, () => null);
729
+ }
730
+ }
731
+ async requestOnce(texts, requestTexts, signal, purpose) {
651
732
  let isProbe = false;
652
733
  let internalController;
653
734
  let timeoutHandle;
@@ -680,9 +761,14 @@ class OpenAICompatibleEmbeddingProvider {
680
761
  redirect: "error",
681
762
  signal: internalController.signal
682
763
  });
764
+ if (response.status === 429) {
765
+ await response.text().catch(() => "");
766
+ this.noteRateLimit(response.headers.get("retry-after"));
767
+ return RATE_LIMITED;
768
+ }
683
769
  if (!response.ok) {
684
770
  const excerpt = await response.text().catch(() => "");
685
- const failure = this.failure("http_error", `HTTP ${response.status} from endpoint${this.bodyExcerpt(excerpt)}`, response.status >= 500 || response.status === 408 || response.status === 429);
771
+ const failure = this.failure("http_error", `HTTP ${response.status} from endpoint${this.bodyExcerpt(excerpt)}`, response.status >= 500 || response.status === 408);
686
772
  log2(`[magic-context] openai-compatible embedding request failed: ${failure.reason}`);
687
773
  this.recordFailure(isProbe, failure);
688
774
  return Array.from({ length: texts.length }, () => null);
@@ -781,6 +867,36 @@ class OpenAICompatibleEmbeddingProvider {
781
867
  isLoaded() {
782
868
  return this.initialized;
783
869
  }
870
+ get rateLimit() {
871
+ let state = rateLimitStates.get(this.rateLimitKey);
872
+ if (!state) {
873
+ state = { until: 0, consecutive: 0 };
874
+ rateLimitStates.set(this.rateLimitKey, state);
875
+ }
876
+ return state;
877
+ }
878
+ async waitForRateLimitCooldown(signal) {
879
+ for (;; ) {
880
+ const remaining = this.rateLimit.until - Date.now();
881
+ if (remaining <= 0)
882
+ return true;
883
+ if (!await sleepUnlessAborted(remaining, signal))
884
+ return false;
885
+ }
886
+ }
887
+ noteRateLimit(retryAfter) {
888
+ const state = this.rateLimit;
889
+ const now = Date.now();
890
+ const headerDelayMs = parseRetryAfterMs(retryAfter, now);
891
+ const delayMs = headerDelayMs ?? rateLimitBackoffMs(state.consecutive);
892
+ state.consecutive += 1;
893
+ const alreadyCoolingDown = now < state.until;
894
+ state.until = Math.max(state.until, now + delayMs);
895
+ const seconds = Math.ceil(delayMs / 1000);
896
+ if (!alreadyCoolingDown) {
897
+ log2(`[magic-context] openai-compatible embedding rate limited (HTTP 429): pausing requests for ${seconds}s (${headerDelayMs !== null ? "Retry-After" : "backoff"}); background embedding resumes after the pause and searches run lexical-only until then`);
898
+ }
899
+ }
784
900
  claimProbeOrShortCircuit() {
785
901
  if (this.circuitOpenUntil === 0) {
786
902
  return "allow";
@@ -835,6 +951,7 @@ class OpenAICompatibleEmbeddingProvider {
835
951
  this.circuitOpenUntil = 0;
836
952
  this.openLogged = false;
837
953
  this.lastFailureReason = null;
954
+ this.rateLimit.consecutive = 0;
838
955
  }
839
956
  getLastFailureReason() {
840
957
  return this.lastFailureReason;
@@ -850,6 +967,9 @@ class OpenAICompatibleEmbeddingProvider {
850
967
  _getFailureCount() {
851
968
  return this.failureTimes.length;
852
969
  }
970
+ _getRateLimitedUntil() {
971
+ return this.rateLimit.until;
972
+ }
853
973
  _resetCircuit() {
854
974
  this.failureTimes = [];
855
975
  this.circuitOpenUntil = 0;
@@ -1304,10 +1424,10 @@ function stableStringify(value) {
1304
1424
  return JSON.stringify(value);
1305
1425
  }
1306
1426
  function sha256Prefix(value, length = 16) {
1307
- return createHash2("sha256").update(value).digest("hex").slice(0, length);
1427
+ return createHash3("sha256").update(value).digest("hex").slice(0, length);
1308
1428
  }
1309
1429
  function contentSha2562(value) {
1310
- return createHash2("sha256").update(value).digest("hex");
1430
+ return createHash3("sha256").update(value).digest("hex");
1311
1431
  }
1312
1432
  function getRuntimeFingerprint(config) {
1313
1433
  if (config.provider === "off") {
@@ -2631,7 +2751,7 @@ async function drainCommitBacklogForProject2(db, projectIdentity, deadline) {
2631
2751
  }
2632
2752
  return total;
2633
2753
  }
2634
- async function embedCompartmentChunkBatch(db, projectIdentity, batchSize) {
2754
+ async function embedCompartmentChunkBatch(db, projectIdentity, batchSize, signal) {
2635
2755
  const snapshot = getProjectEmbeddingSnapshot2(projectIdentity);
2636
2756
  if (!snapshot?.historyEnabled || snapshot.chunkModelId === "off")
2637
2757
  return 0;
@@ -2639,7 +2759,7 @@ async function embedCompartmentChunkBatch(db, projectIdentity, batchSize) {
2639
2759
  const candidates = await loadUnembeddedCompartmentChunkCandidatesPolite(db, projectIdentity, snapshot.chunkModelId, batchSize, getProjectEmbeddingMaxInputTokens2(projectIdentity), true);
2640
2760
  if (candidates.length === 0)
2641
2761
  return 0;
2642
- const { embedded } = await embedCandidateChunkBatch(db, projectIdentity, snapshot.chunkModelId, candidates);
2762
+ const { embedded } = await embedCandidateChunkBatch(db, projectIdentity, snapshot.chunkModelId, candidates, signal);
2643
2763
  return embedded;
2644
2764
  }
2645
2765
  function getLastEmbeddingFailureForProject(projectIdentity) {
@@ -2776,6 +2896,9 @@ async function drainCompartmentChunkBacklogForProject(db, projectIdentity, deadl
2776
2896
  }
2777
2897
  let total = 0;
2778
2898
  let leaseLost = false;
2899
+ const drainAbort = new AbortController;
2900
+ const deadlineTimer = setTimeout(() => drainAbort.abort(), Math.max(0, deadline - Date.now()));
2901
+ deadlineTimer.unref?.();
2779
2902
  const renewal = inRootAsyncContext2(() => setInterval(() => {
2780
2903
  try {
2781
2904
  if (!renewGitSweepLease(db, projectIdentity, holderId))
@@ -2784,8 +2907,8 @@ async function drainCompartmentChunkBacklogForProject(db, projectIdentity, deadl
2784
2907
  }, SESSION_EMBED_LEASE_RENEWAL_MS));
2785
2908
  renewal.unref?.();
2786
2909
  try {
2787
- while (!leaseLost && !isEmbeddingHostBusy2() && Date.now() < deadline && total < CHUNK_DRAIN_MAX_PER_SWEEP) {
2788
- const embedded = await embedCompartmentChunkBatch(db, projectIdentity, CHUNK_DRAIN_BATCH_SIZE);
2910
+ while (!leaseLost && !drainAbort.signal.aborted && !isEmbeddingHostBusy2() && Date.now() < deadline && total < CHUNK_DRAIN_MAX_PER_SWEEP) {
2911
+ const embedded = await embedCompartmentChunkBatch(db, projectIdentity, CHUNK_DRAIN_BATCH_SIZE, drainAbort.signal);
2789
2912
  if (!renewGitSweepLease(db, projectIdentity, holderId))
2790
2913
  leaseLost = true;
2791
2914
  if (leaseLost || embedded === 0)
@@ -2795,6 +2918,7 @@ async function drainCompartmentChunkBacklogForProject(db, projectIdentity, deadl
2795
2918
  break;
2796
2919
  }
2797
2920
  } finally {
2921
+ clearTimeout(deadlineTimer);
2798
2922
  clearInterval(renewal);
2799
2923
  releaseGitSweepLease(db, projectIdentity, holderId);
2800
2924
  }
@@ -2940,6 +3064,14 @@ function getEmbeddingCoverageStatus2(db, projectIdentity, sessionId) {
2940
3064
  shadowBackfillStalls: listShadowBackfillStalls2(db, projectIdentity)
2941
3065
  };
2942
3066
  }
3067
+ async function getAutoEmbeddingSessionCoverage2(db, projectIdentity, sessionId) {
3068
+ const snapshot = getProjectEmbeddingSnapshot2(projectIdentity);
3069
+ if (!snapshot?.historyEnabled || snapshot.chunkModelId === "off") {
3070
+ return { enabled: false, embedded: 0, total: 0 };
3071
+ }
3072
+ const coverage = await countSessionCompartmentEmbedCoveragePolite(db, projectIdentity, sessionId, snapshot.chunkModelId, getProjectEmbeddingMaxInputTokens2(projectIdentity));
3073
+ return { enabled: true, ...coverage };
3074
+ }
2943
3075
  async function sweepAllRegisteredProjects2(db, batchSize = 10) {
2944
3076
  if (projectSweepInProgress || isEmbeddingHostBusy2()) {
2945
3077
  log2("[magic-context] project embedding sweep already in progress, skipping this tick");
@@ -3020,4 +3152,4 @@ function _resetProjectEmbeddingRegistryForTests2() {
3020
3152
  setBootQuietPeriodForTests(null);
3021
3153
  }
3022
3154
 
3023
- export { drainBackgroundBatches, recordEmbeddingMeasurement, saveCommitEmbedding, loadProjectCommitEmbeddings, loadUnembeddedCommits, countEmbeddedCommits, upsertCommits, getLatestIndexedCommitSha, enforceProjectCap, GIT_SWEEP_LEASE_RENEWAL_MS, acquireGitSweepLease, renewGitSweepLease, markGitSweepSuccessAndRelease, parkGitSweepNonIndexable, releaseGitSweepLease, OpenAICompatibleEmbeddingProvider, recordSessionProjectIdentity, hasRecordedSessionProjectIdentity, describeShadowBackfillWriteRefusal2, listShadowBackfillStalls2, getShadowBackfillStopReason2, markProjectLoadUntrusted2, contentSha2562, drainProjectEmbeddingIdentityMaintenance2, drainStaleEmbeddingIdentitiesForProject2, registerProjectEmbedding2, registerProjectShadowEmbedding2, getShadowEmbeddingMeasurementCohort2, getPrimaryEmbeddingMeasurementCohort2, embedShadowTextForProject2, enqueueShadowEmbeddingItems2, getShadowBackfillRemaining2, flushShadowEmbeddingBacklog2, registerProjectInObservationMode2, unregisterProjectShadowEmbedding2, unregisterProjectEmbedding2, getProjectEmbeddingSnapshot2, installProjectEmbeddingSearchBridge2, getProjectChunkEmbeddingModelId2, getProjectEmbeddingMaxInputTokens2, embedTextForProject2, embedBatchForProject2, embedItemsForProject2, embedUnembeddedMemoriesForProject2, embedUnembeddedMemoriesForProjectOutcome2, drainCommitBacklogForProject2, embedUnembeddedCompartmentChunksForProject2, embedSessionCompartmentChunks2, getEmbeddingCoverageStatus2, sweepAllRegisteredProjects2, _setTestProviderFactoryForProject2, _resetProjectEmbeddingRegistryForTests2 };
3155
+ export { drainBackgroundBatches, recordEmbeddingMeasurement, saveCommitEmbedding, loadProjectCommitEmbeddings, loadUnembeddedCommits, countEmbeddedCommits, upsertCommits, getLatestIndexedCommitSha, enforceProjectCap, GIT_SWEEP_LEASE_RENEWAL_MS, acquireGitSweepLease, renewGitSweepLease, markGitSweepSuccessAndRelease, parkGitSweepNonIndexable, releaseGitSweepLease, OpenAICompatibleEmbeddingProvider, recordSessionProjectIdentity, hasRecordedSessionProjectIdentity, describeShadowBackfillWriteRefusal2, listShadowBackfillStalls2, getShadowBackfillStopReason2, markProjectLoadUntrusted2, contentSha2562, drainProjectEmbeddingIdentityMaintenance2, drainStaleEmbeddingIdentitiesForProject2, registerProjectEmbedding2, registerProjectShadowEmbedding2, getShadowEmbeddingMeasurementCohort2, getPrimaryEmbeddingMeasurementCohort2, embedShadowTextForProject2, enqueueShadowEmbeddingItems2, getShadowBackfillRemaining2, flushShadowEmbeddingBacklog2, registerProjectInObservationMode2, unregisterProjectShadowEmbedding2, unregisterProjectEmbedding2, getProjectEmbeddingSnapshot2, installProjectEmbeddingSearchBridge2, getProjectChunkEmbeddingModelId2, getProjectEmbeddingMaxInputTokens2, embedTextForProject2, embedBatchForProject2, embedItemsForProject2, embedUnembeddedMemoriesForProject2, embedUnembeddedMemoriesForProjectOutcome2, drainCommitBacklogForProject2, embedUnembeddedCompartmentChunksForProject2, embedSessionCompartmentChunks2, getEmbeddingCoverageStatus2, getAutoEmbeddingSessionCoverage2, sweepAllRegisteredProjects2, _setTestProviderFactoryForProject2, _resetProjectEmbeddingRegistryForTests2 };
@@ -5659,7 +5659,7 @@ var DreamTasksSchema = object({
5659
5659
  max_tokens: 12000
5660
5660
  })),
5661
5661
  "evaluate-smart-notes": DreamTaskBaseConfigSchema.default(() => DreamTaskBaseConfigSchema.parse(defaultTaskConfig("evaluate-smart-notes"))),
5662
- "review-user-memories": ReviewUserMemoriesTaskConfigSchema.default(() => ReviewUserMemoriesTaskConfigSchema.parse(defaultTaskConfig("review-user-memories"))),
5662
+ "review-user-memories": ReviewUserMemoriesTaskConfigSchema.default(() => ReviewUserMemoriesTaskConfigSchema.parse(defaultTaskConfig("review-user-memories"))).describe("Promote recurring user observations into the <user-profile> block. A non-empty schedule also makes the historian collect user observations, but only while the dreamer is runnable (dreamer.disable not true); collection and review follow that one gate and do not depend on memory.enabled."),
5663
5663
  "promote-primers": PromotePrimersTaskConfigSchema.default(() => PromotePrimersTaskConfigSchema.parse(defaultTaskConfig("promote-primers"))),
5664
5664
  "refresh-primers": DreamTaskBaseConfigSchema.default(() => DreamTaskBaseConfigSchema.parse(defaultTaskConfig("refresh-primers")))
5665
5665
  }).describe("Harness-independent task metadata. schedule, promotion_threshold, and other task metadata remain here; execution settings live under dreamer.opencode.tasks, dreamer.pi.tasks, or dreamer.omp.tasks.");
@@ -5677,13 +5677,13 @@ var AgentMetadataSchema = AgentOverrideConfigSchema.pick({
5677
5677
  maxTokens: true
5678
5678
  });
5679
5679
  var DreamerConfigSchema = AgentMetadataSchema.extend({
5680
- disable: boolean2().optional().describe("Disable this agent"),
5680
+ disable: boolean2().optional().describe("Disable the dreamer: no scheduled or manual dream task runs. Also turns off smart notes (ctx_note drops surface_condition even with smart_notes.enabled true) and the historian's collection of user observations for review-user-memories. dreamer.inject_docs still applies."),
5681
5681
  runner: _enum(["broca", "host"]).optional().describe(`Which side runs the dreamer completions the Rust module routes (classify-memories) in Rust transform mode: "host" runs them on this process's carrier, "broca" routes them to the Broca module. When unset, historian.runner applies, and when that is unset too the harness decides the same way it does for the historian. User-level config only.`),
5682
5682
  opencode: DreamerOpenCodeHarnessBlockSchema.optional(),
5683
5683
  pi: DreamerPiHarnessBlockSchema.optional(),
5684
5684
  omp: DreamerOmpHarnessBlockSchema.optional(),
5685
5685
  tasks: DreamTasksSchema.default(() => DreamTasksSchema.parse({})),
5686
- inject_docs: boolean2().default(true).describe("Inject ARCHITECTURE.md and STRUCTURE.md into the m[0] `<project-docs>` block (default true)")
5686
+ inject_docs: boolean2().default(true).describe("Inject ARCHITECTURE.md and STRUCTURE.md into the m[0] `<project-docs>` block (default true). Not a dreamer setting despite its place under dreamer: it applies on every host, also with dreamer.disable true.")
5687
5687
  });
5688
5688
  var HistorianConfigSchema = AgentMetadataSchema.extend({
5689
5689
  expand_tools: record(string(), union([
@@ -5822,9 +5822,9 @@ var MagicContextConfigSchema = object({
5822
5822
  profile: string().trim().min(1).optional().describe("Select a named user-owned model profile. A valid project name overrides this user default; an empty string, null, or other non-string project value is ignored with a warning so the user selection still applies. Unknown names warn and use the base configuration."),
5823
5823
  profiles: ConfigProfilesSchema.optional().describe("User-level named model profiles. A profile may contain only historian/dreamer model, fallback_models, OpenCode variant, and Pi/OMP thinking_level fields; task execution policy (including timeout_minutes) is excluded. Project configs may select a name but cannot define profiles."),
5824
5824
  historian: HistorianConfigSchema.describe("Historian metadata plus independent strict OpenCode, Pi, and OMP execution blocks. Retained metadata stays at historian; model, fallback_models, variant, and thinking_level belong only in historian.opencode, historian.pi, or historian.omp."),
5825
- dreamer: DreamerConfigSchema.optional().describe("Dreamer metadata and scheduling plus independent strict OpenCode, Pi, and OMP execution blocks. schedule and promotion_threshold stay at dreamer.tasks; model, fallback_models, variant, thinking_level, and timeout_minutes belong only in the matching harness block."),
5825
+ dreamer: DreamerConfigSchema.optional().describe("Dreamer metadata and scheduling plus independent strict OpenCode, Pi, and OMP execution blocks. schedule and promotion_threshold stay at dreamer.tasks; model, fallback_models, variant, thinking_level, and timeout_minutes belong only in the matching harness block. Each task follows the setting it serves: memory tasks need memory.enabled, evaluate-smart-notes needs smart_notes.enabled, review-user-memories needs its schedule, maintain-docs only a runnable dreamer."),
5826
5826
  smart_notes: object({
5827
- enabled: boolean2().default(true).describe("Enable smart-note authoring and condition evaluation. User-level only: tool definitions are process-wide. Changes require a host restart and rebuild each session's cached prompt once. Pending notes remain stored and unchecked; already-ready notes still surface."),
5827
+ enabled: boolean2().default(true).describe("Enable smart-note authoring and condition evaluation. Needs a runnable dreamer, which evaluates the conditions: with dreamer.disable true (or no dreamer block) ctx_note offers no surface_condition whatever this says. User-level only: tool definitions are process-wide. Changes require a host restart and rebuild each session's cached prompt once. Pending notes remain stored and unchecked; already-ready notes still surface."),
5828
5828
  retina_handoff: boolean2().default(false).describe("When true, dreamer skips smart notes whose surface conditions compiled to retina provider configs at authoring time. Default false keeps both paths active until the retina consumer is deployed.")
5829
5829
  }).default({ enabled: true, retina_handoff: false }).describe("Smart-note ownership transition controls."),
5830
5830
  cache_ttl: union([string(), object({ default: string() }).catchall(string())]).default("5m").describe(`How long Magic Context assumes the provider's cached prefix stays valid. This is MC's own deferral gate — it does not change the provider's actual cache lifetime. String (e.g. "5m", "1h", "30s") or per-model object ({ default: "5m", "provider/model": "1h", "provider/*": "never" }); keys resolve most-specific first (exact provider/model, bare model ID, shorter dash-prefixes, then the provider/* wildcard, then default). User and project settings, including an explicit "5m" or object default, apply on the next pass. Only built-in defaults are frozen per session, including across restarts: when unset, GPT-5.6 and later (including gpt-6*, through any provider prefix) use 30m, other models use 5m. /ctx-status shows the effective TTL and whether it comes from your config or a frozen built-in default. Editing the TTL does not itself rewrite prompt bytes; a lowered TTL rebuilds only after normal idle expiry. OpenAI documents at least 30 minutes since the latest write or reuse: https://developers.openai.com/api/docs/guides/prompt-caching (Cache lifetime and Summary of model differences). Set to "never" to mean MC never assumes expiry (for lanes kept warm externally by a cache-keep tool) — disables the idle-TTL heuristic so MC never initiates a rebuild based on elapsed time. Provider-side extended TTL is a separate request-level concern (cache_control: { ttl } in the request body).`),
@@ -5852,11 +5852,11 @@ var MagicContextConfigSchema = object({
5852
5852
  object({ default: number2().int().min(0).max(1e6).optional() }).catchall(number2().int().min(0).max(1e6))
5853
5853
  ]).optional().describe("Reasoning tokens to keep on rebuilding passes. Number or per-model object; exact, shorter model keys, provider/*, then default. Omitted: fixed 10,000. 0 removes all eligible historical reasoning; newest and exempt steps always stay."),
5854
5854
  history_budget_percentage: number2().min(0.05).max(0.5).default(DEFAULT_HISTORY_BUDGET_PERCENTAGE).describe("Fraction of usable context (context_limit × execute_threshold) reserved for the session history block (default: 0.15)"),
5855
- historian_timeout_ms: number2().min(60000).default(DEFAULT_HISTORIAN_TIMEOUT_MS).describe("Timeout for each historian prompt call in both TypeScript and Rust transform modes, in milliseconds (default: 600000)"),
5855
+ historian_timeout_ms: number2().min(60000).default(DEFAULT_HISTORIAN_TIMEOUT_MS).describe("Timeout for each historian prompt call in both TypeScript and Rust transform modes, in milliseconds (default: 600000). A historian setting kept at the top level for compatibility; no effect while historian.disable is true or compaction.enabled is false."),
5856
5856
  commit_cluster_trigger: object({
5857
5857
  enabled: boolean2().default(true).describe("Enable commit-cluster based historian triggering (default: true)"),
5858
5858
  min_clusters: number2().min(1).default(3).describe("Minimum commit clusters required to trigger historian (min: 1, default: 3)")
5859
- }).default({ enabled: true, min_clusters: 3 }).describe("Commit-cluster trigger: fire historian when enough commit clusters accumulate in the unsummarized tail"),
5859
+ }).default({ enabled: true, min_clusters: 3 }).describe("Commit-cluster trigger: fire historian when enough commit clusters accumulate in the unsummarized tail. A historian setting kept at the top level for compatibility; no effect while historian.disable is true or compaction.enabled is false."),
5860
5860
  system_prompt_injection: object({
5861
5861
  enabled: boolean2().default(true).describe("When false, NO injection happens for ANY agent — global escape hatch. (default: true)"),
5862
5862
  skip_signatures: array(string()).default(["<!-- magic-context: skip -->"]).describe(`Substring opt-out list. If the agent's system prompt contains any of these strings, skip ALL Magic Context injection for that call. Default "<!-- magic-context: skip -->" is meant to be added inside a user's custom agent prompt to opt that agent out.`)
@@ -5901,20 +5901,20 @@ var MagicContextConfigSchema = object({
5901
5901
  min_chars: number2().min(100).max(1e4).default(500).describe("Text parts shorter than this (characters) stay untouched. Min 100, max 10000. Default: 500.")
5902
5902
  }).default({ enabled: false, min_chars: 500 }).describe("Age-tier caveman compression for long user/assistant text parts. Active for primary sessions when enabled; never for subagents. Oldest 20% of eligible tags (outside protected tail) go to ultra, next 20% to full, next 20% to lite, newest 40% untouched. Graduated from experimental.caveman_text_compression; opt-in, default off (lossy)."),
5903
5903
  memory: object({
5904
- enabled: boolean2().default(true).describe("Enable cross-session memory (default: true). Does not affect history embedding or semantic ctx_search over session history; set embedding.provider to 'off' to stop all embedding."),
5904
+ enabled: boolean2().default(true).describe("Enable cross-session project memory (default: true). Also gates the dreamer's project-memory tasks: while false, map-memories, verify, verify-broad, curate, compress-cues, classify-memories, retrospective, promote-primers and refresh-primers neither run on schedule nor through /ctx-dream; maintain-docs, evaluate-smart-notes and review-user-memories still run. memory.auto_search and memory.git_commit_indexing do not depend on it. Does not affect history embedding or semantic ctx_search over session history; set embedding.provider to 'off' to stop all embedding."),
5905
5905
  injection_budget_tokens: number2().min(500).max(20000).default(4000).describe("Token budget for memory injection on session start (min: 500, max: 20000, default: 4000)"),
5906
- auto_promote: boolean2().default(true).describe("Automatically promote eligible session facts into memory (default: true)"),
5907
- retrieval_count_promotion_threshold: number2().min(1).default(3).describe("retrieval_count threshold for promoting memory to permanent status (min: 1, default: 3)"),
5906
+ auto_promote: boolean2().default(true).describe("Automatically promote eligible session facts into memory (default: true). No effect while memory.enabled is false."),
5907
+ retrieval_count_promotion_threshold: number2().min(1).default(3).describe("Currently has no effect: no code reads this value, and memories are not promoted to permanent by retrieval count. Kept so existing configs stay valid (min: 1, default: 3)."),
5908
5908
  auto_search: object({
5909
- enabled: boolean2().default(true).describe("Automatically append a compact <ctx-search-hint> to eligible user messages when relevant memories, conversation, or commits are found. Graduated from experimental.auto_search; on by default (set false to opt out). Independent of memory.enabled."),
5909
+ enabled: boolean2().default(true).describe("Automatically append a compact <ctx-search-hint> to eligible user messages when relevant memories, conversation, or commits are found. Graduated from experimental.auto_search; on by default (set false to opt out). Independent of memory.enabled despite its place under memory: with memory off it still searches past conversation and commits, only the memory source is skipped."),
5910
5910
  score_threshold: number2().min(0.3).max(0.95).default(0.6).describe("Top hit score must exceed this threshold for the hint to fire (min: 0.3, max: 0.95, default: 0.60)"),
5911
5911
  min_prompt_chars: number2().min(5).max(500).default(20).describe("Skip hint when user message is shorter than this (min: 5, max: 500, default: 20)")
5912
- }).default({ enabled: true, score_threshold: 0.6, min_prompt_chars: 20 }).describe("Auto-search hint: transform-time ctx_search on each new user message; when the top hit clears the threshold, append a compact <ctx-search-hint> block of vague fragments to that user message. Does NOT inject full content. Graduated from experimental.auto_search; enabled by default (set enabled: false to opt out). Independent of memory.enabled."),
5912
+ }).default({ enabled: true, score_threshold: 0.6, min_prompt_chars: 20 }).describe("Auto-search hint: transform-time ctx_search on each new user message; when the top hit clears the threshold, append a compact <ctx-search-hint> block of vague fragments to that user message. Does NOT inject full content. Graduated from experimental.auto_search; enabled by default (set enabled: false to opt out). Independent of memory.enabled despite its place under memory: with memory off it still searches past conversation and commits."),
5913
5913
  git_commit_indexing: object({
5914
- enabled: boolean2().default(false).describe("Index HEAD git commits for ctx_search (git_commit source). Graduated from experimental.git_commit_indexing; opt-in, default off. Independent of memory.enabled."),
5914
+ enabled: boolean2().default(false).describe("Index HEAD git commits for ctx_search (git_commit source). Graduated from experimental.git_commit_indexing; opt-in, default off. Independent of memory.enabled despite its place under memory."),
5915
5915
  since_days: number2().min(7).max(3650).default(365).describe("Days of HEAD history to index (min: 7, max: 3650, default: 365)"),
5916
5916
  max_commits: number2().min(100).max(20000).default(2000).describe("Max commits kept per project; oldest evicted (min: 100, max: 20000, default: 2000)")
5917
- }).default({ enabled: false, since_days: 365, max_commits: 2000 }).describe("Index git commit messages from HEAD into ctx_search. Commits become a 4th searchable source alongside memories and session history. Graduated from experimental.git_commit_indexing; opt-in, default off (per-project embedding cost). Independent of memory.enabled.")
5917
+ }).default({ enabled: false, since_days: 365, max_commits: 2000 }).describe("Index git commit messages from HEAD into ctx_search. Commits become a 4th searchable source alongside memories and session history. Graduated from experimental.git_commit_indexing; opt-in, default off (per-project embedding cost). Independent of memory.enabled despite its place under memory.")
5918
5918
  }).default({
5919
5919
  enabled: true,
5920
5920
  injection_budget_tokens: 4000,
@@ -5922,7 +5922,7 @@ var MagicContextConfigSchema = object({
5922
5922
  retrieval_count_promotion_threshold: 3,
5923
5923
  auto_search: { enabled: true, score_threshold: 0.6, min_prompt_chars: 20 },
5924
5924
  git_commit_indexing: { enabled: false, since_days: 365, max_commits: 2000 }
5925
- }).describe("Cross-session memory configuration")
5925
+ }).describe("Cross-session memory configuration. auto_search and git_commit_indexing sit here for history but work with memory.enabled false.")
5926
5926
  }).transform((data) => {
5927
5927
  return {
5928
5928
  ...data,
@@ -6001,4 +6001,4 @@ function deriveDefaultProtectedTokens(usableSoft) {
6001
6001
  return Math.min(64000, Math.max(lowerBound, target));
6002
6002
  }
6003
6003
 
6004
- export { string, unknown, array, object, union, tuple, record, withContentLanguageDirective, buildPrimaryLanguageDirective, parseCron, nextOccurrence, nextDueAtMs, renderToolTemplate, promptSurfaceConfigIdentity, resolveModelConfigValue, resolvePromptSurface, DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE, DEFAULT_HISTORIAN_TIMEOUT_MS, PROTECTED_TOKENS_MIN, DEFAULT_LOCAL_EMBEDDING_MODEL, PER_HARNESS_MIGRATION_INVENTORY, PER_HARNESS_MODEL_KEYS, ConfigProfilesSchema, DREAM_TASK_PROMOTION_DEFAULTS, MagicContextConfigSchema, LIVE_RELOAD_CONFIG_PATHS, deriveDefaultProtectedTokens };
6004
+ export { string, unknown, array, object, union, tuple, record, isValidLanguageCode, withContentLanguageDirective, buildPrimaryLanguageDirective, parseCron, nextOccurrence, nextDueAtMs, renderToolTemplate, promptSurfaceConfigIdentity, resolveModelConfigValue, resolvePromptSurface, DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE, DEFAULT_HISTORIAN_TIMEOUT_MS, PROTECTED_TOKENS_MIN, DEFAULT_LOCAL_EMBEDDING_MODEL, PER_HARNESS_MIGRATION_INVENTORY, PER_HARNESS_MODEL_KEYS, ConfigProfilesSchema, DREAM_TASK_PROMOTION_DEFAULTS, MagicContextConfigSchema, LIVE_RELOAD_CONFIG_PATHS, deriveDefaultProtectedTokens };