@cortexkit/opencode-magic-context 0.42.5 → 0.43.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (511) hide show
  1. package/README.md +6 -7
  2. package/dist/agents/dreamer.d.ts +7 -9
  3. package/dist/agents/dreamer.d.ts.map +1 -1
  4. package/dist/agents/hidden-agent-registrations.d.ts.map +1 -1
  5. package/dist/agents/magic-context-prompt.d.ts.map +1 -1
  6. package/dist/config/index.d.ts +10 -1
  7. package/dist/config/index.d.ts.map +1 -1
  8. package/dist/config/live-run-config.d.ts +12 -0
  9. package/dist/config/live-run-config.d.ts.map +1 -0
  10. package/dist/config/live-snapshot.d.ts +32 -0
  11. package/dist/config/live-snapshot.d.ts.map +1 -0
  12. package/dist/config/schema/magic-context.d.ts +13 -2
  13. package/dist/config/schema/magic-context.d.ts.map +1 -1
  14. package/dist/{conflict-warning-hook-jyj54gbe.js → conflict-warning-hook-t2vb0wnx.js} +3 -3
  15. package/dist/{derive-budgets-v1fkhjjr.js → derive-budgets-0sg5vp61.js} +5 -2
  16. package/dist/features/builtin-commands/commands.d.ts +0 -4
  17. package/dist/features/builtin-commands/commands.d.ts.map +1 -1
  18. package/dist/features/magic-context/compaction-marker.d.ts +6 -0
  19. package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
  20. package/dist/features/magic-context/compartment-chunk-embedding.d.ts +4 -1
  21. package/dist/features/magic-context/compartment-chunk-embedding.d.ts.map +1 -1
  22. package/dist/features/magic-context/compartment-lease.d.ts +8 -0
  23. package/dist/features/magic-context/compartment-lease.d.ts.map +1 -1
  24. package/dist/features/magic-context/compartment-storage.d.ts +21 -0
  25. package/dist/features/magic-context/compartment-storage.d.ts.map +1 -1
  26. package/dist/features/magic-context/context-authority.d.ts +37 -3
  27. package/dist/features/magic-context/context-authority.d.ts.map +1 -1
  28. package/dist/features/magic-context/dreamer/classify.d.ts.map +1 -1
  29. package/dist/features/magic-context/dreamer/docs-proposals.d.ts +23 -0
  30. package/dist/features/magic-context/dreamer/docs-proposals.d.ts.map +1 -0
  31. package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts +5 -1
  32. package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts.map +1 -1
  33. package/dist/features/magic-context/dreamer/hidden-single-shot.d.ts +48 -0
  34. package/dist/features/magic-context/dreamer/hidden-single-shot.d.ts.map +1 -0
  35. package/dist/features/magic-context/dreamer/manual-summary.d.ts +7 -0
  36. package/dist/features/magic-context/dreamer/manual-summary.d.ts.map +1 -0
  37. package/dist/features/magic-context/dreamer/map-memories.d.ts.map +1 -1
  38. package/dist/features/magic-context/dreamer/open-opencode-db.d.ts.map +1 -1
  39. package/dist/features/magic-context/dreamer/promote-primers.d.ts +8 -1
  40. package/dist/features/magic-context/dreamer/promote-primers.d.ts.map +1 -1
  41. package/dist/features/magic-context/dreamer/refresh-primers.d.ts.map +1 -1
  42. package/dist/features/magic-context/dreamer/retrospective-orphan-sweep.d.ts +5 -2
  43. package/dist/features/magic-context/dreamer/retrospective-orphan-sweep.d.ts.map +1 -1
  44. package/dist/features/magic-context/dreamer/retrospective-raw-provider.d.ts +22 -13
  45. package/dist/features/magic-context/dreamer/retrospective-raw-provider.d.ts.map +1 -1
  46. package/dist/features/magic-context/dreamer/storage-task-schedule.d.ts +9 -0
  47. package/dist/features/magic-context/dreamer/storage-task-schedule.d.ts.map +1 -1
  48. package/dist/features/magic-context/dreamer/task-config.d.ts.map +1 -1
  49. package/dist/features/magic-context/dreamer/task-executor.d.ts +3 -0
  50. package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
  51. package/dist/features/magic-context/dreamer/task-prompts.d.ts +7 -4
  52. package/dist/features/magic-context/dreamer/task-prompts.d.ts.map +1 -1
  53. package/dist/features/magic-context/dreamer/task-registry.d.ts +53 -2
  54. package/dist/features/magic-context/dreamer/task-registry.d.ts.map +1 -1
  55. package/dist/features/magic-context/dreamer/task-scheduler.d.ts +3 -0
  56. package/dist/features/magic-context/dreamer/task-scheduler.d.ts.map +1 -1
  57. package/dist/features/magic-context/dreamer/tick-failure.d.ts +38 -0
  58. package/dist/features/magic-context/dreamer/tick-failure.d.ts.map +1 -0
  59. package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
  60. package/dist/features/magic-context/git-commits/search-git-commits.d.ts +2 -0
  61. package/dist/features/magic-context/git-commits/search-git-commits.d.ts.map +1 -1
  62. package/dist/features/magic-context/memory/embedding-identity.d.ts +1 -0
  63. package/dist/features/magic-context/memory/embedding-identity.d.ts.map +1 -1
  64. package/dist/features/magic-context/memory/embedding-local.d.ts +1 -0
  65. package/dist/features/magic-context/memory/embedding-local.d.ts.map +1 -1
  66. package/dist/features/magic-context/memory/embedding.d.ts +1 -1
  67. package/dist/features/magic-context/memory/embedding.d.ts.map +1 -1
  68. package/dist/features/magic-context/memory/memory-diagnostics.d.ts +6 -0
  69. package/dist/features/magic-context/memory/memory-diagnostics.d.ts.map +1 -0
  70. package/dist/features/magic-context/memory/memory-selection.d.ts +12 -0
  71. package/dist/features/magic-context/memory/memory-selection.d.ts.map +1 -0
  72. package/dist/features/magic-context/memory/memory-visibility.d.ts +46 -0
  73. package/dist/features/magic-context/memory/memory-visibility.d.ts.map +1 -0
  74. package/dist/features/magic-context/memory/mirror-reembed.d.ts +22 -0
  75. package/dist/features/magic-context/memory/mirror-reembed.d.ts.map +1 -0
  76. package/dist/features/magic-context/memory/project-identity.d.ts +9 -0
  77. package/dist/features/magic-context/memory/project-identity.d.ts.map +1 -1
  78. package/dist/features/magic-context/memory/storage-memory-fts.d.ts +6 -2
  79. package/dist/features/magic-context/memory/storage-memory-fts.d.ts.map +1 -1
  80. package/dist/features/magic-context/memory/storage-memory.d.ts.map +1 -1
  81. package/dist/features/magic-context/memory/transformers-remote-host.d.ts +6 -0
  82. package/dist/features/magic-context/memory/transformers-remote-host.d.ts.map +1 -0
  83. package/dist/features/magic-context/memory/transformers-web-entry.d.ts.map +1 -1
  84. package/dist/features/magic-context/message-fts-rowid-map.d.ts +3 -1
  85. package/dist/features/magic-context/message-fts-rowid-map.d.ts.map +1 -1
  86. package/dist/features/magic-context/message-index-async.d.ts +8 -3
  87. package/dist/features/magic-context/message-index-async.d.ts.map +1 -1
  88. package/dist/features/magic-context/message-index.d.ts +7 -1
  89. package/dist/features/magic-context/message-index.d.ts.map +1 -1
  90. package/dist/features/magic-context/message-time-backfill.d.ts +19 -0
  91. package/dist/features/magic-context/message-time-backfill.d.ts.map +1 -0
  92. package/dist/features/magic-context/migrations.d.ts +16 -0
  93. package/dist/features/magic-context/migrations.d.ts.map +1 -1
  94. package/dist/features/magic-context/mural/compress-cues.d.ts.map +1 -1
  95. package/dist/features/magic-context/mural/storage-mural.d.ts +5 -0
  96. package/dist/features/magic-context/mural/storage-mural.d.ts.map +1 -1
  97. package/dist/features/magic-context/opencode2-relabel.d.ts +132 -0
  98. package/dist/features/magic-context/opencode2-relabel.d.ts.map +1 -0
  99. package/dist/features/magic-context/overflow-detection.d.ts +3 -0
  100. package/dist/features/magic-context/overflow-detection.d.ts.map +1 -1
  101. package/dist/features/magic-context/project-embedding-registry.d.ts +1 -0
  102. package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
  103. package/dist/features/magic-context/protection-window.d.ts +1 -1
  104. package/dist/features/magic-context/protection-window.d.ts.map +1 -1
  105. package/dist/features/magic-context/search.d.ts +6 -0
  106. package/dist/features/magic-context/search.d.ts.map +1 -1
  107. package/dist/features/magic-context/session-decision-calibration.d.ts +31 -0
  108. package/dist/features/magic-context/session-decision-calibration.d.ts.map +1 -0
  109. package/dist/features/magic-context/session-project-backfill.d.ts.map +1 -1
  110. package/dist/features/magic-context/shadow-backfill-state.d.ts +1 -1
  111. package/dist/features/magic-context/shadow-backfill-state.d.ts.map +1 -1
  112. package/dist/features/magic-context/smart-notes/compiler.d.ts +5 -1
  113. package/dist/features/magic-context/smart-notes/compiler.d.ts.map +1 -1
  114. package/dist/features/magic-context/storage-clone.d.ts.map +1 -1
  115. package/dist/features/magic-context/storage-db.d.ts +1 -1
  116. package/dist/features/magic-context/storage-db.d.ts.map +1 -1
  117. package/dist/features/magic-context/storage-historian-runs.d.ts +4 -2
  118. package/dist/features/magic-context/storage-historian-runs.d.ts.map +1 -1
  119. package/dist/features/magic-context/storage-meta-persisted.d.ts +16 -2
  120. package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
  121. package/dist/features/magic-context/storage-meta-shared.d.ts +1 -1
  122. package/dist/features/magic-context/storage-meta-shared.d.ts.map +1 -1
  123. package/dist/features/magic-context/storage-meta.d.ts +1 -1
  124. package/dist/features/magic-context/storage-meta.d.ts.map +1 -1
  125. package/dist/features/magic-context/storage-notes.d.ts +1 -0
  126. package/dist/features/magic-context/storage-notes.d.ts.map +1 -1
  127. package/dist/features/magic-context/storage-replay-document.d.ts +2 -0
  128. package/dist/features/magic-context/storage-replay-document.d.ts.map +1 -1
  129. package/dist/features/magic-context/storage-subagent-invocations.d.ts +1 -1
  130. package/dist/features/magic-context/storage-subagent-invocations.d.ts.map +1 -1
  131. package/dist/features/magic-context/storage-tags.d.ts +42 -4
  132. package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
  133. package/dist/features/magic-context/storage.d.ts +2 -2
  134. package/dist/features/magic-context/storage.d.ts.map +1 -1
  135. package/dist/features/magic-context/store-generation-rebase.d.ts +95 -0
  136. package/dist/features/magic-context/store-generation-rebase.d.ts.map +1 -0
  137. package/dist/features/magic-context/subagent-token-capture.d.ts +1 -0
  138. package/dist/features/magic-context/subagent-token-capture.d.ts.map +1 -1
  139. package/dist/features/magic-context/tagger.d.ts +2 -0
  140. package/dist/features/magic-context/tagger.d.ts.map +1 -1
  141. package/dist/features/magic-context/tool-definition-tokens.d.ts +1 -0
  142. package/dist/features/magic-context/tool-definition-tokens.d.ts.map +1 -1
  143. package/dist/features/magic-context/tool-owner-backfill.d.ts.map +1 -1
  144. package/dist/features/magic-context/user-memory/review-user-memories.d.ts +5 -1
  145. package/dist/features/magic-context/user-memory/review-user-memories.d.ts.map +1 -1
  146. package/dist/hooks/auto-update-checker/index.d.ts.map +1 -1
  147. package/dist/hooks/magic-context/apply-operations.d.ts +10 -1
  148. package/dist/hooks/magic-context/apply-operations.d.ts.map +1 -1
  149. package/dist/hooks/magic-context/cache-busting-signals.d.ts +19 -4
  150. package/dist/hooks/magic-context/cache-busting-signals.d.ts.map +1 -1
  151. package/dist/hooks/magic-context/channel2-delivery.d.ts +8 -0
  152. package/dist/hooks/magic-context/channel2-delivery.d.ts.map +1 -1
  153. package/dist/hooks/magic-context/command-handler.d.ts +5 -4
  154. package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
  155. package/dist/hooks/magic-context/compaction-marker-manager.d.ts.map +1 -1
  156. package/dist/hooks/magic-context/compaction-off-transition.d.ts +1 -0
  157. package/dist/hooks/magic-context/compaction-off-transition.d.ts.map +1 -1
  158. package/dist/hooks/magic-context/compartment-prompt.d.ts +1 -1
  159. package/dist/hooks/magic-context/compartment-prompt.d.ts.map +1 -1
  160. package/dist/hooks/magic-context/compartment-render-epoch.d.ts +3 -1
  161. package/dist/hooks/magic-context/compartment-render-epoch.d.ts.map +1 -1
  162. package/dist/hooks/magic-context/compartment-runner-drop-queue.d.ts +1 -1
  163. package/dist/hooks/magic-context/compartment-runner-drop-queue.d.ts.map +1 -1
  164. package/dist/hooks/magic-context/compartment-runner-historian.d.ts +1 -0
  165. package/dist/hooks/magic-context/compartment-runner-historian.d.ts.map +1 -1
  166. package/dist/hooks/magic-context/compartment-runner-incremental.d.ts +19 -0
  167. package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
  168. package/dist/hooks/magic-context/compartment-runner-recomp.d.ts.map +1 -1
  169. package/dist/hooks/magic-context/compartment-runner-types.d.ts +19 -11
  170. package/dist/hooks/magic-context/compartment-runner-types.d.ts.map +1 -1
  171. package/dist/hooks/magic-context/compartment-runner-validation.d.ts +4 -1
  172. package/dist/hooks/magic-context/compartment-runner-validation.d.ts.map +1 -1
  173. package/dist/hooks/magic-context/compartment-runner.d.ts.map +1 -1
  174. package/dist/hooks/magic-context/compartment-trigger.d.ts.map +1 -1
  175. package/dist/hooks/magic-context/decay-render.d.ts +1 -0
  176. package/dist/hooks/magic-context/decay-render.d.ts.map +1 -1
  177. package/dist/hooks/magic-context/decision-calibration.d.ts +24 -0
  178. package/dist/hooks/magic-context/decision-calibration.d.ts.map +1 -0
  179. package/dist/hooks/magic-context/derive-budgets.d.ts +2 -0
  180. package/dist/hooks/magic-context/derive-budgets.d.ts.map +1 -1
  181. package/dist/hooks/magic-context/dropped-input-guard.d.ts +50 -4
  182. package/dist/hooks/magic-context/dropped-input-guard.d.ts.map +1 -1
  183. package/dist/hooks/magic-context/embed-history-runner.d.ts +30 -0
  184. package/dist/hooks/magic-context/embed-history-runner.d.ts.map +1 -0
  185. package/dist/hooks/magic-context/emergency-drop.d.ts +13 -8
  186. package/dist/hooks/magic-context/emergency-drop.d.ts.map +1 -1
  187. package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
  188. package/dist/hooks/magic-context/event-payloads.d.ts +2 -1
  189. package/dist/hooks/magic-context/event-payloads.d.ts.map +1 -1
  190. package/dist/hooks/magic-context/execute-status.d.ts +2 -1
  191. package/dist/hooks/magic-context/execute-status.d.ts.map +1 -1
  192. package/dist/hooks/magic-context/final-wire-token-estimate.d.ts +12 -4
  193. package/dist/hooks/magic-context/final-wire-token-estimate.d.ts.map +1 -1
  194. package/dist/hooks/magic-context/heuristic-cleanup.d.ts.map +1 -1
  195. package/dist/hooks/magic-context/historian-no-fire-cause.d.ts +5 -0
  196. package/dist/hooks/magic-context/historian-no-fire-cause.d.ts.map +1 -0
  197. package/dist/hooks/magic-context/historian-publish-stage-logger.d.ts +3 -0
  198. package/dist/hooks/magic-context/historian-publish-stage-logger.d.ts.map +1 -0
  199. package/dist/hooks/magic-context/hook-handlers.d.ts +0 -3
  200. package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
  201. package/dist/hooks/magic-context/hook.d.ts +4 -4
  202. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  203. package/dist/hooks/magic-context/host-served-rows.d.ts +58 -0
  204. package/dist/hooks/magic-context/host-served-rows.d.ts.map +1 -0
  205. package/dist/hooks/magic-context/inject-compartments.d.ts +38 -0
  206. package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
  207. package/dist/hooks/magic-context/legacy-compartments.d.ts +20 -0
  208. package/dist/hooks/magic-context/legacy-compartments.d.ts.map +1 -0
  209. package/dist/hooks/magic-context/live-session-state.d.ts +7 -7
  210. package/dist/hooks/magic-context/m0-token-breakdown.d.ts +6 -0
  211. package/dist/hooks/magic-context/m0-token-breakdown.d.ts.map +1 -1
  212. package/dist/hooks/magic-context/maintenance-authority.d.ts +0 -1
  213. package/dist/hooks/magic-context/maintenance-authority.d.ts.map +1 -1
  214. package/dist/hooks/magic-context/module-state-sync.d.ts +4 -1
  215. package/dist/hooks/magic-context/module-state-sync.d.ts.map +1 -1
  216. package/dist/hooks/magic-context/module-transport.d.ts +24 -2
  217. package/dist/hooks/magic-context/module-transport.d.ts.map +1 -1
  218. package/dist/hooks/magic-context/module-wire.d.ts +43 -1
  219. package/dist/hooks/magic-context/module-wire.d.ts.map +1 -1
  220. package/dist/hooks/magic-context/note-nudger.d.ts.map +1 -1
  221. package/dist/hooks/magic-context/postprocess-read-cache.d.ts +8 -0
  222. package/dist/hooks/magic-context/postprocess-read-cache.d.ts.map +1 -0
  223. package/dist/hooks/magic-context/producer-window-guard.d.ts +47 -1
  224. package/dist/hooks/magic-context/producer-window-guard.d.ts.map +1 -1
  225. package/dist/hooks/magic-context/producer-window-test-support.d.ts +14 -0
  226. package/dist/hooks/magic-context/producer-window-test-support.d.ts.map +1 -0
  227. package/dist/hooks/magic-context/protected-tail-boundary.d.ts +2 -0
  228. package/dist/hooks/magic-context/protected-tail-boundary.d.ts.map +1 -1
  229. package/dist/hooks/magic-context/read-session-chunk.d.ts +51 -10
  230. package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
  231. package/dist/hooks/magic-context/read-session-db.d.ts +8 -0
  232. package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
  233. package/dist/hooks/magic-context/read-session-formatting.d.ts +6 -0
  234. package/dist/hooks/magic-context/read-session-formatting.d.ts.map +1 -1
  235. package/dist/hooks/magic-context/read-session-raw.d.ts +4 -0
  236. package/dist/hooks/magic-context/read-session-raw.d.ts.map +1 -1
  237. package/dist/hooks/magic-context/read-session-true-raw-tokens.d.ts +6 -0
  238. package/dist/hooks/magic-context/read-session-true-raw-tokens.d.ts.map +1 -1
  239. package/dist/hooks/magic-context/recomp-orchestrator.d.ts +17 -39
  240. package/dist/hooks/magic-context/recomp-orchestrator.d.ts.map +1 -1
  241. package/dist/hooks/magic-context/rust-mode-transform.d.ts +51 -0
  242. package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
  243. package/dist/hooks/magic-context/rust-refusal-recovery.d.ts +28 -0
  244. package/dist/hooks/magic-context/rust-refusal-recovery.d.ts.map +1 -0
  245. package/dist/hooks/magic-context/sentinel.d.ts.map +1 -1
  246. package/dist/hooks/magic-context/system-prompt-hash.d.ts +6 -7
  247. package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
  248. package/dist/hooks/magic-context/tag-messages.d.ts +21 -1
  249. package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
  250. package/dist/hooks/magic-context/tail-hygiene-walk.d.ts +63 -0
  251. package/dist/hooks/magic-context/tail-hygiene-walk.d.ts.map +1 -1
  252. package/dist/hooks/magic-context/tokenizer-calibration.d.ts +19 -12
  253. package/dist/hooks/magic-context/tokenizer-calibration.d.ts.map +1 -1
  254. package/dist/hooks/magic-context/tool-drop-target.d.ts +52 -1
  255. package/dist/hooks/magic-context/tool-drop-target.d.ts.map +1 -1
  256. package/dist/hooks/magic-context/tool-sweep-policy.d.ts +50 -0
  257. package/dist/hooks/magic-context/tool-sweep-policy.d.ts.map +1 -0
  258. package/dist/hooks/magic-context/transform-compartment-phase.d.ts +20 -1
  259. package/dist/hooks/magic-context/transform-compartment-phase.d.ts.map +1 -1
  260. package/dist/hooks/magic-context/transform-context-state.d.ts +9 -0
  261. package/dist/hooks/magic-context/transform-context-state.d.ts.map +1 -1
  262. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +5 -3
  263. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  264. package/dist/hooks/magic-context/transform.d.ts +44 -4
  265. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  266. package/dist/hooks/magic-context/wrapup-orchestrator.d.ts.map +1 -1
  267. package/dist/{index-f9gem5cr.js → index-8w1skpnm.js} +85 -5
  268. package/dist/index-99sfbrrf.js +170 -0
  269. package/dist/index-9skq8m9y.js +16 -0
  270. package/dist/{index-3wbd8sdq.js → index-d0dh7v0f.js} +28107 -29850
  271. package/dist/{index-d8mgqezq.js → index-rpz2me0v.js} +133 -78
  272. package/dist/{index-p474rw9p.js → index-rvwvdq59.js} +1 -1
  273. package/dist/index-w2ety11c.js +393 -0
  274. package/dist/index-y5145x8k.js +619 -0
  275. package/dist/index-ygwdyntq.js +5407 -0
  276. package/dist/{index-jkrqhc7y.js → index-ykg9sdzz.js} +147 -28
  277. package/dist/index.d.ts.map +1 -1
  278. package/dist/index.js +7065 -3197
  279. package/dist/message-time-backfill-gzjer78y.js +108 -0
  280. package/dist/plugin/dream-timer.d.ts +13 -0
  281. package/dist/plugin/dream-timer.d.ts.map +1 -1
  282. package/dist/plugin/embedding-bootstrap.d.ts.map +1 -1
  283. package/dist/plugin/hooks/create-session-hooks.d.ts +5 -2
  284. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  285. package/dist/plugin/memory-id-translation.d.ts +109 -0
  286. package/dist/plugin/memory-id-translation.d.ts.map +1 -0
  287. package/dist/plugin/messages-transform.d.ts.map +1 -1
  288. package/dist/plugin/rpc-handlers.d.ts +10 -0
  289. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  290. package/dist/plugin/rust-note-backend.d.ts +84 -0
  291. package/dist/plugin/rust-note-backend.d.ts.map +1 -0
  292. package/dist/plugin/rust-tool-backends.d.ts +1 -1
  293. package/dist/plugin/rust-tool-backends.d.ts.map +1 -1
  294. package/dist/plugin/tool-registry.d.ts +1 -0
  295. package/dist/plugin/tool-registry.d.ts.map +1 -1
  296. package/dist/read-session-chunk-ec3jkvhg.js +61 -0
  297. package/dist/{recomp-orchestrator-k20sfpm2.js → recomp-orchestrator-6akjp11f.js} +8 -8
  298. package/dist/{send-session-notification-xnypkxpx.js → send-session-notification-f6gwkesy.js} +2 -2
  299. package/dist/shared/assistant-message-extractor.d.ts +6 -0
  300. package/dist/shared/assistant-message-extractor.d.ts.map +1 -1
  301. package/dist/shared/auto-update-provenance.d.ts +9 -0
  302. package/dist/shared/auto-update-provenance.d.ts.map +1 -0
  303. package/dist/shared/conflict-detector.d.ts +14 -5
  304. package/dist/shared/conflict-detector.d.ts.map +1 -1
  305. package/dist/shared/hidden-variant-warnings.d.ts +5 -0
  306. package/dist/shared/hidden-variant-warnings.d.ts.map +1 -0
  307. package/dist/shared/host-limitations.d.ts +14 -0
  308. package/dist/shared/host-limitations.d.ts.map +1 -0
  309. package/dist/shared/keep-subagents.d.ts +1 -1
  310. package/dist/shared/keep-subagents.d.ts.map +1 -1
  311. package/dist/shared/model-suggestion-retry.d.ts.map +1 -1
  312. package/dist/shared/models-dev-cache.d.ts +1 -0
  313. package/dist/shared/models-dev-cache.d.ts.map +1 -1
  314. package/dist/shared/opencode-config-dir.d.ts +52 -0
  315. package/dist/shared/opencode-config-dir.d.ts.map +1 -1
  316. package/dist/shared/opencode-db-path.d.ts +46 -2
  317. package/dist/shared/opencode-db-path.d.ts.map +1 -1
  318. package/dist/shared/prompt-surface-runtime.d.ts +6 -6
  319. package/dist/shared/prompt-surface-runtime.d.ts.map +1 -1
  320. package/dist/shared/rpc-server.d.ts +10 -0
  321. package/dist/shared/rpc-server.d.ts.map +1 -1
  322. package/dist/shared/rpc-types.d.ts +64 -5
  323. package/dist/shared/rpc-types.d.ts.map +1 -1
  324. package/dist/shared/status-detail-text.d.ts +1 -3
  325. package/dist/shared/status-detail-text.d.ts.map +1 -1
  326. package/dist/shared/status-summary.d.ts +7 -0
  327. package/dist/shared/status-summary.d.ts.map +1 -1
  328. package/dist/shared/status-view.d.ts +229 -0
  329. package/dist/shared/status-view.d.ts.map +1 -0
  330. package/dist/shared/tag-transcript.d.ts.map +1 -1
  331. package/dist/shared/tail-hygiene-status.d.ts +8 -0
  332. package/dist/shared/tail-hygiene-status.d.ts.map +1 -1
  333. package/dist/shared/user-facing-codes.d.ts +32 -7
  334. package/dist/shared/user-facing-codes.d.ts.map +1 -1
  335. package/dist/shared/window-geometry.d.ts +3 -0
  336. package/dist/shared/window-geometry.d.ts.map +1 -1
  337. package/dist/{task-config-cv8k9y8r.js → task-config-ex4nt0q0.js} +1 -1
  338. package/dist/tools/ctx-expand/constants.d.ts +1 -1
  339. package/dist/tools/ctx-expand/constants.d.ts.map +1 -1
  340. package/dist/tools/ctx-expand/mode.d.ts +31 -0
  341. package/dist/tools/ctx-expand/mode.d.ts.map +1 -0
  342. package/dist/tools/ctx-expand/render.d.ts.map +1 -1
  343. package/dist/tools/ctx-expand/tools.d.ts.map +1 -1
  344. package/dist/tools/ctx-memory/constants.d.ts +3 -1
  345. package/dist/tools/ctx-memory/constants.d.ts.map +1 -1
  346. package/dist/tools/ctx-memory/tools.d.ts +1 -0
  347. package/dist/tools/ctx-memory/tools.d.ts.map +1 -1
  348. package/dist/tools/ctx-memory/types.d.ts +2 -2
  349. package/dist/tools/ctx-note/constants.d.ts +1 -1
  350. package/dist/tools/ctx-note/constants.d.ts.map +1 -1
  351. package/dist/tools/ctx-note/render.d.ts +88 -0
  352. package/dist/tools/ctx-note/render.d.ts.map +1 -0
  353. package/dist/tools/ctx-note/tools.d.ts.map +1 -1
  354. package/dist/tools/ctx-note/types.d.ts +1 -1
  355. package/dist/tools/ctx-note/types.d.ts.map +1 -1
  356. package/dist/tools/ctx-reduce/constants.d.ts +1 -1
  357. package/dist/tools/ctx-reduce/constants.d.ts.map +1 -1
  358. package/dist/tools/ctx-search/constants.d.ts +1 -1
  359. package/dist/tools/ctx-search/constants.d.ts.map +1 -1
  360. package/dist/tools/ctx-search/date-range.d.ts +9 -0
  361. package/dist/tools/ctx-search/date-range.d.ts.map +1 -0
  362. package/dist/tools/ctx-search/tools.d.ts.map +1 -1
  363. package/dist/tools/ctx-search/types.d.ts +3 -1
  364. package/dist/tools/ctx-search/types.d.ts.map +1 -1
  365. package/dist/tools/light-descriptions.d.ts +5 -5
  366. package/dist/tools/light-descriptions.d.ts.map +1 -1
  367. package/dist/tools/parameter-descriptions.d.ts +75 -0
  368. package/dist/tools/parameter-descriptions.d.ts.map +1 -0
  369. package/dist/transformers-node-wasm.js +1918 -826
  370. package/dist/transformers-web.js +1736 -636
  371. package/dist/{transformers.node-dpmf3wpx.js → transformers.node-3zqr6k1w.js} +4087 -2898
  372. package/dist/tui/data/context-db.d.ts +19 -7
  373. package/dist/tui/data/context-db.d.ts.map +1 -1
  374. package/dist/tui-compiled/data/context-db.d.ts +19 -7
  375. package/dist/tui-compiled/data/context-db.d.ts.map +1 -1
  376. package/dist/v2/fold/host-media.d.ts +36 -0
  377. package/dist/v2/fold/host-media.d.ts.map +1 -0
  378. package/dist/v2/fold/restore.d.ts +21 -1
  379. package/dist/v2/fold/restore.d.ts.map +1 -1
  380. package/dist/v2/hidden-completion.d.ts +114 -14
  381. package/dist/v2/hidden-completion.d.ts.map +1 -1
  382. package/dist/v2/hooks/commands.d.ts +29 -0
  383. package/dist/v2/hooks/commands.d.ts.map +1 -0
  384. package/dist/v2/hooks/context.d.ts +58 -2
  385. package/dist/v2/hooks/context.d.ts.map +1 -1
  386. package/dist/v2/hooks/deleted-session-tombstones.d.ts +10 -0
  387. package/dist/v2/hooks/deleted-session-tombstones.d.ts.map +1 -0
  388. package/dist/v2/hooks/dream-manual.d.ts +43 -0
  389. package/dist/v2/hooks/dream-manual.d.ts.map +1 -0
  390. package/dist/v2/hooks/dream-trigger.d.ts +7 -0
  391. package/dist/v2/hooks/dream-trigger.d.ts.map +1 -1
  392. package/dist/v2/hooks/hidden-child.d.ts +32 -0
  393. package/dist/v2/hooks/hidden-child.d.ts.map +1 -0
  394. package/dist/v2/hooks/model-limit-cache.d.ts +19 -0
  395. package/dist/v2/hooks/model-limit-cache.d.ts.map +1 -0
  396. package/dist/v2/hooks/payload.d.ts.map +1 -1
  397. package/dist/v2/hooks/provider-admission.d.ts +22 -0
  398. package/dist/v2/hooks/provider-admission.d.ts.map +1 -0
  399. package/dist/v2/hooks/rpc-live-state.d.ts +9 -0
  400. package/dist/v2/hooks/rpc-live-state.d.ts.map +1 -0
  401. package/dist/v2/hooks/store.d.ts +38 -2
  402. package/dist/v2/hooks/store.d.ts.map +1 -1
  403. package/dist/v2/hooks/tools.d.ts +8 -0
  404. package/dist/v2/hooks/tools.d.ts.map +1 -0
  405. package/dist/v2/hooks/types.d.ts +157 -19
  406. package/dist/v2/hooks/types.d.ts.map +1 -1
  407. package/dist/v2/hooks/usage-reading.d.ts +42 -0
  408. package/dist/v2/hooks/usage-reading.d.ts.map +1 -0
  409. package/dist/v2/host-service.d.ts +65 -0
  410. package/dist/v2/host-service.d.ts.map +1 -0
  411. package/dist/v2/server.d.ts +19 -0
  412. package/dist/v2/server.d.ts.map +1 -1
  413. package/dist/v2/server.js +141849 -110533
  414. package/dist/v2/store-reader.d.ts +78 -6
  415. package/dist/v2/store-reader.d.ts.map +1 -1
  416. package/dist/v2/tui/events.d.ts +7 -0
  417. package/dist/v2/tui/events.d.ts.map +1 -0
  418. package/dist/v2/tui/index.d.ts +33 -0
  419. package/dist/v2/tui/index.d.ts.map +1 -0
  420. package/dist/v2/tui/sidebar-mount.d.ts +40 -0
  421. package/dist/v2/tui/sidebar-mount.d.ts.map +1 -0
  422. package/dist/v2/tui/status-dialog-mount.d.ts +29 -0
  423. package/dist/v2/tui/status-dialog-mount.d.ts.map +1 -0
  424. package/dist/v2/tui/types.d.ts +148 -0
  425. package/dist/v2/tui/types.d.ts.map +1 -0
  426. package/dist/wrapup-orchestrator-5akc87gr.js +16 -0
  427. package/package.json +9 -7
  428. package/src/agents/dreamer.ts +7 -16
  429. package/src/agents/hidden-agent-registrations.ts +10 -22
  430. package/src/agents/magic-context-prompt.test.ts +29 -39
  431. package/src/agents/magic-context-prompt.ts +99 -122
  432. package/src/agents/permissions.test.ts +17 -21
  433. package/src/config/index.ts +39 -4
  434. package/src/config/live-run-config.test.ts +237 -0
  435. package/src/config/live-run-config.ts +80 -0
  436. package/src/config/live-schema-drift.test.ts +67 -0
  437. package/src/config/live-snapshot.test.ts +85 -0
  438. package/src/config/live-snapshot.ts +191 -0
  439. package/src/config/protected-tokens.test.ts +40 -0
  440. package/src/config/raw-loader.test.ts +1 -0
  441. package/src/config/schema/magic-context.test.ts +13 -5
  442. package/src/config/schema/magic-context.ts +109 -13
  443. package/src/features/magic-context/dreamer/task-registry.ts +137 -13
  444. package/src/shared/assistant-message-extractor.test.ts +21 -0
  445. package/src/shared/assistant-message-extractor.ts +43 -8
  446. package/src/shared/auto-update-provenance.ts +42 -0
  447. package/src/shared/child-session-teardown.test.ts +38 -3
  448. package/src/shared/child-session-teardown.ts +3 -3
  449. package/src/shared/conflict-detector.test.ts +277 -7
  450. package/src/shared/conflict-detector.ts +221 -80
  451. package/src/shared/hidden-variant-warnings.ts +21 -0
  452. package/src/shared/host-limitations.ts +43 -0
  453. package/src/shared/keep-subagents.ts +6 -6
  454. package/src/shared/model-suggestion-retry.test.ts +43 -0
  455. package/src/shared/model-suggestion-retry.ts +12 -0
  456. package/src/shared/models-dev-cache.test.ts +25 -0
  457. package/src/shared/models-dev-cache.ts +5 -0
  458. package/src/shared/opencode-config-dir.ts +80 -7
  459. package/src/shared/opencode-db-path.test.ts +174 -0
  460. package/src/shared/opencode-db-path.ts +193 -15
  461. package/src/shared/opencode-host-generation.test.ts +29 -0
  462. package/src/shared/prompt-surface-a1-golden.md +142 -215
  463. package/src/shared/prompt-surface-runtime.test.ts +20 -0
  464. package/src/shared/prompt-surface-runtime.ts +7 -5
  465. package/src/shared/rpc-server.ts +18 -0
  466. package/src/shared/rpc-types.ts +63 -4
  467. package/src/shared/status-detail-text.test.ts +52 -18
  468. package/src/shared/status-detail-text.ts +1 -90
  469. package/src/shared/status-summary.ts +37 -2
  470. package/src/shared/status-view.test.ts +441 -0
  471. package/src/shared/status-view.ts +707 -0
  472. package/src/shared/tag-transcript.ts +115 -16
  473. package/src/shared/tail-hygiene-status.ts +9 -1
  474. package/src/shared/user-facing-codes.test.ts +3 -4
  475. package/src/shared/user-facing-codes.ts +33 -8
  476. package/src/shared/window-geometry.test.ts +23 -5
  477. package/src/shared/window-geometry.ts +13 -3
  478. package/src/tui/data/context-db.ts +50 -15
  479. package/src/tui/dialogs/status-dialog-colors.test.ts +58 -0
  480. package/src/tui/dialogs/status-dialog.tsx +288 -0
  481. package/src/tui/entry.mjs +11 -1
  482. package/src/tui/index.tsx +7 -464
  483. package/src/tui/slots/sidebar-content.tsx +21 -5
  484. package/src/tui-compiled/data/context-db.ts +50 -15
  485. package/src/tui-compiled/dialogs/status-dialog.tsx +552 -0
  486. package/src/tui-compiled/index.tsx +43 -1025
  487. package/src/tui-compiled/slots/sidebar-content.tsx +173 -152
  488. package/src/v2/tui/__fixtures__/ga-host-theme.json +160 -0
  489. package/src/v2/tui/events.ts +23 -0
  490. package/src/v2/tui/host-contract.test.ts +251 -0
  491. package/src/v2/tui/index.ts +526 -0
  492. package/src/v2/tui/load-compiled-sidebar.d.mts +59 -0
  493. package/src/v2/tui/load-compiled-sidebar.mjs +24 -0
  494. package/src/v2/tui/load-compiled-status-dialog.d.mts +17 -0
  495. package/src/v2/tui/load-compiled-status-dialog.mjs +16 -0
  496. package/src/v2/tui/sidebar-fallback.test.ts +100 -0
  497. package/src/v2/tui/sidebar-mount.ts +164 -0
  498. package/src/v2/tui/sidebar-text.test.ts +70 -0
  499. package/src/v2/tui/status-dialog-fallback.test.ts +97 -0
  500. package/src/v2/tui/status-dialog-mount.ts +76 -0
  501. package/src/v2/tui/theme-mapping.test.ts +57 -0
  502. package/src/v2/tui/types.ts +132 -0
  503. package/tui.js +1 -0
  504. package/dist/features/magic-context/memory/memory-migration.d.ts +0 -129
  505. package/dist/features/magic-context/memory/memory-migration.d.ts.map +0 -1
  506. package/dist/hooks/magic-context/upgrade-reminder.d.ts +0 -76
  507. package/dist/hooks/magic-context/upgrade-reminder.d.ts.map +0 -1
  508. package/dist/index-1ar7b3e9.js +0 -637
  509. package/dist/index-4wwr6cz0.js +0 -112
  510. package/dist/index-avwt563y.js +0 -62
  511. package/dist/storage-meta-session-x3j0q9qy.js +0 -20
@@ -0,0 +1,191 @@
1
+ import { createHash } from "node:crypto";
2
+ import { readFileSync, statSync } from "node:fs";
3
+
4
+ import { detectConfigFile, parseJsoncRecovering } from "../shared/jsonc-parser";
5
+ import {
6
+ cortexKitProjectConfigBasePath,
7
+ cortexKitUserConfigBasePath,
8
+ } from "./migrate-config-location";
9
+
10
+ export interface ConfigSnapshot<T> {
11
+ readonly generation: number;
12
+ readonly digest: string;
13
+ readonly adoptedAt: number;
14
+ readonly effective: T;
15
+ }
16
+
17
+ export interface ConfigReloadFailure {
18
+ readonly path: string;
19
+ readonly message: string;
20
+ readonly digest: string;
21
+ }
22
+
23
+ interface FileState {
24
+ metadata: string;
25
+ digest: string;
26
+ }
27
+
28
+ /**
29
+ * Publishes a project configuration only after the user and project files parse
30
+ * and the loader assembles the final effective configuration successfully.
31
+ */
32
+ export class LiveConfigReader<T> {
33
+ private snapshot: ConfigSnapshot<T>;
34
+ private files = new Map<string, FileState>();
35
+ private initialized = false;
36
+ private warned = new Set<string>();
37
+ private failure: ConfigReloadFailure | undefined;
38
+
39
+ constructor(
40
+ private readonly directory: string,
41
+ initial: T,
42
+ private readonly load: () => T,
43
+ // Callers pass the host's log sink; the default is silent so a caller that
44
+ // forgets never writes into the host process's stderr.
45
+ private readonly onLog: (message: string) => void = () => {},
46
+ private readonly changedKeys: (previous: T, next: T) => readonly string[] = (
47
+ previous,
48
+ next,
49
+ ) =>
50
+ Object.keys(next as object).filter(
51
+ (key) =>
52
+ JSON.stringify((previous as Record<string, unknown>)[key]) !==
53
+ JSON.stringify((next as Record<string, unknown>)[key]),
54
+ ),
55
+ ) {
56
+ this.snapshot = {
57
+ generation: 1,
58
+ digest: "initial",
59
+ adoptedAt: Date.now(),
60
+ effective: initial,
61
+ };
62
+ }
63
+
64
+ current(): ConfigSnapshot<T> {
65
+ return this.snapshot;
66
+ }
67
+
68
+ lastFailure(): ConfigReloadFailure | undefined {
69
+ return this.failure;
70
+ }
71
+
72
+ poll(): ConfigSnapshot<T> {
73
+ const paths = [
74
+ cortexKitUserConfigBasePath(),
75
+ cortexKitProjectConfigBasePath(this.directory),
76
+ ].map((base) => detectConfigFile(base).path);
77
+ const next = new Map<string, FileState>();
78
+ let changed = paths.some((path) => !this.files.has(path));
79
+ for (const path of paths) {
80
+ let metadata: string;
81
+ try {
82
+ const stat = statSync(path);
83
+ metadata = `${stat.mtimeMs}:${stat.size}:${stat.ino}`;
84
+ } catch (error) {
85
+ if ((error as NodeJS.ErrnoException).code !== "ENOENT") {
86
+ this.reportFailure(path, String(error), error);
87
+ return this.snapshot;
88
+ }
89
+ metadata = "absent";
90
+ }
91
+ const previous = this.files.get(path);
92
+ if (previous?.metadata === metadata) {
93
+ next.set(path, previous);
94
+ continue;
95
+ }
96
+ let content: string;
97
+ try {
98
+ content = metadata === "absent" ? "" : readFileSync(path, "utf8");
99
+ } catch (error) {
100
+ this.reportFailure(path, String(error), error);
101
+ return this.snapshot;
102
+ }
103
+ const digest = createHash("sha256").update(content).digest("hex");
104
+ if (metadata !== "absent") {
105
+ const parsed = parseJsoncRecovering(content);
106
+ if (
107
+ parsed.issues.length ||
108
+ !parsed.value ||
109
+ typeof parsed.value !== "object" ||
110
+ Array.isArray(parsed.value)
111
+ ) {
112
+ const issue = parsed.issues[0];
113
+ this.reportFailure(
114
+ path,
115
+ digest,
116
+ issue
117
+ ? `${issue.line}:${issue.column}: ${issue.message}`
118
+ : "expected an object",
119
+ );
120
+ return this.snapshot;
121
+ }
122
+ }
123
+ next.set(path, { metadata, digest });
124
+ changed ||= previous?.digest !== digest;
125
+ }
126
+ if (!changed) {
127
+ this.files = next;
128
+ return this.snapshot;
129
+ }
130
+ let effective: T;
131
+ try {
132
+ effective = this.load();
133
+ } catch (error) {
134
+ this.reportFailure(paths[0] ?? this.directory, "load", error);
135
+ return this.snapshot;
136
+ }
137
+ // The loader reads both tiers again. A concurrent writer must not let it
138
+ // publish a mixed user/project pair under the metadata staged above.
139
+ for (const path of paths) {
140
+ let metadata = "absent";
141
+ try {
142
+ const stat = statSync(path);
143
+ metadata = `${stat.mtimeMs}:${stat.size}:${stat.ino}`;
144
+ } catch (error) {
145
+ if ((error as NodeJS.ErrnoException).code !== "ENOENT") {
146
+ this.reportFailure(path, String(error), error);
147
+ return this.snapshot;
148
+ }
149
+ }
150
+ if (metadata !== next.get(path)?.metadata) return this.snapshot;
151
+ }
152
+ const digest = createHash("sha256")
153
+ .update(paths.map((path) => `${path}:${next.get(path)?.digest}`).join("\n"))
154
+ .digest("hex");
155
+ this.files = next;
156
+ this.failure = undefined;
157
+ if (!this.initialized) {
158
+ this.initialized = true;
159
+ this.snapshot = {
160
+ generation: 1,
161
+ digest,
162
+ adoptedAt: this.snapshot.adoptedAt,
163
+ effective,
164
+ };
165
+ } else if (this.snapshot.digest !== digest) {
166
+ const keys = this.changedKeys(this.snapshot.effective, effective);
167
+ this.snapshot = {
168
+ generation: this.snapshot.generation + 1,
169
+ digest,
170
+ adoptedAt: Date.now(),
171
+ effective,
172
+ };
173
+ // A file can change (a save, a comment edit) without any setting changing;
174
+ // only a real change is worth a line.
175
+ if (keys.length > 0) {
176
+ this.onLog(
177
+ `config reloaded gen=${this.snapshot.generation} keys=[${keys.join(",")}]`,
178
+ );
179
+ }
180
+ }
181
+ return this.snapshot;
182
+ }
183
+
184
+ private reportFailure(path: string, digest: string, error: unknown): void {
185
+ const message = error instanceof Error ? error.message : String(error);
186
+ this.failure = { path, message, digest };
187
+ if (this.warned.has(`${path}:${digest}`)) return;
188
+ this.warned.add(`${path}:${digest}`);
189
+ this.onLog(`config reload failed ${path}: ${message}`);
190
+ }
191
+ }
@@ -188,6 +188,46 @@ describe("protected_tokens config and derivation", () => {
188
188
  });
189
189
  });
190
190
 
191
+ describe("protected_tokens below-minimum warning", () => {
192
+ it("emits the specific token-floor warning for a numeric value below the schema minimum", () => {
193
+ const recovered = parsePluginConfig({ protected_tokens: 20 });
194
+ const warnings = recovered.configWarnings ?? [];
195
+ expect(warnings.some((w) => w.includes("protected_tokens is a token floor"))).toBe(
196
+ true,
197
+ );
198
+ expect(warnings.some((w) => w.includes('"protected_tokens": invalid value'))).toBe(
199
+ false,
200
+ );
201
+ });
202
+
203
+ it("keeps the generic type message for a string value", () => {
204
+ const recovered = parsePluginConfig({ protected_tokens: "20" });
205
+ const warnings = recovered.configWarnings ?? [];
206
+ expect(warnings.some((w) => w.includes('"protected_tokens": invalid value'))).toBe(
207
+ true,
208
+ );
209
+ expect(warnings.some((w) => w.includes("protected_tokens is a token floor"))).toBe(
210
+ false,
211
+ );
212
+ });
213
+
214
+ it("keeps the generic above-max message for a value above the maximum", () => {
215
+ const recovered = parsePluginConfig({ protected_tokens: 2_000_000 });
216
+ const warnings = recovered.configWarnings ?? [];
217
+ expect(warnings.some((w) => w.includes('"protected_tokens": invalid value'))).toBe(
218
+ true,
219
+ );
220
+ expect(warnings.some((w) => w.includes("protected_tokens is a token floor"))).toBe(
221
+ false,
222
+ );
223
+ });
224
+
225
+ it("emits no warning when the key is absent", () => {
226
+ const recovered = parsePluginConfig({});
227
+ expect(recovered.configWarnings ?? []).toEqual([]);
228
+ });
229
+ });
230
+
191
231
  describe("protected_tags deprecation", () => {
192
232
  it("is parsed at any value (including 0 and 101) with parse succeeding and no numeric conversion", () => {
193
233
  resetProtectedTagsDeprecationWarningForTest();
@@ -168,6 +168,7 @@ describe("per-harness raw config migration", () => {
168
168
  const taskRetained = {
169
169
  schedule: "0 3 * * *",
170
170
  promotion_threshold: 4,
171
+ recency_days: 30,
171
172
  };
172
173
  expect(Object.keys(historianRetained)).toEqual(
173
174
  PER_HARNESS_MIGRATION_INVENTORY.historian.retained,
@@ -191,12 +191,20 @@ describe("MagicContextConfigSchema", () => {
191
191
  expect(result.dreamer?.tasks.retrospective.schedule).toBe("0 5 * * *");
192
192
  });
193
193
 
194
- it("defaults classify-memories and retrospective on daily in dreamer task metadata", () => {
195
- const result = MagicContextConfigSchema.parse({
194
+ it("defaults retrospective to a 30-day source window and accepts an override", () => {
195
+ const defaults = MagicContextConfigSchema.parse({
196
196
  dreamer: { opencode: { model: "x/y" } },
197
197
  });
198
- expect(result.dreamer?.tasks["classify-memories"].schedule).toBe("0 6 * * *");
199
- expect(result.dreamer?.tasks.retrospective.schedule).toBe("0 5 * * *");
198
+ expect(defaults.dreamer?.tasks["classify-memories"].schedule).toBe("0 6 * * *");
199
+ expect(defaults.dreamer?.tasks.retrospective.schedule).toBe("0 5 * * *");
200
+ expect(defaults.dreamer?.tasks.retrospective.recency_days).toBe(30);
201
+
202
+ const overridden = MagicContextConfigSchema.parse({
203
+ dreamer: {
204
+ tasks: { retrospective: { schedule: "0 5 * * *", recency_days: 14 } },
205
+ },
206
+ });
207
+ expect(overridden.dreamer?.tasks.retrospective.recency_days).toBe(14);
200
208
  });
201
209
 
202
210
  it("parses both transform modes", () => {
@@ -449,7 +457,7 @@ describe("MagicContextConfigSchema", () => {
449
457
  migrated_execution: ["model", "fallback_models", "variant", "thinking_level"],
450
458
  },
451
459
  task: {
452
- retained: ["schedule", "promotion_threshold"],
460
+ retained: ["schedule", "promotion_threshold", "recency_days"],
453
461
  migrated_execution: [
454
462
  "model",
455
463
  "fallback_models",
@@ -18,6 +18,11 @@ export const EXECUTE_THRESHOLD_CAP_MESSAGE =
18
18
  export const DEFAULT_HISTORIAN_TIMEOUT_MS = 600_000;
19
19
  export const DEFAULT_HISTORY_BUDGET_PERCENTAGE = 0.15;
20
20
 
21
+ // Minimum absolute token floor for protected_tokens. Kept as a named constant so
22
+ // the schema's `.min()` and the loader's below-minimum warning share ONE source
23
+ // of truth — the loader must not duplicate the literal 4000.
24
+ export const PROTECTED_TOKENS_MIN = 4000;
25
+
21
26
  export const DEFAULT_LOCAL_EMBEDDING_MODEL = "Xenova/all-MiniLM-L6-v2";
22
27
 
23
28
  // Re-exported from the (DB-free) task registry so the schema and the runtime
@@ -151,7 +156,7 @@ export const PER_HARNESS_MIGRATION_INVENTORY = {
151
156
  migrated_execution: ["model", "fallback_models", "variant", "thinking_level"],
152
157
  },
153
158
  task: {
154
- retained: ["schedule", "promotion_threshold"],
159
+ retained: ["schedule", "promotion_threshold", "recency_days"],
155
160
  migrated_execution: [
156
161
  "model",
157
162
  "fallback_models",
@@ -507,6 +512,15 @@ const ReviewUserMemoriesTaskConfigSchema = DreamTaskBaseConfigSchema.extend({
507
512
  const PromotePrimersTaskConfigSchema = DreamTaskBaseConfigSchema.extend({
508
513
  promotion_threshold: PrimerPromotionThresholdSchema,
509
514
  });
515
+ const RetrospectiveTaskConfigSchema = DreamTaskBaseConfigSchema.extend({
516
+ recency_days: z
517
+ .number()
518
+ .int()
519
+ .min(1)
520
+ .max(3650)
521
+ .default(30)
522
+ .describe("retrospective: collect source messages from only the most recent N days"),
523
+ });
510
524
  export type DreamTaskConfig = z.infer<typeof DreamTaskConfigSchema>;
511
525
 
512
526
  /** Default schedule per task. Preserves v1 behavior: verify runs nightly;
@@ -561,12 +575,22 @@ export const DreamTasksSchema = z
561
575
  "classify-memories": DreamTaskBaseConfigSchema.default(() =>
562
576
  DreamTaskBaseConfigSchema.parse(defaultTaskConfig("classify-memories")),
563
577
  ),
564
- retrospective: DreamTaskBaseConfigSchema.default(() =>
565
- DreamTaskBaseConfigSchema.parse(defaultTaskConfig("retrospective")),
566
- ),
567
- "maintain-docs": DreamTaskBaseConfigSchema.default(() =>
568
- DreamTaskBaseConfigSchema.parse(defaultTaskConfig("maintain-docs")),
578
+ retrospective: RetrospectiveTaskConfigSchema.default(() =>
579
+ RetrospectiveTaskConfigSchema.parse(defaultTaskConfig("retrospective")),
569
580
  ),
581
+ "maintain-docs": DreamTaskBaseConfigSchema.extend({
582
+ max_tokens: z
583
+ .number()
584
+ .int()
585
+ .positive()
586
+ .default(12000)
587
+ .describe(
588
+ "Maximum combined token count of proposed ARCHITECTURE.md and STRUCTURE.md",
589
+ ),
590
+ }).default(() => ({
591
+ ...DreamTaskBaseConfigSchema.parse(defaultTaskConfig("maintain-docs")),
592
+ max_tokens: 12000,
593
+ })),
570
594
  "evaluate-smart-notes": DreamTaskBaseConfigSchema.default(() =>
571
595
  DreamTaskBaseConfigSchema.parse(defaultTaskConfig("evaluate-smart-notes")),
572
596
  ),
@@ -920,7 +944,7 @@ export interface MagicContextConfig {
920
944
  * Graduated from `experimental.temporal_awareness`; default: true. */
921
945
  temporal_awareness: boolean;
922
946
  /** Debug: when true, keep the child sessions Magic Context spawns for its
923
- * own subagents (historian, dreamer, memory-migration) instead
947
+ * own subagents (historian, dreamer) instead
924
948
  * of deleting them on success. For short-term inspection/data collection;
925
949
  * kept sessions accumulate until manually cleared. Default false. */
926
950
  keep_subagents: boolean;
@@ -1107,10 +1131,10 @@ export const MagicContextConfigSchema = z
1107
1131
  .union([z.string(), z.object({ default: z.string() }).catchall(z.string())])
1108
1132
  .default("5m")
1109
1133
  .describe(
1110
- 'How long Magic Context assumes the provider\'s cached prefix stays valid. This is MC\'s own deferral gate — it does not change the provider\'s actual cache lifetime. String (e.g. "5m", "1h", "30s") or per-model object ({ default: "5m", "model-id": "10m" }). Set to "never" to mean MC never assumes expiry (for lanes kept warm externally by a cache-keep tool) — disables the idle-TTL heuristic so MC never initiates a rebuild based on elapsed time. Provider-side extended TTL is a separate request-level concern (cache_control: { ttl } in the request body).',
1134
+ 'How long Magic Context assumes the provider\'s cached prefix stays valid. This is MC\'s own deferral gate — it does not change the provider\'s actual cache lifetime. String (e.g. "5m", "1h", "30s") or per-model object ({ default: "5m", "provider/model": "1h", "provider/*": "never" }); keys resolve most-specific first (exact provider/model, bare model ID, shorter dash-prefixes, then the provider/* wildcard, then default). Set to "never" to mean MC never assumes expiry (for lanes kept warm externally by a cache-keep tool) — disables the idle-TTL heuristic so MC never initiates a rebuild based on elapsed time. Provider-side extended TTL is a separate request-level concern (cache_control: { ttl } in the request body).',
1111
1135
  ),
1112
1136
  prompt_surface: PromptSurfaceConfigSchema.default({ default: "full" }).describe(
1113
- "Prompt-surface presets: default is full; models use bare model IDs, provider/model, or provider/* routing keys. Guidance and tool-description overrides are user-level only. On OpenCode and Pi, per-model routing applies to the guidance block only: tool descriptions are registered once per process, so they follow the default preset (a v1 plugin-surface limitation; per-model tool descriptions are planned for the OpenCode v2 plugin API once the SDK stabilizes).",
1137
+ "Prompt-surface presets: default is full; models use bare model IDs, provider/model, or provider/* routing keys. Guidance and tool-description overrides are user-level only. OpenCode 1.x, Pi, and OMP register tool descriptions once per process (they follow the default preset). OpenCode 2 rewrites the five ctx_* descriptions per request from the draft model.",
1114
1138
  ),
1115
1139
  output_reserve: z
1116
1140
  .union([
@@ -1160,7 +1184,7 @@ export const MagicContextConfigSchema = z
1160
1184
  protected_tokens: z
1161
1185
  .number()
1162
1186
  .int()
1163
- .min(4000)
1187
+ .min(PROTECTED_TOKENS_MIN)
1164
1188
  .max(1_000_000)
1165
1189
  .optional()
1166
1190
  .describe(
@@ -1190,7 +1214,9 @@ export const MagicContextConfigSchema = z
1190
1214
  .number()
1191
1215
  .min(60_000)
1192
1216
  .default(DEFAULT_HISTORIAN_TIMEOUT_MS)
1193
- .describe("Timeout for each historian prompt call in milliseconds (default: 600000)"),
1217
+ .describe(
1218
+ "Timeout for each historian prompt call in both TypeScript and Rust transform modes, in milliseconds (default: 600000)",
1219
+ ),
1194
1220
  commit_cluster_trigger: z
1195
1221
  .object({
1196
1222
  enabled: z
@@ -1306,7 +1332,7 @@ export const MagicContextConfigSchema = z
1306
1332
  .boolean()
1307
1333
  .default(false)
1308
1334
  .describe(
1309
- "Debug: keep the child sessions Magic Context spawns for its own subagents (historian, dreamer, 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.",
1335
+ "Debug: keep every settled Magic Context child session instead of deleting it after success: historian, all Dreamer tasks, smart-note evaluation and compilation, user-memory review, and memory migration. Kept Dreamer children can contain memory-pool text and user messages from other sessions of the same operator; 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. On OpenCode 2, one hidden session holds many runs; it is kept once any of its runs settled, and only a Dreamer session none of whose runs settled is still deleted.",
1310
1336
  ),
1311
1337
  debug_rpc: z
1312
1338
  .boolean()
@@ -1326,7 +1352,7 @@ export const MagicContextConfigSchema = z
1326
1352
  .boolean()
1327
1353
  .default(true)
1328
1354
  .describe(
1329
- "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. 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.",
1355
+ "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. 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, and /ctx-flush 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.",
1330
1356
  ),
1331
1357
  })
1332
1358
  .default({ enabled: true })
@@ -1485,6 +1511,76 @@ export const MagicContextConfigSchema = z
1485
1511
  };
1486
1512
  });
1487
1513
 
1514
+ /** Settings whose fresh values can be used by later agent runs without changing rendered prompt bytes. */
1515
+ export const LIVE_RELOAD_CONFIG_PATHS = [
1516
+ "mural.model",
1517
+ "toast_duration_ms",
1518
+ "historian.opencode.model",
1519
+ "historian.opencode.fallback_models",
1520
+ "historian.opencode.variant",
1521
+ "historian.pi.model",
1522
+ "historian.pi.fallback_models",
1523
+ "historian.pi.thinking_level",
1524
+ "historian.omp.model",
1525
+ "historian.omp.fallback_models",
1526
+ "historian.omp.thinking_level",
1527
+ "historian.two_pass",
1528
+ "historian_timeout_ms",
1529
+ "commit_cluster_trigger.enabled",
1530
+ "commit_cluster_trigger.min_clusters",
1531
+ "memory.auto_promote",
1532
+ "dreamer.opencode.model",
1533
+ "dreamer.opencode.fallback_models",
1534
+ "dreamer.opencode.variant",
1535
+ "dreamer.opencode.tasks",
1536
+ "dreamer.pi.model",
1537
+ "dreamer.pi.fallback_models",
1538
+ "dreamer.pi.thinking_level",
1539
+ "dreamer.pi.tasks",
1540
+ "dreamer.omp.model",
1541
+ "dreamer.omp.fallback_models",
1542
+ "dreamer.omp.thinking_level",
1543
+ "dreamer.omp.tasks",
1544
+ "dreamer.tasks.map-memories.schedule",
1545
+ "dreamer.tasks.verify.schedule",
1546
+ "dreamer.tasks.verify-broad.schedule",
1547
+ "dreamer.tasks.curate.schedule",
1548
+ "dreamer.tasks.compress-cues.schedule",
1549
+ "dreamer.tasks.classify-memories.schedule",
1550
+ "dreamer.tasks.retrospective.schedule",
1551
+ "dreamer.tasks.retrospective.recency_days",
1552
+ "dreamer.tasks.maintain-docs.schedule",
1553
+ "dreamer.tasks.evaluate-smart-notes.schedule",
1554
+ "dreamer.tasks.review-user-memories.schedule",
1555
+ "dreamer.tasks.review-user-memories.promotion_threshold",
1556
+ "dreamer.tasks.promote-primers.schedule",
1557
+ "dreamer.tasks.promote-primers.promotion_threshold",
1558
+ "dreamer.tasks.refresh-primers.schedule",
1559
+ "memory.git_commit_indexing.enabled",
1560
+ "memory.git_commit_indexing.since_days",
1561
+ "memory.git_commit_indexing.max_commits",
1562
+ ] as const;
1563
+
1564
+ // Mark the input schema nodes, not their parsed defaults, so the JSON schema,
1565
+ // runtime projection, docs and dashboard all share one policy source.
1566
+ for (const path of LIVE_RELOAD_CONFIG_PATHS) {
1567
+ let node: z.ZodType = MagicContextConfigSchema._def.in as z.ZodType;
1568
+ for (const part of path.split(".")) {
1569
+ while (
1570
+ node instanceof z.ZodOptional ||
1571
+ node instanceof z.ZodDefault ||
1572
+ node instanceof z.ZodNullable
1573
+ ) {
1574
+ node = node.unwrap() as z.ZodType;
1575
+ }
1576
+ if (!(node instanceof z.ZodObject) || !(part in node.shape)) {
1577
+ throw new Error(`Unknown live config path: ${path}`);
1578
+ }
1579
+ node = node.shape[part] as z.ZodType;
1580
+ }
1581
+ z.globalRegistry.add(node, { ...node.meta(), "x-mc-live-reload": true });
1582
+ }
1583
+
1488
1584
  /**
1489
1585
  * Derived default protected_tokens formula:
1490
1586
  * clamp(round(0.05 × usableSoft), min(16000, round(0.08 × usableSoft)), 64000)
@@ -29,25 +29,102 @@ export const CANONICAL_DREAM_TASKS = [
29
29
 
30
30
  export type DreamTaskName = (typeof CANONICAL_DREAM_TASKS)[number];
31
31
 
32
- export const DREAM_TASK_CAPABILITIES: Record<DreamTaskName, { requiresTools: boolean }> = {
32
+ /**
33
+ * How a Dreamer task reaches its result, which is what decides whether a host
34
+ * without a tool loop can run it:
35
+ * - "tool-loop": the task drives an agent that must call tools between model
36
+ * turns (reading files, searching, writing memories through `ctx_memory`).
37
+ * - "single-shot": one or more no-tool completions whose entire answer is the
38
+ * returned text. Any transport that can deliver a prompt and return text runs
39
+ * these, including a hidden completion carrier.
40
+ * - "host-only": no model call at all. The task is database work done in this
41
+ * process, so it needs no completion transport whatsoever.
42
+ */
43
+ export type DreamTaskTransport = "tool-loop" | "single-shot" | "host-only";
44
+
45
+ export interface DreamTaskCapability {
46
+ /** True only when the task cannot finish without a tool loop. */
47
+ requiresTools: boolean;
48
+ transport: DreamTaskTransport;
49
+ /**
50
+ * What the tool loop is needed FOR, as one clause a user can read. Present
51
+ * only on tool-loop tasks, where it becomes the named per-task reason shown
52
+ * when a host refuses the task instead of a single anonymous "filtered" list.
53
+ */
54
+ toolLoopPurpose?: string;
55
+ }
56
+
57
+ export const DREAM_TASK_CAPABILITIES: Record<DreamTaskName, DreamTaskCapability> = {
33
58
  // A single manifest is not a tool-free task: mapping and verification need
34
59
  // read-only tools to inspect backing code before they can change memory state.
35
- "map-memories": { requiresTools: true },
36
- verify: { requiresTools: true },
37
- "verify-broad": { requiresTools: true },
38
- curate: { requiresTools: true },
60
+ "map-memories": {
61
+ requiresTools: true,
62
+ transport: "tool-loop",
63
+ toolLoopPurpose: "needs read-only file tools to locate the code each memory describes",
64
+ },
65
+ verify: {
66
+ requiresTools: true,
67
+ transport: "tool-loop",
68
+ toolLoopPurpose: "needs read-only file tools to re-check each memory against the code",
69
+ },
70
+ "verify-broad": {
71
+ requiresTools: true,
72
+ transport: "tool-loop",
73
+ toolLoopPurpose: "needs read-only file tools to re-check each memory against the code",
74
+ },
75
+ curate: {
76
+ requiresTools: true,
77
+ transport: "tool-loop",
78
+ toolLoopPurpose: "needs the ctx_memory tool to apply its merge and archive decisions",
79
+ },
39
80
  // mural/compress-cues.ts is a zero-tool transform; its child transport
40
81
  // still needs substitution before the generate executor can dispatch it.
41
- "compress-cues": { requiresTools: false },
42
- "classify-memories": { requiresTools: false },
43
- retrospective: { requiresTools: true },
44
- "maintain-docs": { requiresTools: true },
45
- "evaluate-smart-notes": { requiresTools: true },
46
- "review-user-memories": { requiresTools: true },
47
- "promote-primers": { requiresTools: true },
48
- "refresh-primers": { requiresTools: true },
82
+ "compress-cues": { requiresTools: false, transport: "single-shot" },
83
+ "classify-memories": { requiresTools: false, transport: "single-shot" },
84
+ retrospective: {
85
+ requiresTools: true,
86
+ transport: "tool-loop",
87
+ toolLoopPurpose: "needs search tools to investigate the friction it finds in past sessions",
88
+ },
89
+ "maintain-docs": {
90
+ requiresTools: true,
91
+ transport: "tool-loop",
92
+ toolLoopPurpose: "needs file read and write tools to update project documentation",
93
+ },
94
+ // The evaluator is a no-tool compiler plus a no-tool confirmation prompt; the
95
+ // generated check runs in the local capability sandbox, never as model tools.
96
+ "evaluate-smart-notes": { requiresTools: false, transport: "single-shot" },
97
+ // The reviewer reads candidate text and answers with JSON; the host applies it.
98
+ "review-user-memories": { requiresTools: false, transport: "single-shot" },
99
+ // Promotion clusters existing candidates and writes rows. It calls no model.
100
+ "promote-primers": { requiresTools: false, transport: "host-only" },
101
+ "refresh-primers": {
102
+ requiresTools: true,
103
+ transport: "tool-loop",
104
+ toolLoopPurpose: "needs read-only investigation tools to answer each standing question",
105
+ },
49
106
  };
50
107
 
108
+ /** Tasks a host without a tool loop cannot run, in canonical order. */
109
+ export function toolLoopDreamTasks(): DreamTaskName[] {
110
+ return CANONICAL_DREAM_TASKS.filter((task) => DREAM_TASK_CAPABILITIES[task].requiresTools);
111
+ }
112
+
113
+ /**
114
+ * One line per refused task, naming the task, the stable code and what the tool
115
+ * loop is needed for. A user reading /ctx-dream or /ctx-status output should be
116
+ * able to tell which specific task is unavailable and why, rather than seeing a
117
+ * single anonymous "unsupported" list.
118
+ */
119
+ export function formatUnsupportedDreamTasks(tasks: readonly DreamTaskName[], code: string): string {
120
+ return tasks
121
+ .map((task) => {
122
+ const purpose = DREAM_TASK_CAPABILITIES[task].toolLoopPurpose;
123
+ return `- ${task}: unavailable on this host (${code})${purpose ? ` — ${purpose}` : ""}`;
124
+ })
125
+ .join("\n");
126
+ }
127
+
51
128
  /** Cheap, read-only work counts for one Dreamer task. */
52
129
  export interface DreamTaskBacklog {
53
130
  /** Items selected by the task's current backlog predicate. */
@@ -78,6 +155,53 @@ export function formatDreamTaskBacklogs(
78
155
  .join("\n");
79
156
  }
80
157
 
158
+ /** One dreamer task whose last scheduled run failed. */
159
+ export interface DreamTaskFailureState {
160
+ task: string;
161
+ /** The scheduler's recorded failure text. */
162
+ error: string;
163
+ /** Epoch ms of the last run that SUCCEEDED, or null if none ever has. A failed run
164
+ * never advances `last_run_at`, so this says how long the task has been stuck, not
165
+ * when it last failed — the scheduler keeps no failure timestamp. */
166
+ lastSucceededAt: number | null;
167
+ /** Consecutive retries queued so far; reset once the retry cap pushes the task to
168
+ * its next cron slot, so a long-running failure oscillates rather than climbs. */
169
+ retryCount: number;
170
+ }
171
+
172
+ /** How much of a scheduler failure message a status line carries before eliding. */
173
+ const FAILURE_TEXT_BUDGET = 180;
174
+
175
+ function sinceLabel(lastSucceededAt: number | null, now: number): string {
176
+ if (lastSucceededAt === null || lastSucceededAt <= 0) return "never succeeded";
177
+ const hours = Math.max(0, Math.floor((now - lastSucceededAt) / 3_600_000));
178
+ if (hours < 1) return "last succeeded under an hour ago";
179
+ if (hours < 48) return `last succeeded ${hours}h ago`;
180
+ return `last succeeded ${Math.floor(hours / 24)}d ago`;
181
+ }
182
+
183
+ /**
184
+ * One line per failing task, shared by the status surfaces.
185
+ *
186
+ * The elapsed time is measured from the last SUCCESS, not the last failure: a failed
187
+ * run deliberately does not advance `last_run_at`, so that is the only timestamp the
188
+ * scheduler keeps and "stuck since" is what a reader needs anyway.
189
+ */
190
+ export function formatDreamTaskFailures(
191
+ failures: readonly DreamTaskFailureState[],
192
+ now: number = Date.now(),
193
+ ): string {
194
+ return failures
195
+ .map((failure) => {
196
+ const error =
197
+ failure.error.length > FAILURE_TEXT_BUDGET
198
+ ? `${failure.error.slice(0, FAILURE_TEXT_BUDGET)}…`
199
+ : failure.error;
200
+ return `- ${failure.task}: failing (${sinceLabel(failure.lastSucceededAt, now)}) — ${error}`;
201
+ })
202
+ .join("\n");
203
+ }
204
+
81
205
  /** Process-local progress for the task currently applying a run chunk. */
82
206
  export interface DreamTaskProgress {
83
207
  task: DreamTaskName;