@cortexkit/opencode-magic-context 0.33.1 → 0.34.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (240) hide show
  1. package/README.md +20 -3
  2. package/dist/config/agent-disable.d.ts +22 -0
  3. package/dist/config/agent-disable.d.ts.map +1 -1
  4. package/dist/config/index.d.ts.map +1 -1
  5. package/dist/config/migrate-experimental.d.ts +2 -1
  6. package/dist/config/migrate-experimental.d.ts.map +1 -1
  7. package/dist/config/project-security.d.ts +9 -0
  8. package/dist/config/project-security.d.ts.map +1 -1
  9. package/dist/config/schema/magic-context.d.ts +90 -17
  10. package/dist/config/schema/magic-context.d.ts.map +1 -1
  11. package/dist/config/transform-mode.d.ts +2 -0
  12. package/dist/config/transform-mode.d.ts.map +1 -1
  13. package/dist/{conflict-warning-hook-n48c783v.js → conflict-warning-hook-fvpfvt0w.js} +1 -1
  14. package/dist/{derive-budgets-e9j09sjr.js → derive-budgets-9crp0cvd.js} +1 -1
  15. package/dist/features/builtin-commands/commands.d.ts +1 -1
  16. package/dist/features/builtin-commands/commands.d.ts.map +1 -1
  17. package/dist/features/magic-context/compaction-marker.d.ts +57 -0
  18. package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
  19. package/dist/features/magic-context/compartment-chunk-embedding.d.ts.map +1 -1
  20. package/dist/features/magic-context/dreamer/classify.d.ts +1 -0
  21. package/dist/features/magic-context/dreamer/classify.d.ts.map +1 -1
  22. package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts.map +1 -1
  23. package/dist/features/magic-context/dreamer/map-memories.d.ts +1 -0
  24. package/dist/features/magic-context/dreamer/map-memories.d.ts.map +1 -1
  25. package/dist/features/magic-context/dreamer/refresh-primers.d.ts +1 -0
  26. package/dist/features/magic-context/dreamer/refresh-primers.d.ts.map +1 -1
  27. package/dist/features/magic-context/dreamer/storage-dream-runs.d.ts +2 -0
  28. package/dist/features/magic-context/dreamer/storage-dream-runs.d.ts.map +1 -1
  29. package/dist/features/magic-context/dreamer/task-executor.d.ts +4 -1
  30. package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
  31. package/dist/features/magic-context/dreamer/task-gates.d.ts +19 -1
  32. package/dist/features/magic-context/dreamer/task-gates.d.ts.map +1 -1
  33. package/dist/features/magic-context/dreamer/task-registry.d.ts +28 -0
  34. package/dist/features/magic-context/dreamer/task-registry.d.ts.map +1 -1
  35. package/dist/features/magic-context/dreamer/task-scheduler.d.ts +7 -1
  36. package/dist/features/magic-context/dreamer/task-scheduler.d.ts.map +1 -1
  37. package/dist/features/magic-context/dreamer/verify.d.ts +1 -0
  38. package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
  39. package/dist/features/magic-context/fail-closed-block.d.ts +10 -0
  40. package/dist/features/magic-context/fail-closed-block.d.ts.map +1 -1
  41. package/dist/features/magic-context/git-commits/storage-git-commit-embeddings.d.ts.map +1 -1
  42. package/dist/features/magic-context/git-commits/storage-git-commits.d.ts.map +1 -1
  43. package/dist/features/magic-context/memory/embedding-identity.d.ts.map +1 -1
  44. package/dist/features/magic-context/memory/embedding-local.d.ts +7 -1
  45. package/dist/features/magic-context/memory/embedding-local.d.ts.map +1 -1
  46. package/dist/features/magic-context/memory/embedding.d.ts.map +1 -1
  47. package/dist/features/magic-context/memory/memory-migration.d.ts.map +1 -1
  48. package/dist/features/magic-context/memory/project-identity.d.ts +2 -6
  49. package/dist/features/magic-context/memory/project-identity.d.ts.map +1 -1
  50. package/dist/features/magic-context/memory/storage-memory-embeddings.d.ts.map +1 -1
  51. package/dist/features/magic-context/migrations.d.ts +23 -1
  52. package/dist/features/magic-context/migrations.d.ts.map +1 -1
  53. package/dist/features/magic-context/mural/compress-cues.d.ts +1 -0
  54. package/dist/features/magic-context/mural/compress-cues.d.ts.map +1 -1
  55. package/dist/features/magic-context/mural/render-mural.d.ts.map +1 -1
  56. package/dist/features/magic-context/overflow-detection.d.ts +8 -1
  57. package/dist/features/magic-context/overflow-detection.d.ts.map +1 -1
  58. package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
  59. package/dist/features/magic-context/scheduler.d.ts.map +1 -1
  60. package/dist/features/magic-context/schema-fence-probe.d.ts +28 -0
  61. package/dist/features/magic-context/schema-fence-probe.d.ts.map +1 -0
  62. package/dist/features/magic-context/sidekick/agent.d.ts.map +1 -1
  63. package/dist/features/magic-context/smart-notes/compiler.d.ts.map +1 -1
  64. package/dist/features/magic-context/storage-db.d.ts +37 -2
  65. package/dist/features/magic-context/storage-db.d.ts.map +1 -1
  66. package/dist/features/magic-context/storage-meta-persisted.d.ts +38 -4
  67. package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
  68. package/dist/features/magic-context/storage-meta.d.ts +1 -1
  69. package/dist/features/magic-context/storage-meta.d.ts.map +1 -1
  70. package/dist/features/magic-context/storage.d.ts +2 -2
  71. package/dist/features/magic-context/storage.d.ts.map +1 -1
  72. package/dist/features/magic-context/user-memory/review-user-memories.d.ts.map +1 -1
  73. package/dist/hooks/magic-context/boundary-execution.d.ts +1 -1
  74. package/dist/hooks/magic-context/boundary-execution.d.ts.map +1 -1
  75. package/dist/hooks/magic-context/cache-busting-signals.d.ts +1 -0
  76. package/dist/hooks/magic-context/cache-busting-signals.d.ts.map +1 -1
  77. package/dist/hooks/magic-context/child-session-spawn.d.ts +26 -0
  78. package/dist/hooks/magic-context/child-session-spawn.d.ts.map +1 -0
  79. package/dist/hooks/magic-context/command-handler.d.ts +3 -0
  80. package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
  81. package/dist/hooks/magic-context/compaction-off-transition.d.ts +96 -0
  82. package/dist/hooks/magic-context/compaction-off-transition.d.ts.map +1 -0
  83. package/dist/hooks/magic-context/compartment-runner-historian.d.ts +2 -0
  84. package/dist/hooks/magic-context/compartment-runner-historian.d.ts.map +1 -1
  85. package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
  86. package/dist/hooks/magic-context/compartment-runner-mapping.d.ts.map +1 -1
  87. package/dist/hooks/magic-context/compartment-runner-partial-recomp.d.ts.map +1 -1
  88. package/dist/hooks/magic-context/compartment-runner-recomp.d.ts.map +1 -1
  89. package/dist/hooks/magic-context/compartment-trigger.d.ts +12 -5
  90. package/dist/hooks/magic-context/compartment-trigger.d.ts.map +1 -1
  91. package/dist/hooks/magic-context/ctx-reduce-availability.d.ts +47 -1
  92. package/dist/hooks/magic-context/ctx-reduce-availability.d.ts.map +1 -1
  93. package/dist/hooks/magic-context/emergency-drop.d.ts +2 -2
  94. package/dist/hooks/magic-context/event-handler.d.ts +7 -0
  95. package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
  96. package/dist/hooks/magic-context/event-resolvers.d.ts +13 -21
  97. package/dist/hooks/magic-context/event-resolvers.d.ts.map +1 -1
  98. package/dist/hooks/magic-context/execute-status.d.ts +5 -1
  99. package/dist/hooks/magic-context/execute-status.d.ts.map +1 -1
  100. package/dist/hooks/magic-context/final-wire-token-estimate.d.ts +2 -0
  101. package/dist/hooks/magic-context/final-wire-token-estimate.d.ts.map +1 -1
  102. package/dist/hooks/magic-context/heuristic-cleanup.d.ts +1 -1
  103. package/dist/hooks/magic-context/hook-handlers.d.ts +1 -0
  104. package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
  105. package/dist/hooks/magic-context/hook.d.ts +14 -6
  106. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  107. package/dist/hooks/magic-context/inject-compartments.d.ts +10 -1
  108. package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
  109. package/dist/hooks/magic-context/live-session-state.d.ts +3 -0
  110. package/dist/hooks/magic-context/live-session-state.d.ts.map +1 -1
  111. package/dist/hooks/magic-context/protected-tail-boundary.d.ts.map +1 -1
  112. package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
  113. package/dist/hooks/magic-context/read-session-true-raw-tokens.d.ts.map +1 -1
  114. package/dist/hooks/magic-context/rust-mode-transform.d.ts +3 -0
  115. package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
  116. package/dist/hooks/magic-context/send-session-notification.d.ts +20 -1
  117. package/dist/hooks/magic-context/send-session-notification.d.ts.map +1 -1
  118. package/dist/hooks/magic-context/transform-compartment-phase.d.ts +3 -0
  119. package/dist/hooks/magic-context/transform-compartment-phase.d.ts.map +1 -1
  120. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +31 -1
  121. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  122. package/dist/hooks/magic-context/transform.d.ts +29 -2
  123. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  124. package/dist/{index-56yjaeb2.js → index-2y0ybv5x.js} +11 -1
  125. package/dist/{index-ey1bc14z.js → index-b563sga5.js} +7 -264
  126. package/dist/{index-y1c9tcm3.js → index-cn960ffd.js} +101 -20
  127. package/dist/{index-xyaekybw.js → index-dtas91s5.js} +6 -4
  128. package/dist/index-fcyvznch.js +279 -0
  129. package/dist/{index-63dq2g4d.js → index-ry8rh8cv.js} +138 -24
  130. package/dist/{index-c2gahrks.js → index-x8spt5wy.js} +1682 -893
  131. package/dist/index.d.ts.map +1 -1
  132. package/dist/index.js +1677 -723
  133. package/dist/plugin/dream-timer.d.ts +4 -2
  134. package/dist/plugin/dream-timer.d.ts.map +1 -1
  135. package/dist/plugin/embedding-bootstrap.d.ts.map +1 -1
  136. package/dist/plugin/hooks/create-session-hooks.d.ts +12 -1
  137. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  138. package/dist/plugin/messages-transform.d.ts +10 -0
  139. package/dist/plugin/messages-transform.d.ts.map +1 -1
  140. package/dist/plugin/rpc-handlers.d.ts +3 -7
  141. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  142. package/dist/plugin/tool-registry.d.ts +8 -0
  143. package/dist/plugin/tool-registry.d.ts.map +1 -1
  144. package/dist/{recomp-orchestrator-2yb2hfh2.js → recomp-orchestrator-k72ejkkh.js} +6 -4
  145. package/dist/send-session-notification-6njqewzk.js +20 -0
  146. package/dist/shared/conflict-detector.d.ts +38 -1
  147. package/dist/shared/conflict-detector.d.ts.map +1 -1
  148. package/dist/shared/conflict-fixer.d.ts +18 -1
  149. package/dist/shared/conflict-fixer.d.ts.map +1 -1
  150. package/dist/shared/context-limit-provenance.d.ts +3 -0
  151. package/dist/shared/context-limit-provenance.d.ts.map +1 -0
  152. package/dist/shared/escalation-bands.d.ts +9 -0
  153. package/dist/shared/escalation-bands.d.ts.map +1 -0
  154. package/dist/shared/format-threshold.d.ts +1 -1
  155. package/dist/shared/models-dev-cache.d.ts +29 -3
  156. package/dist/shared/models-dev-cache.d.ts.map +1 -1
  157. package/dist/shared/rpc-server.d.ts.map +1 -1
  158. package/dist/shared/rpc-types.d.ts +51 -1
  159. package/dist/shared/rpc-types.d.ts.map +1 -1
  160. package/dist/shared/rpc-utils.d.ts +19 -0
  161. package/dist/shared/rpc-utils.d.ts.map +1 -1
  162. package/dist/shared/storage-permissions.d.ts +5 -0
  163. package/dist/shared/storage-permissions.d.ts.map +1 -0
  164. package/dist/shared/tui-runtime-specifiers.d.ts +20 -0
  165. package/dist/shared/tui-runtime-specifiers.d.ts.map +1 -0
  166. package/dist/{storage-meta-session-td6bwtky.js → storage-meta-session-xt41zbw4.js} +2 -1
  167. package/dist/{task-config-5nx3qfz8.js → task-config-gbp7r23g.js} +1 -1
  168. package/dist/tui/compaction-off.d.ts +13 -0
  169. package/dist/tui/compaction-off.d.ts.map +1 -0
  170. package/dist/tui/data/context-db.d.ts.map +1 -1
  171. package/dist/tui-compiled/compaction-off.d.ts +13 -0
  172. package/dist/tui-compiled/compaction-off.d.ts.map +1 -0
  173. package/dist/tui-compiled/data/context-db.d.ts.map +1 -1
  174. package/package.json +6 -1
  175. package/src/agents/dreamer.ts +68 -0
  176. package/src/agents/hidden-agent-registrations.ts +331 -0
  177. package/src/agents/historian.ts +3 -0
  178. package/src/agents/language-directive.test.ts +138 -0
  179. package/src/agents/language-directive.ts +121 -0
  180. package/src/agents/magic-context-prompt.language.test.ts +35 -0
  181. package/src/agents/magic-context-prompt.test.ts +292 -0
  182. package/src/agents/magic-context-prompt.ts +182 -0
  183. package/src/agents/permissions.test.ts +252 -0
  184. package/src/agents/permissions.ts +186 -0
  185. package/src/agents/sidekick.ts +1 -0
  186. package/src/agents/smart-note-compiler.ts +1 -0
  187. package/src/config/agent-disable.ts +106 -0
  188. package/src/config/compaction-accessor-guard.test.ts +82 -0
  189. package/src/config/compaction-backcompat.test.ts +52 -0
  190. package/src/config/index.test.ts +936 -0
  191. package/src/config/index.ts +601 -0
  192. package/src/config/migrate-config-location.test.ts +332 -0
  193. package/src/config/migrate-config-location.ts +635 -0
  194. package/src/config/migrate-dreamer-v2.test.ts +287 -0
  195. package/src/config/migrate-dreamer-v2.ts +336 -0
  196. package/src/config/migrate-experimental.test.ts +41 -0
  197. package/src/config/migrate-experimental.ts +185 -0
  198. package/src/config/project-security.test.ts +388 -0
  199. package/src/config/project-security.ts +611 -0
  200. package/src/config/prune-config-leaf.test.ts +78 -0
  201. package/src/config/prune-config-leaf.ts +68 -0
  202. package/src/config/removed-config-keys.test.ts +116 -0
  203. package/src/config/schema/agent-overrides.ts +45 -0
  204. package/src/config/schema/magic-context.test.ts +359 -0
  205. package/src/config/schema/magic-context.ts +991 -0
  206. package/src/config/transform-mode.test.ts +62 -0
  207. package/src/config/transform-mode.ts +34 -0
  208. package/src/config/variable.test.ts +323 -0
  209. package/src/config/variable.ts +192 -0
  210. package/src/features/magic-context/defaults.ts +1 -0
  211. package/src/features/magic-context/dreamer/cron.ts +243 -0
  212. package/src/features/magic-context/dreamer/task-registry.ts +151 -0
  213. package/src/shared/conflict-detector.test.ts +121 -0
  214. package/src/shared/conflict-detector.ts +50 -3
  215. package/src/shared/conflict-fixer.test.ts +309 -0
  216. package/src/shared/conflict-fixer.ts +82 -5
  217. package/src/shared/context-limit-provenance.ts +6 -0
  218. package/src/shared/escalation-bands.test.ts +23 -0
  219. package/src/shared/escalation-bands.ts +18 -0
  220. package/src/shared/format-threshold.ts +1 -1
  221. package/src/shared/models-dev-cache.test.ts +171 -0
  222. package/src/shared/models-dev-cache.ts +195 -38
  223. package/src/shared/rpc-server.ts +27 -18
  224. package/src/shared/rpc-types.ts +55 -1
  225. package/src/shared/rpc-utils.test.ts +157 -0
  226. package/src/shared/rpc-utils.ts +137 -0
  227. package/src/shared/storage-permissions.ts +20 -0
  228. package/src/shared/tui-runtime-specifiers.ts +32 -0
  229. package/src/tui/compaction-off.test.ts +56 -0
  230. package/src/tui/compaction-off.ts +29 -0
  231. package/src/tui/data/context-db.ts +6 -0
  232. package/src/tui/index.tsx +113 -65
  233. package/src/tui/slots/sidebar-content.tsx +189 -91
  234. package/src/tui/tui-compiled-runtime-imports.test.ts +151 -0
  235. package/src/tui-compiled/compaction-off.ts +29 -0
  236. package/src/tui-compiled/data/context-db.ts +6 -0
  237. package/src/tui-compiled/index.tsx +558 -455
  238. package/src/tui-compiled/slots/sidebar-content.tsx +334 -169
  239. package/dist/send-session-notification-tghq9gnh.js +0 -11
  240. /package/dist/{index-v7fmc1s2.js → index-ygcng9t8.js} +0 -0
@@ -1,7 +1,9 @@
1
1
  import {
2
2
  deriveTriggerBudget,
3
- modelSupportsVision
4
- } from "./index-63dq2g4d.js";
3
+ modelSupportsVision,
4
+ piModelRefToCanonical,
5
+ shouldEnforcePrivateStoragePermissions
6
+ } from "./index-ry8rh8cv.js";
5
7
  import {
6
8
  parseProviderModel
7
9
  } from "./index-td9depx5.js";
@@ -9,18 +11,15 @@ import {
9
11
  describeError,
10
12
  getErrorMessage,
11
13
  sendIgnoredMessage
12
- } from "./index-y1c9tcm3.js";
14
+ } from "./index-cn960ffd.js";
13
15
  import {
14
- Database,
15
16
  clearCachedM0M1,
16
17
  clearCompressionDepth,
17
18
  clearCompressionDepthRange,
18
- closeQuietly,
19
19
  ensureSessionMetaRow,
20
20
  estimateTokens,
21
21
  getCachedAbsoluteMessageCount,
22
22
  getLegacyProtectedTailStartOrdinal,
23
- getMessageTimesFromOpenCodeDb,
24
23
  getRawSessionMessageCount,
25
24
  getRawSessionTagKeysThrough,
26
25
  hasMeaningfulUserText,
@@ -29,9 +28,17 @@ import {
29
28
  persistCachedM0,
30
29
  readRawSessionMessages,
31
30
  readSessionChunk,
32
- updateSessionMeta,
31
+ updateSessionMeta
32
+ } from "./index-b563sga5.js";
33
+ import {
34
+ Database,
35
+ closeQuietly,
36
+ getMessageTimesFromOpenCodeDb,
33
37
  withPrivilegedWriter
34
- } from "./index-ey1bc14z.js";
38
+ } from "./index-fcyvznch.js";
39
+ import {
40
+ pushNotification
41
+ } from "./index-d62ypazr.js";
35
42
  import {
36
43
  log,
37
44
  sessionLog
@@ -372,462 +379,175 @@ function buildPrimaryLanguageDirective(language) {
372
379
  return "";
373
380
  return `Use ${target} for your natural-language replies to the user unless the user explicitly asks for another language. Keep code, identifiers, file paths, commands, logs, and quoted text verbatim.`;
374
381
  }
375
- // src/features/magic-context/overflow-detection.ts
376
- var OVERFLOW_PATTERNS = [
377
- /prompt is too long/i,
378
- /input is too long for requested model/i,
379
- /exceeds the context window/i,
380
- /input token count.*exceeds the maximum/i,
381
- /maximum prompt length is \d+/i,
382
- /reduce the length of the messages/i,
383
- /maximum context length is \d+ tokens/i,
384
- /exceeds the limit of \d+/i,
385
- /exceeds the available context size/i,
386
- /greater than the context length/i,
387
- /context window exceeds limit/i,
388
- /exceeded model token limit/i,
389
- /context[_ ]length[_ ]exceeded/i,
390
- /request entity too large/i,
391
- /context length is only \d+ tokens/i,
392
- /input length.*exceeds.*context length/i,
393
- /prompt too long; exceeded (?:max )?context length/i,
394
- /too large for model with \d+ maximum context length/i,
395
- /model_context_window_exceeded/i,
396
- /context size has been exceeded/i
397
- ];
398
- var LIMIT_EXTRACTION_PATTERNS = [
399
- /maximum prompt length is (\d+)/i,
400
- /maximum context length is (\d+) tokens?/i,
401
- /context length is only (\d+) tokens?/i,
402
- /exceeds the limit of (\d+)/i,
403
- /too large for model with (\d+) maximum context length/i,
404
- /context size.*(\d+) tokens?/i,
405
- /exceeds? the context length of (\d+)/i,
406
- />\s*(\d+)\s*(?:tokens?\s*)?(?:maximum|max|limit)\b/i,
407
- /max(?:imum)?.*context.*?(\d+)/i
408
- ];
409
- var MIN_PLAUSIBLE_LIMIT = 1024;
410
- var MAX_PLAUSIBLE_LIMIT = 1e7;
411
- function extractErrorMessage(error) {
412
- if (!error)
413
- return "";
414
- if (typeof error === "string")
415
- return error;
416
- if (typeof error === "object") {
417
- const obj = error;
418
- const nested = obj.error;
419
- if (nested && typeof nested.message === "string" && nested.message.length > 0) {
420
- return nested.message;
421
- }
422
- }
423
- if (error instanceof Error)
424
- return error.message;
425
- if (typeof error === "object") {
426
- const obj = error;
427
- if (typeof obj.message === "string")
428
- return obj.message;
429
- if (typeof obj.responseBody === "string")
430
- return obj.responseBody;
431
- try {
432
- return JSON.stringify(error);
433
- } catch {
434
- return String(error);
435
- }
436
- }
437
- return String(error);
382
+
383
+ // src/features/magic-context/storage-db.ts
384
+ import {
385
+ chmodSync,
386
+ copyFileSync,
387
+ cpSync,
388
+ existsSync as existsSync3,
389
+ mkdirSync,
390
+ mkdtempSync,
391
+ readdirSync,
392
+ readFileSync as readFileSync2,
393
+ unlinkSync
394
+ } from "node:fs";
395
+ import { basename, dirname, join as join3 } from "node:path";
396
+
397
+ // src/plugin/boot-quiet.ts
398
+ var BOOT_QUIET_MS = 120000;
399
+ var bootQuietUntilMs = 0;
400
+ function beginBootQuietPeriod(now = Date.now()) {
401
+ if (bootQuietUntilMs === 0)
402
+ bootQuietUntilMs = now + BOOT_QUIET_MS;
438
403
  }
439
- function detectOverflow(error) {
440
- const message = extractErrorMessage(error);
441
- if (!message) {
442
- return { isOverflow: false };
443
- }
444
- const hasStatus413 = /\b413\b/.test(message) && /(entity|payload|context|prompt)/i.test(message);
445
- let matched;
446
- for (const pattern of OVERFLOW_PATTERNS) {
447
- if (pattern.test(message)) {
448
- matched = pattern;
449
- break;
450
- }
451
- }
452
- if (!matched && !hasStatus413) {
453
- return { isOverflow: false };
454
- }
455
- const reportedLimit = parseReportedLimit(message);
456
- return {
457
- isOverflow: true,
458
- reportedLimit,
459
- matchedPattern: matched?.source
460
- };
404
+ function bootQuietRemainingMs(now = Date.now()) {
405
+ return Math.max(0, bootQuietUntilMs - now);
461
406
  }
462
- function parseReportedLimit(message) {
463
- if (!message)
464
- return;
465
- for (const pattern of LIMIT_EXTRACTION_PATTERNS) {
466
- const match = message.match(pattern);
467
- if (!match)
468
- continue;
469
- const raw = match[1];
470
- if (!raw)
471
- continue;
472
- const value = Number.parseInt(raw, 10);
473
- if (!Number.isFinite(value))
474
- continue;
475
- if (value < MIN_PLAUSIBLE_LIMIT || value > MAX_PLAUSIBLE_LIMIT)
476
- continue;
477
- return value;
478
- }
479
- return;
407
+ function scheduleAfterBootQuiet(task, additionalDelayMs = 0) {
408
+ const timer = setTimeout(task, bootQuietRemainingMs() + Math.max(0, additionalDelayMs));
409
+ timer.unref?.();
410
+ return timer;
480
411
  }
481
412
 
482
- // src/shared/model-suggestion-retry.ts
483
- var ABORT_CALL_TIMEOUT_MS = 3000;
484
- function copyPromptArgs(args, body) {
485
- return { ...args, body: { ...body } };
413
+ // src/shared/rpc-utils.ts
414
+ import { execFileSync } from "node:child_process";
415
+ import { createHash } from "node:crypto";
416
+ import { readFileSync } from "node:fs";
417
+ import { join } from "node:path";
418
+ function projectHash(directory) {
419
+ const normalized = directory.replace(/\/+$/, "");
420
+ return createHash("sha256").update(normalized).digest("hex").slice(0, 16);
486
421
  }
487
- function extractMessage(error) {
488
- if (typeof error === "string")
489
- return error;
490
- if (error instanceof Error)
491
- return error.message;
492
- if (typeof error === "object" && error !== null) {
493
- const obj = error;
494
- if (typeof obj.message === "string")
495
- return obj.message;
496
- }
497
- try {
498
- return JSON.stringify(error);
499
- } catch (_error) {
500
- return String(error);
501
- }
422
+ function rpcPortDir(storageDir, directory) {
423
+ return join(storageDir, "rpc", projectHash(directory));
502
424
  }
503
- function parseModelSuggestion(error) {
504
- if (!error)
425
+ function rpcPortFilePath(storageDir, directory, pid = process.pid, instanceId) {
426
+ const suffix = instanceId ? `-${instanceId}` : "";
427
+ return join(rpcPortDir(storageDir, directory), `port-${pid}${suffix}.json`);
428
+ }
429
+ function isPidAlive(pid) {
430
+ if (!Number.isInteger(pid) || pid <= 0)
431
+ return false;
432
+ try {
433
+ process.kill(pid, 0);
434
+ return true;
435
+ } catch (err) {
436
+ return err.code === "EPERM";
437
+ }
438
+ }
439
+ var RPC_IDENTITY_SKEW_TOLERANCE_MS = 120000;
440
+ var LINUX_CLOCK_TICKS_PER_SECOND = 100;
441
+ var PS_PROBE_TIMEOUT_MS = 1000;
442
+ var OPEN_CODE_COMMAND_MARKERS = ["opencode", "node", "bun", "electron"];
443
+ var rpcIdentityReadFileSync = readFileSync;
444
+ var rpcIdentityExecFileSync = execFileSync;
445
+ var rpcIdentityPlatform = process.platform;
446
+ var rpcIdentityNowMs = () => Date.now();
447
+ function parseLinuxProcessStartTime(statContent, uptimeContent) {
448
+ const closingCommandName = statContent.lastIndexOf(")");
449
+ if (closingCommandName < 0)
505
450
  return null;
506
- if (typeof error === "object" && error !== null) {
507
- const errObj = error;
508
- if (errObj.name === "ProviderModelNotFoundError" && typeof errObj.data === "object" && errObj.data !== null) {
509
- const data = errObj.data;
510
- const suggestions = data.suggestions;
511
- if (Array.isArray(suggestions) && typeof suggestions[0] === "string") {
512
- return {
513
- providerID: String(data.providerID ?? ""),
514
- modelID: String(data.modelID ?? ""),
515
- suggestion: suggestions[0]
516
- };
517
- }
518
- }
519
- for (const key of ["data", "error", "cause"]) {
520
- const nested = errObj[key];
521
- if (nested && typeof nested === "object") {
522
- const result = parseModelSuggestion(nested);
523
- if (result)
524
- return result;
525
- }
526
- }
527
- }
528
- const message = extractMessage(error);
529
- const modelMatch = message.match(/model not found:\s*([^/\s]+)\s*\/\s*([^.,\s]+)/i);
530
- const suggestionMatch = message.match(/did you mean:\s*([^,?]+)/i);
531
- if (!modelMatch || !suggestionMatch) {
451
+ const statFields = statContent.slice(closingCommandName + 1).trim().split(/\s+/);
452
+ const startTimeTicks = Number(statFields[19]);
453
+ const uptimeSeconds = Number(uptimeContent.trim().split(/\s+/)[0]);
454
+ if (!Number.isFinite(startTimeTicks) || startTimeTicks < 0 || !Number.isFinite(uptimeSeconds) || uptimeSeconds < 0) {
532
455
  return null;
533
456
  }
534
- return {
535
- providerID: modelMatch[1].trim(),
536
- modelID: modelMatch[2].trim(),
537
- suggestion: suggestionMatch[1].trim()
538
- };
457
+ const processStartTime = rpcIdentityNowMs() - uptimeSeconds * 1000 + startTimeTicks / LINUX_CLOCK_TICKS_PER_SECOND * 1000;
458
+ return Number.isFinite(processStartTime) ? processStartTime : null;
539
459
  }
540
- async function promptWithTimeout(client, args, timeoutMs, signal) {
541
- if (signal?.aborted) {
542
- throw new Error("prompt aborted by external signal");
543
- }
544
- const controller = new AbortController;
545
- const timeout = setTimeout(() => controller.abort(), timeoutMs);
546
- const onExternalAbort = () => controller.abort();
547
- signal?.addEventListener("abort", onExternalAbort);
460
+ function readLinuxProcessStartTime(pid) {
548
461
  try {
549
- await client.session.prompt({
550
- ...args,
551
- signal: controller.signal
552
- });
553
- } catch (error) {
554
- if (signal?.aborted) {
555
- await abortChildRun(client, args.path.id);
556
- throw new Error("prompt aborted by external signal");
557
- }
558
- if (controller.signal.aborted) {
559
- await abortChildRun(client, args.path.id);
560
- throw new Error(`prompt timed out after ${timeoutMs}ms`);
561
- }
562
- throw error;
563
- } finally {
564
- clearTimeout(timeout);
565
- signal?.removeEventListener("abort", onExternalAbort);
462
+ const statContent = String(rpcIdentityReadFileSync(`/proc/${pid}/stat`, "utf8"));
463
+ const uptimeContent = String(rpcIdentityReadFileSync("/proc/uptime", "utf8"));
464
+ return parseLinuxProcessStartTime(statContent, uptimeContent);
465
+ } catch {
466
+ return null;
566
467
  }
567
468
  }
568
- async function abortChildRun(client, sessionId) {
469
+ function readPsProcessStartTime(pid) {
569
470
  try {
570
- await Promise.race([
571
- client.session.abort({ path: { id: sessionId } }),
572
- new Promise((resolve) => setTimeout(resolve, ABORT_CALL_TIMEOUT_MS))
573
- ]);
574
- } catch (error) {
575
- log(`[model-retry] child session abort failed for ${sessionId}: ${String(error)}`);
576
- }
577
- }
578
- function isNonRetryable(error, externalSignal) {
579
- if (externalSignal?.aborted)
580
- return true;
581
- if (error instanceof Error) {
582
- if (error.name === "AbortError")
583
- return true;
584
- if (error.message === "prompt aborted by external signal")
585
- return true;
586
- if (/^prompt timed out after \d+ms$/.test(error.message))
587
- return true;
471
+ const output = rpcIdentityExecFileSync("ps", ["-p", String(pid), "-o", "lstart="], {
472
+ encoding: "utf8",
473
+ timeout: PS_PROBE_TIMEOUT_MS
474
+ });
475
+ const processStartTime = Date.parse(String(output).trim());
476
+ return Number.isFinite(processStartTime) ? processStartTime : null;
477
+ } catch {
478
+ return null;
588
479
  }
589
- if (detectOverflow(error).isOverflow)
590
- return true;
591
- return false;
592
480
  }
593
- function shortErr(error) {
594
- if (error instanceof Error) {
595
- return error.name && error.name !== "Error" ? `${error.name}: ${error.message}` : error.message;
596
- }
597
- return extractMessage(error);
598
- }
599
- async function attemptOnce(client, args, timeoutMs, signal, callContext, label) {
600
- const originalBody = { ...args.body };
601
- const attemptArgs = copyPromptArgs(args, originalBody);
481
+ function readLinuxProcessCommand(pid) {
602
482
  try {
603
- await promptWithTimeout(client, attemptArgs, timeoutMs, signal);
604
- return;
605
- } catch (error) {
606
- if (isNonRetryable(error, signal))
607
- throw error;
608
- const suggestion = parseModelSuggestion(error);
609
- if (!suggestion || !originalBody.model) {
610
- throw error;
611
- }
612
- log(`[${callContext}] ${label}: model not found, retrying with suggestion`, {
613
- original: `${suggestion.providerID}/${suggestion.modelID}`,
614
- suggested: suggestion.suggestion
615
- });
616
- await promptWithTimeout(client, copyPromptArgs(args, {
617
- ...originalBody,
618
- model: {
619
- providerID: suggestion.providerID,
620
- modelID: suggestion.suggestion
621
- }
622
- }), timeoutMs, signal);
483
+ return String(rpcIdentityReadFileSync(`/proc/${pid}/cmdline`, "utf8"));
484
+ } catch {
485
+ return null;
623
486
  }
624
487
  }
625
- async function promptSyncWithModelSuggestionRetry(client, args, options = {}) {
626
- const timeoutMs = options.timeoutMs ?? 300000;
627
- const callContext = options.callContext ?? "subagent";
628
- const fallbacks = options.fallbackModels ?? [];
629
- const baseBody = { ...args.body };
630
- const baseArgs = copyPromptArgs(args, baseBody);
631
- const explicitPrimaryLabel = baseBody.model?.providerID && baseBody.model.modelID ? `${baseBody.model.providerID}/${baseBody.model.modelID}` : "primary";
632
- let lastError = null;
488
+ function readPsProcessCommand(pid) {
633
489
  try {
634
- await attemptOnce(client, baseArgs, timeoutMs, options.signal, callContext, explicitPrimaryLabel);
635
- return;
636
- } catch (error) {
637
- lastError = error;
638
- if (isNonRetryable(error, options.signal))
639
- throw error;
640
- if (fallbacks.length === 0) {
641
- throw error;
642
- }
643
- log(`[${callContext}] primary (${explicitPrimaryLabel}) failed: ${shortErr(error)}; trying ${fallbacks.length} fallback(s)`);
644
- }
645
- for (let i = 0;i < fallbacks.length; i += 1) {
646
- const parsed = parseProviderModel(fallbacks[i]);
647
- if (!parsed) {
648
- log(`[${callContext}] skipping invalid fallback spec: ${fallbacks[i]}`);
649
- continue;
650
- }
651
- const label = `${parsed.providerID}/${parsed.modelID}`;
652
- const attemptArgs = copyPromptArgs(baseArgs, {
653
- ...baseBody,
654
- model: parsed
490
+ const output = rpcIdentityExecFileSync("ps", ["-p", String(pid), "-o", "command="], {
491
+ encoding: "utf8",
492
+ timeout: PS_PROBE_TIMEOUT_MS
655
493
  });
656
- try {
657
- await attemptOnce(client, attemptArgs, timeoutMs, options.signal, callContext, label);
658
- log(`[${callContext}] fallback succeeded with ${label} (attempt ${i + 2}/${fallbacks.length + 1})`);
659
- return;
660
- } catch (error) {
661
- lastError = error;
662
- if (isNonRetryable(error, options.signal))
663
- throw error;
664
- const remaining = fallbacks.length - i - 1;
665
- if (remaining > 0) {
666
- log(`[${callContext}] ${label} failed: ${shortErr(error)}; ${remaining} fallback(s) left`);
667
- }
668
- }
494
+ return String(output);
495
+ } catch {
496
+ return null;
669
497
  }
670
- log(`[${callContext}] all models exhausted; tried: ${[explicitPrimaryLabel, ...fallbacks].join(", ")}; last error: ${shortErr(lastError)}`);
671
- throw lastError ?? new Error("All fallback models failed");
672
498
  }
673
- async function attemptAndValidate(client, args, timeoutMs, signal, callContext, attempt, options) {
674
- await attemptOnce(client, args, timeoutMs, signal, callContext, attempt.label);
675
- const output = await options.fetchOutput(args, attempt);
676
- const validated = await options.validateOutput(output, attempt);
677
- return { output, validated, attempt };
499
+ function commandLooksLikeOpenCode(command) {
500
+ const normalized = command.toLowerCase();
501
+ return OPEN_CODE_COMMAND_MARKERS.some((marker) => normalized.includes(marker));
678
502
  }
679
- async function promptSyncWithValidatedOutputRetry(client, args, options) {
680
- const timeoutMs = options.timeoutMs ?? 300000;
681
- const callContext = options.callContext ?? "subagent";
682
- const fallbacks = options.fallbackModels ?? [];
683
- const baseBody = { ...args.body };
684
- const baseArgs = copyPromptArgs(args, baseBody);
685
- const explicitPrimaryLabel = baseBody.model?.providerID && baseBody.model.modelID ? `${baseBody.model.providerID}/${baseBody.model.modelID}` : "primary";
686
- const totalAttempts = fallbacks.length + 1;
687
- let firstError = null;
688
- let lastError = null;
689
- try {
690
- return await attemptAndValidate(client, baseArgs, timeoutMs, options.signal, callContext, {
691
- label: explicitPrimaryLabel,
692
- attemptIndex: 0,
693
- isFallback: false,
694
- totalAttempts,
695
- model: baseBody.model
696
- }, options);
697
- } catch (error) {
698
- firstError = error;
699
- lastError = error;
700
- if (isNonRetryable(error, options.signal))
701
- throw error;
702
- if (fallbacks.length === 0) {
703
- throw error;
704
- }
705
- log(`[${callContext}] primary (${explicitPrimaryLabel}) failed validation/prompt: ${shortErr(error)}; trying ${fallbacks.length} fallback(s)`);
706
- }
707
- for (let i = 0;i < fallbacks.length; i += 1) {
708
- const parsed = parseProviderModel(fallbacks[i]);
709
- if (!parsed) {
710
- log(`[${callContext}] skipping invalid fallback spec: ${fallbacks[i]}`);
711
- continue;
712
- }
713
- const label = `${parsed.providerID}/${parsed.modelID}`;
714
- const attemptArgs = copyPromptArgs(baseArgs, {
715
- ...baseBody,
716
- model: parsed
717
- });
718
- const attempt = {
719
- label,
720
- attemptIndex: i + 1,
721
- isFallback: true,
722
- totalAttempts,
723
- model: parsed
724
- };
725
- try {
726
- const result = await attemptAndValidate(client, attemptArgs, timeoutMs, options.signal, callContext, attempt, options);
727
- log(`[${callContext}] fallback succeeded with ${label} (attempt ${i + 2}/${fallbacks.length + 1})`);
728
- return result;
729
- } catch (error) {
730
- if (firstError === null)
731
- firstError = error;
732
- lastError = error;
733
- if (isNonRetryable(error, options.signal))
734
- throw error;
735
- const remaining = fallbacks.length - i - 1;
736
- if (remaining > 0) {
737
- log(`[${callContext}] ${label} failed validation/prompt: ${shortErr(error)}; ${remaining} fallback(s) left`);
738
- }
739
- }
503
+ function isPidIdentityPlausible(record) {
504
+ if (!Number.isInteger(record.pid) || record.pid <= 0)
505
+ return false;
506
+ if (Number.isFinite(record.started_at) && record.started_at > 0) {
507
+ const processStartTime = rpcIdentityPlatform === "linux" ? readLinuxProcessStartTime(record.pid) : readPsProcessStartTime(record.pid);
508
+ if (processStartTime === null)
509
+ return true;
510
+ return processStartTime <= record.started_at + RPC_IDENTITY_SKEW_TOLERANCE_MS;
740
511
  }
741
- log(`[${callContext}] all models exhausted; tried: ${[explicitPrimaryLabel, ...fallbacks].join(", ")}; original error: ${shortErr(firstError)}; last error: ${shortErr(lastError)}`);
742
- throw firstError ?? lastError ?? new Error("All fallback models failed validation");
512
+ const command = rpcIdentityPlatform === "linux" ? readLinuxProcessCommand(record.pid) : readPsProcessCommand(record.pid);
513
+ if (command === null)
514
+ return true;
515
+ return commandLooksLikeOpenCode(command);
743
516
  }
744
- // src/shared/normalize-sdk-response.ts
745
- function normalizeSDKResponse(response, fallback, options) {
746
- if (response === null || response === undefined) {
747
- return fallback;
748
- }
749
- if (Array.isArray(response)) {
750
- return response;
751
- }
752
- if (typeof response === "object" && "data" in response) {
753
- const data = response.data;
754
- if (data !== null && data !== undefined) {
755
- return data;
756
- }
757
- if (options?.preferResponseOnMissingData === true) {
758
- return response;
517
+ function parseRpcPortFile(content, fallbackPid = 0) {
518
+ const trimmed = content.trim();
519
+ if (!trimmed)
520
+ return null;
521
+ if (trimmed.startsWith("{")) {
522
+ try {
523
+ const parsed = JSON.parse(trimmed);
524
+ const port2 = Number(parsed.port);
525
+ const pid = Number(parsed.pid);
526
+ const startedAt = Number(parsed.started_at);
527
+ if (!isValidPort(port2) || !Number.isInteger(pid) || pid <= 0)
528
+ return null;
529
+ return {
530
+ port: port2,
531
+ pid,
532
+ started_at: Number.isFinite(startedAt) ? startedAt : 0,
533
+ token: typeof parsed.token === "string" ? parsed.token : undefined,
534
+ instance_id: typeof parsed.instance_id === "string" ? parsed.instance_id : undefined
535
+ };
536
+ } catch {
537
+ return null;
759
538
  }
760
- return fallback;
761
539
  }
762
- if (options?.preferResponseOnMissingData === true) {
763
- return response;
764
- }
765
- return fallback;
766
- }
767
- // src/shared/assistant-message-extractor.ts
768
- function asSessionMessage(value) {
769
- if (!isRecord(value))
770
- return null;
771
- const info = value.info;
772
- const parts = value.parts;
773
- return {
774
- info: isRecord(info) ? {
775
- role: typeof info.role === "string" ? info.role : undefined,
776
- time: isRecord(info.time) ? {
777
- created: typeof info.time.created === "number" ? info.time.created : undefined
778
- } : undefined
779
- } : undefined,
780
- parts
781
- };
782
- }
783
- function getCreatedTime(message) {
784
- return message.info?.time?.created ?? 0;
785
- }
786
- function getTextParts(message) {
787
- if (!Array.isArray(message.parts))
788
- return [];
789
- return message.parts.filter((part) => isRecord(part)).map((part) => ({
790
- type: typeof part.type === "string" ? part.type : undefined,
791
- text: typeof part.text === "string" ? part.text : undefined
792
- })).filter((part) => part.type === "text" && Boolean(part.text));
793
- }
794
- function extractLatestAssistantText(messages) {
795
- if (!Array.isArray(messages) || messages.length === 0)
796
- return null;
797
- const assistantMessages = messages.map(asSessionMessage).filter((message) => message !== null).filter((message) => message.info?.role === "assistant").sort((a, b) => getCreatedTime(b) - getCreatedTime(a));
798
- const latest = assistantMessages[0];
799
- if (!latest)
540
+ const port = Number.parseInt(trimmed, 10);
541
+ if (!isValidPort(port))
800
542
  return null;
801
- return getTextParts(latest).map((part) => part.text).join(`
802
- `) || null;
543
+ return { port, pid: fallbackPid, started_at: 0 };
803
544
  }
804
- function hasLengthCappedOutput(value) {
805
- if (Array.isArray(value))
806
- return value.some((item) => hasLengthCappedOutput(item));
807
- if (!isRecord(value))
808
- return false;
809
- if (value.length_capped === true || value.lengthCapped === true)
810
- return true;
811
- const finishReason = value.finish_reason ?? value.finishReason;
812
- if (typeof finishReason === "string") {
813
- const normalized = finishReason.toLowerCase();
814
- if (normalized === "length" || normalized === "max_tokens" || normalized === "max_output_tokens") {
815
- return true;
816
- }
817
- }
818
- return Object.values(value).some((item) => hasLengthCappedOutput(item));
545
+ function isValidPort(port) {
546
+ return Number.isInteger(port) && port > 0 && port <= 65535;
819
547
  }
820
548
 
821
- // src/shared/keep-subagents.ts
822
- var keepSubagents = false;
823
- function setKeepSubagents(value) {
824
- keepSubagents = value === true;
825
- }
826
- function shouldKeepSubagents() {
827
- return keepSubagents;
828
- }
829
549
  // src/features/magic-context/context-authority.ts
830
- import { createHash, randomUUID } from "node:crypto";
550
+ import { createHash as createHash2, randomUUID } from "node:crypto";
831
551
  var AUTHORITY_DOMAINS = ["memories", "notes"];
832
552
  var moduleNoteEvaluationBridges = new Map;
833
553
  function registerModuleNoteEvaluationBridge(projectPath, bridge) {
@@ -959,7 +679,7 @@ function checksumAuthoritySeedRows(rows) {
959
679
  const rightId = seedSourceRowId(right) ?? Number.MAX_SAFE_INTEGER;
960
680
  return leftId - rightId;
961
681
  });
962
- return createHash("sha256").update(JSON.stringify(ordered.map(canonicalizeSeedValue))).digest("hex");
682
+ return createHash2("sha256").update(JSON.stringify(ordered.map(canonicalizeSeedValue))).digest("hex");
963
683
  }
964
684
  function maxDomainRowId(db, domain, projectPath) {
965
685
  const row = domain === "memories" ? db.prepare("SELECT COALESCE(MAX(rowid), 0) AS max_rowid FROM memories WHERE project_path = ?").get(projectPath) : db.prepare(`SELECT COALESCE(MAX(n.rowid), 0) AS max_rowid
@@ -1047,10 +767,14 @@ async function prepareAuthority(args) {
1047
767
  domain,
1048
768
  rows: page
1049
769
  });
1050
- const identities = (seedResponse.module_row_ids ?? []).map((moduleRowId, index) => ({
1051
- moduleRowId,
1052
- sourceRowId: seedSourceRowId(page[index])
1053
- })).filter((identity) => identity.sourceRowId !== null);
770
+ const identityByModuleRowId = new Map;
771
+ for (const [index, moduleRowId] of (seedResponse.module_row_ids ?? []).entries()) {
772
+ const sourceRowId = seedSourceRowId(page[index]);
773
+ if (sourceRowId === null)
774
+ continue;
775
+ identityByModuleRowId.set(moduleRowId, { moduleRowId, sourceRowId });
776
+ }
777
+ const identities = [...identityByModuleRowId.values()];
1054
778
  if (identities.length > 0) {
1055
779
  args.db.transaction(() => {
1056
780
  for (const identity of identities) {
@@ -1951,6 +1675,7 @@ function pullMemoryMirrorOnce(args) {
1951
1675
  mirrorFlights.set(args.module, flight);
1952
1676
  return flight;
1953
1677
  }
1678
+
1954
1679
  // src/hooks/magic-context/compartment-parser.ts
1955
1680
  var COMPARTMENT_REGEX = /<compartment\s+([^>]*?)\s*>(.*?)<\/compartment>/gs;
1956
1681
  var ATTR_START_REGEX = /\bstart="(\d+)"/;
@@ -2221,7 +1946,7 @@ function healMissingMemoryBlockIds(db, columns) {
2221
1946
  }
2222
1947
 
2223
1948
  // src/features/magic-context/workspaces.ts
2224
- import { createHash as createHash3 } from "node:crypto";
1949
+ import { createHash as createHash4 } from "node:crypto";
2225
1950
 
2226
1951
  // src/features/magic-context/memory/constants.ts
2227
1952
  var V2_MEMORY_CATEGORIES = [
@@ -2274,8 +1999,8 @@ var CATEGORY_DEFAULT_TTL = {
2274
1999
  };
2275
2000
 
2276
2001
  // src/features/magic-context/memory/project-identity.ts
2277
- import { execFileSync } from "node:child_process";
2278
- import { createHash as createHash2 } from "node:crypto";
2002
+ import { execFileSync as execFileSync2 } from "node:child_process";
2003
+ import { createHash as createHash3 } from "node:crypto";
2279
2004
  import { existsSync, realpathSync, statSync } from "node:fs";
2280
2005
  import { homedir } from "node:os";
2281
2006
  import path from "node:path";
@@ -2289,7 +2014,8 @@ var dubiousOwnershipFallbackDirectories = new Set;
2289
2014
  var dubiousOwnershipLoggedDirectories = new Set;
2290
2015
  var dubiousOwnershipWarnedDirectories = new Set;
2291
2016
  var transientGitIdentityReuseLoggedDirectories = new Set;
2292
- var execFileSyncForIdentity = execFileSync;
2017
+ var execFileSyncForIdentity = execFileSync2;
2018
+ var userHomeDirectoryForIdentity = () => homedir();
2293
2019
  var nowMs = () => Date.now();
2294
2020
 
2295
2021
  class ProjectIdentityError extends Error {
@@ -2343,7 +2069,7 @@ function getErrorStderr(error) {
2343
2069
  }
2344
2070
  function directoryFallback(directory) {
2345
2071
  const canonical = path.resolve(directory);
2346
- const hash = createHash2("md5").update(canonical, "utf8").digest("hex").slice(0, 12);
2072
+ const hash = createHash3("md5").update(canonical, "utf8").digest("hex").slice(0, 12);
2347
2073
  return `dir:${hash}`;
2348
2074
  }
2349
2075
  function assertDirectoryUsable(canonicalDirectory, rawDirectory) {
@@ -2494,9 +2220,12 @@ function takeDubiousOwnershipProjectIdentityWarning(directory) {
2494
2220
  dubiousOwnershipWarnedDirectories.add(canonical);
2495
2221
  return formatDubiousOwnershipWarning(canonical);
2496
2222
  }
2223
+ function canonicalUserHomeDirectory() {
2224
+ return realpathSync.native(userHomeDirectoryForIdentity());
2225
+ }
2497
2226
  function isUserHomeDirectory(directory) {
2498
2227
  try {
2499
- return realpathSync.native(path.resolve(directory)) === realpathSync.native(homedir());
2228
+ return realpathSync.native(path.resolve(directory)) === canonicalUserHomeDirectory();
2500
2229
  } catch {
2501
2230
  return false;
2502
2231
  }
@@ -2565,22 +2294,52 @@ function hasGitDir(canonical) {
2565
2294
  return false;
2566
2295
  }
2567
2296
  }
2568
- function hasGitDirInAncestorChain(startDirectory) {
2297
+ function gitRootInAncestorChain(startDirectory) {
2569
2298
  let current = startDirectory;
2570
2299
  while (true) {
2571
2300
  if (existsSync(path.join(current, ".git"))) {
2572
- return true;
2301
+ try {
2302
+ return realpathSync.native(current);
2303
+ } catch {
2304
+ return path.resolve(current);
2305
+ }
2573
2306
  }
2574
2307
  const parent = path.dirname(current);
2575
2308
  if (parent === current) {
2576
- return false;
2309
+ return null;
2577
2310
  }
2578
2311
  current = parent;
2579
2312
  }
2580
2313
  }
2581
- function resolveProjectIdentityForSession(directory) {
2582
- if (isUserHomeDirectory(directory))
2583
- return;
2314
+ function hasGitDirInAncestorChain(startDirectory) {
2315
+ return gitRootInAncestorChain(startDirectory) !== null;
2316
+ }
2317
+ function gitRootDirectory(canonical) {
2318
+ const direct = gitRootInAncestorChain(canonical);
2319
+ if (direct)
2320
+ return direct;
2321
+ try {
2322
+ const realCanonical = realpathSync.native(canonical);
2323
+ return realCanonical === canonical ? null : gitRootInAncestorChain(realCanonical);
2324
+ } catch {
2325
+ return null;
2326
+ }
2327
+ }
2328
+ function resolveProjectIdentityForSession(directory, allowHomeProject = false) {
2329
+ const canonicalHome = canonicalUserHomeDirectory();
2330
+ const canonicalDirectory = (() => {
2331
+ try {
2332
+ return realpathSync.native(path.resolve(directory));
2333
+ } catch {
2334
+ return path.resolve(directory);
2335
+ }
2336
+ })();
2337
+ const inheritsHomeRepository = gitRootDirectory(canonicalDirectory) === canonicalHome;
2338
+ if (canonicalDirectory === canonicalHome || inheritsHomeRepository) {
2339
+ if (!allowHomeProject)
2340
+ return;
2341
+ return directoryFallback(canonicalHome);
2342
+ }
2584
2343
  return resolveProjectIdentityOrFallback(directory);
2585
2344
  }
2586
2345
  function normalizeStoredProjectPath(rawOrStored) {
@@ -2782,7 +2541,7 @@ function computeWorkspaceEpochFingerprint(db, identities) {
2782
2541
  const canonical = uniqueSorted(identities.filter((identity) => identity.length > 0));
2783
2542
  const epochs = getEpochMap(db, canonical);
2784
2543
  const shareCategories = selectWorkspaceShareCategories(db, canonical);
2785
- const hash = createHash3("sha256");
2544
+ const hash = createHash4("sha256");
2786
2545
  hash.update("share_categories", "utf8");
2787
2546
  hash.update("\x00");
2788
2547
  hash.update(shareCategories === null ? "NO_WORKSPACE" : JSON.stringify(shareCategories), "utf8");
@@ -2859,6 +2618,7 @@ function bumpEpochsForWorkspaceMemberSet(db, identities, now = Date.now()) {
2859
2618
  }
2860
2619
 
2861
2620
  // src/features/magic-context/migrations.ts
2621
+ var FORK_MIGRATION_VERSION_FLOOR = 1e4;
2862
2622
  var MIGRATION_LOCK_RETRY_DELAYS_MS = [1000, 2000, 4000, 8000, 15000];
2863
2623
 
2864
2624
  class MigrationLockBusyError extends Error {
@@ -4869,6 +4629,33 @@ var MIGRATIONS = [
4869
4629
  up(db) {
4870
4630
  installLatestAuthorityTriggers(db);
4871
4631
  }
4632
+ },
4633
+ {
4634
+ version: 72,
4635
+ description: "add per-session compaction mode record column (issue #266)",
4636
+ up(db) {
4637
+ if (tableExists2(db, "session_meta")) {
4638
+ ensureColumn(db, "session_meta", "compaction_mode_record", "TEXT");
4639
+ }
4640
+ }
4641
+ },
4642
+ {
4643
+ version: 73,
4644
+ description: "persist the last successful todowrite permission verdict",
4645
+ up(db) {
4646
+ if (tableExists2(db, "session_meta")) {
4647
+ ensureColumn(db, "session_meta", "todo_permission_denied", "INTEGER NOT NULL DEFAULT 2");
4648
+ }
4649
+ }
4650
+ },
4651
+ {
4652
+ version: 74,
4653
+ description: "persist detected context-limit provenance",
4654
+ up(db) {
4655
+ if (tableExists2(db, "session_meta")) {
4656
+ ensureColumn(db, "session_meta", "detected_context_limit_provenance", "TEXT NOT NULL DEFAULT 'unknown'");
4657
+ }
4658
+ }
4872
4659
  }
4873
4660
  ];
4874
4661
  var LATEST_MIGRATION_VERSION = MIGRATIONS.reduce((max, m) => Math.max(max, m.version), 0);
@@ -4882,9 +4669,12 @@ function ensureMigrationsTable(db) {
4882
4669
  `);
4883
4670
  }
4884
4671
  function getCurrentVersion(db) {
4885
- const row = db.prepare("SELECT MAX(version) as version FROM schema_migrations").get();
4672
+ const row = db.prepare("SELECT COALESCE(MAX(version), 0) AS version FROM schema_migrations WHERE version < ?").get(FORK_MIGRATION_VERSION_FLOOR);
4886
4673
  return row?.version ?? 0;
4887
4674
  }
4675
+ function isMigrationApplied(db, version) {
4676
+ return db.prepare("SELECT 1 FROM schema_migrations WHERE version = ?").get(version) != null;
4677
+ }
4888
4678
  function isSiblingMigrationConflict(db, error, version) {
4889
4679
  if (!(error instanceof Error))
4890
4680
  return false;
@@ -4913,12 +4703,12 @@ function runMigrations(db) {
4913
4703
  try {
4914
4704
  const applied = db.transaction(() => {
4915
4705
  currentVersion = getCurrentVersion(db);
4916
- migration = MIGRATIONS.find((candidate) => candidate.version > currentVersion);
4706
+ migration = MIGRATIONS.find((candidate) => candidate.version > currentVersion && !isMigrationApplied(db, candidate.version));
4917
4707
  if (!migration)
4918
4708
  return false;
4919
4709
  if (!loggedPlan) {
4920
- const pendingCount = MIGRATIONS.filter((candidate) => candidate.version > currentVersion).length;
4921
- log(`[migrations] current schema version: ${currentVersion}, applying ${pendingCount} migration(s)`);
4710
+ const pendingCount = MIGRATIONS.filter((candidate) => candidate.version > currentVersion && !isMigrationApplied(db, candidate.version)).length;
4711
+ log(`[migrations] current upstream migration lane: ${currentVersion}, applying ${pendingCount} migration(s)`);
4922
4712
  loggedPlan = true;
4923
4713
  }
4924
4714
  migration.up(db);
@@ -4955,7 +4745,7 @@ function runMigrations(db) {
4955
4745
  }
4956
4746
  }
4957
4747
  if (loggedPlan) {
4958
- log(`[migrations] schema version now: ${MIGRATIONS[MIGRATIONS.length - 1].version}`);
4748
+ log(`[migrations] upstream migration lane now: ${MIGRATIONS[MIGRATIONS.length - 1].version}`);
4959
4749
  }
4960
4750
  }
4961
4751
  async function runMigrationsWithRetry(db, options = {}) {
@@ -4978,151 +4768,6 @@ async function runMigrationsWithRetry(db, options = {}) {
4978
4768
  }
4979
4769
  }
4980
4770
  }
4981
- // src/features/magic-context/project-docs-hash.ts
4982
- import { createHash as createHash4 } from "node:crypto";
4983
- import { lstatSync, readFileSync, statSync as statSync2 } from "node:fs";
4984
- import path2 from "node:path";
4985
- var PROJECT_DOC_FILES = ["ARCHITECTURE.md", "STRUCTURE.md"];
4986
- var PROJECT_DOCS_DELIMITER = `
4987
-
4988
- ---
4989
-
4990
- `;
4991
- var MAX_PROJECT_DOC_BYTES = 256 * 1024;
4992
- var docsCache = new Map;
4993
- function canonicalizeDocContent(raw) {
4994
- return raw.replace(/^\uFEFF/, "").replace(/\r\n/g, `
4995
- `).split(`
4996
- `).map((line) => line.replace(/[ \t]+$/, "")).join(`
4997
- `).replace(/\n+$/, "");
4998
- }
4999
- function fingerprintFile(filePath) {
5000
- try {
5001
- const stat = lstatSync(filePath);
5002
- const isReadableDoc = stat.isFile() && stat.size <= MAX_PROJECT_DOC_BYTES;
5003
- return {
5004
- exists: isReadableDoc,
5005
- mtimeMs: stat.mtimeMs,
5006
- size: stat.size
5007
- };
5008
- } catch {
5009
- return { exists: false, mtimeMs: 0, size: 0 };
5010
- }
5011
- }
5012
- function readDirectoryMtimeMs(projectDirectory) {
5013
- try {
5014
- return statSync2(projectDirectory).mtimeMs;
5015
- } catch {
5016
- return 0;
5017
- }
5018
- }
5019
- function fingerprintsEqual(a, b) {
5020
- return a?.exists === b.exists && a.mtimeMs === b.mtimeMs && a.size === b.size;
5021
- }
5022
- function cacheFilesEqual(cachedFiles, currentFiles) {
5023
- for (const [filePath, current] of currentFiles) {
5024
- if (!fingerprintsEqual(cachedFiles.get(filePath), current)) {
5025
- return false;
5026
- }
5027
- }
5028
- return true;
5029
- }
5030
- function readCurrentFingerprints(projectDirectory) {
5031
- const files = new Map;
5032
- for (const filename of PROJECT_DOC_FILES) {
5033
- const filePath = path2.join(projectDirectory, filename);
5034
- files.set(filePath, fingerprintFile(filePath));
5035
- }
5036
- return { directoryMtimeMs: readDirectoryMtimeMs(projectDirectory), files };
5037
- }
5038
- function readCanonicalPieces(projectDirectory, files) {
5039
- const hashPieces = [];
5040
- const renderedSections = [];
5041
- for (const filename of PROJECT_DOC_FILES) {
5042
- const filePath = path2.join(projectDirectory, filename);
5043
- const fingerprint = files.get(filePath);
5044
- if (!fingerprint?.exists) {
5045
- continue;
5046
- }
5047
- let safeToRead = false;
5048
- try {
5049
- const st = lstatSync(filePath);
5050
- safeToRead = st.isFile() && st.size <= MAX_PROJECT_DOC_BYTES;
5051
- } catch {
5052
- safeToRead = false;
5053
- }
5054
- if (!safeToRead) {
5055
- continue;
5056
- }
5057
- const canonicalContent = canonicalizeDocContent(readFileSync(filePath, "utf8"));
5058
- hashPieces.push(`file:${filename}
5059
- ${canonicalContent}`);
5060
- renderedSections.push(`<file name="${escapeXmlAttr(filename)}">
5061
- ${escapeXmlContent(canonicalContent)}
5062
- </file>`);
5063
- }
5064
- return { hashPieces, renderedSections };
5065
- }
5066
- function buildRenderedBlock(renderedSections) {
5067
- if (renderedSections.length === 0) {
5068
- return "";
5069
- }
5070
- return `<project-docs>
5071
- ${renderedSections.join(`
5072
-
5073
- `)}
5074
- </project-docs>`;
5075
- }
5076
- function hashCanonicalPieces(hashPieces) {
5077
- if (hashPieces.length === 0) {
5078
- return "";
5079
- }
5080
- return createHash4("sha256").update(hashPieces.join(PROJECT_DOCS_DELIMITER), "utf8").digest("hex");
5081
- }
5082
- function readProjectDocsCanonical(projectDirectory) {
5083
- const canonicalDirectory = path2.resolve(projectDirectory);
5084
- const current = readCurrentFingerprints(canonicalDirectory);
5085
- const cached = docsCache.get(canonicalDirectory);
5086
- if (cached && cacheFilesEqual(cached.files, current.files)) {
5087
- cached.directoryMtimeMs = current.directoryMtimeMs;
5088
- return {
5089
- renderedBlock: cached.cachedRendered,
5090
- canonicalHash: cached.cachedHash
5091
- };
5092
- }
5093
- const { hashPieces, renderedSections } = readCanonicalPieces(canonicalDirectory, current.files);
5094
- const canonicalHash = hashCanonicalPieces(hashPieces);
5095
- const renderedBlock = buildRenderedBlock(renderedSections);
5096
- docsCache.set(canonicalDirectory, {
5097
- directoryMtimeMs: current.directoryMtimeMs,
5098
- files: current.files,
5099
- cachedHash: canonicalHash,
5100
- cachedRendered: renderedBlock
5101
- });
5102
- return { renderedBlock, canonicalHash };
5103
- }
5104
- function computeProjectDocsHash(projectDirectory) {
5105
- return readProjectDocsCanonical(projectDirectory).canonicalHash;
5106
- }
5107
- // src/features/magic-context/storage-db.ts
5108
- import { chmodSync, copyFileSync, cpSync, existsSync as existsSync3, mkdirSync, mkdtempSync } from "node:fs";
5109
- import { dirname, join as join2 } from "node:path";
5110
-
5111
- // src/plugin/boot-quiet.ts
5112
- var BOOT_QUIET_MS = 120000;
5113
- var bootQuietUntilMs = 0;
5114
- function beginBootQuietPeriod(now = Date.now()) {
5115
- if (bootQuietUntilMs === 0)
5116
- bootQuietUntilMs = now + BOOT_QUIET_MS;
5117
- }
5118
- function bootQuietRemainingMs(now = Date.now()) {
5119
- return Math.max(0, bootQuietUntilMs - now);
5120
- }
5121
- function scheduleAfterBootQuiet(task, additionalDelayMs = 0) {
5122
- const timer = setTimeout(task, bootQuietRemainingMs() + Math.max(0, additionalDelayMs));
5123
- timer.unref?.();
5124
- return timer;
5125
- }
5126
4771
 
5127
4772
  // src/features/magic-context/tool-definition-tokens.ts
5128
4773
  import { createHash as createHash5 } from "node:crypto";
@@ -5236,11 +4881,11 @@ function getMeasuredToolDefinitionTokens(providerID, modelID, agentName) {
5236
4881
 
5237
4882
  // src/features/magic-context/tool-owner-backfill.ts
5238
4883
  import { existsSync as existsSync2 } from "node:fs";
5239
- import { join } from "node:path";
4884
+ import { join as join2 } from "node:path";
5240
4885
  var LEASE_DURATION_MS = 5 * 60 * 1000;
5241
4886
  var LEASE_RENEWAL_MS = 60 * 1000;
5242
4887
  function resolveOpencodeDbPath() {
5243
- return join(getDataDir(), "opencode", "opencode.db");
4888
+ return join2(getDataDir(), "opencode", "opencode.db");
5244
4889
  }
5245
4890
  function ensureBackfillStateTable(db) {
5246
4891
  db.exec(`
@@ -5495,30 +5140,40 @@ var persistenceByDatabase = new WeakMap;
5495
5140
  var persistenceErrorByDatabase = new WeakMap;
5496
5141
  var pathByDatabase = new WeakMap;
5497
5142
  var lastSchemaFenceRejection = null;
5143
+ var lastMigrationOnOpenRefusal = null;
5498
5144
  function getSchemaFenceRejection() {
5499
5145
  return lastSchemaFenceRejection;
5500
5146
  }
5501
- var LATEST_SUPPORTED_VERSION = 71;
5147
+ function getMigrationOnOpenRefusal() {
5148
+ return lastMigrationOnOpenRefusal;
5149
+ }
5150
+ var LATEST_SUPPORTED_VERSION = 74;
5502
5151
  var PERMISSIONS_ENFORCEABLE = process.platform !== "win32";
5152
+ var defaultStoragePermissionFs = { chmodSync, mkdirSync };
5153
+ var storagePermissionFs = defaultStoragePermissionFs;
5503
5154
  function ensureSecureStorageDir(dir) {
5504
- mkdirSync(dir, { recursive: true, mode: 448 });
5155
+ if (!shouldEnforcePrivateStoragePermissions()) {
5156
+ storagePermissionFs.mkdirSync(dir, { recursive: true });
5157
+ return;
5158
+ }
5159
+ storagePermissionFs.mkdirSync(dir, { recursive: true, mode: 448 });
5505
5160
  if (!PERMISSIONS_ENFORCEABLE)
5506
5161
  return;
5507
5162
  try {
5508
- chmodSync(dir, 448);
5163
+ storagePermissionFs.chmodSync(dir, 448);
5509
5164
  } catch (error) {
5510
5165
  log(`[magic-context] could not restrict storage dir permissions on ${dir}: ${getErrorMessage(error)}`);
5511
5166
  }
5512
5167
  }
5513
5168
  function restrictDatabaseFilePermissions(dbPath) {
5514
- if (!PERMISSIONS_ENFORCEABLE)
5169
+ if (!PERMISSIONS_ENFORCEABLE || !shouldEnforcePrivateStoragePermissions())
5515
5170
  return;
5516
5171
  for (const suffix of ["", "-wal", "-shm"]) {
5517
5172
  const file = `${dbPath}${suffix}`;
5518
5173
  if (!existsSync3(file))
5519
5174
  continue;
5520
5175
  try {
5521
- chmodSync(file, 384);
5176
+ storagePermissionFs.chmodSync(file, 384);
5522
5177
  } catch (error) {
5523
5178
  log(`[magic-context] could not restrict DB file permissions on ${file}: ${getErrorMessage(error)}`);
5524
5179
  }
@@ -5530,12 +5185,12 @@ function resolveDatabasePath(dbPathOverride) {
5530
5185
  }
5531
5186
  const testDataDir = process.env.MAGIC_CONTEXT_TEST_DATA_DIR;
5532
5187
  if (testDataDir && !process.env.XDG_DATA_HOME) {
5533
- const dbDir2 = join2(testDataDir, "cortexkit", "magic-context");
5534
- return { dbDir: dbDir2, dbPath: join2(dbDir2, "context.db") };
5188
+ const dbDir2 = join3(testDataDir, "cortexkit", "magic-context");
5189
+ return { dbDir: dbDir2, dbPath: join3(dbDir2, "context.db") };
5535
5190
  }
5536
5191
  if (false) {}
5537
5192
  const dbDir = getMagicContextStorageDir();
5538
- return { dbDir, dbPath: join2(dbDir, "context.db") };
5193
+ return { dbDir, dbPath: join3(dbDir, "context.db") };
5539
5194
  }
5540
5195
  function getDatabasePath(db) {
5541
5196
  return pathByDatabase.get(db) ?? null;
@@ -5544,7 +5199,7 @@ function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
5544
5199
  if (existsSync3(targetDbPath))
5545
5200
  return;
5546
5201
  const legacyDir = getLegacyOpenCodeMagicContextStorageDir();
5547
- const legacyDbPath = join2(legacyDir, "context.db");
5202
+ const legacyDbPath = join3(legacyDir, "context.db");
5548
5203
  if (!existsSync3(legacyDbPath))
5549
5204
  return;
5550
5205
  log(`[magic-context] migrating legacy plugin storage: ${legacyDir} -> ${targetDbDir} (legacy left in place as backup)`);
@@ -5561,7 +5216,7 @@ function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
5561
5216
  }
5562
5217
  for (const suffix of ["", "-wal", "-shm"]) {
5563
5218
  const src = `${legacyDbPath}${suffix}`;
5564
- const dst = join2(targetDbDir, `context.db${suffix}`);
5219
+ const dst = join3(targetDbDir, `context.db${suffix}`);
5565
5220
  if (existsSync3(src)) {
5566
5221
  try {
5567
5222
  copyFileSync(src, dst);
@@ -5570,8 +5225,8 @@ function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
5570
5225
  }
5571
5226
  }
5572
5227
  }
5573
- const legacyModelsDir = join2(legacyDir, "models");
5574
- const targetModelsDir = join2(targetDbDir, "models");
5228
+ const legacyModelsDir = join3(legacyDir, "models");
5229
+ const targetModelsDir = join3(targetDbDir, "models");
5575
5230
  if (existsSync3(legacyModelsDir) && !existsSync3(targetModelsDir)) {
5576
5231
  try {
5577
5232
  cpSync(legacyModelsDir, targetModelsDir, { recursive: true });
@@ -5585,9 +5240,12 @@ function getPersistedSchemaVersion(db) {
5585
5240
  if (!hasMigrationsTable) {
5586
5241
  return 0;
5587
5242
  }
5588
- const row = db.prepare("SELECT MAX(version) AS version FROM schema_migrations").get();
5243
+ const row = db.prepare("SELECT COALESCE(MAX(version), 0) AS version FROM schema_migrations WHERE version < ?").get(FORK_MIGRATION_VERSION_FLOOR);
5589
5244
  return row?.version ?? 0;
5590
5245
  }
5246
+ function formatSchemaFenceBootLog(persistedVersion, supportedVersion) {
5247
+ return `[magic-context] upstream migration lane at boot: database=v${persistedVersion}, supported_fence=v${supportedVersion}`;
5248
+ }
5591
5249
  function getRuntimeLatestSupportedVersion(options) {
5592
5250
  if (options?.latestSupportedVersion !== undefined) {
5593
5251
  return options.latestSupportedVersion;
@@ -5604,10 +5262,107 @@ function getRuntimeLatestSupportedVersion(options) {
5604
5262
  function enforceSchemaFence(db, dbPath, latestSupportedVersion) {
5605
5263
  const persistedVersion = getPersistedSchemaVersion(db);
5606
5264
  if (persistedVersion <= latestSupportedVersion) {
5265
+ lastSchemaFenceRejection = null;
5607
5266
  return true;
5608
5267
  }
5609
5268
  lastSchemaFenceRejection = { persistedVersion, supportedVersion: latestSupportedVersion };
5610
- log(`[magic-context] storage fatal: refusing to open ${dbPath}; database schema v${persistedVersion} is newer than this binary supports (max v${latestSupportedVersion}). A pinned or stale plugin is likely sharing this database with a newer instance; update or unpin Magic Context with 'npx @cortexkit/magic-context@latest doctor --force', then restart.`);
5269
+ log(`[magic-context] storage fatal: refusing to open ${dbPath}; upstream migration lane v${persistedVersion} is newer than this binary supports (max v${latestSupportedVersion}). A pinned or stale plugin is likely sharing this database with a newer instance; update or unpin Magic Context with 'npx @cortexkit/magic-context@latest doctor --force', then restart.`);
5270
+ return false;
5271
+ }
5272
+ function unreadableDiscovery(path2) {
5273
+ return {
5274
+ state: "unreadable",
5275
+ serverPids: [],
5276
+ staleFiles: [],
5277
+ unreadableFile: path2
5278
+ };
5279
+ }
5280
+ function inspectRpcServerDiscovery(storageDir) {
5281
+ const rpcRoot = join3(storageDir, "rpc");
5282
+ let projectEntries;
5283
+ try {
5284
+ projectEntries = readdirSync(rpcRoot, { withFileTypes: true });
5285
+ } catch (error) {
5286
+ if (error.code === "ENOENT") {
5287
+ return { state: "absent", serverPids: [], staleFiles: [] };
5288
+ }
5289
+ return unreadableDiscovery(rpcRoot);
5290
+ }
5291
+ const portFiles = [];
5292
+ for (const projectEntry of projectEntries) {
5293
+ if (!projectEntry.isDirectory())
5294
+ continue;
5295
+ const projectDir = join3(rpcRoot, projectEntry.name);
5296
+ let entries;
5297
+ try {
5298
+ entries = readdirSync(projectDir);
5299
+ } catch {
5300
+ return unreadableDiscovery(projectDir);
5301
+ }
5302
+ for (const entry of entries) {
5303
+ if (entry === "port" || entry.startsWith("port-") && entry.endsWith(".json")) {
5304
+ portFiles.push(join3(projectDir, entry));
5305
+ }
5306
+ }
5307
+ }
5308
+ if (portFiles.length === 0) {
5309
+ return { state: "absent", serverPids: [], staleFiles: [] };
5310
+ }
5311
+ const pids = new Set;
5312
+ const staleFiles = [];
5313
+ for (const portFile of portFiles) {
5314
+ let raw;
5315
+ try {
5316
+ raw = readFileSync2(portFile, "utf8");
5317
+ } catch {
5318
+ return unreadableDiscovery(portFile);
5319
+ }
5320
+ const filename = basename(portFile);
5321
+ const pidFromName = /^port-(\d+)/.exec(filename)?.[1];
5322
+ const record = parseRpcPortFile(raw, pidFromName ? Number(pidFromName) : 0);
5323
+ if (!record || !Number.isInteger(record.pid) || record.pid <= 0) {
5324
+ return unreadableDiscovery(portFile);
5325
+ }
5326
+ if (isPidAlive(record.pid) && isPidIdentityPlausible(record))
5327
+ pids.add(record.pid);
5328
+ else
5329
+ staleFiles.push(portFile);
5330
+ }
5331
+ for (const staleFile of staleFiles) {
5332
+ try {
5333
+ unlinkSync(staleFile);
5334
+ } catch {
5335
+ return unreadableDiscovery(staleFile);
5336
+ }
5337
+ }
5338
+ const serverPids = [...pids].sort((a, b) => a - b);
5339
+ if (serverPids.length > 0) {
5340
+ return { state: "live", serverPids, staleFiles };
5341
+ }
5342
+ return { state: "stale", serverPids: [], staleFiles };
5343
+ }
5344
+ function enforceMigrationOnOpenGuard(db, dbPath, dbDir, latestSupportedVersion) {
5345
+ const persistedVersion = getPersistedSchemaVersion(db);
5346
+ if (persistedVersion >= latestSupportedVersion) {
5347
+ lastMigrationOnOpenRefusal = null;
5348
+ return true;
5349
+ }
5350
+ const discovery = inspectRpcServerDiscovery(dbDir);
5351
+ if (discovery.state === "absent" || discovery.state === "stale") {
5352
+ lastMigrationOnOpenRefusal = null;
5353
+ return true;
5354
+ }
5355
+ lastMigrationOnOpenRefusal = {
5356
+ persistedVersion,
5357
+ supportedVersion: latestSupportedVersion,
5358
+ serverPids: discovery.serverPids,
5359
+ ...discovery.unreadableFile ? { unreadableFile: discovery.unreadableFile } : {}
5360
+ };
5361
+ if (discovery.state === "unreadable") {
5362
+ log(`[magic-context] storage fatal: refusing to migrate ${dbPath} from upstream migration v${persistedVersion} to v${latestSupportedVersion} because RPC discovery file ${discovery.unreadableFile ?? "<unknown>"} is unreadable or invalid, so the absence of a live OpenCode server cannot be proven. Restart OpenCode, remove or repair the named discovery file, then retry this process.`);
5363
+ } else {
5364
+ log(`[magic-context] storage fatal: refusing to migrate ${dbPath} from upstream migration v${persistedVersion} to v${latestSupportedVersion} while live OpenCode server PID(s) ${discovery.serverPids.join(", ")} may still use the old plugin build. Restart OpenCode, then retry this process.`);
5365
+ }
5611
5366
  return false;
5612
5367
  }
5613
5368
  var sqlitePragmaConfig = {
@@ -5654,6 +5409,9 @@ function finishDatabaseOpen(db, dbPath, explicitDbPath, latestSupportedVersion)
5654
5409
  pathByDatabase.set(db, dbPath);
5655
5410
  persistenceByDatabase.set(db, true);
5656
5411
  persistenceErrorByDatabase.delete(db);
5412
+ if (!explicitDbPath) {
5413
+ log(formatSchemaFenceBootLog(getPersistedSchemaVersion(db), latestSupportedVersion));
5414
+ }
5657
5415
  return db;
5658
5416
  }
5659
5417
  function initializeDatabase(db) {
@@ -6254,12 +6012,14 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
6254
6012
  note_nudge_anchors TEXT NOT NULL DEFAULT '[]',
6255
6013
  auto_search_hint_decisions TEXT NOT NULL DEFAULT '[]',
6256
6014
  last_todo_state TEXT DEFAULT '',
6015
+ todo_permission_denied INTEGER NOT NULL DEFAULT 2,
6257
6016
  todo_synthetic_call_id TEXT DEFAULT '',
6258
6017
  todo_synthetic_anchor_message_id TEXT DEFAULT '',
6259
6018
  todo_synthetic_state_json TEXT DEFAULT '',
6260
6019
  is_subagent INTEGER DEFAULT 0,
6261
6020
  last_context_percentage REAL DEFAULT 0,
6262
6021
  last_input_tokens INTEGER DEFAULT 0,
6022
+ detected_context_limit_provenance TEXT NOT NULL DEFAULT 'unknown',
6263
6023
  observed_safe_input_tokens INTEGER NOT NULL DEFAULT 0,
6264
6024
  cache_alert_sent INTEGER NOT NULL DEFAULT 0,
6265
6025
  times_execute_threshold_reached INTEGER DEFAULT 0,
@@ -6314,6 +6074,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
6314
6074
  emergency_drain_active INTEGER NOT NULL DEFAULT 0,
6315
6075
  historian_drain_failure_at INTEGER NOT NULL DEFAULT 0,
6316
6076
  wrapup_in_progress_state TEXT,
6077
+ compaction_mode_record TEXT,
6317
6078
  cached_m0_materialized_at INTEGER,
6318
6079
  cached_m0_session_facts_version INTEGER,
6319
6080
  cached_m0_upgrade_state TEXT,
@@ -6513,6 +6274,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
6513
6274
  ensureColumn(db, "session_meta", "note_nudge_anchors", "TEXT NOT NULL DEFAULT '[]'");
6514
6275
  ensureColumn(db, "session_meta", "auto_search_hint_decisions", "TEXT NOT NULL DEFAULT '[]'");
6515
6276
  ensureColumn(db, "session_meta", "last_todo_state", "TEXT DEFAULT ''");
6277
+ ensureColumn(db, "session_meta", "todo_permission_denied", "INTEGER NOT NULL DEFAULT 2");
6516
6278
  ensureColumn(db, "session_meta", "todo_synthetic_call_id", "TEXT DEFAULT ''");
6517
6279
  ensureColumn(db, "session_meta", "todo_synthetic_anchor_message_id", "TEXT DEFAULT ''");
6518
6280
  ensureColumn(db, "session_meta", "todo_synthetic_state_json", "TEXT DEFAULT ''");
@@ -6569,6 +6331,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
6569
6331
  ensureColumn(db, "session_meta", "recomp_partial_range_end", "INTEGER DEFAULT 0");
6570
6332
  ensureColumn(db, "session_meta", "detected_context_limit", "INTEGER DEFAULT 0");
6571
6333
  ensureColumn(db, "session_meta", "detected_context_limit_model_key", "TEXT");
6334
+ ensureColumn(db, "session_meta", "detected_context_limit_provenance", "TEXT NOT NULL DEFAULT 'unknown'");
6572
6335
  ensureColumn(db, "session_meta", "needs_emergency_recovery", "INTEGER DEFAULT 0");
6573
6336
  ensureColumn(db, "session_meta", "emergency_recovery_origin", "TEXT DEFAULT ''");
6574
6337
  ensureColumn(db, "session_meta", "pending_compaction_marker_state", "TEXT");
@@ -6619,6 +6382,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
6619
6382
  ensureColumn(db, "session_meta", "emergency_drain_active", "INTEGER NOT NULL DEFAULT 0");
6620
6383
  ensureColumn(db, "session_meta", "historian_drain_failure_at", "INTEGER NOT NULL DEFAULT 0");
6621
6384
  ensureColumn(db, "session_meta", "wrapup_in_progress_state", "TEXT");
6385
+ ensureColumn(db, "session_meta", "compaction_mode_record", "TEXT");
6622
6386
  ensureColumn(db, "session_meta", "cached_m0_materialized_at", "INTEGER");
6623
6387
  ensureColumn(db, "session_meta", "cached_m0_session_facts_version", "INTEGER");
6624
6388
  ensureColumn(db, "session_meta", "cached_m0_upgrade_state", "TEXT");
@@ -6758,6 +6522,8 @@ function openDatabase(dbPathOrOptions) {
6758
6522
  const explicitDbPath = options?.dbPath !== undefined;
6759
6523
  const { dbDir, dbPath } = resolveDatabasePath(options?.dbPath);
6760
6524
  const latestSupportedVersion = getRuntimeLatestSupportedVersion(options);
6525
+ lastSchemaFenceRejection = null;
6526
+ lastMigrationOnOpenRefusal = null;
6761
6527
  const existing = databases.get(dbPath);
6762
6528
  if (existing) {
6763
6529
  if (!enforceSchemaFence(existing, dbPath, latestSupportedVersion)) {
@@ -6779,6 +6545,10 @@ function openDatabase(dbPathOrOptions) {
6779
6545
  closeQuietly(db);
6780
6546
  return null;
6781
6547
  }
6548
+ if (!enforceMigrationOnOpenGuard(db, dbPath, dbDir, latestSupportedVersion)) {
6549
+ closeQuietly(db);
6550
+ return null;
6551
+ }
6782
6552
  initializeDatabase(db);
6783
6553
  runMigrations(db);
6784
6554
  ensureContextStoreUuid(db);
@@ -6794,6 +6564,8 @@ async function openDatabaseAsync(dbPathOrOptions) {
6794
6564
  const explicitDbPath = options?.dbPath !== undefined;
6795
6565
  const { dbDir, dbPath } = resolveDatabasePath(options?.dbPath);
6796
6566
  const latestSupportedVersion = getRuntimeLatestSupportedVersion(options);
6567
+ lastSchemaFenceRejection = null;
6568
+ lastMigrationOnOpenRefusal = null;
6797
6569
  const existing = databases.get(dbPath);
6798
6570
  if (existing) {
6799
6571
  if (!enforceSchemaFence(existing, dbPath, latestSupportedVersion))
@@ -6817,6 +6589,10 @@ async function openDatabaseAsync(dbPathOrOptions) {
6817
6589
  closeQuietly(db);
6818
6590
  return null;
6819
6591
  }
6592
+ if (!enforceMigrationOnOpenGuard(db, dbPath, dbDir, latestSupportedVersion)) {
6593
+ closeQuietly(db);
6594
+ return null;
6595
+ }
6820
6596
  initializeDatabase(db);
6821
6597
  await runMigrationsWithRetry(db);
6822
6598
  ensureContextStoreUuid(db);
@@ -6847,11 +6623,188 @@ function getDatabasePersistenceError(db) {
6847
6623
  return null;
6848
6624
  return persistenceErrorByDatabase.get(db) ?? null;
6849
6625
  }
6850
- // src/features/magic-context/storage-embedding-measurements.ts
6626
+
6627
+ // src/features/magic-context/schema-fence-probe.ts
6628
+ var STALE_CHILD_SPAWN_FAILURE = "stale_schema_fence";
6629
+ var STALE_CHILD_SPAWN_LATCH_THRESHOLD = 2;
6630
+ var state = {
6631
+ consecutiveFailures: 0,
6632
+ totalFailures: 0,
6633
+ latched: false,
6634
+ noticeEmitted: false,
6635
+ failure: null
6636
+ };
6637
+ function recordStaleFence(persistedVersion, supportedVersion) {
6638
+ state.consecutiveFailures += 1;
6639
+ state.totalFailures += 1;
6640
+ const latched = state.consecutiveFailures >= STALE_CHILD_SPAWN_LATCH_THRESHOLD;
6641
+ state.latched ||= latched;
6642
+ const failure = {
6643
+ failureClass: STALE_CHILD_SPAWN_FAILURE,
6644
+ persistedVersion,
6645
+ supportedVersion,
6646
+ consecutiveFailures: state.consecutiveFailures,
6647
+ totalFailures: state.totalFailures,
6648
+ latched: state.latched
6649
+ };
6650
+ state.failure = failure;
6651
+ const shouldSurface = state.latched && !state.noticeEmitted;
6652
+ if (shouldSurface)
6653
+ state.noticeEmitted = true;
6654
+ return { allowSpawn: false, failure, shouldSurface };
6655
+ }
6656
+ function probeChildSpawnFence(db) {
6657
+ if (!db) {
6658
+ const knownRejection = getSchemaFenceRejection();
6659
+ if (knownRejection) {
6660
+ return recordStaleFence(knownRejection.persistedVersion, knownRejection.supportedVersion);
6661
+ }
6662
+ return { allowSpawn: true };
6663
+ }
6664
+ try {
6665
+ const persistedVersion = getPersistedSchemaVersion(db);
6666
+ if (persistedVersion > LATEST_SUPPORTED_VERSION) {
6667
+ return recordStaleFence(persistedVersion, LATEST_SUPPORTED_VERSION);
6668
+ }
6669
+ } catch {
6670
+ return { allowSpawn: true };
6671
+ }
6672
+ state.consecutiveFailures = 0;
6673
+ state.latched = false;
6674
+ state.noticeEmitted = false;
6675
+ return { allowSpawn: true };
6676
+ }
6677
+ // src/features/magic-context/project-docs-hash.ts
6851
6678
  import { createHash as createHash6 } from "node:crypto";
6679
+ import { lstatSync, readFileSync as readFileSync3, statSync as statSync2 } from "node:fs";
6680
+ import path2 from "node:path";
6681
+ var PROJECT_DOC_FILES = ["ARCHITECTURE.md", "STRUCTURE.md"];
6682
+ var PROJECT_DOCS_DELIMITER = `
6683
+
6684
+ ---
6685
+
6686
+ `;
6687
+ var MAX_PROJECT_DOC_BYTES = 256 * 1024;
6688
+ var docsCache = new Map;
6689
+ function canonicalizeDocContent(raw) {
6690
+ return raw.replace(/^\uFEFF/, "").replace(/\r\n/g, `
6691
+ `).split(`
6692
+ `).map((line) => line.replace(/[ \t]+$/, "")).join(`
6693
+ `).replace(/\n+$/, "");
6694
+ }
6695
+ function fingerprintFile(filePath) {
6696
+ try {
6697
+ const stat = lstatSync(filePath);
6698
+ const isReadableDoc = stat.isFile() && stat.size <= MAX_PROJECT_DOC_BYTES;
6699
+ return {
6700
+ exists: isReadableDoc,
6701
+ mtimeMs: stat.mtimeMs,
6702
+ size: stat.size
6703
+ };
6704
+ } catch {
6705
+ return { exists: false, mtimeMs: 0, size: 0 };
6706
+ }
6707
+ }
6708
+ function readDirectoryMtimeMs(projectDirectory) {
6709
+ try {
6710
+ return statSync2(projectDirectory).mtimeMs;
6711
+ } catch {
6712
+ return 0;
6713
+ }
6714
+ }
6715
+ function fingerprintsEqual(a, b) {
6716
+ return a?.exists === b.exists && a.mtimeMs === b.mtimeMs && a.size === b.size;
6717
+ }
6718
+ function cacheFilesEqual(cachedFiles, currentFiles) {
6719
+ for (const [filePath, current] of currentFiles) {
6720
+ if (!fingerprintsEqual(cachedFiles.get(filePath), current)) {
6721
+ return false;
6722
+ }
6723
+ }
6724
+ return true;
6725
+ }
6726
+ function readCurrentFingerprints(projectDirectory) {
6727
+ const files = new Map;
6728
+ for (const filename of PROJECT_DOC_FILES) {
6729
+ const filePath = path2.join(projectDirectory, filename);
6730
+ files.set(filePath, fingerprintFile(filePath));
6731
+ }
6732
+ return { directoryMtimeMs: readDirectoryMtimeMs(projectDirectory), files };
6733
+ }
6734
+ function readCanonicalPieces(projectDirectory, files) {
6735
+ const hashPieces = [];
6736
+ const renderedSections = [];
6737
+ for (const filename of PROJECT_DOC_FILES) {
6738
+ const filePath = path2.join(projectDirectory, filename);
6739
+ const fingerprint = files.get(filePath);
6740
+ if (!fingerprint?.exists) {
6741
+ continue;
6742
+ }
6743
+ let safeToRead = false;
6744
+ try {
6745
+ const st = lstatSync(filePath);
6746
+ safeToRead = st.isFile() && st.size <= MAX_PROJECT_DOC_BYTES;
6747
+ } catch {
6748
+ safeToRead = false;
6749
+ }
6750
+ if (!safeToRead) {
6751
+ continue;
6752
+ }
6753
+ const canonicalContent = canonicalizeDocContent(readFileSync3(filePath, "utf8"));
6754
+ hashPieces.push(`file:${filename}
6755
+ ${canonicalContent}`);
6756
+ renderedSections.push(`<file name="${escapeXmlAttr(filename)}">
6757
+ ${escapeXmlContent(canonicalContent)}
6758
+ </file>`);
6759
+ }
6760
+ return { hashPieces, renderedSections };
6761
+ }
6762
+ function buildRenderedBlock(renderedSections) {
6763
+ if (renderedSections.length === 0) {
6764
+ return "";
6765
+ }
6766
+ return `<project-docs>
6767
+ ${renderedSections.join(`
6768
+
6769
+ `)}
6770
+ </project-docs>`;
6771
+ }
6772
+ function hashCanonicalPieces(hashPieces) {
6773
+ if (hashPieces.length === 0) {
6774
+ return "";
6775
+ }
6776
+ return createHash6("sha256").update(hashPieces.join(PROJECT_DOCS_DELIMITER), "utf8").digest("hex");
6777
+ }
6778
+ function readProjectDocsCanonical(projectDirectory) {
6779
+ const canonicalDirectory = path2.resolve(projectDirectory);
6780
+ const current = readCurrentFingerprints(canonicalDirectory);
6781
+ const cached = docsCache.get(canonicalDirectory);
6782
+ if (cached && cacheFilesEqual(cached.files, current.files)) {
6783
+ cached.directoryMtimeMs = current.directoryMtimeMs;
6784
+ return {
6785
+ renderedBlock: cached.cachedRendered,
6786
+ canonicalHash: cached.cachedHash
6787
+ };
6788
+ }
6789
+ const { hashPieces, renderedSections } = readCanonicalPieces(canonicalDirectory, current.files);
6790
+ const canonicalHash = hashCanonicalPieces(hashPieces);
6791
+ const renderedBlock = buildRenderedBlock(renderedSections);
6792
+ docsCache.set(canonicalDirectory, {
6793
+ directoryMtimeMs: current.directoryMtimeMs,
6794
+ files: current.files,
6795
+ cachedHash: canonicalHash,
6796
+ cachedRendered: renderedBlock
6797
+ });
6798
+ return { renderedBlock, canonicalHash };
6799
+ }
6800
+ function computeProjectDocsHash(projectDirectory) {
6801
+ return readProjectDocsCanonical(projectDirectory).canonicalHash;
6802
+ }
6803
+ // src/features/magic-context/storage-embedding-measurements.ts
6804
+ import { createHash as createHash7 } from "node:crypto";
6852
6805
  function normalizedQueryHash(query) {
6853
6806
  const normalized = query.trim().replace(/\s+/g, " ").toLowerCase();
6854
- return createHash6("sha256").update(normalized).digest("hex");
6807
+ return createHash7("sha256").update(normalized).digest("hex");
6855
6808
  }
6856
6809
  var MEASUREMENT_CORPUS_SESSION_ROW_CAP = 2000;
6857
6810
  function recordEmbeddingMeasurement(db, input) {
@@ -7067,7 +7020,7 @@ function getMemoryMutationsForRenderByIdentitySet(db, projectPaths, afterId, ren
7067
7020
  }
7068
7021
  visited.add(terminal);
7069
7022
  const next = byTarget.get(terminal);
7070
- if (!next || next.mutationType !== "superseded")
7023
+ if (next?.mutationType !== "superseded")
7071
7024
  break;
7072
7025
  if (depth >= MAX_MEMORY_REPLACEMENT_DEPTH - 1) {
7073
7026
  terminal = null;
@@ -7101,6 +7054,24 @@ function getMaxMemoryMutationIdForProjects(db, projectPaths) {
7101
7054
  WHERE project_path IN (${placeholders2(identities)})`).get(...identities);
7102
7055
  return row?.max_id ?? null;
7103
7056
  }
7057
+ // src/shared/context-limit-provenance.ts
7058
+ function normalizeContextLimitProvenance(value) {
7059
+ if (value === "prompt_only" || value === "combined")
7060
+ return value;
7061
+ return "unknown";
7062
+ }
7063
+
7064
+ // src/shared/escalation-bands.ts
7065
+ var MAX_EXECUTE_THRESHOLD = 90;
7066
+ var ABSOLUTE_EMERGENCY_PERCENTAGE = 95;
7067
+ function escalationBands(effectiveThresholdPercentage) {
7068
+ const threshold = Number.isFinite(effectiveThresholdPercentage) ? Math.min(effectiveThresholdPercentage, MAX_EXECUTE_THRESHOLD) : 65;
7069
+ return {
7070
+ forceMaterializationPercentage: Math.max(85, threshold + 2),
7071
+ emergencyPercentage: ABSOLUTE_EMERGENCY_PERCENTAGE
7072
+ };
7073
+ }
7074
+
7104
7075
  // src/features/magic-context/storage-meta-persisted.ts
7105
7076
  var emergencyRecoveryArmedSessions = new Set;
7106
7077
  var providerOverflowReconfirmedSessions = new Set;
@@ -7322,11 +7293,11 @@ function readRawWrapupState(db, sessionId) {
7322
7293
  return parseWrapupState(row?.wrapup_in_progress_state);
7323
7294
  }
7324
7295
  function getWrapupInProgressState(db, sessionId, now = Date.now()) {
7325
- const state = readRawWrapupState(db, sessionId);
7326
- if (!state)
7296
+ const state2 = readRawWrapupState(db, sessionId);
7297
+ if (!state2)
7327
7298
  return null;
7328
- if (state.expiresAt > now)
7329
- return state;
7299
+ if (state2.expiresAt > now)
7300
+ return state2;
7330
7301
  try {
7331
7302
  db.exec("BEGIN IMMEDIATE");
7332
7303
  } catch {
@@ -7352,10 +7323,10 @@ function getWrapupInProgressState(db, sessionId, now = Date.now()) {
7352
7323
  function isWrapupInProgress(db, sessionId, now = Date.now()) {
7353
7324
  return getWrapupInProgressState(db, sessionId, now) !== null;
7354
7325
  }
7355
- function acquireWrapupInProgress(db, sessionId, state, now = Date.now()) {
7326
+ function acquireWrapupInProgress(db, sessionId, state2, now = Date.now()) {
7356
7327
  const acquiredAt = now;
7357
7328
  const next = {
7358
- ...state,
7329
+ ...state2,
7359
7330
  acquiredAt,
7360
7331
  expiresAt: acquiredAt + WRAPUP_IN_PROGRESS_TTL_MS,
7361
7332
  updatedAt: acquiredAt
@@ -7365,7 +7336,7 @@ function acquireWrapupInProgress(db, sessionId, state, now = Date.now()) {
7365
7336
  try {
7366
7337
  ensureSessionMetaRow(db, sessionId);
7367
7338
  const current = readRawWrapupState(db, sessionId);
7368
- if (current && current.expiresAt > now && current.holderId !== state.holderId) {
7339
+ if (current && current.expiresAt > now && current.holderId !== state2.holderId) {
7369
7340
  db.exec("COMMIT");
7370
7341
  finished = true;
7371
7342
  return { ok: false, state: current };
@@ -7429,6 +7400,45 @@ function releaseWrapupInProgress(db, sessionId, holderId) {
7429
7400
  }
7430
7401
  }
7431
7402
  }
7403
+ var COMPACTION_MODE_RECORD_VALUES = new Set([
7404
+ "on",
7405
+ "off",
7406
+ "on_notice_pending",
7407
+ "off_notice_pending",
7408
+ "off_cleanup_pending"
7409
+ ]);
7410
+ function normalizeCompactionModeRecord(value) {
7411
+ if (value === null || value === undefined)
7412
+ return null;
7413
+ if (typeof value === "string" && COMPACTION_MODE_RECORD_VALUES.has(value)) {
7414
+ return value;
7415
+ }
7416
+ return null;
7417
+ }
7418
+ function resolveCompactionModeRecord(record) {
7419
+ switch (record) {
7420
+ case "on":
7421
+ case "on_notice_pending":
7422
+ return "on";
7423
+ case "off":
7424
+ case "off_notice_pending":
7425
+ case "off_cleanup_pending":
7426
+ return "off";
7427
+ default:
7428
+ return null;
7429
+ }
7430
+ }
7431
+ function getCompactionModeRecord(db, sessionId) {
7432
+ const row = db.prepare("SELECT compaction_mode_record FROM session_meta WHERE session_id = ?").get(sessionId);
7433
+ return normalizeCompactionModeRecord(row?.compaction_mode_record);
7434
+ }
7435
+ function setCompactionModeRecord(db, sessionId, value) {
7436
+ if (value !== null && !COMPACTION_MODE_RECORD_VALUES.has(value)) {
7437
+ throw new Error(`Invalid compaction_mode_record value: ${String(value)} (expected a supported compaction mode record or null)`);
7438
+ }
7439
+ ensureSessionMetaRow(db, sessionId);
7440
+ db.prepare("UPDATE session_meta SET compaction_mode_record = ? WHERE session_id = ?").run(value, sessionId);
7441
+ }
7432
7442
  function protectedTailWindowBudget(usagePercentage, usable, perRunCap) {
7433
7443
  if (usagePercentage >= 95)
7434
7444
  return Math.min(1e6, Math.max(4 * perRunCap, Math.round(0.5 * usable)));
@@ -7436,7 +7446,6 @@ function protectedTailWindowBudget(usagePercentage, usable, perRunCap) {
7436
7446
  return Math.min(750000, Math.max(3 * perRunCap, Math.round(0.35 * usable)));
7437
7447
  return Math.min(500000, Math.max(perRunCap, Math.round(0.2 * usable)));
7438
7448
  }
7439
- var EMERGENCY_DRAIN_ENTER_PERCENTAGE = 95;
7440
7449
  var EMERGENCY_DRAIN_EXIT_MARGIN = 10;
7441
7450
  var EMERGENCY_DRAIN_FALLBACK_EXIT_PERCENTAGE = 55;
7442
7451
  var EMERGENCY_DRAIN_FAILURE_BACKOFF_MS = 60000;
@@ -7471,7 +7480,8 @@ function reserveProtectedTailDrainTokens(args) {
7471
7480
  }
7472
7481
  const exitThreshold = emergencyDrainExitThreshold(args.executeThresholdPercentage);
7473
7482
  let latchActiveSince = meta.emergencyDrainActive;
7474
- if (args.usagePercentage >= EMERGENCY_DRAIN_ENTER_PERCENTAGE) {
7483
+ const { forceMaterializationPercentage } = escalationBands(args.executeThresholdPercentage);
7484
+ if (args.usagePercentage >= forceMaterializationPercentage) {
7475
7485
  if (latchActiveSince <= 0)
7476
7486
  latchActiveSince = now;
7477
7487
  } else if (latchActiveSince > 0) {
@@ -7623,13 +7633,20 @@ function getChannel2NudgeState(db, sessionId) {
7623
7633
  function getChannel2NudgeClaim(db, sessionId) {
7624
7634
  const result = db.prepare("SELECT channel2_nudge_state, channel2_nudge_claimed_at, channel2_nudge_claim_token FROM session_meta WHERE session_id = ?").get(sessionId);
7625
7635
  const rawState = typeof result?.channel2_nudge_state === "string" ? result.channel2_nudge_state : "";
7626
- const state = rawState === "pending" || rawState === "claimed" || rawState === "delivered" ? rawState : "";
7636
+ const state2 = rawState === "pending" || rawState === "claimed" || rawState === "delivered" ? rawState : "";
7627
7637
  return {
7628
- state,
7638
+ state: state2,
7629
7639
  claimedAt: typeof result?.channel2_nudge_claimed_at === "number" ? result.channel2_nudge_claimed_at : 0,
7630
7640
  claimToken: typeof result?.channel2_nudge_claim_token === "string" ? result.channel2_nudge_claim_token : ""
7631
7641
  };
7632
7642
  }
7643
+ function setChannel2NudgeState(db, sessionId, state2) {
7644
+ db.transaction(() => {
7645
+ ensureSessionMetaRow(db, sessionId);
7646
+ const claimedAt = state2 === "claimed" ? Date.now() : 0;
7647
+ db.prepare("UPDATE session_meta SET channel2_nudge_state = ?, channel2_nudge_claimed_at = ?, channel2_nudge_claim_token = '' WHERE session_id = ?").run(state2, claimedAt, sessionId);
7648
+ })();
7649
+ }
7633
7650
  function casChannel2NudgeState(db, sessionId, from, to) {
7634
7651
  let changed = false;
7635
7652
  db.transaction(() => {
@@ -7809,6 +7826,18 @@ function removeAutoSearchHintDecisionByMessageId(db, sessionId, messageId) {
7809
7826
  }, { ensureRow: false });
7810
7827
  return ok && removed;
7811
7828
  }
7829
+ function getPersistedTodoPermissionDenied(db, sessionId) {
7830
+ const row = db.prepare("SELECT todo_permission_denied FROM session_meta WHERE session_id = ?").get(sessionId);
7831
+ if (row?.todo_permission_denied === 1)
7832
+ return true;
7833
+ if (row?.todo_permission_denied === 0)
7834
+ return false;
7835
+ return null;
7836
+ }
7837
+ function setPersistedTodoPermissionDenied(db, sessionId, denied) {
7838
+ ensureSessionMetaRow(db, sessionId);
7839
+ db.prepare("UPDATE session_meta SET todo_permission_denied = ? WHERE session_id = ?").run(denied ? 1 : 0, sessionId);
7840
+ }
7812
7841
  function getPersistedTodoSyntheticAnchor(db, sessionId) {
7813
7842
  const result = db.prepare("SELECT todo_synthetic_call_id, todo_synthetic_anchor_message_id, todo_synthetic_state_json FROM session_meta WHERE session_id = ?").get(sessionId);
7814
7843
  if (!isPersistedTodoSyntheticAnchorRow(result)) {
@@ -7885,17 +7914,19 @@ function normalizeEmergencyRecoveryOrigin(value) {
7885
7914
  return value === "provider_overflow" || value === "proactive_model_shrink" ? value : null;
7886
7915
  }
7887
7916
  function getOverflowState(db, sessionId, modelKey) {
7888
- const result = db.prepare("SELECT detected_context_limit, detected_context_limit_model_key, needs_emergency_recovery, emergency_recovery_origin FROM session_meta WHERE session_id = ?").get(sessionId);
7917
+ const result = db.prepare("SELECT detected_context_limit, detected_context_limit_model_key, detected_context_limit_provenance, needs_emergency_recovery, emergency_recovery_origin FROM session_meta WHERE session_id = ?").get(sessionId);
7889
7918
  if (!result) {
7890
7919
  return {
7891
7920
  detectedContextLimit: 0,
7892
7921
  detectedContextLimitModelKey: null,
7922
+ detectedContextLimitProvenance: "unknown",
7893
7923
  needsEmergencyRecovery: false,
7894
7924
  emergencyRecoveryOrigin: null
7895
7925
  };
7896
7926
  }
7897
7927
  const storedModelKey = normalizeDetectedLimitModelKey(result.detected_context_limit_model_key);
7898
7928
  const requestedModelKey = normalizeDetectedLimitModelKey(modelKey);
7929
+ const provenance = normalizeContextLimitProvenance(result.detected_context_limit_provenance);
7899
7930
  const limit = typeof result.detected_context_limit === "number" && result.detected_context_limit > 0 ? result.detected_context_limit : 0;
7900
7931
  const modelMatches = limit > 0 && requestedModelKey && storedModelKey ? requestedModelKey === storedModelKey : true;
7901
7932
  const needs = typeof result.needs_emergency_recovery === "number" && result.needs_emergency_recovery > 0;
@@ -7904,11 +7935,12 @@ function getOverflowState(db, sessionId, modelKey) {
7904
7935
  return {
7905
7936
  detectedContextLimit: modelMatches ? limit : 0,
7906
7937
  detectedContextLimitModelKey: storedModelKey,
7938
+ detectedContextLimitProvenance: provenance,
7907
7939
  needsEmergencyRecovery: needs,
7908
7940
  emergencyRecoveryOrigin: recoveryOrigin
7909
7941
  };
7910
7942
  }
7911
- function recordOverflowDetected(db, sessionId, reportedLimit, modelKey, origin = "provider_overflow") {
7943
+ function recordOverflowDetected(db, sessionId, reportedLimit, modelKey, origin = "provider_overflow", provenance = "unknown") {
7912
7944
  emergencyRecoveryArmedSessions.add(sessionId);
7913
7945
  db.transaction(() => {
7914
7946
  ensureSessionMetaRow(db, sessionId);
@@ -7917,18 +7949,18 @@ function recordOverflowDetected(db, sessionId, reportedLimit, modelKey, origin =
7917
7949
  providerOverflowReconfirmedSessions.add(sessionId);
7918
7950
  }
7919
7951
  if (typeof reportedLimit === "number" && reportedLimit > 0) {
7920
- db.prepare("UPDATE session_meta SET detected_context_limit = ?, detected_context_limit_model_key = ?, needs_emergency_recovery = 1, emergency_recovery_origin = ?, observed_safe_input_tokens = 0, cache_alert_sent = 0 WHERE session_id = ?").run(reportedLimit, normalizeDetectedLimitModelKey(modelKey), origin, sessionId);
7952
+ db.prepare("UPDATE session_meta SET detected_context_limit = ?, detected_context_limit_model_key = ?, detected_context_limit_provenance = ?, needs_emergency_recovery = 1, emergency_recovery_origin = ?, observed_safe_input_tokens = 0, cache_alert_sent = 0 WHERE session_id = ?").run(reportedLimit, normalizeDetectedLimitModelKey(modelKey), normalizeContextLimitProvenance(provenance), origin, sessionId);
7921
7953
  } else {
7922
7954
  db.prepare("UPDATE session_meta SET needs_emergency_recovery = 1, emergency_recovery_origin = ?, observed_safe_input_tokens = 0, cache_alert_sent = 0 WHERE session_id = ?").run(origin, sessionId);
7923
7955
  }
7924
7956
  })();
7925
7957
  }
7926
- function recordDetectedContextLimit(db, sessionId, reportedLimit, modelKey) {
7958
+ function recordDetectedContextLimit(db, sessionId, reportedLimit, modelKey, provenance = "unknown") {
7927
7959
  if (!(reportedLimit > 0))
7928
7960
  return;
7929
7961
  db.transaction(() => {
7930
7962
  ensureSessionMetaRow(db, sessionId);
7931
- db.prepare("UPDATE session_meta SET detected_context_limit = ?, detected_context_limit_model_key = ?, observed_safe_input_tokens = 0, cache_alert_sent = 0 WHERE session_id = ?").run(reportedLimit, normalizeDetectedLimitModelKey(modelKey), sessionId);
7963
+ db.prepare("UPDATE session_meta SET detected_context_limit = ?, detected_context_limit_model_key = ?, detected_context_limit_provenance = ?, observed_safe_input_tokens = 0, cache_alert_sent = 0 WHERE session_id = ?").run(reportedLimit, normalizeDetectedLimitModelKey(modelKey), normalizeContextLimitProvenance(provenance), sessionId);
7932
7964
  })();
7933
7965
  }
7934
7966
  function clearEmergencyRecovery(db, sessionId) {
@@ -7946,7 +7978,7 @@ function clearEmergencyRecovery(db, sessionId) {
7946
7978
  function clearDetectedContextLimit(db, sessionId) {
7947
7979
  db.transaction(() => {
7948
7980
  ensureSessionMetaRow(db, sessionId);
7949
- db.prepare("UPDATE session_meta SET detected_context_limit = 0, detected_context_limit_model_key = NULL WHERE session_id = ?").run(sessionId);
7981
+ db.prepare("UPDATE session_meta SET detected_context_limit = 0, detected_context_limit_model_key = NULL, detected_context_limit_provenance = 'unknown' WHERE session_id = ?").run(sessionId);
7950
7982
  })();
7951
7983
  }
7952
7984
  function getPersistedCompactionMarkerState(db, sessionId) {
@@ -7966,10 +7998,10 @@ function getPersistedCompactionMarkerState(db, sessionId) {
7966
7998
  } catch {}
7967
7999
  return null;
7968
8000
  }
7969
- function setPersistedCompactionMarkerState(db, sessionId, state) {
8001
+ function setPersistedCompactionMarkerState(db, sessionId, state2) {
7970
8002
  ensureSessionMetaRow(db, sessionId);
7971
- const json = state ? JSON.stringify(state) : "";
7972
- db.prepare("UPDATE session_meta SET compaction_marker_state = ?, compaction_marker_target_end_message_id = ? WHERE session_id = ?").run(json, state?.targetEndMessageId ?? null, sessionId);
8003
+ const json = state2 ? JSON.stringify(state2) : "";
8004
+ db.prepare("UPDATE session_meta SET compaction_marker_state = ?, compaction_marker_target_end_message_id = ? WHERE session_id = ?").run(json, state2?.targetEndMessageId ?? null, sessionId);
7973
8005
  }
7974
8006
  function getStrippedPlaceholderIds(db, sessionId) {
7975
8007
  const row = db.prepare("SELECT stripped_placeholder_ids FROM session_meta WHERE session_id = ?").get(sessionId);
@@ -8101,9 +8133,9 @@ function getPendingCompactionMarkerState(db, sessionId) {
8101
8133
  } catch {}
8102
8134
  return null;
8103
8135
  }
8104
- function setPendingCompactionMarkerState(db, sessionId, state) {
8136
+ function setPendingCompactionMarkerState(db, sessionId, state2) {
8105
8137
  ensureSessionMetaRow(db, sessionId);
8106
- const blob = state ? stableStringify(state) : null;
8138
+ const blob = state2 ? stableStringify(state2) : null;
8107
8139
  db.prepare("UPDATE session_meta SET pending_compaction_marker_state = ? WHERE session_id = ?").run(blob, sessionId);
8108
8140
  }
8109
8141
  function clearPendingCompactionMarkerStateIf(db, sessionId, expected) {
@@ -8374,6 +8406,14 @@ function getPendingOpsStatement(db) {
8374
8406
  }
8375
8407
  return stmt;
8376
8408
  }
8409
+ function getClearPendingOpsStatement(db) {
8410
+ let stmt = clearPendingOpsStatements.get(db);
8411
+ if (!stmt) {
8412
+ stmt = db.prepare("DELETE FROM pending_ops WHERE session_id = ?");
8413
+ clearPendingOpsStatements.set(db, stmt);
8414
+ }
8415
+ return stmt;
8416
+ }
8377
8417
  function getRemovePendingOpStatement(db) {
8378
8418
  let stmt = removePendingOpStatements.get(db);
8379
8419
  if (!stmt) {
@@ -8408,6 +8448,9 @@ function getPendingOps(db, sessionId) {
8408
8448
  const rows = getPendingOpsStatement(db).all(sessionId).filter(isPendingOpRow);
8409
8449
  return rows.map(toPendingOp).filter((op) => op !== null);
8410
8450
  }
8451
+ function clearPendingOps(db, sessionId) {
8452
+ getClearPendingOpsStatement(db).run(sessionId);
8453
+ }
8411
8454
  function removePendingOp(db, sessionId, tagId) {
8412
8455
  getRemovePendingOpStatement(db).run(sessionId, tagId);
8413
8456
  }
@@ -8603,11 +8646,11 @@ function bumpProjectMemoryEpoch(db, projectPath, now = Date.now()) {
8603
8646
  ON CONFLICT(project_path) DO UPDATE SET
8604
8647
  project_memory_epoch = project_memory_epoch + 1,
8605
8648
  updated_at = excluded.updated_at`).run(projectPath, now);
8606
- const state = getProjectState(db, projectPath);
8607
- if (!state) {
8649
+ const state2 = getProjectState(db, projectPath);
8650
+ if (!state2) {
8608
8651
  throw new Error(`Failed to bump project memory epoch for ${projectPath}`);
8609
8652
  }
8610
- return state;
8653
+ return state2;
8611
8654
  }
8612
8655
  function bumpProjectUserProfileVersion(db, projectPath = GLOBAL_USER_PROFILE_PROJECT_PATH, now = Date.now()) {
8613
8656
  db.prepare(`INSERT INTO project_state
@@ -8616,11 +8659,11 @@ function bumpProjectUserProfileVersion(db, projectPath = GLOBAL_USER_PROFILE_PRO
8616
8659
  ON CONFLICT(project_path) DO UPDATE SET
8617
8660
  project_user_profile_version = project_user_profile_version + 1,
8618
8661
  updated_at = excluded.updated_at`).run(projectPath, now);
8619
- const state = getProjectState(db, projectPath);
8620
- if (!state) {
8662
+ const state2 = getProjectState(db, projectPath);
8663
+ if (!state2) {
8621
8664
  throw new Error(`Failed to bump project user profile version for ${projectPath}`);
8622
8665
  }
8623
- return state;
8666
+ return state2;
8624
8667
  }
8625
8668
  // src/features/magic-context/storage-source.ts
8626
8669
  function isSourceContentRow(row) {
@@ -9210,6 +9253,518 @@ var ERROR_CLASSES = new Set([
9210
9253
  "permission_denied",
9211
9254
  "unknown"
9212
9255
  ]);
9256
+ // src/hooks/magic-context/child-session-spawn.ts
9257
+ var STALE_PLUGIN_RESTART_NOTICE = "Magic Context: plugin build is older than its database — restart OpenCode";
9258
+ async function surfaceStalePluginBuild(args) {
9259
+ if (!args.parentSessionId)
9260
+ return;
9261
+ try {
9262
+ if (args.db) {
9263
+ updateSessionMeta(args.db, args.parentSessionId, {
9264
+ lastTransformError: STALE_PLUGIN_RESTART_NOTICE
9265
+ });
9266
+ }
9267
+ pushNotification("toast", {
9268
+ title: "Magic Context",
9269
+ message: STALE_PLUGIN_RESTART_NOTICE,
9270
+ variant: "error",
9271
+ duration: 1e4
9272
+ }, args.parentSessionId);
9273
+ pushNotification("action", { action: "refresh-sidebar" }, args.parentSessionId);
9274
+ await sendIgnoredMessage(args.client, args.parentSessionId, STALE_PLUGIN_RESTART_NOTICE, args.notificationParams ?? {}, true);
9275
+ } catch (error) {
9276
+ sessionLog(args.parentSessionId, `stale plugin-build warning delivery failed: ${error instanceof Error ? error.message : String(error)}`);
9277
+ }
9278
+ }
9279
+ async function createChildSessionWithFence(args) {
9280
+ const verdict = probeChildSpawnFence(args.db);
9281
+ if (!verdict.allowSpawn) {
9282
+ if (args.parentSessionId) {
9283
+ sessionLog(args.parentSessionId, `child session skipped (${verdict.failure.failureClass}): database=v${verdict.failure.persistedVersion}, supported_fence=v${verdict.failure.supportedVersion}, consecutive=${verdict.failure.consecutiveFailures}, total=${verdict.failure.totalFailures}`);
9284
+ }
9285
+ if (verdict.shouldSurface) {
9286
+ if (args.onFenceLatched)
9287
+ await args.onFenceLatched(verdict.failure);
9288
+ else
9289
+ await surfaceStalePluginBuild(args);
9290
+ }
9291
+ return null;
9292
+ }
9293
+ return args.client.session.create({
9294
+ body: {
9295
+ ...args.parentSessionId ? { parentID: args.parentSessionId } : {},
9296
+ title: args.title
9297
+ },
9298
+ query: { directory: args.directory }
9299
+ });
9300
+ }
9301
+ // src/features/magic-context/overflow-detection.ts
9302
+ var OVERFLOW_PATTERNS = [
9303
+ /prompt is too long/i,
9304
+ /input is too long for requested model/i,
9305
+ /exceeds the context window/i,
9306
+ /input token count.*exceeds the maximum/i,
9307
+ /maximum prompt length is \d+/i,
9308
+ /reduce the length of the messages/i,
9309
+ /maximum context length is \d+ tokens/i,
9310
+ /maximum model length is \d+/i,
9311
+ /exceeds the limit of \d+/i,
9312
+ /exceeds the available context size/i,
9313
+ /greater than the context length/i,
9314
+ /context window exceeds limit/i,
9315
+ /exceeded model token limit/i,
9316
+ /context[_ ]length[_ ]exceeded/i,
9317
+ /request entity too large/i,
9318
+ /context length is only \d+ tokens/i,
9319
+ /input length.*exceeds.*context length/i,
9320
+ /prompt too long; exceeded (?:max )?context length/i,
9321
+ /too large for model with \d+ maximum context length/i,
9322
+ /model_context_window_exceeded/i,
9323
+ /context size has been exceeded/i
9324
+ ];
9325
+ var LIMIT_EXTRACTION_PATTERNS = [
9326
+ { pattern: /maximum prompt length is (\d+)/i, provenance: "prompt_only" },
9327
+ {
9328
+ pattern: /maximum context length is (\d+) tokens?/i,
9329
+ provenance: "combined"
9330
+ },
9331
+ { pattern: /maximum model length is (\d+)/i, provenance: "combined" },
9332
+ { pattern: /context length is only (\d+) tokens?/i, provenance: "combined" },
9333
+ { pattern: /exceeds the limit of (\d+)/i, provenance: "unknown" },
9334
+ {
9335
+ pattern: /too large for model with (\d+) maximum context length/i,
9336
+ provenance: "combined"
9337
+ },
9338
+ { pattern: /context size.*(\d+) tokens?/i, provenance: "combined" },
9339
+ { pattern: /exceeds? the context length of (\d+)/i, provenance: "combined" },
9340
+ {
9341
+ pattern: />\s*(\d+)\s*(?:tokens?\s*)?(?:maximum|max|limit)\b/i,
9342
+ provenance: "prompt_only"
9343
+ },
9344
+ { pattern: /max(?:imum)?.*context.*?(\d+)/i, provenance: "unknown" }
9345
+ ];
9346
+ var MIN_PLAUSIBLE_LIMIT = 1024;
9347
+ var MAX_PLAUSIBLE_LIMIT = 1e7;
9348
+ function extractErrorMessage(error) {
9349
+ if (!error)
9350
+ return "";
9351
+ if (typeof error === "string")
9352
+ return error;
9353
+ if (typeof error === "object") {
9354
+ const obj = error;
9355
+ const nested = obj.error;
9356
+ if (nested && typeof nested.message === "string" && nested.message.length > 0) {
9357
+ return nested.message;
9358
+ }
9359
+ }
9360
+ if (error instanceof Error)
9361
+ return error.message;
9362
+ if (typeof error === "object") {
9363
+ const obj = error;
9364
+ if (typeof obj.message === "string")
9365
+ return obj.message;
9366
+ if (typeof obj.responseBody === "string")
9367
+ return obj.responseBody;
9368
+ try {
9369
+ return JSON.stringify(error);
9370
+ } catch {
9371
+ return String(error);
9372
+ }
9373
+ }
9374
+ return String(error);
9375
+ }
9376
+ function detectOverflow(error) {
9377
+ const message = extractErrorMessage(error);
9378
+ if (!message) {
9379
+ return { isOverflow: false };
9380
+ }
9381
+ const hasStatus413 = /\b413\b/.test(message) && /(entity|payload|context|prompt)/i.test(message);
9382
+ let matched;
9383
+ for (const pattern of OVERFLOW_PATTERNS) {
9384
+ if (pattern.test(message)) {
9385
+ matched = pattern;
9386
+ break;
9387
+ }
9388
+ }
9389
+ if (!matched && !hasStatus413) {
9390
+ return { isOverflow: false };
9391
+ }
9392
+ const reportedLimit = parseReportedLimit(message);
9393
+ return {
9394
+ isOverflow: true,
9395
+ reportedLimit: reportedLimit?.value,
9396
+ reportedLimitProvenance: reportedLimit?.provenance,
9397
+ matchedPattern: matched?.source
9398
+ };
9399
+ }
9400
+ function parseReportedLimit(message) {
9401
+ if (!message)
9402
+ return;
9403
+ for (const { pattern, provenance } of LIMIT_EXTRACTION_PATTERNS) {
9404
+ const match = message.match(pattern);
9405
+ if (!match)
9406
+ continue;
9407
+ const raw = match[1];
9408
+ if (!raw)
9409
+ continue;
9410
+ const value = Number.parseInt(raw, 10);
9411
+ if (!Number.isFinite(value))
9412
+ continue;
9413
+ if (value < MIN_PLAUSIBLE_LIMIT || value > MAX_PLAUSIBLE_LIMIT)
9414
+ continue;
9415
+ return { value, provenance };
9416
+ }
9417
+ return;
9418
+ }
9419
+
9420
+ // src/shared/model-suggestion-retry.ts
9421
+ var ABORT_CALL_TIMEOUT_MS = 3000;
9422
+ function copyPromptArgs(args, body) {
9423
+ return { ...args, body: { ...body } };
9424
+ }
9425
+ function extractMessage(error) {
9426
+ if (typeof error === "string")
9427
+ return error;
9428
+ if (error instanceof Error)
9429
+ return error.message;
9430
+ if (typeof error === "object" && error !== null) {
9431
+ const obj = error;
9432
+ if (typeof obj.message === "string")
9433
+ return obj.message;
9434
+ }
9435
+ try {
9436
+ return JSON.stringify(error);
9437
+ } catch (_error) {
9438
+ return String(error);
9439
+ }
9440
+ }
9441
+ function parseModelSuggestion(error) {
9442
+ if (!error)
9443
+ return null;
9444
+ if (typeof error === "object" && error !== null) {
9445
+ const errObj = error;
9446
+ if (errObj.name === "ProviderModelNotFoundError" && typeof errObj.data === "object" && errObj.data !== null) {
9447
+ const data = errObj.data;
9448
+ const suggestions = data.suggestions;
9449
+ if (Array.isArray(suggestions) && typeof suggestions[0] === "string") {
9450
+ return {
9451
+ providerID: String(data.providerID ?? ""),
9452
+ modelID: String(data.modelID ?? ""),
9453
+ suggestion: suggestions[0]
9454
+ };
9455
+ }
9456
+ }
9457
+ for (const key of ["data", "error", "cause"]) {
9458
+ const nested = errObj[key];
9459
+ if (nested && typeof nested === "object") {
9460
+ const result = parseModelSuggestion(nested);
9461
+ if (result)
9462
+ return result;
9463
+ }
9464
+ }
9465
+ }
9466
+ const message = extractMessage(error);
9467
+ const modelMatch = message.match(/model not found:\s*([^/\s]+)\s*\/\s*([^.,\s]+)/i);
9468
+ const suggestionMatch = message.match(/did you mean:\s*([^,?]+)/i);
9469
+ if (!modelMatch || !suggestionMatch) {
9470
+ return null;
9471
+ }
9472
+ return {
9473
+ providerID: modelMatch[1].trim(),
9474
+ modelID: modelMatch[2].trim(),
9475
+ suggestion: suggestionMatch[1].trim()
9476
+ };
9477
+ }
9478
+ async function promptWithTimeout(client, args, timeoutMs, signal) {
9479
+ if (signal?.aborted) {
9480
+ throw new Error("prompt aborted by external signal");
9481
+ }
9482
+ const controller = new AbortController;
9483
+ const timeout = setTimeout(() => controller.abort(), timeoutMs);
9484
+ const onExternalAbort = () => controller.abort();
9485
+ signal?.addEventListener("abort", onExternalAbort);
9486
+ try {
9487
+ await client.session.prompt({
9488
+ ...args,
9489
+ signal: controller.signal
9490
+ });
9491
+ } catch (error) {
9492
+ if (signal?.aborted) {
9493
+ await abortChildRun(client, args.path.id);
9494
+ throw new Error("prompt aborted by external signal");
9495
+ }
9496
+ if (controller.signal.aborted) {
9497
+ await abortChildRun(client, args.path.id);
9498
+ throw new Error(`prompt timed out after ${timeoutMs}ms`);
9499
+ }
9500
+ throw error;
9501
+ } finally {
9502
+ clearTimeout(timeout);
9503
+ signal?.removeEventListener("abort", onExternalAbort);
9504
+ }
9505
+ }
9506
+ async function abortChildRun(client, sessionId) {
9507
+ try {
9508
+ await Promise.race([
9509
+ client.session.abort({ path: { id: sessionId } }),
9510
+ new Promise((resolve) => setTimeout(resolve, ABORT_CALL_TIMEOUT_MS))
9511
+ ]);
9512
+ } catch (error) {
9513
+ log(`[model-retry] child session abort failed for ${sessionId}: ${String(error)}`);
9514
+ }
9515
+ }
9516
+ function isNonRetryable(error, externalSignal) {
9517
+ if (externalSignal?.aborted)
9518
+ return true;
9519
+ if (error instanceof Error) {
9520
+ if (error.name === "AbortError")
9521
+ return true;
9522
+ if (error.message === "prompt aborted by external signal")
9523
+ return true;
9524
+ if (/^prompt timed out after \d+ms$/.test(error.message))
9525
+ return true;
9526
+ }
9527
+ if (detectOverflow(error).isOverflow)
9528
+ return true;
9529
+ return false;
9530
+ }
9531
+ function shortErr(error) {
9532
+ if (error instanceof Error) {
9533
+ return error.name && error.name !== "Error" ? `${error.name}: ${error.message}` : error.message;
9534
+ }
9535
+ return extractMessage(error);
9536
+ }
9537
+ async function attemptOnce(client, args, timeoutMs, signal, callContext, label) {
9538
+ const originalBody = { ...args.body };
9539
+ const attemptArgs = copyPromptArgs(args, originalBody);
9540
+ try {
9541
+ await promptWithTimeout(client, attemptArgs, timeoutMs, signal);
9542
+ return;
9543
+ } catch (error) {
9544
+ if (isNonRetryable(error, signal))
9545
+ throw error;
9546
+ const suggestion = parseModelSuggestion(error);
9547
+ if (!suggestion || !originalBody.model) {
9548
+ throw error;
9549
+ }
9550
+ log(`[${callContext}] ${label}: model not found, retrying with suggestion`, {
9551
+ original: `${suggestion.providerID}/${suggestion.modelID}`,
9552
+ suggested: suggestion.suggestion
9553
+ });
9554
+ await promptWithTimeout(client, copyPromptArgs(args, {
9555
+ ...originalBody,
9556
+ model: {
9557
+ providerID: suggestion.providerID,
9558
+ modelID: suggestion.suggestion
9559
+ }
9560
+ }), timeoutMs, signal);
9561
+ }
9562
+ }
9563
+ async function promptSyncWithModelSuggestionRetry(client, args, options = {}) {
9564
+ const timeoutMs = options.timeoutMs ?? 300000;
9565
+ const callContext = options.callContext ?? "subagent";
9566
+ const fallbacks = options.fallbackModels ?? [];
9567
+ const baseBody = { ...args.body };
9568
+ const baseArgs = copyPromptArgs(args, baseBody);
9569
+ const explicitPrimaryLabel = baseBody.model?.providerID && baseBody.model.modelID ? `${baseBody.model.providerID}/${baseBody.model.modelID}` : "primary";
9570
+ let lastError = null;
9571
+ try {
9572
+ await attemptOnce(client, baseArgs, timeoutMs, options.signal, callContext, explicitPrimaryLabel);
9573
+ return;
9574
+ } catch (error) {
9575
+ lastError = error;
9576
+ if (isNonRetryable(error, options.signal))
9577
+ throw error;
9578
+ if (fallbacks.length === 0) {
9579
+ throw error;
9580
+ }
9581
+ log(`[${callContext}] primary (${explicitPrimaryLabel}) failed: ${shortErr(error)}; trying ${fallbacks.length} fallback(s)`);
9582
+ }
9583
+ for (let i = 0;i < fallbacks.length; i += 1) {
9584
+ const parsed = parseProviderModel(fallbacks[i]);
9585
+ if (!parsed) {
9586
+ log(`[${callContext}] skipping invalid fallback spec: ${fallbacks[i]}`);
9587
+ continue;
9588
+ }
9589
+ const label = `${parsed.providerID}/${parsed.modelID}`;
9590
+ const attemptArgs = copyPromptArgs(baseArgs, {
9591
+ ...baseBody,
9592
+ model: parsed
9593
+ });
9594
+ try {
9595
+ await attemptOnce(client, attemptArgs, timeoutMs, options.signal, callContext, label);
9596
+ log(`[${callContext}] fallback succeeded with ${label} (attempt ${i + 2}/${fallbacks.length + 1})`);
9597
+ return;
9598
+ } catch (error) {
9599
+ lastError = error;
9600
+ if (isNonRetryable(error, options.signal))
9601
+ throw error;
9602
+ const remaining = fallbacks.length - i - 1;
9603
+ if (remaining > 0) {
9604
+ log(`[${callContext}] ${label} failed: ${shortErr(error)}; ${remaining} fallback(s) left`);
9605
+ }
9606
+ }
9607
+ }
9608
+ log(`[${callContext}] all models exhausted; tried: ${[explicitPrimaryLabel, ...fallbacks].join(", ")}; last error: ${shortErr(lastError)}`);
9609
+ throw lastError ?? new Error("All fallback models failed");
9610
+ }
9611
+ async function attemptAndValidate(client, args, timeoutMs, signal, callContext, attempt, options) {
9612
+ await attemptOnce(client, args, timeoutMs, signal, callContext, attempt.label);
9613
+ const output = await options.fetchOutput(args, attempt);
9614
+ const validated = await options.validateOutput(output, attempt);
9615
+ return { output, validated, attempt };
9616
+ }
9617
+ async function promptSyncWithValidatedOutputRetry(client, args, options) {
9618
+ const timeoutMs = options.timeoutMs ?? 300000;
9619
+ const callContext = options.callContext ?? "subagent";
9620
+ const fallbacks = options.fallbackModels ?? [];
9621
+ const baseBody = { ...args.body };
9622
+ const baseArgs = copyPromptArgs(args, baseBody);
9623
+ const explicitPrimaryLabel = baseBody.model?.providerID && baseBody.model.modelID ? `${baseBody.model.providerID}/${baseBody.model.modelID}` : "primary";
9624
+ const totalAttempts = fallbacks.length + 1;
9625
+ let firstError = null;
9626
+ let lastError = null;
9627
+ try {
9628
+ return await attemptAndValidate(client, baseArgs, timeoutMs, options.signal, callContext, {
9629
+ label: explicitPrimaryLabel,
9630
+ attemptIndex: 0,
9631
+ isFallback: false,
9632
+ totalAttempts,
9633
+ model: baseBody.model
9634
+ }, options);
9635
+ } catch (error) {
9636
+ firstError = error;
9637
+ lastError = error;
9638
+ if (isNonRetryable(error, options.signal))
9639
+ throw error;
9640
+ if (fallbacks.length === 0) {
9641
+ throw error;
9642
+ }
9643
+ log(`[${callContext}] primary (${explicitPrimaryLabel}) failed validation/prompt: ${shortErr(error)}; trying ${fallbacks.length} fallback(s)`);
9644
+ }
9645
+ for (let i = 0;i < fallbacks.length; i += 1) {
9646
+ const parsed = parseProviderModel(fallbacks[i]);
9647
+ if (!parsed) {
9648
+ log(`[${callContext}] skipping invalid fallback spec: ${fallbacks[i]}`);
9649
+ continue;
9650
+ }
9651
+ const label = `${parsed.providerID}/${parsed.modelID}`;
9652
+ const attemptArgs = copyPromptArgs(baseArgs, {
9653
+ ...baseBody,
9654
+ model: parsed
9655
+ });
9656
+ const attempt = {
9657
+ label,
9658
+ attemptIndex: i + 1,
9659
+ isFallback: true,
9660
+ totalAttempts,
9661
+ model: parsed
9662
+ };
9663
+ try {
9664
+ const result = await attemptAndValidate(client, attemptArgs, timeoutMs, options.signal, callContext, attempt, options);
9665
+ log(`[${callContext}] fallback succeeded with ${label} (attempt ${i + 2}/${fallbacks.length + 1})`);
9666
+ return result;
9667
+ } catch (error) {
9668
+ if (firstError === null)
9669
+ firstError = error;
9670
+ lastError = error;
9671
+ if (isNonRetryable(error, options.signal))
9672
+ throw error;
9673
+ const remaining = fallbacks.length - i - 1;
9674
+ if (remaining > 0) {
9675
+ log(`[${callContext}] ${label} failed validation/prompt: ${shortErr(error)}; ${remaining} fallback(s) left`);
9676
+ }
9677
+ }
9678
+ }
9679
+ log(`[${callContext}] all models exhausted; tried: ${[explicitPrimaryLabel, ...fallbacks].join(", ")}; original error: ${shortErr(firstError)}; last error: ${shortErr(lastError)}`);
9680
+ throw firstError ?? lastError ?? new Error("All fallback models failed validation");
9681
+ }
9682
+ // src/shared/normalize-sdk-response.ts
9683
+ function normalizeSDKResponse(response, fallback, options) {
9684
+ if (response === null || response === undefined) {
9685
+ return fallback;
9686
+ }
9687
+ if (Array.isArray(response)) {
9688
+ return response;
9689
+ }
9690
+ if (typeof response === "object" && "data" in response) {
9691
+ const data = response.data;
9692
+ if (data !== null && data !== undefined) {
9693
+ return data;
9694
+ }
9695
+ if (options?.preferResponseOnMissingData === true) {
9696
+ return response;
9697
+ }
9698
+ return fallback;
9699
+ }
9700
+ if (options?.preferResponseOnMissingData === true) {
9701
+ return response;
9702
+ }
9703
+ return fallback;
9704
+ }
9705
+ // src/shared/assistant-message-extractor.ts
9706
+ function asSessionMessage(value) {
9707
+ if (!isRecord(value))
9708
+ return null;
9709
+ const info = value.info;
9710
+ const parts = value.parts;
9711
+ return {
9712
+ info: isRecord(info) ? {
9713
+ role: typeof info.role === "string" ? info.role : undefined,
9714
+ time: isRecord(info.time) ? {
9715
+ created: typeof info.time.created === "number" ? info.time.created : undefined
9716
+ } : undefined
9717
+ } : undefined,
9718
+ parts
9719
+ };
9720
+ }
9721
+ function getCreatedTime(message) {
9722
+ return message.info?.time?.created ?? 0;
9723
+ }
9724
+ function getTextParts(message) {
9725
+ if (!Array.isArray(message.parts))
9726
+ return [];
9727
+ return message.parts.filter((part) => isRecord(part)).map((part) => ({
9728
+ type: typeof part.type === "string" ? part.type : undefined,
9729
+ text: typeof part.text === "string" ? part.text : undefined
9730
+ })).filter((part) => part.type === "text" && Boolean(part.text));
9731
+ }
9732
+ function extractLatestAssistantText(messages) {
9733
+ if (!Array.isArray(messages) || messages.length === 0)
9734
+ return null;
9735
+ const assistantMessages = messages.map(asSessionMessage).filter((message) => message !== null).filter((message) => message.info?.role === "assistant").sort((a, b) => getCreatedTime(b) - getCreatedTime(a));
9736
+ const latest = assistantMessages[0];
9737
+ if (!latest)
9738
+ return null;
9739
+ return getTextParts(latest).map((part) => part.text).join(`
9740
+ `) || null;
9741
+ }
9742
+ function hasLengthCappedOutput(value) {
9743
+ if (Array.isArray(value))
9744
+ return value.some((item) => hasLengthCappedOutput(item));
9745
+ if (!isRecord(value))
9746
+ return false;
9747
+ if (value.length_capped === true || value.lengthCapped === true)
9748
+ return true;
9749
+ const finishReason = value.finish_reason ?? value.finishReason;
9750
+ if (typeof finishReason === "string") {
9751
+ const normalized = finishReason.toLowerCase();
9752
+ if (normalized === "length" || normalized === "max_tokens" || normalized === "max_output_tokens") {
9753
+ return true;
9754
+ }
9755
+ }
9756
+ return Object.values(value).some((item) => hasLengthCappedOutput(item));
9757
+ }
9758
+
9759
+ // src/shared/keep-subagents.ts
9760
+ var keepSubagents = false;
9761
+ function setKeepSubagents(value) {
9762
+ keepSubagents = value === true;
9763
+ }
9764
+ function shouldKeepSubagents() {
9765
+ return keepSubagents;
9766
+ }
9767
+
9213
9768
  // src/features/magic-context/user-memory/storage-user-memory.ts
9214
9769
  var USER_MEMORY_CANDIDATE_TTL_MS = 30 * 24 * 60 * 60 * 1000;
9215
9770
  function insertUserMemoryCandidates(db, candidates) {
@@ -9277,9 +9832,9 @@ function parseUserMemoryRow(row) {
9277
9832
  }
9278
9833
 
9279
9834
  // src/features/magic-context/mural/storage-mural-cues.ts
9280
- import { createHash as createHash7 } from "node:crypto";
9835
+ import { createHash as createHash8 } from "node:crypto";
9281
9836
  function computeCueContentHash(content) {
9282
- return createHash7("sha256").update(content).digest("hex");
9837
+ return createHash8("sha256").update(content).digest("hex");
9283
9838
  }
9284
9839
  var muralCueColumnCache = new WeakMap;
9285
9840
  function hasMuralCueColumns(db) {
@@ -9305,10 +9860,10 @@ function getMuralCueState(db, memoryIds) {
9305
9860
  }
9306
9861
  return out;
9307
9862
  }
9308
- function memoryNeedsCue(state, currentContent) {
9309
- if (!state || state.cue === null || state.hash === null)
9863
+ function memoryNeedsCue(state2, currentContent) {
9864
+ if (!state2 || state2.cue === null || state2.hash === null)
9310
9865
  return true;
9311
- return state.hash !== computeCueContentHash(currentContent);
9866
+ return state2.hash !== computeCueContentHash(currentContent);
9312
9867
  }
9313
9868
  function setMuralCue(db, projectPath, id, cue, contentHash) {
9314
9869
  if (!hasMuralCueColumns(db))
@@ -9330,7 +9885,6 @@ var deleteEmbeddingStatements = new WeakMap;
9330
9885
  var getStoredModelIdStatements = new WeakMap;
9331
9886
  var clearAllEmbeddingsStatements = new WeakMap;
9332
9887
  var clearModelEmbeddingsStatements = new WeakMap;
9333
- var getDistinctStoredModelIdsStatements = new WeakMap;
9334
9888
  function isEmbeddingBlob(value) {
9335
9889
  return value instanceof Uint8Array || value instanceof ArrayBuffer;
9336
9890
  }
@@ -9447,13 +10001,13 @@ function invalidateMemory(projectPath, memoryId) {
9447
10001
  }
9448
10002
 
9449
10003
  // src/features/magic-context/memory/normalize-hash.ts
9450
- import { createHash as createHash8 } from "node:crypto";
10004
+ import { createHash as createHash9 } from "node:crypto";
9451
10005
  function normalizeMemoryContent(content) {
9452
10006
  return content.toLowerCase().replace(/\s+/g, " ").trim();
9453
10007
  }
9454
10008
  function computeNormalizedHash(content) {
9455
10009
  const normalized = normalizeMemoryContent(content);
9456
- return createHash8("md5").update(normalized).digest("hex");
10010
+ return createHash9("md5").update(normalized).digest("hex");
9457
10011
  }
9458
10012
 
9459
10013
  // src/features/magic-context/memory/visibility.ts
@@ -10317,9 +10871,12 @@ async function runMemoryMigration(deps) {
10317
10871
  const modelOverride = modelId ? parseProviderModel(modelId) : null;
10318
10872
  await cleanupChildSession(agentSessionId);
10319
10873
  agentSessionId = null;
10320
- const createResponse = await client.session.create({
10321
- body: { parentID: parentSessionId, title: "magic-context-memory-migration" },
10322
- query: { directory }
10874
+ const createResponse = await createChildSessionWithFence({
10875
+ client,
10876
+ db,
10877
+ parentSessionId,
10878
+ title: "magic-context-memory-migration",
10879
+ directory
10323
10880
  });
10324
10881
  const created = normalizeSDKResponse(createResponse, null, {
10325
10882
  preferResponseOnMissingData: true
@@ -10419,7 +10976,7 @@ async function runMemoryMigration(deps) {
10419
10976
  }
10420
10977
 
10421
10978
  // src/features/magic-context/compartment-chunk-embedding.ts
10422
- import { createHash as createHash9 } from "node:crypto";
10979
+ import { createHash as createHash10 } from "node:crypto";
10423
10980
 
10424
10981
  // src/features/magic-context/recursive-text-splitter.ts
10425
10982
  var DEFAULT_SEPARATORS = [`
@@ -10514,9 +11071,6 @@ var existingHashStatements = new WeakMap;
10514
11071
  var existingHashByProjectStatements = new WeakMap;
10515
11072
  var deleteByCompartmentStatements = new WeakMap;
10516
11073
  var insertEmbeddingStatements = new WeakMap;
10517
- var distinctModelStatements = new WeakMap;
10518
- var clearProjectStatements = new WeakMap;
10519
- var clearProjectModelStatements = new WeakMap;
10520
11074
  var searchRowsStatements = new WeakMap;
10521
11075
  var searchRowsByModelStatements = new WeakMap;
10522
11076
  var searchPoolProbeStatements = new WeakMap;
@@ -10707,7 +11261,7 @@ function parseCanonicalLineRange(line) {
10707
11261
  return { start, end };
10708
11262
  }
10709
11263
  function hashChunkText(text) {
10710
- return createHash9("sha256").update(text).digest("hex");
11264
+ return createHash10("sha256").update(text).digest("hex");
10711
11265
  }
10712
11266
  function vectorBlob2(vector) {
10713
11267
  return new Uint8Array(vector.buffer, vector.byteOffset, vector.byteLength);
@@ -11098,7 +11652,7 @@ function countSessionCompartmentEmbedCoverage(db, projectPath, sessionId, modelI
11098
11652
  }
11099
11653
 
11100
11654
  // src/features/magic-context/project-embedding-registry.ts
11101
- import { createHash as createHash11, randomUUID as randomUUID2 } from "node:crypto";
11655
+ import { createHash as createHash12, randomUUID as randomUUID2 } from "node:crypto";
11102
11656
 
11103
11657
  // src/config/schema/magic-context.ts
11104
11658
  import { homedir as homedir2 } from "node:os";
@@ -25550,7 +26104,7 @@ var AgentOverrideConfigSchema = exports_external.object({
25550
26104
 
25551
26105
  // src/config/schema/magic-context.ts
25552
26106
  var DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE = 65;
25553
- var EXECUTE_THRESHOLD_CAP_MESSAGE = "execute_threshold is capped at 80% for cache safety: a single large agent step can overflow the context window before Magic Context can compact between turns, forcing OpenCode's native compaction (hard to recover from). 80% also leaves headroom below the 85%/95% emergency bands. Use a value between 20 and 80.";
26107
+ var EXECUTE_THRESHOLD_CAP_MESSAGE = "execute_threshold is capped at 90% for cache safety: output capacity is reserved from the usable context window, and the remaining 10% absorbs mid-turn growth before the absolute 95% emergency wall. Use a value between 20 and 90.";
25554
26108
  var DEFAULT_HISTORIAN_TIMEOUT_MS = 300000;
25555
26109
  var DEFAULT_HISTORY_BUDGET_PERCENTAGE = 0.15;
25556
26110
  var DEFAULT_LOCAL_EMBEDDING_MODEL = "Xenova/all-MiniLM-L6-v2";
@@ -25648,7 +26202,22 @@ var BaseEmbeddingConfigSchema = exports_external.object({
25648
26202
  input_type: exports_external.string().optional().describe("Default input_type for stored/indexed (passage) embeddings in the request body. Required by some openai-compatible providers (e.g. NVIDIA NIM). Omitted from the request when unset."),
25649
26203
  query_input_type: exports_external.string().optional().describe("Optional input_type for query (search) embeddings on asymmetric models (e.g. NVIDIA NIM 'query'). When unset, query embeddings use embedding.input_type. Passage/stored content always uses embedding.input_type."),
25650
26204
  truncate: exports_external.string().optional().describe("Optional truncate mode sent in the embedding request body (e.g. NVIDIA NIM accepts 'NONE' | 'START' | 'END'). Omitted from the request when unset."),
25651
- max_input_tokens: exports_external.number().int().positive().optional().describe("Optional maximum input tokens for chunk embeddings. Defaults conservatively to 512 when omitted.")
26205
+ max_input_tokens: exports_external.number().int().positive().optional().describe("Optional maximum input tokens for chunk embeddings. Defaults conservatively to 512 when omitted."),
26206
+ local_dtype: exports_external.enum([
26207
+ "auto",
26208
+ "fp32",
26209
+ "fp16",
26210
+ "q8",
26211
+ "int8",
26212
+ "uint8",
26213
+ "q4",
26214
+ "bnb4",
26215
+ "q4f16",
26216
+ "q2",
26217
+ "q2f16",
26218
+ "q1",
26219
+ "q1f16"
26220
+ ]).optional().describe("Local provider only: ONNX model dtype passed to the transformers.js feature-extraction pipeline. Accepts the @huggingface/transformers DataType strings (auto, fp32, fp16, q8, int8, uint8, q4, bnb4, q4f16, q2, q2f16, q1, q1f16). Omitted keeps today's behavior (fp32). A non-default value changes the produced vectors and folds into the embedding model identity, so switching dtype re-embeds rather than mixing vector spaces. Useful for selecting a quantized variant (e.g. q8) of a larger multilingual model to cut memory and CPU cost; see issue #259.")
25652
26221
  }).superRefine((data, ctx) => {
25653
26222
  const validationProvider = data.provider === "synapse" ? data.fallback_provider : data.provider;
25654
26223
  if (validationProvider === "openai-compatible" && !data.endpoint?.trim()) {
@@ -25690,7 +26259,8 @@ var EmbeddingConfigSchema = BaseEmbeddingConfigSchema.transform((data) => {
25690
26259
  return {
25691
26260
  provider: "local",
25692
26261
  model: data.model?.trim() || DEFAULT_LOCAL_EMBEDDING_MODEL,
25693
- ...data.max_input_tokens ? { max_input_tokens: data.max_input_tokens } : {}
26262
+ ...data.max_input_tokens ? { max_input_tokens: data.max_input_tokens } : {},
26263
+ ...data.local_dtype ? { local_dtype: data.local_dtype } : {}
25694
26264
  };
25695
26265
  }
25696
26266
  if (data.provider === "openai-compatible") {
@@ -25713,26 +26283,29 @@ var EmbeddingConfigSchema = BaseEmbeddingConfigSchema.transform((data) => {
25713
26283
  });
25714
26284
  var MagicContextConfigSchema = exports_external.object({
25715
26285
  enabled: exports_external.boolean().default(true).describe("Enable magic context (default: true)"),
25716
- experimental: exports_external.object({
25717
- mural: exports_external.object({
25718
- enabled: exports_external.boolean().default(false),
25719
- model: exports_external.string().trim().min(1).optional().describe("Model for the compress-cues task that compresses each memory into a mural cue. The mural image itself is rendered deterministically (no author model).")
25720
- }).default({ enabled: false }).describe("Experimental mural: a single deterministically-rendered image of project memories that did not fit the context budget. Cues are compressed per-memory by the compress-cues dreamer task.")
25721
- }).default({ mural: { enabled: false } }).describe("Experimental feature switches. User and project configuration are both accepted."),
26286
+ allow_home_project: exports_external.boolean().default(false).describe("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."),
26287
+ mural: exports_external.object({
26288
+ enabled: exports_external.boolean().default(false),
26289
+ model: exports_external.string().trim().min(1).optional().describe("Model for the compress-cues task that compresses each memory into a mural cue. The mural image itself is rendered deterministically (no author model).")
26290
+ }).default({ enabled: false }).describe("Experimental mural: a single deterministically-rendered image of project memories that did not fit the context budget. Cues are compressed per-memory by the compress-cues dreamer task."),
25722
26291
  transform_mode: exports_external.enum(["ts", "rust"]).default("ts").describe('Experimental: routes the entire Magic Context runtime for the project through the ck-mc Rust module over subc (requires user-level `subc` config); "ts" is the current TypeScript pipeline.'),
25723
26292
  auto_update: exports_external.boolean().optional().describe("Enable automatic npm self-update checks for the OpenCode plugin. Security: USER-only in config loader, so hostile project configs cannot suppress updates."),
25724
26293
  language: exports_external.string().trim().toLowerCase().refine((s) => isValidLanguageCode(s), 'language must be a 2-letter ISO 639-1 code (e.g. "tr", "es", "de")').optional().describe("Output language for Magic Context's generated content and guidance, as a " + '2-letter ISO 639-1 code (e.g. "tr", "es", "de", "ja", "pt"). When set, the ' + "historian, dreamer, sidekick, and the agent-guidance block instruct the model to " + "write its PROSE in this language while keeping all structural tokens (XML tags, " + "the five memory category names, code identifiers, file paths) in English. " + "USER-LEVEL ONLY (ignored in project config for security). Unset = today's " + "behavior (model mirrors the conversation; English scaffolding). Changing it " + "triggers one cache re-materialization; existing compartments/memories keep their " + "original language until naturally rewritten."),
25725
26294
  historian: HistorianConfigSchema.describe("Historian agent configuration (model, fallback_models, variant, temperature, maxTokens, permission, two_pass, etc.)"),
25726
26295
  dreamer: DreamerConfigSchema.optional().describe("Dreamer agent + scheduling configuration (model, fallback_models, disable, schedule, tasks, etc.)"),
25727
- cache_ttl: exports_external.union([exports_external.string(), exports_external.object({ default: exports_external.string() }).catchall(exports_external.string())]).default("5m").describe('Cache TTL: string (e.g. "5m") or per-model object ({ default: "5m", "model-id": "10m" })'),
26296
+ cache_ttl: exports_external.union([exports_external.string(), exports_external.object({ default: exports_external.string() }).catchall(exports_external.string())]).default("5m").describe('Cache TTL: string (e.g. "5m", "1h", "30s") or per-model object ({ default: "5m", "model-id": "10m" }). Set to "never" for lanes kept warm by an external keepwarm proxy — disables the idle-TTL heuristic so MC never initiates a rebuild based on elapsed time.'),
26297
+ output_reserve: exports_external.union([
26298
+ exports_external.number().min(0),
26299
+ exports_external.object({ default: exports_external.number().min(0) }).catchall(exports_external.number().min(0))
26300
+ ]).optional().describe('User-only output-token reservation override. Number or per-model object ({ default: 16384, "provider/model": 8192 }); 0 disables reservation. When unset, Magic Context reserves the catalog output limit (capped at 25% of context) for shared-window providers and keeps proven separate-quota Google/Gemini windows unchanged.'),
25728
26301
  toast_duration_ms: exports_external.number().min(0).max(60000).default(5000).describe("TUI toast lifetime in milliseconds for Magic Context notifications. Set to 0 to disable Magic Context toasts entirely (min: 0, max: 60000, default: 5000)"),
25729
26302
  execute_threshold_percentage: exports_external.union([
25730
- exports_external.number().min(20).max(80, EXECUTE_THRESHOLD_CAP_MESSAGE),
25731
- exports_external.object({ default: exports_external.number().min(20).max(80, EXECUTE_THRESHOLD_CAP_MESSAGE) }).catchall(exports_external.number().min(20).max(80, EXECUTE_THRESHOLD_CAP_MESSAGE))
25732
- ]).default(DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE).describe('Context percentage that forces queued operations to execute. Number or per-model object ({ default: 65, "provider/model": 45 }). Values above 80 are rejected because the runtime caps at 80% for cache safety (MAX_EXECUTE_THRESHOLD). Default: DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE'),
26303
+ exports_external.number().min(20).max(90, EXECUTE_THRESHOLD_CAP_MESSAGE),
26304
+ exports_external.object({ default: exports_external.number().min(20).max(90, EXECUTE_THRESHOLD_CAP_MESSAGE) }).catchall(exports_external.number().min(20).max(90, EXECUTE_THRESHOLD_CAP_MESSAGE))
26305
+ ]).default(DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE).describe('Context percentage that forces queued operations to execute. Number or per-model object ({ default: 65, "provider/model": 45 }). Values above 90 are rejected because the runtime caps at 90% of the output-reserved safe window (MAX_EXECUTE_THRESHOLD). Default: DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE'),
25733
26306
  execute_threshold_tokens: exports_external.object({
25734
26307
  default: exports_external.number().min(5000).max(2000000).optional()
25735
- }).catchall(exports_external.number().min(5000).max(2000000)).optional().describe("Absolute token thresholds per model. When matched, overrides execute_threshold_percentage for that model. Accepts `default` for all models or per-model keys. Values above 80% × context_limit are clamped with a warning log. Min 5_000, max 2_000_000."),
26308
+ }).catchall(exports_external.number().min(5000).max(2000000)).optional().describe("Absolute token thresholds per model. When matched, overrides execute_threshold_percentage for that model. Accepts `default` for all models or per-model keys. Values above 90% × context_limit are clamped with a warning log. Min 5_000, max 2_000_000."),
25736
26309
  protected_tags: exports_external.number().min(1).max(100).optional().describe("Number of recent tags to protect from dropping (min: 1, max: 100, default: 20)"),
25737
26310
  clear_reasoning_age: exports_external.number().min(10).default(50).describe("Clear reasoning/thinking blocks older than N tags (default: 50)"),
25738
26311
  history_budget_percentage: exports_external.number().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)"),
@@ -25752,6 +26325,9 @@ var MagicContextConfigSchema = exports_external.object({
25752
26325
  cache_size_mb: exports_external.number().min(2).max(2048).default(64).describe("Page-cache size in MiB per connection (PRAGMA cache_size). Larger keeps more hot pages resident, cutting re-reads on repeated full-table scans. (min 2, max 2048, default 64)"),
25753
26326
  mmap_size_mb: exports_external.number().min(0).max(8192).default(0).describe("Memory-mapped I/O size in MiB (PRAGMA mmap_size). 0 disables mmap (SQLite default). Raising it can cut read overhead on large DBs at the cost of address space. (min 0, max 8192, default 0)")
25754
26327
  }).default({ cache_size_mb: 64, mmap_size_mb: 0 }).describe("SQLite connection tuning for Magic Context's own context.db. These are per-connection PRAGMAs applied at open; they do not change the schema or what is stored."),
26328
+ storage: exports_external.object({
26329
+ enforce_private_permissions: exports_external.boolean().default(true).describe("When true (default), Magic Context creates and re-tightens its storage directories to owner-only 0700 and storage files to owner-only 0600. Set false only for a deliberate trusted-group deployment whose operator manages directory, database, WAL/SHM, cache, and RPC file permissions externally; Magic Context then never chmods or supplies restrictive creation modes. USER-LEVEL ONLY — ignored in project config for security. On Windows, POSIX chmod modes are already meaningless, so this setting is a no-op.")
26330
+ }).default({ enforce_private_permissions: true }).describe("Storage permission policy. The default keeps session content and memories owner-private. Disabling enforcement is for trusted shared-group storage managed externally; every group member able to read the storage can read all stored session content and memories."),
25755
26331
  embedding: EmbeddingConfigSchema.default({
25756
26332
  provider: "local",
25757
26333
  model: DEFAULT_LOCAL_EMBEDDING_MODEL
@@ -25765,6 +26341,9 @@ var MagicContextConfigSchema = exports_external.object({
25765
26341
  temporal_awareness: exports_external.boolean().default(true).describe('Inject wall-clock gap markers (<!-- +Xm -->) between user messages where > 5 min elapsed since the previous message, and add compact date ranges to compartment headings. Gives the agent a sense of session pacing and "how long ago" across multi-day sessions. Graduated from experimental.temporal_awareness; default: true (set false to opt out).'),
25766
26342
  keep_subagents: exports_external.boolean().default(false).describe("Debug: keep the child sessions Magic Context spawns for its own subagents (historian, dreamer, sidekick, memory-migration) instead of deleting them on success. Useful for short-term inspection/data collection — their full transcript (prompt, tool calls, token usage, output) stays in the host session store. Kept sessions accumulate until manually cleared; leave false for normal use. Requires a restart to take effect."),
25767
26343
  fail_closed_blocking: exports_external.boolean().default(true).describe("When Magic Context cannot operate (schema fence mismatch, storage open/migration failure), block the primary-session prompt with a loud recovery error instead of silently degrading to native compaction. Default true. Set false only to restore the old degrade-silently behavior (not recommended). USER-LEVEL ONLY — ignored in project config for security. Requires a restart."),
26344
+ compaction: exports_external.object({
26345
+ enabled: exports_external.boolean().default(true).describe("When false, Magic Context stops managing the context window and keeps its knowledge layer: memory and docs/user-profile/key-files injection through additive m[0]/m[1], raw-message FTS indexing, dreamer, notes, ctx_search, ctx_expand, ctx_memory, and /ctx-embed remain available. MC's historian/compartment preparation, tagging, markers, pruning, folding, drops, strips, splicing, synthetic context-management todos, temporal markers, nudges, and fail-closed blocking stop; ctx_expand remains a knowledge-surface tool. fail_closed_blocking is inert: a transform failure passes the input messages through without blocking or cancelling. This setting does not enable native compaction: OpenCode's compaction.auto / compaction.prune or Pi's equivalent owns the window, or nothing does. MC's compaction.enabled in magic-context.jsonc is distinct from OpenCode's compaction.auto / compaction.prune in opencode.jsonc; they are different files and different owners. On the first turn after disabling, a long session may trigger one native compaction cycle; MC removes only its own marker boundary, leaves native boundaries and stored compartments intact, and does no pre-trimming mitigation. Marker cleanup is lazy per session, so an unresumed session is cleaned when it is next resumed. If compaction is enabled again, run /ctx-wrapup when the historian is runnable to catch up. OpenCode peer verification against v1.18.4 confirms native compaction covers child sessions: subagents receive additive memory/docs injection and no MC reclaim in this mode, so keep subagent tasks small or leave compaction.enabled on for long subagent runs. If transform_mode is rust, compaction-off resolves to the TypeScript transform and emits one frozen boot warning because there is no Rust reduced-mode contract. This is boot-resolved and requires a process restart; project-tier compaction.enabled is stripped so a cloned repository cannot disable the user's setting. The sidebar reports raw usage as Context: <pct>% · native compaction or Context: <pct>% · no active compaction and does not show an MC execute-threshold fill. /ctx-wrapup, /ctx-recomp, /ctx-flush, and /ctx-session-upgrade refuse without context-management side effects; /ctx-embed remains functional. Raw content hidden by a native boundary before Magic Context's first pass is not retroactively indexed.")
26346
+ }).default({ enabled: true }).describe("Compaction-off mode gate. Default true (MC manages the context window as today). Set compaction.enabled=false to keep the knowledge layer while letting native compaction (or nothing) own the window. Boot-resolved; requires a restart to change."),
25768
26347
  todowrite: exports_external.object({
25769
26348
  enabled: exports_external.boolean().default(true).describe("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."),
25770
26349
  overlay: exports_external.boolean().default(true).describe("Pi only: show the persistent todo overlay above the editor while tasks are active.")
@@ -25811,9 +26390,6 @@ var saveStatements = new WeakMap;
25811
26390
  var loadProjectStatements = new WeakMap;
25812
26391
  var loadUnembeddedStatements = new WeakMap;
25813
26392
  var countEmbeddedStatements = new WeakMap;
25814
- var clearProjectStatements2 = new WeakMap;
25815
- var clearProjectModelStatements2 = new WeakMap;
25816
- var distinctModelIdStatements = new WeakMap;
25817
26393
  function getSaveStatement(db) {
25818
26394
  let stmt = saveStatements.get(db);
25819
26395
  if (!stmt) {
@@ -25884,7 +26460,6 @@ function countEmbeddedCommits(db, projectPath, modelId) {
25884
26460
  var insertStatements = new WeakMap;
25885
26461
  var existingShasStatements = new WeakMap;
25886
26462
  var projectCountStatements = new WeakMap;
25887
- var evictStatements = new WeakMap;
25888
26463
  var evictOverflowStatements = new WeakMap;
25889
26464
  var latestCommitTimeStatements = new WeakMap;
25890
26465
  function getInsertStatement(db) {
@@ -26126,7 +26701,7 @@ function releaseGitSweepLease(db, projectPath, holderId) {
26126
26701
  }
26127
26702
 
26128
26703
  // src/features/magic-context/memory/embedding-synapse.ts
26129
- import { createHash as createHash10 } from "node:crypto";
26704
+ import { createHash as createHash11 } from "node:crypto";
26130
26705
 
26131
26706
  // ../../node_modules/.bun/@cortexkit+subc-client@0.4.1/node_modules/@cortexkit/subc-client/dist/client.js
26132
26707
  import { promises as fs2 } from "node:fs";
@@ -28339,7 +28914,7 @@ function wait(ms) {
28339
28914
  return new Promise((resolve) => setTimeout(resolve, ms));
28340
28915
  }
28341
28916
  function sha256(value) {
28342
- return createHash10("sha256").update(value).digest("hex");
28917
+ return createHash11("sha256").update(value).digest("hex");
28343
28918
  }
28344
28919
  function stableJson(value) {
28345
28920
  if (Array.isArray(value))
@@ -28387,7 +28962,7 @@ function extractCatalogEntries(value) {
28387
28962
  const batchRecord = asRecord(rawBatch);
28388
28963
  const recommendedBatch = typeof rawBatch === "number" ? rawBatch : batchRecord ? batchRecord.rows : undefined;
28389
28964
  const recommendedTokenBudget = batchRecord ? batchRecord.token_budget : undefined;
28390
- const state = typeof record2.state === "string" ? record2.state : undefined;
28965
+ const state2 = typeof record2.state === "string" ? record2.state : undefined;
28391
28966
  return [
28392
28967
  {
28393
28968
  model,
@@ -28398,7 +28973,7 @@ function extractCatalogEntries(value) {
28398
28973
  ...typeof recommendedTokenBudget === "number" && recommendedTokenBudget > 0 ? { recommended_token_budget: Math.floor(recommendedTokenBudget) } : {},
28399
28974
  ...record2.provenance !== undefined ? { provenance: record2.provenance } : {},
28400
28975
  ...typeof record2.certified === "boolean" ? { certified: record2.certified } : {},
28401
- ...typeof record2.status === "string" ? { status: record2.status } : state ? { status: state } : {}
28976
+ ...typeof record2.status === "string" ? { status: record2.status } : state2 ? { status: state2 } : {}
28402
28977
  }
28403
28978
  ];
28404
28979
  });
@@ -28784,6 +29359,7 @@ function getEmbeddingProviderIdentity(config2) {
28784
29359
  throw new Error("Unknown embedding provider");
28785
29360
  }
28786
29361
  const truncate = config2.provider === "openai-compatible" ? config2.truncate?.trim() : undefined;
29362
+ const localDtype = config2.provider === "local" && config2.local_dtype && config2.local_dtype !== "fp32" ? config2.local_dtype : undefined;
28787
29363
  const identityInput = config2.provider === "openai-compatible" ? {
28788
29364
  provider: "openai-compatible",
28789
29365
  model: config2.model.trim(),
@@ -28795,7 +29371,8 @@ function getEmbeddingProviderIdentity(config2) {
28795
29371
  provider: "local",
28796
29372
  model: config2.model?.trim() || DEFAULT_LOCAL_EMBEDDING_MODEL,
28797
29373
  endpoint: "",
28798
- apiKeyPresent: false
29374
+ apiKeyPresent: false,
29375
+ ...localDtype ? { localDtype } : {}
28799
29376
  };
28800
29377
  return `embedding-provider:${computeNormalizedHash(JSON.stringify(identityInput))}`;
28801
29378
  }
@@ -28803,7 +29380,7 @@ function getEmbeddingProviderIdentity(config2) {
28803
29380
  // src/features/magic-context/memory/embedding-local.ts
28804
29381
  import { chmodSync as chmodSync2, mkdirSync as mkdirSync2 } from "node:fs";
28805
29382
  import { open, stat, unlink, writeFile } from "node:fs/promises";
28806
- import { dirname as dirname2, join as join3 } from "node:path";
29383
+ import { dirname as dirname2, join as join4 } from "node:path";
28807
29384
  import { pathToFileURL } from "node:url";
28808
29385
  var LOCK_POLL_MS = 150;
28809
29386
  var STALE_LOCK_MS = 3 * 60000;
@@ -28883,6 +29460,7 @@ async function injectWasmOrtForElectron() {
28883
29460
  return false;
28884
29461
  }
28885
29462
  }
29463
+ var DEFAULT_LOCAL_DTYPE = "fp32";
28886
29464
  async function withQuietConsole(fn) {
28887
29465
  const origWarn = console.warn;
28888
29466
  const origError = console.error;
@@ -28959,16 +29537,22 @@ class LocalEmbeddingProvider {
28959
29537
  modelId;
28960
29538
  maxInputTokens;
28961
29539
  model;
29540
+ dtype;
28962
29541
  pipeline = null;
28963
29542
  initPromise = null;
28964
29543
  inFlight = 0;
28965
29544
  disposing = false;
28966
29545
  disposePromise = null;
28967
29546
  inFlightWaiters = [];
28968
- constructor(model = DEFAULT_LOCAL_EMBEDDING_MODEL, maxInputTokens = 512) {
29547
+ constructor(model = DEFAULT_LOCAL_EMBEDDING_MODEL, maxInputTokens = 512, dtype = DEFAULT_LOCAL_DTYPE) {
28969
29548
  this.model = model;
28970
29549
  this.maxInputTokens = maxInputTokens;
28971
- this.modelId = getEmbeddingProviderIdentity({ provider: "local", model });
29550
+ this.dtype = dtype || DEFAULT_LOCAL_DTYPE;
29551
+ this.modelId = getEmbeddingProviderIdentity({
29552
+ provider: "local",
29553
+ model,
29554
+ ...dtype && dtype !== DEFAULT_LOCAL_DTYPE ? { local_dtype: dtype } : {}
29555
+ });
28972
29556
  }
28973
29557
  async initialize() {
28974
29558
  if (this.disposing) {
@@ -28997,20 +29581,24 @@ class LocalEmbeddingProvider {
28997
29581
  if (LogLevel && "ERROR" in LogLevel) {
28998
29582
  env.logLevel = LogLevel.ERROR;
28999
29583
  }
29000
- const modelCacheDir = join3(getMagicContextStorageDir(), "models");
29584
+ const modelCacheDir = join4(getMagicContextStorageDir(), "models");
29001
29585
  try {
29002
- mkdirSync2(modelCacheDir, { recursive: true, mode: 448 });
29003
- if (process.platform !== "win32") {
29004
- try {
29005
- chmodSync2(modelCacheDir, 448);
29006
- } catch {}
29586
+ if (shouldEnforcePrivateStoragePermissions()) {
29587
+ mkdirSync2(modelCacheDir, { recursive: true, mode: 448 });
29588
+ if (process.platform !== "win32") {
29589
+ try {
29590
+ chmodSync2(modelCacheDir, 448);
29591
+ } catch {}
29592
+ }
29593
+ } else {
29594
+ mkdirSync2(modelCacheDir, { recursive: true });
29007
29595
  }
29008
29596
  env.cacheDir = modelCacheDir;
29009
29597
  } catch {
29010
29598
  log("[magic-context] could not create model cache dir, using library default");
29011
29599
  }
29012
29600
  const createPipeline = transformersModule.pipeline;
29013
- const lockPath = join3(modelCacheDir, ".load.lock");
29601
+ const lockPath = join4(modelCacheDir, ".load.lock");
29014
29602
  const releaseLock = await acquireModelLoadLock(lockPath);
29015
29603
  const stopHeartbeat = startLockHeartbeat(lockPath);
29016
29604
  try {
@@ -29019,7 +29607,7 @@ class LocalEmbeddingProvider {
29019
29607
  for (let attempt = 1;attempt <= MAX_ATTEMPTS; attempt++) {
29020
29608
  try {
29021
29609
  const pipeline = await withQuietConsole(() => createPipeline("feature-extraction", this.model, {
29022
- dtype: "fp32",
29610
+ dtype: this.dtype,
29023
29611
  ...injectedWasmOrt ? { device: "auto" } : {}
29024
29612
  }));
29025
29613
  if (this.disposing) {
@@ -29670,7 +30258,8 @@ function resolveEmbeddingConfig(config2) {
29670
30258
  model: config2?.model?.trim() || DEFAULT_LOCAL_EMBEDDING_MODEL,
29671
30259
  ...config2?.max_input_tokens ? {
29672
30260
  max_input_tokens: normalizeCompartmentChunkMaxInputTokens(config2.max_input_tokens)
29673
- } : {}
30261
+ } : {},
30262
+ ...config2?.local_dtype ? { local_dtype: config2.local_dtype } : {}
29674
30263
  };
29675
30264
  }
29676
30265
  if (config2.provider === "openai-compatible") {
@@ -29729,7 +30318,7 @@ function createProvider(config2, context) {
29729
30318
  });
29730
30319
  }
29731
30320
  if (config2.provider === "local") {
29732
- return new LocalEmbeddingProvider(config2.model, config2.max_input_tokens);
30321
+ return new LocalEmbeddingProvider(config2.model, config2.max_input_tokens, config2.local_dtype);
29733
30322
  }
29734
30323
  if (config2.provider === "synapse") {
29735
30324
  const synapse = config2;
@@ -29758,10 +30347,10 @@ function stableStringify2(value) {
29758
30347
  return JSON.stringify(value);
29759
30348
  }
29760
30349
  function sha256Prefix(value, length = 16) {
29761
- return createHash11("sha256").update(value).digest("hex").slice(0, length);
30350
+ return createHash12("sha256").update(value).digest("hex").slice(0, length);
29762
30351
  }
29763
30352
  function contentSha256(value) {
29764
- return createHash11("sha256").update(value).digest("hex");
30353
+ return createHash12("sha256").update(value).digest("hex");
29765
30354
  }
29766
30355
  function getRuntimeFingerprint(config2) {
29767
30356
  if (config2.provider === "off") {
@@ -31036,12 +31625,12 @@ function parseFields(json2) {
31036
31625
  }
31037
31626
 
31038
31627
  // src/hooks/magic-context/historian-state-file.ts
31039
- import { mkdirSync as mkdirSync3, unlinkSync, writeFileSync } from "node:fs";
31628
+ import { mkdirSync as mkdirSync3, unlinkSync as unlinkSync2, writeFileSync } from "node:fs";
31040
31629
  function cleanupHistorianStateFile(path3) {
31041
31630
  if (!path3)
31042
31631
  return;
31043
31632
  try {
31044
- unlinkSync(path3);
31633
+ unlinkSync2(path3);
31045
31634
  } catch {}
31046
31635
  }
31047
31636
  // src/features/magic-context/memory/cosine-similarity.ts
@@ -31084,7 +31673,7 @@ function createProvider2(config2) {
31084
31673
  });
31085
31674
  }
31086
31675
  if (config2.provider === "local") {
31087
- return new LocalEmbeddingProvider(config2.model, config2.max_input_tokens);
31676
+ return new LocalEmbeddingProvider(config2.model, config2.max_input_tokens, config2.local_dtype);
31088
31677
  }
31089
31678
  if (config2.provider === "synapse") {
31090
31679
  const synapse = config2;
@@ -31356,8 +31945,8 @@ function getMemoryVerifications(db, memoryIds) {
31356
31945
  existing.mappedAt = Math.max(existing.mappedAt, row.mapped_at ?? 0);
31357
31946
  result.set(row.memory_id, existing);
31358
31947
  }
31359
- for (const state of result.values()) {
31360
- state.files.sort();
31948
+ for (const state2 of result.values()) {
31949
+ state2.files.sort();
31361
31950
  }
31362
31951
  return result;
31363
31952
  }
@@ -31594,18 +32183,18 @@ function tallyFactsByCategory(facts) {
31594
32183
  }
31595
32184
 
31596
32185
  // src/hooks/magic-context/compaction-marker-manager.ts
31597
- import { join as join5 } from "node:path";
32186
+ import { join as join6 } from "node:path";
31598
32187
 
31599
32188
  // src/features/magic-context/compaction-marker.ts
31600
- import { createHash as createHash12 } from "node:crypto";
32189
+ import { createHash as createHash13 } from "node:crypto";
31601
32190
  import { existsSync as existsSync5 } from "node:fs";
31602
- import { join as join4 } from "node:path";
32191
+ import { join as join5 } from "node:path";
31603
32192
  var BASE62_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
31604
32193
  var ID_PREFIX_HEX_LENGTH = 12;
31605
32194
  var ID_SUFFIX_LENGTH = 14;
31606
32195
  var ID_PREFIX_MASK = (1n << BigInt(ID_PREFIX_HEX_LENGTH * 4)) - 1n;
31607
32196
  function deterministicBase62(seed, length) {
31608
- let value = BigInt(`0x${createHash12("sha256").update(seed).digest("hex")}`);
32197
+ let value = BigInt(`0x${createHash13("sha256").update(seed).digest("hex")}`);
31609
32198
  const chars = Array(length);
31610
32199
  for (let index = length - 1;index >= 0; index -= 1) {
31611
32200
  chars[index] = BASE62_CHARS[Number(value % 62n)];
@@ -31625,7 +32214,7 @@ function generatePartId(timestampMs, counter = 0n, identity = "") {
31625
32214
  return generateId("prt", timestampMs, counter, identity);
31626
32215
  }
31627
32216
  function getOpenCodeDbPath() {
31628
- return join4(getDataDir(), "opencode", "opencode.db");
32217
+ return join5(getDataDir(), "opencode", "opencode.db");
31629
32218
  }
31630
32219
  var cachedWriteDb = null;
31631
32220
  var REQUIRED_MESSAGE_COLUMNS = ["id", "session_id", "time_created", "time_updated", "data"];
@@ -31885,13 +32474,176 @@ function removeForeignCompactionMarker(sessionId, marker, protectedSummaryMessag
31885
32474
  return false;
31886
32475
  }
31887
32476
  }
31888
- function removeCompactionMarker(state) {
32477
+ function dataReferencesTailStart(data) {
32478
+ if (typeof data !== "object" || data === null)
32479
+ return null;
32480
+ const record2 = data;
32481
+ if (typeof record2.tail_start_id === "string" && record2.tail_start_id.length > 0) {
32482
+ return record2.tail_start_id;
32483
+ }
32484
+ const nested = record2.compaction;
32485
+ if (typeof nested === "object" && nested !== null) {
32486
+ const nestedTail = nested.tail_start_id;
32487
+ if (typeof nestedTail === "string" && nestedTail.length > 0)
32488
+ return nestedTail;
32489
+ }
32490
+ return null;
32491
+ }
32492
+ function isMcCanonicalCompactionPartData(data) {
32493
+ if (typeof data !== "object" || data === null || Array.isArray(data))
32494
+ return false;
32495
+ const record2 = data;
32496
+ const keys = Object.keys(record2).sort();
32497
+ return keys.length === 2 && keys[0] === "auto" && keys[1] === "type" && record2.type === "compaction" && record2.auto === true;
32498
+ }
32499
+ function removeMcOwnedCompactionMarkers(sessionId, summaryText) {
32500
+ const db = getWritableOpenCodeDb();
32501
+ if (!isOpenCodeSchemaCompatible(db, getOpenCodeDbPath())) {
32502
+ return {
32503
+ verified: false,
32504
+ removedLineages: 0,
32505
+ removedRows: 0,
32506
+ retainedLineages: 0
32507
+ };
32508
+ }
32509
+ const canonicalSummaries = db.prepare(`SELECT id, COALESCE(json_extract(data, '$.parentID'), '') AS parent_id
32510
+ FROM message
32511
+ WHERE session_id = ?
32512
+ AND COALESCE(json_extract(data, '$.summary'), 0) = 1
32513
+ AND COALESCE(json_extract(data, '$.finish'), '') = 'stop'
32514
+ AND COALESCE(json_extract(data, '$.providerID'), '') = 'magic-context'`).all(sessionId);
32515
+ const legacySummaries = db.prepare(`SELECT m.id, COALESCE(json_extract(m.data, '$.parentID'), '') AS parent_id
32516
+ FROM message m
32517
+ WHERE m.session_id = ?
32518
+ AND COALESCE(json_extract(m.data, '$.summary'), 0) = 1
32519
+ AND COALESCE(json_extract(m.data, '$.finish'), '') = 'stop'
32520
+ AND COALESCE(json_extract(m.data, '$.providerID'), '') <> 'magic-context'
32521
+ AND EXISTS (
32522
+ SELECT 1
32523
+ FROM part p
32524
+ WHERE p.session_id = m.session_id
32525
+ AND p.message_id = m.id
32526
+ AND COALESCE(json_extract(p.data, '$.type'), '') = 'text'
32527
+ AND COALESCE(json_extract(p.data, '$.text'), '') = ?
32528
+ )`).all(sessionId, summaryText);
32529
+ const summariesByBoundary = new Map;
32530
+ const orphanSummaryIds = new Set;
32531
+ for (const row of [...canonicalSummaries, ...legacySummaries]) {
32532
+ if (typeof row.id !== "string")
32533
+ continue;
32534
+ if (typeof row.parent_id === "string" && row.parent_id.length > 0) {
32535
+ const set2 = summariesByBoundary.get(row.parent_id) ?? new Set;
32536
+ set2.add(row.id);
32537
+ summariesByBoundary.set(row.parent_id, set2);
32538
+ } else {
32539
+ orphanSummaryIds.add(row.id);
32540
+ }
32541
+ }
32542
+ const compactionParts = db.prepare(`SELECT id, message_id, data
32543
+ FROM part
32544
+ WHERE session_id = ?
32545
+ AND COALESCE(json_extract(data, '$.type'), '') = 'compaction'`).all(sessionId);
32546
+ const parsedParts = [];
32547
+ for (const part of compactionParts) {
32548
+ if (typeof part.id !== "string" || typeof part.message_id !== "string")
32549
+ continue;
32550
+ let data;
32551
+ try {
32552
+ data = typeof part.data === "string" ? JSON.parse(part.data) : part.data;
32553
+ } catch {
32554
+ data = null;
32555
+ }
32556
+ parsedParts.push({
32557
+ id: part.id,
32558
+ messageId: part.message_id,
32559
+ data,
32560
+ tailStartId: dataReferencesTailStart(data)
32561
+ });
32562
+ }
32563
+ const messageTailRefs = db.prepare(`SELECT id, data
32564
+ FROM message
32565
+ WHERE session_id = ?
32566
+ AND json_extract(data, '$.compaction.tail_start_id') IS NOT NULL`).all(sessionId);
32567
+ const messageTailStartIds = new Set;
32568
+ for (const row of messageTailRefs) {
32569
+ if (typeof row.id !== "string")
32570
+ continue;
32571
+ let data;
32572
+ try {
32573
+ data = typeof row.data === "string" ? JSON.parse(row.data) : row.data;
32574
+ } catch {
32575
+ data = null;
32576
+ }
32577
+ const ref = dataReferencesTailStart(data);
32578
+ if (ref)
32579
+ messageTailStartIds.add(ref);
32580
+ }
32581
+ let removedLineages = 0;
32582
+ let removedRows = 0;
32583
+ let retainedLineages = 0;
32584
+ const deletePartsOfMessage = db.prepare("DELETE FROM part WHERE session_id = ? AND message_id = ?");
32585
+ const deleteMessage = db.prepare("DELETE FROM message WHERE session_id = ? AND id = ?");
32586
+ const deletePart = db.prepare("DELETE FROM part WHERE session_id = ? AND id = ?");
32587
+ const deleteSummaries = (summaryIds) => {
32588
+ let rows = 0;
32589
+ for (const summaryId of summaryIds) {
32590
+ rows += deletePartsOfMessage.run(sessionId, summaryId).changes;
32591
+ rows += deleteMessage.run(sessionId, summaryId).changes;
32592
+ }
32593
+ return rows;
32594
+ };
32595
+ for (const [boundaryMessageId, summaryIds] of summariesByBoundary) {
32596
+ const boundaryParts = parsedParts.filter((part) => part.messageId === boundaryMessageId);
32597
+ const mcPartIds = boundaryParts.filter((part) => isMcCanonicalCompactionPartData(part.data)).map((part) => part.id);
32598
+ const rowsToDelete = new Set([...summaryIds, ...mcPartIds]);
32599
+ const survivingPartsReferenceDeletion = parsedParts.some((part) => !mcPartIds.includes(part.id) && part.tailStartId !== null && rowsToDelete.has(part.tailStartId));
32600
+ const messageFieldReferencesDeletion = [...rowsToDelete].some((id) => messageTailStartIds.has(id));
32601
+ if (survivingPartsReferenceDeletion || messageFieldReferencesDeletion) {
32602
+ retainedLineages += 1;
32603
+ log(`[magic-context] compaction-marker: flip-off cleanup RETAINED lineage at boundary ${boundaryMessageId} — a surviving tail_start_id references a row the deletion would remove`);
32604
+ continue;
32605
+ }
32606
+ const rows = db.transaction(() => {
32607
+ let changed = deleteSummaries(summaryIds);
32608
+ for (const partId of mcPartIds) {
32609
+ changed += deletePart.run(sessionId, partId).changes;
32610
+ }
32611
+ return changed;
32612
+ })();
32613
+ if (rows > 0 || summaryIds.size > 0 || mcPartIds.length > 0) {
32614
+ removedLineages += 1;
32615
+ removedRows += rows;
32616
+ }
32617
+ }
32618
+ if (orphanSummaryIds.size > 0) {
32619
+ const rowsToDelete = new Set(orphanSummaryIds);
32620
+ const survivingPartsReferenceDeletion = parsedParts.some((part) => part.tailStartId !== null && rowsToDelete.has(part.tailStartId));
32621
+ const messageFieldReferencesDeletion = [...rowsToDelete].some((id) => messageTailStartIds.has(id));
32622
+ if (survivingPartsReferenceDeletion || messageFieldReferencesDeletion) {
32623
+ retainedLineages += 1;
32624
+ } else {
32625
+ const rows = db.transaction(() => deleteSummaries(orphanSummaryIds))();
32626
+ removedLineages += 1;
32627
+ removedRows += rows;
32628
+ }
32629
+ }
32630
+ if (removedLineages > 0 || retainedLineages > 0) {
32631
+ log(`[magic-context] compaction-marker: flip-off cleanup for ${sessionId} removed ${removedLineages} lineage(s) (${removedRows} rows), retained ${retainedLineages}`);
32632
+ }
32633
+ return {
32634
+ verified: retainedLineages === 0,
32635
+ removedLineages,
32636
+ removedRows,
32637
+ retainedLineages
32638
+ };
32639
+ }
32640
+ function removeCompactionMarker(state2) {
31889
32641
  try {
31890
32642
  const db = getWritableOpenCodeDb();
31891
32643
  db.transaction(() => {
31892
- db.prepare("DELETE FROM part WHERE id = ?").run(state.summaryPartId);
31893
- db.prepare("DELETE FROM message WHERE id = ?").run(state.summaryMessageId);
31894
- db.prepare("DELETE FROM part WHERE id = ?").run(state.compactionPartId);
32644
+ db.prepare("DELETE FROM part WHERE id = ?").run(state2.summaryPartId);
32645
+ db.prepare("DELETE FROM message WHERE id = ?").run(state2.summaryMessageId);
32646
+ db.prepare("DELETE FROM part WHERE id = ?").run(state2.compactionPartId);
31895
32647
  })();
31896
32648
  return true;
31897
32649
  } catch (error51) {
@@ -31907,9 +32659,9 @@ function dropMarkerSummaryTag(db, sessionId, summaryMessageId) {
31907
32659
  if (tagNumber !== null)
31908
32660
  updateTagStatus(db, sessionId, tagNumber, "dropped");
31909
32661
  }
31910
- function persistMarkerStateAndDropReplacedTag(db, sessionId, state, replacedSummaryMessageId) {
32662
+ function persistMarkerStateAndDropReplacedTag(db, sessionId, state2, replacedSummaryMessageId) {
31911
32663
  db.transaction(() => {
31912
- setPersistedCompactionMarkerState(db, sessionId, state);
32664
+ setPersistedCompactionMarkerState(db, sessionId, state2);
31913
32665
  if (replacedSummaryMessageId !== null) {
31914
32666
  dropMarkerSummaryTag(db, sessionId, replacedSummaryMessageId);
31915
32667
  }
@@ -32130,7 +32882,7 @@ function reconcileForkOrphanedCompactionMarkers(db, sessionId) {
32130
32882
  }
32131
32883
  }
32132
32884
  function checkCompactionMarkerConsistency(db) {
32133
- const opencodeDbPath = join5(getDataDir(), "opencode", "opencode.db");
32885
+ const opencodeDbPath = join6(getDataDir(), "opencode", "opencode.db");
32134
32886
  let opencodeDb;
32135
32887
  try {
32136
32888
  opencodeDb = new Database(opencodeDbPath, { readonly: true });
@@ -32146,19 +32898,19 @@ function checkCompactionMarkerConsistency(db) {
32146
32898
  const checkPart = opencodeDb.prepare("SELECT 1 FROM part WHERE id = ? LIMIT 1");
32147
32899
  let reconciledCount = 0;
32148
32900
  for (const row of persistedRows) {
32149
- const state = getPersistedCompactionMarkerState(db, row.session_id);
32150
- if (!state)
32901
+ const state2 = getPersistedCompactionMarkerState(db, row.session_id);
32902
+ if (!state2)
32151
32903
  continue;
32152
- const boundaryExists = checkMessage.get(state.boundaryMessageId) != null;
32153
- const summaryMessageExists = checkMessage.get(state.summaryMessageId) != null;
32154
- const compactionPartExists = checkPart.get(state.compactionPartId) != null;
32155
- const summaryPartExists = checkPart.get(state.summaryPartId) != null;
32904
+ const boundaryExists = checkMessage.get(state2.boundaryMessageId) != null;
32905
+ const summaryMessageExists = checkMessage.get(state2.summaryMessageId) != null;
32906
+ const compactionPartExists = checkPart.get(state2.compactionPartId) != null;
32907
+ const summaryPartExists = checkPart.get(state2.summaryPartId) != null;
32156
32908
  const allPresent = boundaryExists && summaryMessageExists && compactionPartExists && summaryPartExists;
32157
32909
  if (allPresent)
32158
32910
  continue;
32159
32911
  let removedOk = false;
32160
32912
  try {
32161
- removedOk = removeCompactionMarker(state);
32913
+ removedOk = removeCompactionMarker(state2);
32162
32914
  } catch (error51) {
32163
32915
  sessionLog(row.session_id, "compaction-marker consistency: partial cleanup of half-written marker failed:", error51);
32164
32916
  }
@@ -33108,8 +33860,8 @@ function queueDropsForCompartmentalizedMessages(db, sessionId, upToMessageIndex)
33108
33860
  }
33109
33861
 
33110
33862
  // src/hooks/magic-context/compartment-runner-historian.ts
33111
- import { mkdirSync as mkdirSync4, unlinkSync as unlinkSync2, writeFileSync as writeFileSync2 } from "node:fs";
33112
- import { join as join6 } from "node:path";
33863
+ import { mkdirSync as mkdirSync4, unlinkSync as unlinkSync3, writeFileSync as writeFileSync2 } from "node:fs";
33864
+ import { join as join7 } from "node:path";
33113
33865
 
33114
33866
  // src/features/magic-context/subagent-token-capture.ts
33115
33867
  function asNumber(value) {
@@ -33405,6 +34157,24 @@ function historianResponseDumpDir(directory) {
33405
34157
  return getProjectMagicContextHistorianDir(directory);
33406
34158
  }
33407
34159
  var MAX_HISTORIAN_RETRIES = 2;
34160
+ var HISTORIAN_REASONING_PART_TYPES = new Set(["reasoning", "thinking", "redacted_thinking"]);
34161
+ function extractLatestHistorianReasoning(messages) {
34162
+ if (!Array.isArray(messages))
34163
+ return null;
34164
+ const latest = messages.filter((message) => isRecord(message) && isRecord(message.info) && message.info.role === "assistant").sort((left, right) => historianMessageCreatedAt(right) - historianMessageCreatedAt(left))[0];
34165
+ if (!latest || !Array.isArray(latest.parts))
34166
+ return null;
34167
+ return latest.parts.filter(isHistorianReasoningPart).map((part) => part.text).join(`
34168
+ `) || null;
34169
+ }
34170
+ function isHistorianReasoningPart(part) {
34171
+ return isRecord(part) && typeof part.type === "string" && HISTORIAN_REASONING_PART_TYPES.has(part.type) && typeof part.text === "string" && part.text.length > 0;
34172
+ }
34173
+ function historianMessageCreatedAt(message) {
34174
+ if (!isRecord(message.info) || !isRecord(message.info.time))
34175
+ return 0;
34176
+ return typeof message.info.time.created === "number" ? message.info.time.created : 0;
34177
+ }
33408
34178
  async function runValidatedHistorianPass(args) {
33409
34179
  const firstRun = await runHistorianPrompt({
33410
34180
  ...args,
@@ -33470,6 +34240,7 @@ async function runEditorPassOrFallback(args) {
33470
34240
  sessionLog(args.parentSessionId, "historian two-pass: running editor on draft");
33471
34241
  const editorRun = await runHistorianPrompt({
33472
34242
  client: args.client,
34243
+ db: args.db,
33473
34244
  parentSessionId: args.parentSessionId,
33474
34245
  sessionDirectory: args.sessionDirectory,
33475
34246
  prompt: buildHistorianEditorPrompt(args.draftXml),
@@ -33496,6 +34267,7 @@ async function runEditorPassOrFallback(args) {
33496
34267
  async function runHistorianPrompt(args) {
33497
34268
  const {
33498
34269
  client,
34270
+ db,
33499
34271
  parentSessionId,
33500
34272
  sessionDirectory,
33501
34273
  prompt,
@@ -33529,12 +34301,12 @@ async function runHistorianPrompt(args) {
33529
34301
  };
33530
34302
  try {
33531
34303
  sessionLog(parentSessionId, `historian: creating child session (agent=${agentId}, model=${modelOverride ? `${modelOverride.providerID}/${modelOverride.modelID}` : `agent:${agentId}`})`);
33532
- const createResponse = await client.session.create({
33533
- body: {
33534
- parentID: parentSessionId,
33535
- title: "magic-context-compartment"
33536
- },
33537
- query: { directory: sessionDirectory }
34304
+ const createResponse = await createChildSessionWithFence({
34305
+ client,
34306
+ db,
34307
+ parentSessionId,
34308
+ title: "magic-context-compartment",
34309
+ directory: sessionDirectory
33538
34310
  });
33539
34311
  const createdSession = normalizeSDKResponse(createResponse, null, { preferResponseOnMissingData: true });
33540
34312
  agentSessionId = typeof createdSession?.id === "string" ? createdSession.id : null;
@@ -33582,7 +34354,18 @@ async function runHistorianPrompt(args) {
33582
34354
  preferResponseOnMissingData: true
33583
34355
  });
33584
34356
  const invocationId = recordInvocation({ status: "completed", messages });
33585
- const result = extractLatestAssistantText(messages);
34357
+ const lengthCapped = hasLengthCappedOutput(messages);
34358
+ const textResult = extractLatestAssistantText(messages);
34359
+ const reasoningResult = textResult ? null : extractLatestHistorianReasoning(messages);
34360
+ if (!textResult && reasoningResult && lengthCapped) {
34361
+ const outputTokens = sumTokensFromChildMessages(messages).output;
34362
+ return {
34363
+ ok: false,
34364
+ error: `historian output length-capped at ${outputTokens} tokens (all reasoning, no text) — set historian.maxTokens or route historian.model to a low-reasoning lane/variant`,
34365
+ invocationId: invocationId ?? undefined
34366
+ };
34367
+ }
34368
+ const result = textResult ?? reasoningResult;
33586
34369
  if (!result) {
33587
34370
  return {
33588
34371
  ok: false,
@@ -33634,6 +34417,7 @@ async function runFallbackHistorianPass(args) {
33634
34417
  args.callbacks?.onModelFallback?.(modelId, i + 1, chain.length);
33635
34418
  const fallbackRun = await runHistorianPrompt({
33636
34419
  client: args.client,
34420
+ db: args.db,
33637
34421
  parentSessionId: args.parentSessionId,
33638
34422
  sessionDirectory: args.sessionDirectory,
33639
34423
  prompt: args.prompt,
@@ -33695,7 +34479,7 @@ function cleanupHistorianDump(sessionId, dumpPath) {
33695
34479
  if (!dumpPath)
33696
34480
  return;
33697
34481
  try {
33698
- unlinkSync2(dumpPath);
34482
+ unlinkSync3(dumpPath);
33699
34483
  } catch (error51) {
33700
34484
  sessionLog(sessionId, "compartment agent: failed to remove historian response dump", {
33701
34485
  dumpPath,
@@ -33710,7 +34494,7 @@ function dumpHistorianResponse(sessionId, directory, label, text) {
33710
34494
  ensureCortexKitArtifactGitignore(directory);
33711
34495
  const safeSessionId = sanitizeDumpName(sessionId);
33712
34496
  const safeLabel = sanitizeDumpName(label);
33713
- const dumpPath = join6(dumpDir, `${safeSessionId}-${safeLabel}-${Date.now()}.xml`);
34497
+ const dumpPath = join7(dumpDir, `${safeSessionId}-${safeLabel}-${Date.now()}.xml`);
33714
34498
  writeFileSync2(dumpPath, text, "utf8");
33715
34499
  sessionLog(sessionId, "compartment agent: historian response dumped", {
33716
34500
  label,
@@ -33733,26 +34517,7 @@ function sanitizeDumpName(value) {
33733
34517
  import { Buffer as Buffer3 } from "node:buffer";
33734
34518
 
33735
34519
  // src/features/magic-context/mural/render-trigger.ts
33736
- import { createHash as createHash13 } from "node:crypto";
33737
-
33738
- // src/shared/harness-provider-map.ts
33739
- var PI_TO_CANONICAL_PROVIDER = {
33740
- "openai-codex": "openai",
33741
- "google-antigravity": "google"
33742
- };
33743
- function remapProviderPrefix(ref, map2) {
33744
- if (typeof ref !== "string")
33745
- return ref;
33746
- const slash = ref.indexOf("/");
33747
- if (slash <= 0)
33748
- return ref;
33749
- const provider2 = ref.slice(0, slash);
33750
- const mapped = map2[provider2];
33751
- return mapped ? `${mapped}${ref.slice(slash)}` : ref;
33752
- }
33753
- function piModelRefToCanonical(ref) {
33754
- return remapProviderPrefix(ref, PI_TO_CANONICAL_PROVIDER);
33755
- }
34520
+ import { createHash as createHash14 } from "node:crypto";
33756
34521
 
33757
34522
  // src/features/magic-context/mural/mural-selection.ts
33758
34523
  var DEFAULT_MURAL_MEMORY_BUDGET = 8000;
@@ -33955,6 +34720,8 @@ function naturalLineLengths(entries, roomWidth) {
33955
34720
  let currentCategory = null;
33956
34721
  for (let index = 0;index < entries.length; index++) {
33957
34722
  const entry = entries[index];
34723
+ if (!entry)
34724
+ continue;
33958
34725
  if (entry.category !== currentCategory) {
33959
34726
  currentCategory = entry.category;
33960
34727
  lengths.push(codepoints(` <${entry.category}> `));
@@ -33987,6 +34754,8 @@ function planLines(entries, roomWidth) {
33987
34754
  let currentCategory = null;
33988
34755
  for (let index = 0;index < entries.length; index++) {
33989
34756
  const entry = entries[index];
34757
+ if (!entry)
34758
+ continue;
33990
34759
  if (entry.category !== currentCategory) {
33991
34760
  currentCategory = entry.category;
33992
34761
  lines.push({
@@ -34050,8 +34819,11 @@ function renderLayout(entries, plan, roomWidth, columnCount) {
34050
34819
  const usage = {};
34051
34820
  let filledLineCount = 0;
34052
34821
  for (const [column, columnPlan] of splitPlan(plan, columnCount).entries()) {
34822
+ const columnGrid = grid[column];
34823
+ if (!columnGrid)
34824
+ continue;
34053
34825
  for (const [row, line] of columnPlan.entries()) {
34054
- grid[column][row] = line.text;
34826
+ columnGrid[row] = line.text;
34055
34827
  filledLineCount += 1;
34056
34828
  usage[line.category] = (usage[line.category] ?? 0) + 1;
34057
34829
  const placementLine = row + 1;
@@ -34162,6 +34934,7 @@ function glyph(character) {
34162
34934
  }
34163
34935
  function drawGlyph(pixels, width, height, x, y, character, color) {
34164
34936
  const glyphData = glyph(character);
34937
+ const [red, green, blue] = color;
34165
34938
  for (let row = 0;row < MURAL_CELL_HEIGHT; row++) {
34166
34939
  const pattern = glyphData.rows[row] ?? 0;
34167
34940
  for (let column = 0;column < glyphData.width; column++) {
@@ -34172,9 +34945,9 @@ function drawGlyph(pixels, width, height, x, y, character, color) {
34172
34945
  if (px < 0 || py < 0 || px >= width || py >= height)
34173
34946
  continue;
34174
34947
  const offset = (py * width + px) * 3;
34175
- pixels[offset] = color[0];
34176
- pixels[offset + 1] = color[1];
34177
- pixels[offset + 2] = color[2];
34948
+ pixels[offset] = red;
34949
+ pixels[offset + 1] = green;
34950
+ pixels[offset + 2] = blue;
34178
34951
  }
34179
34952
  }
34180
34953
  }
@@ -34186,6 +34959,7 @@ function drawText(pixels, width, height, x, y, text, color) {
34186
34959
  }
34187
34960
  }
34188
34961
  function fillRect(pixels, canvasWidth, canvasHeight, x, y, width, height, color) {
34962
+ const [red, green, blue] = color;
34189
34963
  const left = Math.max(0, x);
34190
34964
  const top = Math.max(0, y);
34191
34965
  const right = Math.min(canvasWidth, x + width);
@@ -34193,9 +34967,9 @@ function fillRect(pixels, canvasWidth, canvasHeight, x, y, width, height, color)
34193
34967
  for (let py = top;py < bottom; py++) {
34194
34968
  for (let px = left;px < right; px++) {
34195
34969
  const offset = (py * canvasWidth + px) * 3;
34196
- pixels[offset] = color[0];
34197
- pixels[offset + 1] = color[1];
34198
- pixels[offset + 2] = color[2];
34970
+ pixels[offset] = red;
34971
+ pixels[offset + 1] = green;
34972
+ pixels[offset + 2] = blue;
34199
34973
  }
34200
34974
  }
34201
34975
  }
@@ -34222,6 +34996,9 @@ function renderMural(entries) {
34222
34996
  });
34223
34997
  const fittingCandidates = candidates.filter((candidate) => candidate.layout.droppedIds.length === 0);
34224
34998
  const candidatesToCompare = fittingCandidates.length > 0 ? fittingCandidates : candidates;
34999
+ const firstCandidate = candidatesToCompare[0];
35000
+ if (!firstCandidate)
35001
+ throw new Error("mural layout candidate list is empty");
34225
35002
  const selected = candidatesToCompare.reduce((best, candidate) => {
34226
35003
  if (!best)
34227
35004
  return candidate;
@@ -34232,7 +35009,7 @@ function renderMural(entries) {
34232
35009
  return candidate.tileArea < best.tileArea ? candidate : best;
34233
35010
  }
34234
35011
  return candidate.requestedColumnCount < best.requestedColumnCount ? candidate : best;
34235
- }, candidatesToCompare[0]);
35012
+ }, firstCandidate);
34236
35013
  const { layout, width, height } = selected;
34237
35014
  const pixels = new Uint8Array(width * height * 3).fill(255);
34238
35015
  const contentWidth = layout.columnCount === 0 ? 0 : layout.columnCount * roomWidth * MURAL_CELL_WIDTH + MURAL_COLUMN_GAP * (layout.columnCount - 1) * MURAL_CELL_WIDTH;
@@ -34276,8 +35053,8 @@ function getMuralCoverage(db, projectIdentity) {
34276
35053
  const cueState = getMuralCueState(db, memories.map((memory) => memory.id));
34277
35054
  let cuedMemoryCount = 0;
34278
35055
  for (const memory of memories) {
34279
- const state = cueState.get(memory.id);
34280
- if (state && typeof state.cue === "string" && state.cue.trim() !== "" && state.hash !== null && state.hash === computeCueContentHash(memory.content)) {
35056
+ const state2 = cueState.get(memory.id);
35057
+ if (state2 && typeof state2.cue === "string" && state2.cue.trim() !== "" && state2.hash !== null && state2.hash === computeCueContentHash(memory.content)) {
34281
35058
  cuedMemoryCount += 1;
34282
35059
  }
34283
35060
  }
@@ -34291,16 +35068,16 @@ function resolveMural(db, projectIdentity, budgetTokens = DEFAULT_MURAL_MEMORY_B
34291
35068
  const cueState = getMuralCueState(db, overflow.map((memory) => memory.id));
34292
35069
  const entries = [];
34293
35070
  for (const memory of overflow) {
34294
- const state = cueState.get(memory.id);
34295
- if (!state || state.cue === null || state.hash === null)
35071
+ const state2 = cueState.get(memory.id);
35072
+ if (!state2 || state2.cue === null || state2.hash === null)
34296
35073
  continue;
34297
- if (state.hash !== computeCueContentHash(memory.content))
35074
+ if (state2.hash !== computeCueContentHash(memory.content))
34298
35075
  continue;
34299
35076
  entries.push({
34300
35077
  id: memory.id,
34301
35078
  category: memory.category,
34302
35079
  importance: memory.importance ?? 50,
34303
- cue: state.cue
35080
+ cue: state2.cue
34304
35081
  });
34305
35082
  }
34306
35083
  entries.sort(compareMuralEntries);
@@ -34366,7 +35143,7 @@ function ensureMuralRendered(db, projectIdentity, budgetTokens = DEFAULT_MURAL_M
34366
35143
  return { hasMural: false, rerendered: false };
34367
35144
  }
34368
35145
  const rendered = renderMural(entries);
34369
- const textHash = createHash13("sha256").update(rendered.sha256Input).digest("hex");
35146
+ const textHash = createHash14("sha256").update(rendered.sha256Input).digest("hex");
34370
35147
  const existing = getMural(db, projectIdentity);
34371
35148
  if (existing && existing.contentHash === textHash && existing.width === rendered.width && existing.height === rendered.height) {
34372
35149
  return {
@@ -35491,41 +36268,41 @@ function readCurrentM0SnapshotMarkers(args) {
35491
36268
  });
35492
36269
  return fresh.markers;
35493
36270
  }
35494
- function snapshotMarkersFromCachedM0(state) {
35495
- if (!state.cachedM0Bytes)
36271
+ function snapshotMarkersFromCachedM0(state2) {
36272
+ if (!state2.cachedM0Bytes)
35496
36273
  return null;
35497
- const cachedUpgradeIdentity = decodeCachedM0UpgradeIdentity(state.cachedM0UpgradeState);
35498
- if (state.cachedM0ProjectMemoryEpoch === null)
36274
+ const cachedUpgradeIdentity = decodeCachedM0UpgradeIdentity(state2.cachedM0UpgradeState);
36275
+ if (state2.cachedM0ProjectMemoryEpoch === null)
35499
36276
  return null;
35500
- if (state.cachedM0ProjectUserProfileVersion === null)
36277
+ if (state2.cachedM0ProjectUserProfileVersion === null)
35501
36278
  return null;
35502
- if (state.cachedM0MaxCompartmentSeq === null)
36279
+ if (state2.cachedM0MaxCompartmentSeq === null)
35503
36280
  return null;
35504
- if (state.cachedM0MaxMemoryId === null)
36281
+ if (state2.cachedM0MaxMemoryId === null)
35505
36282
  return null;
35506
- if (state.cachedM0MaxMutationId === null)
36283
+ if (state2.cachedM0MaxMutationId === null)
35507
36284
  return null;
35508
- if (state.cachedM0MaxMemoryMutationId === null)
36285
+ if (state2.cachedM0MaxMemoryMutationId === null)
35509
36286
  return null;
35510
- if (state.cachedM0SessionFactsVersion === null)
36287
+ if (state2.cachedM0SessionFactsVersion === null)
35511
36288
  return null;
35512
36289
  return {
35513
- projectMemoryEpoch: state.cachedM0ProjectMemoryEpoch,
35514
- workspaceFingerprint: state.cachedM0WorkspaceFingerprint,
35515
- projectUserProfileVersion: state.cachedM0ProjectUserProfileVersion,
35516
- maxCompartmentSeq: state.cachedM0MaxCompartmentSeq,
35517
- maxMemoryId: state.cachedM0MaxMemoryId,
35518
- maxMutationId: state.cachedM0MaxMutationId,
35519
- maxMemoryMutationId: state.cachedM0MaxMemoryMutationId,
35520
- projectDocsHash: state.cachedM0ProjectDocsHash ?? "",
35521
- materializedAt: state.cachedM0MaterializedAt ?? 0,
35522
- sessionFactsVersion: state.cachedM0SessionFactsVersion,
36290
+ projectMemoryEpoch: state2.cachedM0ProjectMemoryEpoch,
36291
+ workspaceFingerprint: state2.cachedM0WorkspaceFingerprint,
36292
+ projectUserProfileVersion: state2.cachedM0ProjectUserProfileVersion,
36293
+ maxCompartmentSeq: state2.cachedM0MaxCompartmentSeq,
36294
+ maxMemoryId: state2.cachedM0MaxMemoryId,
36295
+ maxMutationId: state2.cachedM0MaxMutationId,
36296
+ maxMemoryMutationId: state2.cachedM0MaxMemoryMutationId,
36297
+ projectDocsHash: state2.cachedM0ProjectDocsHash ?? "",
36298
+ materializedAt: state2.cachedM0MaterializedAt ?? 0,
36299
+ sessionFactsVersion: state2.cachedM0SessionFactsVersion,
35523
36300
  upgradeState: cachedUpgradeIdentity.upgradeState,
35524
36301
  compartmentRenderEpoch: cachedUpgradeIdentity.compartmentRenderEpoch,
35525
- systemHash: state.cachedM0SystemHash ?? "",
35526
- modelKey: state.cachedM0ModelKey ?? "",
35527
- projectIdentity: state.cachedM0ProjectIdentity ?? null,
35528
- muralHash: state.cachedM0MuralHash ?? null
36302
+ systemHash: state2.cachedM0SystemHash ?? "",
36303
+ modelKey: state2.cachedM0ModelKey ?? "",
36304
+ projectIdentity: state2.cachedM0ProjectIdentity ?? null,
36305
+ muralHash: state2.cachedM0MuralHash ?? null
35529
36306
  };
35530
36307
  }
35531
36308
  function mustMaterialize(args) {
@@ -35841,26 +36618,26 @@ ${sessionHistory}
35841
36618
 
35842
36619
  `).trim();
35843
36620
  }
35844
- function applyMarkersToState(state, m0Bytes, markers, m1Bytes) {
35845
- state.cachedM0Bytes = m0Bytes;
36621
+ function applyMarkersToState(state2, m0Bytes, markers, m1Bytes) {
36622
+ state2.cachedM0Bytes = m0Bytes;
35846
36623
  if (m1Bytes)
35847
- state.cachedM1Bytes = m1Bytes;
35848
- state.cachedM0ProjectMemoryEpoch = markers.projectMemoryEpoch;
35849
- state.cachedM0WorkspaceFingerprint = markers.workspaceFingerprint;
35850
- state.cachedM0ProjectUserProfileVersion = markers.projectUserProfileVersion;
35851
- state.cachedM0MaxCompartmentSeq = markers.maxCompartmentSeq;
35852
- state.cachedM0MaxMemoryId = markers.maxMemoryId;
35853
- state.cachedM0MaxMutationId = markers.maxMutationId;
35854
- state.cachedM0MaxMemoryMutationId = markers.maxMemoryMutationId;
35855
- state.cachedM0ProjectDocsHash = markers.projectDocsHash;
35856
- state.cachedM0MaterializedAt = markers.materializedAt;
35857
- state.cachedM0SessionFactsVersion = markers.sessionFactsVersion;
35858
- state.cachedM0UpgradeState = encodeCachedM0UpgradeIdentity(markers.upgradeState, markers.compartmentRenderEpoch);
35859
- state.cachedM0SystemHash = markers.systemHash;
35860
- state.cachedM0ModelKey = markers.modelKey;
35861
- state.cachedM0ProjectIdentity = markers.projectIdentity;
35862
- state.cachedM0MuralHash = markers.muralHash ?? null;
35863
- state.snapshotMarkers = markers;
36624
+ state2.cachedM1Bytes = m1Bytes;
36625
+ state2.cachedM0ProjectMemoryEpoch = markers.projectMemoryEpoch;
36626
+ state2.cachedM0WorkspaceFingerprint = markers.workspaceFingerprint;
36627
+ state2.cachedM0ProjectUserProfileVersion = markers.projectUserProfileVersion;
36628
+ state2.cachedM0MaxCompartmentSeq = markers.maxCompartmentSeq;
36629
+ state2.cachedM0MaxMemoryId = markers.maxMemoryId;
36630
+ state2.cachedM0MaxMutationId = markers.maxMutationId;
36631
+ state2.cachedM0MaxMemoryMutationId = markers.maxMemoryMutationId;
36632
+ state2.cachedM0ProjectDocsHash = markers.projectDocsHash;
36633
+ state2.cachedM0MaterializedAt = markers.materializedAt;
36634
+ state2.cachedM0SessionFactsVersion = markers.sessionFactsVersion;
36635
+ state2.cachedM0UpgradeState = encodeCachedM0UpgradeIdentity(markers.upgradeState, markers.compartmentRenderEpoch);
36636
+ state2.cachedM0SystemHash = markers.systemHash;
36637
+ state2.cachedM0ModelKey = markers.modelKey;
36638
+ state2.cachedM0ProjectIdentity = markers.projectIdentity;
36639
+ state2.cachedM0MuralHash = markers.muralHash ?? null;
36640
+ state2.snapshotMarkers = markers;
35864
36641
  }
35865
36642
  function historySliceTokens(m0Text) {
35866
36643
  const slice = extractM0Block(m0Text, "session-history");
@@ -35910,7 +36687,7 @@ function materializeM0(options) {
35910
36687
  });
35911
36688
  docs = readProjectDocsForM0(projectDirectory, options.injectDocs);
35912
36689
  snapshotMarkers.projectDocsHash = docs.canonicalHash;
35913
- compartments = readM0Compartments(options.db, options.sessionId);
36690
+ compartments = options.compactionOff ? [] : readM0Compartments(options.db, options.sessionId);
35914
36691
  facts = [];
35915
36692
  memories = projectPath ? workspace.isWorkspaced ? getMemoriesByProjects(options.db, workspace.expandedIdentities, ["active", "permanent"], foldMaterializedAt, workspace.ownIdentities, workspace.shareCategories) : getMemoriesByProject(options.db, projectPath, ["active", "permanent"], foldMaterializedAt) : [];
35916
36693
  userMemories = safeGetActiveUserMemories(options.db);
@@ -36275,39 +37052,39 @@ function markersFromCachedRow(row) {
36275
37052
  muralHash: row.cached_m0_mural_hash ?? null
36276
37053
  };
36277
37054
  }
36278
- function cachedRowMatchesState(row, state) {
36279
- return bufferEqualsNullable(row.cached_m0_bytes, state.cachedM0Bytes) && (row.cached_m0_mural_data_url ?? null) === (state.cachedM0MuralDataUrl ?? null) && (row.cached_m0_mural_hash ?? null) === (state.cachedM0MuralHash ?? null) && row.cached_m0_project_memory_epoch === state.cachedM0ProjectMemoryEpoch && (row.cached_m0_workspace_fingerprint ?? null) === (state.cachedM0WorkspaceFingerprint ?? null) && row.cached_m0_project_user_profile_version === state.cachedM0ProjectUserProfileVersion && row.cached_m0_max_compartment_seq === state.cachedM0MaxCompartmentSeq && row.cached_m0_max_memory_id === state.cachedM0MaxMemoryId && row.cached_m0_max_mutation_id === state.cachedM0MaxMutationId && row.cached_m0_max_memory_mutation_id === state.cachedM0MaxMemoryMutationId && row.cached_m0_materialized_at === state.cachedM0MaterializedAt && row.cached_m0_session_facts_version === state.cachedM0SessionFactsVersion && (row.cached_m0_upgrade_state ?? null) === (state.cachedM0UpgradeState ?? null) && (row.cached_m0_system_hash ?? "") === (state.cachedM0SystemHash ?? "") && (row.cached_m0_model_key ?? "") === (state.cachedM0ModelKey ?? "") && (row.cached_m0_project_identity ?? null) === (state.cachedM0ProjectIdentity ?? null);
37055
+ function cachedRowMatchesState(row, state2) {
37056
+ return bufferEqualsNullable(row.cached_m0_bytes, state2.cachedM0Bytes) && (row.cached_m0_mural_data_url ?? null) === (state2.cachedM0MuralDataUrl ?? null) && (row.cached_m0_mural_hash ?? null) === (state2.cachedM0MuralHash ?? null) && row.cached_m0_project_memory_epoch === state2.cachedM0ProjectMemoryEpoch && (row.cached_m0_workspace_fingerprint ?? null) === (state2.cachedM0WorkspaceFingerprint ?? null) && row.cached_m0_project_user_profile_version === state2.cachedM0ProjectUserProfileVersion && row.cached_m0_max_compartment_seq === state2.cachedM0MaxCompartmentSeq && row.cached_m0_max_memory_id === state2.cachedM0MaxMemoryId && row.cached_m0_max_mutation_id === state2.cachedM0MaxMutationId && row.cached_m0_max_memory_mutation_id === state2.cachedM0MaxMemoryMutationId && row.cached_m0_materialized_at === state2.cachedM0MaterializedAt && row.cached_m0_session_facts_version === state2.cachedM0SessionFactsVersion && (row.cached_m0_upgrade_state ?? null) === (state2.cachedM0UpgradeState ?? null) && (row.cached_m0_system_hash ?? "") === (state2.cachedM0SystemHash ?? "") && (row.cached_m0_model_key ?? "") === (state2.cachedM0ModelKey ?? "") && (row.cached_m0_project_identity ?? null) === (state2.cachedM0ProjectIdentity ?? null);
36280
37057
  }
36281
- function applyCachedRowToState(state, row) {
37058
+ function applyCachedRowToState(state2, row) {
36282
37059
  const markers = markersFromCachedRow(row);
36283
37060
  if (!row.cached_m0_bytes || !row.cached_m1_bytes || !markers) {
36284
- throw new RenderM1InvalidMarkersError(state.sessionId);
36285
- }
36286
- state.cachedM0Bytes = toBuffer(row.cached_m0_bytes);
36287
- state.cachedM0MuralDataUrl = row.cached_m0_mural_data_url ?? null;
36288
- state.cachedM0MuralHash = row.cached_m0_mural_hash ?? null;
36289
- state.cachedM1Bytes = toBuffer(row.cached_m1_bytes);
36290
- state.cachedM0ProjectMemoryEpoch = markers.projectMemoryEpoch;
36291
- state.cachedM0WorkspaceFingerprint = markers.workspaceFingerprint;
36292
- state.cachedM0ProjectUserProfileVersion = markers.projectUserProfileVersion;
36293
- state.cachedM0MaxCompartmentSeq = markers.maxCompartmentSeq;
36294
- state.cachedM0MaxMemoryId = markers.maxMemoryId;
36295
- state.cachedM0MaxMutationId = markers.maxMutationId;
36296
- state.cachedM0MaxMemoryMutationId = markers.maxMemoryMutationId;
36297
- state.cachedM0ProjectDocsHash = markers.projectDocsHash;
36298
- state.cachedM0MaterializedAt = markers.materializedAt;
36299
- state.cachedM0SessionFactsVersion = markers.sessionFactsVersion;
36300
- state.cachedM0UpgradeState = encodeCachedM0UpgradeIdentity(markers.upgradeState, markers.compartmentRenderEpoch);
36301
- state.cachedM0SystemHash = markers.systemHash;
36302
- state.cachedM0ModelKey = markers.modelKey;
36303
- state.cachedM0ProjectIdentity = markers.projectIdentity;
36304
- state.snapshotMarkers = markers;
36305
- }
36306
- function replayCachedM1(state) {
36307
- if (!state.cachedM1Bytes) {
36308
- throw new RenderM1InvalidMarkersError(state.sessionId);
36309
- }
36310
- return decodeM0Bytes(state.cachedM1Bytes) ?? M1_EMPTY_PLACEHOLDER;
37061
+ throw new RenderM1InvalidMarkersError(state2.sessionId);
37062
+ }
37063
+ state2.cachedM0Bytes = toBuffer(row.cached_m0_bytes);
37064
+ state2.cachedM0MuralDataUrl = row.cached_m0_mural_data_url ?? null;
37065
+ state2.cachedM0MuralHash = row.cached_m0_mural_hash ?? null;
37066
+ state2.cachedM1Bytes = toBuffer(row.cached_m1_bytes);
37067
+ state2.cachedM0ProjectMemoryEpoch = markers.projectMemoryEpoch;
37068
+ state2.cachedM0WorkspaceFingerprint = markers.workspaceFingerprint;
37069
+ state2.cachedM0ProjectUserProfileVersion = markers.projectUserProfileVersion;
37070
+ state2.cachedM0MaxCompartmentSeq = markers.maxCompartmentSeq;
37071
+ state2.cachedM0MaxMemoryId = markers.maxMemoryId;
37072
+ state2.cachedM0MaxMutationId = markers.maxMutationId;
37073
+ state2.cachedM0MaxMemoryMutationId = markers.maxMemoryMutationId;
37074
+ state2.cachedM0ProjectDocsHash = markers.projectDocsHash;
37075
+ state2.cachedM0MaterializedAt = markers.materializedAt;
37076
+ state2.cachedM0SessionFactsVersion = markers.sessionFactsVersion;
37077
+ state2.cachedM0UpgradeState = encodeCachedM0UpgradeIdentity(markers.upgradeState, markers.compartmentRenderEpoch);
37078
+ state2.cachedM0SystemHash = markers.systemHash;
37079
+ state2.cachedM0ModelKey = markers.modelKey;
37080
+ state2.cachedM0ProjectIdentity = markers.projectIdentity;
37081
+ state2.snapshotMarkers = markers;
37082
+ }
37083
+ function replayCachedM1(state2) {
37084
+ if (!state2.cachedM1Bytes) {
37085
+ throw new RenderM1InvalidMarkersError(state2.sessionId);
37086
+ }
37087
+ return decodeM0Bytes(state2.cachedM1Bytes) ?? M1_EMPTY_PLACEHOLDER;
36311
37088
  }
36312
37089
  function softRefreshCachedM1(options) {
36313
37090
  options.db.exec("BEGIN IMMEDIATE");
@@ -36391,7 +37168,7 @@ function renderFreshM0NonPersisted(options) {
36391
37168
  const docs = readProjectDocsForM0(projectDirectory ?? "", options.injectDocs);
36392
37169
  snapshotMarkers.projectDocsHash = docs.canonicalHash;
36393
37170
  snapshotMarkers.materializedAt = options.state.cachedM0MaterializedAt ?? 0;
36394
- const compartments = withCompartmentDates(options.sessionId, readM0Compartments(options.db, options.sessionId), options.temporalAwareness);
37171
+ const compartments = options.compactionOff ? [] : withCompartmentDates(options.sessionId, readM0Compartments(options.db, options.sessionId), options.temporalAwareness);
36395
37172
  const memories = projectPath ? workspace.isWorkspaced ? getMemoriesByProjects(options.db, workspace.expandedIdentities, ["active", "permanent"], snapshotMarkers.materializedAt, workspace.ownIdentities, workspace.shareCategories) : getMemoriesByProject(options.db, projectPath, ["active", "permanent"], snapshotMarkers.materializedAt) : [];
36396
37173
  const userMemories = safeGetActiveUserMemories(options.db);
36397
37174
  const memoryBudget = options.memoryInjectionBudgetTokens ?? DEFAULT_MEMORY_BUDGET_TOKENS;
@@ -36469,7 +37246,7 @@ function injectM0M1(options) {
36469
37246
  m0Bytes: options.state.cachedM0Bytes,
36470
37247
  m1Text: null
36471
37248
  };
36472
- if (options.state.isSubagent)
37249
+ if (options.state.isSubagent && !options.compactionOff)
36473
37250
  return skipped;
36474
37251
  const decision = mustMaterialize({
36475
37252
  db: options.db,
@@ -36598,14 +37375,14 @@ function onNoteTrigger(db, sessionId, trigger) {
36598
37375
  sessionLog(sessionId, `note-nudge: trigger fired (${trigger}), triggerPending=true`);
36599
37376
  }
36600
37377
  function peekNoteNudgeText(db, sessionId, currentUserMessageId, projectIdentity, noteReadStillVisible) {
36601
- const state = getPersistedNoteNudge(db, sessionId);
36602
- if (!state.triggerPending)
37378
+ const state2 = getPersistedNoteNudge(db, sessionId);
37379
+ if (!state2.triggerPending)
36603
37380
  return null;
36604
- if (!state.triggerMessageId && currentUserMessageId) {
37381
+ if (!state2.triggerMessageId && currentUserMessageId) {
36605
37382
  setPersistedNoteNudgeTriggerMessageId(db, sessionId, currentUserMessageId);
36606
- state.triggerMessageId = currentUserMessageId;
37383
+ state2.triggerMessageId = currentUserMessageId;
36607
37384
  }
36608
- if (state.triggerMessageId && currentUserMessageId && state.triggerMessageId === currentUserMessageId) {
37385
+ if (state2.triggerMessageId && currentUserMessageId && state2.triggerMessageId === currentUserMessageId) {
36609
37386
  sessionLog(sessionId, `note-nudge: deferring — current user message ${currentUserMessageId} is same as trigger-time message`);
36610
37387
  return null;
36611
37388
  }
@@ -36807,29 +37584,29 @@ function callIdFromPart(part) {
36807
37584
  const direct = firstStringField(part, ["callID", "callId", "toolCallId", "tool_call_id", "id"]);
36808
37585
  if (direct)
36809
37586
  return direct;
36810
- const state = isRecord(part.state) ? part.state : null;
36811
- return state ? firstStringField(state, ["callID", "callId", "toolCallId", "tool_call_id", "id"]) ?? "" : "";
37587
+ const state2 = isRecord(part.state) ? part.state : null;
37588
+ return state2 ? firstStringField(state2, ["callID", "callId", "toolCallId", "tool_call_id", "id"]) ?? "" : "";
36812
37589
  }
36813
37590
  function toolSignalFromPart(part) {
36814
37591
  if (!isRecord(part))
36815
37592
  return null;
36816
37593
  const type = partType(part);
36817
- const state = isRecord(part.state) ? part.state : null;
37594
+ const state2 = isRecord(part.state) ? part.state : null;
36818
37595
  const callId = callIdFromPart(part);
36819
37596
  if (!callId && type !== "tool")
36820
37597
  return null;
36821
37598
  if (type === "tool") {
36822
- const hasInput = state !== null && hasOwn(state, "input");
36823
- const outputKey = state ? hasOwn(state, "output") ? "output" : hasOwn(state, "error") ? "error" : hasOwn(state, "result") ? "result" : null : null;
37599
+ const hasInput = state2 !== null && hasOwn(state2, "input");
37600
+ const outputKey = state2 ? hasOwn(state2, "output") ? "output" : hasOwn(state2, "error") ? "error" : hasOwn(state2, "result") ? "result" : null : null;
36824
37601
  const hasOutput = outputKey !== null;
36825
- const outputValue = outputKey && state ? state[outputKey] : undefined;
37602
+ const outputValue = outputKey && state2 ? state2[outputKey] : undefined;
36826
37603
  const providerExecuted = part.providerExecuted === true;
36827
37604
  const openInvocation = !providerExecuted && !hasOutput;
36828
37605
  return {
36829
37606
  callId,
36830
37607
  hasInput: hasInput || openInvocation,
36831
37608
  hasOutput,
36832
- inputText: hasInput && state ? stringValue(state.input) : "",
37609
+ inputText: hasInput && state2 ? stringValue(state2.input) : "",
36833
37610
  outputText: hasOutput ? stringValue(outputValue) : ""
36834
37611
  };
36835
37612
  }
@@ -37057,24 +37834,27 @@ function tokenForMessage(message, options) {
37057
37834
  function buildTrueRawTokenIndex(sessionId, messages, options) {
37058
37835
  const ordered = [...messages].sort((a, b) => a.ordinal - b.ordinal);
37059
37836
  const sliceCount = ordered.length;
37060
- const maxOrdinal = ordered.length > 0 ? ordered[ordered.length - 1].ordinal : 0;
37061
- const rawMessageCount = Math.max(sliceCount, maxOrdinal, options.absoluteMessageCount ?? sliceCount);
37837
+ const firstOrdinal = ordered.length > 0 ? ordered[0].ordinal : 1;
37838
+ const terminalOrdinal = ordered.length > 0 ? ordered[ordered.length - 1].ordinal : 0;
37839
+ const rawMessageCount = Math.max(sliceCount, terminalOrdinal, options.absoluteMessageCount ?? sliceCount);
37840
+ const ordinalSpan = terminalOrdinal >= firstOrdinal ? terminalOrdinal - firstOrdinal + 1 : 0;
37062
37841
  const tokensByOrdinal = new Map;
37063
37842
  const idsByOrdinal = new Map;
37064
- const prefix = new Array(rawMessageCount + 1).fill(0);
37843
+ const prefix = new Array(ordinalSpan + 1).fill(0);
37065
37844
  for (const message of ordered) {
37066
37845
  const stored = options.storedTotalForMessage?.(message);
37067
37846
  const total = stored !== undefined && stored !== null ? stored : tokenForMessage(message, options).total;
37068
37847
  tokensByOrdinal.set(message.ordinal, total);
37069
37848
  idsByOrdinal.set(message.ordinal, message.id);
37070
- if (message.ordinal >= 1 && message.ordinal <= rawMessageCount) {
37071
- prefix[message.ordinal] = total;
37849
+ const relative = message.ordinal - firstOrdinal + 1;
37850
+ if (relative >= 1 && relative <= ordinalSpan) {
37851
+ prefix[relative] = total;
37072
37852
  }
37073
37853
  }
37074
- for (let k = 1;k <= rawMessageCount; k += 1) {
37854
+ for (let k = 1;k <= ordinalSpan; k += 1) {
37075
37855
  prefix[k] += prefix[k - 1];
37076
37856
  }
37077
- const ordinalToIndex = (ordinal) => Math.max(0, Math.min(rawMessageCount, ordinal - 1));
37857
+ const ordinalToIndex = (ordinal) => Math.max(0, Math.min(ordinalSpan, ordinal - firstOrdinal));
37078
37858
  return {
37079
37859
  sessionId,
37080
37860
  providerShapeVersion: options.providerShapeVersion,
@@ -37086,27 +37866,27 @@ function buildTrueRawTokenIndex(sessionId, messages, options) {
37086
37866
  return idsByOrdinal.get(ordinal) ?? null;
37087
37867
  },
37088
37868
  suffixTokensFromOrdinal(ordinal) {
37089
- if (ordinal <= 1)
37090
- return prefix[rawMessageCount];
37091
- if (ordinal > rawMessageCount)
37869
+ if (ordinal <= firstOrdinal)
37870
+ return prefix[ordinalSpan];
37871
+ if (ordinal > terminalOrdinal)
37092
37872
  return 0;
37093
- return prefix[rawMessageCount] - prefix[ordinalToIndex(ordinal)];
37873
+ return prefix[ordinalSpan] - prefix[ordinalToIndex(ordinal)];
37094
37874
  },
37095
37875
  rangeTokens(startInclusive, endExclusive) {
37096
- const start = Math.max(1, startInclusive);
37097
- const end = Math.max(start, Math.min(rawMessageCount + 1, endExclusive));
37098
- return prefix[end - 1] - prefix[start - 1];
37876
+ const start = Math.max(firstOrdinal, startInclusive);
37877
+ const end = Math.max(start, Math.min(terminalOrdinal + 1, endExclusive));
37878
+ return prefix[end - firstOrdinal] - prefix[start - firstOrdinal];
37099
37879
  },
37100
37880
  findSuffixStartForTokens(tokens) {
37101
37881
  if (!Number.isFinite(tokens) || tokens <= 0)
37102
- return rawMessageCount + 1;
37882
+ return terminalOrdinal + 1;
37103
37883
  const target = Math.max(0, Math.floor(tokens));
37104
- const total = prefix[rawMessageCount];
37884
+ const total = prefix[ordinalSpan];
37105
37885
  if (total < target)
37106
- return 1;
37886
+ return firstOrdinal;
37107
37887
  const cut = total - target;
37108
37888
  let lo = 0;
37109
- let hi = rawMessageCount;
37889
+ let hi = ordinalSpan;
37110
37890
  let best = 0;
37111
37891
  while (lo <= hi) {
37112
37892
  const mid = lo + hi >> 1;
@@ -37117,29 +37897,31 @@ function buildTrueRawTokenIndex(sessionId, messages, options) {
37117
37897
  hi = mid - 1;
37118
37898
  }
37119
37899
  }
37120
- return best + 1;
37900
+ return firstOrdinal + best;
37121
37901
  },
37122
37902
  findHeadEndForCap(startInclusive, endExclusive, capTokens) {
37123
- const start = Math.max(1, Math.min(rawMessageCount + 1, startInclusive));
37124
- const end = Math.max(start, Math.min(rawMessageCount + 1, endExclusive));
37903
+ const start = Math.max(firstOrdinal, Math.min(terminalOrdinal + 1, startInclusive));
37904
+ const end = Math.max(start, Math.min(terminalOrdinal + 1, endExclusive));
37125
37905
  if (!Number.isFinite(capTokens) || capTokens <= 0)
37126
37906
  return start;
37127
- const startPrefix = prefix[start - 1];
37128
- const cut = startPrefix + Math.floor(capTokens);
37129
- let lo = start;
37130
- let hi = end - 1;
37131
- let bestEnd = start;
37907
+ const startIndex = start - firstOrdinal;
37908
+ const endIndex = end - firstOrdinal;
37909
+ const cut = prefix[startIndex] + Math.floor(capTokens);
37910
+ let lo = startIndex + 1;
37911
+ let hi = endIndex;
37912
+ let bestEndIndex = startIndex;
37132
37913
  while (lo <= hi) {
37133
37914
  const mid = lo + hi >> 1;
37134
37915
  if (prefix[mid] <= cut) {
37135
- bestEnd = mid + 1;
37916
+ bestEndIndex = mid;
37136
37917
  lo = mid + 1;
37137
37918
  } else {
37138
37919
  hi = mid - 1;
37139
37920
  }
37140
37921
  }
37922
+ let bestEnd = firstOrdinal + bestEndIndex;
37141
37923
  if (bestEnd === start && start < end)
37142
- return start + 1;
37924
+ bestEnd = start + 1;
37143
37925
  return Math.min(bestEnd, end);
37144
37926
  }
37145
37927
  };
@@ -37456,7 +38238,8 @@ function resolveProtectedTailBoundary(ctx) {
37456
38238
  if (ctx.migrationFloorActive)
37457
38239
  runtimeFloor = Math.max(runtimeFloor, ctx.priorBoundaryOrdinal);
37458
38240
  let protectedTailStart = Math.max(boundary, runtimeFloor);
37459
- if (!ctx.emergencyTailScale && usagePercentage < 80) {
38241
+ const forceMaterializationPercentage = escalationBands(ctx.executeThresholdPercentage).forceMaterializationPercentage;
38242
+ if (!ctx.emergencyTailScale && usagePercentage < forceMaterializationPercentage) {
37460
38243
  let lastMeaningfulUserOrdinal = 0;
37461
38244
  for (let i = messages.length - 1;i >= 0; i--) {
37462
38245
  const message = messages[i];
@@ -37697,7 +38480,8 @@ function getRawHistoryEligibility(db, sessionId) {
37697
38480
  function hasRunnableCompartmentWindow(snapshot) {
37698
38481
  if (snapshot.offset >= snapshot.protectedTailStart)
37699
38482
  return false;
37700
- if (snapshot.usagePercentage >= 80 || snapshot.emergencyTailScale) {
38483
+ const forceMaterializationPercentage = escalationBands(snapshot.executeThresholdPercentage).forceMaterializationPercentage;
38484
+ if (snapshot.usagePercentage >= forceMaterializationPercentage || snapshot.emergencyTailScale) {
37701
38485
  return snapshot.trueRawEligibleTokens >= deriveMinForceEligibleTokens(snapshot.N) || snapshot.eligibleEndOrdinal > snapshot.offset;
37702
38486
  }
37703
38487
  return snapshot.eligibleEndOrdinal > snapshot.offset;
@@ -37760,8 +38544,10 @@ function validateBoundarySnapshot(args) {
37760
38544
  return { ok: true };
37761
38545
  }
37762
38546
  function recordHighPressureNoEligibleHead(db, snapshot) {
37763
- if (snapshot.usagePercentage < 80 && !snapshot.emergencyTailScale)
38547
+ const forceMaterializationPercentage = escalationBands(snapshot.executeThresholdPercentage).forceMaterializationPercentage;
38548
+ if (snapshot.usagePercentage < forceMaterializationPercentage && !snapshot.emergencyTailScale) {
37764
38549
  return 0;
38550
+ }
37765
38551
  return recordProtectedTailNoEligibleHead(db, snapshot.sessionId);
37766
38552
  }
37767
38553
 
@@ -39792,6 +40578,7 @@ ${chunkText}`,
39792
40578
  retainDrainReservationForRetryThrottle = true;
39793
40579
  const validatedPass = await runValidatedHistorianPass({
39794
40580
  client,
40581
+ db,
39795
40582
  parentSessionId: sessionId,
39796
40583
  sessionDirectory,
39797
40584
  prompt,
@@ -40252,6 +41039,7 @@ Historian pass ${passCount + 1}, attempt ${passAttempt} started for messages ${c
40252
41039
  emitProgress(`Running historian (pass ${passCount + 1})…`);
40253
41040
  const validatedPass = await runValidatedHistorianPass({
40254
41041
  client,
41042
+ db,
40255
41043
  parentSessionId: sessionId,
40256
41044
  sessionDirectory,
40257
41045
  prompt,
@@ -40671,6 +41459,7 @@ ${chunk.text}`,
40671
41459
  Historian pass ${passCount + 1}, attempt ${passAttempt} started for messages ${chunk.startIndex}-${chunk.endIndex}.`, notifParams());
40672
41460
  const validatedPass = await runValidatedHistorianPass({
40673
41461
  client,
41462
+ db,
40674
41463
  parentSessionId: sessionId,
40675
41464
  sessionDirectory,
40676
41465
  prompt,
@@ -40922,7 +41711,7 @@ async function executeContextRecomp(deps, options = {}) {
40922
41711
  }
40923
41712
 
40924
41713
  // src/hooks/magic-context/lkg-slot.ts
40925
- import { createHash as createHash14 } from "node:crypto";
41714
+ import { createHash as createHash15 } from "node:crypto";
40926
41715
  var LKG_TOTAL_BYTES = 64 * 1024 * 1024;
40927
41716
  var LKG_SINGLE_SLOT_BYTES = 24 * 1024 * 1024;
40928
41717
  var LKG_METADATA_BYTES = 256;
@@ -40933,7 +41722,7 @@ function slotBytes(slot) {
40933
41722
  return 2 * slot.jsonPrefix.length + digestBytes + LKG_METADATA_BYTES;
40934
41723
  }
40935
41724
  function lkgContentDigest(message) {
40936
- const hash2 = createHash14("sha256");
41725
+ const hash2 = createHash15("sha256");
40937
41726
  const seen = new WeakSet;
40938
41727
  const visit = (value) => {
40939
41728
  if (value === null) {
@@ -41299,4 +42088,4 @@ async function runUpgradeMemoryMigration(ctx, sessionId, migrationDirectory) {
41299
42088
  }
41300
42089
  }
41301
42090
 
41302
- export { withContentLanguageDirective, buildPrimaryLanguageDirective, exports_external, DEFAULT_PROTECTED_TAGS, parseCron, nextOccurrence, nextDueAtMs, DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE, DEFAULT_HISTORIAN_TIMEOUT_MS, DEFAULT_LOCAL_EMBEDDING_MODEL, MagicContextConfigSchema, getOpenCodeDbPath, ProjectIdentityError, resolveProjectIdentityStrict, takeDubiousOwnershipProjectIdentityWarning, resolveProjectIdentity, resolveProjectIdentityForSession, normalizeStoredProjectPath, storedPathBelongsToIdentity, recordSessionProjectIdentity, detectOverflow, promptSyncWithValidatedOutputRetry, normalizeSDKResponse, extractLatestAssistantText, hasLengthCappedOutput, setKeepSubagents, shouldKeepSubagents, COMPARTMENT_LEASE_RENEWAL_MS, acquireCompartmentLease, renewCompartmentLease, releaseCompartmentLease, getCompartments, getLastCompartmentEndMessage, getLastCompartmentEndMessageId, clearRecompStaging, registerModuleNoteEvaluationBridge, getModuleNoteEvaluationBridge, getContextStoreUuid, ensureContextStoreUuid, getAuthorityManagedMarker, reconcileAuthorityProject, checksumAuthoritySeedRows, prepareAuthority, drainAuthority, getMirrorCursor, applyMirrorPage, pullMemoryMirrorOnce, V2_MEMORY_CATEGORIES, CATEGORY_PRIORITY, resolveWorkspaceShareCategories, resolveWorkspaceIdentitySet, expandWorkspaceIdentitySetWithAliases, resolveStoredPathWorkspaceIdentity, storedPathBelongsToWorkspace, sourceNameForMemory, computeWorkspaceEpochFingerprint, beginBootQuietPeriod, bootQuietRemainingMs, scheduleAfterBootQuiet, recordToolDefinition, getMeasuredToolDefinitionTokens, getSchemaFenceRejection, getDatabasePath, setSqlitePragmaConfig, runSqliteOptimize, openDatabase, openDatabaseAsync, isDatabasePersisted, getDatabasePersistenceError, recordEmbeddingMeasurement, getMaxM0MutationId, queueMemoryMutation, getMemoryMutationsForRenderByProjects, getMaxMemoryMutationIdForProjects, isEmergencyRecoveryArmed, isProviderOverflowReconfirmed, loadPersistedUsage, loadProtectedTailMeta, resetProtectedTailNoEligibleHead, getWrapupInProgressState, acquireWrapupInProgress, updateWrapupInProgress, releaseWrapupInProgress, getPersistedReasoningWatermark, setPersistedReasoningWatermark, clearPersistedReasoningWatermark, getEmergencyInputSample, setEmergencyDropSample, clearEmergencyDropSample, getLastNudgeUndropped, setLastNudgeUndropped, getLastNudgeLevel, setLastNudgeLevel, resetLastNudgeCycle, resetLastNudgeCycleIfTailShrank, getChannel2NudgeState, getChannel2NudgeClaim, casChannel2NudgeState, claimChannel2NudgeState, casChannel2NudgeClaim, getPersistedNoteNudge, getNoteNudgeAnchors, getAutoSearchHintDecisions, appendAutoSearchHintDecision, pruneNoteNudgeAnchors, pruneAutoSearchHintDecisions, removeNoteNudgeAnchorByMessageId, removeAutoSearchHintDecisionByMessageId, getPersistedTodoSyntheticAnchor, setPersistedTodoSyntheticAnchor, clearPersistedTodoSyntheticAnchor, setNoteLastReadAt, getHistorianFailureState, clearHistorianFailureState, getOverflowState, recordOverflowDetected, recordDetectedContextLimit, clearEmergencyRecovery, clearDetectedContextLimit, getPersistedCompactionMarkerState, getStrippedPlaceholderIds, applyStrippedPlaceholderDelta, removeStrippedPlaceholderId, getStaleReduceStrippedIds, addStaleReduceStrippedIds, getProcessedImageStrippedIds, addProcessedImageStrippedIds, getPendingCompactionMarkerState, clearPendingCompactionMarkerStateIf, peekDeferredExecutePending, setDeferredExecutePendingIfAbsent, clearDeferredExecutePendingIfMatches, getSessionsWithPendingMarker, setSessionWorkMetrics, getNotes, addNote, getSessionNotes, getPendingSmartNotes, getReadySmartNotes, updateNote, dismissNote, markNoteReady, markNoteChecked, queuePendingOp, getPendingOps, removePendingOp, PRIMER_CANDIDATE_TTL_MS, PRIMER_CANDIDATE_MAX_AGE_MS, primerOccurrenceKey, primerOccurrenceUtcDay, updatePrimerCandidateEmbedding, getPrimerCandidatesByIds, getPrimerCandidatesForPromotion, countPrimerCandidatesForProject, getActivePrimers, createPrimer, updatePrimerSupport, updatePrimerAnswer, GLOBAL_USER_PROFILE_PROJECT_PATH, getProjectState, bumpProjectMemoryEpoch, bumpProjectUserProfileVersion, saveSourceContent, replaceSourceContent, getSourceContents, getActiveTagTokenAggregate, AGE_RECLAIM_MIN_TOKENS, getOldestActiveUnprotectedToolTags, getActiveToolTagsForAgeReclaim, getTriggerTagTokenUpperBound, getActiveTagTokenTotalsByMessage, tagTokenCountIsNull, backfillTagTokenCounts, insertTag, updateTagStatus, updateTagDropMode, updateCavemanDepth, updateTagMessageId, deleteTagsByMessageId, getMaxTagNumberBySession, getTagNumberByMessageId, deriveTagLoadFloor, getTagsBySession, getActiveTagsBySession, getDroppedTagsBySession, getTagsByNumbers, getMaxDroppedTagNumber, getToolTagNumberByOwner, getNullOwnerToolTag, adoptNullOwnerToolTag, getCandidateToolOwners, pickNearestPriorOwner, recordChildInvocation, COMPARTMENT_AGENT_SYSTEM_PROMPT, HISTORIAN_EDITOR_SYSTEM_PROMPT, COMPARTMENT_STRUCTURAL_SYSTEM_PROMPT, Priority, AdmissionClass, StaleRouteHandleError, SocketClosedError, SocketTimeoutError, SubcClient, isConsumerReconnectTransient, getCompartmentEvents, loadCompartmentChunkEmbeddingsForSearch, cosineSimilarity, SYNAPSE_DEFAULT_MODEL, SynapseEmbeddingProvider, computeNormalizedHash, saveCommitEmbedding, loadProjectCommitEmbeddings, loadUnembeddedCommits, countEmbeddedCommits, upsertCommits, getLatestIndexedCommitTimeMs, enforceProjectCap, GIT_SWEEP_LEASE_RENEWAL_MS, acquireGitSweepLease, renewGitSweepLease, markGitSweepSuccessAndRelease, parkGitSweepNonIndexable, releaseGitSweepLease, saveEmbeddingIfHashMatches, getProjectEmbeddings, peekProjectEmbeddings, invalidateProject, invalidateMemory, markProjectLoadUntrusted, contentSha256, sweepStaleEmbeddingIdentitiesForProject, registerProjectEmbedding, registerProjectShadowEmbedding, getShadowEmbeddingMeasurementCohort, getPrimaryEmbeddingMeasurementCohort, embedShadowTextForProject, enqueueShadowEmbeddingItems, registerProjectInObservationMode, getProjectEmbeddingSnapshot, embedTextForProject, embedBatchForProject, embedItemsForProject, embedUnembeddedMemoriesForProject, drainCommitBacklogForProject, embedSessionCompartmentChunks, getEmbeddingCoverageStatus, isEmbeddingEnabled, embedText, ensureMemoryEmbeddings, computeCueContentHash, getMuralCueState, memoryNeedsCue, setMuralCue, hasMemoryShareableColumn, hasMemoryClassifiedAtColumn, getUnclassifiedMemoryIds, ModuleMemoryAuthorityError, insertMemory, insertMemoryIdempotent, getMemoryByHash, getMemoriesByProject, buildWorkspaceMemorySqlFilter, getMemoriesByProjects, getMaxMemoryIdForProjects, readNewMemoriesForM1Union, getMemoryById, getMemoriesByIds, updateMemorySeenCount, updateMemoryRetrievalCount, setMemoryClassification, supersededMemory, mergeMemoryStats, archiveMemory, getMemoryCountsByStatus, sanitizeFtsQuery, searchMemoriesFTS, searchMemoriesFTSUnion, recordMemoryMapping, recordMemoryVerifications, getUnmappedMemoryIds, clearMemoryVerifications, getMemoryVerifications, resolveGitTopLevel, readGitHead, readGitChangedFilesSince, readGitFileChangeTimesSince, verificationFileExists, normalizeVerificationFiles, USER_MEMORY_CANDIDATE_TTL_MS, insertUserMemoryCandidates, getUserMemoryCandidates, deleteUserMemoryCandidates, pruneExpiredUserMemoryCandidates, insertUserMemory, getActiveUserMemories, updateUserMemoryContent, dismissUserMemory, MARKER_SUMMARY_TEXT, applyDeferredCompactionMarker, removeCompactionMarkerForSession, checkCompactionMarkerConsistency, getMural, BoundedSessionMap, extractM0Block, formatDate, injectTemporalMarkers, clearInjectionCache, getVisibleMemoryIds, prepareCompartmentInjection, renderCompartmentInjection, mustMaterialize, trimMemoriesToBudgetV2, renderMemoryBlockV2, injectM0M1, onNoteTrigger, peekNoteNudgeText, markNoteNudgeDelivered, clearNoteNudgeTriggerAndCooldown, resetNoteNudgeCooldownOnly, clearNoteNudgeTriggerOnly, estimateTrueRawMessageTokens, invalidateTrueRawTokenCache, RECOVERY_NO_HEAD_LIMIT, resolveOpenCodeProtectedTailBoundary, resolveWrapupProtectedTailBoundary, getRawHistoryEligibility, hasRunnableCompartmentWindow, recordHighPressureNoEligibleHead, runCompartmentAgent, snapRangeToCompartments, lkgContentDigest, captureSlot, getSlot, dropSlot, noteEntry, getActiveCompartmentRun, markActiveCompartmentRunPublished, registerActiveCompartmentRun, startCompartmentAgent, isRecompFailure, isRecompSkip, isRecompComplete, extractRecompReason, contextualizeUpgradeReason, setRecompStarting, setRecompNote, setRecompTerminal, runManagedRecomp, runManagedUpgrade };
42091
+ export { withContentLanguageDirective, buildPrimaryLanguageDirective, exports_external, DEFAULT_PROTECTED_TAGS, parseCron, nextOccurrence, nextDueAtMs, DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE, DEFAULT_HISTORIAN_TIMEOUT_MS, DEFAULT_LOCAL_EMBEDDING_MODEL, MagicContextConfigSchema, getOpenCodeDbPath, removeMcOwnedCompactionMarkers, ProjectIdentityError, resolveProjectIdentityStrict, takeDubiousOwnershipProjectIdentityWarning, resolveProjectIdentity, resolveProjectIdentityForSession, normalizeStoredProjectPath, storedPathBelongsToIdentity, recordSessionProjectIdentity, beginBootQuietPeriod, bootQuietRemainingMs, scheduleAfterBootQuiet, rpcPortDir, rpcPortFilePath, isPidAlive, parseRpcPortFile, registerModuleNoteEvaluationBridge, getModuleNoteEvaluationBridge, getContextStoreUuid, ensureContextStoreUuid, getAuthorityManagedMarker, reconcileAuthorityProject, checksumAuthoritySeedRows, prepareAuthority, drainAuthority, getMirrorCursor, applyMirrorPage, pullMemoryMirrorOnce, V2_MEMORY_CATEGORIES, CATEGORY_PRIORITY, resolveWorkspaceShareCategories, resolveWorkspaceIdentitySet, expandWorkspaceIdentitySetWithAliases, resolveStoredPathWorkspaceIdentity, storedPathBelongsToWorkspace, sourceNameForMemory, computeWorkspaceEpochFingerprint, recordToolDefinition, getMeasuredToolDefinitionTokens, getSchemaFenceRejection, getMigrationOnOpenRefusal, LATEST_SUPPORTED_VERSION, getDatabasePath, getPersistedSchemaVersion, setSqlitePragmaConfig, runSqliteOptimize, openDatabase, openDatabaseAsync, isDatabasePersisted, getDatabasePersistenceError, COMPARTMENT_LEASE_RENEWAL_MS, acquireCompartmentLease, renewCompartmentLease, releaseCompartmentLease, getCompartments, getLastCompartmentEndMessage, getLastCompartmentEndMessageId, clearRecompStaging, recordEmbeddingMeasurement, getMaxM0MutationId, queueMemoryMutation, getMemoryMutationsForRenderByProjects, getMaxMemoryMutationIdForProjects, MAX_EXECUTE_THRESHOLD, escalationBands, isEmergencyRecoveryArmed, isProviderOverflowReconfirmed, loadPersistedUsage, loadProtectedTailMeta, resetProtectedTailNoEligibleHead, getWrapupInProgressState, acquireWrapupInProgress, updateWrapupInProgress, releaseWrapupInProgress, resolveCompactionModeRecord, getCompactionModeRecord, setCompactionModeRecord, getPersistedReasoningWatermark, setPersistedReasoningWatermark, clearPersistedReasoningWatermark, getEmergencyInputSample, setEmergencyDropSample, clearEmergencyDropSample, getLastNudgeUndropped, setLastNudgeUndropped, getLastNudgeLevel, setLastNudgeLevel, resetLastNudgeCycle, resetLastNudgeCycleIfTailShrank, getChannel2NudgeState, getChannel2NudgeClaim, setChannel2NudgeState, casChannel2NudgeState, claimChannel2NudgeState, casChannel2NudgeClaim, getPersistedNoteNudge, getNoteNudgeAnchors, getAutoSearchHintDecisions, appendAutoSearchHintDecision, pruneNoteNudgeAnchors, pruneAutoSearchHintDecisions, removeNoteNudgeAnchorByMessageId, removeAutoSearchHintDecisionByMessageId, getPersistedTodoPermissionDenied, setPersistedTodoPermissionDenied, getPersistedTodoSyntheticAnchor, setPersistedTodoSyntheticAnchor, clearPersistedTodoSyntheticAnchor, setNoteLastReadAt, getHistorianFailureState, clearHistorianFailureState, getOverflowState, recordOverflowDetected, recordDetectedContextLimit, clearEmergencyRecovery, clearDetectedContextLimit, getPersistedCompactionMarkerState, setPersistedCompactionMarkerState, getStrippedPlaceholderIds, applyStrippedPlaceholderDelta, removeStrippedPlaceholderId, getStaleReduceStrippedIds, addStaleReduceStrippedIds, getProcessedImageStrippedIds, addProcessedImageStrippedIds, getPendingCompactionMarkerState, clearPendingCompactionMarkerStateIf, peekDeferredExecutePending, setDeferredExecutePendingIfAbsent, clearDeferredExecutePendingIfMatches, getSessionsWithPendingMarker, setSessionWorkMetrics, getNotes, addNote, getSessionNotes, getPendingSmartNotes, getReadySmartNotes, updateNote, dismissNote, markNoteReady, markNoteChecked, queuePendingOp, getPendingOps, clearPendingOps, removePendingOp, PRIMER_CANDIDATE_TTL_MS, PRIMER_CANDIDATE_MAX_AGE_MS, primerOccurrenceKey, primerOccurrenceUtcDay, updatePrimerCandidateEmbedding, getPrimerCandidatesByIds, getPrimerCandidatesForPromotion, countPrimerCandidatesForProject, getActivePrimers, createPrimer, updatePrimerSupport, updatePrimerAnswer, GLOBAL_USER_PROFILE_PROJECT_PATH, getProjectState, bumpProjectMemoryEpoch, bumpProjectUserProfileVersion, saveSourceContent, replaceSourceContent, getSourceContents, getActiveTagTokenAggregate, AGE_RECLAIM_MIN_TOKENS, getOldestActiveUnprotectedToolTags, getActiveToolTagsForAgeReclaim, getTriggerTagTokenUpperBound, getActiveTagTokenTotalsByMessage, tagTokenCountIsNull, backfillTagTokenCounts, insertTag, updateTagStatus, updateTagDropMode, updateCavemanDepth, updateTagMessageId, deleteTagsByMessageId, getMaxTagNumberBySession, getTagNumberByMessageId, deriveTagLoadFloor, getTagsBySession, getActiveTagsBySession, getDroppedTagsBySession, getTagsByNumbers, getMaxDroppedTagNumber, getToolTagNumberByOwner, getNullOwnerToolTag, adoptNullOwnerToolTag, getCandidateToolOwners, pickNearestPriorOwner, createChildSessionWithFence, detectOverflow, promptSyncWithValidatedOutputRetry, normalizeSDKResponse, extractLatestAssistantText, hasLengthCappedOutput, setKeepSubagents, shouldKeepSubagents, recordChildInvocation, COMPARTMENT_AGENT_SYSTEM_PROMPT, HISTORIAN_EDITOR_SYSTEM_PROMPT, COMPARTMENT_STRUCTURAL_SYSTEM_PROMPT, Priority, AdmissionClass, StaleRouteHandleError, SocketClosedError, SocketTimeoutError, SubcClient, isConsumerReconnectTransient, getCompartmentEvents, loadCompartmentChunkEmbeddingsForSearch, cosineSimilarity, SYNAPSE_DEFAULT_MODEL, SynapseEmbeddingProvider, computeNormalizedHash, saveCommitEmbedding, loadProjectCommitEmbeddings, loadUnembeddedCommits, countEmbeddedCommits, upsertCommits, getLatestIndexedCommitTimeMs, enforceProjectCap, GIT_SWEEP_LEASE_RENEWAL_MS, acquireGitSweepLease, renewGitSweepLease, markGitSweepSuccessAndRelease, parkGitSweepNonIndexable, releaseGitSweepLease, saveEmbeddingIfHashMatches, getProjectEmbeddings, peekProjectEmbeddings, invalidateProject, invalidateMemory, markProjectLoadUntrusted, contentSha256, sweepStaleEmbeddingIdentitiesForProject, registerProjectEmbedding, registerProjectShadowEmbedding, getShadowEmbeddingMeasurementCohort, getPrimaryEmbeddingMeasurementCohort, embedShadowTextForProject, enqueueShadowEmbeddingItems, registerProjectInObservationMode, getProjectEmbeddingSnapshot, embedTextForProject, embedBatchForProject, embedItemsForProject, embedUnembeddedMemoriesForProject, drainCommitBacklogForProject, embedSessionCompartmentChunks, getEmbeddingCoverageStatus, isEmbeddingEnabled, embedText, ensureMemoryEmbeddings, computeCueContentHash, hasMuralCueColumns, getMuralCueState, memoryNeedsCue, setMuralCue, hasMemoryShareableColumn, hasMemoryClassifiedAtColumn, getUnclassifiedMemoryIds, ModuleMemoryAuthorityError, insertMemory, insertMemoryIdempotent, getMemoryByHash, getMemoriesByProject, buildWorkspaceMemorySqlFilter, getMemoriesByProjects, getMaxMemoryIdForProjects, readNewMemoriesForM1Union, getMemoryById, getMemoriesByIds, updateMemorySeenCount, updateMemoryRetrievalCount, setMemoryClassification, supersededMemory, mergeMemoryStats, archiveMemory, getMemoryCountsByStatus, sanitizeFtsQuery, searchMemoriesFTS, searchMemoriesFTSUnion, recordMemoryMapping, recordMemoryVerifications, getUnmappedMemoryIds, clearMemoryVerifications, getMemoryVerifications, resolveGitTopLevel, readGitHead, readGitChangedFilesSince, readGitFileChangeTimesSince, verificationFileExists, normalizeVerificationFiles, USER_MEMORY_CANDIDATE_TTL_MS, insertUserMemoryCandidates, getUserMemoryCandidates, deleteUserMemoryCandidates, pruneExpiredUserMemoryCandidates, insertUserMemory, getActiveUserMemories, updateUserMemoryContent, dismissUserMemory, MARKER_SUMMARY_TEXT, applyDeferredCompactionMarker, removeCompactionMarkerForSession, checkCompactionMarkerConsistency, getMural, BoundedSessionMap, extractM0Block, formatDate, injectTemporalMarkers, clearInjectionCache, getVisibleMemoryIds, prepareCompartmentInjection, renderCompartmentInjection, mustMaterialize, trimMemoriesToBudgetV2, renderMemoryBlockV2, injectM0M1, onNoteTrigger, peekNoteNudgeText, markNoteNudgeDelivered, clearNoteNudgeTriggerAndCooldown, resetNoteNudgeCooldownOnly, clearNoteNudgeTriggerOnly, estimateTrueRawMessageTokens, invalidateTrueRawTokenCache, RECOVERY_NO_HEAD_LIMIT, resolveOpenCodeProtectedTailBoundary, resolveWrapupProtectedTailBoundary, getRawHistoryEligibility, hasRunnableCompartmentWindow, recordHighPressureNoEligibleHead, runCompartmentAgent, snapRangeToCompartments, lkgContentDigest, captureSlot, getSlot, dropSlot, noteEntry, getActiveCompartmentRun, markActiveCompartmentRunPublished, registerActiveCompartmentRun, startCompartmentAgent, isRecompFailure, isRecompSkip, isRecompComplete, extractRecompReason, contextualizeUpgradeReason, setRecompStarting, setRecompNote, setRecompTerminal, runManagedRecomp, runManagedUpgrade };