@getrift/rift 0.1.0-beta.21 → 0.1.0-beta.23

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 (320) hide show
  1. package/README.md +7 -3
  2. package/dist/src/capture/auto-capture.d.ts +105 -4
  3. package/dist/src/capture/auto-capture.d.ts.map +1 -1
  4. package/dist/src/capture/auto-capture.js +313 -34
  5. package/dist/src/capture/auto-capture.js.map +1 -1
  6. package/dist/src/capture/claude-cli-triage-provider.d.ts +28 -0
  7. package/dist/src/capture/claude-cli-triage-provider.d.ts.map +1 -0
  8. package/dist/src/capture/claude-cli-triage-provider.js +88 -0
  9. package/dist/src/capture/claude-cli-triage-provider.js.map +1 -0
  10. package/dist/src/capture/codex-cli-triage-provider.d.ts.map +1 -1
  11. package/dist/src/capture/codex-cli-triage-provider.js +1 -33
  12. package/dist/src/capture/codex-cli-triage-provider.js.map +1 -1
  13. package/dist/src/capture/cursor-capture.d.ts +89 -0
  14. package/dist/src/capture/cursor-capture.d.ts.map +1 -0
  15. package/dist/src/capture/cursor-capture.js +121 -0
  16. package/dist/src/capture/cursor-capture.js.map +1 -0
  17. package/dist/src/capture/observability.d.ts +30 -0
  18. package/dist/src/capture/observability.d.ts.map +1 -1
  19. package/dist/src/capture/observability.js +29 -0
  20. package/dist/src/capture/observability.js.map +1 -1
  21. package/dist/src/capture/recover-quarantine.d.ts +4 -4
  22. package/dist/src/capture/sources.d.ts +41 -3
  23. package/dist/src/capture/sources.d.ts.map +1 -1
  24. package/dist/src/capture/sources.js +43 -1
  25. package/dist/src/capture/sources.js.map +1 -1
  26. package/dist/src/capture/triage-classification.d.ts +69 -0
  27. package/dist/src/capture/triage-classification.d.ts.map +1 -0
  28. package/dist/src/capture/triage-classification.js +62 -0
  29. package/dist/src/capture/triage-classification.js.map +1 -0
  30. package/dist/src/capture/triage-provider-factory.d.ts +36 -0
  31. package/dist/src/capture/triage-provider-factory.d.ts.map +1 -0
  32. package/dist/src/capture/triage-provider-factory.js +55 -0
  33. package/dist/src/capture/triage-provider-factory.js.map +1 -0
  34. package/dist/src/capture/triage.d.ts +1 -1
  35. package/dist/src/capture/triage.d.ts.map +1 -1
  36. package/dist/src/capture/triage.js +8 -6
  37. package/dist/src/capture/triage.js.map +1 -1
  38. package/dist/src/cli/commands/capture.d.ts.map +1 -1
  39. package/dist/src/cli/commands/capture.js +79 -17
  40. package/dist/src/cli/commands/capture.js.map +1 -1
  41. package/dist/src/cli/commands/chunk-backfill.d.ts +13 -0
  42. package/dist/src/cli/commands/chunk-backfill.d.ts.map +1 -0
  43. package/dist/src/cli/commands/chunk-backfill.js +157 -0
  44. package/dist/src/cli/commands/chunk-backfill.js.map +1 -0
  45. package/dist/src/cli/commands/cursor-probe.d.ts +20 -0
  46. package/dist/src/cli/commands/cursor-probe.d.ts.map +1 -0
  47. package/dist/src/cli/commands/cursor-probe.js +162 -0
  48. package/dist/src/cli/commands/cursor-probe.js.map +1 -0
  49. package/dist/src/cli/commands/menubar.d.ts +3 -1
  50. package/dist/src/cli/commands/menubar.d.ts.map +1 -1
  51. package/dist/src/cli/commands/menubar.js +36 -12
  52. package/dist/src/cli/commands/menubar.js.map +1 -1
  53. package/dist/src/cli/commands/onboard.d.ts +22 -2
  54. package/dist/src/cli/commands/onboard.d.ts.map +1 -1
  55. package/dist/src/cli/commands/onboard.js +160 -32
  56. package/dist/src/cli/commands/onboard.js.map +1 -1
  57. package/dist/src/cli/commands/status.d.ts.map +1 -1
  58. package/dist/src/cli/commands/status.js +12 -0
  59. package/dist/src/cli/commands/status.js.map +1 -1
  60. package/dist/src/cli/commands/update.d.ts +34 -1
  61. package/dist/src/cli/commands/update.d.ts.map +1 -1
  62. package/dist/src/cli/commands/update.js +166 -1
  63. package/dist/src/cli/commands/update.js.map +1 -1
  64. package/dist/src/cli/index.d.ts.map +1 -1
  65. package/dist/src/cli/index.js +4 -0
  66. package/dist/src/cli/index.js.map +1 -1
  67. package/dist/src/cli/postinstall-menubar.d.ts +20 -13
  68. package/dist/src/cli/postinstall-menubar.d.ts.map +1 -1
  69. package/dist/src/cli/postinstall-menubar.js +56 -1
  70. package/dist/src/cli/postinstall-menubar.js.map +1 -1
  71. package/dist/src/cli/status/friend-header.d.ts +16 -3
  72. package/dist/src/cli/status/friend-header.d.ts.map +1 -1
  73. package/dist/src/cli/status/friend-header.js +186 -10
  74. package/dist/src/cli/status/friend-header.js.map +1 -1
  75. package/dist/src/cli/status/local-signals.d.ts +42 -4
  76. package/dist/src/cli/status/local-signals.d.ts.map +1 -1
  77. package/dist/src/cli/status/local-signals.js +52 -1
  78. package/dist/src/cli/status/local-signals.js.map +1 -1
  79. package/dist/src/config/schema.d.ts +220 -14
  80. package/dist/src/config/schema.d.ts.map +1 -1
  81. package/dist/src/config/schema.js +82 -7
  82. package/dist/src/config/schema.js.map +1 -1
  83. package/dist/src/diagnostics/claude-preflight.d.ts +35 -0
  84. package/dist/src/diagnostics/claude-preflight.d.ts.map +1 -0
  85. package/dist/src/diagnostics/claude-preflight.js +90 -0
  86. package/dist/src/diagnostics/claude-preflight.js.map +1 -0
  87. package/dist/src/diagnostics/codex-preflight.d.ts +1 -1
  88. package/dist/src/diagnostics/codex-preflight.d.ts.map +1 -1
  89. package/dist/src/diagnostics/codex-preflight.js +24 -0
  90. package/dist/src/diagnostics/codex-preflight.js.map +1 -1
  91. package/dist/src/diagnostics/doctor.d.ts +7 -4
  92. package/dist/src/diagnostics/doctor.d.ts.map +1 -1
  93. package/dist/src/diagnostics/doctor.js +70 -11
  94. package/dist/src/diagnostics/doctor.js.map +1 -1
  95. package/dist/src/diagnostics/memory-coverage.d.ts +54 -0
  96. package/dist/src/diagnostics/memory-coverage.d.ts.map +1 -0
  97. package/dist/src/diagnostics/memory-coverage.js +272 -0
  98. package/dist/src/diagnostics/memory-coverage.js.map +1 -0
  99. package/dist/src/diagnostics/notify.d.ts +20 -3
  100. package/dist/src/diagnostics/notify.d.ts.map +1 -1
  101. package/dist/src/diagnostics/notify.js +54 -14
  102. package/dist/src/diagnostics/notify.js.map +1 -1
  103. package/dist/src/ingestion/chunk-meta.d.ts +85 -0
  104. package/dist/src/ingestion/chunk-meta.d.ts.map +1 -0
  105. package/dist/src/ingestion/chunk-meta.js +167 -0
  106. package/dist/src/ingestion/chunk-meta.js.map +1 -0
  107. package/dist/src/ingestion/chunk-text.d.ts +39 -0
  108. package/dist/src/ingestion/chunk-text.d.ts.map +1 -0
  109. package/dist/src/ingestion/chunk-text.js +114 -0
  110. package/dist/src/ingestion/chunk-text.js.map +1 -0
  111. package/dist/src/ingestion/cursor/cursor-store.d.ts +177 -0
  112. package/dist/src/ingestion/cursor/cursor-store.d.ts.map +1 -0
  113. package/dist/src/ingestion/cursor/cursor-store.js +243 -0
  114. package/dist/src/ingestion/cursor/cursor-store.js.map +1 -0
  115. package/dist/src/ingestion/cursor/enrich-roots.d.ts +16 -0
  116. package/dist/src/ingestion/cursor/enrich-roots.d.ts.map +1 -0
  117. package/dist/src/ingestion/cursor/enrich-roots.js +22 -0
  118. package/dist/src/ingestion/cursor/enrich-roots.js.map +1 -0
  119. package/dist/src/ingestion/cursor/vscdb-reader.d.ts +32 -0
  120. package/dist/src/ingestion/cursor/vscdb-reader.d.ts.map +1 -0
  121. package/dist/src/ingestion/cursor/vscdb-reader.js +113 -0
  122. package/dist/src/ingestion/cursor/vscdb-reader.js.map +1 -0
  123. package/dist/src/ingestion/cursor/workspace-root.d.ts +96 -0
  124. package/dist/src/ingestion/cursor/workspace-root.d.ts.map +1 -0
  125. package/dist/src/ingestion/cursor/workspace-root.js +187 -0
  126. package/dist/src/ingestion/cursor/workspace-root.js.map +1 -0
  127. package/dist/src/ingestion/indexer.d.ts.map +1 -1
  128. package/dist/src/ingestion/indexer.js +41 -32
  129. package/dist/src/ingestion/indexer.js.map +1 -1
  130. package/dist/src/jobs/handlers/compact.d.ts.map +1 -1
  131. package/dist/src/jobs/handlers/compact.js +9 -4
  132. package/dist/src/jobs/handlers/compact.js.map +1 -1
  133. package/dist/src/jobs/handlers/ingest.d.ts.map +1 -1
  134. package/dist/src/jobs/handlers/ingest.js +60 -30
  135. package/dist/src/jobs/handlers/ingest.js.map +1 -1
  136. package/dist/src/jobs/handlers/reconcile.d.ts.map +1 -1
  137. package/dist/src/jobs/handlers/reconcile.js +128 -45
  138. package/dist/src/jobs/handlers/reconcile.js.map +1 -1
  139. package/dist/src/jobs/handlers/save.d.ts.map +1 -1
  140. package/dist/src/jobs/handlers/save.js +122 -72
  141. package/dist/src/jobs/handlers/save.js.map +1 -1
  142. package/dist/src/jobs/types.d.ts +1 -1
  143. package/dist/src/main.js +27 -16
  144. package/dist/src/main.js.map +1 -1
  145. package/dist/src/mcp/capture-diagnostics.d.ts +51 -0
  146. package/dist/src/mcp/capture-diagnostics.d.ts.map +1 -0
  147. package/dist/src/mcp/capture-diagnostics.js +127 -0
  148. package/dist/src/mcp/capture-diagnostics.js.map +1 -0
  149. package/dist/src/mcp/memory-diagnostics.d.ts +6 -0
  150. package/dist/src/mcp/memory-diagnostics.d.ts.map +1 -0
  151. package/dist/src/mcp/memory-diagnostics.js +51 -0
  152. package/dist/src/mcp/memory-diagnostics.js.map +1 -0
  153. package/dist/src/mcp/server.d.ts.map +1 -1
  154. package/dist/src/mcp/server.js +10 -3
  155. package/dist/src/mcp/server.js.map +1 -1
  156. package/dist/src/mcp/tools/context-pack.d.ts.map +1 -1
  157. package/dist/src/mcp/tools/context-pack.js +7 -1
  158. package/dist/src/mcp/tools/context-pack.js.map +1 -1
  159. package/dist/src/mcp/tools/conversations-search.d.ts +1 -1
  160. package/dist/src/mcp/tools/conversations-search.d.ts.map +1 -1
  161. package/dist/src/mcp/tools/conversations-search.js +7 -1
  162. package/dist/src/mcp/tools/conversations-search.js.map +1 -1
  163. package/dist/src/mcp/tools/evidence-feedback.d.ts +60 -0
  164. package/dist/src/mcp/tools/evidence-feedback.d.ts.map +1 -0
  165. package/dist/src/mcp/tools/evidence-feedback.js +62 -0
  166. package/dist/src/mcp/tools/evidence-feedback.js.map +1 -0
  167. package/dist/src/mcp/tools/log-outcome.d.ts +72 -0
  168. package/dist/src/mcp/tools/log-outcome.d.ts.map +1 -0
  169. package/dist/src/mcp/tools/log-outcome.js +59 -0
  170. package/dist/src/mcp/tools/log-outcome.js.map +1 -0
  171. package/dist/src/mcp/tools/open-evidence.d.ts +37 -0
  172. package/dist/src/mcp/tools/open-evidence.d.ts.map +1 -0
  173. package/dist/src/mcp/tools/open-evidence.js +72 -0
  174. package/dist/src/mcp/tools/open-evidence.js.map +1 -0
  175. package/dist/src/mcp/tools/save.d.ts +7 -2
  176. package/dist/src/mcp/tools/save.d.ts.map +1 -1
  177. package/dist/src/mcp/tools/save.js +7 -2
  178. package/dist/src/mcp/tools/save.js.map +1 -1
  179. package/dist/src/mcp/tools/search.d.ts.map +1 -1
  180. package/dist/src/mcp/tools/search.js +7 -1
  181. package/dist/src/mcp/tools/search.js.map +1 -1
  182. package/dist/src/mcp/tools/status.d.ts +15 -1
  183. package/dist/src/mcp/tools/status.d.ts.map +1 -1
  184. package/dist/src/mcp/tools/status.js +53 -2
  185. package/dist/src/mcp/tools/status.js.map +1 -1
  186. package/dist/src/observability/retrieval-feedback.d.ts +82 -0
  187. package/dist/src/observability/retrieval-feedback.d.ts.map +1 -0
  188. package/dist/src/observability/retrieval-feedback.js +231 -0
  189. package/dist/src/observability/retrieval-feedback.js.map +1 -0
  190. package/dist/src/observability/rift-context.d.ts.map +1 -1
  191. package/dist/src/observability/rift-context.js +3 -0
  192. package/dist/src/observability/rift-context.js.map +1 -1
  193. package/dist/src/observability/tool-usage-stats.d.ts +13 -0
  194. package/dist/src/observability/tool-usage-stats.d.ts.map +1 -1
  195. package/dist/src/observability/tool-usage-stats.js +15 -0
  196. package/dist/src/observability/tool-usage-stats.js.map +1 -1
  197. package/dist/src/observability/tool-usage.d.ts +56 -0
  198. package/dist/src/observability/tool-usage.d.ts.map +1 -1
  199. package/dist/src/observability/tool-usage.js +86 -0
  200. package/dist/src/observability/tool-usage.js.map +1 -1
  201. package/dist/src/providers/claude-cli-metadata-extraction.d.ts +47 -0
  202. package/dist/src/providers/claude-cli-metadata-extraction.d.ts.map +1 -0
  203. package/dist/src/providers/claude-cli-metadata-extraction.js +120 -0
  204. package/dist/src/providers/claude-cli-metadata-extraction.js.map +1 -0
  205. package/dist/src/providers/claude-cli-runner.d.ts +92 -0
  206. package/dist/src/providers/claude-cli-runner.d.ts.map +1 -0
  207. package/dist/src/providers/claude-cli-runner.js +598 -0
  208. package/dist/src/providers/claude-cli-runner.js.map +1 -0
  209. package/dist/src/providers/codex-cli-metadata-extraction.d.ts.map +1 -1
  210. package/dist/src/providers/codex-cli-metadata-extraction.js +1 -40
  211. package/dist/src/providers/codex-cli-metadata-extraction.js.map +1 -1
  212. package/dist/src/providers/codex-cli-runner.d.ts +7 -0
  213. package/dist/src/providers/codex-cli-runner.d.ts.map +1 -1
  214. package/dist/src/providers/codex-cli-runner.js +131 -5
  215. package/dist/src/providers/codex-cli-runner.js.map +1 -1
  216. package/dist/src/providers/conversation-generation.d.ts +10 -0
  217. package/dist/src/providers/conversation-generation.d.ts.map +1 -1
  218. package/dist/src/providers/conversation-generation.js +54 -13
  219. package/dist/src/providers/conversation-generation.js.map +1 -1
  220. package/dist/src/providers/openai-metadata-extraction.d.ts +48 -1
  221. package/dist/src/providers/openai-metadata-extraction.d.ts.map +1 -1
  222. package/dist/src/providers/openai-metadata-extraction.js +51 -2
  223. package/dist/src/providers/openai-metadata-extraction.js.map +1 -1
  224. package/dist/src/providers/types.d.ts +1 -1
  225. package/dist/src/providers/types.d.ts.map +1 -1
  226. package/dist/src/providers/types.js +4 -0
  227. package/dist/src/providers/types.js.map +1 -1
  228. package/dist/src/retrieval/canonical-files.d.ts +48 -0
  229. package/dist/src/retrieval/canonical-files.d.ts.map +1 -0
  230. package/dist/src/retrieval/canonical-files.js +210 -0
  231. package/dist/src/retrieval/canonical-files.js.map +1 -0
  232. package/dist/src/retrieval/compact.d.ts +95 -0
  233. package/dist/src/retrieval/compact.d.ts.map +1 -1
  234. package/dist/src/retrieval/compact.js +254 -8
  235. package/dist/src/retrieval/compact.js.map +1 -1
  236. package/dist/src/retrieval/context-pack.d.ts.map +1 -1
  237. package/dist/src/retrieval/context-pack.js +65 -15
  238. package/dist/src/retrieval/context-pack.js.map +1 -1
  239. package/dist/src/retrieval/conversation-dedup.d.ts +40 -0
  240. package/dist/src/retrieval/conversation-dedup.d.ts.map +1 -0
  241. package/dist/src/retrieval/conversation-dedup.js +141 -0
  242. package/dist/src/retrieval/conversation-dedup.js.map +1 -0
  243. package/dist/src/retrieval/evidence-key.d.ts +48 -0
  244. package/dist/src/retrieval/evidence-key.d.ts.map +1 -0
  245. package/dist/src/retrieval/evidence-key.js +131 -0
  246. package/dist/src/retrieval/evidence-key.js.map +1 -0
  247. package/dist/src/retrieval/feedback-ranking.d.ts +49 -0
  248. package/dist/src/retrieval/feedback-ranking.d.ts.map +1 -0
  249. package/dist/src/retrieval/feedback-ranking.js +138 -0
  250. package/dist/src/retrieval/feedback-ranking.js.map +1 -0
  251. package/dist/src/retrieval/git-state.d.ts +9 -0
  252. package/dist/src/retrieval/git-state.d.ts.map +1 -1
  253. package/dist/src/retrieval/git-state.js +18 -0
  254. package/dist/src/retrieval/git-state.js.map +1 -1
  255. package/dist/src/retrieval/group-by-parent.d.ts +38 -0
  256. package/dist/src/retrieval/group-by-parent.d.ts.map +1 -0
  257. package/dist/src/retrieval/group-by-parent.js +40 -0
  258. package/dist/src/retrieval/group-by-parent.js.map +1 -0
  259. package/dist/src/retrieval/lexical.d.ts.map +1 -1
  260. package/dist/src/retrieval/lexical.js +1 -3
  261. package/dist/src/retrieval/lexical.js.map +1 -1
  262. package/dist/src/retrieval/receipt.d.ts +57 -0
  263. package/dist/src/retrieval/receipt.d.ts.map +1 -0
  264. package/dist/src/retrieval/receipt.js +119 -0
  265. package/dist/src/retrieval/receipt.js.map +1 -0
  266. package/dist/src/retrieval/reranker.d.ts +49 -2
  267. package/dist/src/retrieval/reranker.d.ts.map +1 -1
  268. package/dist/src/retrieval/reranker.js +64 -4
  269. package/dist/src/retrieval/reranker.js.map +1 -1
  270. package/dist/src/retrieval/stitch-chunks.d.ts +73 -0
  271. package/dist/src/retrieval/stitch-chunks.d.ts.map +1 -0
  272. package/dist/src/retrieval/stitch-chunks.js +106 -0
  273. package/dist/src/retrieval/stitch-chunks.js.map +1 -0
  274. package/dist/src/server/app.d.ts +1 -1
  275. package/dist/src/server/app.d.ts.map +1 -1
  276. package/dist/src/server/app.js +20 -3
  277. package/dist/src/server/app.js.map +1 -1
  278. package/dist/src/server/routes/conversations-search.d.ts.map +1 -1
  279. package/dist/src/server/routes/conversations-search.js +22 -3
  280. package/dist/src/server/routes/conversations-search.js.map +1 -1
  281. package/dist/src/server/routes/friend-status.d.ts +64 -6
  282. package/dist/src/server/routes/friend-status.d.ts.map +1 -1
  283. package/dist/src/server/routes/friend-status.js +114 -18
  284. package/dist/src/server/routes/friend-status.js.map +1 -1
  285. package/dist/src/server/routes/mcp-usage.d.ts +9 -6
  286. package/dist/src/server/routes/mcp-usage.d.ts.map +1 -1
  287. package/dist/src/server/routes/mcp-usage.js.map +1 -1
  288. package/dist/src/server/routes/retrieval-feedback.d.ts +3 -0
  289. package/dist/src/server/routes/retrieval-feedback.d.ts.map +1 -0
  290. package/dist/src/server/routes/retrieval-feedback.js +290 -0
  291. package/dist/src/server/routes/retrieval-feedback.js.map +1 -0
  292. package/dist/src/server/routes/save.d.ts +3 -3
  293. package/dist/src/server/routes/save.d.ts.map +1 -1
  294. package/dist/src/server/routes/save.js +6 -2
  295. package/dist/src/server/routes/save.js.map +1 -1
  296. package/dist/src/server/routes/search.d.ts +1 -1
  297. package/dist/src/server/routes/search.d.ts.map +1 -1
  298. package/dist/src/server/routes/search.js +55 -8
  299. package/dist/src/server/routes/search.js.map +1 -1
  300. package/dist/src/server/serving-marker.d.ts +85 -0
  301. package/dist/src/server/serving-marker.d.ts.map +1 -0
  302. package/dist/src/server/serving-marker.js +226 -0
  303. package/dist/src/server/serving-marker.js.map +1 -0
  304. package/dist/src/storage/chunk-backfill.d.ts +39 -0
  305. package/dist/src/storage/chunk-backfill.d.ts.map +1 -0
  306. package/dist/src/storage/chunk-backfill.js +295 -0
  307. package/dist/src/storage/chunk-backfill.js.map +1 -0
  308. package/dist/src/storage/filter.d.ts +42 -0
  309. package/dist/src/storage/filter.d.ts.map +1 -0
  310. package/dist/src/storage/filter.js +70 -0
  311. package/dist/src/storage/filter.js.map +1 -0
  312. package/dist/src/storage/rebuild.d.ts.map +1 -1
  313. package/dist/src/storage/rebuild.js +44 -27
  314. package/dist/src/storage/rebuild.js.map +1 -1
  315. package/dist/src/storage/tables.d.ts +41 -0
  316. package/dist/src/storage/tables.d.ts.map +1 -1
  317. package/dist/src/storage/tables.js +64 -1
  318. package/dist/src/storage/tables.js.map +1 -1
  319. package/operator/swiftbar/render-menu.py +60 -18
  320. package/package.json +6 -4
@@ -0,0 +1,272 @@
1
+ /**
2
+ * Memory coverage diagnostics for status surfaces.
3
+ *
4
+ * Counts alone are not enough: "0 digests" can mean AI enrichment is off,
5
+ * Claude was selected (no digest worker yet), or compaction simply has not run.
6
+ * "0 structured docs" can mean no sources, empty sources, missing embeddings,
7
+ * or a watch-mode backfill gap. This module turns config + cheap filesystem
8
+ * probes + table counts into explicit, leak-safe reasons.
9
+ */
10
+ import fs from "node:fs";
11
+ import path from "node:path";
12
+ import { buildIgnoredPaths } from "../ingestion/ignored-paths.js";
13
+ import { isSupported } from "../ingestion/extractor.js";
14
+ import { isWatcherPathIgnored } from "../ingestion/watcher.js";
15
+ const DEFAULT_SUPPORTED_FILE_SCAN_LIMIT = 100;
16
+ const DEFAULT_SOURCE_ENTRY_SCAN_LIMIT = 1_000;
17
+ export function buildMemoryCoverageDiagnostics(input) {
18
+ const counts = input.counts
19
+ ? {
20
+ conversations: input.counts.conversations_hot + input.counts.conversations_cold,
21
+ digests: input.counts.digests,
22
+ structured_docs: input.counts.structured_docs,
23
+ }
24
+ : null;
25
+ return {
26
+ counts,
27
+ digests: buildDigestCoverage({
28
+ config: input.config,
29
+ counts,
30
+ compactAvailable: input.compactAvailable,
31
+ }),
32
+ documents: buildDocumentCoverage({
33
+ config: input.config,
34
+ counts,
35
+ voyageKeyPresent: input.voyageKeyPresent,
36
+ supportedFileScanLimit: input.supportedFileScanLimit ?? DEFAULT_SUPPORTED_FILE_SCAN_LIMIT,
37
+ }),
38
+ };
39
+ }
40
+ function selectedMetadataProvider(config) {
41
+ if (config.local_generation?.enabled === true)
42
+ return "ollama";
43
+ if (config.enrichment?.ai_metadata !== true)
44
+ return "basic";
45
+ return config.enrichment.metadata?.provider ?? "codex_cli";
46
+ }
47
+ function buildDigestCoverage(input) {
48
+ const provider = selectedMetadataProvider(input.config);
49
+ if (!input.counts) {
50
+ return {
51
+ status: "unknown",
52
+ metadata_provider: provider,
53
+ compact_available: input.compactAvailable,
54
+ summary: "Digest coverage could not be counted.",
55
+ next_action: "Run: rift status --json",
56
+ };
57
+ }
58
+ if (input.counts.digests > 0) {
59
+ return {
60
+ status: "indexed",
61
+ metadata_provider: provider,
62
+ compact_available: input.compactAvailable,
63
+ summary: `${input.counts.digests} digest${input.counts.digests === 1 ? "" : "s"} indexed.`,
64
+ next_action: null,
65
+ };
66
+ }
67
+ if (provider === "basic") {
68
+ return {
69
+ status: "unavailable_basic",
70
+ metadata_provider: provider,
71
+ compact_available: input.compactAvailable,
72
+ summary: "No digests because AI enrichment is off, so no digest worker is registered.",
73
+ next_action: "Enable a digest worker, e.g. rift onboard --enable-codex-enrichment, then run rift compact.",
74
+ };
75
+ }
76
+ if (provider === "claude_code") {
77
+ return {
78
+ status: "unavailable_claude",
79
+ metadata_provider: provider,
80
+ compact_available: input.compactAvailable,
81
+ summary: "No digests because Claude Code metadata is selected, but Claude digest support has not shipped yet.",
82
+ next_action: "Use Codex or Ollama for digest generation for now; keep Claude metadata if you do not need digests.",
83
+ };
84
+ }
85
+ if (!input.compactAvailable) {
86
+ return {
87
+ status: "unavailable_worker",
88
+ metadata_provider: provider,
89
+ compact_available: input.compactAvailable,
90
+ summary: "No digests because the compact/digest worker is not available in this daemon.",
91
+ next_action: "Run: rift doctor",
92
+ };
93
+ }
94
+ // We know only that a digest-capable worker is registered and the digest
95
+ // count is zero — NOT that compaction never ran. A corpus younger than the
96
+ // compaction age threshold legitimately has a working worker, compaction
97
+ // having run repeatedly, and still zero digests. Stay honest about that.
98
+ return {
99
+ status: "available_not_run",
100
+ metadata_provider: provider,
101
+ compact_available: input.compactAvailable,
102
+ summary: "No digests yet. A digest worker is available, but nothing has been compacted into a digest — either no conversation has reached the compaction age threshold, or compaction has not run.",
103
+ next_action: "Run: rift compact --dry-run to see what would be compacted.",
104
+ };
105
+ }
106
+ function buildDocumentCoverage(input) {
107
+ const sources = input.config.sources ?? [];
108
+ // Config-derived fields only (no filesystem touch). The probe-derived fields
109
+ // stay zeroed and `probed` stays false until we actually walk the sources.
110
+ const configDerived = {
111
+ probed: false,
112
+ configured_sources: sources.length,
113
+ existing_sources: 0,
114
+ cloud_sources: sources.filter((s) => s.extraction === "cloud").length,
115
+ local_sources: sources.filter((s) => s.extraction === "local").length,
116
+ sources_with_supported_files: 0,
117
+ supported_files_seen: 0,
118
+ cloud_supported_files_seen: 0,
119
+ local_supported_files_seen: 0,
120
+ scan_limit: input.supportedFileScanLimit,
121
+ scan_limited: false,
122
+ cloud_embedding_ready: input.voyageKeyPresent,
123
+ };
124
+ // Counts unavailable: nothing to conclude, and probing can't diagnose without
125
+ // a baseline count. Degrade to "unknown" without touching the filesystem.
126
+ if (!input.counts) {
127
+ return {
128
+ ...configDerived,
129
+ status: "unknown",
130
+ summary: "Structured-document coverage could not be counted.",
131
+ next_action: "Run: rift status --json",
132
+ };
133
+ }
134
+ // Healthy steady state: documents are already indexed, so we owe no
135
+ // explanation and skip the probe entirely. `rift status --json` is polled
136
+ // ~every 10s by the menu bar; walking every configured source tree on each
137
+ // poll once docs exist is pure waste — the probe only earns its cost when
138
+ // docs == 0.
139
+ if (input.counts.structured_docs > 0) {
140
+ return {
141
+ ...configDerived,
142
+ status: "indexed",
143
+ summary: `${input.counts.structured_docs} structured document${input.counts.structured_docs === 1 ? "" : "s"} indexed.`,
144
+ next_action: null,
145
+ };
146
+ }
147
+ // Zero docs: probe the sources to explain why.
148
+ const probes = sources.map((source) => probeSource(source, input.config, input.supportedFileScanLimit));
149
+ const existingSources = probes.filter((p) => p.exists).length;
150
+ const supportedFilesSeen = sum(probes.map((p) => p.supportedFilesSeen));
151
+ const scanLimited = probes.some((p) => p.scanLimited);
152
+ const sourcesWithSupportedFiles = probes.filter((p) => p.supportedFilesSeen > 0).length;
153
+ const cloudSupportedFilesSeen = sum(probes.map((p, i) => sources[i]?.extraction === "cloud" ? p.supportedFilesSeen : 0));
154
+ const localSupportedFilesSeen = sum(probes.map((p, i) => sources[i]?.extraction === "local" ? p.supportedFilesSeen : 0));
155
+ const base = {
156
+ ...configDerived,
157
+ probed: true,
158
+ existing_sources: existingSources,
159
+ sources_with_supported_files: sourcesWithSupportedFiles,
160
+ supported_files_seen: supportedFilesSeen,
161
+ cloud_supported_files_seen: cloudSupportedFilesSeen,
162
+ local_supported_files_seen: localSupportedFilesSeen,
163
+ scan_limited: scanLimited,
164
+ };
165
+ if (configDerived.configured_sources === 0) {
166
+ return {
167
+ ...base,
168
+ status: "not_configured",
169
+ summary: "No structured documents because no document sources are configured.",
170
+ next_action: "Add a source to the active Rift config, then run rift reconcile.",
171
+ };
172
+ }
173
+ if (existingSources === 0) {
174
+ return {
175
+ ...base,
176
+ status: "source_missing",
177
+ summary: "No structured documents because the configured source paths are missing on disk.",
178
+ next_action: "Fix or remove the missing source paths in the active Rift config.",
179
+ };
180
+ }
181
+ if (supportedFilesSeen === 0 && scanLimited) {
182
+ return {
183
+ ...base,
184
+ status: "unknown",
185
+ summary: "No structured documents, and the source probe hit its scan limit before finding supported files.",
186
+ next_action: "Run: rift reconcile",
187
+ };
188
+ }
189
+ if (supportedFilesSeen === 0) {
190
+ return {
191
+ ...base,
192
+ status: "source_empty",
193
+ summary: "No structured documents because the active sources contain no supported files.",
194
+ next_action: "Add supported files to an active source, or point the active config at the folders you want indexed.",
195
+ };
196
+ }
197
+ if (cloudSupportedFilesSeen > 0 && !input.voyageKeyPresent) {
198
+ return {
199
+ ...base,
200
+ status: "embedding_unavailable",
201
+ summary: "No structured documents because cloud sources contain supported files, but no Voyage key is loaded.",
202
+ next_action: "Run: rift onboard --reconfigure-voyage",
203
+ };
204
+ }
205
+ return {
206
+ ...base,
207
+ status: "backfill_needed",
208
+ summary: "No structured documents even though active sources contain supported files; existing files likely need a reconcile/backfill pass.",
209
+ next_action: "Run: rift reconcile",
210
+ };
211
+ }
212
+ function probeSource(source, config, limit) {
213
+ let stat;
214
+ try {
215
+ stat = fs.statSync(source.path);
216
+ }
217
+ catch {
218
+ return { exists: false, supportedFilesSeen: 0, scanLimited: false };
219
+ }
220
+ if (!stat.isDirectory()) {
221
+ return { exists: false, supportedFilesSeen: 0, scanLimited: false };
222
+ }
223
+ const ignoredPaths = buildIgnoredPaths(source, config.data_paths);
224
+ const result = countSupportedFiles(source.path, ignoredPaths, limit, DEFAULT_SOURCE_ENTRY_SCAN_LIMIT);
225
+ return {
226
+ exists: true,
227
+ supportedFilesSeen: result.count,
228
+ scanLimited: result.limited,
229
+ };
230
+ }
231
+ function countSupportedFiles(dir, ignoredPaths, supportedFileLimit, entryLimit) {
232
+ let count = 0;
233
+ let entriesSeen = 0;
234
+ let limited = false;
235
+ const visit = (current) => {
236
+ if (count >= supportedFileLimit || entriesSeen >= entryLimit) {
237
+ limited = true;
238
+ return;
239
+ }
240
+ if (isWatcherPathIgnored(current, ignoredPaths))
241
+ return;
242
+ let entries;
243
+ try {
244
+ entries = fs.readdirSync(current, { withFileTypes: true });
245
+ }
246
+ catch {
247
+ return;
248
+ }
249
+ for (const entry of entries) {
250
+ if (count >= supportedFileLimit || entriesSeen >= entryLimit) {
251
+ limited = true;
252
+ return;
253
+ }
254
+ entriesSeen++;
255
+ const fullPath = path.join(current, entry.name);
256
+ if (isWatcherPathIgnored(fullPath, ignoredPaths))
257
+ continue;
258
+ if (entry.isDirectory() && !entry.isSymbolicLink()) {
259
+ visit(fullPath);
260
+ }
261
+ else if (entry.isFile() && isSupported(fullPath)) {
262
+ count++;
263
+ }
264
+ }
265
+ };
266
+ visit(dir);
267
+ return { count, limited };
268
+ }
269
+ function sum(values) {
270
+ return values.reduce((acc, n) => acc + n, 0);
271
+ }
272
+ //# sourceMappingURL=memory-coverage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-coverage.js","sourceRoot":"","sources":["../../../src/diagnostics/memory-coverage.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,18 @@
1
1
  import type { DoctorIssue, DoctorIssueKind } from "./doctor.js";
2
2
  /** Re-notify cadence for an issue that stays unresolved. */
3
3
  export declare const RENOTIFY_INTERVAL_MS: number;
4
+ /**
5
+ * The only issue kinds that ever raise a friend-facing macOS banner — the
6
+ * user-ACTIONABLE failures, where the friend can sign in or add a key and the
7
+ * problem clears. Everything else (a transient codex/claude probe failure, an
8
+ * index-write or save error, a backend timeout) is operator-only: surfaced in
9
+ * `rift doctor` / `rift status` and the logs, never a banner, because a
10
+ * non-technical friend cannot act on it and Rift retries it on its own.
11
+ *
12
+ * New kinds default to operator-only (fail-closed): add a kind here only when
13
+ * there is a safe, concrete action the friend can take.
14
+ */
15
+ export declare const FRIEND_NOTIFY_KINDS: ReadonlySet<DoctorIssueKind>;
4
16
  export interface NotificationPayload {
5
17
  /** macOS notification title — always the same friend-facing banner. */
6
18
  title: string;
@@ -53,9 +65,14 @@ export declare function buildNotificationPayload(issue: DoctorIssue): Notificati
53
65
  * Decide which notifications to send this tick and what state to persist.
54
66
  * Pure: no IO, no clock except the injected `now`.
55
67
  *
56
- * Only `daemonObservable` issues are eligible the daemon must not
57
- * notify about things it cannot itself observe (e.g. a dead daemon, or
58
- * user-side rejected imports).
68
+ * Eligible issues are the intersection of `daemonObservable` (the daemon can
69
+ * see them) and `FRIEND_NOTIFY_KINDS` (the friend can act on them) so a
70
+ * transient probe/index/save failure never reaches a banner.
71
+ *
72
+ * The dedup memory survives a healthy run: a record is retained until its 24h
73
+ * cooldown elapses, even on ticks where the issue is absent. That is the flood
74
+ * fix — without it, one healthy poll wiped the "already warned you" memory and
75
+ * the next recurrence re-notified, defeating the daily limit.
59
76
  */
60
77
  export declare function planNotifications(input: PlanNotificationsInput): PlanNotificationsResult;
61
78
  /** Absolute path to the dedup-state file under the data dir. */
@@ -1 +1 @@
1
- {"version":3,"file":"notify.d.ts","sourceRoot":"","sources":["../../../src/diagnostics/notify.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEhE,4DAA4D;AAC5D,eAAO,MAAM,oBAAoB,QAAsB,CAAC;AAExD,MAAM,WAAW,mBAAmB;IAClC,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAC;IACd,sDAAsD;IACtD,QAAQ,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,kCAAkC;AAClC,MAAM,WAAW,YAAY;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,YAAY,CAAC,CAAC,CAAC;CACxD;AAOD,MAAM,WAAW,sBAAsB;IACrC,iEAAiE;IACjE,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,wCAAwC;IACxC,KAAK,EAAE,WAAW,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,uBAAuB;IACtC,kEAAkE;IAClE,aAAa,EAAE,mBAAmB,EAAE,CAAC;IACrC,sCAAsC;IACtC,SAAS,EAAE,WAAW,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,WAAW,GACjB,mBAAmB,CAMrB;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,sBAAsB,GAC5B,uBAAuB,CA+CzB;AAED,gEAAgE;AAChE,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,uEAAuE;AACvE,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,CAW5D;AAED,2DAA2D;AAC3D,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI,CAQ1E;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,mBAAmB,EAC5B,IAAI,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAA;CAAO,GACxC,IAAI,CAcN;AAED,iEAAiE;AACjE,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,WAAW,EAAE,EACrB,IAAI,GAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAA;CAAO,GACtD,IAAI,CAmBN"}
1
+ {"version":3,"file":"notify.d.ts","sourceRoot":"","sources":["../../../src/diagnostics/notify.ts"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEhE,4DAA4D;AAC5D,eAAO,MAAM,oBAAoB,QAAsB,CAAC;AAExD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,mBAAmB,EAAE,WAAW,CAAC,eAAe,CAQ3D,CAAC;AAEH,MAAM,WAAW,mBAAmB;IAClC,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAC;IACd,sDAAsD;IACtD,QAAQ,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,kCAAkC;AAClC,MAAM,WAAW,YAAY;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,YAAY,CAAC,CAAC,CAAC;CACxD;AAOD,MAAM,WAAW,sBAAsB;IACrC,iEAAiE;IACjE,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,wCAAwC;IACxC,KAAK,EAAE,WAAW,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,uBAAuB;IACtC,kEAAkE;IAClE,aAAa,EAAE,mBAAmB,EAAE,CAAC;IACrC,sCAAsC;IACtC,SAAS,EAAE,WAAW,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,WAAW,GACjB,mBAAmB,CAMrB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,sBAAsB,GAC5B,uBAAuB,CA2DzB;AAED,gEAAgE;AAChE,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,uEAAuE;AACvE,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,CAW5D;AAED,2DAA2D;AAC3D,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI,CAQ1E;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,mBAAmB,EAC5B,IAAI,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAA;CAAO,GACxC,IAAI,CAcN;AAED,iEAAiE;AACjE,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,WAAW,EAAE,EACrB,IAAI,GAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAA;CAAO,GACtD,IAAI,CAmBN"}
@@ -11,10 +11,15 @@
11
11
  * about itself. That needs a separate watchdog and is explicitly Slice D
12
12
  * (see docs/feedback/2026-05-20-friend-onboarding-status-surface.md).
13
13
  *
14
- * Rate-limiting rules (from the status-surface plan):
14
+ * Rate-limiting rules (status-surface plan + the 2026-06 flood fix):
15
+ * - Only user-ACTIONABLE kinds (FRIEND_NOTIFY_KINDS) ever reach a friend;
16
+ * transient/infra failures (probe timeouts, index/save errors) are
17
+ * operator-only — visible in `rift doctor`/`status`, never a banner.
15
18
  * - Notify on state transition, not every poll.
16
- * - Do not repeat the same unresolved issue more than once per day.
17
- * - Notify again after the issue resolves and later recurs.
19
+ * - Do not repeat the same unresolved issue more than once per day — and the
20
+ * dedup memory SURVIVES a healthy run, so an intermittent failure
21
+ * (fail → heal → fail within 24h) notifies once, not on every recurrence.
22
+ * - After the cooldown elapses, a genuine later recurrence notifies fresh.
18
23
  *
19
24
  * The planning logic (`planNotifications`) is pure and fully tested; the
20
25
  * IO (reading/writing dedup state, sending via osascript) is thin and
@@ -25,6 +30,26 @@ import fs from "node:fs";
25
30
  import path from "node:path";
26
31
  /** Re-notify cadence for an issue that stays unresolved. */
27
32
  export const RENOTIFY_INTERVAL_MS = 24 * 60 * 60 * 1000;
33
+ /**
34
+ * The only issue kinds that ever raise a friend-facing macOS banner — the
35
+ * user-ACTIONABLE failures, where the friend can sign in or add a key and the
36
+ * problem clears. Everything else (a transient codex/claude probe failure, an
37
+ * index-write or save error, a backend timeout) is operator-only: surfaced in
38
+ * `rift doctor` / `rift status` and the logs, never a banner, because a
39
+ * non-technical friend cannot act on it and Rift retries it on its own.
40
+ *
41
+ * New kinds default to operator-only (fail-closed): add a kind here only when
42
+ * there is a safe, concrete action the friend can take.
43
+ */
44
+ export const FRIEND_NOTIFY_KINDS = new Set([
45
+ "codex_auth_expired",
46
+ "claude_auth_expired",
47
+ "voyage_key_missing",
48
+ // NOT voyage_embed_errors: "key present but embedding failed" is not cleanly
49
+ // friend-actionable — it spans an invalid key AND a network/provider flake.
50
+ // It stays operator-only until the cause is split into its own kind
51
+ // (voyage_key_invalid → friend banner, voyage_embed_errors → operator).
52
+ ]);
28
53
  /** Cause identity for an issue: explicit fingerprint, else its kind. */
29
54
  function issueFingerprint(issue) {
30
55
  return issue.fingerprint ?? issue.kind;
@@ -45,16 +70,34 @@ export function buildNotificationPayload(issue) {
45
70
  * Decide which notifications to send this tick and what state to persist.
46
71
  * Pure: no IO, no clock except the injected `now`.
47
72
  *
48
- * Only `daemonObservable` issues are eligible the daemon must not
49
- * notify about things it cannot itself observe (e.g. a dead daemon, or
50
- * user-side rejected imports).
73
+ * Eligible issues are the intersection of `daemonObservable` (the daemon can
74
+ * see them) and `FRIEND_NOTIFY_KINDS` (the friend can act on them) so a
75
+ * transient probe/index/save failure never reaches a banner.
76
+ *
77
+ * The dedup memory survives a healthy run: a record is retained until its 24h
78
+ * cooldown elapses, even on ticks where the issue is absent. That is the flood
79
+ * fix — without it, one healthy poll wiped the "already warned you" memory and
80
+ * the next recurrence re-notified, defeating the daily limit.
51
81
  */
52
82
  export function planNotifications(input) {
53
83
  const { issues, state, now } = input;
54
- const eligible = issues.filter((i) => i.daemonObservable);
55
- const eligibleKinds = new Set(eligible.map((i) => i.kind));
56
- const nextActive = {};
84
+ const eligible = issues.filter((i) => i.daemonObservable && FRIEND_NOTIFY_KINDS.has(i.kind));
85
+ const presentKinds = new Set(eligible.map((i) => i.kind));
57
86
  const notifications = [];
87
+ const nextActive = {};
88
+ // Carry over prior records for kinds NOT failing this tick, as long as their
89
+ // cooldown window has not elapsed. This keeps the "already warned" memory
90
+ // alive across a healthy run, so an intermittent failure notifies once per
91
+ // day rather than on every recurrence. Expired records are dropped, so a
92
+ // genuine later recurrence notifies fresh.
93
+ for (const [kind, record] of Object.entries(state.active)) {
94
+ if (presentKinds.has(kind))
95
+ continue;
96
+ const lastMs = Date.parse(record.last_notified_at);
97
+ const fresh = !Number.isNaN(lastMs) && now - lastMs < RENOTIFY_INTERVAL_MS;
98
+ if (fresh)
99
+ nextActive[kind] = record;
100
+ }
58
101
  for (const issue of eligible) {
59
102
  const prior = state.active[issue.kind];
60
103
  const fingerprint = issueFingerprint(issue);
@@ -66,7 +109,7 @@ export function planNotifications(input) {
66
109
  };
67
110
  };
68
111
  if (!prior) {
69
- // New transition into failure → notify.
112
+ // First transition into failure → notify.
70
113
  notify();
71
114
  continue;
72
115
  }
@@ -84,13 +127,10 @@ export function planNotifications(input) {
84
127
  notify();
85
128
  }
86
129
  else {
87
- // Already notified within the window → stay quiet, keep record.
130
+ // Already notified within the window → stay quiet, keep the record.
88
131
  nextActive[issue.kind] = prior;
89
132
  }
90
133
  }
91
- // Anything previously active but no longer present has resolved; it is
92
- // simply absent from `nextActive`, so a later recurrence notifies fresh.
93
- void eligibleKinds;
94
134
  return { notifications, nextState: { active: nextActive } };
95
135
  }
96
136
  /** Absolute path to the dedup-state file under the data dir. */
@@ -1 +1 @@
1
- {"version":3,"file":"notify.js","sourceRoot":"","sources":["../../../src/diagnostics/notify.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"notify.js","sourceRoot":"","sources":["../../../src/diagnostics/notify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,4DAA4D;AAC5D,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAExD;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAiC,IAAI,GAAG,CAAC;IACvE,oBAAoB;IACpB,qBAAqB;IACrB,oBAAoB;IACpB,6EAA6E;IAC7E,4EAA4E;IAC5E,oEAAoE;IACpE,wEAAwE;CACzE,CAAC,CAAC;AAkCH,wEAAwE;AACxE,SAAS,gBAAgB,CAAC,KAAkB;IAC1C,OAAO,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,IAAI,CAAC;AACzC,CAAC;AAiBD;;;;GAIG;AACH,MAAM,UAAU,wBAAwB,CACtC,KAAkB;IAElB,OAAO;QACL,KAAK,EAAE,sBAAsB;QAC7B,QAAQ,EAAE,KAAK,CAAC,KAAK;QACrB,OAAO,EAAE,KAAK,CAAC,UAAU;KAC1B,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,iBAAiB,CAC/B,KAA6B;IAE7B,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC;IACrC,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAC5B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,gBAAgB,IAAI,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAC7D,CAAC;IACF,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAE1D,MAAM,aAAa,GAA0B,EAAE,CAAC;IAChD,MAAM,UAAU,GAA0B,EAAE,CAAC;IAE7C,6EAA6E;IAC7E,0EAA0E;IAC1E,2EAA2E;IAC3E,yEAAyE;IACzE,2CAA2C;IAC3C,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAEvD,EAAE,CAAC;QACF,IAAI,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,SAAS;QACrC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;QACnD,MAAM,KAAK,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,GAAG,GAAG,MAAM,GAAG,oBAAoB,CAAC;QAC3E,IAAI,KAAK;YAAE,UAAU,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC;IACvC,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACvC,MAAM,WAAW,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;QAC5C,MAAM,MAAM,GAAG,GAAS,EAAE;YACxB,aAAa,CAAC,IAAI,CAAC,wBAAwB,CAAC,KAAK,CAAC,CAAC,CAAC;YACpD,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG;gBACvB,gBAAgB,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE;gBAC7C,WAAW;aACZ,CAAC;QACJ,CAAC,CAAC;QACF,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,0CAA0C;YAC1C,MAAM,EAAE,CAAC;YACT,SAAS;QACX,CAAC;QACD,oEAAoE;QACpE,oEAAoE;QACpE,qEAAqE;QACrE,IAAI,CAAC,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,WAAW,EAAE,CAAC;YACtD,MAAM,EAAE,CAAC;YACT,SAAS;QACX,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;QACnD,MAAM,KAAK,GACT,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,GAAG,GAAG,OAAO,IAAI,oBAAoB,CAAC;QACjE,IAAI,KAAK,EAAE,CAAC;YACV,2DAA2D;YAC3D,MAAM,EAAE,CAAC;QACX,CAAC;aAAM,CAAC;YACN,oEAAoE;YACpE,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;QACjC,CAAC;IACH,CAAC;IAED,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,CAAC;AAC9D,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,EAAE,oBAAoB,CAAC,CAAC;AACnE,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,eAAe,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,CAAC;QAC9D,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAyB,CAAC;QACvD,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;QACnC,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,eAAe;IACjB,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;AACxB,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,gBAAgB,CAAC,OAAe,EAAE,KAAkB;IAClE,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;QACtC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACtD,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC;IACxE,CAAC;IAAC,MAAM,CAAC;QACP,qEAAqE;IACvE,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,gBAAgB,CAC9B,OAA4B,EAC5B,OAAuC,EAAE;IAEzC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC;IACnD,IAAI,QAAQ,KAAK,QAAQ;QAAE,OAAO;IAClC,MAAM,MAAM,GACV,wBAAwB,mBAAmB,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG;QAC/D,cAAc,mBAAmB,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG;QACnD,YAAY,mBAAmB,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;IACtD,IAAI,CAAC;QACH,QAAQ,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE;YACzC,2CAA2C;QAC7C,CAAC,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,gCAAgC;IAClC,CAAC;AACH,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC;AAClE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAClC,OAAe,EACf,MAAqB,EACrB,OAAqD,EAAE;IAEvD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;QACvC,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,GAAG,iBAAiB,CAAC;YACrD,MAAM;YACN,KAAK;YACL,GAAG;SACJ,CAAC,CAAC;QACH,KAAK,MAAM,OAAO,IAAI,aAAa,EAAE,CAAC;YACpC,gBAAgB,CACd,OAAO,EACP,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CACjD,CAAC;QACJ,CAAC;QACD,gBAAgB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,8DAA8D;IAChE,CAAC;AACH,CAAC"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * The single source of truth for chunk MARKERS — how a row declares it is one
3
+ * piece of a larger logical document/conversation, and how readers recover the
4
+ * parent grouping. Every producer (indexer, save, ingest, rebuild) and every
5
+ * consumer (retrieval grouping, reconcile, dedup) imports from here, so there is
6
+ * exactly one marker contract.
7
+ *
8
+ * Representation:
9
+ * - Conversations carry explicit columns `parent_id`, `chunk_index`,
10
+ * `chunk_count` (all strings; empty = legacy/unchunked).
11
+ * - Documents carry `chunk_index` / `chunk_count` inside the existing
12
+ * `metadata` JSON; the parent key is the already-indexed `source_path`.
13
+ *
14
+ * The explicit `chunk_count` IS the marker: `chunk_count > 1` means "this row is
15
+ * part of a chunk set". A row WITHOUT that marker is never grouped — sharing a
16
+ * `source_path` or `idempotency_key` alone must not cause a collapse. Ordinals
17
+ * are stored explicitly (not parsed out of the row id), so completeness checks
18
+ * and honest "section k of N" display never treat the id as the source of truth.
19
+ */
20
+ import type { TableName } from "../storage/tables.js";
21
+ export interface ChunkMarker {
22
+ /** Parent key value: `source_path` for docs, `parent_id` for conversations. */
23
+ parentId: string;
24
+ /** 0-based ordinal within the set. */
25
+ index: number;
26
+ /** Total chunks in the set (> 1 when this is genuinely chunked). */
27
+ count: number;
28
+ }
29
+ /** Separators for chunk row ids. Distinct per family for readability; ids are
30
+ * unique either way and are NOT load-bearing for ordering (use chunk_index). */
31
+ export declare const DOC_CHUNK_SEP = ":";
32
+ export declare const CONV_CHUNK_SEP = "::";
33
+ /** Read the chunk marker from a conversation row, or null if unchunked/legacy. */
34
+ export declare function readConversationChunkMarker(row: Record<string, unknown>): ChunkMarker | null;
35
+ /** Read the chunk marker from a structured-doc row, or null if unchunked/legacy. */
36
+ export declare function readDocChunkMarker(row: Record<string, unknown>): ChunkMarker | null;
37
+ /**
38
+ * Namespaced parent key for retrieval grouping, or `null` when the row carries
39
+ * NO explicit chunk marker (the flag-off / legacy case — never grouped).
40
+ *
41
+ * Namespacing guarantees mixed-vintage / cross-table rows can never collapse:
42
+ * - docs → `doc|<source_table>|<source_path>` (so `structured_docs` vs
43
+ * `structured_docs_local` with the same path stay separate)
44
+ * - convs → `conv|<source>|<parent_id>`
45
+ */
46
+ export declare function parentKeyForRow(sourceTable: TableName, row: Record<string, unknown>): string | null;
47
+ /** True iff the row is part of a genuine chunk set (`chunk_count > 1`). */
48
+ export declare function isChunked(sourceTable: TableName, row: Record<string, unknown>): boolean;
49
+ /**
50
+ * Unified chunk-marker reader across the conversation and document families,
51
+ * or `null` for an unchunked/legacy row (no marker / `chunk_count <= 1`) and for
52
+ * digests (which never chunk). Lets the read-side (expand stitching) inspect a
53
+ * row's position in its set without re-deriving the per-family column vs metadata
54
+ * split. `parentId` is the raw column value (`parent_id` / `source_path`), not the
55
+ * namespaced retrieval key.
56
+ */
57
+ export declare function readChunkMarker(sourceTable: TableName, row: Record<string, unknown>): ChunkMarker | null;
58
+ /** Conversation chunk columns. count <= 1 → empty markers (matches seed/legacy). */
59
+ export declare function conversationChunkColumns(parentId: string, index: number, count: number): {
60
+ parent_id: string;
61
+ chunk_index: string;
62
+ chunk_count: string;
63
+ };
64
+ /** Merge chunk ordinals into a doc metadata object. count <= 1 → unchanged
65
+ * (NO `chunk_*` keys), so a single/legacy doc stays byte-identical. */
66
+ export declare function docChunkMetadata(base: Record<string, unknown>, index: number, count: number): Record<string, unknown>;
67
+ export declare function convChunkId(parentId: string, index: number): string;
68
+ export declare function docChunkId(fileId: string, index: number): string;
69
+ /** The largest declared `chunk_count` across a set of rows (≥ 1). */
70
+ export declare function expectedChunkCount(rows: Record<string, unknown>[]): number;
71
+ /**
72
+ * True iff the rows already indexed for a parent form a COMPLETE set. Used by
73
+ * save/ingest/reconcile dedup so a partially-written set (crash mid-append) is
74
+ * repaired rather than mistaken for "already indexed".
75
+ *
76
+ * Completeness is stricter than a row count: a chunked set is complete only when
77
+ * every chunk index `0 .. count-1` is present EXACTLY once and every row agrees
78
+ * on the same `chunk_count`. This rejects the degenerate set that a bare
79
+ * `rows.length >= count` check would wave through — e.g. a duplicated chunk 0
80
+ * with a missing chunk 1 (length 2, count 2, but broken). An unchunked set
81
+ * (`count <= 1`, all legacy/`/ingest`-job rows) keeps the legacy semantics: any
82
+ * existing row counts as complete, so this never changes flag-off behavior.
83
+ */
84
+ export declare function chunkSetComplete(rows: Record<string, unknown>[]): boolean;
85
+ //# sourceMappingURL=chunk-meta.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk-meta.d.ts","sourceRoot":"","sources":["../../../src/ingestion/chunk-meta.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEtD,MAAM,WAAW,WAAW;IAC1B,+EAA+E;IAC/E,QAAQ,EAAE,MAAM,CAAC;IACjB,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAC;CACf;AAED;iFACiF;AACjF,eAAO,MAAM,aAAa,MAAM,CAAC;AACjC,eAAO,MAAM,cAAc,OAAO,CAAC;AAgCnC,kFAAkF;AAClF,wBAAgB,2BAA2B,CACzC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC3B,WAAW,GAAG,IAAI,CAMpB;AAED,oFAAoF;AACpF,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC3B,WAAW,GAAG,IAAI,CAQpB;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,WAAW,EAAE,SAAS,EACtB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC3B,MAAM,GAAG,IAAI,CAaf;AAED,2EAA2E;AAC3E,wBAAgB,SAAS,CACvB,WAAW,EAAE,SAAS,EACtB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC3B,OAAO,CAET;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,WAAW,EAAE,SAAS,EACtB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC3B,WAAW,GAAG,IAAI,CAQpB;AAID,oFAAoF;AACpF,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACZ;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAOjE;AAED;wEACwE;AACxE,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACZ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAGzB;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAEnE;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhE;AAID,qEAAqE;AACrE,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,MAAM,CAI1E;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,OAAO,CAczE"}