paperlint 7.2.0 → 9.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 (474) hide show
  1. package/CLAUDE.md +9 -25
  2. package/CONTRIBUTING.md +5 -4
  3. package/README.md +4 -3
  4. package/dist/adapters/bibtex/index.d.ts +3 -0
  5. package/dist/adapters/bibtex/index.d.ts.map +1 -0
  6. package/dist/adapters/bibtex/index.js +103 -0
  7. package/dist/adapters/bibtex/index.js.map +1 -0
  8. package/dist/adapters/latex/filecontents.d.ts +33 -0
  9. package/dist/adapters/latex/filecontents.d.ts.map +1 -0
  10. package/dist/adapters/latex/filecontents.js +65 -0
  11. package/dist/adapters/latex/filecontents.js.map +1 -0
  12. package/dist/adapters/latex/includes.d.ts +3 -3
  13. package/dist/adapters/latex/includes.d.ts.map +1 -1
  14. package/dist/adapters/latex/includes.js +18 -10
  15. package/dist/adapters/latex/includes.js.map +1 -1
  16. package/dist/adapters/latex/index.d.ts.map +1 -1
  17. package/dist/adapters/latex/index.js +2 -0
  18. package/dist/adapters/latex/index.js.map +1 -1
  19. package/dist/adapters/latex/nodes.d.ts +12 -0
  20. package/dist/adapters/latex/nodes.d.ts.map +1 -1
  21. package/dist/adapters/latex/nodes.js +39 -0
  22. package/dist/adapters/latex/nodes.js.map +1 -1
  23. package/dist/adapters/latex/parse.d.ts +7 -1
  24. package/dist/adapters/latex/parse.d.ts.map +1 -1
  25. package/dist/adapters/latex/parse.js +55 -6
  26. package/dist/adapters/latex/parse.js.map +1 -1
  27. package/dist/adapters/memory/index.d.ts +3 -0
  28. package/dist/adapters/memory/index.d.ts.map +1 -1
  29. package/dist/adapters/memory/index.js +9 -0
  30. package/dist/adapters/memory/index.js.map +1 -1
  31. package/dist/adapters/references/index.d.ts.map +1 -1
  32. package/dist/adapters/references/index.js +27 -24
  33. package/dist/adapters/references/index.js.map +1 -1
  34. package/dist/adapters/sources-record/index.d.ts +9 -0
  35. package/dist/adapters/sources-record/index.d.ts.map +1 -0
  36. package/dist/adapters/sources-record/index.js +68 -0
  37. package/dist/adapters/sources-record/index.js.map +1 -0
  38. package/dist/adapters/tex-output/blg.d.ts +9 -0
  39. package/dist/adapters/tex-output/blg.d.ts.map +1 -0
  40. package/dist/adapters/tex-output/blg.js +20 -0
  41. package/dist/adapters/tex-output/blg.js.map +1 -0
  42. package/dist/adapters/tex-output/fls.d.ts +8 -0
  43. package/dist/adapters/tex-output/fls.d.ts.map +1 -0
  44. package/dist/adapters/tex-output/fls.js +16 -0
  45. package/dist/adapters/tex-output/fls.js.map +1 -0
  46. package/dist/adapters/tex-output/index.d.ts +7 -0
  47. package/dist/adapters/tex-output/index.d.ts.map +1 -0
  48. package/dist/adapters/tex-output/index.js +7 -0
  49. package/dist/adapters/tex-output/index.js.map +1 -0
  50. package/dist/bib-rules.d.ts +47 -0
  51. package/dist/bib-rules.d.ts.map +1 -0
  52. package/dist/bib-rules.js +127 -0
  53. package/dist/bib-rules.js.map +1 -0
  54. package/dist/build.d.ts +29 -1
  55. package/dist/build.d.ts.map +1 -1
  56. package/dist/build.js +41 -30
  57. package/dist/build.js.map +1 -1
  58. package/dist/claim-provenance.d.ts +2 -2
  59. package/dist/cli.d.ts +9 -5
  60. package/dist/cli.d.ts.map +1 -1
  61. package/dist/cli.js +43 -68
  62. package/dist/cli.js.map +1 -1
  63. package/dist/domain/paper-source.d.ts +1 -10
  64. package/dist/domain/paper-source.d.ts.map +1 -1
  65. package/dist/domain/paper-source.js +34 -24
  66. package/dist/domain/paper-source.js.map +1 -1
  67. package/dist/domain/paper-sources.d.ts +72 -0
  68. package/dist/domain/paper-sources.d.ts.map +1 -0
  69. package/dist/domain/paper-sources.js +18 -0
  70. package/dist/domain/paper-sources.js.map +1 -0
  71. package/dist/domain/sources-record.d.ts +102 -0
  72. package/dist/domain/sources-record.d.ts.map +1 -0
  73. package/dist/domain/sources-record.js +38 -0
  74. package/dist/domain/sources-record.js.map +1 -0
  75. package/dist/domain/tex-run.d.ts +25 -0
  76. package/dist/domain/tex-run.d.ts.map +1 -0
  77. package/dist/domain/tex-run.js +79 -0
  78. package/dist/domain/tex-run.js.map +1 -0
  79. package/dist/eslint-rules/latex-language.d.ts.map +1 -1
  80. package/dist/eslint-rules/latex-language.js +10 -13
  81. package/dist/eslint-rules/latex-language.js.map +1 -1
  82. package/dist/eslint-rules/paper-context.d.ts.map +1 -1
  83. package/dist/eslint-rules/paper-context.js +6 -5
  84. package/dist/eslint-rules/paper-context.js.map +1 -1
  85. package/dist/eslint-rules/paper-typography.d.ts +0 -9
  86. package/dist/eslint-rules/paper-typography.d.ts.map +1 -1
  87. package/dist/eslint-rules/paper-typography.js +34 -96
  88. package/dist/eslint-rules/paper-typography.js.map +1 -1
  89. package/dist/eslint-rules/papers.d.ts +1 -3
  90. package/dist/eslint-rules/papers.d.ts.map +1 -1
  91. package/dist/eslint-rules/papers.js +2 -4
  92. package/dist/eslint-rules/papers.js.map +1 -1
  93. package/dist/eslint-rules/tex-build.d.ts.map +1 -1
  94. package/dist/eslint-rules/tex-build.js +8 -25
  95. package/dist/eslint-rules/tex-build.js.map +1 -1
  96. package/dist/init.d.ts +1 -4
  97. package/dist/init.d.ts.map +1 -1
  98. package/dist/init.js +3 -9
  99. package/dist/init.js.map +1 -1
  100. package/dist/latex-log.d.ts +10 -0
  101. package/dist/latex-log.d.ts.map +1 -1
  102. package/dist/latex-log.js +10 -0
  103. package/dist/latex-log.js.map +1 -1
  104. package/dist/latex-loop.d.ts +2 -0
  105. package/dist/latex-loop.d.ts.map +1 -1
  106. package/dist/latex-loop.js.map +1 -1
  107. package/dist/lib/markdown.d.ts +5 -81
  108. package/dist/lib/markdown.d.ts.map +1 -1
  109. package/dist/lib/markdown.js +5 -116
  110. package/dist/lib/markdown.js.map +1 -1
  111. package/dist/lib/paper-config.d.ts.map +1 -1
  112. package/dist/lib/paper-config.js +0 -2
  113. package/dist/lib/paper-config.js.map +1 -1
  114. package/dist/lib/skill-eval-fixture.d.ts +6 -4
  115. package/dist/lib/skill-eval-fixture.d.ts.map +1 -1
  116. package/dist/lib/skill-eval-fixture.js +25 -18
  117. package/dist/lib/skill-eval-fixture.js.map +1 -1
  118. package/dist/new-paper.d.ts +5 -11
  119. package/dist/new-paper.d.ts.map +1 -1
  120. package/dist/new-paper.js +12 -23
  121. package/dist/new-paper.js.map +1 -1
  122. package/dist/package-dirs.d.ts.map +1 -1
  123. package/dist/package-dirs.js +3 -2
  124. package/dist/package-dirs.js.map +1 -1
  125. package/dist/paper-files.d.ts +4 -4
  126. package/dist/paper-includes.d.ts +4 -7
  127. package/dist/paper-includes.d.ts.map +1 -1
  128. package/dist/paper-includes.js +29 -21
  129. package/dist/paper-includes.js.map +1 -1
  130. package/dist/paper-prose.d.ts +17 -0
  131. package/dist/paper-prose.d.ts.map +1 -0
  132. package/dist/paper-prose.js +46 -0
  133. package/dist/paper-prose.js.map +1 -0
  134. package/dist/paper-record.d.ts +25 -0
  135. package/dist/paper-record.d.ts.map +1 -0
  136. package/dist/paper-record.js +39 -0
  137. package/dist/paper-record.js.map +1 -0
  138. package/dist/paper-sources.d.ts +66 -0
  139. package/dist/paper-sources.d.ts.map +1 -0
  140. package/dist/paper-sources.js +92 -0
  141. package/dist/paper-sources.js.map +1 -0
  142. package/dist/ports/bib-reader.d.ts +18 -0
  143. package/dist/ports/bib-reader.d.ts.map +1 -0
  144. package/dist/ports/bib-reader.js +2 -0
  145. package/dist/ports/bib-reader.js.map +1 -0
  146. package/dist/ports/check-references.d.ts +9 -4
  147. package/dist/ports/check-references.d.ts.map +1 -1
  148. package/dist/ports/latex.d.ts +15 -0
  149. package/dist/ports/latex.d.ts.map +1 -1
  150. package/dist/ports/sources-codec.d.ts +11 -0
  151. package/dist/ports/sources-codec.d.ts.map +1 -0
  152. package/dist/ports/sources-codec.js +2 -0
  153. package/dist/ports/sources-codec.js.map +1 -0
  154. package/dist/ports/tex-output.d.ts +17 -0
  155. package/dist/ports/tex-output.d.ts.map +1 -0
  156. package/dist/ports/tex-output.js +2 -0
  157. package/dist/ports/tex-output.js.map +1 -0
  158. package/dist/recorded-bibliography.d.ts +89 -0
  159. package/dist/recorded-bibliography.d.ts.map +1 -0
  160. package/dist/recorded-bibliography.js +136 -0
  161. package/dist/recorded-bibliography.js.map +1 -0
  162. package/dist/reference-rules.d.ts +5 -5
  163. package/dist/reference-rules.d.ts.map +1 -1
  164. package/dist/reference-rules.js +150 -77
  165. package/dist/reference-rules.js.map +1 -1
  166. package/dist/references.d.ts +71 -16
  167. package/dist/references.d.ts.map +1 -1
  168. package/dist/references.js +110 -26
  169. package/dist/references.js.map +1 -1
  170. package/dist/register-bands.d.ts +3 -3
  171. package/dist/register-bands.d.ts.map +1 -1
  172. package/dist/register-bands.js.map +1 -1
  173. package/dist/register.d.ts +2 -2
  174. package/dist/sources-record.d.ts +38 -0
  175. package/dist/sources-record.d.ts.map +1 -0
  176. package/dist/sources-record.js +123 -0
  177. package/dist/sources-record.js.map +1 -0
  178. package/dist/sources-rules.d.ts +44 -0
  179. package/dist/sources-rules.d.ts.map +1 -0
  180. package/dist/sources-rules.js +76 -0
  181. package/dist/sources-rules.js.map +1 -0
  182. package/dist/structure.d.ts.map +1 -1
  183. package/dist/structure.js +4 -3
  184. package/dist/structure.js.map +1 -1
  185. package/dist/tex-paper.d.ts +10 -15
  186. package/dist/tex-paper.d.ts.map +1 -1
  187. package/dist/tex-paper.js +24 -40
  188. package/dist/tex-paper.js.map +1 -1
  189. package/dist/tex-venue-rules.d.ts +3 -3
  190. package/dist/tex-venue-rules.d.ts.map +1 -1
  191. package/dist/tex-venue-rules.js.map +1 -1
  192. package/dist/types.d.ts +0 -2
  193. package/dist/types.d.ts.map +1 -1
  194. package/docs/configuration.md +18 -12
  195. package/docs/design/paper-sources.md +197 -0
  196. package/docs/e2e.md +4 -6
  197. package/docs/package-shape-options.md +1 -1
  198. package/docs/prior-art/paper-folder-scaffolding.md +24 -29
  199. package/docs/references.md +34 -8
  200. package/docs/rules/bib/reachable-entry.md +64 -0
  201. package/docs/rules/paper/sources-fresh.md +81 -0
  202. package/docs/rules/tex/claim-provenance.md +0 -1
  203. package/docs/rules.md +62 -61
  204. package/eslint-rules/latex-language.harness.mjs +3 -3
  205. package/eslint-rules/latex-language.ts +10 -13
  206. package/eslint-rules/paper-context.ts +6 -5
  207. package/eslint-rules/paper-typography.test.mjs +29 -157
  208. package/eslint-rules/paper-typography.ts +35 -104
  209. package/eslint-rules/papers.harness.mjs +1 -1
  210. package/eslint-rules/papers.ts +2 -4
  211. package/eslint-rules/tex-build.harness.mjs +2 -2
  212. package/eslint-rules/tex-build.ts +8 -25
  213. package/eslint.config.mjs +22 -1
  214. package/fixtures/build-e2e/aidc/paper.tex +1 -1
  215. package/fixtures/build-e2e/anon-ack/paper.tex +1 -1
  216. package/fixtures/build-e2e/anon-author/paper.tex +1 -1
  217. package/fixtures/build-e2e/anon-bib/paper.tex +1 -1
  218. package/fixtures/build-e2e/anon-href/paper.tex +1 -1
  219. package/fixtures/build-e2e/anon-macro/paper.tex +1 -1
  220. package/fixtures/build-e2e/anon-pdfauthor/paper.tex +1 -1
  221. package/fixtures/paper-sources/p1/paper.tex +30 -0
  222. package/fixtures/paper-sources/p1/refs.bib +6 -0
  223. package/fixtures/paper-sources/p1/sections/dead.tex +6 -0
  224. package/fixtures/paper-sources/p1/sections/intro.tex +7 -0
  225. package/fixtures/paper-sources/p1/sections/parked.tex +6 -0
  226. package/fixtures/paper-sources/p1/tex-truth.json +37 -0
  227. package/fixtures/paper-sources/p1/versions/2026-01-01-review.tex +4 -0
  228. package/fixtures/paper-sources/v1-stale/paper.tex +14 -0
  229. package/fixtures/paper-sources/v1-stale/refs.bib +6 -0
  230. package/fixtures/paper-sources/v1-stale/tex-truth.json +32 -0
  231. package/fixtures/paper-sources/v10-ifthenelse/anon.bib +1 -0
  232. package/fixtures/paper-sources/v10-ifthenelse/paper.tex +9 -0
  233. package/fixtures/paper-sources/v10-ifthenelse/real.bib +1 -0
  234. package/fixtures/paper-sources/v10-ifthenelse/tex-truth.json +28 -0
  235. package/fixtures/paper-sources/v11-two-blocks/paper.tex +12 -0
  236. package/fixtures/paper-sources/v11-two-blocks/tex-truth.json +30 -0
  237. package/fixtures/paper-sources/v13-percent-text/paper.tex +6 -0
  238. package/fixtures/paper-sources/v13-percent-text/refs.bib +3 -0
  239. package/fixtures/paper-sources/v13-percent-text/tex-truth.json +30 -0
  240. package/fixtures/paper-sources/v15-after-end/paper.tex +6 -0
  241. package/fixtures/paper-sources/v15-after-end/refs.bib +1 -0
  242. package/fixtures/paper-sources/v15-after-end/tex-truth.json +17 -0
  243. package/fixtures/paper-sources/v16-included-block/bibblock.tex +3 -0
  244. package/fixtures/paper-sources/v16-included-block/paper.tex +7 -0
  245. package/fixtures/paper-sources/v16-included-block/refs.bib +1 -0
  246. package/fixtures/paper-sources/v16-included-block/tex-truth.json +35 -0
  247. package/fixtures/paper-sources/v17-include-order/bibsetup.tex +1 -0
  248. package/fixtures/paper-sources/v17-include-order/first.bib +1 -0
  249. package/fixtures/paper-sources/v17-include-order/later.bib +1 -0
  250. package/fixtures/paper-sources/v17-include-order/paper.tex +7 -0
  251. package/fixtures/paper-sources/v17-include-order/tex-truth.json +40 -0
  252. package/fixtures/paper-sources/v2-overwrite/paper.tex +14 -0
  253. package/fixtures/paper-sources/v2-overwrite/refs.bib +6 -0
  254. package/fixtures/paper-sources/v2-overwrite/tex-truth.json +30 -0
  255. package/fixtures/paper-sources/v22-parked-thebibliography/paper.tex +7 -0
  256. package/fixtures/paper-sources/v22-parked-thebibliography/tex-truth.json +17 -0
  257. package/fixtures/paper-sources/v23-parked-include/old.bib +1 -0
  258. package/fixtures/paper-sources/v23-parked-include/paper.tex +7 -0
  259. package/fixtures/paper-sources/v23-parked-include/parked.tex +1 -0
  260. package/fixtures/paper-sources/v23-parked-include/refs.bib +1 -0
  261. package/fixtures/paper-sources/v23-parked-include/tex-truth.json +28 -0
  262. package/fixtures/paper-sources/v24-quoted-fields/paper.tex +6 -0
  263. package/fixtures/paper-sources/v24-quoted-fields/refs.bib +5 -0
  264. package/fixtures/paper-sources/v24-quoted-fields/tex-truth.json +32 -0
  265. package/fixtures/paper-sources/v25-string-differs/paper.tex +10 -0
  266. package/fixtures/paper-sources/v25-string-differs/refs.bib +2 -0
  267. package/fixtures/paper-sources/v25-string-differs/tex-truth.json +32 -0
  268. package/fixtures/paper-sources/v26-comment-in-names/one.bib +1 -0
  269. package/fixtures/paper-sources/v26-comment-in-names/paper.tex +7 -0
  270. package/fixtures/paper-sources/v26-comment-in-names/tex-truth.json +32 -0
  271. package/fixtures/paper-sources/v26-comment-in-names/two.bib +1 -0
  272. package/fixtures/paper-sources/v27-shared-string/abbreviations.bib +2 -0
  273. package/fixtures/paper-sources/v27-shared-string/paper.tex +6 -0
  274. package/fixtures/paper-sources/v27-shared-string/references.bib +6 -0
  275. package/fixtures/paper-sources/v27-shared-string/tex-truth.json +31 -0
  276. package/fixtures/paper-sources/v28-shared-string-block/abbreviations.bib +2 -0
  277. package/fixtures/paper-sources/v28-shared-string-block/paper.tex +14 -0
  278. package/fixtures/paper-sources/v28-shared-string-block/tex-truth.json +33 -0
  279. package/fixtures/paper-sources/v29-generated-input/paper.tex +9 -0
  280. package/fixtures/paper-sources/v29-generated-input/tex-truth.json +24 -0
  281. package/fixtures/paper-sources/v3-declared/paper.bib +6 -0
  282. package/fixtures/paper-sources/v3-declared/paper.tex +6 -0
  283. package/fixtures/paper-sources/v3-declared/tex-truth.json +28 -0
  284. package/fixtures/paper-sources/v30-name-next-line/paper.tex +14 -0
  285. package/fixtures/paper-sources/v30-name-next-line/tex-truth.json +30 -0
  286. package/fixtures/paper-sources/v4-commented/paper.tex +14 -0
  287. package/fixtures/paper-sources/v4-commented/refs.bib +6 -0
  288. package/fixtures/paper-sources/v4-commented/tex-truth.json +28 -0
  289. package/fixtures/paper-sources/v5-percent-entry/paper.tex +20 -0
  290. package/fixtures/paper-sources/v5-percent-entry/tex-truth.json +37 -0
  291. package/fixtures/paper-sources/v6-unclosed/paper.tex +6 -0
  292. package/fixtures/paper-sources/v6-unclosed/refs.bib +5 -0
  293. package/fixtures/paper-sources/v6-unclosed/tex-truth.json +37 -0
  294. package/fixtures/paper-sources/v8-jobname/paper.tex +9 -0
  295. package/fixtures/paper-sources/v8-jobname/tex-truth.json +30 -0
  296. package/fixtures/paper-sources/v9-two-bibliographies/one.bib +1 -0
  297. package/fixtures/paper-sources/v9-two-bibliographies/paper.tex +7 -0
  298. package/fixtures/paper-sources/v9-two-bibliographies/tex-truth.json +35 -0
  299. package/fixtures/paper-sources/v9-two-bibliographies/two.bib +1 -0
  300. package/fixtures/paper-typography/clean-paper/paper.tex +1 -1
  301. package/fixtures/paper-typography/messy-paper/paper.tex +1 -1
  302. package/hooks/hooks.harness.ts +15 -15
  303. package/hooks/paper-edit-guard.hook.mjs +5 -8
  304. package/hooks/paper-edit-guard.test.ts +12 -3
  305. package/hooks/paper-skills-nudge.hook.mjs +2 -3
  306. package/hooks/paper-skills-nudge.test.ts +13 -3
  307. package/hooks/paper-status-gates.hook.mjs +2 -2
  308. package/hooks/paper-status-gates.test.ts +14 -2
  309. package/lib/markdown.test.mjs +5 -60
  310. package/lib/markdown.ts +9 -136
  311. package/lib/paper-config.ts +0 -2
  312. package/lib/skill-checks.test.mjs +4 -1
  313. package/lib/skill-eval-fixture.ts +25 -18
  314. package/package.json +2 -12
  315. package/presets/realm.jsonc +1 -1
  316. package/scripts/check.test.ts +23 -1
  317. package/scripts/check.ts +7 -3
  318. package/scripts/coverage-config.test.ts +19 -10
  319. package/scripts/harness-api.frozen.json +0 -5
  320. package/scripts/layer-legacy-frozen.test.ts +41 -2
  321. package/scripts/layer-legacy-frozen.ts +31 -2
  322. package/skills/cold-read-diff/SKILL.md +3 -3
  323. package/skills/cold-read-diff/SKILL.md.spec.ts +2 -2
  324. package/skills/grade-paper-writing/SKILL.md +15 -22
  325. package/skills/grade-paper-writing/SKILL.md.spec.ts +14 -21
  326. package/skills/grade-paper-writing/__snapshots__/prose-lint.test.ts.snap +40 -26
  327. package/skills/grade-paper-writing/prose-lint.mjs +117 -278
  328. package/skills/grade-paper-writing/prose-lint.test.ts +230 -79
  329. package/skills/paper-adversarial-review/SKILL.md +2 -2
  330. package/skills/paper-adversarial-review/SKILL.md.spec.ts +1 -1
  331. package/skills/paper-pipeline/SKILL.md +9 -12
  332. package/skills/paper-pipeline/SKILL.md.spec.ts +8 -11
  333. package/skills/paper-pipeline/description-language.eval.mjs +25 -15
  334. package/skills/paper-pipeline/framing-vs-vocabulary.eval.mjs +25 -15
  335. package/skills/paper-pipeline/grade-paper-writing-ablation.eval.mjs +25 -15
  336. package/skills/paper-pipeline/pipeline-firing.eval.mjs +27 -16
  337. package/skills/paper-pipeline/pipeline-language.eval.mjs +25 -15
  338. package/skills/paper-pipeline/references/acceptance-gate.md +16 -20
  339. package/skills/paper-pipeline/references/artifact-checklist.md +4 -5
  340. package/skills/paper-pipeline/references/pipeline-status-template.md +1 -1
  341. package/skills/paper-pipeline/scripts/README.md +0 -4
  342. package/skills/paper-pipeline/scripts/extract-ref-facts.harness.mjs +91 -105
  343. package/skills/paper-pipeline/scripts/extract-ref-facts.mjs +85 -241
  344. package/skills/paper-pipeline/scripts/extract-ref-facts.test.mjs +166 -153
  345. package/skills/paper-pipeline/scripts/generated-code.harness.mjs +3 -3
  346. package/skills/paper-status/SKILL.md +2 -2
  347. package/skills/paper-status/SKILL.md.spec.ts +1 -1
  348. package/skills/render-paper/SKILL.md +2 -2
  349. package/skills/render-paper/SKILL.md.spec.ts +1 -1
  350. package/skills/render-paper/extract-pdf-facts.mjs +2 -2
  351. package/skills/tighten-paper/SKILL.md +29 -42
  352. package/skills/tighten-paper/SKILL.md.spec.ts +28 -41
  353. package/skills/verify-citations/SKILL.md +7 -4
  354. package/skills/verify-citations/SKILL.md.spec.ts +6 -3
  355. package/skills/verify-citations/scripts/bib-authors.check.test.mjs +17 -32
  356. package/skills/verify-citations/scripts/bib-authors.cli.test.ts +138 -43
  357. package/skills/verify-citations/scripts/bib-authors.d.mts +22 -2
  358. package/skills/verify-citations/scripts/bib-authors.mjs +54 -193
  359. package/skills/verify-citations/scripts/bib-authors.test.mjs +1 -44
  360. package/skills/verify-citations/scripts/verify-cites.cli.test.ts +16 -0
  361. package/skills/verify-citations/scripts/verify-cites.d.mts +19 -3
  362. package/skills/verify-citations/scripts/verify-cites.mjs +42 -108
  363. package/skills/verify-citations/scripts/verify-cites.test.mjs +23 -36
  364. package/src/adapters/bibtex/index.test.ts +163 -0
  365. package/src/adapters/bibtex/index.ts +155 -0
  366. package/src/adapters/latex/filecontents.ts +114 -0
  367. package/src/adapters/latex/includes.ts +18 -10
  368. package/src/adapters/latex/index.test.ts +73 -0
  369. package/src/adapters/latex/index.ts +2 -0
  370. package/src/adapters/latex/nodes.ts +64 -0
  371. package/src/adapters/latex/parse.test.ts +38 -0
  372. package/src/adapters/latex/parse.ts +67 -6
  373. package/src/adapters/memory/index.ts +17 -0
  374. package/src/adapters/references/index.test.ts +75 -21
  375. package/src/adapters/references/index.ts +37 -32
  376. package/src/adapters/sources-record/index.test.ts +87 -0
  377. package/src/adapters/sources-record/index.ts +82 -0
  378. package/src/adapters/tex-output/blg.ts +27 -0
  379. package/src/adapters/tex-output/fls.ts +24 -0
  380. package/src/adapters/tex-output/index.test.ts +171 -0
  381. package/src/adapters/tex-output/index.ts +12 -0
  382. package/src/bib-rules.test.ts +356 -0
  383. package/src/bib-rules.ts +228 -0
  384. package/src/bibliography-at.test.ts +286 -0
  385. package/src/build.harness.mjs +2 -2
  386. package/src/build.test.ts +211 -1
  387. package/src/build.ts +101 -41
  388. package/src/claim-provenance.test.ts +33 -7
  389. package/src/claim-provenance.ts +2 -2
  390. package/src/cli.harness.mjs +46 -56
  391. package/src/cli.test.ts +44 -48
  392. package/src/cli.ts +51 -82
  393. package/src/domain/paper-source.test.ts +58 -20
  394. package/src/domain/paper-source.ts +38 -42
  395. package/src/domain/paper-sources.ts +94 -0
  396. package/src/domain/sources-record.test.ts +71 -0
  397. package/src/domain/sources-record.ts +136 -0
  398. package/src/domain/tex-run.test.ts +228 -0
  399. package/src/domain/tex-run.ts +139 -0
  400. package/src/folder-venue-rule.test.ts +1 -1
  401. package/src/heading-case.test.ts +24 -10
  402. package/src/init.test.ts +6 -7
  403. package/src/init.ts +3 -22
  404. package/src/latex-log.ts +20 -0
  405. package/src/latex-loop.harness.ts +1 -0
  406. package/src/latex-loop.ts +2 -0
  407. package/src/lint-fix.test.ts +10 -4
  408. package/src/linted-set.test.ts +9 -1
  409. package/src/new-paper.harness.mjs +12 -30
  410. package/src/new-paper.test.ts +15 -11
  411. package/src/new-paper.ts +11 -30
  412. package/src/package-dirs.ts +3 -2
  413. package/src/paper-files.test.ts +5 -4
  414. package/src/paper-files.ts +4 -4
  415. package/src/paper-includes.test.ts +157 -38
  416. package/src/paper-includes.ts +39 -35
  417. package/src/paper-prose.test.ts +78 -0
  418. package/src/paper-prose.ts +67 -0
  419. package/src/paper-record.test.ts +173 -0
  420. package/src/paper-record.ts +66 -0
  421. package/src/paper-settings-commands.test.ts +5 -2
  422. package/src/paper-sources.ts +151 -0
  423. package/src/parse-args.test.ts +0 -1
  424. package/src/ports/bib-reader.ts +27 -0
  425. package/src/ports/check-references.ts +7 -3
  426. package/src/ports/latex.ts +19 -0
  427. package/src/ports/sources-codec.ts +11 -0
  428. package/src/ports/tex-output.ts +17 -0
  429. package/src/recorded-bibliography.ts +297 -0
  430. package/src/reference-rules.ts +217 -104
  431. package/src/references.test.ts +520 -177
  432. package/src/references.ts +185 -37
  433. package/src/register-bands.test.ts +5 -1
  434. package/src/register-bands.ts +3 -5
  435. package/src/register.test.ts +6 -1
  436. package/src/register.ts +2 -2
  437. package/src/rule-cases.test.ts +68 -12
  438. package/src/rule-docs.test.ts +0 -1
  439. package/src/sources-record.test.ts +308 -0
  440. package/src/sources-record.ts +231 -0
  441. package/src/sources-rules.test.ts +152 -0
  442. package/src/sources-rules.ts +117 -0
  443. package/src/structure.harness.ts +5 -11
  444. package/src/structure.ts +4 -3
  445. package/src/tex-paper.test.ts +148 -78
  446. package/src/tex-paper.ts +31 -61
  447. package/src/tex-venue-rules.test.ts +36 -8
  448. package/src/tex-venue-rules.ts +3 -5
  449. package/src/types.ts +0 -2
  450. package/dist/eslint-rules/bib-reachable-entry.d.ts +0 -22
  451. package/dist/eslint-rules/bib-reachable-entry.d.ts.map +0 -1
  452. package/dist/eslint-rules/bib-reachable-entry.js +0 -75
  453. package/dist/eslint-rules/bib-reachable-entry.js.map +0 -1
  454. package/eslint-rules/bib-reachable-entry.ts +0 -76
  455. package/fixtures/real-markdown-paper/baseline.json +0 -22
  456. package/fixtures/real-markdown-paper/baseline.ts +0 -70
  457. package/skills/paper-pipeline/PIPELINE-MAP.md +0 -381
  458. package/skills/paper-pipeline/pipeline-firing.baseline.json +0 -270
  459. package/skills/paper-pipeline/references/sweep-2026-08-09-ideal-pipeline.md +0 -585
  460. package/skills/paper-pipeline/scripts/artifact-coverage.harness.mjs +0 -492
  461. package/skills/paper-pipeline/scripts/artifact-coverage.mjs +0 -397
  462. package/skills/paper-pipeline/scripts/artifact-coverage.test.ts +0 -86
  463. package/skills/paper-pipeline/scripts/check-provenance.mjs +0 -184
  464. package/skills/paper-pipeline/scripts/population-map.harness.mjs +0 -135
  465. package/skills/paper-pipeline/scripts/population-map.mjs +0 -188
  466. package/skills/paper-pipeline/scripts/population-map.test.mjs +0 -154
  467. package/skills/paper-pipeline/scripts/provenance.harness.mjs +0 -266
  468. package/skills/paper-pipeline/scripts/round-diff.harness.ts +0 -907
  469. package/skills/paper-pipeline/scripts/round-diff.mjs +0 -583
  470. package/skills/paper-pipeline/scripts/round-diff.test.mjs +0 -159
  471. package/skills/tighten-paper/__snapshots__/structure.test.ts.snap +0 -133
  472. package/skills/tighten-paper/structure.mjs +0 -364
  473. package/skills/tighten-paper/structure.test.ts +0 -117
  474. package/templates/paper/paper.md +0 -4
@@ -9,7 +9,7 @@
9
9
  * 🔴 THREE MEASUREMENTS HERE — THESE ARE THREE DEFECTS THAT LIVED THE ENTIRE LIFE OF THE PREDECESSOR. Each
10
10
  * is pinned by an assertion on a REAL repository file, not a fixture, because all three
11
11
  * held exactly because nobody ever passed the real file:
12
- * 1. `refs.bib` was not in the list of sources (`resolveSource`);
12
+ * 1. `refs.bib` was never opened;
13
13
  * 2. the regex `.bib` required `}` on a separate line and gave 0 entries on both our files;
14
14
  * 3. in `.bib` an author is written "LastName, FirstName", but comparison took the last token.
15
15
  *
@@ -39,11 +39,18 @@ import {
39
39
  import { tmpdir } from "node:os";
40
40
  import { dirname, join } from "node:path";
41
41
  import { fileURLToPath } from "node:url";
42
+ import { bibReader } from "#src/adapters/bibtex/index";
43
+ import { absolutePath } from "#src/domain/paths";
44
+ import { sha256Hex } from "#src/domain/sha256";
45
+ import { serializeSourcesRecord } from "#src/domain/sources-record";
42
46
  import { consumerRoot } from "./consumer.mjs";
43
47
 
44
48
  const HERE = dirname(fileURLToPath(import.meta.url));
45
49
  const ROOT = consumerRoot();
46
50
  const X = await import(join(HERE, "extract-ref-facts.mjs"));
51
+ /** The facts' entries of a BibTeX text, read by the one bibtex reader. */
52
+ const factsOf = (text) =>
53
+ X.factEntries(bibReader.readFile(absolutePath("/p/refs.bib"), text));
47
54
 
48
55
  // 🔴 PAPERS ROOT — FROM THE DECLARATION, NOT BY THE FIRST CONSUMER'S DIRECTORY NAME (12.09.2026).
49
56
  // `package.json` → `paperlint.papersDir`, default `papers`. The same key is read by
@@ -70,38 +77,71 @@ const REAL_PAPERS = existsSync(PAPERS_ROOT)
70
77
  : [];
71
78
 
72
79
  const TMP = realpathSync(mkdtempSync(join(tmpdir(), "extract-ref-facts-")));
80
+
81
+ /**
82
+ * What `paperlint build` leaves in a paper's folder (`_build/sources.json`): bibtex opened `refs.bib`.
83
+ * The paper is read through that record and refused without it, so every paper here is built first.
84
+ */
85
+ function built(dir) {
86
+ const digest = (name) => sha256Hex(readFileSync(join(dir, name)));
87
+ mkdirSync(join(dir, "_build"), { recursive: true });
88
+ writeFileSync(
89
+ join(dir, "_build", "sources.json"),
90
+ serializeSourcesRecord({
91
+ schema: 1,
92
+ inputs: [
93
+ { path: "paper.tex", role: "body" },
94
+ { path: "refs.bib", role: "preamble" },
95
+ ],
96
+ written: [],
97
+ bibdata: ["refs"],
98
+ bibtex: {
99
+ ran: true,
100
+ databases: ["refs.bib"],
101
+ keys: [],
102
+ exit: 0,
103
+ errors: [],
104
+ },
105
+ sha256: {
106
+ "paper.tex": digest("paper.tex"),
107
+ "refs.bib": digest("refs.bib"),
108
+ },
109
+ }),
110
+ );
111
+ }
73
112
  // Cleanup is attached IMMEDIATELY: assertions throw, and "rmSync at end of file" does not execute precisely in those
74
113
  // runs that are red.
75
114
  process.on("exit", () => rmSync(TMP, { recursive: true, force: true }));
76
115
 
77
- // ── 1. DEFECT #1: `refs.bib` must be in the list of sources ─────────────────
116
+ // ── 1. DEFECT #1: the `.bib` a paper declares is opened ──────────────────────
117
+ //
118
+ // The build recorded that bibtex opened `refs.bib`, and `bibliographyAt` opens it. A fixture paper
119
+ // holds the frozen real `.bib`, so the leg is proven on a real file in every checkout.
78
120
  {
79
- assert.ok(
80
- X.SOURCE_ORDER.includes("refs.bib"),
81
- `refs.bib missing from SOURCE_ORDER — this is the defect that kept the .bib leg from ever opening: ${X.SOURCE_ORDER.join(", ")}`,
121
+ const dir = join(TMP, "declares-real-bib");
122
+ mkdirSync(dir, { recursive: true });
123
+ writeFileSync(
124
+ join(dir, "paper.tex"),
125
+ "\\documentclass{article}\\begin{document}x\\bibliography{refs}\\end{document}\n",
82
126
  );
83
- // 🔴 SUBJECT — FIXTURE, real papers ADDITION (12.09.2026). There used to be only a loop over
84
- // our two papers with `continue` if file doesn't exist. In this repo they exist, and test is green;
85
- // in the extracted pipeline their directories WON'T EXIST — both loops make no iteration, and
86
- // harness prints success having checked zero files. "Green over void", a class this base has paid for thrice. Fixture makes an empty run INEXPRESSIBLE: it always lies nearby.
87
- //
88
- // ⚠️ Directory, not file: `resolveSource` returns the path itself if it IS A FILE, and only for
89
- // a directory descends the `SOURCE_ORDER`. A fixture-file would check the wrong branch.
90
- {
91
- const dir = join(HERE, "fixtures", "real-bib");
92
- assert.equal(
93
- X.resolveSource(dir),
94
- join(dir, "refs.bib"),
95
- "resolveSource cannot find the frozen real .bib — .bib leg is dead again",
96
- );
97
- }
127
+ writeFileSync(
128
+ join(dir, "refs.bib"),
129
+ readFileSync(join(HERE, "fixtures", "real-bib", "refs.bib")),
130
+ );
131
+ built(dir);
132
+ const found = X.bibliographyFrom(dir);
133
+ assert.deepEqual(
134
+ found.ok && found.texts.map((t) => t.path),
135
+ [join(dir, "refs.bib")],
136
+ `a paper declaring \\bibliography{refs} does not open its refs.bib — the .bib leg is dead again: ${JSON.stringify(found.why ?? "")}`,
137
+ );
138
+ // Real consumer papers: whatever each declares is either read or refused WITH A REASON — never a
139
+ // silent nothing.
98
140
  for (const paper of REAL_PAPERS) {
99
- const dir = join(PAPERS_ROOT, paper);
100
- if (!existsSync(join(dir, "refs.bib"))) continue;
101
- assert.equal(
102
- X.resolveSource(dir),
103
- join(dir, "refs.bib"),
104
- `resolveSource cannot find real refs.bib for ${paper} — .bib leg is dead again`,
141
+ const r = X.bibliographyFrom(join(PAPERS_ROOT, paper));
142
+ assert.ok(
143
+ r.ok ? r.texts.length > 0 : r.why.length > 0,
144
+ `${paper}: neither a bibliography nor a reason`,
105
145
  );
106
146
  }
107
147
  }
@@ -128,7 +168,7 @@ process.on("exit", () => rmSync(TMP, { recursive: true, force: true }));
128
168
  parsed++;
129
169
  const text = readFileSync(f, "utf8");
130
170
  const want = (text.match(/^@\w+\{/gm) ?? []).length;
131
- const got = await X.parseBib(text);
171
+ const got = factsOf(text);
132
172
  assert.ok(
133
173
  want > 0,
134
174
  `${paper}/refs.bib: no @… entries in file — fixture is broken`,
@@ -170,7 +210,7 @@ process.on("exit", () => rmSync(TMP, { recursive: true, force: true }));
170
210
  @misc{inst2,
171
211
  author={{sh-guard contributors}},
172
212
  title={Another}, year={2026}}`;
173
- const es = await X.parseBib(bib);
213
+ const es = factsOf(bib);
174
214
  assert.deepEqual(
175
215
  es.map((e) => e.authors),
176
216
  [["Adversa AI"], ["sh-guard contributors"]],
@@ -185,7 +225,7 @@ process.on("exit", () => rmSync(TMP, { recursive: true, force: true }));
185
225
  // single brace — ordinary author, and order "LastName, FirstName" must be unwound.
186
226
  {
187
227
  const bib = `@misc{human, author={Adversa, Alice}, title={T}, year={2026}}`;
188
- const [e] = await X.parseBib(bib);
228
+ const [e] = factsOf(bib);
189
229
  assert.deepEqual(
190
230
  e.authors,
191
231
  ["Alice Adversa"],
@@ -201,7 +241,7 @@ process.on("exit", () => rmSync(TMP, { recursive: true, force: true }));
201
241
  const bib = `@inproceedings{k1,
202
242
  author={Jimenez, Carlos E. and Di Penta, Massimiliano and others},
203
243
  title={A Title}, booktitle={ICLR}, year={2024}, note={arXiv:2310.06770}}`;
204
- const [e] = await X.parseBib(bib);
244
+ const [e] = factsOf(bib);
205
245
  assert.deepEqual(
206
246
  e.authors,
207
247
  ["Carlos E. Jimenez", "Massimiliano Di Penta"],
@@ -308,71 +348,17 @@ process.on("exit", () => rmSync(TMP, { recursive: true, force: true }));
308
348
  );
309
349
  }
310
350
 
311
- // ── 7. markdown: reference list, source lines, `et al.`, appendix ───
312
- {
313
- const md = [
314
- "# Paper",
315
- "",
316
- "## 1. Intro",
317
- "",
318
- "Prose.",
319
- "",
320
- "## References",
321
- "",
322
- "1. C. Yang, Z. Zhao, L. Zhang. *KNighter: Transforming Static Analysis.* arXiv:2503.09002, 2025.",
323
- "2. Z. Xiang et al. *Another Work.* ICSE 2024. arXiv:2401.00001",
324
- "",
325
- "## Appendix A",
326
- "",
327
- "1. Not a reference at all.",
328
- "",
329
- ].join("\n");
330
- const es = X.parseMarkdownRefs(md);
331
- assert.equal(
332
- es.length,
333
- 2,
334
- `heading must close the reference list, parsed ${es.length}`,
335
- );
336
- assert.equal(
337
- es[0].line,
338
- 9,
339
- `line of first entry is ${es[0].line}, but it is ninth in file`,
340
- );
341
- assert.equal(es[0].title, "KNighter: Transforming Static Analysis");
342
- assert.equal(es[1].truncated, true, "`et al.` must be marked as truncation");
343
- assert.deepEqual(es[1].authors, ["Z. Xiang"]);
344
- assert.equal(es[1].year, "2024");
345
- }
346
-
347
- // ── 8. `## References` inside ```-block does NOT open list ──────────────────
348
- // Papers in this repo cite their own markup in pieces; the old `split` would open
349
- // bibliography in the middle of a code example.
350
- {
351
- const md = [
352
- "# P",
353
- "",
354
- "## Body",
355
- "",
356
- "```md",
357
- "## References",
358
- "",
359
- "1. Fake. *X.* arXiv:1111.11111",
360
- "```",
361
- "",
362
- ].join("\n");
363
- assert.deepEqual(
364
- X.parseMarkdownRefs(md),
365
- [],
366
- "heading inside ```-block is not a heading",
367
- );
368
- }
369
-
370
- // ── 9. CLI: ZERO ENTRIES — REFUSAL, not empty facts ─────────────────────────
351
+ // ── 7. CLI: ZERO ENTRIES — REFUSAL, not empty facts ─────────────────────────
371
352
  {
372
353
  const { spawnSync } = await import("node:child_process");
373
354
  const dir = join(TMP, "empty");
374
355
  mkdirSync(dir, { recursive: true });
375
- writeFileSync(join(dir, "paper.md"), "# P\n\nNo links at all.\n");
356
+ writeFileSync(
357
+ join(dir, "paper.tex"),
358
+ "\\documentclass{article}\\begin{document}x\\bibliography{refs}\\end{document}\n",
359
+ );
360
+ writeFileSync(join(dir, "refs.bib"), "% no entries at all\n");
361
+ built(dir);
376
362
  const r = spawnSync(
377
363
  "node",
378
364
  [join(HERE, "extract-ref-facts.mjs"), dir, "--offline"],
@@ -393,7 +379,7 @@ process.on("exit", () => rmSync(TMP, { recursive: true, force: true }));
393
379
  );
394
380
  }
395
381
 
396
- // ── 10. CLI: no source — also refusal, not silence ─────────────────────────
382
+ // ── 8. CLI: no source — also refusal, not silence ─────────────────────────
397
383
  {
398
384
  const { spawnSync } = await import("node:child_process");
399
385
  const dir = join(TMP, "nosrc");
@@ -405,25 +391,25 @@ process.on("exit", () => rmSync(TMP, { recursive: true, force: true }));
405
391
  );
406
392
  assert.equal(r.status, 1);
407
393
  assert.ok(
408
- /refs\.bib/u.test(r.stderr),
409
- "message must list sources, including refs.bib",
394
+ /no paper\.tex/u.test(r.stderr),
395
+ `message must say what is missing: ${r.stderr}`,
410
396
  );
411
397
  }
412
398
 
413
- // ── 11. end-to-end: real paper → facts, freshness is computed ───────────────
399
+ // ── 9. end-to-end: real paper → facts, freshness is computed ───────────────
414
400
  {
415
401
  const { spawnSync } = await import("node:child_process");
416
402
  const dir = join(TMP, "e2e");
417
403
  mkdirSync(join(dir, "repro"), { recursive: true });
418
- const paper = [
419
- "# P",
420
- "",
421
- "## References",
422
- "",
423
- "1. A. Lovelace, G. Hopper. *A Study.* arXiv:2503.09002, 2025.",
424
- "",
425
- ].join("\n");
426
- writeFileSync(join(dir, "paper.md"), paper);
404
+ const paper =
405
+ "@misc{lovelace2025,\n author={Lovelace, Ada and Hopper, Grace},\n title={A Study},\n" +
406
+ " note={arXiv:2503.09002},\n year={2025}}\n";
407
+ writeFileSync(join(dir, "refs.bib"), paper);
408
+ writeFileSync(
409
+ join(dir, "paper.tex"),
410
+ "\\documentclass{article}\\begin{document}x\\bibliography{refs}\\end{document}\n",
411
+ );
412
+ built(dir);
427
413
  writeFileSync(
428
414
  join(dir, "repro", "refs-cache.json"),
429
415
  JSON.stringify({
@@ -454,6 +440,6 @@ process.on("exit", () => rmSync(TMP, { recursive: true, force: true }));
454
440
  }
455
441
 
456
442
  console.log(
457
- "✓ extract-ref-facts: refs.bib in sources, both real .bib parse completely, name order unwound, " +
443
+ "✓ extract-ref-facts: the declared refs.bib is opened, both real .bib parse completely, name order unwound, " +
458
444
  "arXiv-DOI does not go to CrossRef, registry readers run on raw bodies, zero entries = refusal",
459
445
  );