@cortexkit/opencode-magic-context 0.44.0 → 0.44.2

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 +6 -0
  2. package/dist/agents/dreamer.d.ts +4 -6
  3. package/dist/agents/dreamer.d.ts.map +1 -1
  4. package/dist/agents/magic-context-prompt.d.ts +2 -0
  5. package/dist/agents/magic-context-prompt.d.ts.map +1 -1
  6. package/dist/{announcement-1a8bvswd.js → announcement-n8hs7kjw.js} +2 -2
  7. package/dist/config/live-child-output-cap.d.ts +18 -0
  8. package/dist/config/live-child-output-cap.d.ts.map +1 -0
  9. package/dist/config/schema/magic-context.d.ts +64 -11
  10. package/dist/config/schema/magic-context.d.ts.map +1 -1
  11. package/dist/{conflict-warning-hook-48f7np9d.js → conflict-warning-hook-1msyvb51.js} +6 -6
  12. package/dist/{derive-budgets-8kgevxmx.js → derive-budgets-gd2270s0.js} +3 -3
  13. package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
  14. package/dist/features/magic-context/compartment-chunk-embedding.d.ts +11 -0
  15. package/dist/features/magic-context/compartment-chunk-embedding.d.ts.map +1 -1
  16. package/dist/features/magic-context/compartment-storage.d.ts.map +1 -1
  17. package/dist/features/magic-context/dreamer/docs-proposals.d.ts +2 -0
  18. package/dist/features/magic-context/dreamer/docs-proposals.d.ts.map +1 -1
  19. package/dist/features/magic-context/dreamer/manual-summary.d.ts.map +1 -1
  20. package/dist/features/magic-context/dreamer/map-memories-prompt.d.ts +1 -1
  21. package/dist/features/magic-context/dreamer/map-memories-prompt.d.ts.map +1 -1
  22. package/dist/features/magic-context/dreamer/map-memories.d.ts +5 -0
  23. package/dist/features/magic-context/dreamer/map-memories.d.ts.map +1 -1
  24. package/dist/features/magic-context/dreamer/open-opencode-db.d.ts +2 -0
  25. package/dist/features/magic-context/dreamer/open-opencode-db.d.ts.map +1 -1
  26. package/dist/features/magic-context/dreamer/primer-seed.d.ts +11 -5
  27. package/dist/features/magic-context/dreamer/primer-seed.d.ts.map +1 -1
  28. package/dist/features/magic-context/dreamer/refresh-primers.d.ts +7 -2
  29. package/dist/features/magic-context/dreamer/refresh-primers.d.ts.map +1 -1
  30. package/dist/features/magic-context/dreamer/retrospective-raw-provider.d.ts +2 -2
  31. package/dist/features/magic-context/dreamer/retrospective-raw-provider.d.ts.map +1 -1
  32. package/dist/features/magic-context/dreamer/storage-dream-runs.d.ts +8 -1
  33. package/dist/features/magic-context/dreamer/storage-dream-runs.d.ts.map +1 -1
  34. package/dist/features/magic-context/dreamer/task-config.d.ts.map +1 -1
  35. package/dist/features/magic-context/dreamer/task-executor.d.ts +5 -0
  36. package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
  37. package/dist/features/magic-context/dreamer/task-gates.d.ts.map +1 -1
  38. package/dist/features/magic-context/dreamer/task-prompts.d.ts +18 -2
  39. package/dist/features/magic-context/dreamer/task-prompts.d.ts.map +1 -1
  40. package/dist/features/magic-context/dreamer/task-registry.d.ts +12 -0
  41. package/dist/features/magic-context/dreamer/task-registry.d.ts.map +1 -1
  42. package/dist/features/magic-context/dreamer/task-scheduler.d.ts +3 -1
  43. package/dist/features/magic-context/dreamer/task-scheduler.d.ts.map +1 -1
  44. package/dist/features/magic-context/dreamer/token-budget.d.ts +33 -0
  45. package/dist/features/magic-context/dreamer/token-budget.d.ts.map +1 -0
  46. package/dist/features/magic-context/dreamer/verify-diff.d.ts +15 -0
  47. package/dist/features/magic-context/dreamer/verify-diff.d.ts.map +1 -0
  48. package/dist/features/magic-context/dreamer/verify-gate.d.ts.map +1 -1
  49. package/dist/features/magic-context/dreamer/verify-prompt.d.ts +5 -2
  50. package/dist/features/magic-context/dreamer/verify-prompt.d.ts.map +1 -1
  51. package/dist/features/magic-context/dreamer/verify-read-cap.d.ts +4 -0
  52. package/dist/features/magic-context/dreamer/verify-read-cap.d.ts.map +1 -0
  53. package/dist/features/magic-context/dreamer/verify.d.ts +5 -0
  54. package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
  55. package/dist/features/magic-context/git-commits/git-log-reader.d.ts.map +1 -1
  56. package/dist/features/magic-context/memory/project-identity-cache.d.ts +6 -0
  57. package/dist/features/magic-context/memory/project-identity-cache.d.ts.map +1 -0
  58. package/dist/features/magic-context/memory/project-identity.d.ts +15 -22
  59. package/dist/features/magic-context/memory/project-identity.d.ts.map +1 -1
  60. package/dist/features/magic-context/memory/storage-memory-fts.d.ts +1 -0
  61. package/dist/features/magic-context/memory/storage-memory-fts.d.ts.map +1 -1
  62. package/dist/features/magic-context/memory/verification-paths.d.ts +1 -0
  63. package/dist/features/magic-context/memory/verification-paths.d.ts.map +1 -1
  64. package/dist/features/magic-context/mural/mural-font.generated.d.ts.map +1 -1
  65. package/dist/features/magic-context/project-embedding-registry.d.ts +5 -0
  66. package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
  67. package/dist/features/magic-context/search.d.ts.map +1 -1
  68. package/dist/features/magic-context/session-activity.d.ts +10 -0
  69. package/dist/features/magic-context/session-activity.d.ts.map +1 -0
  70. package/dist/features/magic-context/session-cache-ttl.d.ts +10 -0
  71. package/dist/features/magic-context/session-cache-ttl.d.ts.map +1 -0
  72. package/dist/features/magic-context/session-project-backfill.d.ts +4 -1
  73. package/dist/features/magic-context/session-project-backfill.d.ts.map +1 -1
  74. package/dist/features/magic-context/smart-notes/compiler.d.ts +5 -0
  75. package/dist/features/magic-context/smart-notes/compiler.d.ts.map +1 -1
  76. package/dist/features/magic-context/smart-notes/sandbox-runner.d.ts +1 -0
  77. package/dist/features/magic-context/smart-notes/sandbox-runner.d.ts.map +1 -1
  78. package/dist/features/magic-context/smart-notes/storage.d.ts +1 -1
  79. package/dist/features/magic-context/smart-notes/storage.d.ts.map +1 -1
  80. package/dist/features/magic-context/smart-notes/types.d.ts +2 -0
  81. package/dist/features/magic-context/smart-notes/types.d.ts.map +1 -1
  82. package/dist/features/magic-context/storage-db.d.ts +2 -1
  83. package/dist/features/magic-context/storage-db.d.ts.map +1 -1
  84. package/dist/features/magic-context/storage-identity-merge.d.ts +4 -1
  85. package/dist/features/magic-context/storage-identity-merge.d.ts.map +1 -1
  86. package/dist/features/magic-context/storage-session-tables.d.ts.map +1 -1
  87. package/dist/features/magic-context/v22-deferred-backfill.d.ts.map +1 -1
  88. package/dist/hooks/auto-update-checker/checker.d.ts.map +1 -1
  89. package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
  90. package/dist/hooks/magic-context/compartment-runner-historian.d.ts.map +1 -1
  91. package/dist/hooks/magic-context/compartment-runner-recomp.d.ts.map +1 -1
  92. package/dist/hooks/magic-context/compartment-runner.d.ts +1 -0
  93. package/dist/hooks/magic-context/compartment-runner.d.ts.map +1 -1
  94. package/dist/hooks/magic-context/dropped-input-guard.d.ts.map +1 -1
  95. package/dist/hooks/magic-context/embed-session-state.d.ts +3 -0
  96. package/dist/hooks/magic-context/embed-session-state.d.ts.map +1 -1
  97. package/dist/hooks/magic-context/event-handler.d.ts +1 -0
  98. package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
  99. package/dist/hooks/magic-context/event-payloads.d.ts +1 -0
  100. package/dist/hooks/magic-context/event-payloads.d.ts.map +1 -1
  101. package/dist/hooks/magic-context/event-resolvers.d.ts.map +1 -1
  102. package/dist/hooks/magic-context/execute-status.d.ts.map +1 -1
  103. package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
  104. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  105. package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
  106. package/dist/hooks/magic-context/lkg-replay.d.ts +6 -4
  107. package/dist/hooks/magic-context/lkg-replay.d.ts.map +1 -1
  108. package/dist/hooks/magic-context/module-state-sync.d.ts.map +1 -1
  109. package/dist/hooks/magic-context/module-wire.d.ts.map +1 -1
  110. package/dist/hooks/magic-context/opencode-v1-store-fixture.d.ts +12 -0
  111. package/dist/hooks/magic-context/opencode-v1-store-fixture.d.ts.map +1 -0
  112. package/dist/hooks/magic-context/read-session-chunk.d.ts +16 -0
  113. package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
  114. package/dist/hooks/magic-context/read-session-db.d.ts +5 -1
  115. package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
  116. package/dist/hooks/magic-context/read-session-raw.d.ts +10 -0
  117. package/dist/hooks/magic-context/read-session-raw.d.ts.map +1 -1
  118. package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
  119. package/dist/hooks/magic-context/storage-busy-refusal.d.ts +7 -0
  120. package/dist/hooks/magic-context/storage-busy-refusal.d.ts.map +1 -0
  121. package/dist/hooks/magic-context/strip-content.d.ts +1 -0
  122. package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
  123. package/dist/hooks/magic-context/transform-compartment-phase.d.ts.map +1 -1
  124. package/dist/hooks/magic-context/transform.d.ts +1 -0
  125. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  126. package/dist/{index-5f4qsnaq.js → index-18tjha8g.js} +2 -2
  127. package/dist/{index-4b30nf6z.js → index-32b096cc.js} +1 -1
  128. package/dist/{index-tjq5jztd.js → index-3bygzk2d.js} +1 -1
  129. package/dist/{index-cj5qe2nw.js → index-3x9caerx.js} +8 -6
  130. package/dist/index-40s1xz22.js +125 -0
  131. package/dist/{index-pye48m79.js → index-egkfvhms.js} +130 -42
  132. package/dist/{index-2zf5fv89.js → index-esxfcz5z.js} +171 -12
  133. package/dist/index-gtzcmv90.js +7260 -0
  134. package/dist/{index-6w9p73jz.js → index-jqcbs2k1.js} +10 -0
  135. package/dist/{index-v6wsttqt.js → index-kr5qehbd.js} +1 -1
  136. package/dist/{index-dx0xnd4q.js → index-kwe03yde.js} +1 -1
  137. package/dist/{index-c906f3ff.js → index-r9vkp4n9.js} +4 -4
  138. package/dist/{index-6z9g64js.js → index-s70wtd8k.js} +4 -1
  139. package/dist/{index-01ft0h3p.js → index-stb5fg12.js} +2 -2
  140. package/dist/{index-rdey8znw.js → index-ttdn47aq.js} +35260 -32540
  141. package/dist/index.d.ts.map +1 -1
  142. package/dist/index.js +15123 -23504
  143. package/dist/{message-time-backfill-rm9wmcem.js → message-time-backfill-q374fxc5.js} +3 -3
  144. package/dist/plugin/dream-timer.d.ts.map +1 -1
  145. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  146. package/dist/plugin/messages-transform.d.ts +10 -9
  147. package/dist/plugin/messages-transform.d.ts.map +1 -1
  148. package/dist/plugin/rpc-handlers.d.ts +1 -0
  149. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  150. package/dist/{read-session-chunk-ktz5zt70.js → read-session-chunk-wmvgnd24.js} +6 -4
  151. package/dist/{recomp-orchestrator-ahekzt0s.js → recomp-orchestrator-rk40ff15.js} +10 -9
  152. package/dist/{safe-notification-target-6w0esgd6.js → safe-notification-target-50gm9c58.js} +3 -3
  153. package/dist/{send-session-notification-w7xbnrsm.js → send-session-notification-6xsrcxnp.js} +5 -5
  154. package/dist/shared/cache-ttl-display.d.ts +3 -1
  155. package/dist/shared/cache-ttl-display.d.ts.map +1 -1
  156. package/dist/shared/harness.d.ts +11 -0
  157. package/dist/shared/harness.d.ts.map +1 -1
  158. package/dist/shared/model-cache-ttl.d.ts +9 -0
  159. package/dist/shared/model-cache-ttl.d.ts.map +1 -0
  160. package/dist/shared/model-suggestion-retry.d.ts +1 -1
  161. package/dist/shared/model-suggestion-retry.d.ts.map +1 -1
  162. package/dist/shared/prompt-async-transport.d.ts +7 -7
  163. package/dist/shared/prompt-async-transport.d.ts.map +1 -1
  164. package/dist/shared/rpc-server.d.ts.map +1 -1
  165. package/dist/shared/rpc-types.d.ts +1 -1
  166. package/dist/shared/rpc-types.d.ts.map +1 -1
  167. package/dist/shared/rpc-utils.d.ts +21 -0
  168. package/dist/shared/rpc-utils.d.ts.map +1 -1
  169. package/dist/shared/sqlite-write-locker-test-support.d.ts.map +1 -1
  170. package/dist/shared/sqlite.d.ts +12 -0
  171. package/dist/shared/sqlite.d.ts.map +1 -1
  172. package/dist/shared/status-view.d.ts +1 -1
  173. package/dist/shared/status-view.d.ts.map +1 -1
  174. package/dist/shared/subagent-runner.d.ts +3 -1
  175. package/dist/shared/subagent-runner.d.ts.map +1 -1
  176. package/dist/shared/user-facing-codes.d.ts +5 -0
  177. package/dist/shared/user-facing-codes.d.ts.map +1 -1
  178. package/dist/{task-config-mgf5nsh3.js → task-config-2bm68628.js} +1 -1
  179. package/dist/tools/ctx-expand/render.d.ts.map +1 -1
  180. package/dist/transform-postprocess-phase-t7xgdhdf.js +36 -0
  181. package/dist/v2/hidden-completion.d.ts +2 -0
  182. package/dist/v2/hidden-completion.d.ts.map +1 -1
  183. package/dist/v2/hooks/context.d.ts.map +1 -1
  184. package/dist/v2/hooks/hidden-child.d.ts +1 -0
  185. package/dist/v2/hooks/hidden-child.d.ts.map +1 -1
  186. package/dist/v2/hooks/lkg-system.d.ts +11 -0
  187. package/dist/v2/hooks/lkg-system.d.ts.map +1 -0
  188. package/dist/v2/hooks/session-project-backfill.d.ts +1 -1
  189. package/dist/v2/hooks/session-project-backfill.d.ts.map +1 -1
  190. package/dist/v2/hooks/storage-gate.d.ts +11 -5
  191. package/dist/v2/hooks/storage-gate.d.ts.map +1 -1
  192. package/dist/v2/host-service.d.ts +2 -1
  193. package/dist/v2/host-service.d.ts.map +1 -1
  194. package/dist/v2/server.js +95347 -93236
  195. package/dist/v2/store-reader.d.ts +2 -0
  196. package/dist/v2/store-reader.d.ts.map +1 -1
  197. package/dist/wrapup-orchestrator-h8tr10c6.js +19 -0
  198. package/package.json +1 -1
  199. package/src/agents/dreamer.ts +4 -6
  200. package/src/agents/hidden-agent-registrations.ts +3 -3
  201. package/src/agents/magic-context-prompt.test.ts +125 -0
  202. package/src/agents/magic-context-prompt.ts +12 -7
  203. package/src/agents/permissions.test.ts +3 -4
  204. package/src/config/latch-permanence-guard.test.ts +9 -0
  205. package/src/config/live-child-output-cap.test.ts +101 -0
  206. package/src/config/live-child-output-cap.ts +74 -0
  207. package/src/config/live-run-config.test.ts +24 -11
  208. package/src/config/schema/magic-context.test.ts +16 -1
  209. package/src/config/schema/magic-context.ts +27 -10
  210. package/src/features/magic-context/dreamer/task-registry.ts +13 -0
  211. package/src/shared/cache-ttl-display.ts +14 -20
  212. package/src/shared/harness.ts +14 -0
  213. package/src/shared/logger.test.ts +1 -0
  214. package/src/shared/model-cache-ttl.test.ts +40 -0
  215. package/src/shared/model-cache-ttl.ts +58 -0
  216. package/src/shared/model-suggestion-retry.ts +9 -2
  217. package/src/shared/prompt-async-transport.test.ts +254 -1
  218. package/src/shared/prompt-async-transport.ts +153 -44
  219. package/src/shared/prompt-surface-a1-golden.md +13 -13
  220. package/src/shared/rpc-async-probes.test.ts +230 -0
  221. package/src/shared/rpc-server.ts +6 -4
  222. package/src/shared/rpc-types.ts +1 -1
  223. package/src/shared/rpc-utils.test.ts +27 -1
  224. package/src/shared/rpc-utils.ts +161 -9
  225. package/src/shared/sqlite-acquisition-fence.test.ts +132 -0
  226. package/src/shared/sqlite-acquisition-routing.test.ts +94 -0
  227. package/src/shared/sqlite-pass-scope.test.ts +182 -0
  228. package/src/shared/sqlite-transaction-mode-guard.test.ts +42 -10
  229. package/src/shared/sqlite-write-locker-test-support.ts +1 -0
  230. package/src/shared/sqlite.ts +142 -56
  231. package/src/shared/status-view.ts +1 -1
  232. package/src/shared/storage-busy.test.ts +95 -0
  233. package/src/shared/subagent-runner.ts +4 -0
  234. package/src/shared/user-facing-codes.ts +6 -0
  235. package/src/shared/windows-hidden-spawns.test.ts +132 -0
  236. package/src/shared/write-transaction-attribution.test.ts +1 -0
  237. package/dist/wrapup-orchestrator-9srk0kjf.js +0 -18
@@ -7,12 +7,13 @@ import {
7
7
  buildDreamTaskRuntimeConfigs,
8
8
  userMemoryCollectionEnabled,
9
9
  } from "../features/magic-context/dreamer/task-config";
10
+ import { producerInputTokenLimit } from "../hooks/magic-context/producer-window-guard";
10
11
  import { resolveHistorianModel } from "../shared/model-resolution";
11
12
  import { loadPluginConfigDetailed } from "./index";
12
13
  import { dreamerRunConfig, historianRunConfig } from "./live-run-config";
13
14
  import { LiveConfigReader } from "./live-snapshot";
14
15
 
15
- for (const host of ["OC1", "OC2", "Pi"] as const) {
16
+ for (const host of ["OC1", "OC2", "Pi", "OMP"] as const) {
16
17
  test(`${host} historian samples the next generation while an existing run keeps its model and fallback`, () => {
17
18
  const root = mkdtempSync(join(tmpdir(), "mc-live-historian-"));
18
19
  const previous = { home: process.env.HOME, config: process.env.XDG_CONFIG_HOME };
@@ -23,22 +24,23 @@ for (const host of ["OC1", "OC2", "Pi"] as const) {
23
24
  mkdirSync(join(root, "config", "cortexkit"), { recursive: true });
24
25
  mkdirSync(join(directory, ".cortexkit"), { recursive: true });
25
26
  try {
26
- const block = host === "Pi" ? "pi" : "opencode";
27
+ const block = host === "Pi" ? "pi" : host === "OMP" ? "omp" : "opencode";
27
28
  const write = (
28
29
  model: string,
29
30
  fallback: string,
30
31
  autoPromote: boolean,
31
32
  minClusters: number,
33
+ maxTokens: number,
32
34
  ) =>
33
35
  writeFileSync(
34
36
  file,
35
37
  JSON.stringify({
36
- historian: { [block]: { model, fallback_models: [fallback] } },
38
+ historian: { maxTokens, [block]: { model, fallback_models: [fallback] } },
37
39
  memory: { auto_promote: autoPromote },
38
40
  commit_cluster_trigger: { enabled: true, min_clusters: minClusters },
39
41
  }),
40
42
  );
41
- write("anthropic/old-model", "anthropic/old-fallback", true, 3);
43
+ write("anthropic/old-model", "anthropic/old-fallback", true, 3, 4096);
42
44
  const load = () => loadPluginConfigDetailed(directory, false).config;
43
45
  const boot = load();
44
46
  const reader = new LiveConfigReader(directory, boot, load, () => {});
@@ -49,9 +51,10 @@ for (const host of ["OC1", "OC2", "Pi"] as const) {
49
51
  "anthropic/new-fallback-with-longer-name",
50
52
  false,
51
53
  5,
54
+ 8192,
52
55
  );
53
56
  const runTwo = historianRunConfig(boot, reader.poll().effective);
54
- const harness = host === "Pi" ? "pi" : "opencode";
57
+ const harness = host === "Pi" ? "pi" : host === "OMP" ? "omp" : "opencode";
55
58
  expect(resolveHistorianModel(runOne, harness).primary?.model).toBe(
56
59
  "anthropic/old-model",
57
60
  );
@@ -68,6 +71,9 @@ for (const host of ["OC1", "OC2", "Pi"] as const) {
68
71
  expect(runTwo.memory.auto_promote).toBe(false);
69
72
  expect(runOne.commit_cluster_trigger.min_clusters).toBe(3);
70
73
  expect(runTwo.commit_cluster_trigger.min_clusters).toBe(5);
74
+ expect(runOne.historian?.maxTokens).toBe(4096);
75
+ expect(runTwo.historian?.maxTokens).toBe(8192);
76
+ expect(producerInputTokenLimit(32_000, runTwo.historian?.maxTokens ?? 0)).toBe(23_093);
71
77
  expect(reader.current().generation).toBe(2);
72
78
  } finally {
73
79
  if (previous.home === undefined) delete process.env.HOME;
@@ -79,7 +85,7 @@ for (const host of ["OC1", "OC2", "Pi"] as const) {
79
85
  });
80
86
  }
81
87
 
82
- for (const host of ["OC1", "OC2", "Pi"] as const) {
88
+ for (const host of ["OC1", "OC2", "Pi", "OMP"] as const) {
83
89
  test(`${host} dreamer samples the new schedule and model chain without changing a running task`, () => {
84
90
  const root = mkdtempSync(join(tmpdir(), "mc-live-dreamer-"));
85
91
  const previous = { home: process.env.HOME, config: process.env.XDG_CONFIG_HOME };
@@ -91,11 +97,14 @@ for (const host of ["OC1", "OC2", "Pi"] as const) {
91
97
  mkdirSync(join(root, "config", "cortexkit"), { recursive: true });
92
98
  mkdirSync(join(directory, ".cortexkit"), { recursive: true });
93
99
  try {
94
- const block = host === "Pi" ? "pi" : "opencode";
100
+ const block = host === "Pi" ? "pi" : host === "OMP" ? "omp" : "opencode";
95
101
  writeFileSync(
96
102
  userFile,
97
103
  JSON.stringify({
98
- dreamer: { [block]: { model: "old/model", fallback_models: ["old/fallback"] } },
104
+ dreamer: {
105
+ maxTokens: 4096,
106
+ [block]: { model: "old/model", fallback_models: ["old/fallback"] },
107
+ },
99
108
  }),
100
109
  );
101
110
  const writeSchedule = (schedule: string) =>
@@ -122,6 +131,7 @@ for (const host of ["OC1", "OC2", "Pi"] as const) {
122
131
  userFile,
123
132
  JSON.stringify({
124
133
  dreamer: {
134
+ maxTokens: 8192,
125
135
  [block]: {
126
136
  model: "new/model-long",
127
137
  fallback_models: ["new/fallback-long"],
@@ -132,14 +142,17 @@ for (const host of ["OC1", "OC2", "Pi"] as const) {
132
142
  writeSchedule("15 4 * * *");
133
143
  const runTwo = dreamerRunConfig(boot, reader.poll().effective);
134
144
  const task = (cfg: typeof runOne) =>
135
- buildDreamTaskRuntimeConfigs(cfg.dreamer, host === "Pi" ? "pi" : "opencode").find(
136
- (entry) => entry.task === "verify",
137
- )!;
145
+ buildDreamTaskRuntimeConfigs(
146
+ cfg.dreamer,
147
+ host === "Pi" ? "pi" : host === "OMP" ? "omp" : "opencode",
148
+ ).find((entry) => entry.task === "verify")!;
138
149
  expect(task(runOne).schedule).toBe("0 3 * * *");
139
150
  expect(userMemoryCollectionEnabled(runOne.dreamer)).toBe(false);
140
151
  expect(task(runOne).model?.model).toBe("old/model");
141
152
  expect(task(runOne).fallbackModels[0]?.model).toBe("old/fallback");
142
153
  expect(task(runTwo).schedule).toBe("15 4 * * *");
154
+ expect(runOne.dreamer?.maxTokens).toBe(4096);
155
+ expect(runTwo.dreamer?.maxTokens).toBe(8192);
143
156
  expect(
144
157
  userMemoryCollectionEnabled(
145
158
  historianRunConfig(boot, reader.current().effective).dreamer,
@@ -38,7 +38,7 @@ describe("MagicContextConfigSchema", () => {
38
38
  retrieval_count_promotion_threshold: 3,
39
39
  },
40
40
  todowrite: {
41
- enabled: true,
41
+ enabled: false,
42
42
  overlay: true,
43
43
  },
44
44
  });
@@ -50,6 +50,21 @@ describe("MagicContextConfigSchema", () => {
50
50
  });
51
51
  });
52
52
 
53
+ it("defaults todowrite off but honors explicit enablement and disablement", () => {
54
+ expect(MagicContextConfigSchema.parse({}).todowrite).toEqual({
55
+ enabled: false,
56
+ overlay: true,
57
+ });
58
+ expect(MagicContextConfigSchema.parse({ todowrite: {} }).todowrite.enabled).toBe(false);
59
+ expect(MagicContextConfigSchema.parse({ todowrite: { enabled: true } }).todowrite).toEqual({
60
+ enabled: true,
61
+ overlay: true,
62
+ });
63
+ expect(
64
+ MagicContextConfigSchema.parse({ todowrite: { enabled: false } }).todowrite.enabled,
65
+ ).toBe(false);
66
+ });
67
+
53
68
  describe("budget configuration", () => {
54
69
  it("accepts 90% execute thresholds and rejects 91%", () => {
55
70
  expect(
@@ -484,14 +484,27 @@ const CronScheduleSchema = z
484
484
  const DreamTaskBaseConfigSchema = z
485
485
  .object({
486
486
  schedule: CronScheduleSchema.default(""),
487
+ token_budget: z
488
+ .number()
489
+ .int()
490
+ .positive()
491
+ .optional()
492
+ .describe(
493
+ "Maximum cumulative prompt tokens (input + cache read + cache write) for one tool-loop child. Defaults vary by task.",
494
+ ),
487
495
  })
488
496
  .strict();
489
497
 
498
+ export const DREAM_TASK_PROMOTION_DEFAULTS = {
499
+ "review-user-memories": 3,
500
+ "promote-primers": 2,
501
+ } as const;
502
+
490
503
  const PromotionThresholdSchema = z
491
504
  .number()
492
505
  .min(2)
493
506
  .max(20)
494
- .optional()
507
+ .default(DREAM_TASK_PROMOTION_DEFAULTS["review-user-memories"])
495
508
  .describe(
496
509
  "review-user-memories: min candidate observations before promotion is considered (default: 3)",
497
510
  );
@@ -499,7 +512,7 @@ const PrimerPromotionThresholdSchema = z
499
512
  .number()
500
513
  .min(2)
501
514
  .max(20)
502
- .optional()
515
+ .default(DREAM_TASK_PROMOTION_DEFAULTS["promote-primers"])
503
516
  .describe(
504
517
  "promote-primers: min recurring source days before promotion is considered (default: 2)",
505
518
  );
@@ -548,8 +561,10 @@ const DEFAULT_TASK_SCHEDULES: Record<DreamTaskName, string> = {
548
561
 
549
562
  function defaultTaskConfig(task: DreamTaskName): z.input<typeof DreamTaskConfigSchema> {
550
563
  const base: z.input<typeof DreamTaskConfigSchema> = { schedule: DEFAULT_TASK_SCHEDULES[task] };
551
- if (task === "review-user-memories") base.promotion_threshold = 3;
552
- if (task === "promote-primers") base.promotion_threshold = 2;
564
+ if (task === "review-user-memories")
565
+ base.promotion_threshold = DREAM_TASK_PROMOTION_DEFAULTS["review-user-memories"];
566
+ if (task === "promote-primers")
567
+ base.promotion_threshold = DREAM_TASK_PROMOTION_DEFAULTS["promote-primers"];
553
568
  return base;
554
569
  }
555
570
 
@@ -888,7 +903,7 @@ export interface MuralConfig {
888
903
 
889
904
  export interface MagicContextConfig {
890
905
  enabled: boolean;
891
- /** User-level setting that lets a session started exactly in the canonical home directory use a deterministic directory identity. */
906
+ /** User-level setting that lets a session in the canonical home directory use project memory. */
892
907
  allow_home_project: boolean;
893
908
  mural: MuralConfig;
894
909
  /** Selects the runtime implementation for this project. Rust mode is experimental and requires user-level subc configuration. */
@@ -1074,7 +1089,7 @@ export const MagicContextConfigSchema = z
1074
1089
  .boolean()
1075
1090
  .default(false)
1076
1091
  .describe(
1077
- "Allow Magic Context sessions launched from the exact canonical home directory. The home session uses its deterministic dir: identity so pre-gate memories reconnect. USER-LEVEL ONLY: project config is ignored. The home identity is excluded from registry seed exports, never resolves descendants by containment, and cannot join a workspace.",
1092
+ "Allow Magic Context sessions launched from the exact canonical home directory. A non-git home uses its deterministic dir: identity; a home repository uses its git: identity. USER-LEVEL ONLY: project config is ignored. The home identity is excluded from registry seed exports, never resolves descendants by containment, and cannot join a workspace.",
1078
1093
  ),
1079
1094
  mural: z
1080
1095
  .object({
@@ -1156,7 +1171,7 @@ export const MagicContextConfigSchema = z
1156
1171
  .union([z.string(), z.object({ default: z.string() }).catchall(z.string())])
1157
1172
  .default("5m")
1158
1173
  .describe(
1159
- '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). 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).',
1174
+ '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). Explicit per-model entries win; otherwise GPT-5.6 and later (including gpt-6*, through any provider prefix) use a built-in 30m lifetime before the object default or 5m fallback. An unset or global "5m" opts into built-in defaults; any other global string is an explicit policy and wins. Policy is frozen per session, including across restarts; a model switch resolves against that frozen policy. /ctx-status shows the effective value and source. 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).',
1160
1175
  ),
1161
1176
  prompt_surface: PromptSurfaceConfigSchema.default({ default: "full" }).describe(
1162
1177
  "Prompt-surface presets: default is full; models use bare model IDs, provider/model, or provider/* routing keys. Guidance and tool-description overrides are user-level only. OpenCode 1.x, Pi, and OMP register tool descriptions once per process (they follow the default preset). OpenCode 2 rewrites the five ctx_* descriptions per request from the draft model.",
@@ -1388,9 +1403,9 @@ export const MagicContextConfigSchema = z
1388
1403
  .object({
1389
1404
  enabled: z
1390
1405
  .boolean()
1391
- .default(true)
1406
+ .default(false)
1392
1407
  .describe(
1393
- "Pi only: register Magic Context's todowrite task-list tool. Disable if you use your own todo extension. OpenCode ships its own built-in todowrite; this setting has no effect there.",
1408
+ "Pi only: off by default. Set todowrite.enabled=true to register Magic Context's todowrite task-list tool and /todos command. OpenCode ships its own built-in todowrite; this setting has no effect there.",
1394
1409
  ),
1395
1410
  overlay: z
1396
1411
  .boolean()
@@ -1399,7 +1414,7 @@ export const MagicContextConfigSchema = z
1399
1414
  "Pi only: show the persistent todo overlay above the editor while tasks are active.",
1400
1415
  ),
1401
1416
  })
1402
- .default({ enabled: true, overlay: true })
1417
+ .default({ enabled: false, overlay: true })
1403
1418
  .describe(
1404
1419
  "Pi-only todowrite tool and overlay controls. Pi registers tools and widgets at extension boot, so changing this after /cd requires /reload or restart.",
1405
1420
  ),
@@ -1552,10 +1567,12 @@ export const LIVE_RELOAD_CONFIG_PATHS = [
1552
1567
  "historian.omp.fallback_models",
1553
1568
  "historian.omp.thinking_level",
1554
1569
  "historian.two_pass",
1570
+ "historian.maxTokens",
1555
1571
  "historian_timeout_ms",
1556
1572
  "commit_cluster_trigger.enabled",
1557
1573
  "commit_cluster_trigger.min_clusters",
1558
1574
  "memory.auto_promote",
1575
+ "dreamer.maxTokens",
1559
1576
  "dreamer.opencode.model",
1560
1577
  "dreamer.opencode.fallback_models",
1561
1578
  "dreamer.opencode.variant",
@@ -29,6 +29,19 @@ export const CANONICAL_DREAM_TASKS = [
29
29
 
30
30
  export type DreamTaskName = (typeof CANONICAL_DREAM_TASKS)[number];
31
31
 
32
+ /** Prompt-token ceilings informed by docs/reports/dreamer-token-usage.md.
33
+ * Multi-memory batches need more room than a single primer investigation;
34
+ * curate's 150-step tool loop warrants a larger allowance too. */
35
+ export const DREAM_TOOL_LOOP_TOKEN_BUDGETS = {
36
+ "map-memories": 1_500_000,
37
+ verify: 1_700_000,
38
+ "verify-broad": 1_700_000,
39
+ curate: 1_500_000,
40
+ retrospective: 300_000,
41
+ "maintain-docs": 1_600_000,
42
+ "refresh-primers": 350_000,
43
+ } as const;
44
+
32
45
  /**
33
46
  * How a Dreamer task reaches its result, which is what decides whether a host
34
47
  * without a tool loop can run it:
@@ -1,7 +1,7 @@
1
1
  import type { MagicContextConfig } from "../config/schema/magic-context";
2
- import { resolveModelConfigValue } from "./prompt-surface";
2
+ import { type ResolvedCacheTtl, resolveModelCacheTtl } from "./model-cache-ttl";
3
3
 
4
- export type CacheTtlDisplaySource = "config" | "session" | "default";
4
+ export type CacheTtlDisplaySource = ResolvedCacheTtl["source"] | "session";
5
5
 
6
6
  export interface CacheTtlDisplay {
7
7
  value: string;
@@ -10,6 +10,7 @@ export interface CacheTtlDisplay {
10
10
  }
11
11
 
12
12
  export interface ResolveCacheTtlDisplayArgs {
13
+ frozen?: ResolvedCacheTtl;
13
14
  configured: MagicContextConfig["cache_ttl"];
14
15
  configuredExplicitly: boolean;
15
16
  modelKey: string | undefined;
@@ -24,6 +25,7 @@ export interface ResolveCacheTtlDisplayArgs {
24
25
  * displayed; otherwise use live config because the session value may be for another model.
25
26
  */
26
27
  export function resolveCacheTtlDisplay(args: ResolveCacheTtlDisplayArgs): CacheTtlDisplay {
28
+ if (args.frozen) return args.frozen;
27
29
  if (
28
30
  (args.sessionModelKey && (!args.modelKey || args.sessionModelKey === args.modelKey)) ||
29
31
  (!args.modelKey && !args.sessionModelKey && args.sessionValue !== "5m")
@@ -35,27 +37,19 @@ export function resolveCacheTtlDisplay(args: ResolveCacheTtlDisplayArgs): CacheT
35
37
  };
36
38
  }
37
39
 
38
- if (typeof args.configured === "string") {
39
- return {
40
- value: args.configured,
41
- source: args.configuredExplicitly ? "config" : "default",
42
- modelKey: args.modelKey,
43
- };
44
- }
45
-
46
- const matched = resolveModelConfigValue(args.configured, args.modelKey);
47
- if (matched) {
48
- return { value: matched.value, source: "config", modelKey: args.modelKey };
49
- }
50
-
51
- return {
52
- value: args.configured.default ?? "5m",
53
- source: "default",
54
- modelKey: args.modelKey,
55
- };
40
+ const resolved = resolveModelCacheTtl(args.configured, args.modelKey);
41
+ if (
42
+ resolved.source === "default" &&
43
+ typeof args.configured === "string" &&
44
+ args.configuredExplicitly
45
+ )
46
+ return { ...resolved, source: "config" };
47
+ return resolved;
56
48
  }
57
49
 
58
50
  export function formatCacheTtlDisplay(display: CacheTtlDisplay): string {
51
+ if (display.source === "OpenAI GPT-5.6+ default")
52
+ return `Cache TTL: ${display.value} (${display.source})`;
59
53
  if (display.source === "session") return `Cache TTL: ${display.value} (session)`;
60
54
  if (display.source === "config") {
61
55
  return `Cache TTL: ${display.value} (config for ${display.modelKey ?? "current model"})`;
@@ -52,6 +52,20 @@ export function getHarness(): HarnessId {
52
52
  return currentHarness;
53
53
  }
54
54
 
55
+ /**
56
+ * Whether this process may read OpenCode's own session store (opencode.db).
57
+ *
58
+ * Only the OpenCode plugins own that store. A Pi or OMP process keeps its
59
+ * history in Pi JSONL sessions and shares only Magic Context's context.db with
60
+ * OpenCode. Any history read in a Pi process for a session with no Pi provider
61
+ * used to fall through to opencode.db, which let background work load another
62
+ * project's OpenCode sessions into Pi's heap. Pi therefore treats the OpenCode
63
+ * store as absent, the same as on a Pi-only install.
64
+ */
65
+ export function harnessOwnsOpenCodeStore(harness: HarnessId = currentHarness): boolean {
66
+ return harness === "opencode" || harness === "opencode2";
67
+ }
68
+
55
69
  /**
56
70
  * Test-only helper to reset harness state between test cases. Do NOT call
57
71
  * from production code paths.
@@ -189,6 +189,7 @@ async function runLoggerScenario<T>(
189
189
  const root = mkdtempSync(path.join(os.tmpdir(), "magic-context-logger-test-"));
190
190
  scenarioRoots.push(root);
191
191
  const child = Bun.spawn({
192
+ windowsHide: true,
192
193
  cmd: ["bun", "--eval", loggerScenario],
193
194
  cwd: import.meta.dir,
194
195
  env: {
@@ -0,0 +1,40 @@
1
+ import { describe, expect, it } from "bun:test";
2
+ import { MagicContextConfigSchema } from "../config/schema/magic-context";
3
+ import { resolveCacheTtl } from "../hooks/magic-context/event-resolvers";
4
+
5
+ describe("known model cache TTL", () => {
6
+ it("matches canonical model versions through provider prefixes", () => {
7
+ for (const prefix of ["", "openai/", "openai-codex/", "openrouter/openai/", "azure/"]) {
8
+ for (const model of [
9
+ "gpt-5.6",
10
+ "gpt-5.6-sol",
11
+ "gpt-5.7",
12
+ "gpt-5.10",
13
+ "gpt-6",
14
+ "gpt-6.1",
15
+ "gpt-6-mini",
16
+ "gpt-7",
17
+ ]) {
18
+ expect(resolveCacheTtl("5m", prefix + model), prefix + model).toBe("30m");
19
+ }
20
+ for (const model of ["gpt-5.5", "gpt-5.1", "gpt-5", "gpt-4o", "unknown", "not-gpt-6"]) {
21
+ expect(resolveCacheTtl("5m", prefix + model), prefix + model).toBe("5m");
22
+ }
23
+ }
24
+ });
25
+ it("uses built-ins for unset and global 5m, but honors global 10m", () => {
26
+ expect(resolveCacheTtl(MagicContextConfigSchema.parse({}).cache_ttl, "openai/gpt-6")).toBe(
27
+ "30m",
28
+ );
29
+ expect(resolveCacheTtl("5m", "openai/gpt-6")).toBe("30m");
30
+ expect(resolveCacheTtl("10m", "openai/gpt-6")).toBe("10m");
31
+ });
32
+ it("honors per-model entries before built-ins and built-ins before object defaults", () => {
33
+ expect(resolveCacheTtl({ default: "10m" }, "openai/gpt-6")).toBe("30m");
34
+ expect(resolveCacheTtl({ default: "10m", "gpt-6": "5m" }, "openai/gpt-6")).toBe("5m");
35
+ expect(resolveCacheTtl({ default: "10m", "openai/*": "never" }, "openai/gpt-6")).toBe(
36
+ "never",
37
+ );
38
+ expect(resolveCacheTtl({ default: "10m" }, "other/model")).toBe("10m");
39
+ });
40
+ });
@@ -0,0 +1,58 @@
1
+ import { canonicalModelIdentity } from "./harness-provider-map";
2
+ import { resolveModelConfigValue } from "./prompt-surface";
3
+
4
+ export type CacheTtlConfig = string | Record<string, string>;
5
+ export type CacheTtlSource = "config" | "default" | "OpenAI GPT-5.6+ default";
6
+ export interface ResolvedCacheTtl {
7
+ value: string;
8
+ source: CacheTtlSource;
9
+ modelKey: string | undefined;
10
+ }
11
+
12
+ // Provider documentation: https://developers.openai.com/api/docs/guides/prompt-caching
13
+ // Cache lifetime / Summary of model differences: at least 30 minutes since write or reuse.
14
+ const MODEL_CACHE_LIFETIMES = [
15
+ {
16
+ source: "OpenAI GPT-5.6+ default" as const,
17
+ value: "30m",
18
+ matches(model: string): boolean {
19
+ const version = /^gpt-(\d+)(?:\.(\d+))?(?:$|[^\d.])/.exec(model);
20
+ if (!version) return false;
21
+ const major = Number(version[1]);
22
+ const minor = Number(version[2] ?? 0);
23
+ return major > 5 || (major === 5 && minor >= 6);
24
+ },
25
+ },
26
+ ];
27
+
28
+ export function resolveModelCacheTtl(
29
+ config: CacheTtlConfig | undefined,
30
+ modelKey: string | undefined,
31
+ ): ResolvedCacheTtl {
32
+ if (config && typeof config !== "string") {
33
+ const match =
34
+ modelKey &&
35
+ !modelKey.includes("/") &&
36
+ Object.hasOwn(config, modelKey) &&
37
+ modelKey !== "default"
38
+ ? config[modelKey]
39
+ : resolveModelConfigValue(config, modelKey)?.value;
40
+ if (match !== undefined) return { value: match, source: "config", modelKey };
41
+ }
42
+ // A non-5m global string is an explicit policy. The generic 5m default is
43
+ // not evidence of provider eviction: documented lifetimes avoid paid rewrites.
44
+ if (typeof config === "string" && config !== "5m")
45
+ return { value: config, source: "config", modelKey };
46
+ const model =
47
+ canonicalModelIdentity(modelKey ?? "")
48
+ .toLowerCase()
49
+ .split("/")
50
+ .at(-1) ?? "";
51
+ const known = MODEL_CACHE_LIFETIMES.find((entry) => entry.matches(model));
52
+ if (known) return { value: known.value, source: known.source, modelKey };
53
+ return {
54
+ value: (typeof config === "object" ? config.default : config) ?? "5m",
55
+ source: "default",
56
+ modelKey,
57
+ };
58
+ }
@@ -1,5 +1,5 @@
1
1
  import type { createOpencodeClient } from "@opencode-ai/sdk";
2
-
2
+ import { DreamTokenBudgetExceeded } from "../features/magic-context/dreamer/token-budget";
3
3
  import { detectOverflow } from "../features/magic-context/overflow-detection";
4
4
  import { HiddenAgentStepLimit } from "../v2/hooks/hidden-child";
5
5
  import {
@@ -115,6 +115,7 @@ export type PromptFailureClass =
115
115
  | "provider_timeout"
116
116
  | "provider_error"
117
117
  | "step_limit"
118
+ | "token_budget"
118
119
  | "empty_completion"
119
120
  | "no_models"
120
121
  | "child_aborted"
@@ -351,7 +352,12 @@ async function abortChildRun(client: Client, sessionId: string): Promise<void> {
351
352
  * different model.
352
353
  */
353
354
  function isNonRetryable(error: unknown, externalSignal?: AbortSignal): boolean {
354
- if (externalSignal?.aborted || error instanceof HiddenAgentStepLimit) return true;
355
+ if (
356
+ externalSignal?.aborted ||
357
+ error instanceof HiddenAgentStepLimit ||
358
+ error instanceof DreamTokenBudgetExceeded
359
+ )
360
+ return true;
355
361
 
356
362
  if (error instanceof Error) {
357
363
  if (error.name === "AbortError") return true;
@@ -393,6 +399,7 @@ function classifyPromptFailure(
393
399
  ): PromptFailureClass {
394
400
  const message = extractMessage(error);
395
401
  if (error instanceof HiddenAgentStepLimit) return "step_limit";
402
+ if (error instanceof DreamTokenBudgetExceeded) return "token_budget";
396
403
  if (externalSignal?.aborted || message === "prompt aborted by external signal") {
397
404
  return "child_aborted";
398
405
  }