daftari 1.29.0 → 1.31.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 (369) hide show
  1. package/CHANGELOG.md +281 -0
  2. package/README.md +263 -9
  3. package/dist/access/rbac.d.ts +1 -0
  4. package/dist/access/rbac.d.ts.map +1 -1
  5. package/dist/access/rbac.js +7 -0
  6. package/dist/access/rbac.js.map +1 -1
  7. package/dist/asof/git-read.d.ts +17 -0
  8. package/dist/asof/git-read.d.ts.map +1 -0
  9. package/dist/asof/git-read.js +163 -0
  10. package/dist/asof/git-read.js.map +1 -0
  11. package/dist/asof/index.d.ts +2 -0
  12. package/dist/asof/index.d.ts.map +1 -0
  13. package/dist/asof/index.js +151 -0
  14. package/dist/asof/index.js.map +1 -0
  15. package/dist/asof/report.d.ts +11 -0
  16. package/dist/asof/report.d.ts.map +1 -0
  17. package/dist/asof/report.js +119 -0
  18. package/dist/asof/report.js.map +1 -0
  19. package/dist/asof/snapshot.d.ts +72 -0
  20. package/dist/asof/snapshot.d.ts.map +1 -0
  21. package/dist/asof/snapshot.js +207 -0
  22. package/dist/asof/snapshot.js.map +1 -0
  23. package/dist/audit/checks/broken_refs.d.ts +1 -1
  24. package/dist/audit/checks/broken_refs.d.ts.map +1 -1
  25. package/dist/audit/checks/broken_refs.js +77 -22
  26. package/dist/audit/checks/broken_refs.js.map +1 -1
  27. package/dist/audit/collect.d.ts +1 -0
  28. package/dist/audit/collect.d.ts.map +1 -1
  29. package/dist/audit/collect.js +22 -2
  30. package/dist/audit/collect.js.map +1 -1
  31. package/dist/audit/index.d.ts.map +1 -1
  32. package/dist/audit/index.js +9 -3
  33. package/dist/audit/index.js.map +1 -1
  34. package/dist/audit/links.d.ts.map +1 -1
  35. package/dist/audit/links.js +9 -3
  36. package/dist/audit/links.js.map +1 -1
  37. package/dist/audit/report.d.ts.map +1 -1
  38. package/dist/audit/report.js +2 -0
  39. package/dist/audit/report.js.map +1 -1
  40. package/dist/audit/types.d.ts +4 -1
  41. package/dist/audit/types.d.ts.map +1 -1
  42. package/dist/audit/types.js.map +1 -1
  43. package/dist/backfill/apply.js +2 -2
  44. package/dist/backfill/apply.js.map +1 -1
  45. package/dist/backfill/derive.d.ts.map +1 -1
  46. package/dist/backfill/derive.js +1 -0
  47. package/dist/backfill/derive.js.map +1 -1
  48. package/dist/backfill/plan.js +2 -2
  49. package/dist/backfill/plan.js.map +1 -1
  50. package/dist/cli.d.ts.map +1 -1
  51. package/dist/cli.js +36 -0
  52. package/dist/cli.js.map +1 -1
  53. package/dist/consolidate/call-budget.d.ts +3 -0
  54. package/dist/consolidate/call-budget.d.ts.map +1 -0
  55. package/dist/consolidate/call-budget.js +37 -0
  56. package/dist/consolidate/call-budget.js.map +1 -0
  57. package/dist/consolidate/constants.d.ts +1 -0
  58. package/dist/consolidate/constants.d.ts.map +1 -1
  59. package/dist/consolidate/constants.js +5 -0
  60. package/dist/consolidate/constants.js.map +1 -1
  61. package/dist/consolidate/index.d.ts.map +1 -1
  62. package/dist/consolidate/index.js +96 -27
  63. package/dist/consolidate/index.js.map +1 -1
  64. package/dist/court/docket.d.ts +39 -0
  65. package/dist/court/docket.d.ts.map +1 -0
  66. package/dist/court/docket.js +103 -0
  67. package/dist/court/docket.js.map +1 -0
  68. package/dist/court/index.d.ts +2 -0
  69. package/dist/court/index.d.ts.map +1 -0
  70. package/dist/court/index.js +169 -0
  71. package/dist/court/index.js.map +1 -0
  72. package/dist/court/precedent.d.ts +18 -0
  73. package/dist/court/precedent.d.ts.map +1 -0
  74. package/dist/court/precedent.js +89 -0
  75. package/dist/court/precedent.js.map +1 -0
  76. package/dist/court/report.d.ts +10 -0
  77. package/dist/court/report.d.ts.map +1 -0
  78. package/dist/court/report.js +77 -0
  79. package/dist/court/report.js.map +1 -0
  80. package/dist/curation/consumes.d.ts +24 -0
  81. package/dist/curation/consumes.d.ts.map +1 -0
  82. package/dist/curation/consumes.js +122 -0
  83. package/dist/curation/consumes.js.map +1 -0
  84. package/dist/curation/edge-staleness.d.ts +47 -0
  85. package/dist/curation/edge-staleness.d.ts.map +1 -0
  86. package/dist/curation/edge-staleness.js +258 -0
  87. package/dist/curation/edge-staleness.js.map +1 -0
  88. package/dist/curation/edges.d.ts.map +1 -1
  89. package/dist/curation/edges.js +164 -10
  90. package/dist/curation/edges.js.map +1 -1
  91. package/dist/curation/lint.d.ts +4 -1
  92. package/dist/curation/lint.d.ts.map +1 -1
  93. package/dist/curation/lint.js +61 -6
  94. package/dist/curation/lint.js.map +1 -1
  95. package/dist/curation/provenance.d.ts +2 -0
  96. package/dist/curation/provenance.d.ts.map +1 -1
  97. package/dist/curation/provenance.js +2 -0
  98. package/dist/curation/provenance.js.map +1 -1
  99. package/dist/curation/read-log.d.ts +19 -0
  100. package/dist/curation/read-log.d.ts.map +1 -0
  101. package/dist/curation/read-log.js +120 -0
  102. package/dist/curation/read-log.js.map +1 -0
  103. package/dist/curation/review-throughput.d.ts +24 -0
  104. package/dist/curation/review-throughput.d.ts.map +1 -0
  105. package/dist/curation/review-throughput.js +102 -0
  106. package/dist/curation/review-throughput.js.map +1 -0
  107. package/dist/curation/staged-actions.d.ts +11 -1
  108. package/dist/curation/staged-actions.d.ts.map +1 -1
  109. package/dist/curation/staged-actions.js +117 -30
  110. package/dist/curation/staged-actions.js.map +1 -1
  111. package/dist/curation/staleness.js +1 -1
  112. package/dist/curation/staleness.js.map +1 -1
  113. package/dist/curation/structural.d.ts +16 -0
  114. package/dist/curation/structural.d.ts.map +1 -0
  115. package/dist/curation/structural.js +64 -0
  116. package/dist/curation/structural.js.map +1 -0
  117. package/dist/curation/tension-access.d.ts +7 -0
  118. package/dist/curation/tension-access.d.ts.map +1 -0
  119. package/dist/curation/tension-access.js +44 -0
  120. package/dist/curation/tension-access.js.map +1 -0
  121. package/dist/curation/tension-blast.d.ts +6 -1
  122. package/dist/curation/tension-blast.d.ts.map +1 -1
  123. package/dist/curation/tension-blast.js +11 -2
  124. package/dist/curation/tension-blast.js.map +1 -1
  125. package/dist/curation/tension-clusters.d.ts +1 -1
  126. package/dist/curation/tension-clusters.d.ts.map +1 -1
  127. package/dist/curation/tension-clusters.js +5 -2
  128. package/dist/curation/tension-clusters.js.map +1 -1
  129. package/dist/curation/tension.d.ts +6 -2
  130. package/dist/curation/tension.d.ts.map +1 -1
  131. package/dist/curation/tension.js +86 -35
  132. package/dist/curation/tension.js.map +1 -1
  133. package/dist/curation/tier0.d.ts +27 -0
  134. package/dist/curation/tier0.d.ts.map +1 -0
  135. package/dist/curation/tier0.js +196 -0
  136. package/dist/curation/tier0.js.map +1 -0
  137. package/dist/curation/tier1.d.ts +30 -0
  138. package/dist/curation/tier1.d.ts.map +1 -0
  139. package/dist/curation/tier1.js +142 -0
  140. package/dist/curation/tier1.js.map +1 -0
  141. package/dist/curation/tier2.d.ts +43 -0
  142. package/dist/curation/tier2.d.ts.map +1 -0
  143. package/dist/curation/tier2.js +182 -0
  144. package/dist/curation/tier2.js.map +1 -0
  145. package/dist/curation/vault-docs.d.ts +5 -1
  146. package/dist/curation/vault-docs.d.ts.map +1 -1
  147. package/dist/curation/vault-docs.js +15 -1
  148. package/dist/curation/vault-docs.js.map +1 -1
  149. package/dist/eval/generate.js +22 -5
  150. package/dist/eval/generate.js.map +1 -1
  151. package/dist/eval/index.d.ts.map +1 -1
  152. package/dist/eval/index.js +173 -25
  153. package/dist/eval/index.js.map +1 -1
  154. package/dist/eval/llm-openrouter.d.ts +9 -0
  155. package/dist/eval/llm-openrouter.d.ts.map +1 -0
  156. package/dist/eval/llm-openrouter.js +171 -0
  157. package/dist/eval/llm-openrouter.js.map +1 -0
  158. package/dist/eval/llm.js +1 -1
  159. package/dist/eval/llm.js.map +1 -1
  160. package/dist/eval/prune.d.ts +24 -0
  161. package/dist/eval/prune.d.ts.map +1 -0
  162. package/dist/eval/prune.js +83 -0
  163. package/dist/eval/prune.js.map +1 -0
  164. package/dist/eval/storage.d.ts +3 -0
  165. package/dist/eval/storage.d.ts.map +1 -1
  166. package/dist/eval/storage.js +14 -0
  167. package/dist/eval/storage.js.map +1 -1
  168. package/dist/frontmatter/parser.d.ts +1 -0
  169. package/dist/frontmatter/parser.d.ts.map +1 -1
  170. package/dist/frontmatter/parser.js +12 -0
  171. package/dist/frontmatter/parser.js.map +1 -1
  172. package/dist/frontmatter/schema.d.ts.map +1 -1
  173. package/dist/frontmatter/schema.js +38 -3
  174. package/dist/frontmatter/schema.js.map +1 -1
  175. package/dist/frontmatter/types.d.ts +4 -1
  176. package/dist/frontmatter/types.d.ts.map +1 -1
  177. package/dist/frontmatter/types.js +8 -0
  178. package/dist/frontmatter/types.js.map +1 -1
  179. package/dist/import/index.d.ts.map +1 -1
  180. package/dist/import/index.js +44 -9
  181. package/dist/import/index.js.map +1 -1
  182. package/dist/import/langgraph-store.d.ts +53 -0
  183. package/dist/import/langgraph-store.d.ts.map +1 -0
  184. package/dist/import/langgraph-store.js +292 -0
  185. package/dist/import/langgraph-store.js.map +1 -0
  186. package/dist/index.d.ts +5 -0
  187. package/dist/index.d.ts.map +1 -1
  188. package/dist/index.js +56 -18
  189. package/dist/index.js.map +1 -1
  190. package/dist/lifecycle/lock.d.ts +9 -1
  191. package/dist/lifecycle/lock.d.ts.map +1 -1
  192. package/dist/lifecycle/lock.js +34 -9
  193. package/dist/lifecycle/lock.js.map +1 -1
  194. package/dist/okf/export.d.ts +12 -0
  195. package/dist/okf/export.d.ts.map +1 -0
  196. package/dist/okf/export.js +115 -0
  197. package/dist/okf/export.js.map +1 -0
  198. package/dist/okf/import.d.ts +24 -0
  199. package/dist/okf/import.d.ts.map +1 -0
  200. package/dist/okf/import.js +107 -0
  201. package/dist/okf/import.js.map +1 -0
  202. package/dist/okf/index.d.ts +2 -0
  203. package/dist/okf/index.d.ts.map +1 -0
  204. package/dist/okf/index.js +147 -0
  205. package/dist/okf/index.js.map +1 -0
  206. package/dist/okf/map.d.ts +16 -0
  207. package/dist/okf/map.d.ts.map +1 -0
  208. package/dist/okf/map.js +149 -0
  209. package/dist/okf/map.js.map +1 -0
  210. package/dist/okf/types.d.ts +9 -0
  211. package/dist/okf/types.d.ts.map +1 -0
  212. package/dist/okf/types.js +48 -0
  213. package/dist/okf/types.js.map +1 -0
  214. package/dist/search/contested.d.ts +18 -0
  215. package/dist/search/contested.d.ts.map +1 -0
  216. package/dist/search/contested.js +119 -0
  217. package/dist/search/contested.js.map +1 -0
  218. package/dist/search/coverage.d.ts.map +1 -1
  219. package/dist/search/coverage.js +1 -1
  220. package/dist/search/coverage.js.map +1 -1
  221. package/dist/search/hybrid.d.ts +23 -0
  222. package/dist/search/hybrid.d.ts.map +1 -1
  223. package/dist/search/hybrid.js +75 -15
  224. package/dist/search/hybrid.js.map +1 -1
  225. package/dist/search/reindex.d.ts +1 -0
  226. package/dist/search/reindex.d.ts.map +1 -1
  227. package/dist/search/reindex.js +57 -24
  228. package/dist/search/reindex.js.map +1 -1
  229. package/dist/search/watcher.d.ts +2 -0
  230. package/dist/search/watcher.d.ts.map +1 -1
  231. package/dist/search/watcher.js +23 -12
  232. package/dist/search/watcher.js.map +1 -1
  233. package/dist/serve/index.d.ts +36 -0
  234. package/dist/serve/index.d.ts.map +1 -0
  235. package/dist/serve/index.js +507 -0
  236. package/dist/serve/index.js.map +1 -0
  237. package/dist/server.d.ts +10 -1
  238. package/dist/server.d.ts.map +1 -1
  239. package/dist/server.js +91 -12
  240. package/dist/server.js.map +1 -1
  241. package/dist/sleep/cycle.d.ts +59 -0
  242. package/dist/sleep/cycle.d.ts.map +1 -0
  243. package/dist/sleep/cycle.js +127 -0
  244. package/dist/sleep/cycle.js.map +1 -0
  245. package/dist/sleep/index.d.ts +5 -0
  246. package/dist/sleep/index.d.ts.map +1 -0
  247. package/dist/sleep/index.js +320 -0
  248. package/dist/sleep/index.js.map +1 -0
  249. package/dist/sleep/report.d.ts +14 -0
  250. package/dist/sleep/report.d.ts.map +1 -0
  251. package/dist/sleep/report.js +139 -0
  252. package/dist/sleep/report.js.map +1 -0
  253. package/dist/sleep/tension-scan-state.d.ts +19 -0
  254. package/dist/sleep/tension-scan-state.d.ts.map +1 -0
  255. package/dist/sleep/tension-scan-state.js +0 -0
  256. package/dist/sleep/tension-scan-state.js.map +1 -0
  257. package/dist/sleep/tension-scan.d.ts +44 -0
  258. package/dist/sleep/tension-scan.d.ts.map +1 -0
  259. package/dist/sleep/tension-scan.js +0 -0
  260. package/dist/sleep/tension-scan.js.map +1 -0
  261. package/dist/storage/backend.d.ts +12 -0
  262. package/dist/storage/backend.d.ts.map +1 -0
  263. package/dist/storage/backend.js +231 -0
  264. package/dist/storage/backend.js.map +1 -0
  265. package/dist/storage/backends/fs.d.ts +4 -0
  266. package/dist/storage/backends/fs.d.ts.map +1 -0
  267. package/dist/storage/backends/fs.js +99 -0
  268. package/dist/storage/backends/fs.js.map +1 -0
  269. package/dist/storage/fs-walk.d.ts +5 -0
  270. package/dist/storage/fs-walk.d.ts.map +1 -0
  271. package/dist/storage/fs-walk.js +28 -0
  272. package/dist/storage/fs-walk.js.map +1 -0
  273. package/dist/storage/index-db.d.ts +18 -0
  274. package/dist/storage/index-db.d.ts.map +1 -1
  275. package/dist/storage/index-db.js +159 -22
  276. package/dist/storage/index-db.js.map +1 -1
  277. package/dist/storage/local.d.ts +7 -1
  278. package/dist/storage/local.d.ts.map +1 -1
  279. package/dist/storage/local.js +42 -4
  280. package/dist/storage/local.js.map +1 -1
  281. package/dist/storage/sync.d.ts +25 -0
  282. package/dist/storage/sync.d.ts.map +1 -0
  283. package/dist/storage/sync.js +308 -0
  284. package/dist/storage/sync.js.map +1 -0
  285. package/dist/sync/index.d.ts +2 -0
  286. package/dist/sync/index.d.ts.map +1 -0
  287. package/dist/sync/index.js +136 -0
  288. package/dist/sync/index.js.map +1 -0
  289. package/dist/themes/clustering.d.ts +6 -11
  290. package/dist/themes/clustering.d.ts.map +1 -1
  291. package/dist/themes/clustering.js +76 -84
  292. package/dist/themes/clustering.js.map +1 -1
  293. package/dist/tools/consumes.d.ts +14 -0
  294. package/dist/tools/consumes.d.ts.map +1 -0
  295. package/dist/tools/consumes.js +99 -0
  296. package/dist/tools/consumes.js.map +1 -0
  297. package/dist/tools/curation.d.ts +2 -0
  298. package/dist/tools/curation.d.ts.map +1 -1
  299. package/dist/tools/curation.js +102 -7
  300. package/dist/tools/curation.js.map +1 -1
  301. package/dist/tools/edge-staleness.d.ts +28 -0
  302. package/dist/tools/edge-staleness.d.ts.map +1 -0
  303. package/dist/tools/edge-staleness.js +205 -0
  304. package/dist/tools/edge-staleness.js.map +1 -0
  305. package/dist/tools/edges.d.ts.map +1 -1
  306. package/dist/tools/edges.js +28 -22
  307. package/dist/tools/edges.js.map +1 -1
  308. package/dist/tools/read.d.ts +15 -1
  309. package/dist/tools/read.d.ts.map +1 -1
  310. package/dist/tools/read.js +144 -31
  311. package/dist/tools/read.js.map +1 -1
  312. package/dist/tools/receipt.d.ts +65 -0
  313. package/dist/tools/receipt.d.ts.map +1 -0
  314. package/dist/tools/receipt.js +257 -0
  315. package/dist/tools/receipt.js.map +1 -0
  316. package/dist/tools/search.d.ts +1 -0
  317. package/dist/tools/search.d.ts.map +1 -1
  318. package/dist/tools/search.js +186 -12
  319. package/dist/tools/search.js.map +1 -1
  320. package/dist/tools/staged-actions.d.ts +3 -0
  321. package/dist/tools/staged-actions.d.ts.map +1 -1
  322. package/dist/tools/staged-actions.js +228 -23
  323. package/dist/tools/staged-actions.js.map +1 -1
  324. package/dist/tools/themes.d.ts +9 -0
  325. package/dist/tools/themes.d.ts.map +1 -1
  326. package/dist/tools/themes.js +333 -133
  327. package/dist/tools/themes.js.map +1 -1
  328. package/dist/tools/tier1.d.ts +14 -0
  329. package/dist/tools/tier1.d.ts.map +1 -0
  330. package/dist/tools/tier1.js +169 -0
  331. package/dist/tools/tier1.js.map +1 -0
  332. package/dist/tools/tier2.d.ts +27 -0
  333. package/dist/tools/tier2.d.ts.map +1 -0
  334. package/dist/tools/tier2.js +344 -0
  335. package/dist/tools/tier2.js.map +1 -0
  336. package/dist/tools/witness.d.ts +9 -0
  337. package/dist/tools/witness.d.ts.map +1 -0
  338. package/dist/tools/witness.js +66 -0
  339. package/dist/tools/witness.js.map +1 -0
  340. package/dist/tools/write.d.ts +9 -1
  341. package/dist/tools/write.d.ts.map +1 -1
  342. package/dist/tools/write.js +593 -59
  343. package/dist/tools/write.js.map +1 -1
  344. package/dist/utils/config.d.ts +54 -0
  345. package/dist/utils/config.d.ts.map +1 -1
  346. package/dist/utils/config.js +420 -4
  347. package/dist/utils/config.js.map +1 -1
  348. package/dist/utils/paths.d.ts +2 -0
  349. package/dist/utils/paths.d.ts.map +1 -0
  350. package/dist/utils/paths.js +15 -0
  351. package/dist/utils/paths.js.map +1 -0
  352. package/dist/utils/redos.d.ts +2 -0
  353. package/dist/utils/redos.d.ts.map +1 -0
  354. package/dist/utils/redos.js +101 -0
  355. package/dist/utils/redos.js.map +1 -0
  356. package/dist/utils/run-id.d.ts +3 -0
  357. package/dist/utils/run-id.d.ts.map +1 -0
  358. package/dist/utils/run-id.js +19 -0
  359. package/dist/utils/run-id.js.map +1 -0
  360. package/dist/utils/vault-gitignore.d.ts +1 -1
  361. package/dist/utils/vault-gitignore.d.ts.map +1 -1
  362. package/dist/utils/vault-gitignore.js +6 -1
  363. package/dist/utils/vault-gitignore.js.map +1 -1
  364. package/dist/witness/track-record.d.ts +42 -0
  365. package/dist/witness/track-record.d.ts.map +1 -0
  366. package/dist/witness/track-record.js +189 -0
  367. package/dist/witness/track-record.js.map +1 -0
  368. package/package.json +27 -2
  369. package/templates/config.yaml +8 -0
@@ -0,0 +1,308 @@
1
+ // The sync engine (#6, spec Decision 3): pushes the canonical local working
2
+ // copy — markdown tree, .git directory, and durable .daftari state — to a
3
+ // storage backend, and can restore a vault from that backing into an empty
4
+ // directory.
5
+ //
6
+ // Key namespace on the backend:
7
+ // tree/<vault-relative-path> file bytes
8
+ // meta/manifest.json what the backing currently holds
9
+ //
10
+ // The manifest (key → sha256) is the remote source of truth for diffing, so
11
+ // sync is stateless locally and incremental: only changed/new keys upload,
12
+ // removed keys delete. The manifest is written LAST — a crashed sync leaves
13
+ // it understating what was pushed, so the next run re-uploads at worst, never
14
+ // skips.
15
+ //
16
+ // What never syncs: the rebuildable SQLite databases (index.db, locks.db and
17
+ // their journals), the process lock, and transient per-cycle staging files.
18
+ // Durable-but-gitignored audit state (read-log, edges, provenance journals)
19
+ // DOES sync — unlike the index it cannot be rebuilt from the markdown.
20
+ //
21
+ // Concurrency note: sync reads the live tree without taking the process
22
+ // lock, so a write racing the walk can capture a torn snapshot (a ref
23
+ // updated mid-copy). That snapshot is repaired by the next run — acceptable
24
+ // for a backup channel, and the price of syncing while the server serves.
25
+ import { createHash } from "node:crypto";
26
+ import { createReadStream } from "node:fs";
27
+ import { mkdir, readdir, readFile, stat, writeFile } from "node:fs/promises";
28
+ import { dirname, isAbsolute, relative, resolve, sep } from "node:path";
29
+ import { err, ok } from "../frontmatter/types.js";
30
+ import { walkFiles } from "./fs-walk.js";
31
+ export const MANIFEST_KEY = "meta/manifest.json";
32
+ const TREE_PREFIX = "tree/";
33
+ const CONCURRENCY = 8;
34
+ // Rebuildable or transient files that must never reach the backing. Everything
35
+ // else under the vault root — including .git and the durable .daftari
36
+ // journals — is part of the backup.
37
+ const SYNC_EXCLUDED = new Set([
38
+ ".daftari/process.lock",
39
+ ".daftari/index.db",
40
+ ".daftari/index.db-journal",
41
+ ".daftari/index.db-wal",
42
+ ".daftari/index.db-shm",
43
+ ".daftari/locks.db",
44
+ ".daftari/locks.db-journal",
45
+ ".daftari/locks.db-wal",
46
+ ".daftari/locks.db-shm",
47
+ ".daftari/backfill-plan.jsonl",
48
+ ".daftari/wake-queue.jsonl",
49
+ // Its own header calls it "ephemeral cross-session memory … rebuildable:
50
+ // absent OR corrupt ⇒ the empty default" — same class as the wake queue.
51
+ ".daftari/consolidate-state.json",
52
+ ]);
53
+ function isExcluded(relPath) {
54
+ if (SYNC_EXCLUDED.has(relPath))
55
+ return true;
56
+ // Git EXECUTES what these declare — filter/fsmonitor command lines in
57
+ // config, hook scripts in hooks/ — and a `git clone` deliberately never
58
+ // transmits them from a remote for exactly that reason. Carrying them
59
+ // through the backing would turn backend write access into code execution
60
+ // on the operator's next auto-commit, so they are excluded in BOTH
61
+ // directions; the restore side re-enforces this against a poisoned
62
+ // manifest. After a restore, remotes and local config are re-added by the
63
+ // operator.
64
+ if (relPath === ".git/config" || relPath.startsWith(".git/hooks/"))
65
+ return true;
66
+ // Defensive: a vault should never contain one, but never ship it if it does.
67
+ return relPath.split("/").includes("node_modules");
68
+ }
69
+ // Streaming hash so the walk phase never buffers a whole file — .git is in
70
+ // scope now, and packfiles can dwarf the markdown they version.
71
+ function streamHash(abs) {
72
+ return new Promise((resolveHash, rejectHash) => {
73
+ const digest = createHash("sha256");
74
+ let size = 0;
75
+ const stream = createReadStream(abs);
76
+ stream.on("data", (chunk) => {
77
+ digest.update(chunk);
78
+ size += chunk.length;
79
+ });
80
+ stream.on("error", rejectHash);
81
+ stream.on("end", () => resolveHash({ hash: digest.digest("hex"), size }));
82
+ });
83
+ }
84
+ // (size, mtime) → hash memo so a periodic sync (`daftari serve`, every N
85
+ // minutes) re-hashes only what actually changed instead of streaming the
86
+ // whole tree — with .git in scope, full-history rehash every tick scales
87
+ // with repo size, not the delta. In-memory on purpose: it lives exactly as
88
+ // long as the serving process, needs no invalidation story across
89
+ // processes, and a one-shot CLI run simply pays the honest full cost.
90
+ const hashMemo = new Map();
91
+ async function hashFile(abs) {
92
+ const s = await stat(abs);
93
+ const memo = hashMemo.get(abs);
94
+ if (memo && memo.size === s.size && memo.mtimeMs === s.mtimeMs) {
95
+ return { hash: memo.hash, size: memo.size };
96
+ }
97
+ const hashed = await streamHash(abs);
98
+ hashMemo.set(abs, { size: hashed.size, mtimeMs: s.mtimeMs, hash: hashed.hash });
99
+ return hashed;
100
+ }
101
+ // Walks the vault tree (dotfiles included — .git is the point), hashing every
102
+ // non-excluded regular file. Symlinks are skipped and counted: an object
103
+ // store has no symlink notion, and following one could escape the vault.
104
+ async function collectLocalState(vaultRoot) {
105
+ const root = resolve(vaultRoot);
106
+ try {
107
+ const walked = await walkFiles(root);
108
+ const candidates = walked.files
109
+ .map((abs) => ({ abs, rel: relative(root, abs).split(sep).join("/") }))
110
+ .filter((c) => !isExcluded(c.rel));
111
+ // Evict memo entries for files that no longer exist under THIS root —
112
+ // without it the memo grows with total churn (git gc repacks, deletes),
113
+ // not live tree size. Scoped to the root so one process syncing several
114
+ // vaults never evicts another vault's entries.
115
+ const live = new Set(candidates.map((c) => c.abs));
116
+ const rootPrefix = root + sep;
117
+ for (const key of hashMemo.keys()) {
118
+ if (key.startsWith(rootPrefix) && !live.has(key))
119
+ hashMemo.delete(key);
120
+ }
121
+ // Hash with the same bounded pool the upload phase uses — the walk now
122
+ // covers .git, and serializing on disk I/O for packfiles wastes time.
123
+ const files = new Array(candidates.length);
124
+ const hashed = await runPool(candidates.map((c, i) => async () => {
125
+ try {
126
+ const { hash, size } = await hashFile(c.abs);
127
+ files[i] = { relPath: c.rel, absPath: c.abs, hash, size };
128
+ return ok(undefined);
129
+ }
130
+ catch (e) {
131
+ return err(new Error(`cannot hash ${c.rel}: ${e instanceof Error ? e.message : String(e)}`));
132
+ }
133
+ }));
134
+ if (!hashed.ok)
135
+ return hashed;
136
+ return ok({ files, skippedSymlinks: walked.symlinks });
137
+ }
138
+ catch (e) {
139
+ return err(new Error(`cannot walk vault: ${e instanceof Error ? e.message : String(e)}`));
140
+ }
141
+ }
142
+ async function readManifest(backend) {
143
+ const raw = await backend.get(MANIFEST_KEY);
144
+ if (!raw.ok)
145
+ return raw;
146
+ if (raw.value === null)
147
+ return ok({ version: 1, files: {} });
148
+ try {
149
+ const parsed = JSON.parse(raw.value.toString("utf-8"));
150
+ if (parsed.version !== 1 || typeof parsed.files !== "object" || parsed.files === null) {
151
+ return err(new Error(`backing manifest at ${MANIFEST_KEY} has an unknown shape`));
152
+ }
153
+ // Null prototype so a file literally named __proto__ (possible in a git
154
+ // object dir? no — but in the tree, yes) round-trips as an own key.
155
+ const files = Object.create(null);
156
+ for (const [k, v] of Object.entries(parsed.files)) {
157
+ if (typeof v === "string")
158
+ files[k] = v;
159
+ }
160
+ return ok({ version: 1, files });
161
+ }
162
+ catch (e) {
163
+ return err(new Error(`backing manifest is not valid JSON: ${e instanceof Error ? e.message : String(e)}`));
164
+ }
165
+ }
166
+ // Runs `tasks` with a bounded worker pool, stopping at the first error.
167
+ async function runPool(tasks) {
168
+ let index = 0;
169
+ let failure = null;
170
+ async function worker() {
171
+ while (failure === null) {
172
+ const i = index++;
173
+ const task = tasks[i];
174
+ if (!task)
175
+ return;
176
+ const res = await task();
177
+ if (!res.ok && failure === null)
178
+ failure = res.error;
179
+ }
180
+ }
181
+ await Promise.all(Array.from({ length: Math.min(CONCURRENCY, tasks.length) }, worker));
182
+ return failure ? err(failure) : ok(undefined);
183
+ }
184
+ // Push the working copy to the backend. Incremental against the remote
185
+ // manifest; writes the updated manifest last.
186
+ export async function syncVault(vaultRoot, backend, options = {}) {
187
+ const local = await collectLocalState(vaultRoot);
188
+ if (!local.ok)
189
+ return local;
190
+ const manifest = await readManifest(backend);
191
+ if (!manifest.ok)
192
+ return manifest;
193
+ const remote = manifest.value.files;
194
+ const localByPath = new Map(local.value.files.map((f) => [f.relPath, f]));
195
+ const toUpload = local.value.files.filter((f) => remote[f.relPath] !== f.hash);
196
+ const toDelete = Object.keys(remote).filter((relPath) => !localByPath.has(relPath));
197
+ const unchanged = local.value.files.length - toUpload.length;
198
+ const summary = {
199
+ uploaded: toUpload.length,
200
+ deleted: toDelete.length,
201
+ unchanged,
202
+ skippedSymlinks: local.value.skippedSymlinks,
203
+ bytesUploaded: toUpload.reduce((n, f) => n + f.size, 0),
204
+ };
205
+ if (options.dryRun)
206
+ return ok(summary);
207
+ const uploads = toUpload.map((f) => async () => {
208
+ // Re-read at upload time: the hash was computed during the walk and the
209
+ // manifest must describe the bytes actually pushed, so hash what we send.
210
+ let bytes;
211
+ try {
212
+ bytes = await readFile(f.absPath);
213
+ }
214
+ catch (e) {
215
+ return err(new Error(`cannot read ${f.relPath}: ${e instanceof Error ? e.message : String(e)}`));
216
+ }
217
+ f.hash = createHash("sha256").update(bytes).digest("hex");
218
+ f.size = bytes.byteLength;
219
+ return backend.put(TREE_PREFIX + f.relPath, bytes);
220
+ });
221
+ const uploaded = await runPool(uploads);
222
+ if (!uploaded.ok)
223
+ return uploaded;
224
+ const deletes = toDelete.map((relPath) => () => backend.delete(TREE_PREFIX + relPath));
225
+ const deleted = await runPool(deletes);
226
+ if (!deleted.ok)
227
+ return deleted;
228
+ const nextManifest = { version: 1, files: {} };
229
+ const nextFiles = Object.create(null);
230
+ for (const f of local.value.files)
231
+ nextFiles[f.relPath] = f.hash;
232
+ nextManifest.files = nextFiles;
233
+ const wrote = await backend.put(MANIFEST_KEY, Buffer.from(JSON.stringify(nextManifest, null, 2), "utf-8"));
234
+ if (!wrote.ok)
235
+ return wrote;
236
+ return ok(summary);
237
+ }
238
+ // Restore a vault from the backing into `vaultRoot`, which must be empty or
239
+ // absent — restore never merges into or overwrites live state. After a
240
+ // restore the caller reindexes (the index was deliberately never synced).
241
+ export async function restoreVault(vaultRoot, backend) {
242
+ const root = resolve(vaultRoot);
243
+ try {
244
+ const existing = await readdir(root);
245
+ if (existing.length > 0) {
246
+ return err(new Error(`refusing to restore into non-empty directory: ${root}`));
247
+ }
248
+ }
249
+ catch (e) {
250
+ if (e.code !== "ENOENT") {
251
+ return err(new Error(`cannot inspect ${root}: ${e instanceof Error ? e.message : String(e)}`));
252
+ }
253
+ }
254
+ const manifest = await readManifest(backend);
255
+ if (!manifest.ok)
256
+ return manifest;
257
+ // The manifest is data from the backing, not trusted input: re-apply the
258
+ // exclusion rules here so a poisoned manifest cannot smuggle in what push
259
+ // would never have uploaded (git config/hooks — code execution on the
260
+ // next auto-commit).
261
+ const allPaths = Object.keys(manifest.value.files);
262
+ const paths = allPaths.filter((p) => !isExcluded(p));
263
+ const skippedExcluded = allPaths.length - paths.length;
264
+ if (allPaths.length === 0) {
265
+ return err(new Error(`backing at ${backend.id} holds no manifest — nothing to restore`));
266
+ }
267
+ let bytesTotal = 0;
268
+ const tasks = paths.map((relPath) => async () => {
269
+ // Confine each manifest path to the restore root — the manifest is data
270
+ // from the backing, not trusted input.
271
+ const target = resolve(root, relPath);
272
+ const rel = relative(root, target);
273
+ if (rel === "" || rel.startsWith("..") || isAbsolute(rel)) {
274
+ return err(new Error(`manifest path escapes restore root: ${relPath}`));
275
+ }
276
+ const got = await backend.get(TREE_PREFIX + relPath);
277
+ if (!got.ok)
278
+ return got;
279
+ if (got.value === null) {
280
+ return err(new Error(`backing is missing ${TREE_PREFIX}${relPath} listed in its manifest`));
281
+ }
282
+ // Verify the bytes against the manifest's hash — that is what the hash
283
+ // is FOR. This catches corruption, torn writes, and a push racing the
284
+ // restore; it is not a tamper defense (an attacker who can rewrite
285
+ // objects can rewrite the manifest too).
286
+ const gotHash = createHash("sha256").update(got.value).digest("hex");
287
+ const wantHash = manifest.value.files[relPath];
288
+ if (gotHash !== wantHash) {
289
+ return err(new Error(`backing object ${TREE_PREFIX}${relPath} does not match its manifest hash ` +
290
+ `(got ${gotHash.slice(0, 12)}…, manifest says ${wantHash?.slice(0, 12)}…) — ` +
291
+ "the backing is corrupt or a push is racing this restore"));
292
+ }
293
+ try {
294
+ await mkdir(dirname(target), { recursive: true });
295
+ await writeFile(target, got.value);
296
+ }
297
+ catch (e) {
298
+ return err(new Error(`cannot write ${relPath}: ${e instanceof Error ? e.message : String(e)}`));
299
+ }
300
+ bytesTotal += got.value.byteLength;
301
+ return ok(undefined);
302
+ });
303
+ const ran = await runPool(tasks);
304
+ if (!ran.ok)
305
+ return ran;
306
+ return ok({ restored: paths.length, bytes: bytesTotal, skippedExcluded });
307
+ }
308
+ //# sourceMappingURL=sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/storage/sync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function runSync(argv: string[]): Promise<number>;
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sync/index.ts"],"names":[],"mappings":"AA8BA,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAwD7D"}
@@ -0,0 +1,136 @@
1
+ // `daftari sync` (#6): push the canonical local vault to its configured
2
+ // storage backing, or restore a vault from the backing into an empty
3
+ // directory. The backing is configured in .daftari/config.yaml (`storage`
4
+ // block); credentials come from the SDKs' standard environment chains.
5
+ import { parseFlag } from "../index.js";
6
+ import { reindexVault, reindexWarnings } from "../search/reindex.js";
7
+ import { createBackend } from "../storage/backend.js";
8
+ import { restoreVault, syncVault } from "../storage/sync.js";
9
+ import { loadConfig } from "../utils/config.js";
10
+ const USAGE = `daftari sync — push a vault to its storage backing, or restore from it.
11
+
12
+ Usage:
13
+ daftari sync --vault <path> [--dry-run] Push the working copy to the backing
14
+ daftari sync --vault <path> --restore Restore into an EMPTY directory, then reindex
15
+
16
+ The backing is the \`storage\` block in .daftari/config.yaml (backends: fs,
17
+ s3 — including MinIO/R2/GCS-interop endpoints — and azure). The local git
18
+ working copy is canonical; the backing is durable backing, not a second
19
+ source of truth. The SQLite index and lock files are never synced. A restore
20
+ has no local config to read yet, so the backing is named with flags using
21
+ the config block's names (--backend s3 --bucket team-vault [--prefix …]).
22
+
23
+ Push reads the live tree without stopping a running server; a write racing
24
+ the walk is repaired by the next sync.
25
+
26
+ Exit codes: 2 config/usage error, 3 runtime error.
27
+ `;
28
+ export async function runSync(argv) {
29
+ if (argv.includes("--help") || argv.includes("-h")) {
30
+ process.stdout.write(USAGE);
31
+ return 0;
32
+ }
33
+ const vault = parseFlag(argv, "vault");
34
+ if (!vault) {
35
+ process.stderr.write("daftari sync: --vault <path> is required\n\n");
36
+ process.stderr.write(USAGE);
37
+ return 2;
38
+ }
39
+ const restore = argv.includes("--restore");
40
+ const dryRun = argv.includes("--dry-run");
41
+ if (restore && dryRun) {
42
+ process.stderr.write("daftari sync: --restore and --dry-run cannot be combined\n");
43
+ return 2;
44
+ }
45
+ if (restore) {
46
+ return runRestore(vault, argv);
47
+ }
48
+ const config = loadConfig(vault);
49
+ if (!config.ok) {
50
+ process.stderr.write(`daftari sync: ${config.error.message}\n`);
51
+ return 2;
52
+ }
53
+ if (!config.value.storage) {
54
+ process.stderr.write("daftari sync: no storage backing configured — add a `storage` block " +
55
+ "to .daftari/config.yaml (see README: Storage backing)\n");
56
+ return 2;
57
+ }
58
+ const backend = await createBackend(config.value.storage);
59
+ if (!backend.ok) {
60
+ process.stderr.write(`daftari sync: ${backend.error.message}\n`);
61
+ return 2;
62
+ }
63
+ const result = await syncVault(vault, backend.value, { dryRun });
64
+ if (!result.ok) {
65
+ process.stderr.write(`daftari sync: ${result.error.message}\n`);
66
+ return 3;
67
+ }
68
+ const s = result.value;
69
+ process.stdout.write(`${dryRun ? "[dry-run] would push" : "pushed"} to ${backend.value.id}: ` +
70
+ `${s.uploaded} uploaded (${s.bytesUploaded} bytes), ${s.deleted} deleted, ` +
71
+ `${s.unchanged} unchanged` +
72
+ (s.skippedSymlinks > 0 ? `, ${s.skippedSymlinks} symlink(s) skipped` : "") +
73
+ "\n");
74
+ return 0;
75
+ }
76
+ // Restore cannot read the vault's config (the vault does not exist yet), so
77
+ // the backing is described on the command line with the same names as the
78
+ // config block.
79
+ async function runRestore(vault, argv) {
80
+ const backendName = parseFlag(argv, "backend");
81
+ if (!backendName || !["fs", "s3", "azure"].includes(backendName)) {
82
+ process.stderr.write("daftari sync --restore: --backend <fs|s3|azure> is required " +
83
+ "(plus its target flag: --path, --bucket, or --container)\n");
84
+ return 2;
85
+ }
86
+ const storage = {
87
+ backend: backendName,
88
+ path: parseFlag(argv, "path") ?? undefined,
89
+ bucket: parseFlag(argv, "bucket") ?? undefined,
90
+ container: parseFlag(argv, "container") ?? undefined,
91
+ prefix: parseFlag(argv, "prefix") ?? undefined,
92
+ region: parseFlag(argv, "region") ?? undefined,
93
+ endpoint: parseFlag(argv, "endpoint") ?? undefined,
94
+ forcePathStyle: argv.includes("--force-path-style") ? true : undefined,
95
+ };
96
+ const required = { fs: "path", s3: "bucket", azure: "container" }[storage.backend];
97
+ if (!storage[required]) {
98
+ process.stderr.write(`daftari sync --restore: --${required} is required for ${storage.backend}\n`);
99
+ return 2;
100
+ }
101
+ const backend = await createBackend(storage);
102
+ if (!backend.ok) {
103
+ process.stderr.write(`daftari sync: ${backend.error.message}\n`);
104
+ return 2;
105
+ }
106
+ const restored = await restoreVault(vault, backend.value);
107
+ if (!restored.ok) {
108
+ process.stderr.write(`daftari sync: ${restored.error.message}\n`);
109
+ return 3;
110
+ }
111
+ process.stdout.write(`restored ${restored.value.restored} files (${restored.value.bytes} bytes) ` +
112
+ `from ${backend.value.id} into ${vault}\n`);
113
+ if (restored.value.skippedExcluded > 0) {
114
+ process.stderr.write(`daftari sync: warning: ${restored.value.skippedExcluded} manifest entr(ies) refused by ` +
115
+ "the exclusion rules (git config/hooks or rebuildable state) — the backing was " +
116
+ "written by something other than daftari sync\n");
117
+ }
118
+ process.stderr.write("daftari sync: note: git config and hooks are never synced or restored " +
119
+ "(git executes them; a backup channel must not deliver code) — re-add " +
120
+ "remotes and local git config by hand\n");
121
+ // The index was deliberately never synced — rebuild it so the restored
122
+ // vault is immediately servable.
123
+ const indexed = await reindexVault(vault);
124
+ if (indexed.ok) {
125
+ process.stdout.write(`reindexed ${indexed.value.documentCount} docs\n`);
126
+ for (const line of reindexWarnings(indexed.value)) {
127
+ process.stderr.write(`daftari sync: warning: ${line}\n`);
128
+ }
129
+ }
130
+ else {
131
+ process.stderr.write(`daftari sync: warning: reindex after restore failed: ${indexed.error.message}\n` +
132
+ " run `daftari --vault <path> --reindex` before serving\n");
133
+ }
134
+ return 0;
135
+ }
136
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sync/index.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,qEAAqE;AACrE,0EAA0E;AAC1E,uEAAuE;AAEvE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD,MAAM,KAAK,GAAG;;;;;;;;;;;;;;;;;CAiBb,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAc;IAC1C,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC5B,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACvC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAC;QACrE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC5B,OAAO,CAAC,CAAC;IACX,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAC1C,IAAI,OAAO,IAAI,MAAM,EAAE,CAAC;QACtB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,4DAA4D,CAAC,CAAC;QACnF,OAAO,CAAC,CAAC;IACX,CAAC;IAED,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACjC,CAAC;IAED,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IACjC,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,MAAM,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;QAChE,OAAO,CAAC,CAAC;IACX,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QAC1B,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,sEAAsE;YACpE,yDAAyD,CAC5D,CAAC;QACF,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC1D,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;QAChB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,OAAO,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;QACjE,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;IACjE,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,MAAM,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;QAChE,OAAO,CAAC,CAAC;IACX,CAAC;IACD,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC;IACvB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,GAAG,MAAM,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,QAAQ,OAAO,OAAO,CAAC,KAAK,CAAC,EAAE,IAAI;QACtE,GAAG,CAAC,CAAC,QAAQ,cAAc,CAAC,CAAC,aAAa,YAAY,CAAC,CAAC,OAAO,YAAY;QAC3E,GAAG,CAAC,CAAC,SAAS,YAAY;QAC1B,CAAC,CAAC,CAAC,eAAe,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,eAAe,qBAAqB,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1E,IAAI,CACP,CAAC;IACF,OAAO,CAAC,CAAC;AACX,CAAC;AAED,4EAA4E;AAC5E,0EAA0E;AAC1E,gBAAgB;AAChB,KAAK,UAAU,UAAU,CAAC,KAAa,EAAE,IAAc;IACrD,MAAM,WAAW,GAAG,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAC/C,IAAI,CAAC,WAAW,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;QACjE,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,8DAA8D;YAC5D,4DAA4D,CAC/D,CAAC;QACF,OAAO,CAAC,CAAC;IACX,CAAC;IACD,MAAM,OAAO,GAAG;QACd,OAAO,EAAE,WAAoC;QAC7C,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,SAAS;QAC1C,MAAM,EAAE,SAAS,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,SAAS;QAC9C,SAAS,EAAE,SAAS,CAAC,IAAI,EAAE,WAAW,CAAC,IAAI,SAAS;QACpD,MAAM,EAAE,SAAS,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,SAAS;QAC9C,MAAM,EAAE,SAAS,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,SAAS;QAC9C,QAAQ,EAAE,SAAS,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,SAAS;QAClD,cAAc,EAAE,IAAI,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;KACvE,CAAC;IACF,MAAM,QAAQ,GAAG,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,CAGlE,CAAC;IAChB,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,6BAA6B,QAAQ,oBAAoB,OAAO,CAAC,OAAO,IAAI,CAC7E,CAAC;QACF,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,CAAC;IAC7C,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;QAChB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,OAAO,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;QACjE,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IAC1D,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,QAAQ,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;QAClE,OAAO,CAAC,CAAC;IACX,CAAC;IACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,YAAY,QAAQ,CAAC,KAAK,CAAC,QAAQ,WAAW,QAAQ,CAAC,KAAK,CAAC,KAAK,UAAU;QAC1E,QAAQ,OAAO,CAAC,KAAK,CAAC,EAAE,SAAS,KAAK,IAAI,CAC7C,CAAC;IACF,IAAI,QAAQ,CAAC,KAAK,CAAC,eAAe,GAAG,CAAC,EAAE,CAAC;QACvC,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,0BAA0B,QAAQ,CAAC,KAAK,CAAC,eAAe,iCAAiC;YACvF,gFAAgF;YAChF,gDAAgD,CACnD,CAAC;IACJ,CAAC;IACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,wEAAwE;QACtE,uEAAuE;QACvE,wCAAwC,CAC3C,CAAC;IAEF,uEAAuE;IACvE,iCAAiC;IACjC,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,CAAC;IAC1C,IAAI,OAAO,CAAC,EAAE,EAAE,CAAC;QACf,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,OAAO,CAAC,KAAK,CAAC,aAAa,SAAS,CAAC,CAAC;QACxE,KAAK,MAAM,IAAI,IAAI,eAAe,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAClD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,0BAA0B,IAAI,IAAI,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,wDAAwD,OAAO,CAAC,KAAK,CAAC,OAAO,IAAI;YAC/E,2DAA2D,CAC9D,CAAC;IACJ,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC"}
@@ -1,6 +1,5 @@
1
1
  export declare function seededRng(seed: number): () => number;
2
2
  export declare function l2Normalize(vec: Float32Array): Float32Array;
3
- export declare function meanPoolL2(vectors: Float32Array[]): Float32Array | null;
4
3
  export declare function kmeansPlusPlusInit(data: Float32Array[], k: number, rng: () => number): number[];
5
4
  export interface KMeansResult {
6
5
  assignments: number[];
@@ -16,15 +15,11 @@ export interface PickKResult {
16
15
  assignments: number[];
17
16
  centroids: Float32Array[];
18
17
  }
19
- export declare function pickK(data: Float32Array[], candidates: number[], rng: () => number, maxIter: number): PickKResult;
20
- export interface SecondaryMembership {
21
- docIndex: number;
22
- sim: number;
18
+ export declare function strideSample(n: number, cap: number): number[];
19
+ export declare function pickK(data: Float32Array[], candidates: number[], rng: () => number, maxIter: number, silhouetteCap?: number): PickKResult;
20
+ export interface DocMembership {
21
+ cluster: number;
22
+ weight: number;
23
23
  }
24
- export interface SecondaryOptions {
25
- delta: number;
26
- minSimilarity: number;
27
- maxPerDoc: number;
28
- }
29
- export declare function selectSecondaryMemberships(vectors: Float32Array[], assignments: number[], centroids: Float32Array[], options: SecondaryOptions): Map<number, SecondaryMembership[]>;
24
+ export declare function membershipDistributions(chunkAssignments: number[], chunkDoc: number[], docCount: number, minFraction: number): DocMembership[][];
30
25
  //# sourceMappingURL=clustering.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"clustering.d.ts","sourceRoot":"","sources":["../../src/themes/clustering.ts"],"names":[],"mappings":"AAwBA,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,MAAM,CASpD;AAMD,wBAAgB,WAAW,CAAC,GAAG,EAAE,YAAY,GAAG,YAAY,CAa3D;AAKD,wBAAgB,UAAU,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,YAAY,GAAG,IAAI,CAsBvE;AAoCD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,YAAY,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,MAAM,GAAG,MAAM,EAAE,CAoE/F;AAID,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;CACpB;AAKD,wBAAgB,MAAM,CACpB,IAAI,EAAE,YAAY,EAAE,EACpB,CAAC,EAAE,MAAM,EACT,GAAG,EAAE,MAAM,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,YAAY,CAkFd;AAUD,wBAAgB,eAAe,CAAC,IAAI,EAAE,YAAY,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,MAAM,CA6CnF;AAQD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM,CAahE;AAID,MAAM,WAAW,WAAW;IAC1B,CAAC,EAAE,MAAM,CAAC;IACV,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,EAAE,YAAY,EAAE,CAAC;CAC3B;AAOD,wBAAgB,KAAK,CACnB,IAAI,EAAE,YAAY,EAAE,EACpB,UAAU,EAAE,MAAM,EAAE,EACpB,GAAG,EAAE,MAAM,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,WAAW,CAuBb;AAQD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,gBAAgB;IAG/B,KAAK,EAAE,MAAM,CAAC;IAId,aAAa,EAAE,MAAM,CAAC;IAItB,SAAS,EAAE,MAAM,CAAC;CACnB;AAUD,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,YAAY,EAAE,EACvB,WAAW,EAAE,MAAM,EAAE,EACrB,SAAS,EAAE,YAAY,EAAE,EACzB,OAAO,EAAE,gBAAgB,GACxB,GAAG,CAAC,MAAM,EAAE,mBAAmB,EAAE,CAAC,CA2CpC"}
1
+ {"version":3,"file":"clustering.d.ts","sourceRoot":"","sources":["../../src/themes/clustering.ts"],"names":[],"mappings":"AAwBA,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,MAAM,CASpD;AAMD,wBAAgB,WAAW,CAAC,GAAG,EAAE,YAAY,GAAG,YAAY,CAa3D;AAoCD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,YAAY,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,MAAM,GAAG,MAAM,EAAE,CAoE/F;AAID,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;CACpB;AAKD,wBAAgB,MAAM,CACpB,IAAI,EAAE,YAAY,EAAE,EACpB,CAAC,EAAE,MAAM,EACT,GAAG,EAAE,MAAM,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,YAAY,CAkFd;AAUD,wBAAgB,eAAe,CAAC,IAAI,EAAE,YAAY,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,MAAM,CA6CnF;AAQD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM,CAahE;AAID,MAAM,WAAW,WAAW;IAC1B,CAAC,EAAE,MAAM,CAAC;IACV,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,EAAE,YAAY,EAAE,CAAC;CAC3B;AAMD,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAO7D;AAaD,wBAAgB,KAAK,CACnB,IAAI,EAAE,YAAY,EAAE,EACpB,UAAU,EAAE,MAAM,EAAE,EACpB,GAAG,EAAE,MAAM,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,aAAa,CAAC,EAAE,MAAM,GACrB,WAAW,CA8Bb;AAOD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAgBD,wBAAgB,uBAAuB,CACrC,gBAAgB,EAAE,MAAM,EAAE,EAC1B,QAAQ,EAAE,MAAM,EAAE,EAClB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,GAClB,aAAa,EAAE,EAAE,CA2CnB"}