@cairn-tool/cairn 2.0.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 (526) hide show
  1. package/.markdownlintrc +7 -0
  2. package/LICENSE +21 -0
  3. package/README.md +1431 -0
  4. package/dist/agent/audit/baseline.d.ts +69 -0
  5. package/dist/agent/audit/baseline.js +128 -0
  6. package/dist/agent/audit/baseline.js.map +1 -0
  7. package/dist/agent/audit/index.d.ts +126 -0
  8. package/dist/agent/audit/index.js +625 -0
  9. package/dist/agent/audit/index.js.map +1 -0
  10. package/dist/agent/import/detect.d.ts +49 -0
  11. package/dist/agent/import/detect.js +159 -0
  12. package/dist/agent/import/detect.js.map +1 -0
  13. package/dist/agent/import/normalize.d.ts +72 -0
  14. package/dist/agent/import/normalize.js +475 -0
  15. package/dist/agent/import/normalize.js.map +1 -0
  16. package/dist/agent/install/index.d.ts +211 -0
  17. package/dist/agent/install/index.js +907 -0
  18. package/dist/agent/install/index.js.map +1 -0
  19. package/dist/agent/manifest.d.ts +75 -0
  20. package/dist/agent/manifest.js +210 -0
  21. package/dist/agent/manifest.js.map +1 -0
  22. package/dist/agent/marketplace/index.d.ts +69 -0
  23. package/dist/agent/marketplace/index.js +212 -0
  24. package/dist/agent/marketplace/index.js.map +1 -0
  25. package/dist/agent/marketplace/spec.d.ts +48 -0
  26. package/dist/agent/marketplace/spec.js +237 -0
  27. package/dist/agent/marketplace/spec.js.map +1 -0
  28. package/dist/agent/output.d.ts +36 -0
  29. package/dist/agent/output.js +56 -0
  30. package/dist/agent/output.js.map +1 -0
  31. package/dist/agent/overlays.d.ts +38 -0
  32. package/dist/agent/overlays.js +223 -0
  33. package/dist/agent/overlays.js.map +1 -0
  34. package/dist/agent/package/index.d.ts +105 -0
  35. package/dist/agent/package/index.js +339 -0
  36. package/dist/agent/package/index.js.map +1 -0
  37. package/dist/agent/package/tar.d.ts +36 -0
  38. package/dist/agent/package/tar.js +137 -0
  39. package/dist/agent/package/tar.js.map +1 -0
  40. package/dist/agent/parser.d.ts +13 -0
  41. package/dist/agent/parser.js +559 -0
  42. package/dist/agent/parser.js.map +1 -0
  43. package/dist/agent/render.d.ts +16 -0
  44. package/dist/agent/render.js +721 -0
  45. package/dist/agent/render.js.map +1 -0
  46. package/dist/agent/sarif.d.ts +18 -0
  47. package/dist/agent/sarif.js +56 -0
  48. package/dist/agent/sarif.js.map +1 -0
  49. package/dist/agent/scaffold.d.ts +86 -0
  50. package/dist/agent/scaffold.js +250 -0
  51. package/dist/agent/scaffold.js.map +1 -0
  52. package/dist/agent/targets/antigravity.d.ts +17 -0
  53. package/dist/agent/targets/antigravity.js +218 -0
  54. package/dist/agent/targets/antigravity.js.map +1 -0
  55. package/dist/agent/targets/claude-code.d.ts +2 -0
  56. package/dist/agent/targets/claude-code.js +220 -0
  57. package/dist/agent/targets/claude-code.js.map +1 -0
  58. package/dist/agent/targets/codex.d.ts +2 -0
  59. package/dist/agent/targets/codex.js +212 -0
  60. package/dist/agent/targets/codex.js.map +1 -0
  61. package/dist/agent/targets/cursor.d.ts +2 -0
  62. package/dist/agent/targets/cursor.js +210 -0
  63. package/dist/agent/targets/cursor.js.map +1 -0
  64. package/dist/agent/targets/index.d.ts +31 -0
  65. package/dist/agent/targets/index.js +64 -0
  66. package/dist/agent/targets/index.js.map +1 -0
  67. package/dist/agent/targets/opencode.d.ts +15 -0
  68. package/dist/agent/targets/opencode.js +215 -0
  69. package/dist/agent/targets/opencode.js.map +1 -0
  70. package/dist/agent/targets/schema.d.ts +315 -0
  71. package/dist/agent/targets/schema.js +179 -0
  72. package/dist/agent/targets/schema.js.map +1 -0
  73. package/dist/agent/test/assert.d.ts +46 -0
  74. package/dist/agent/test/assert.js +288 -0
  75. package/dist/agent/test/assert.js.map +1 -0
  76. package/dist/agent/test/index.d.ts +73 -0
  77. package/dist/agent/test/index.js +181 -0
  78. package/dist/agent/test/index.js.map +1 -0
  79. package/dist/agent/test/schema.d.ts +81 -0
  80. package/dist/agent/test/schema.js +235 -0
  81. package/dist/agent/test/schema.js.map +1 -0
  82. package/dist/agent/types.d.ts +204 -0
  83. package/dist/agent/types.js +11 -0
  84. package/dist/agent/types.js.map +1 -0
  85. package/dist/agent/upgrade.d.ts +29 -0
  86. package/dist/agent/upgrade.js +72 -0
  87. package/dist/agent/upgrade.js.map +1 -0
  88. package/dist/agent/writer.d.ts +30 -0
  89. package/dist/agent/writer.js +73 -0
  90. package/dist/agent/writer.js.map +1 -0
  91. package/dist/archive/db.d.ts +20 -0
  92. package/dist/archive/db.js +98 -0
  93. package/dist/archive/db.js.map +1 -0
  94. package/dist/archive/progress.d.ts +62 -0
  95. package/dist/archive/progress.js +151 -0
  96. package/dist/archive/progress.js.map +1 -0
  97. package/dist/archive/query.d.ts +86 -0
  98. package/dist/archive/query.js +241 -0
  99. package/dist/archive/query.js.map +1 -0
  100. package/dist/archive/run.d.ts +91 -0
  101. package/dist/archive/run.js +331 -0
  102. package/dist/archive/run.js.map +1 -0
  103. package/dist/archive/segments.d.ts +89 -0
  104. package/dist/archive/segments.js +144 -0
  105. package/dist/archive/segments.js.map +1 -0
  106. package/dist/archive/sets.d.ts +58 -0
  107. package/dist/archive/sets.js +344 -0
  108. package/dist/archive/sets.js.map +1 -0
  109. package/dist/archive/tar-read.d.ts +35 -0
  110. package/dist/archive/tar-read.js +90 -0
  111. package/dist/archive/tar-read.js.map +1 -0
  112. package/dist/audit-baseline.d.ts +66 -0
  113. package/dist/audit-baseline.js +124 -0
  114. package/dist/audit-baseline.js.map +1 -0
  115. package/dist/automation.d.ts +16 -0
  116. package/dist/automation.js +38 -0
  117. package/dist/automation.js.map +1 -0
  118. package/dist/backlinks.d.ts +15 -0
  119. package/dist/backlinks.js +30 -0
  120. package/dist/backlinks.js.map +1 -0
  121. package/dist/checkers/katex.d.ts +3 -0
  122. package/dist/checkers/katex.js +71 -0
  123. package/dist/checkers/katex.js.map +1 -0
  124. package/dist/checkers/markdown-lint.d.ts +28 -0
  125. package/dist/checkers/markdown-lint.js +53 -0
  126. package/dist/checkers/markdown-lint.js.map +1 -0
  127. package/dist/checkers/mermaid.d.ts +6 -0
  128. package/dist/checkers/mermaid.js +53 -0
  129. package/dist/checkers/mermaid.js.map +1 -0
  130. package/dist/checkers/references.d.ts +3 -0
  131. package/dist/checkers/references.js +55 -0
  132. package/dist/checkers/references.js.map +1 -0
  133. package/dist/cli.d.ts +2 -0
  134. package/dist/cli.js +1117 -0
  135. package/dist/cli.js.map +1 -0
  136. package/dist/command-result.d.ts +6 -0
  137. package/dist/command-result.js +13 -0
  138. package/dist/command-result.js.map +1 -0
  139. package/dist/commands/agent-audit.d.ts +21 -0
  140. package/dist/commands/agent-audit.js +119 -0
  141. package/dist/commands/agent-audit.js.map +1 -0
  142. package/dist/commands/agent-doctor.d.ts +25 -0
  143. package/dist/commands/agent-doctor.js +217 -0
  144. package/dist/commands/agent-doctor.js.map +1 -0
  145. package/dist/commands/agent-import.d.ts +21 -0
  146. package/dist/commands/agent-import.js +212 -0
  147. package/dist/commands/agent-import.js.map +1 -0
  148. package/dist/commands/agent-install.d.ts +18 -0
  149. package/dist/commands/agent-install.js +59 -0
  150. package/dist/commands/agent-install.js.map +1 -0
  151. package/dist/commands/agent-installed.d.ts +6 -0
  152. package/dist/commands/agent-installed.js +17 -0
  153. package/dist/commands/agent-installed.js.map +1 -0
  154. package/dist/commands/agent-marketplace.d.ts +11 -0
  155. package/dist/commands/agent-marketplace.js +178 -0
  156. package/dist/commands/agent-marketplace.js.map +1 -0
  157. package/dist/commands/agent-package.d.ts +16 -0
  158. package/dist/commands/agent-package.js +159 -0
  159. package/dist/commands/agent-package.js.map +1 -0
  160. package/dist/commands/agent-scaffold.d.ts +17 -0
  161. package/dist/commands/agent-scaffold.js +181 -0
  162. package/dist/commands/agent-scaffold.js.map +1 -0
  163. package/dist/commands/agent-specs.d.ts +7 -0
  164. package/dist/commands/agent-specs.js +20 -0
  165. package/dist/commands/agent-specs.js.map +1 -0
  166. package/dist/commands/agent-test.d.ts +21 -0
  167. package/dist/commands/agent-test.js +50 -0
  168. package/dist/commands/agent-test.js.map +1 -0
  169. package/dist/commands/agent-uninstall.d.ts +6 -0
  170. package/dist/commands/agent-uninstall.js +45 -0
  171. package/dist/commands/agent-uninstall.js.map +1 -0
  172. package/dist/commands/agent-upgrade.d.ts +5 -0
  173. package/dist/commands/agent-upgrade.js +105 -0
  174. package/dist/commands/agent-upgrade.js.map +1 -0
  175. package/dist/commands/agent.d.ts +27 -0
  176. package/dist/commands/agent.js +549 -0
  177. package/dist/commands/agent.js.map +1 -0
  178. package/dist/commands/archive.d.ts +47 -0
  179. package/dist/commands/archive.js +311 -0
  180. package/dist/commands/archive.js.map +1 -0
  181. package/dist/commands/audit.d.ts +25 -0
  182. package/dist/commands/audit.js +325 -0
  183. package/dist/commands/audit.js.map +1 -0
  184. package/dist/commands/check-snippets.d.ts +58 -0
  185. package/dist/commands/check-snippets.js +247 -0
  186. package/dist/commands/check-snippets.js.map +1 -0
  187. package/dist/commands/check-urls.d.ts +52 -0
  188. package/dist/commands/check-urls.js +205 -0
  189. package/dist/commands/check-urls.js.map +1 -0
  190. package/dist/commands/code-blocks.d.ts +8 -0
  191. package/dist/commands/code-blocks.js +66 -0
  192. package/dist/commands/code-blocks.js.map +1 -0
  193. package/dist/commands/completion.d.ts +15 -0
  194. package/dist/commands/completion.js +20 -0
  195. package/dist/commands/completion.js.map +1 -0
  196. package/dist/commands/context.d.ts +16 -0
  197. package/dist/commands/context.js +131 -0
  198. package/dist/commands/context.js.map +1 -0
  199. package/dist/commands/describe.d.ts +12 -0
  200. package/dist/commands/describe.js +62 -0
  201. package/dist/commands/describe.js.map +1 -0
  202. package/dist/commands/diff.d.ts +11 -0
  203. package/dist/commands/diff.js +185 -0
  204. package/dist/commands/diff.js.map +1 -0
  205. package/dist/commands/fix.d.ts +59 -0
  206. package/dist/commands/fix.js +173 -0
  207. package/dist/commands/fix.js.map +1 -0
  208. package/dist/commands/frontmatter.d.ts +7 -0
  209. package/dist/commands/frontmatter.js +84 -0
  210. package/dist/commands/frontmatter.js.map +1 -0
  211. package/dist/commands/graph.d.ts +12 -0
  212. package/dist/commands/graph.js +122 -0
  213. package/dist/commands/graph.js.map +1 -0
  214. package/dist/commands/headers.d.ts +7 -0
  215. package/dist/commands/headers.js +48 -0
  216. package/dist/commands/headers.js.map +1 -0
  217. package/dist/commands/index.d.ts +8 -0
  218. package/dist/commands/index.js +32 -0
  219. package/dist/commands/index.js.map +1 -0
  220. package/dist/commands/links.d.ts +9 -0
  221. package/dist/commands/links.js +123 -0
  222. package/dist/commands/links.js.map +1 -0
  223. package/dist/commands/lint-dir.d.ts +15 -0
  224. package/dist/commands/lint-dir.js +156 -0
  225. package/dist/commands/lint-dir.js.map +1 -0
  226. package/dist/commands/lint.d.ts +14 -0
  227. package/dist/commands/lint.js +45 -0
  228. package/dist/commands/lint.js.map +1 -0
  229. package/dist/commands/orphans.d.ts +10 -0
  230. package/dist/commands/orphans.js +74 -0
  231. package/dist/commands/orphans.js.map +1 -0
  232. package/dist/commands/outline.d.ts +7 -0
  233. package/dist/commands/outline.js +54 -0
  234. package/dist/commands/outline.js.map +1 -0
  235. package/dist/commands/query.d.ts +18 -0
  236. package/dist/commands/query.js +341 -0
  237. package/dist/commands/query.js.map +1 -0
  238. package/dist/commands/refs-to.d.ts +8 -0
  239. package/dist/commands/refs-to.js +65 -0
  240. package/dist/commands/refs-to.js.map +1 -0
  241. package/dist/commands/refs.d.ts +10 -0
  242. package/dist/commands/refs.js +103 -0
  243. package/dist/commands/refs.js.map +1 -0
  244. package/dist/commands/rename-file.d.ts +16 -0
  245. package/dist/commands/rename-file.js +215 -0
  246. package/dist/commands/rename-file.js.map +1 -0
  247. package/dist/commands/rename-heading.d.ts +10 -0
  248. package/dist/commands/rename-heading.js +182 -0
  249. package/dist/commands/rename-heading.js.map +1 -0
  250. package/dist/commands/schema.d.ts +10 -0
  251. package/dist/commands/schema.js +34 -0
  252. package/dist/commands/schema.js.map +1 -0
  253. package/dist/commands/scripts.d.ts +59 -0
  254. package/dist/commands/scripts.js +222 -0
  255. package/dist/commands/scripts.js.map +1 -0
  256. package/dist/commands/section.d.ts +9 -0
  257. package/dist/commands/section.js +49 -0
  258. package/dist/commands/section.js.map +1 -0
  259. package/dist/commands/serve.d.ts +6 -0
  260. package/dist/commands/serve.js +48 -0
  261. package/dist/commands/serve.js.map +1 -0
  262. package/dist/commands/stats.d.ts +6 -0
  263. package/dist/commands/stats.js +109 -0
  264. package/dist/commands/stats.js.map +1 -0
  265. package/dist/commands/structure.d.ts +6 -0
  266. package/dist/commands/structure.js +130 -0
  267. package/dist/commands/structure.js.map +1 -0
  268. package/dist/commands/tables.d.ts +8 -0
  269. package/dist/commands/tables.js +77 -0
  270. package/dist/commands/tables.js.map +1 -0
  271. package/dist/commands/tasks.d.ts +8 -0
  272. package/dist/commands/tasks.js +59 -0
  273. package/dist/commands/tasks.js.map +1 -0
  274. package/dist/commands/toc.d.ts +18 -0
  275. package/dist/commands/toc.js +105 -0
  276. package/dist/commands/toc.js.map +1 -0
  277. package/dist/commands/update-check.d.ts +36 -0
  278. package/dist/commands/update-check.js +119 -0
  279. package/dist/commands/update-check.js.map +1 -0
  280. package/dist/commands/usage.d.ts +56 -0
  281. package/dist/commands/usage.js +883 -0
  282. package/dist/commands/usage.js.map +1 -0
  283. package/dist/commands/validate-frontmatter.d.ts +13 -0
  284. package/dist/commands/validate-frontmatter.js +34 -0
  285. package/dist/commands/validate-frontmatter.js.map +1 -0
  286. package/dist/completion/model.d.ts +49 -0
  287. package/dist/completion/model.js +194 -0
  288. package/dist/completion/model.js.map +1 -0
  289. package/dist/completion/shells.d.ts +2 -0
  290. package/dist/completion/shells.js +280 -0
  291. package/dist/completion/shells.js.map +1 -0
  292. package/dist/config-schema.d.ts +15 -0
  293. package/dist/config-schema.js +44 -0
  294. package/dist/config-schema.js.map +1 -0
  295. package/dist/config.d.ts +102 -0
  296. package/dist/config.js +614 -0
  297. package/dist/config.js.map +1 -0
  298. package/dist/context.d.ts +106 -0
  299. package/dist/context.js +202 -0
  300. package/dist/context.js.map +1 -0
  301. package/dist/contract/describe.d.ts +84 -0
  302. package/dist/contract/describe.js +104 -0
  303. package/dist/contract/describe.js.map +1 -0
  304. package/dist/contract/registry.d.ts +2 -0
  305. package/dist/contract/registry.js +622 -0
  306. package/dist/contract/registry.js.map +1 -0
  307. package/dist/contract/schemas/agent.d.ts +2 -0
  308. package/dist/contract/schemas/agent.js +572 -0
  309. package/dist/contract/schemas/agent.js.map +1 -0
  310. package/dist/contract/schemas/archive.d.ts +3 -0
  311. package/dist/contract/schemas/archive.js +227 -0
  312. package/dist/contract/schemas/archive.js.map +1 -0
  313. package/dist/contract/schemas/index.d.ts +11 -0
  314. package/dist/contract/schemas/index.js +49 -0
  315. package/dist/contract/schemas/index.js.map +1 -0
  316. package/dist/contract/schemas/markdown.d.ts +15 -0
  317. package/dist/contract/schemas/markdown.js +1035 -0
  318. package/dist/contract/schemas/markdown.js.map +1 -0
  319. package/dist/contract/schemas/meta.d.ts +5 -0
  320. package/dist/contract/schemas/meta.js +233 -0
  321. package/dist/contract/schemas/meta.js.map +1 -0
  322. package/dist/contract/schemas/scripts.d.ts +4 -0
  323. package/dist/contract/schemas/scripts.js +183 -0
  324. package/dist/contract/schemas/scripts.js.map +1 -0
  325. package/dist/contract/schemas/shared.d.ts +11 -0
  326. package/dist/contract/schemas/shared.js +26 -0
  327. package/dist/contract/schemas/shared.js.map +1 -0
  328. package/dist/contract/schemas/usage.d.ts +6 -0
  329. package/dist/contract/schemas/usage.js +489 -0
  330. package/dist/contract/schemas/usage.js.map +1 -0
  331. package/dist/contract/types.d.ts +63 -0
  332. package/dist/contract/types.js +2 -0
  333. package/dist/contract/types.js.map +1 -0
  334. package/dist/contract/version.d.ts +20 -0
  335. package/dist/contract/version.js +21 -0
  336. package/dist/contract/version.js.map +1 -0
  337. package/dist/diff.d.ts +156 -0
  338. package/dist/diff.js +500 -0
  339. package/dist/diff.js.map +1 -0
  340. package/dist/edit-plan.d.ts +133 -0
  341. package/dist/edit-plan.js +245 -0
  342. package/dist/edit-plan.js.map +1 -0
  343. package/dist/fix/markdownlint-fixer.d.ts +34 -0
  344. package/dist/fix/markdownlint-fixer.js +125 -0
  345. package/dist/fix/markdownlint-fixer.js.map +1 -0
  346. package/dist/fix/registry.d.ts +48 -0
  347. package/dist/fix/registry.js +28 -0
  348. package/dist/fix/registry.js.map +1 -0
  349. package/dist/fix/relative-links-fixer.d.ts +21 -0
  350. package/dist/fix/relative-links-fixer.js +96 -0
  351. package/dist/fix/relative-links-fixer.js.map +1 -0
  352. package/dist/fix/snippets-fixer.d.ts +2 -0
  353. package/dist/fix/snippets-fixer.js +64 -0
  354. package/dist/fix/snippets-fixer.js.map +1 -0
  355. package/dist/fix/toc-fixer.d.ts +2 -0
  356. package/dist/fix/toc-fixer.js +94 -0
  357. package/dist/fix/toc-fixer.js.map +1 -0
  358. package/dist/formats.d.ts +22 -0
  359. package/dist/formats.js +34 -0
  360. package/dist/formats.js.map +1 -0
  361. package/dist/formatters.d.ts +11 -0
  362. package/dist/formatters.js +48 -0
  363. package/dist/formatters.js.map +1 -0
  364. package/dist/frontmatter-validation.d.ts +11 -0
  365. package/dist/frontmatter-validation.js +188 -0
  366. package/dist/frontmatter-validation.js.map +1 -0
  367. package/dist/git.d.ts +40 -0
  368. package/dist/git.js +124 -0
  369. package/dist/git.js.map +1 -0
  370. package/dist/graph.d.ts +50 -0
  371. package/dist/graph.js +200 -0
  372. package/dist/graph.js.map +1 -0
  373. package/dist/input-selection.d.ts +9 -0
  374. package/dist/input-selection.js +122 -0
  375. package/dist/input-selection.js.map +1 -0
  376. package/dist/input.d.ts +2 -0
  377. package/dist/input.js +32 -0
  378. package/dist/input.js.map +1 -0
  379. package/dist/link-target.d.ts +39 -0
  380. package/dist/link-target.js +68 -0
  381. package/dist/link-target.js.map +1 -0
  382. package/dist/lint.d.ts +13 -0
  383. package/dist/lint.js +27 -0
  384. package/dist/lint.js.map +1 -0
  385. package/dist/markdown-ast.d.ts +73 -0
  386. package/dist/markdown-ast.js +187 -0
  387. package/dist/markdown-ast.js.map +1 -0
  388. package/dist/object-path.d.ts +14 -0
  389. package/dist/object-path.js +14 -0
  390. package/dist/object-path.js.map +1 -0
  391. package/dist/option-utils.d.ts +13 -0
  392. package/dist/option-utils.js +25 -0
  393. package/dist/option-utils.js.map +1 -0
  394. package/dist/outline.d.ts +16 -0
  395. package/dist/outline.js +32 -0
  396. package/dist/outline.js.map +1 -0
  397. package/dist/query/entities.d.ts +60 -0
  398. package/dist/query/entities.js +219 -0
  399. package/dist/query/entities.js.map +1 -0
  400. package/dist/query/execute.d.ts +22 -0
  401. package/dist/query/execute.js +0 -0
  402. package/dist/query/execute.js.map +1 -0
  403. package/dist/query/plan.d.ts +76 -0
  404. package/dist/query/plan.js +183 -0
  405. package/dist/query/plan.js.map +1 -0
  406. package/dist/query/render.d.ts +3 -0
  407. package/dist/query/render.js +39 -0
  408. package/dist/query/render.js.map +1 -0
  409. package/dist/refs.d.ts +19 -0
  410. package/dist/refs.js +10 -0
  411. package/dist/refs.js.map +1 -0
  412. package/dist/result.d.ts +49 -0
  413. package/dist/result.js +47 -0
  414. package/dist/result.js.map +1 -0
  415. package/dist/runtime.d.ts +35 -0
  416. package/dist/runtime.js +77 -0
  417. package/dist/runtime.js.map +1 -0
  418. package/dist/sarif.d.ts +36 -0
  419. package/dist/sarif.js +30 -0
  420. package/dist/sarif.js.map +1 -0
  421. package/dist/scripts/execute.d.ts +65 -0
  422. package/dist/scripts/execute.js +235 -0
  423. package/dist/scripts/execute.js.map +1 -0
  424. package/dist/scripts/registry.d.ts +55 -0
  425. package/dist/scripts/registry.js +103 -0
  426. package/dist/scripts/registry.js.map +1 -0
  427. package/dist/scripts/resolve.d.ts +90 -0
  428. package/dist/scripts/resolve.js +288 -0
  429. package/dist/scripts/resolve.js.map +1 -0
  430. package/dist/sections.d.ts +53 -0
  431. package/dist/sections.js +100 -0
  432. package/dist/sections.js.map +1 -0
  433. package/dist/serve/errors.d.ts +25 -0
  434. package/dist/serve/errors.js +45 -0
  435. package/dist/serve/errors.js.map +1 -0
  436. package/dist/serve/paths.d.ts +32 -0
  437. package/dist/serve/paths.js +71 -0
  438. package/dist/serve/paths.js.map +1 -0
  439. package/dist/serve/server.d.ts +31 -0
  440. package/dist/serve/server.js +123 -0
  441. package/dist/serve/server.js.map +1 -0
  442. package/dist/serve/tools.d.ts +19 -0
  443. package/dist/serve/tools.js +597 -0
  444. package/dist/serve/tools.js.map +1 -0
  445. package/dist/snippets.d.ts +184 -0
  446. package/dist/snippets.js +454 -0
  447. package/dist/snippets.js.map +1 -0
  448. package/dist/sqlite-store.d.ts +62 -0
  449. package/dist/sqlite-store.js +104 -0
  450. package/dist/sqlite-store.js.map +1 -0
  451. package/dist/sqlite.d.ts +59 -0
  452. package/dist/sqlite.js +51 -0
  453. package/dist/sqlite.js.map +1 -0
  454. package/dist/toc.d.ts +58 -0
  455. package/dist/toc.js +83 -0
  456. package/dist/toc.js.map +1 -0
  457. package/dist/types.d.ts +7 -0
  458. package/dist/types.js +2 -0
  459. package/dist/types.js.map +1 -0
  460. package/dist/update-notifier.d.ts +95 -0
  461. package/dist/update-notifier.js +301 -0
  462. package/dist/update-notifier.js.map +1 -0
  463. package/dist/url-cache.d.ts +14 -0
  464. package/dist/url-cache.js +70 -0
  465. package/dist/url-cache.js.map +1 -0
  466. package/dist/usage/aggregate.d.ts +107 -0
  467. package/dist/usage/aggregate.js +435 -0
  468. package/dist/usage/aggregate.js.map +1 -0
  469. package/dist/usage/db/index.d.ts +49 -0
  470. package/dist/usage/db/index.js +118 -0
  471. package/dist/usage/db/index.js.map +1 -0
  472. package/dist/usage/db/migrations.d.ts +29 -0
  473. package/dist/usage/db/migrations.js +38 -0
  474. package/dist/usage/db/migrations.js.map +1 -0
  475. package/dist/usage/db/open.d.ts +33 -0
  476. package/dist/usage/db/open.js +37 -0
  477. package/dist/usage/db/open.js.map +1 -0
  478. package/dist/usage/db/schema.d.ts +18 -0
  479. package/dist/usage/db/schema.js +147 -0
  480. package/dist/usage/db/schema.js.map +1 -0
  481. package/dist/usage/db/store.d.ts +74 -0
  482. package/dist/usage/db/store.js +280 -0
  483. package/dist/usage/db/store.js.map +1 -0
  484. package/dist/usage/events.d.ts +202 -0
  485. package/dist/usage/events.js +243 -0
  486. package/dist/usage/events.js.map +1 -0
  487. package/dist/usage/filter.d.ts +43 -0
  488. package/dist/usage/filter.js +97 -0
  489. package/dist/usage/filter.js.map +1 -0
  490. package/dist/usage/providers/antigravity.d.ts +2 -0
  491. package/dist/usage/providers/antigravity.js +431 -0
  492. package/dist/usage/providers/antigravity.js.map +1 -0
  493. package/dist/usage/providers/claude-code.d.ts +2 -0
  494. package/dist/usage/providers/claude-code.js +400 -0
  495. package/dist/usage/providers/claude-code.js.map +1 -0
  496. package/dist/usage/providers/codex.d.ts +2 -0
  497. package/dist/usage/providers/codex.js +387 -0
  498. package/dist/usage/providers/codex.js.map +1 -0
  499. package/dist/usage/providers/gemini-cli.d.ts +2 -0
  500. package/dist/usage/providers/gemini-cli.js +466 -0
  501. package/dist/usage/providers/gemini-cli.js.map +1 -0
  502. package/dist/usage/providers/index.d.ts +23 -0
  503. package/dist/usage/providers/index.js +46 -0
  504. package/dist/usage/providers/index.js.map +1 -0
  505. package/dist/usage/providers/opencode.d.ts +2 -0
  506. package/dist/usage/providers/opencode.js +422 -0
  507. package/dist/usage/providers/opencode.js.map +1 -0
  508. package/dist/usage/providers/protobuf.d.ts +35 -0
  509. package/dist/usage/providers/protobuf.js +125 -0
  510. package/dist/usage/providers/protobuf.js.map +1 -0
  511. package/dist/usage/providers/types.d.ts +74 -0
  512. package/dist/usage/providers/types.js +2 -0
  513. package/dist/usage/providers/types.js.map +1 -0
  514. package/dist/usage/scan.d.ts +54 -0
  515. package/dist/usage/scan.js +216 -0
  516. package/dist/usage/scan.js.map +1 -0
  517. package/dist/version.d.ts +2 -0
  518. package/dist/version.js +8 -0
  519. package/dist/version.js.map +1 -0
  520. package/dist/workspace-index.d.ts +39 -0
  521. package/dist/workspace-index.js +265 -0
  522. package/dist/workspace-index.js.map +1 -0
  523. package/dist/workspace.d.ts +89 -0
  524. package/dist/workspace.js +219 -0
  525. package/dist/workspace.js.map +1 -0
  526. package/package.json +92 -0
@@ -0,0 +1,331 @@
1
+ import fs from "node:fs";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { loadSqlite } from "../sqlite.js";
5
+ import { closeQuietly, transact } from "../sqlite-store.js";
6
+ import { openArchive, segmentsDirectory } from "./db.js";
7
+ import { profileFor } from "./sets.js";
8
+ import { DEFAULT_SEGMENT_BYTES, hashBuffer, SegmentWriter } from "./segments.js";
9
+ export function emptyCounters() {
10
+ return {
11
+ discovered: 0,
12
+ unchanged: 0,
13
+ hashed: 0,
14
+ duplicate: 0,
15
+ stored: 0,
16
+ skipped: 0,
17
+ bytes: 0,
18
+ };
19
+ }
20
+ /**
21
+ * Walks one set, yielding what it matches.
22
+ *
23
+ * Symbolic links are not followed. A link into a directory the sets deliberately
24
+ * exclude would otherwise pull it in anyway, which is the failure mode the
25
+ * allowlist in `sets.ts` exists to prevent.
26
+ */
27
+ export function collectSet(root, provider, set) {
28
+ const base = set.root ? path.join(root, set.root) : root;
29
+ const found = [];
30
+ const walk = (directory, prefix) => {
31
+ let entries;
32
+ try {
33
+ entries = fs.readdirSync(directory, { withFileTypes: true });
34
+ }
35
+ catch {
36
+ // A directory that is absent or unreadable simply contributes nothing.
37
+ return;
38
+ }
39
+ for (const entry of entries) {
40
+ const relative = prefix ? `${prefix}/${entry.name}` : entry.name;
41
+ const absolute = path.join(directory, entry.name);
42
+ if (entry.isDirectory()) {
43
+ if (set.recursive)
44
+ walk(absolute, relative);
45
+ continue;
46
+ }
47
+ if (!entry.isFile())
48
+ continue;
49
+ if (!set.match(relative))
50
+ continue;
51
+ let stats;
52
+ try {
53
+ stats = fs.statSync(absolute);
54
+ }
55
+ catch {
56
+ continue;
57
+ }
58
+ found.push({
59
+ provider,
60
+ set,
61
+ file: absolute,
62
+ recordPath: absolute,
63
+ size: stats.size,
64
+ mtimeMs: stats.mtimeMs,
65
+ mode: stats.mode & 0o777,
66
+ });
67
+ }
68
+ };
69
+ walk(base, "");
70
+ // Byte comparison, never localeCompare: segment membership must not depend on
71
+ // the ICU build of the machine that ran the archive.
72
+ found.sort((a, b) => (a.file < b.file ? -1 : a.file > b.file ? 1 : 0));
73
+ return found;
74
+ }
75
+ /** Everything the selected classes match, across the selected providers. */
76
+ export function collect(sources, classes) {
77
+ const wanted = new Set(classes);
78
+ const found = [];
79
+ for (const source of sources) {
80
+ const profile = profileFor(source.provider.name);
81
+ if (!profile)
82
+ continue;
83
+ for (const set of profile.sets) {
84
+ if (!wanted.has(set.class))
85
+ continue;
86
+ found.push(...collectSet(source.root, source.provider.name, set));
87
+ }
88
+ }
89
+ return found;
90
+ }
91
+ /**
92
+ * Reads a candidate's bytes.
93
+ *
94
+ * A set marked `snapshot: "sqlite"` is copied through the online backup API into
95
+ * a temporary file rather than read directly: those databases carry live `-wal`
96
+ * sidecars, and a byte copy of the main file alone can capture a page image torn
97
+ * mid-write. The snapshot is a single consistent file, which is also what makes
98
+ * it worth archiving — a `.db` without its `-wal` may be missing recent writes.
99
+ */
100
+ async function readCandidate(candidate) {
101
+ if (candidate.set.snapshot !== "sqlite")
102
+ return fs.readFileSync(candidate.file);
103
+ const sqlite = loadSqlite();
104
+ if (!sqlite)
105
+ return fs.readFileSync(candidate.file);
106
+ const scratch = fs.mkdtempSync(path.join(os.tmpdir(), "cairn-snapshot-"));
107
+ const target = path.join(scratch, "snapshot.db");
108
+ let source;
109
+ try {
110
+ source = new sqlite.DatabaseSync(candidate.file, { readOnly: true });
111
+ const backup = sqlite
112
+ .backup;
113
+ await backup(source, target);
114
+ return fs.readFileSync(target);
115
+ }
116
+ finally {
117
+ closeQuietly(source);
118
+ try {
119
+ fs.rmSync(scratch, { recursive: true, force: true });
120
+ }
121
+ catch {
122
+ // Best-effort.
123
+ }
124
+ }
125
+ }
126
+ /**
127
+ * The key a candidate and its stored row are matched on.
128
+ *
129
+ * One helper for both sides on purpose: they were briefly written separately,
130
+ * with different separators, and the result was an archive that re-hashed its
131
+ * entire corpus on every run while still producing correct output — a bug with
132
+ * no wrong answer to give it away.
133
+ *
134
+ * The separator is a NUL, for the same reason `sessionKey` in
135
+ * `src/usage/events.ts` uses one: it cannot occur in either half. A space can
136
+ * and does occur in a path.
137
+ */
138
+ function artifactKey(provider, file) {
139
+ return `${provider}\u0000${file}`;
140
+ }
141
+ /** What the index already holds, keyed by {@link artifactKey}. */
142
+ function indexedArtifacts(db) {
143
+ const found = new Map();
144
+ // The newest row per path is the one whose size and mtime a freshness test
145
+ // should compare against; an older row describes a version since replaced.
146
+ for (const row of db
147
+ .prepare(`SELECT provider, path, size, mtime_ms FROM artifact
148
+ WHERE id IN (SELECT MAX(id) FROM artifact GROUP BY provider, path)`)
149
+ .all()) {
150
+ found.set(artifactKey(String(row.provider), String(row.path)), {
151
+ size: Number(row.size),
152
+ mtimeMs: Number(row.mtime_ms),
153
+ });
154
+ }
155
+ return found;
156
+ }
157
+ export async function runArchive(options) {
158
+ const counters = emptyCounters();
159
+ const failures = [];
160
+ const byClass = {};
161
+ const bump = (name, field, amount = 1) => {
162
+ const entry = (byClass[name] ??= { discovered: 0, stored: 0, bytes: 0 });
163
+ entry[field] += amount;
164
+ };
165
+ const candidates = collect(options.sources, options.classes);
166
+ counters.discovered = candidates.length;
167
+ let plannedBytes = 0;
168
+ for (const candidate of candidates) {
169
+ bump(candidate.set.class, "discovered");
170
+ plannedBytes += candidate.size;
171
+ }
172
+ const reporter = options.reporter;
173
+ reporter?.start?.({ files: candidates.length, bytes: plannedBytes });
174
+ if (options.dryRun) {
175
+ // Nothing is opened: a dry run reports what the sets matched and how much it
176
+ // is, from the stat the walk already did.
177
+ for (const candidate of candidates) {
178
+ counters.bytes += candidate.size;
179
+ (byClass[candidate.set.class] ??= { discovered: 0, stored: 0, bytes: 0 }).bytes +=
180
+ candidate.size;
181
+ }
182
+ reporter?.finish?.();
183
+ return { counters, failures, segments: [], byClass };
184
+ }
185
+ const opened = openArchive({ root: options.archiveRoot });
186
+ const db = opened.db;
187
+ try {
188
+ const indexed = indexedArtifacts(db);
189
+ /**
190
+ * Blobs the index already holds, so an artifact row may reference them now.
191
+ */
192
+ const storedBlobs = new Set(db
193
+ .prepare("SELECT sha256 FROM blob")
194
+ .all()
195
+ .map((row) => String(row.sha256)));
196
+ /**
197
+ * Blobs buffered for the segment currently being built.
198
+ *
199
+ * Kept apart from {@link storedBlobs} because the two demand opposite
200
+ * handling, and conflating them is a foreign key violation: a second file
201
+ * with the same content as one still in the buffer cannot have its row
202
+ * written yet, because the `blob` row it would reference does not exist
203
+ * until that segment is sealed. It waits instead.
204
+ */
205
+ const pendingBlobs = new Set();
206
+ const nextSequence = Number(db.prepare("SELECT COUNT(*) AS n FROM segment").get()?.n ?? 0) + 1;
207
+ const writer = new SegmentWriter(segmentsDirectory(options.archiveRoot), nextSequence, options.segmentBytes ?? DEFAULT_SEGMENT_BYTES);
208
+ const now = new Date().toISOString();
209
+ const insertSegment = db.prepare("INSERT INTO segment(name, bytes, blobs, sha256, sealed_at) VALUES(?,?,?,?,?)");
210
+ const insertBlob = db.prepare("INSERT OR IGNORE INTO blob(sha256, size, segment_id, offset, stored_at) VALUES(?,?,?,?,?)");
211
+ const insertArtifact = db.prepare(`INSERT INTO artifact(provider, set_id, class, path, sha256, size, mtime_ms, mode,
212
+ first_seen, last_seen)
213
+ VALUES(?,?,?,?,?,?,?,?,?,?)
214
+ ON CONFLICT(provider, path, sha256) DO UPDATE SET last_seen = excluded.last_seen`);
215
+ /** Rows waiting on the segment their content is being written into. */
216
+ let waiting = [];
217
+ const writeArtifact = (candidate, sha256) => {
218
+ insertArtifact.run(candidate.provider, candidate.set.id, candidate.set.class, candidate.recordPath, sha256, candidate.size, candidate.mtimeMs, candidate.mode, now, now);
219
+ };
220
+ /**
221
+ * Seals whatever is buffered and writes the rows that were waiting on it.
222
+ *
223
+ * Segment, blobs and artifact rows go in together: an artifact row pointing
224
+ * at a blob whose segment was never recorded would be an index that cannot
225
+ * find its own content.
226
+ */
227
+ const commitSegment = () => {
228
+ const segment = writer.flush();
229
+ if (!segment)
230
+ return;
231
+ transact(db, () => {
232
+ const inserted = insertSegment.run(segment.name, segment.bytes, segment.blobs.length, segment.sha256, now);
233
+ const segmentId = Number(inserted.lastInsertRowid);
234
+ for (const blob of segment.blobs) {
235
+ insertBlob.run(blob.sha256, blob.size, segmentId, blob.offset, now);
236
+ storedBlobs.add(blob.sha256);
237
+ }
238
+ for (const row of waiting)
239
+ writeArtifact(row.candidate, row.sha256);
240
+ });
241
+ waiting = [];
242
+ pendingBlobs.clear();
243
+ reporter?.segment?.({
244
+ name: segment.name,
245
+ bytes: segment.bytes,
246
+ blobs: segment.blobs.length,
247
+ });
248
+ };
249
+ for (const candidate of candidates) {
250
+ const previous = indexed.get(artifactKey(candidate.provider, candidate.recordPath));
251
+ if (previous && previous.size === candidate.size && previous.mtimeMs === candidate.mtimeMs) {
252
+ counters.unchanged += 1;
253
+ reporter?.file?.({
254
+ path: candidate.recordPath,
255
+ class: candidate.set.class,
256
+ size: candidate.size,
257
+ disposition: "unchanged",
258
+ });
259
+ continue;
260
+ }
261
+ let content;
262
+ try {
263
+ content = await readCandidate(candidate);
264
+ }
265
+ catch (error) {
266
+ counters.skipped += 1;
267
+ const reason = error.message;
268
+ failures.push({ file: candidate.file, reason });
269
+ reporter?.failure?.({ file: candidate.file, reason });
270
+ reporter?.file?.({
271
+ path: candidate.recordPath,
272
+ class: candidate.set.class,
273
+ size: candidate.size,
274
+ disposition: "skipped",
275
+ });
276
+ continue;
277
+ }
278
+ counters.hashed += 1;
279
+ const sha256 = hashBuffer(content);
280
+ const seen = (disposition) => reporter?.file?.({
281
+ path: candidate.recordPath,
282
+ class: candidate.set.class,
283
+ size: candidate.size,
284
+ disposition,
285
+ sha256,
286
+ });
287
+ if (storedBlobs.has(sha256)) {
288
+ // Same bytes under a new path, or a file touched without being changed.
289
+ counters.duplicate += 1;
290
+ transact(db, () => writeArtifact(candidate, sha256));
291
+ seen("duplicate");
292
+ continue;
293
+ }
294
+ if (pendingBlobs.has(sha256)) {
295
+ // Content this same run has already buffered. One member covers both
296
+ // paths, so only the row is added — once the segment is sealed.
297
+ counters.duplicate += 1;
298
+ waiting.push({ candidate, sha256 });
299
+ seen("duplicate");
300
+ continue;
301
+ }
302
+ counters.stored += 1;
303
+ counters.bytes += content.length;
304
+ bump(candidate.set.class, "stored");
305
+ (byClass[candidate.set.class] ??= { discovered: 0, stored: 0, bytes: 0 }).bytes +=
306
+ content.length;
307
+ pendingBlobs.add(sha256);
308
+ waiting.push({ candidate, sha256 });
309
+ seen("stored");
310
+ writer.add({ sha256, content, mode: candidate.mode });
311
+ if (writer.shouldSeal)
312
+ commitSegment();
313
+ }
314
+ commitSegment();
315
+ reporter?.finish?.();
316
+ return {
317
+ counters,
318
+ failures,
319
+ segments: writer.sealed.map((segment) => ({
320
+ name: segment.name,
321
+ bytes: segment.bytes,
322
+ blobs: segment.blobs.length,
323
+ })),
324
+ byClass,
325
+ };
326
+ }
327
+ finally {
328
+ closeQuietly(db);
329
+ }
330
+ }
331
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/archive/run.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Append-only compressed segments.
3
+ *
4
+ * A segment is a deterministic `.tar.gz` built by the writer in
5
+ * `src/agent/package/tar.ts`, which already pins mtime, uid, gid, uname and
6
+ * entry order. Once sealed it is never rewritten: a later run adds a new
7
+ * segment, which is what makes the archive safe to copy to slower storage and
8
+ * what keeps an interrupted run from corrupting what came before.
9
+ *
10
+ * Members are named `blobs/<aa>/<sha256>` rather than by their original path,
11
+ * for two reasons. Deduplication falls out of it — two identical files are one
12
+ * member — and every name is then 73 characters, comfortably inside the ustar
13
+ * `name` field. Real paths would not be: the source corpus nests seven deep
14
+ * under project slugs that are themselves absolute paths with the separators
15
+ * replaced, and `tarball` refuses a path that will not fit rather than escalating
16
+ * to a PAX header.
17
+ */
18
+ /** Default seal threshold, in uncompressed bytes. */
19
+ export declare const DEFAULT_SEGMENT_BYTES: number;
20
+ export interface PendingBlob {
21
+ sha256: string;
22
+ content: Buffer;
23
+ mode: number;
24
+ }
25
+ export interface StoredBlob {
26
+ sha256: string;
27
+ size: number;
28
+ /** Byte offset of the member's data within the uncompressed segment. */
29
+ offset: number;
30
+ }
31
+ export interface SealedSegment {
32
+ name: string;
33
+ /** Size of the `.tar.gz` on disk. */
34
+ bytes: number;
35
+ /** Hash of the `.tar.gz`, which is what `archive verify` checks. */
36
+ sha256: string;
37
+ blobs: StoredBlob[];
38
+ }
39
+ export declare function hashBuffer(content: Buffer): string;
40
+ export declare function memberPath(sha256: string): string;
41
+ export declare function segmentName(sequence: number): string;
42
+ /**
43
+ * Writes pending blobs as one sealed segment.
44
+ *
45
+ * The archive is built once and then read to find each member's offset, rather
46
+ * than the offsets being predicted from the entry sizes. Predicting them would
47
+ * duplicate the writer's padding and header rules in a second place, where they
48
+ * could drift; reading them back cannot be wrong about a file this same process
49
+ * just produced.
50
+ */
51
+ export declare function sealSegment(directory: string, sequence: number, pending: readonly PendingBlob[]): SealedSegment;
52
+ /** Decompresses a segment. Callers that want several members read it once. */
53
+ export declare function readSegment(directory: string, name: string): Buffer;
54
+ /**
55
+ * Extracts one blob from an already-decompressed segment.
56
+ *
57
+ * The offset comes from the index, so this is a slice rather than a walk. The
58
+ * hash is re-checked against the content because an archive whose index and
59
+ * bytes disagree should say so rather than hand back the wrong file.
60
+ */
61
+ export declare function extractBlob(uncompressed: Buffer, blob: StoredBlob): Buffer;
62
+ /**
63
+ * Accumulates blobs and seals a segment when the threshold is reached.
64
+ *
65
+ * The threshold is on *uncompressed* bytes because that is what bounds memory:
66
+ * the tar is built whole before it is compressed. A blob larger than the
67
+ * threshold gets a segment to itself rather than being split, since a member
68
+ * spanning two archives could not be read by `tar`.
69
+ */
70
+ export declare class SegmentWriter {
71
+ private readonly directory;
72
+ private readonly threshold;
73
+ private pending;
74
+ private pendingBytes;
75
+ private sequence;
76
+ readonly sealed: SealedSegment[];
77
+ constructor(directory: string, firstSequence: number, threshold?: number);
78
+ add(blob: PendingBlob): void;
79
+ /**
80
+ * Whether the buffer has reached the threshold.
81
+ *
82
+ * Sealing is the caller's move rather than a side effect of {@link add},
83
+ * because the index rows for the blobs in a segment can only be written once
84
+ * that segment has an id — so the caller has to know exactly when it happened.
85
+ */
86
+ get shouldSeal(): boolean;
87
+ get buffered(): number;
88
+ flush(): SealedSegment | null;
89
+ }
@@ -0,0 +1,144 @@
1
+ import crypto from "node:crypto";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import zlib from "node:zlib";
5
+ import { archive as tarGz, tarball } from "../agent/package/tar.js";
6
+ import { listMembers, readMember } from "./tar-read.js";
7
+ /**
8
+ * Append-only compressed segments.
9
+ *
10
+ * A segment is a deterministic `.tar.gz` built by the writer in
11
+ * `src/agent/package/tar.ts`, which already pins mtime, uid, gid, uname and
12
+ * entry order. Once sealed it is never rewritten: a later run adds a new
13
+ * segment, which is what makes the archive safe to copy to slower storage and
14
+ * what keeps an interrupted run from corrupting what came before.
15
+ *
16
+ * Members are named `blobs/<aa>/<sha256>` rather than by their original path,
17
+ * for two reasons. Deduplication falls out of it — two identical files are one
18
+ * member — and every name is then 73 characters, comfortably inside the ustar
19
+ * `name` field. Real paths would not be: the source corpus nests seven deep
20
+ * under project slugs that are themselves absolute paths with the separators
21
+ * replaced, and `tarball` refuses a path that will not fit rather than escalating
22
+ * to a PAX header.
23
+ */
24
+ /** Default seal threshold, in uncompressed bytes. */
25
+ export const DEFAULT_SEGMENT_BYTES = 64 * 1024 * 1024;
26
+ export function hashBuffer(content) {
27
+ return crypto.createHash("sha256").update(content).digest("hex");
28
+ }
29
+ export function memberPath(sha256) {
30
+ return `blobs/${sha256.slice(0, 2)}/${sha256}`;
31
+ }
32
+ export function segmentName(sequence) {
33
+ return `seg-${String(sequence).padStart(6, "0")}.tar.gz`;
34
+ }
35
+ /**
36
+ * Writes pending blobs as one sealed segment.
37
+ *
38
+ * The archive is built once and then read to find each member's offset, rather
39
+ * than the offsets being predicted from the entry sizes. Predicting them would
40
+ * duplicate the writer's padding and header rules in a second place, where they
41
+ * could drift; reading them back cannot be wrong about a file this same process
42
+ * just produced.
43
+ */
44
+ export function sealSegment(directory, sequence, pending) {
45
+ const entries = pending.map((blob) => ({
46
+ path: memberPath(blob.sha256),
47
+ content: blob.content,
48
+ mode: blob.mode,
49
+ }));
50
+ const uncompressed = tarball(entries);
51
+ const members = new Map(listMembers(uncompressed)
52
+ .filter((member) => !member.directory)
53
+ .map((member) => [member.path, member]));
54
+ const blobs = pending.map((blob) => {
55
+ const member = members.get(memberPath(blob.sha256));
56
+ if (!member)
57
+ throw new Error(`Segment is missing the member it was built with: ${blob.sha256}`);
58
+ return { sha256: blob.sha256, size: member.size, offset: member.offset };
59
+ });
60
+ const name = segmentName(sequence);
61
+ const payload = tarGz(entries);
62
+ fs.mkdirSync(directory, { recursive: true });
63
+ const target = path.join(directory, name);
64
+ // Written to a temporary name and renamed, so an interrupted run never leaves
65
+ // a half-written segment that the index would then claim is complete.
66
+ const temporary = `${target}.${process.pid}.tmp`;
67
+ fs.writeFileSync(temporary, payload);
68
+ fs.renameSync(temporary, target);
69
+ return { name, bytes: payload.length, sha256: hashBuffer(payload), blobs };
70
+ }
71
+ /** Decompresses a segment. Callers that want several members read it once. */
72
+ export function readSegment(directory, name) {
73
+ return zlib.gunzipSync(fs.readFileSync(path.join(directory, name)));
74
+ }
75
+ /**
76
+ * Extracts one blob from an already-decompressed segment.
77
+ *
78
+ * The offset comes from the index, so this is a slice rather than a walk. The
79
+ * hash is re-checked against the content because an archive whose index and
80
+ * bytes disagree should say so rather than hand back the wrong file.
81
+ */
82
+ export function extractBlob(uncompressed, blob) {
83
+ const content = readMember(uncompressed, {
84
+ path: memberPath(blob.sha256),
85
+ mode: 0,
86
+ size: blob.size,
87
+ offset: blob.offset,
88
+ directory: false,
89
+ });
90
+ const actual = hashBuffer(content);
91
+ if (actual !== blob.sha256) {
92
+ throw new Error(`Archive corruption: expected ${blob.sha256}, segment holds ${actual}`);
93
+ }
94
+ return content;
95
+ }
96
+ /**
97
+ * Accumulates blobs and seals a segment when the threshold is reached.
98
+ *
99
+ * The threshold is on *uncompressed* bytes because that is what bounds memory:
100
+ * the tar is built whole before it is compressed. A blob larger than the
101
+ * threshold gets a segment to itself rather than being split, since a member
102
+ * spanning two archives could not be read by `tar`.
103
+ */
104
+ export class SegmentWriter {
105
+ directory;
106
+ threshold;
107
+ pending = [];
108
+ pendingBytes = 0;
109
+ sequence;
110
+ sealed = [];
111
+ constructor(directory, firstSequence, threshold = DEFAULT_SEGMENT_BYTES) {
112
+ this.directory = directory;
113
+ this.threshold = threshold;
114
+ this.sequence = firstSequence;
115
+ }
116
+ add(blob) {
117
+ this.pending.push(blob);
118
+ this.pendingBytes += blob.content.length;
119
+ }
120
+ /**
121
+ * Whether the buffer has reached the threshold.
122
+ *
123
+ * Sealing is the caller's move rather than a side effect of {@link add},
124
+ * because the index rows for the blobs in a segment can only be written once
125
+ * that segment has an id — so the caller has to know exactly when it happened.
126
+ */
127
+ get shouldSeal() {
128
+ return this.pendingBytes >= this.threshold;
129
+ }
130
+ get buffered() {
131
+ return this.pending.length;
132
+ }
133
+ flush() {
134
+ if (this.pending.length === 0)
135
+ return null;
136
+ const segment = sealSegment(this.directory, this.sequence, this.pending);
137
+ this.sealed.push(segment);
138
+ this.sequence += 1;
139
+ this.pending = [];
140
+ this.pendingBytes = 0;
141
+ return segment;
142
+ }
143
+ }
144
+ //# sourceMappingURL=segments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"segments.js","sourceRoot":"","sources":["../../src/archive/segments.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * What each provider leaves on disk that is worth keeping.
3
+ *
4
+ * This is data the archiver reads, exactly as `src/agent/targets/*.ts` is for
5
+ * the renderer and `ProviderCapabilities` is for the usage reports.
6
+ * `src/commands/archive.ts` must never branch on a provider name: a provider
7
+ * that stores plans somewhere unusual says so here, and adding a fourth
8
+ * assistant is a new entry in this list plus the usage provider it names.
9
+ *
10
+ * Selection is an **allowlist of directories**, not a filter over a whole home
11
+ * directory, and that is the design. `~/.claude` alone holds 340 MB of plugin
12
+ * payloads, a 71 MB downloaded binary, and a `jobs/` tree that on this machine
13
+ * was 343 MB of Rust build output — none of it conversation data, all of it
14
+ * things a blocklist would eventually fail to exclude. Walking only what is
15
+ * named here cannot pick them up by accident.
16
+ */
17
+ /**
18
+ * What an artifact is, which is what `--include` selects on.
19
+ *
20
+ * `plan` and `artifact` are archived by default: they are the durable output of
21
+ * a session, they are small, and nothing else keeps them. `transcript` and `log`
22
+ * are opt-in because they are the other three orders of magnitude — the same
23
+ * corpus is roughly 150 MB of the first two and over 9 GB with the rest.
24
+ */
25
+ export type ArtifactClass = "plan" | "artifact" | "transcript" | "log";
26
+ export declare const ARTIFACT_CLASSES: readonly ArtifactClass[];
27
+ /** The classes `archive run` takes when `--include` is not given. */
28
+ export declare const DEFAULT_CLASSES: readonly ArtifactClass[];
29
+ export interface ArtifactSet {
30
+ /** Stable identifier, reported per set so a caller can see what matched. */
31
+ id: string;
32
+ class: ArtifactClass;
33
+ description: string;
34
+ /** Directory under the provider's log root to walk; "" is the root itself. */
35
+ root: string;
36
+ /** Whether to descend into subdirectories. */
37
+ recursive: boolean;
38
+ /** Decides membership, given a path relative to {@link root}, POSIX-separated. */
39
+ match(relative: string): boolean;
40
+ /**
41
+ * How to read a file whose bytes are not safe to copy directly.
42
+ *
43
+ * Every Codex `.sqlite` and all 501 Antigravity `.db` files carry live `-wal`
44
+ * sidecars, so copying the main file alone can capture a torn page image.
45
+ * `sqlite` routes them through the online backup API, which produces a
46
+ * consistent snapshot of a database being written to.
47
+ */
48
+ snapshot?: "sqlite";
49
+ }
50
+ export interface ArchiveProfile {
51
+ /** Matches a `UsageProvider.name`, which is what resolves the log root. */
52
+ provider: string;
53
+ sets: readonly ArtifactSet[];
54
+ }
55
+ export declare const ARCHIVE_PROFILES: readonly ArchiveProfile[];
56
+ export declare function profileFor(provider: string): ArchiveProfile | undefined;
57
+ /** Parses `--include plans,transcripts` into the classes it names. */
58
+ export declare function parseClasses(value: string | undefined): ArtifactClass[];