@getrift/rift 0.0.0 → 0.1.0-beta.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 (628) hide show
  1. package/README.dev.md +110 -0
  2. package/README.md +130 -0
  3. package/dist/src/auth/keychain.d.ts +25 -0
  4. package/dist/src/auth/keychain.d.ts.map +1 -0
  5. package/dist/src/auth/keychain.js +113 -0
  6. package/dist/src/auth/keychain.js.map +1 -0
  7. package/dist/src/auth/middleware.d.ts +20 -0
  8. package/dist/src/auth/middleware.d.ts.map +1 -0
  9. package/dist/src/auth/middleware.js +49 -0
  10. package/dist/src/auth/middleware.js.map +1 -0
  11. package/dist/src/auth/rate-limit.d.ts +16 -0
  12. package/dist/src/auth/rate-limit.d.ts.map +1 -0
  13. package/dist/src/auth/rate-limit.js +38 -0
  14. package/dist/src/auth/rate-limit.js.map +1 -0
  15. package/dist/src/auth/rotation.d.ts +67 -0
  16. package/dist/src/auth/rotation.d.ts.map +1 -0
  17. package/dist/src/auth/rotation.js +190 -0
  18. package/dist/src/auth/rotation.js.map +1 -0
  19. package/dist/src/backfill/project-context-batch-constructor.d.ts +127 -0
  20. package/dist/src/backfill/project-context-batch-constructor.d.ts.map +1 -0
  21. package/dist/src/backfill/project-context-batch-constructor.js +210 -0
  22. package/dist/src/backfill/project-context-batch-constructor.js.map +1 -0
  23. package/dist/src/capture/auto-capture.d.ts +162 -0
  24. package/dist/src/capture/auto-capture.d.ts.map +1 -0
  25. package/dist/src/capture/auto-capture.js +601 -0
  26. package/dist/src/capture/auto-capture.js.map +1 -0
  27. package/dist/src/capture/batch-budget.d.ts +90 -0
  28. package/dist/src/capture/batch-budget.d.ts.map +1 -0
  29. package/dist/src/capture/batch-budget.js +148 -0
  30. package/dist/src/capture/batch-budget.js.map +1 -0
  31. package/dist/src/capture/codex-cli-triage-provider.d.ts +17 -0
  32. package/dist/src/capture/codex-cli-triage-provider.d.ts.map +1 -0
  33. package/dist/src/capture/codex-cli-triage-provider.js +109 -0
  34. package/dist/src/capture/codex-cli-triage-provider.js.map +1 -0
  35. package/dist/src/capture/observability.d.ts +42 -0
  36. package/dist/src/capture/observability.d.ts.map +1 -0
  37. package/dist/src/capture/observability.js +87 -0
  38. package/dist/src/capture/observability.js.map +1 -0
  39. package/dist/src/capture/openai-triage-provider.d.ts +92 -0
  40. package/dist/src/capture/openai-triage-provider.d.ts.map +1 -0
  41. package/dist/src/capture/openai-triage-provider.js +267 -0
  42. package/dist/src/capture/openai-triage-provider.js.map +1 -0
  43. package/dist/src/capture/review-queue-index.d.ts +51 -0
  44. package/dist/src/capture/review-queue-index.d.ts.map +1 -0
  45. package/dist/src/capture/review-queue-index.js +204 -0
  46. package/dist/src/capture/review-queue-index.js.map +1 -0
  47. package/dist/src/capture/review-queue.d.ts +43 -0
  48. package/dist/src/capture/review-queue.d.ts.map +1 -0
  49. package/dist/src/capture/review-queue.js +116 -0
  50. package/dist/src/capture/review-queue.js.map +1 -0
  51. package/dist/src/capture/sources.d.ts +7 -0
  52. package/dist/src/capture/sources.d.ts.map +1 -0
  53. package/dist/src/capture/sources.js +3 -0
  54. package/dist/src/capture/sources.js.map +1 -0
  55. package/dist/src/capture/triage-lane.d.ts +39 -0
  56. package/dist/src/capture/triage-lane.d.ts.map +1 -0
  57. package/dist/src/capture/triage-lane.js +217 -0
  58. package/dist/src/capture/triage-lane.js.map +1 -0
  59. package/dist/src/capture/triage-provider.d.ts +75 -0
  60. package/dist/src/capture/triage-provider.d.ts.map +1 -0
  61. package/dist/src/capture/triage-provider.js +120 -0
  62. package/dist/src/capture/triage-provider.js.map +1 -0
  63. package/dist/src/capture/triage.d.ts +30 -0
  64. package/dist/src/capture/triage.d.ts.map +1 -0
  65. package/dist/src/capture/triage.js +48 -0
  66. package/dist/src/capture/triage.js.map +1 -0
  67. package/dist/src/cli/commands/backfill.d.ts +3 -0
  68. package/dist/src/cli/commands/backfill.d.ts.map +1 -0
  69. package/dist/src/cli/commands/backfill.js +1376 -0
  70. package/dist/src/cli/commands/backfill.js.map +1 -0
  71. package/dist/src/cli/commands/bulk-ingest.d.ts +3 -0
  72. package/dist/src/cli/commands/bulk-ingest.d.ts.map +1 -0
  73. package/dist/src/cli/commands/bulk-ingest.js +126 -0
  74. package/dist/src/cli/commands/bulk-ingest.js.map +1 -0
  75. package/dist/src/cli/commands/capture.d.ts +12 -0
  76. package/dist/src/cli/commands/capture.d.ts.map +1 -0
  77. package/dist/src/cli/commands/capture.js +123 -0
  78. package/dist/src/cli/commands/capture.js.map +1 -0
  79. package/dist/src/cli/commands/compact.d.ts +3 -0
  80. package/dist/src/cli/commands/compact.d.ts.map +1 -0
  81. package/dist/src/cli/commands/compact.js +70 -0
  82. package/dist/src/cli/commands/compact.js.map +1 -0
  83. package/dist/src/cli/commands/feedback.d.ts +22 -0
  84. package/dist/src/cli/commands/feedback.d.ts.map +1 -0
  85. package/dist/src/cli/commands/feedback.js +125 -0
  86. package/dist/src/cli/commands/feedback.js.map +1 -0
  87. package/dist/src/cli/commands/import.d.ts +19 -0
  88. package/dist/src/cli/commands/import.d.ts.map +1 -0
  89. package/dist/src/cli/commands/import.js +258 -0
  90. package/dist/src/cli/commands/import.js.map +1 -0
  91. package/dist/src/cli/commands/ingest.d.ts +3 -0
  92. package/dist/src/cli/commands/ingest.d.ts.map +1 -0
  93. package/dist/src/cli/commands/ingest.js +80 -0
  94. package/dist/src/cli/commands/ingest.js.map +1 -0
  95. package/dist/src/cli/commands/mcp-install.d.ts +25 -0
  96. package/dist/src/cli/commands/mcp-install.d.ts.map +1 -0
  97. package/dist/src/cli/commands/mcp-install.js +134 -0
  98. package/dist/src/cli/commands/mcp-install.js.map +1 -0
  99. package/dist/src/cli/commands/onboard.d.ts +98 -0
  100. package/dist/src/cli/commands/onboard.d.ts.map +1 -0
  101. package/dist/src/cli/commands/onboard.js +742 -0
  102. package/dist/src/cli/commands/onboard.js.map +1 -0
  103. package/dist/src/cli/commands/rebuild.d.ts +12 -0
  104. package/dist/src/cli/commands/rebuild.d.ts.map +1 -0
  105. package/dist/src/cli/commands/rebuild.js +164 -0
  106. package/dist/src/cli/commands/rebuild.js.map +1 -0
  107. package/dist/src/cli/commands/reconcile.d.ts +3 -0
  108. package/dist/src/cli/commands/reconcile.d.ts.map +1 -0
  109. package/dist/src/cli/commands/reconcile.js +56 -0
  110. package/dist/src/cli/commands/reconcile.js.map +1 -0
  111. package/dist/src/cli/commands/reindex.d.ts +3 -0
  112. package/dist/src/cli/commands/reindex.d.ts.map +1 -0
  113. package/dist/src/cli/commands/reindex.js +66 -0
  114. package/dist/src/cli/commands/reindex.js.map +1 -0
  115. package/dist/src/cli/commands/review.d.ts +13 -0
  116. package/dist/src/cli/commands/review.d.ts.map +1 -0
  117. package/dist/src/cli/commands/review.js +383 -0
  118. package/dist/src/cli/commands/review.js.map +1 -0
  119. package/dist/src/cli/commands/save.d.ts +3 -0
  120. package/dist/src/cli/commands/save.d.ts.map +1 -0
  121. package/dist/src/cli/commands/save.js +111 -0
  122. package/dist/src/cli/commands/save.js.map +1 -0
  123. package/dist/src/cli/commands/search.d.ts +35 -0
  124. package/dist/src/cli/commands/search.d.ts.map +1 -0
  125. package/dist/src/cli/commands/search.js +88 -0
  126. package/dist/src/cli/commands/search.js.map +1 -0
  127. package/dist/src/cli/commands/stats.d.ts +3 -0
  128. package/dist/src/cli/commands/stats.d.ts.map +1 -0
  129. package/dist/src/cli/commands/stats.js +42 -0
  130. package/dist/src/cli/commands/stats.js.map +1 -0
  131. package/dist/src/cli/commands/status.d.ts +15 -0
  132. package/dist/src/cli/commands/status.d.ts.map +1 -0
  133. package/dist/src/cli/commands/status.js +89 -0
  134. package/dist/src/cli/commands/status.js.map +1 -0
  135. package/dist/src/cli/commands/token-issue.d.ts +3 -0
  136. package/dist/src/cli/commands/token-issue.d.ts.map +1 -0
  137. package/dist/src/cli/commands/token-issue.js +25 -0
  138. package/dist/src/cli/commands/token-issue.js.map +1 -0
  139. package/dist/src/cli/commands/triage.d.ts +3 -0
  140. package/dist/src/cli/commands/triage.d.ts.map +1 -0
  141. package/dist/src/cli/commands/triage.js +125 -0
  142. package/dist/src/cli/commands/triage.js.map +1 -0
  143. package/dist/src/cli/commands/uninstall.d.ts +3 -0
  144. package/dist/src/cli/commands/uninstall.d.ts.map +1 -0
  145. package/dist/src/cli/commands/uninstall.js +238 -0
  146. package/dist/src/cli/commands/uninstall.js.map +1 -0
  147. package/dist/src/cli/feedback/feedback-config.d.ts +21 -0
  148. package/dist/src/cli/feedback/feedback-config.d.ts.map +1 -0
  149. package/dist/src/cli/feedback/feedback-config.js +43 -0
  150. package/dist/src/cli/feedback/feedback-config.js.map +1 -0
  151. package/dist/src/cli/feedback/feedback-history.d.ts +4 -0
  152. package/dist/src/cli/feedback/feedback-history.d.ts.map +1 -0
  153. package/dist/src/cli/feedback/feedback-history.js +115 -0
  154. package/dist/src/cli/feedback/feedback-history.js.map +1 -0
  155. package/dist/src/cli/feedback/feedback-payload.d.ts +53 -0
  156. package/dist/src/cli/feedback/feedback-payload.d.ts.map +1 -0
  157. package/dist/src/cli/feedback/feedback-payload.js +10 -0
  158. package/dist/src/cli/feedback/feedback-payload.js.map +1 -0
  159. package/dist/src/cli/feedback/feedback-relay.d.ts +15 -0
  160. package/dist/src/cli/feedback/feedback-relay.d.ts.map +1 -0
  161. package/dist/src/cli/feedback/feedback-relay.js +47 -0
  162. package/dist/src/cli/feedback/feedback-relay.js.map +1 -0
  163. package/dist/src/cli/feedback/feedback-status.d.ts +11 -0
  164. package/dist/src/cli/feedback/feedback-status.d.ts.map +1 -0
  165. package/dist/src/cli/feedback/feedback-status.js +122 -0
  166. package/dist/src/cli/feedback/feedback-status.js.map +1 -0
  167. package/dist/src/cli/http-client.d.ts +36 -0
  168. package/dist/src/cli/http-client.d.ts.map +1 -0
  169. package/dist/src/cli/http-client.js +153 -0
  170. package/dist/src/cli/http-client.js.map +1 -0
  171. package/dist/src/cli/index.d.ts +4 -0
  172. package/dist/src/cli/index.d.ts.map +1 -0
  173. package/dist/src/cli/index.js +66 -0
  174. package/dist/src/cli/index.js.map +1 -0
  175. package/dist/src/cli/job-poller.d.ts +13 -0
  176. package/dist/src/cli/job-poller.d.ts.map +1 -0
  177. package/dist/src/cli/job-poller.js +29 -0
  178. package/dist/src/cli/job-poller.js.map +1 -0
  179. package/dist/src/cli/mcp-config-writers/codex-toml.d.ts +10 -0
  180. package/dist/src/cli/mcp-config-writers/codex-toml.d.ts.map +1 -0
  181. package/dist/src/cli/mcp-config-writers/codex-toml.js +410 -0
  182. package/dist/src/cli/mcp-config-writers/codex-toml.js.map +1 -0
  183. package/dist/src/cli/mcp-config-writers/errors.d.ts +17 -0
  184. package/dist/src/cli/mcp-config-writers/errors.d.ts.map +1 -0
  185. package/dist/src/cli/mcp-config-writers/errors.js +13 -0
  186. package/dist/src/cli/mcp-config-writers/errors.js.map +1 -0
  187. package/dist/src/cli/mcp-config-writers/index.d.ts +18 -0
  188. package/dist/src/cli/mcp-config-writers/index.d.ts.map +1 -0
  189. package/dist/src/cli/mcp-config-writers/index.js +49 -0
  190. package/dist/src/cli/mcp-config-writers/index.js.map +1 -0
  191. package/dist/src/cli/mcp-config-writers/json-config.d.ts +12 -0
  192. package/dist/src/cli/mcp-config-writers/json-config.d.ts.map +1 -0
  193. package/dist/src/cli/mcp-config-writers/json-config.js +177 -0
  194. package/dist/src/cli/mcp-config-writers/json-config.js.map +1 -0
  195. package/dist/src/cli/mcp-config-writers/redact.d.ts +28 -0
  196. package/dist/src/cli/mcp-config-writers/redact.d.ts.map +1 -0
  197. package/dist/src/cli/mcp-config-writers/redact.js +48 -0
  198. package/dist/src/cli/mcp-config-writers/redact.js.map +1 -0
  199. package/dist/src/cli/mcp-config-writers/types.d.ts +32 -0
  200. package/dist/src/cli/mcp-config-writers/types.d.ts.map +1 -0
  201. package/dist/src/cli/mcp-config-writers/types.js +5 -0
  202. package/dist/src/cli/mcp-config-writers/types.js.map +1 -0
  203. package/dist/src/cli/output.d.ts +8 -0
  204. package/dist/src/cli/output.d.ts.map +1 -0
  205. package/dist/src/cli/output.js +34 -0
  206. package/dist/src/cli/output.js.map +1 -0
  207. package/dist/src/cli/status/friend-header.d.ts +33 -0
  208. package/dist/src/cli/status/friend-header.d.ts.map +1 -0
  209. package/dist/src/cli/status/friend-header.js +108 -0
  210. package/dist/src/cli/status/friend-header.js.map +1 -0
  211. package/dist/src/cli/status/local-signals.d.ts +14 -0
  212. package/dist/src/cli/status/local-signals.d.ts.map +1 -0
  213. package/dist/src/cli/status/local-signals.js +73 -0
  214. package/dist/src/cli/status/local-signals.js.map +1 -0
  215. package/dist/src/cli/token.d.ts +37 -0
  216. package/dist/src/cli/token.d.ts.map +1 -0
  217. package/dist/src/cli/token.js +105 -0
  218. package/dist/src/cli/token.js.map +1 -0
  219. package/dist/src/cli/uninstall/mcp-uninstall.d.ts +33 -0
  220. package/dist/src/cli/uninstall/mcp-uninstall.d.ts.map +1 -0
  221. package/dist/src/cli/uninstall/mcp-uninstall.js +181 -0
  222. package/dist/src/cli/uninstall/mcp-uninstall.js.map +1 -0
  223. package/dist/src/config/loader.d.ts +9 -0
  224. package/dist/src/config/loader.d.ts.map +1 -0
  225. package/dist/src/config/loader.js +73 -0
  226. package/dist/src/config/loader.js.map +1 -0
  227. package/dist/src/config/schema.d.ts +635 -0
  228. package/dist/src/config/schema.d.ts.map +1 -0
  229. package/dist/src/config/schema.js +208 -0
  230. package/dist/src/config/schema.js.map +1 -0
  231. package/dist/src/ingestion/bulk-ingest.d.ts +11 -0
  232. package/dist/src/ingestion/bulk-ingest.d.ts.map +1 -0
  233. package/dist/src/ingestion/bulk-ingest.js +11 -0
  234. package/dist/src/ingestion/bulk-ingest.js.map +1 -0
  235. package/dist/src/ingestion/extractor.d.ts +16 -0
  236. package/dist/src/ingestion/extractor.d.ts.map +1 -0
  237. package/dist/src/ingestion/extractor.js +85 -0
  238. package/dist/src/ingestion/extractor.js.map +1 -0
  239. package/dist/src/ingestion/extractors/docx.d.ts +3 -0
  240. package/dist/src/ingestion/extractors/docx.d.ts.map +1 -0
  241. package/dist/src/ingestion/extractors/docx.js +20 -0
  242. package/dist/src/ingestion/extractors/docx.js.map +1 -0
  243. package/dist/src/ingestion/extractors/pdf.d.ts +3 -0
  244. package/dist/src/ingestion/extractors/pdf.d.ts.map +1 -0
  245. package/dist/src/ingestion/extractors/pdf.js +32 -0
  246. package/dist/src/ingestion/extractors/pdf.js.map +1 -0
  247. package/dist/src/ingestion/historical-campaign.d.ts +340 -0
  248. package/dist/src/ingestion/historical-campaign.d.ts.map +1 -0
  249. package/dist/src/ingestion/historical-campaign.js +1010 -0
  250. package/dist/src/ingestion/historical-campaign.js.map +1 -0
  251. package/dist/src/ingestion/ignored-paths.d.ts +20 -0
  252. package/dist/src/ingestion/ignored-paths.d.ts.map +1 -0
  253. package/dist/src/ingestion/ignored-paths.js +45 -0
  254. package/dist/src/ingestion/ignored-paths.js.map +1 -0
  255. package/dist/src/ingestion/inbox-watcher.d.ts +12 -0
  256. package/dist/src/ingestion/inbox-watcher.d.ts.map +1 -0
  257. package/dist/src/ingestion/inbox-watcher.js +99 -0
  258. package/dist/src/ingestion/inbox-watcher.js.map +1 -0
  259. package/dist/src/ingestion/indexer.d.ts +32 -0
  260. package/dist/src/ingestion/indexer.d.ts.map +1 -0
  261. package/dist/src/ingestion/indexer.js +68 -0
  262. package/dist/src/ingestion/indexer.js.map +1 -0
  263. package/dist/src/ingestion/metadata-extraction.d.ts +53 -0
  264. package/dist/src/ingestion/metadata-extraction.d.ts.map +1 -0
  265. package/dist/src/ingestion/metadata-extraction.js +132 -0
  266. package/dist/src/ingestion/metadata-extraction.js.map +1 -0
  267. package/dist/src/ingestion/parsers/chatgpt-web.d.ts +29 -0
  268. package/dist/src/ingestion/parsers/chatgpt-web.d.ts.map +1 -0
  269. package/dist/src/ingestion/parsers/chatgpt-web.js +100 -0
  270. package/dist/src/ingestion/parsers/chatgpt-web.js.map +1 -0
  271. package/dist/src/ingestion/parsers/claude-code-jsonl.d.ts +16 -0
  272. package/dist/src/ingestion/parsers/claude-code-jsonl.d.ts.map +1 -0
  273. package/dist/src/ingestion/parsers/claude-code-jsonl.js +123 -0
  274. package/dist/src/ingestion/parsers/claude-code-jsonl.js.map +1 -0
  275. package/dist/src/ingestion/parsers/claude-web.d.ts +24 -0
  276. package/dist/src/ingestion/parsers/claude-web.d.ts.map +1 -0
  277. package/dist/src/ingestion/parsers/claude-web.js +78 -0
  278. package/dist/src/ingestion/parsers/claude-web.js.map +1 -0
  279. package/dist/src/ingestion/parsers/codex-jsonl.d.ts +18 -0
  280. package/dist/src/ingestion/parsers/codex-jsonl.d.ts.map +1 -0
  281. package/dist/src/ingestion/parsers/codex-jsonl.js +125 -0
  282. package/dist/src/ingestion/parsers/codex-jsonl.js.map +1 -0
  283. package/dist/src/ingestion/parsers/gemini-web.d.ts +16 -0
  284. package/dist/src/ingestion/parsers/gemini-web.d.ts.map +1 -0
  285. package/dist/src/ingestion/parsers/gemini-web.js +170 -0
  286. package/dist/src/ingestion/parsers/gemini-web.js.map +1 -0
  287. package/dist/src/ingestion/parsers/grok-web.d.ts +40 -0
  288. package/dist/src/ingestion/parsers/grok-web.d.ts.map +1 -0
  289. package/dist/src/ingestion/parsers/grok-web.js +67 -0
  290. package/dist/src/ingestion/parsers/grok-web.js.map +1 -0
  291. package/dist/src/ingestion/parsers/types.d.ts +34 -0
  292. package/dist/src/ingestion/parsers/types.d.ts.map +1 -0
  293. package/dist/src/ingestion/parsers/types.js +26 -0
  294. package/dist/src/ingestion/parsers/types.js.map +1 -0
  295. package/dist/src/ingestion/scanner.d.ts +48 -0
  296. package/dist/src/ingestion/scanner.d.ts.map +1 -0
  297. package/dist/src/ingestion/scanner.js +131 -0
  298. package/dist/src/ingestion/scanner.js.map +1 -0
  299. package/dist/src/ingestion/staging.d.ts +109 -0
  300. package/dist/src/ingestion/staging.d.ts.map +1 -0
  301. package/dist/src/ingestion/staging.js +411 -0
  302. package/dist/src/ingestion/staging.js.map +1 -0
  303. package/dist/src/ingestion/watcher.d.ts +65 -0
  304. package/dist/src/ingestion/watcher.d.ts.map +1 -0
  305. package/dist/src/ingestion/watcher.js +182 -0
  306. package/dist/src/ingestion/watcher.js.map +1 -0
  307. package/dist/src/jobs/codex-override-handler.d.ts +3 -0
  308. package/dist/src/jobs/codex-override-handler.d.ts.map +1 -0
  309. package/dist/src/jobs/codex-override-handler.js +16 -0
  310. package/dist/src/jobs/codex-override-handler.js.map +1 -0
  311. package/dist/src/jobs/handlers/compact.d.ts +30 -0
  312. package/dist/src/jobs/handlers/compact.d.ts.map +1 -0
  313. package/dist/src/jobs/handlers/compact.js +329 -0
  314. package/dist/src/jobs/handlers/compact.js.map +1 -0
  315. package/dist/src/jobs/handlers/ingest.d.ts +13 -0
  316. package/dist/src/jobs/handlers/ingest.d.ts.map +1 -0
  317. package/dist/src/jobs/handlers/ingest.js +255 -0
  318. package/dist/src/jobs/handlers/ingest.js.map +1 -0
  319. package/dist/src/jobs/handlers/reconcile.d.ts +29 -0
  320. package/dist/src/jobs/handlers/reconcile.d.ts.map +1 -0
  321. package/dist/src/jobs/handlers/reconcile.js +476 -0
  322. package/dist/src/jobs/handlers/reconcile.js.map +1 -0
  323. package/dist/src/jobs/handlers/reindex.d.ts +38 -0
  324. package/dist/src/jobs/handlers/reindex.d.ts.map +1 -0
  325. package/dist/src/jobs/handlers/reindex.js +52 -0
  326. package/dist/src/jobs/handlers/reindex.js.map +1 -0
  327. package/dist/src/jobs/handlers/save.d.ts +10 -0
  328. package/dist/src/jobs/handlers/save.d.ts.map +1 -0
  329. package/dist/src/jobs/handlers/save.js +206 -0
  330. package/dist/src/jobs/handlers/save.js.map +1 -0
  331. package/dist/src/jobs/handlers/triage.d.ts +47 -0
  332. package/dist/src/jobs/handlers/triage.d.ts.map +1 -0
  333. package/dist/src/jobs/handlers/triage.js +95 -0
  334. package/dist/src/jobs/handlers/triage.js.map +1 -0
  335. package/dist/src/jobs/queue.d.ts +107 -0
  336. package/dist/src/jobs/queue.d.ts.map +1 -0
  337. package/dist/src/jobs/queue.js +319 -0
  338. package/dist/src/jobs/queue.js.map +1 -0
  339. package/dist/src/jobs/types.d.ts +39 -0
  340. package/dist/src/jobs/types.d.ts.map +1 -0
  341. package/dist/src/jobs/types.js +29 -0
  342. package/dist/src/jobs/types.js.map +1 -0
  343. package/dist/src/jobs/worker-entry.d.ts +10 -0
  344. package/dist/src/jobs/worker-entry.d.ts.map +1 -0
  345. package/dist/src/jobs/worker-entry.js +210 -0
  346. package/dist/src/jobs/worker-entry.js.map +1 -0
  347. package/dist/src/jobs/worker-process.d.ts +50 -0
  348. package/dist/src/jobs/worker-process.d.ts.map +1 -0
  349. package/dist/src/jobs/worker-process.js +186 -0
  350. package/dist/src/jobs/worker-process.js.map +1 -0
  351. package/dist/src/jobs/worker.d.ts +11 -0
  352. package/dist/src/jobs/worker.d.ts.map +1 -0
  353. package/dist/src/jobs/worker.js +14 -0
  354. package/dist/src/jobs/worker.js.map +1 -0
  355. package/dist/src/main.d.ts +2 -0
  356. package/dist/src/main.d.ts.map +1 -0
  357. package/dist/src/main.js +425 -0
  358. package/dist/src/main.js.map +1 -0
  359. package/dist/src/mcp/errors.d.ts +8 -0
  360. package/dist/src/mcp/errors.d.ts.map +1 -0
  361. package/dist/src/mcp/errors.js +50 -0
  362. package/dist/src/mcp/errors.js.map +1 -0
  363. package/dist/src/mcp/server.d.ts +10 -0
  364. package/dist/src/mcp/server.d.ts.map +1 -0
  365. package/dist/src/mcp/server.js +94 -0
  366. package/dist/src/mcp/server.js.map +1 -0
  367. package/dist/src/mcp/tools/context-pack.d.ts +35 -0
  368. package/dist/src/mcp/tools/context-pack.d.ts.map +1 -0
  369. package/dist/src/mcp/tools/context-pack.js +97 -0
  370. package/dist/src/mcp/tools/context-pack.js.map +1 -0
  371. package/dist/src/mcp/tools/conversations-search.d.ts +38 -0
  372. package/dist/src/mcp/tools/conversations-search.d.ts.map +1 -0
  373. package/dist/src/mcp/tools/conversations-search.js +73 -0
  374. package/dist/src/mcp/tools/conversations-search.js.map +1 -0
  375. package/dist/src/mcp/tools/save.d.ts +32 -0
  376. package/dist/src/mcp/tools/save.d.ts.map +1 -0
  377. package/dist/src/mcp/tools/save.js +60 -0
  378. package/dist/src/mcp/tools/save.js.map +1 -0
  379. package/dist/src/mcp/tools/search.d.ts +33 -0
  380. package/dist/src/mcp/tools/search.d.ts.map +1 -0
  381. package/dist/src/mcp/tools/search.js +58 -0
  382. package/dist/src/mcp/tools/search.js.map +1 -0
  383. package/dist/src/mcp/tools/status.d.ts +17 -0
  384. package/dist/src/mcp/tools/status.d.ts.map +1 -0
  385. package/dist/src/mcp/tools/status.js +12 -0
  386. package/dist/src/mcp/tools/status.js.map +1 -0
  387. package/dist/src/observability/coverage.d.ts +100 -0
  388. package/dist/src/observability/coverage.d.ts.map +1 -0
  389. package/dist/src/observability/coverage.js +180 -0
  390. package/dist/src/observability/coverage.js.map +1 -0
  391. package/dist/src/observability/rift-context.d.ts +47 -0
  392. package/dist/src/observability/rift-context.d.ts.map +1 -0
  393. package/dist/src/observability/rift-context.js +118 -0
  394. package/dist/src/observability/rift-context.js.map +1 -0
  395. package/dist/src/observability/staleness.d.ts +43 -0
  396. package/dist/src/observability/staleness.d.ts.map +1 -0
  397. package/dist/src/observability/staleness.js +74 -0
  398. package/dist/src/observability/staleness.js.map +1 -0
  399. package/dist/src/observability/tool-usage-stats.d.ts +23 -0
  400. package/dist/src/observability/tool-usage-stats.d.ts.map +1 -0
  401. package/dist/src/observability/tool-usage-stats.js +83 -0
  402. package/dist/src/observability/tool-usage-stats.js.map +1 -0
  403. package/dist/src/observability/tool-usage.d.ts +68 -0
  404. package/dist/src/observability/tool-usage.d.ts.map +1 -0
  405. package/dist/src/observability/tool-usage.js +207 -0
  406. package/dist/src/observability/tool-usage.js.map +1 -0
  407. package/dist/src/onboarding/daemon-control.d.ts +33 -0
  408. package/dist/src/onboarding/daemon-control.d.ts.map +1 -0
  409. package/dist/src/onboarding/daemon-control.js +92 -0
  410. package/dist/src/onboarding/daemon-control.js.map +1 -0
  411. package/dist/src/onboarding/env-file.d.ts +18 -0
  412. package/dist/src/onboarding/env-file.d.ts.map +1 -0
  413. package/dist/src/onboarding/env-file.js +89 -0
  414. package/dist/src/onboarding/env-file.js.map +1 -0
  415. package/dist/src/onboarding/voyage-validate.d.ts +16 -0
  416. package/dist/src/onboarding/voyage-validate.d.ts.map +1 -0
  417. package/dist/src/onboarding/voyage-validate.js +85 -0
  418. package/dist/src/onboarding/voyage-validate.js.map +1 -0
  419. package/dist/src/providers/anthropic-digest.d.ts +23 -0
  420. package/dist/src/providers/anthropic-digest.d.ts.map +1 -0
  421. package/dist/src/providers/anthropic-digest.js +91 -0
  422. package/dist/src/providers/anthropic-digest.js.map +1 -0
  423. package/dist/src/providers/codex-cli-digest.d.ts +12 -0
  424. package/dist/src/providers/codex-cli-digest.d.ts.map +1 -0
  425. package/dist/src/providers/codex-cli-digest.js +70 -0
  426. package/dist/src/providers/codex-cli-digest.js.map +1 -0
  427. package/dist/src/providers/codex-cli-metadata-extraction.d.ts +14 -0
  428. package/dist/src/providers/codex-cli-metadata-extraction.d.ts.map +1 -0
  429. package/dist/src/providers/codex-cli-metadata-extraction.js +101 -0
  430. package/dist/src/providers/codex-cli-metadata-extraction.js.map +1 -0
  431. package/dist/src/providers/codex-cli-runner.d.ts +14 -0
  432. package/dist/src/providers/codex-cli-runner.d.ts.map +1 -0
  433. package/dist/src/providers/codex-cli-runner.js +272 -0
  434. package/dist/src/providers/codex-cli-runner.js.map +1 -0
  435. package/dist/src/providers/conversation-generation.d.ts +10 -0
  436. package/dist/src/providers/conversation-generation.d.ts.map +1 -0
  437. package/dist/src/providers/conversation-generation.js +54 -0
  438. package/dist/src/providers/conversation-generation.js.map +1 -0
  439. package/dist/src/providers/ollama-embed.d.ts +22 -0
  440. package/dist/src/providers/ollama-embed.d.ts.map +1 -0
  441. package/dist/src/providers/ollama-embed.js +133 -0
  442. package/dist/src/providers/ollama-embed.js.map +1 -0
  443. package/dist/src/providers/ollama.d.ts +42 -0
  444. package/dist/src/providers/ollama.d.ts.map +1 -0
  445. package/dist/src/providers/ollama.js +169 -0
  446. package/dist/src/providers/ollama.js.map +1 -0
  447. package/dist/src/providers/openai-metadata-extraction.d.ts +73 -0
  448. package/dist/src/providers/openai-metadata-extraction.d.ts.map +1 -0
  449. package/dist/src/providers/openai-metadata-extraction.js +161 -0
  450. package/dist/src/providers/openai-metadata-extraction.js.map +1 -0
  451. package/dist/src/providers/operator-overrides.d.ts +24 -0
  452. package/dist/src/providers/operator-overrides.d.ts.map +1 -0
  453. package/dist/src/providers/operator-overrides.js +84 -0
  454. package/dist/src/providers/operator-overrides.js.map +1 -0
  455. package/dist/src/providers/stub.d.ts +17 -0
  456. package/dist/src/providers/stub.d.ts.map +1 -0
  457. package/dist/src/providers/stub.js +72 -0
  458. package/dist/src/providers/stub.js.map +1 -0
  459. package/dist/src/providers/types.d.ts +82 -0
  460. package/dist/src/providers/types.d.ts.map +1 -0
  461. package/dist/src/providers/types.js +52 -0
  462. package/dist/src/providers/types.js.map +1 -0
  463. package/dist/src/providers/voyage.d.ts +23 -0
  464. package/dist/src/providers/voyage.d.ts.map +1 -0
  465. package/dist/src/providers/voyage.js +135 -0
  466. package/dist/src/providers/voyage.js.map +1 -0
  467. package/dist/src/retrieval/compact.d.ts +89 -0
  468. package/dist/src/retrieval/compact.d.ts.map +1 -0
  469. package/dist/src/retrieval/compact.js +348 -0
  470. package/dist/src/retrieval/compact.js.map +1 -0
  471. package/dist/src/retrieval/context-pack.d.ts +123 -0
  472. package/dist/src/retrieval/context-pack.d.ts.map +1 -0
  473. package/dist/src/retrieval/context-pack.js +553 -0
  474. package/dist/src/retrieval/context-pack.js.map +1 -0
  475. package/dist/src/retrieval/cwd.d.ts +25 -0
  476. package/dist/src/retrieval/cwd.d.ts.map +1 -0
  477. package/dist/src/retrieval/cwd.js +48 -0
  478. package/dist/src/retrieval/cwd.js.map +1 -0
  479. package/dist/src/retrieval/degraded.d.ts +20 -0
  480. package/dist/src/retrieval/degraded.d.ts.map +1 -0
  481. package/dist/src/retrieval/degraded.js +43 -0
  482. package/dist/src/retrieval/degraded.js.map +1 -0
  483. package/dist/src/retrieval/hybrid.d.ts +38 -0
  484. package/dist/src/retrieval/hybrid.d.ts.map +1 -0
  485. package/dist/src/retrieval/hybrid.js +82 -0
  486. package/dist/src/retrieval/hybrid.js.map +1 -0
  487. package/dist/src/retrieval/lexical.d.ts +28 -0
  488. package/dist/src/retrieval/lexical.d.ts.map +1 -0
  489. package/dist/src/retrieval/lexical.js +301 -0
  490. package/dist/src/retrieval/lexical.js.map +1 -0
  491. package/dist/src/retrieval/post-filter.d.ts +32 -0
  492. package/dist/src/retrieval/post-filter.d.ts.map +1 -0
  493. package/dist/src/retrieval/post-filter.js +57 -0
  494. package/dist/src/retrieval/post-filter.js.map +1 -0
  495. package/dist/src/retrieval/reranker.d.ts +72 -0
  496. package/dist/src/retrieval/reranker.d.ts.map +1 -0
  497. package/dist/src/retrieval/reranker.js +129 -0
  498. package/dist/src/retrieval/reranker.js.map +1 -0
  499. package/dist/src/retrieval/vector.d.ts +47 -0
  500. package/dist/src/retrieval/vector.d.ts.map +1 -0
  501. package/dist/src/retrieval/vector.js +112 -0
  502. package/dist/src/retrieval/vector.js.map +1 -0
  503. package/dist/src/runtime/legacy-migration.d.ts +27 -0
  504. package/dist/src/runtime/legacy-migration.d.ts.map +1 -0
  505. package/dist/src/runtime/legacy-migration.js +140 -0
  506. package/dist/src/runtime/legacy-migration.js.map +1 -0
  507. package/dist/src/runtime/legacy-name-guard.d.ts +35 -0
  508. package/dist/src/runtime/legacy-name-guard.d.ts.map +1 -0
  509. package/dist/src/runtime/legacy-name-guard.js +58 -0
  510. package/dist/src/runtime/legacy-name-guard.js.map +1 -0
  511. package/dist/src/runtime/rift-env.d.ts +14 -0
  512. package/dist/src/runtime/rift-env.d.ts.map +1 -0
  513. package/dist/src/runtime/rift-env.js +79 -0
  514. package/dist/src/runtime/rift-env.js.map +1 -0
  515. package/dist/src/runtime/watcher-startup.d.ts +2 -0
  516. package/dist/src/runtime/watcher-startup.d.ts.map +1 -0
  517. package/dist/src/runtime/watcher-startup.js +4 -0
  518. package/dist/src/runtime/watcher-startup.js.map +1 -0
  519. package/dist/src/security/archive.d.ts +23 -0
  520. package/dist/src/security/archive.d.ts.map +1 -0
  521. package/dist/src/security/archive.js +163 -0
  522. package/dist/src/security/archive.js.map +1 -0
  523. package/dist/src/security/paths.d.ts +21 -0
  524. package/dist/src/security/paths.d.ts.map +1 -0
  525. package/dist/src/security/paths.js +67 -0
  526. package/dist/src/security/paths.js.map +1 -0
  527. package/dist/src/server/app.d.ts +29 -0
  528. package/dist/src/server/app.d.ts.map +1 -0
  529. package/dist/src/server/app.js +226 -0
  530. package/dist/src/server/app.js.map +1 -0
  531. package/dist/src/server/build-info.d.ts +8 -0
  532. package/dist/src/server/build-info.d.ts.map +1 -0
  533. package/dist/src/server/build-info.js +61 -0
  534. package/dist/src/server/build-info.js.map +1 -0
  535. package/dist/src/server/lifecycle.d.ts +30 -0
  536. package/dist/src/server/lifecycle.d.ts.map +1 -0
  537. package/dist/src/server/lifecycle.js +59 -0
  538. package/dist/src/server/lifecycle.js.map +1 -0
  539. package/dist/src/server/middleware/multipart.d.ts +51 -0
  540. package/dist/src/server/middleware/multipart.d.ts.map +1 -0
  541. package/dist/src/server/middleware/multipart.js +86 -0
  542. package/dist/src/server/middleware/multipart.js.map +1 -0
  543. package/dist/src/server/routes/compact.d.ts +37 -0
  544. package/dist/src/server/routes/compact.d.ts.map +1 -0
  545. package/dist/src/server/routes/compact.js +77 -0
  546. package/dist/src/server/routes/compact.js.map +1 -0
  547. package/dist/src/server/routes/context.d.ts +5 -0
  548. package/dist/src/server/routes/context.d.ts.map +1 -0
  549. package/dist/src/server/routes/context.js +50 -0
  550. package/dist/src/server/routes/context.js.map +1 -0
  551. package/dist/src/server/routes/conversations-search.d.ts +4 -0
  552. package/dist/src/server/routes/conversations-search.d.ts.map +1 -0
  553. package/dist/src/server/routes/conversations-search.js +243 -0
  554. package/dist/src/server/routes/conversations-search.js.map +1 -0
  555. package/dist/src/server/routes/friend-status.d.ts +72 -0
  556. package/dist/src/server/routes/friend-status.d.ts.map +1 -0
  557. package/dist/src/server/routes/friend-status.js +71 -0
  558. package/dist/src/server/routes/friend-status.js.map +1 -0
  559. package/dist/src/server/routes/ingest.d.ts +15 -0
  560. package/dist/src/server/routes/ingest.d.ts.map +1 -0
  561. package/dist/src/server/routes/ingest.js +139 -0
  562. package/dist/src/server/routes/ingest.js.map +1 -0
  563. package/dist/src/server/routes/jobs.d.ts +10 -0
  564. package/dist/src/server/routes/jobs.d.ts.map +1 -0
  565. package/dist/src/server/routes/jobs.js +29 -0
  566. package/dist/src/server/routes/jobs.js.map +1 -0
  567. package/dist/src/server/routes/mcp-usage.d.ts +13 -0
  568. package/dist/src/server/routes/mcp-usage.d.ts.map +1 -0
  569. package/dist/src/server/routes/mcp-usage.js +17 -0
  570. package/dist/src/server/routes/mcp-usage.js.map +1 -0
  571. package/dist/src/server/routes/reconcile.d.ts +4 -0
  572. package/dist/src/server/routes/reconcile.d.ts.map +1 -0
  573. package/dist/src/server/routes/reconcile.js +43 -0
  574. package/dist/src/server/routes/reconcile.js.map +1 -0
  575. package/dist/src/server/routes/reindex.d.ts +4 -0
  576. package/dist/src/server/routes/reindex.d.ts.map +1 -0
  577. package/dist/src/server/routes/reindex.js +74 -0
  578. package/dist/src/server/routes/reindex.js.map +1 -0
  579. package/dist/src/server/routes/save.d.ts +40 -0
  580. package/dist/src/server/routes/save.d.ts.map +1 -0
  581. package/dist/src/server/routes/save.js +112 -0
  582. package/dist/src/server/routes/save.js.map +1 -0
  583. package/dist/src/server/routes/search.d.ts +5 -0
  584. package/dist/src/server/routes/search.d.ts.map +1 -0
  585. package/dist/src/server/routes/search.js +400 -0
  586. package/dist/src/server/routes/search.js.map +1 -0
  587. package/dist/src/server/routes/stats.d.ts +10 -0
  588. package/dist/src/server/routes/stats.d.ts.map +1 -0
  589. package/dist/src/server/routes/stats.js +15 -0
  590. package/dist/src/server/routes/stats.js.map +1 -0
  591. package/dist/src/server/routes/status.d.ts +20 -0
  592. package/dist/src/server/routes/status.d.ts.map +1 -0
  593. package/dist/src/server/routes/status.js +31 -0
  594. package/dist/src/server/routes/status.js.map +1 -0
  595. package/dist/src/server/routes/triage.d.ts +4 -0
  596. package/dist/src/server/routes/triage.d.ts.map +1 -0
  597. package/dist/src/server/routes/triage.js +94 -0
  598. package/dist/src/server/routes/triage.js.map +1 -0
  599. package/dist/src/server/save-quality.d.ts +21 -0
  600. package/dist/src/server/save-quality.d.ts.map +1 -0
  601. package/dist/src/server/save-quality.js +51 -0
  602. package/dist/src/server/save-quality.js.map +1 -0
  603. package/dist/src/storage/atomic.d.ts +8 -0
  604. package/dist/src/storage/atomic.d.ts.map +1 -0
  605. package/dist/src/storage/atomic.js +22 -0
  606. package/dist/src/storage/atomic.js.map +1 -0
  607. package/dist/src/storage/db.d.ts +15 -0
  608. package/dist/src/storage/db.d.ts.map +1 -0
  609. package/dist/src/storage/db.js +43 -0
  610. package/dist/src/storage/db.js.map +1 -0
  611. package/dist/src/storage/integrity.d.ts +11 -0
  612. package/dist/src/storage/integrity.d.ts.map +1 -0
  613. package/dist/src/storage/integrity.js +66 -0
  614. package/dist/src/storage/integrity.js.map +1 -0
  615. package/dist/src/storage/rebuild.d.ts +37 -0
  616. package/dist/src/storage/rebuild.d.ts.map +1 -0
  617. package/dist/src/storage/rebuild.js +353 -0
  618. package/dist/src/storage/rebuild.js.map +1 -0
  619. package/dist/src/storage/shadow-swap.d.ts +20 -0
  620. package/dist/src/storage/shadow-swap.d.ts.map +1 -0
  621. package/dist/src/storage/shadow-swap.js +163 -0
  622. package/dist/src/storage/shadow-swap.js.map +1 -0
  623. package/dist/src/storage/tables.d.ts +77 -0
  624. package/dist/src/storage/tables.d.ts.map +1 -0
  625. package/dist/src/storage/tables.js +196 -0
  626. package/dist/src/storage/tables.js.map +1 -0
  627. package/package.json +45 -14
  628. package/index.js +0 -3
@@ -0,0 +1,1010 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { atomicWrite } from "../storage/atomic.js";
4
+ import { ARCHIVE_ONLY_THRESHOLD, PROMOTE_TO_EXTRACT_THRESHOLD, } from "../capture/triage-lane.js";
5
+ export const HISTORICAL_IMPORT_POLICY = {
6
+ batch_sizes: {
7
+ initial: 100,
8
+ step_up: 250,
9
+ max_production: 500,
10
+ },
11
+ clean_batch: {
12
+ archive_only_sample_size: 100,
13
+ max_false_discard_rate: 0.05,
14
+ max_failed_files_rate: 0.02,
15
+ max_unsupported_or_junk_rate: 0.10,
16
+ max_review_queue_net_growth: 25,
17
+ },
18
+ scale_up: {
19
+ clean_batches_required_per_level: 2,
20
+ },
21
+ weekly_budget: {
22
+ max_weekly_files_processed: 1500,
23
+ max_daily_files_processed: 300,
24
+ max_weekly_triage_spend_usd: 25,
25
+ },
26
+ stop_rules: {
27
+ review_backlog_open_items_gt: 400,
28
+ review_lane_rate_gt: 0.40,
29
+ archive_only_lane_rate_gt: 0.85,
30
+ promote_to_extract_lane_rate_lt: 0.05,
31
+ promote_to_extract_low_streak_batches: 2,
32
+ },
33
+ lane_rules: {
34
+ archive_only_score_lt: ARCHIVE_ONLY_THRESHOLD,
35
+ review_score_gte: ARCHIVE_ONLY_THRESHOLD,
36
+ review_score_lte: PROMOTE_TO_EXTRACT_THRESHOLD,
37
+ promote_to_extract_score_gt: PROMOTE_TO_EXTRACT_THRESHOLD,
38
+ decision_aware_routing: true,
39
+ routing_source: "scoreHistoricalTriage",
40
+ routing_notes: [
41
+ 'Explicit "review" decisions always stay in the review lane.',
42
+ 'Explicit "discard" decisions only reach archive_only below the archive threshold; otherwise they stay in review.',
43
+ 'Explicit "save" decisions only reach promote_to_extract above the promote threshold; otherwise they stay in review.',
44
+ ],
45
+ },
46
+ batch_quarantine: {
47
+ failed_files_rate_gt: 0.05,
48
+ duplicate_candidates_rate_gt: 0.20,
49
+ unsupported_format_rate_gt: 0.15,
50
+ non_utf8_or_corrupt_rate_gt: 0.05,
51
+ },
52
+ file_quarantine_rules: [
53
+ "parseability fails",
54
+ "format is unsupported",
55
+ "file is corrupt or unreadable",
56
+ "required source markers are missing",
57
+ ],
58
+ resume: {
59
+ terminal_statuses: [
60
+ "archive_only",
61
+ "review",
62
+ "promote_to_extract",
63
+ "quarantined",
64
+ ],
65
+ },
66
+ };
67
+ function makeSummary() {
68
+ return {
69
+ total_batches_seen: 0,
70
+ batches_completed: 0,
71
+ batches_completed_with_warnings: 0,
72
+ batches_failed: 0,
73
+ batches_quarantined: 0,
74
+ files_processed: 0,
75
+ lane_counts: {
76
+ archive_only: 0,
77
+ review: 0,
78
+ promote_to_extract: 0,
79
+ quarantined: 0,
80
+ },
81
+ };
82
+ }
83
+ export function historicalCampaignStatePath(dataDir) {
84
+ return path.join(dataDir, "imports", "campaign-state.json");
85
+ }
86
+ export function createHistoricalCampaignState() {
87
+ return {
88
+ version: 1,
89
+ policy: HISTORICAL_IMPORT_POLICY,
90
+ last_run_at: null,
91
+ weeks: {},
92
+ summary: makeSummary(),
93
+ batches: {},
94
+ };
95
+ }
96
+ export function loadHistoricalCampaignState(dataDir) {
97
+ const filePath = historicalCampaignStatePath(dataDir);
98
+ if (!fs.existsSync(filePath))
99
+ return createHistoricalCampaignState();
100
+ const parsed = JSON.parse(fs.readFileSync(filePath, "utf-8"));
101
+ const merged = {
102
+ ...createHistoricalCampaignState(),
103
+ ...parsed,
104
+ policy: HISTORICAL_IMPORT_POLICY,
105
+ summary: {
106
+ ...makeSummary(),
107
+ ...parsed.summary,
108
+ lane_counts: {
109
+ ...makeSummary().lane_counts,
110
+ ...parsed.summary?.lane_counts,
111
+ },
112
+ },
113
+ };
114
+ if (parsed.baseline_discontinuities) {
115
+ merged.baseline_discontinuities = parsed.baseline_discontinuities;
116
+ }
117
+ return merged;
118
+ }
119
+ export async function writeHistoricalCampaignState(dataDir, state) {
120
+ await atomicWrite(historicalCampaignStatePath(dataDir), JSON.stringify(state, null, 2) + "\n");
121
+ }
122
+ export function ensureHistoricalCampaignBatch(state, batchName, source, nowIso) {
123
+ const existing = state.batches[batchName];
124
+ if (existing) {
125
+ existing.source = source;
126
+ return existing;
127
+ }
128
+ const batch = {
129
+ batch: batchName,
130
+ source,
131
+ status: "pending",
132
+ metering_mode: "openai_usd",
133
+ first_seen_at: nowIso,
134
+ last_started_at: null,
135
+ last_run_at: null,
136
+ run_count: 0,
137
+ total_files: 0,
138
+ last_run_file_count: 0,
139
+ triage_candidates: 0,
140
+ counts: {
141
+ archive_only: 0,
142
+ review: 0,
143
+ promote_to_extract: 0,
144
+ duplicate: 0,
145
+ failed: 0,
146
+ skipped: 0,
147
+ quarantined: 0,
148
+ unsupported_or_junk: 0,
149
+ },
150
+ review_backlog_before: 0,
151
+ review_backlog_after: 0,
152
+ triage_spend_usd: 0,
153
+ archive_only_sample: {
154
+ required_sample_size: HISTORICAL_IMPORT_POLICY.clean_batch.archive_only_sample_size,
155
+ reviewed_count: 0,
156
+ false_discards: 0,
157
+ false_discard_rate: null,
158
+ passed: false,
159
+ },
160
+ clean_checks: {
161
+ archive_only_sample: {
162
+ required_sample_size: HISTORICAL_IMPORT_POLICY.clean_batch.archive_only_sample_size,
163
+ reviewed_count: 0,
164
+ false_discards: 0,
165
+ false_discard_rate: null,
166
+ passed: false,
167
+ },
168
+ failed_files_rate: 0,
169
+ unsupported_or_junk_rate: 0,
170
+ review_queue_net_growth: 0,
171
+ review_queue_net_growth_passed: true,
172
+ clean_batch: false,
173
+ reasons: [],
174
+ },
175
+ policy_flags: {
176
+ stop_due_weekly_spend: false,
177
+ stop_due_review_backlog: false,
178
+ review_lane_rate: 0,
179
+ review_lane_gt_40_percent: false,
180
+ archive_only_lane_rate: 0,
181
+ archive_only_lane_gt_85_percent: false,
182
+ promote_to_extract_lane_rate: 0,
183
+ promote_to_extract_lt_5_percent_streak: 0,
184
+ duplicate_candidates_rate: 0,
185
+ unsupported_format_rate: 0,
186
+ non_utf8_or_corrupt_rate: 0,
187
+ batch_quarantine_reasons: [],
188
+ },
189
+ next_batch_size: HISTORICAL_IMPORT_POLICY.batch_sizes.initial,
190
+ next_action: `Start with ${HISTORICAL_IMPORT_POLICY.batch_sizes.initial} files.`,
191
+ files: {},
192
+ items: {},
193
+ };
194
+ state.batches[batchName] = batch;
195
+ return batch;
196
+ }
197
+ export function startHistoricalCampaignBatch(batch, params) {
198
+ batch.status = "running";
199
+ batch.metering_mode = params.meteringMode;
200
+ batch.last_started_at = params.nowIso;
201
+ batch.total_files = params.totalFiles;
202
+ batch.last_run_file_count = params.runFiles;
203
+ batch.triage_candidates = params.triageCandidates;
204
+ batch.review_backlog_before = params.reviewBacklogBefore;
205
+ batch.run_count += 1;
206
+ }
207
+ export function listTerminalHistoricalItemIds(batch) {
208
+ return new Set(Object.values(batch.items)
209
+ .filter((item) => item.terminal)
210
+ .map((item) => item.item_id));
211
+ }
212
+ export function listTerminalHistoricalFiles(batch) {
213
+ return new Set(Object.values(batch.files)
214
+ .filter((file) => file.terminal)
215
+ .map((file) => file.file));
216
+ }
217
+ export function isFileQuarantineCandidate(file) {
218
+ if (!file.supported)
219
+ return true;
220
+ if (file.junk_markers.includes("unsupported_format"))
221
+ return true;
222
+ if (file.junk_markers.includes("non_utf8"))
223
+ return true;
224
+ if (file.junk_markers.includes("no_assistant_turns"))
225
+ return true;
226
+ if (file.notes.includes("unparseable"))
227
+ return true;
228
+ if (file.notes.includes("unreadable"))
229
+ return true;
230
+ if (file.notes.includes("unvalidated_too_large"))
231
+ return true;
232
+ if (file.size_bytes === 0)
233
+ return true;
234
+ if (file.size_bytes < 512)
235
+ return true;
236
+ return false;
237
+ }
238
+ export function markHistoricalFile(batch, fileName, params) {
239
+ const existing = batch.files[fileName];
240
+ batch.files[fileName] = {
241
+ file: fileName,
242
+ terminal: params.terminal,
243
+ ...(params.terminalStatus ? { terminal_status: params.terminalStatus } : {}),
244
+ item_ids: params.itemIds ?? existing?.item_ids ?? [],
245
+ last_result: params.lastResult,
246
+ attempts: (existing?.attempts ?? 0) + 1,
247
+ updated_at: params.nowIso,
248
+ };
249
+ }
250
+ export function markHistoricalItem(batch, params) {
251
+ batch.items[params.itemId] = {
252
+ item_id: params.itemId,
253
+ file: params.file,
254
+ ...(params.conversationId ? { conversation_id: params.conversationId } : {}),
255
+ ...(params.title ? { title: params.title } : {}),
256
+ last_result: params.lastResult,
257
+ terminal: params.terminal,
258
+ ...(params.terminalStatus ? { terminal_status: params.terminalStatus } : {}),
259
+ ...(params.triage ? { triage: params.triage } : {}),
260
+ updated_at: params.nowIso,
261
+ };
262
+ const fileState = batch.files[params.file];
263
+ const itemIds = new Set(fileState?.item_ids ?? []);
264
+ itemIds.add(params.itemId);
265
+ batch.files[params.file] = {
266
+ file: params.file,
267
+ terminal: fileState?.terminal ?? false,
268
+ ...(fileState?.terminal_status
269
+ ? { terminal_status: fileState.terminal_status }
270
+ : {}),
271
+ item_ids: [...itemIds].sort(),
272
+ last_result: fileState?.last_result ?? "running",
273
+ attempts: fileState?.attempts ?? 0,
274
+ updated_at: params.nowIso,
275
+ };
276
+ }
277
+ export function finalizeHistoricalFiles(batch, nowIso) {
278
+ for (const fileState of Object.values(batch.files)) {
279
+ if (fileState.terminal_status === "quarantined") {
280
+ fileState.terminal = true;
281
+ fileState.last_result = "quarantined";
282
+ fileState.updated_at = nowIso;
283
+ continue;
284
+ }
285
+ if (fileState.item_ids.length === 0) {
286
+ fileState.updated_at = nowIso;
287
+ continue;
288
+ }
289
+ const items = fileState.item_ids
290
+ .map((itemId) => batch.items[itemId])
291
+ .filter((item) => Boolean(item));
292
+ if (items.length === 0) {
293
+ fileState.updated_at = nowIso;
294
+ continue;
295
+ }
296
+ const unresolved = items.filter((item) => !item.terminal);
297
+ if (unresolved.length > 0) {
298
+ fileState.terminal = false;
299
+ const last = unresolved[unresolved.length - 1];
300
+ fileState.last_result = last.last_result;
301
+ delete fileState.terminal_status;
302
+ fileState.updated_at = nowIso;
303
+ continue;
304
+ }
305
+ fileState.terminal = true;
306
+ const terminalStatuses = new Set(items
307
+ .map((item) => item.terminal_status)
308
+ .filter((status) => Boolean(status)));
309
+ if (terminalStatuses.size === 1) {
310
+ const [onlyStatus] = [...terminalStatuses];
311
+ if (onlyStatus) {
312
+ fileState.terminal_status = onlyStatus;
313
+ }
314
+ }
315
+ else {
316
+ delete fileState.terminal_status;
317
+ }
318
+ const itemResults = new Set(items.map((item) => item.last_result));
319
+ fileState.last_result =
320
+ itemResults.size === 1
321
+ ? [...itemResults][0]
322
+ : "promote_to_extract";
323
+ fileState.updated_at = nowIso;
324
+ }
325
+ }
326
+ export function currentHistoricalWeekKey(date) {
327
+ const target = new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()));
328
+ const dayNr = (target.getUTCDay() + 6) % 7;
329
+ target.setUTCDate(target.getUTCDate() - dayNr + 3);
330
+ const firstThursday = new Date(Date.UTC(target.getUTCFullYear(), 0, 4));
331
+ const diff = target.getTime() - firstThursday.getTime();
332
+ const week = 1 + Math.round(diff / 604_800_000);
333
+ return `${target.getUTCFullYear()}-W${String(week).padStart(2, "0")}`;
334
+ }
335
+ export function currentHistoricalDayKey(date) {
336
+ return date.toISOString().slice(0, 10);
337
+ }
338
+ export function getHistoricalWeekState(state, weekKey) {
339
+ state.weeks[weekKey] ??= {
340
+ files_processed: 0,
341
+ triage_spend_usd: 0,
342
+ days: {},
343
+ };
344
+ return state.weeks[weekKey];
345
+ }
346
+ export function getHistoricalDayFilesProcessed(state, weekKey, dayKey) {
347
+ return state.weeks[weekKey]?.days[dayKey]?.files_processed ?? 0;
348
+ }
349
+ export function addHistoricalRunBudgetUsage(state, params) {
350
+ const week = getHistoricalWeekState(state, params.weekKey);
351
+ week.files_processed += params.filesProcessed;
352
+ week.triage_spend_usd = roundUsd(week.triage_spend_usd + params.triageSpendUsd);
353
+ week.days[params.dayKey] ??= { files_processed: 0 };
354
+ week.days[params.dayKey].files_processed += params.filesProcessed;
355
+ }
356
+ export function getHistoricalCampaignBudgetWindow(state, now) {
357
+ const weekKey = currentHistoricalWeekKey(now);
358
+ const dayKey = currentHistoricalDayKey(now);
359
+ const week = getHistoricalWeekState(state, weekKey);
360
+ const dailyFilesProcessed = getHistoricalDayFilesProcessed(state, weekKey, dayKey);
361
+ return {
362
+ week_key: weekKey,
363
+ day_key: dayKey,
364
+ weekly_files_processed: week.files_processed,
365
+ daily_files_processed: dailyFilesProcessed,
366
+ remaining_weekly_files: Math.max(HISTORICAL_IMPORT_POLICY.weekly_budget.max_weekly_files_processed -
367
+ week.files_processed, 0),
368
+ remaining_daily_files: Math.max(HISTORICAL_IMPORT_POLICY.weekly_budget.max_daily_files_processed -
369
+ dailyFilesProcessed, 0),
370
+ weekly_triage_spend_usd: roundUsd(week.triage_spend_usd),
371
+ remaining_weekly_triage_spend_usd: Math.max(HISTORICAL_IMPORT_POLICY.weekly_budget.max_weekly_triage_spend_usd -
372
+ roundUsd(week.triage_spend_usd), 0),
373
+ };
374
+ }
375
+ export function countUnsupportedOrJunkFiles(preflight) {
376
+ return preflight.files.filter((file) => !file.supported || file.junk_markers.length > 0).length;
377
+ }
378
+ export function countUnsupportedFormatFiles(preflight) {
379
+ return preflight.files.filter((file) => file.junk_markers.includes("unsupported_format")).length;
380
+ }
381
+ export function countNonUtf8OrCorruptFiles(preflight) {
382
+ return preflight.files.filter((file) => file.junk_markers.includes("non_utf8") ||
383
+ file.notes.includes("unparseable") ||
384
+ file.notes.includes("unreadable")).length;
385
+ }
386
+ export function collectHistoricalBatchQuarantineReasons(params) {
387
+ const total = Math.max(params.preflight.total_files, 1);
388
+ const duplicateRate = params.preflight.duplicate_candidates / total;
389
+ const unsupportedRate = countUnsupportedFormatFiles(params.preflight) / total;
390
+ const corruptRate = countNonUtf8OrCorruptFiles(params.preflight) / total;
391
+ const reasons = [];
392
+ if (params.failedFilesRate > HISTORICAL_IMPORT_POLICY.batch_quarantine.failed_files_rate_gt) {
393
+ reasons.push(`failed files ${formatPercent(params.failedFilesRate)} > ${formatPercent(HISTORICAL_IMPORT_POLICY.batch_quarantine.failed_files_rate_gt)}`);
394
+ }
395
+ if (duplicateRate > HISTORICAL_IMPORT_POLICY.batch_quarantine.duplicate_candidates_rate_gt) {
396
+ reasons.push(`duplicate candidates ${formatPercent(duplicateRate)} > ${formatPercent(HISTORICAL_IMPORT_POLICY.batch_quarantine.duplicate_candidates_rate_gt)}`);
397
+ }
398
+ if (unsupportedRate > HISTORICAL_IMPORT_POLICY.batch_quarantine.unsupported_format_rate_gt) {
399
+ reasons.push(`unsupported format ${formatPercent(unsupportedRate)} > ${formatPercent(HISTORICAL_IMPORT_POLICY.batch_quarantine.unsupported_format_rate_gt)}`);
400
+ }
401
+ if (corruptRate > HISTORICAL_IMPORT_POLICY.batch_quarantine.non_utf8_or_corrupt_rate_gt) {
402
+ reasons.push(`non-UTF-8 or corrupt ${formatPercent(corruptRate)} > ${formatPercent(HISTORICAL_IMPORT_POLICY.batch_quarantine.non_utf8_or_corrupt_rate_gt)}`);
403
+ }
404
+ return reasons;
405
+ }
406
+ export function summarizeHistoricalBatchState(batch, preflight) {
407
+ const counts = {
408
+ archive_only: 0,
409
+ review: 0,
410
+ promote_to_extract: 0,
411
+ duplicate: 0,
412
+ failed: 0,
413
+ skipped: 0,
414
+ quarantined: 0,
415
+ unsupported_or_junk: countUnsupportedOrJunkFiles(preflight),
416
+ };
417
+ for (const fileState of Object.values(batch.files)) {
418
+ if (fileState.terminal_status === "quarantined")
419
+ counts.quarantined += 1;
420
+ else if (fileState.last_result === "failed" || fileState.last_result === "error")
421
+ counts.failed += 1;
422
+ else if (fileState.last_result === "skipped")
423
+ counts.skipped += 1;
424
+ }
425
+ for (const item of Object.values(batch.items)) {
426
+ if (item.last_result === "archive_only")
427
+ counts.archive_only += 1;
428
+ else if (item.last_result === "review")
429
+ counts.review += 1;
430
+ else if (item.last_result === "promote_to_extract" || item.last_result === "duplicate") {
431
+ counts.promote_to_extract += 1;
432
+ }
433
+ if (item.last_result === "duplicate")
434
+ counts.duplicate += 1;
435
+ }
436
+ const unresolvedFiles = Object.values(batch.files)
437
+ .filter((file) => !file.terminal)
438
+ .map((file) => file.file)
439
+ .sort();
440
+ const terminalFiles = Object.values(batch.files)
441
+ .filter((file) => file.terminal)
442
+ .map((file) => file.file)
443
+ .sort();
444
+ return { counts, unresolvedFiles, terminalFiles };
445
+ }
446
+ function summarizeHistoricalRunReport(params) {
447
+ const counts = {
448
+ archive_only: 0,
449
+ review: 0,
450
+ promote_to_extract: 0,
451
+ duplicate: 0,
452
+ failed: 0,
453
+ skipped: 0,
454
+ quarantined: 0,
455
+ unsupported_or_junk: 0,
456
+ };
457
+ const processedFiles = [...new Set(params.processedFiles)].sort();
458
+ const processedFileSet = new Set(processedFiles);
459
+ for (const result of params.results) {
460
+ switch (result.status) {
461
+ case "archive_only":
462
+ counts.archive_only += 1;
463
+ break;
464
+ case "review":
465
+ counts.review += 1;
466
+ break;
467
+ case "completed":
468
+ counts.promote_to_extract += 1;
469
+ break;
470
+ case "duplicate":
471
+ counts.promote_to_extract += 1;
472
+ counts.duplicate += 1;
473
+ break;
474
+ case "failed":
475
+ case "error":
476
+ counts.failed += 1;
477
+ break;
478
+ case "skipped":
479
+ counts.skipped += 1;
480
+ break;
481
+ case "quarantined":
482
+ counts.quarantined += 1;
483
+ break;
484
+ default:
485
+ break;
486
+ }
487
+ }
488
+ for (const file of params.preflight.files) {
489
+ if (!processedFileSet.has(file.name))
490
+ continue;
491
+ if (!file.supported || file.junk_markers.length > 0) {
492
+ counts.unsupported_or_junk += 1;
493
+ }
494
+ }
495
+ return { counts, processedFiles };
496
+ }
497
+ export function snapshotHistoricalCampaignReport(params) {
498
+ const budget = getHistoricalCampaignBudgetWindow(params.state, params.now);
499
+ const { counts: cumulativeCounts, unresolvedFiles, terminalFiles, } = summarizeHistoricalBatchState(params.batch, params.preflight);
500
+ const { counts: runCounts, processedFiles } = summarizeHistoricalRunReport({
501
+ preflight: params.preflight,
502
+ processedFiles: params.processedFiles ?? [],
503
+ results: params.results ?? [],
504
+ });
505
+ return {
506
+ version: 1,
507
+ batch: params.batch.batch,
508
+ source: params.batch.source,
509
+ status: params.status ?? params.batch.status,
510
+ metering_mode: params.batch.metering_mode,
511
+ generated_at: params.now.toISOString(),
512
+ last_started_at: params.batch.last_started_at,
513
+ last_run_at: params.batch.last_run_at,
514
+ run_count: params.batch.run_count,
515
+ total_files: params.batch.total_files,
516
+ run_files: params.runFileCount,
517
+ triage_candidates: params.batch.triage_candidates,
518
+ counts_scope: "last_run",
519
+ counts: runCounts,
520
+ cumulative_counts: cumulativeCounts,
521
+ duplicate_candidates: params.preflight.duplicate_candidates,
522
+ processed_files_scope: "last_run",
523
+ review_backlog_before: params.batch.review_backlog_before,
524
+ review_backlog_after: params.reviewBacklogAfter,
525
+ review_backlog_net_growth: params.reviewBacklogAfter - params.batch.review_backlog_before,
526
+ triage_spend_usd: roundUsd(params.triageSpendUsd),
527
+ triage_spend_note: describeHistoricalTriageSpend(params.batch.metering_mode),
528
+ weekly_files_processed: budget.weekly_files_processed,
529
+ daily_files_processed: budget.daily_files_processed,
530
+ weekly_triage_spend_usd: budget.weekly_triage_spend_usd,
531
+ clean_checks: params.batch.clean_checks,
532
+ policy_flags: params.batch.policy_flags,
533
+ next_batch_size: params.nextBatchSize ?? params.batch.next_batch_size,
534
+ next_action: params.nextAction ?? params.batch.next_action,
535
+ processed_files: processedFiles,
536
+ terminal_files: terminalFiles,
537
+ unresolved_files: unresolvedFiles,
538
+ results: params.results ?? [],
539
+ };
540
+ }
541
+ function recoverHistoricalProcessedFiles(batch) {
542
+ return Object.values(batch.files)
543
+ .filter((file) => file.terminal || file.attempts > 0 || file.item_ids.length > 0)
544
+ .map((file) => file.file)
545
+ .sort((left, right) => left.localeCompare(right));
546
+ }
547
+ function recoverHistoricalResults(batch) {
548
+ const results = [];
549
+ const files = Object.values(batch.files).sort((left, right) => left.file.localeCompare(right.file));
550
+ for (const fileState of files) {
551
+ if (fileState.terminal_status === "quarantined") {
552
+ results.push({
553
+ file: fileState.file,
554
+ status: "quarantined",
555
+ });
556
+ continue;
557
+ }
558
+ const items = fileState.item_ids
559
+ .map((itemId) => batch.items[itemId])
560
+ .filter((item) => Boolean(item))
561
+ .sort((left, right) => left.item_id.localeCompare(right.item_id));
562
+ if (items.length === 0) {
563
+ if (fileState.last_result === "failed" ||
564
+ fileState.last_result === "error" ||
565
+ fileState.last_result === "skipped") {
566
+ results.push({
567
+ file: fileState.file,
568
+ status: fileState.last_result,
569
+ });
570
+ }
571
+ continue;
572
+ }
573
+ for (const item of items) {
574
+ const base = {
575
+ file: item.file,
576
+ ...(item.conversation_id ? { conversation_id: item.conversation_id } : {}),
577
+ ...(item.title ? { title: item.title } : {}),
578
+ };
579
+ switch (item.last_result) {
580
+ case "archive_only":
581
+ results.push({ ...base, status: "archive_only", lane: "archive_only" });
582
+ break;
583
+ case "review":
584
+ results.push({ ...base, status: "review", lane: "review" });
585
+ break;
586
+ case "promote_to_extract":
587
+ results.push({
588
+ ...base,
589
+ status: "completed",
590
+ lane: "promote_to_extract",
591
+ });
592
+ break;
593
+ case "duplicate":
594
+ results.push({
595
+ ...base,
596
+ status: "duplicate",
597
+ lane: "promote_to_extract",
598
+ });
599
+ break;
600
+ case "failed":
601
+ case "error":
602
+ case "quarantined":
603
+ results.push({
604
+ ...base,
605
+ status: item.last_result,
606
+ ...(item.triage?.lane ? { lane: item.triage.lane } : {}),
607
+ });
608
+ break;
609
+ default:
610
+ break;
611
+ }
612
+ }
613
+ }
614
+ return results;
615
+ }
616
+ export function snapshotHistoricalNoOpReport(params) {
617
+ const budget = getHistoricalCampaignBudgetWindow(params.state, params.now);
618
+ const { counts: cumulativeCounts, unresolvedFiles, terminalFiles, } = summarizeHistoricalBatchState(params.batch, params.preflight);
619
+ const results = recoverHistoricalResults(params.batch);
620
+ // No-op rerun of an already-terminal batch: the visible report IS the
621
+ // batch's cumulative state. Emit cumulative values in `counts` /
622
+ // `processed_files` and flip the scope fields so readers know this is
623
+ // not a last-run slice. Run-level numbers (run_files, triage_spend_usd)
624
+ // stay zero because no new work happened.
625
+ return {
626
+ version: 1,
627
+ batch: params.batch.batch,
628
+ source: params.batch.source,
629
+ status: params.batch.status,
630
+ metering_mode: params.batch.metering_mode,
631
+ generated_at: params.now.toISOString(),
632
+ last_started_at: params.batch.last_started_at,
633
+ last_run_at: params.batch.last_run_at,
634
+ run_count: params.batch.run_count,
635
+ total_files: params.batch.total_files,
636
+ run_files: 0,
637
+ triage_candidates: 0,
638
+ counts_scope: "cumulative",
639
+ counts: cumulativeCounts,
640
+ cumulative_counts: cumulativeCounts,
641
+ duplicate_candidates: params.preflight.duplicate_candidates,
642
+ processed_files_scope: "cumulative",
643
+ review_backlog_before: params.reviewBacklogNow,
644
+ review_backlog_after: params.reviewBacklogNow,
645
+ review_backlog_net_growth: 0,
646
+ triage_spend_usd: 0,
647
+ triage_spend_note: describeHistoricalTriageSpend(params.batch.metering_mode),
648
+ weekly_files_processed: budget.weekly_files_processed,
649
+ daily_files_processed: budget.daily_files_processed,
650
+ weekly_triage_spend_usd: budget.weekly_triage_spend_usd,
651
+ clean_checks: params.batch.clean_checks,
652
+ policy_flags: params.batch.policy_flags,
653
+ next_batch_size: params.batch.next_batch_size,
654
+ next_action: params.nextAction,
655
+ processed_files: terminalFiles,
656
+ terminal_files: terminalFiles,
657
+ unresolved_files: unresolvedFiles,
658
+ results,
659
+ };
660
+ }
661
+ export function evaluateHistoricalBatch(params) {
662
+ const budget = getHistoricalCampaignBudgetWindow(params.state, params.now);
663
+ const { counts, unresolvedFiles, terminalFiles } = summarizeHistoricalBatchState(params.batch, params.preflight);
664
+ params.batch.counts = counts;
665
+ params.batch.review_backlog_after = params.reviewBacklogAfter;
666
+ params.batch.triage_spend_usd = roundUsd(params.batch.triage_spend_usd + params.triageSpendUsd);
667
+ params.batch.report_path = params.reportPath;
668
+ const totalFiles = Math.max(params.batch.total_files, 1);
669
+ const failedFilesRate = counts.failed / totalFiles;
670
+ const unsupportedOrJunkRate = counts.unsupported_or_junk / totalFiles;
671
+ const reviewQueueNetGrowth = params.reviewBacklogAfter - params.batch.review_backlog_before;
672
+ const archiveOnlySample = {
673
+ ...params.batch.archive_only_sample,
674
+ false_discard_rate: params.batch.archive_only_sample.reviewed_count > 0
675
+ ? params.batch.archive_only_sample.false_discards /
676
+ params.batch.archive_only_sample.reviewed_count
677
+ : null,
678
+ };
679
+ archiveOnlySample.passed =
680
+ archiveOnlySample.reviewed_count <= counts.archive_only &&
681
+ archiveOnlySample.reviewed_count >= archiveOnlySample.required_sample_size &&
682
+ archiveOnlySample.false_discard_rate !== null &&
683
+ archiveOnlySample.false_discard_rate <=
684
+ HISTORICAL_IMPORT_POLICY.clean_batch.max_false_discard_rate;
685
+ params.batch.archive_only_sample = archiveOnlySample;
686
+ const cleanReasons = [];
687
+ const archiveOnlySampleInvalid = archiveOnlySample.reviewed_count > counts.archive_only;
688
+ if (archiveOnlySampleInvalid) {
689
+ cleanReasons.push(`archive_only sample invalid (${archiveOnlySample.reviewed_count} reviewed > ${counts.archive_only} available archive_only items)`);
690
+ }
691
+ else if (!archiveOnlySample.passed) {
692
+ cleanReasons.push(archiveOnlySample.reviewed_count >= archiveOnlySample.required_sample_size
693
+ ? `archive_only false-discard rate ${formatPercent(archiveOnlySample.false_discard_rate ?? 0)} > ${formatPercent(HISTORICAL_IMPORT_POLICY.clean_batch.max_false_discard_rate)}`
694
+ : `archive_only sample pending (${archiveOnlySample.reviewed_count}/${archiveOnlySample.required_sample_size} reviewed)`);
695
+ }
696
+ if (failedFilesRate > HISTORICAL_IMPORT_POLICY.clean_batch.max_failed_files_rate) {
697
+ cleanReasons.push(`failed files ${formatPercent(failedFilesRate)} > ${formatPercent(HISTORICAL_IMPORT_POLICY.clean_batch.max_failed_files_rate)}`);
698
+ }
699
+ if (unsupportedOrJunkRate > HISTORICAL_IMPORT_POLICY.clean_batch.max_unsupported_or_junk_rate) {
700
+ cleanReasons.push(`unsupported or junk files ${formatPercent(unsupportedOrJunkRate)} > ${formatPercent(HISTORICAL_IMPORT_POLICY.clean_batch.max_unsupported_or_junk_rate)}`);
701
+ }
702
+ if (reviewQueueNetGrowth > HISTORICAL_IMPORT_POLICY.clean_batch.max_review_queue_net_growth) {
703
+ cleanReasons.push(`review queue net growth ${reviewQueueNetGrowth} > ${HISTORICAL_IMPORT_POLICY.clean_batch.max_review_queue_net_growth}`);
704
+ }
705
+ const laneDenominator = Math.max(counts.archive_only + counts.review + counts.promote_to_extract, 1);
706
+ const reviewLaneRate = counts.review / laneDenominator;
707
+ const archiveOnlyLaneRate = counts.archive_only / laneDenominator;
708
+ const promoteLaneRate = counts.promote_to_extract / laneDenominator;
709
+ const promoteLowStreak = countLowPromoteStreak(params.state, params.batch.batch, promoteLaneRate);
710
+ const batchQuarantineReasons = collectHistoricalBatchQuarantineReasons({
711
+ preflight: params.preflight,
712
+ failedFilesRate,
713
+ });
714
+ const weeklyFilesProcessed = budget.weekly_files_processed;
715
+ const dailyFilesProcessed = budget.daily_files_processed;
716
+ const weeklyTriageSpendUsd = budget.weekly_triage_spend_usd;
717
+ const stopDueWeeklySpend = params.batch.metering_mode === "openai_usd" &&
718
+ weeklyTriageSpendUsd >
719
+ HISTORICAL_IMPORT_POLICY.weekly_budget.max_weekly_triage_spend_usd;
720
+ const stopDueReviewBacklog = params.reviewBacklogAfter > HISTORICAL_IMPORT_POLICY.stop_rules.review_backlog_open_items_gt;
721
+ params.batch.clean_checks = {
722
+ archive_only_sample: archiveOnlySample,
723
+ failed_files_rate: failedFilesRate,
724
+ unsupported_or_junk_rate: unsupportedOrJunkRate,
725
+ review_queue_net_growth: reviewQueueNetGrowth,
726
+ review_queue_net_growth_passed: reviewQueueNetGrowth <=
727
+ HISTORICAL_IMPORT_POLICY.clean_batch.max_review_queue_net_growth,
728
+ clean_batch: cleanReasons.length === 0,
729
+ reasons: cleanReasons,
730
+ };
731
+ params.batch.policy_flags = {
732
+ stop_due_weekly_spend: stopDueWeeklySpend,
733
+ stop_due_review_backlog: stopDueReviewBacklog,
734
+ review_lane_rate: reviewLaneRate,
735
+ review_lane_gt_40_percent: reviewLaneRate > HISTORICAL_IMPORT_POLICY.stop_rules.review_lane_rate_gt,
736
+ archive_only_lane_rate: archiveOnlyLaneRate,
737
+ archive_only_lane_gt_85_percent: archiveOnlyLaneRate > HISTORICAL_IMPORT_POLICY.stop_rules.archive_only_lane_rate_gt,
738
+ promote_to_extract_lane_rate: promoteLaneRate,
739
+ promote_to_extract_lt_5_percent_streak: promoteLowStreak,
740
+ duplicate_candidates_rate: params.preflight.duplicate_candidates / totalFiles,
741
+ unsupported_format_rate: countUnsupportedFormatFiles(params.preflight) / totalFiles,
742
+ non_utf8_or_corrupt_rate: countNonUtf8OrCorruptFiles(params.preflight) / totalFiles,
743
+ batch_quarantine_reasons: batchQuarantineReasons,
744
+ };
745
+ if (batchQuarantineReasons.length > 0) {
746
+ params.batch.status = "quarantined";
747
+ }
748
+ else if (unresolvedFiles.length > 0) {
749
+ params.batch.status =
750
+ params.incompleteStatus ??
751
+ (counts.failed > 0 ? "failed" : "running");
752
+ }
753
+ else if (!params.batch.clean_checks.clean_batch ||
754
+ stopDueWeeklySpend ||
755
+ stopDueReviewBacklog ||
756
+ params.batch.policy_flags.review_lane_gt_40_percent ||
757
+ params.batch.policy_flags.archive_only_lane_gt_85_percent ||
758
+ params.batch.policy_flags.promote_to_extract_lt_5_percent_streak >=
759
+ HISTORICAL_IMPORT_POLICY.stop_rules.promote_to_extract_low_streak_batches) {
760
+ params.batch.status = "completed_with_warnings";
761
+ }
762
+ else {
763
+ params.batch.status = "completed";
764
+ }
765
+ params.batch.next_batch_size =
766
+ params.batch.status === "running"
767
+ ? normalizeBatchLevel(params.batch.total_files)
768
+ : recommendNextBatchSize(params.state, params.batch);
769
+ params.batch.next_action = recommendNextAction(params.batch, params.preflight);
770
+ params.batch.last_run_at = params.now.toISOString();
771
+ recomputeHistoricalCampaignSummary(params.state);
772
+ return {
773
+ report: snapshotHistoricalCampaignReport({
774
+ state: params.state,
775
+ batch: params.batch,
776
+ preflight: params.preflight,
777
+ now: params.now,
778
+ runFileCount: params.runFileCount,
779
+ reviewBacklogAfter: params.reviewBacklogAfter,
780
+ triageSpendUsd: params.triageSpendUsd,
781
+ ...(params.processedFiles
782
+ ? { processedFiles: params.processedFiles }
783
+ : {}),
784
+ ...(params.results ? { results: params.results } : {}),
785
+ }),
786
+ weeklyFilesProcessed,
787
+ dailyFilesProcessed,
788
+ weeklyTriageSpendUsd,
789
+ };
790
+ }
791
+ export function recomputeHistoricalCampaignSummary(state) {
792
+ const summary = makeSummary();
793
+ const batches = Object.values(state.batches);
794
+ summary.total_batches_seen = batches.length;
795
+ summary.files_processed = Object.values(state.weeks).reduce((total, week) => total + week.files_processed, 0);
796
+ for (const batch of batches) {
797
+ if (batch.status === "completed")
798
+ summary.batches_completed += 1;
799
+ if (batch.status === "completed_with_warnings")
800
+ summary.batches_completed_with_warnings += 1;
801
+ if (batch.status === "failed")
802
+ summary.batches_failed += 1;
803
+ if (batch.status === "quarantined")
804
+ summary.batches_quarantined += 1;
805
+ summary.lane_counts.archive_only += batch.counts.archive_only;
806
+ summary.lane_counts.review += batch.counts.review;
807
+ summary.lane_counts.promote_to_extract += batch.counts.promote_to_extract;
808
+ summary.lane_counts.quarantined += batch.counts.quarantined;
809
+ }
810
+ state.summary = summary;
811
+ }
812
+ export async function writeHistoricalCampaignReport(reportPath, report) {
813
+ await atomicWrite(reportPath, JSON.stringify(report, null, 2) + "\n");
814
+ }
815
+ export function historicalCampaignReportPath(batchDir) {
816
+ return path.join(batchDir, "campaign-report.json");
817
+ }
818
+ export function formatHistoricalCampaignSummary(report) {
819
+ const triageSpendLine = report.metering_mode === "unmetered_codex_cli"
820
+ ? "unmetered (Codex CLI override)"
821
+ : `$${report.triage_spend_usd.toFixed(4)}`;
822
+ const weeklySpendLine = report.metering_mode === "unmetered_codex_cli"
823
+ ? `OpenAI-only $${report.weekly_triage_spend_usd.toFixed(4)}/$${HISTORICAL_IMPORT_POLICY.weekly_budget.max_weekly_triage_spend_usd.toFixed(2)}`
824
+ : `$${report.weekly_triage_spend_usd.toFixed(4)}/$${HISTORICAL_IMPORT_POLICY.weekly_budget.max_weekly_triage_spend_usd.toFixed(2)}`;
825
+ return (`\nHistorical import campaign: ${report.batch}\n` +
826
+ ` Status: ${report.status}\n` +
827
+ ` Metering mode: ${report.metering_mode}\n` +
828
+ ` Files in batch: ${report.total_files}\n` +
829
+ ` Files touched this run: ${report.run_files}\n` +
830
+ ` Triage candidates: ${report.triage_candidates}\n` +
831
+ ` archive_only (run): ${report.counts.archive_only}\n` +
832
+ ` review (run): ${report.counts.review}\n` +
833
+ ` promote_to_extract(run): ${report.counts.promote_to_extract}\n` +
834
+ ` quarantined (run): ${report.counts.quarantined}\n` +
835
+ ` failed (run): ${report.counts.failed}\n` +
836
+ ` duplicates (run): ${report.counts.duplicate}\n` +
837
+ ` archive_only (batch): ${report.cumulative_counts.archive_only}\n` +
838
+ ` review (batch): ${report.cumulative_counts.review}\n` +
839
+ ` promote_to_extract(batch): ${report.cumulative_counts.promote_to_extract}\n` +
840
+ ` quarantined (batch): ${report.cumulative_counts.quarantined}\n` +
841
+ ` failed (batch): ${report.cumulative_counts.failed}\n` +
842
+ ` duplicates (batch): ${report.cumulative_counts.duplicate}\n` +
843
+ ` review backlog now: ${report.review_backlog_after} (net ${formatSigned(report.review_backlog_net_growth)})\n` +
844
+ ` triage spend this run: ${triageSpendLine}\n` +
845
+ ` weekly files: ${report.weekly_files_processed}/${HISTORICAL_IMPORT_POLICY.weekly_budget.max_weekly_files_processed}\n` +
846
+ ` daily files: ${report.daily_files_processed}/${HISTORICAL_IMPORT_POLICY.weekly_budget.max_daily_files_processed}\n` +
847
+ ` weekly triage spend: ${weeklySpendLine}\n` +
848
+ ` spend note: ${report.triage_spend_note}\n` +
849
+ ` Clean batch: ${report.clean_checks.clean_batch ? "yes" : "no"}\n` +
850
+ ` Next batch size: ${report.next_batch_size}\n` +
851
+ ` Next action: ${report.next_action}\n`);
852
+ }
853
+ export function reportHistoricalCampaignBlockers(params) {
854
+ const budget = getHistoricalCampaignBudgetWindow(params.state, params.now);
855
+ const blockers = [];
856
+ if (params.meteringMode === "openai_usd") {
857
+ if (budget.weekly_triage_spend_usd >
858
+ HISTORICAL_IMPORT_POLICY.weekly_budget.max_weekly_triage_spend_usd) {
859
+ blockers.push(`weekly triage spend already exceeds $${HISTORICAL_IMPORT_POLICY.weekly_budget.max_weekly_triage_spend_usd.toFixed(2)}`);
860
+ }
861
+ }
862
+ if (params.reviewBacklogBefore > HISTORICAL_IMPORT_POLICY.stop_rules.review_backlog_open_items_gt) {
863
+ blockers.push(`review backlog ${params.reviewBacklogBefore} exceeds ${HISTORICAL_IMPORT_POLICY.stop_rules.review_backlog_open_items_gt}`);
864
+ }
865
+ if (budget.remaining_daily_files <= 0) {
866
+ blockers.push(`daily file budget ${budget.daily_files_processed}/${HISTORICAL_IMPORT_POLICY.weekly_budget.max_daily_files_processed} is already exhausted`);
867
+ }
868
+ if (budget.remaining_weekly_files <= 0) {
869
+ blockers.push(`weekly file budget ${budget.weekly_files_processed}/${HISTORICAL_IMPORT_POLICY.weekly_budget.max_weekly_files_processed} is already exhausted`);
870
+ }
871
+ if (params.meteringMode === "openai_usd" &&
872
+ (params.triageCandidates ?? 0) > 0 &&
873
+ typeof params.triageBatchCostCapUsd === "number" &&
874
+ params.triageBatchCostCapUsd > budget.remaining_weekly_triage_spend_usd) {
875
+ blockers.push(`remaining weekly triage spend $${budget.remaining_weekly_triage_spend_usd.toFixed(4)} is below the configured per-run triage cap $${params.triageBatchCostCapUsd.toFixed(4)}`);
876
+ }
877
+ return blockers;
878
+ }
879
+ function recommendNextBatchSize(state, batch) {
880
+ const currentLevel = normalizeBatchLevel(batch.total_files);
881
+ if (!batch.clean_checks.clean_batch) {
882
+ if (currentLevel === HISTORICAL_IMPORT_POLICY.batch_sizes.max_production) {
883
+ return HISTORICAL_IMPORT_POLICY.batch_sizes.step_up;
884
+ }
885
+ return HISTORICAL_IMPORT_POLICY.batch_sizes.initial;
886
+ }
887
+ if (isScaleUpBlocked(batch)) {
888
+ return currentLevel;
889
+ }
890
+ if (currentLevel === HISTORICAL_IMPORT_POLICY.batch_sizes.max_production) {
891
+ return HISTORICAL_IMPORT_POLICY.batch_sizes.max_production;
892
+ }
893
+ const streak = countCleanLevelStreak(state, batch.batch, currentLevel);
894
+ if (currentLevel === HISTORICAL_IMPORT_POLICY.batch_sizes.initial &&
895
+ streak >= HISTORICAL_IMPORT_POLICY.scale_up.clean_batches_required_per_level) {
896
+ return HISTORICAL_IMPORT_POLICY.batch_sizes.step_up;
897
+ }
898
+ if (currentLevel === HISTORICAL_IMPORT_POLICY.batch_sizes.step_up &&
899
+ streak >= HISTORICAL_IMPORT_POLICY.scale_up.clean_batches_required_per_level) {
900
+ return HISTORICAL_IMPORT_POLICY.batch_sizes.max_production;
901
+ }
902
+ return currentLevel;
903
+ }
904
+ function recommendNextAction(batch, preflight) {
905
+ if (batch.policy_flags.batch_quarantine_reasons.length > 0) {
906
+ return `Quarantine this batch for manual inspection: ${batch.policy_flags.batch_quarantine_reasons.join("; ")}.`;
907
+ }
908
+ if (batch.policy_flags.stop_due_weekly_spend) {
909
+ return `Stop historical import this week. Weekly triage spend exceeded $${HISTORICAL_IMPORT_POLICY.weekly_budget.max_weekly_triage_spend_usd.toFixed(2)}.`;
910
+ }
911
+ if (batch.policy_flags.stop_due_review_backlog) {
912
+ return `Stop historical import. Review backlog exceeds ${HISTORICAL_IMPORT_POLICY.stop_rules.review_backlog_open_items_gt} open items.`;
913
+ }
914
+ const unresolved = Object.values(batch.files).filter((file) => !file.terminal).length;
915
+ if (unresolved > 0) {
916
+ return `Resume only unresolved files. ${unresolved} file(s) still need terminal outcomes.`;
917
+ }
918
+ if (!batch.clean_checks.archive_only_sample.passed) {
919
+ if (batch.archive_only_sample.reviewed_count > batch.counts.archive_only) {
920
+ return `Fix archive_only audit state in campaign-state.json. ${batch.archive_only_sample.reviewed_count} reviewed exceeds ${batch.counts.archive_only} available archive_only items for this batch.`;
921
+ }
922
+ if (batch.counts.archive_only < HISTORICAL_IMPORT_POLICY.clean_batch.archive_only_sample_size) {
923
+ return `Only ${batch.counts.archive_only} archive_only item(s) exist in this batch. Review all ${batch.counts.archive_only} now and do not scale up until the 100-item audit gate is satisfied by campaign policy.`;
924
+ }
925
+ return `Audit ${HISTORICAL_IMPORT_POLICY.clean_batch.archive_only_sample_size} archive_only items and update campaign-state.json before scaling up.`;
926
+ }
927
+ if (batch.policy_flags.review_lane_gt_40_percent) {
928
+ return "Hold current batch size. Review lane exceeded 40% of the batch.";
929
+ }
930
+ if (batch.policy_flags.archive_only_lane_gt_85_percent) {
931
+ return "Inspect source quality before continuing. archive_only exceeded 85% of the batch.";
932
+ }
933
+ if (batch.policy_flags.promote_to_extract_lt_5_percent_streak >=
934
+ HISTORICAL_IMPORT_POLICY.stop_rules.promote_to_extract_low_streak_batches) {
935
+ return "Tighten staging or source selection before continuing. promote_to_extract stayed below 5% for two consecutive batches.";
936
+ }
937
+ if (batch.next_batch_size > normalizeBatchLevel(batch.total_files)) {
938
+ return `Scale the next staged batch to ${batch.next_batch_size} files.`;
939
+ }
940
+ if (preflight.total_files > HISTORICAL_IMPORT_POLICY.batch_sizes.max_production) {
941
+ return `Future staged batches must be split to ${HISTORICAL_IMPORT_POLICY.batch_sizes.max_production} files or fewer.`;
942
+ }
943
+ return `Continue at ${batch.next_batch_size} files until two consecutive clean batches are recorded at that level.`;
944
+ }
945
+ function describeHistoricalTriageSpend(meteringMode) {
946
+ return meteringMode === "unmetered_codex_cli"
947
+ ? "Codex CLI historical backfill override is unmetered by OpenAI USD."
948
+ : "OpenAI USD metering.";
949
+ }
950
+ function countCleanLevelStreak(state, currentBatchName, level) {
951
+ const batches = Object.values(state.batches)
952
+ .filter((batch) => batch.last_run_at)
953
+ .sort((a, b) => (b.last_run_at ?? "").localeCompare(a.last_run_at ?? ""));
954
+ let streak = 0;
955
+ for (const batch of batches) {
956
+ if (normalizeBatchLevel(batch.total_files) !== level) {
957
+ if (batch.batch === currentBatchName)
958
+ continue;
959
+ break;
960
+ }
961
+ if (!batch.clean_checks.clean_batch || isScaleUpBlocked(batch))
962
+ break;
963
+ streak += 1;
964
+ }
965
+ return streak;
966
+ }
967
+ function isScaleUpBlocked(batch) {
968
+ return (batch.policy_flags.stop_due_weekly_spend ||
969
+ batch.policy_flags.stop_due_review_backlog ||
970
+ batch.policy_flags.review_lane_gt_40_percent ||
971
+ batch.policy_flags.archive_only_lane_gt_85_percent ||
972
+ batch.policy_flags.promote_to_extract_lt_5_percent_streak >=
973
+ HISTORICAL_IMPORT_POLICY.stop_rules.promote_to_extract_low_streak_batches);
974
+ }
975
+ function countLowPromoteStreak(state, currentBatchName, currentPromoteRate) {
976
+ const batches = Object.values(state.batches)
977
+ .filter((batch) => batch.last_run_at)
978
+ .sort((a, b) => (b.last_run_at ?? "").localeCompare(a.last_run_at ?? ""));
979
+ let streak = 0;
980
+ for (const batch of batches) {
981
+ const rate = batch.batch === currentBatchName
982
+ ? currentPromoteRate
983
+ : batch.policy_flags.promote_to_extract_lane_rate;
984
+ if (rate < HISTORICAL_IMPORT_POLICY.stop_rules.promote_to_extract_lane_rate_lt) {
985
+ streak += 1;
986
+ continue;
987
+ }
988
+ break;
989
+ }
990
+ return streak;
991
+ }
992
+ function normalizeBatchLevel(totalFiles) {
993
+ if (totalFiles <= HISTORICAL_IMPORT_POLICY.batch_sizes.initial) {
994
+ return HISTORICAL_IMPORT_POLICY.batch_sizes.initial;
995
+ }
996
+ if (totalFiles <= HISTORICAL_IMPORT_POLICY.batch_sizes.step_up) {
997
+ return HISTORICAL_IMPORT_POLICY.batch_sizes.step_up;
998
+ }
999
+ return HISTORICAL_IMPORT_POLICY.batch_sizes.max_production;
1000
+ }
1001
+ function formatPercent(value) {
1002
+ return `${(value * 100).toFixed(1)}%`;
1003
+ }
1004
+ function formatSigned(value) {
1005
+ return value >= 0 ? `+${value}` : String(value);
1006
+ }
1007
+ function roundUsd(value) {
1008
+ return Number(value.toFixed(4));
1009
+ }
1010
+ //# sourceMappingURL=historical-campaign.js.map