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.
- package/CLAUDE.md +9 -25
- package/CONTRIBUTING.md +5 -4
- package/README.md +4 -3
- package/dist/adapters/bibtex/index.d.ts +3 -0
- package/dist/adapters/bibtex/index.d.ts.map +1 -0
- package/dist/adapters/bibtex/index.js +103 -0
- package/dist/adapters/bibtex/index.js.map +1 -0
- package/dist/adapters/latex/filecontents.d.ts +33 -0
- package/dist/adapters/latex/filecontents.d.ts.map +1 -0
- package/dist/adapters/latex/filecontents.js +65 -0
- package/dist/adapters/latex/filecontents.js.map +1 -0
- package/dist/adapters/latex/includes.d.ts +3 -3
- package/dist/adapters/latex/includes.d.ts.map +1 -1
- package/dist/adapters/latex/includes.js +18 -10
- package/dist/adapters/latex/includes.js.map +1 -1
- package/dist/adapters/latex/index.d.ts.map +1 -1
- package/dist/adapters/latex/index.js +2 -0
- package/dist/adapters/latex/index.js.map +1 -1
- package/dist/adapters/latex/nodes.d.ts +12 -0
- package/dist/adapters/latex/nodes.d.ts.map +1 -1
- package/dist/adapters/latex/nodes.js +39 -0
- package/dist/adapters/latex/nodes.js.map +1 -1
- package/dist/adapters/latex/parse.d.ts +7 -1
- package/dist/adapters/latex/parse.d.ts.map +1 -1
- package/dist/adapters/latex/parse.js +55 -6
- package/dist/adapters/latex/parse.js.map +1 -1
- package/dist/adapters/memory/index.d.ts +3 -0
- package/dist/adapters/memory/index.d.ts.map +1 -1
- package/dist/adapters/memory/index.js +9 -0
- package/dist/adapters/memory/index.js.map +1 -1
- package/dist/adapters/references/index.d.ts.map +1 -1
- package/dist/adapters/references/index.js +27 -24
- package/dist/adapters/references/index.js.map +1 -1
- package/dist/adapters/sources-record/index.d.ts +9 -0
- package/dist/adapters/sources-record/index.d.ts.map +1 -0
- package/dist/adapters/sources-record/index.js +68 -0
- package/dist/adapters/sources-record/index.js.map +1 -0
- package/dist/adapters/tex-output/blg.d.ts +9 -0
- package/dist/adapters/tex-output/blg.d.ts.map +1 -0
- package/dist/adapters/tex-output/blg.js +20 -0
- package/dist/adapters/tex-output/blg.js.map +1 -0
- package/dist/adapters/tex-output/fls.d.ts +8 -0
- package/dist/adapters/tex-output/fls.d.ts.map +1 -0
- package/dist/adapters/tex-output/fls.js +16 -0
- package/dist/adapters/tex-output/fls.js.map +1 -0
- package/dist/adapters/tex-output/index.d.ts +7 -0
- package/dist/adapters/tex-output/index.d.ts.map +1 -0
- package/dist/adapters/tex-output/index.js +7 -0
- package/dist/adapters/tex-output/index.js.map +1 -0
- package/dist/bib-rules.d.ts +47 -0
- package/dist/bib-rules.d.ts.map +1 -0
- package/dist/bib-rules.js +127 -0
- package/dist/bib-rules.js.map +1 -0
- package/dist/build.d.ts +29 -1
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +41 -30
- package/dist/build.js.map +1 -1
- package/dist/claim-provenance.d.ts +2 -2
- package/dist/cli.d.ts +9 -5
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +43 -68
- package/dist/cli.js.map +1 -1
- package/dist/domain/paper-source.d.ts +1 -10
- package/dist/domain/paper-source.d.ts.map +1 -1
- package/dist/domain/paper-source.js +34 -24
- package/dist/domain/paper-source.js.map +1 -1
- package/dist/domain/paper-sources.d.ts +72 -0
- package/dist/domain/paper-sources.d.ts.map +1 -0
- package/dist/domain/paper-sources.js +18 -0
- package/dist/domain/paper-sources.js.map +1 -0
- package/dist/domain/sources-record.d.ts +102 -0
- package/dist/domain/sources-record.d.ts.map +1 -0
- package/dist/domain/sources-record.js +38 -0
- package/dist/domain/sources-record.js.map +1 -0
- package/dist/domain/tex-run.d.ts +25 -0
- package/dist/domain/tex-run.d.ts.map +1 -0
- package/dist/domain/tex-run.js +79 -0
- package/dist/domain/tex-run.js.map +1 -0
- package/dist/eslint-rules/latex-language.d.ts.map +1 -1
- package/dist/eslint-rules/latex-language.js +10 -13
- package/dist/eslint-rules/latex-language.js.map +1 -1
- package/dist/eslint-rules/paper-context.d.ts.map +1 -1
- package/dist/eslint-rules/paper-context.js +6 -5
- package/dist/eslint-rules/paper-context.js.map +1 -1
- package/dist/eslint-rules/paper-typography.d.ts +0 -9
- package/dist/eslint-rules/paper-typography.d.ts.map +1 -1
- package/dist/eslint-rules/paper-typography.js +34 -96
- package/dist/eslint-rules/paper-typography.js.map +1 -1
- package/dist/eslint-rules/papers.d.ts +1 -3
- package/dist/eslint-rules/papers.d.ts.map +1 -1
- package/dist/eslint-rules/papers.js +2 -4
- package/dist/eslint-rules/papers.js.map +1 -1
- package/dist/eslint-rules/tex-build.d.ts.map +1 -1
- package/dist/eslint-rules/tex-build.js +8 -25
- package/dist/eslint-rules/tex-build.js.map +1 -1
- package/dist/init.d.ts +1 -4
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +3 -9
- package/dist/init.js.map +1 -1
- package/dist/latex-log.d.ts +10 -0
- package/dist/latex-log.d.ts.map +1 -1
- package/dist/latex-log.js +10 -0
- package/dist/latex-log.js.map +1 -1
- package/dist/latex-loop.d.ts +2 -0
- package/dist/latex-loop.d.ts.map +1 -1
- package/dist/latex-loop.js.map +1 -1
- package/dist/lib/markdown.d.ts +5 -81
- package/dist/lib/markdown.d.ts.map +1 -1
- package/dist/lib/markdown.js +5 -116
- package/dist/lib/markdown.js.map +1 -1
- package/dist/lib/paper-config.d.ts.map +1 -1
- package/dist/lib/paper-config.js +0 -2
- package/dist/lib/paper-config.js.map +1 -1
- package/dist/lib/skill-eval-fixture.d.ts +6 -4
- package/dist/lib/skill-eval-fixture.d.ts.map +1 -1
- package/dist/lib/skill-eval-fixture.js +25 -18
- package/dist/lib/skill-eval-fixture.js.map +1 -1
- package/dist/new-paper.d.ts +5 -11
- package/dist/new-paper.d.ts.map +1 -1
- package/dist/new-paper.js +12 -23
- package/dist/new-paper.js.map +1 -1
- package/dist/package-dirs.d.ts.map +1 -1
- package/dist/package-dirs.js +3 -2
- package/dist/package-dirs.js.map +1 -1
- package/dist/paper-files.d.ts +4 -4
- package/dist/paper-includes.d.ts +4 -7
- package/dist/paper-includes.d.ts.map +1 -1
- package/dist/paper-includes.js +29 -21
- package/dist/paper-includes.js.map +1 -1
- package/dist/paper-prose.d.ts +17 -0
- package/dist/paper-prose.d.ts.map +1 -0
- package/dist/paper-prose.js +46 -0
- package/dist/paper-prose.js.map +1 -0
- package/dist/paper-record.d.ts +25 -0
- package/dist/paper-record.d.ts.map +1 -0
- package/dist/paper-record.js +39 -0
- package/dist/paper-record.js.map +1 -0
- package/dist/paper-sources.d.ts +66 -0
- package/dist/paper-sources.d.ts.map +1 -0
- package/dist/paper-sources.js +92 -0
- package/dist/paper-sources.js.map +1 -0
- package/dist/ports/bib-reader.d.ts +18 -0
- package/dist/ports/bib-reader.d.ts.map +1 -0
- package/dist/ports/bib-reader.js +2 -0
- package/dist/ports/bib-reader.js.map +1 -0
- package/dist/ports/check-references.d.ts +9 -4
- package/dist/ports/check-references.d.ts.map +1 -1
- package/dist/ports/latex.d.ts +15 -0
- package/dist/ports/latex.d.ts.map +1 -1
- package/dist/ports/sources-codec.d.ts +11 -0
- package/dist/ports/sources-codec.d.ts.map +1 -0
- package/dist/ports/sources-codec.js +2 -0
- package/dist/ports/sources-codec.js.map +1 -0
- package/dist/ports/tex-output.d.ts +17 -0
- package/dist/ports/tex-output.d.ts.map +1 -0
- package/dist/ports/tex-output.js +2 -0
- package/dist/ports/tex-output.js.map +1 -0
- package/dist/recorded-bibliography.d.ts +89 -0
- package/dist/recorded-bibliography.d.ts.map +1 -0
- package/dist/recorded-bibliography.js +136 -0
- package/dist/recorded-bibliography.js.map +1 -0
- package/dist/reference-rules.d.ts +5 -5
- package/dist/reference-rules.d.ts.map +1 -1
- package/dist/reference-rules.js +150 -77
- package/dist/reference-rules.js.map +1 -1
- package/dist/references.d.ts +71 -16
- package/dist/references.d.ts.map +1 -1
- package/dist/references.js +110 -26
- package/dist/references.js.map +1 -1
- package/dist/register-bands.d.ts +3 -3
- package/dist/register-bands.d.ts.map +1 -1
- package/dist/register-bands.js.map +1 -1
- package/dist/register.d.ts +2 -2
- package/dist/sources-record.d.ts +38 -0
- package/dist/sources-record.d.ts.map +1 -0
- package/dist/sources-record.js +123 -0
- package/dist/sources-record.js.map +1 -0
- package/dist/sources-rules.d.ts +44 -0
- package/dist/sources-rules.d.ts.map +1 -0
- package/dist/sources-rules.js +76 -0
- package/dist/sources-rules.js.map +1 -0
- package/dist/structure.d.ts.map +1 -1
- package/dist/structure.js +4 -3
- package/dist/structure.js.map +1 -1
- package/dist/tex-paper.d.ts +10 -15
- package/dist/tex-paper.d.ts.map +1 -1
- package/dist/tex-paper.js +24 -40
- package/dist/tex-paper.js.map +1 -1
- package/dist/tex-venue-rules.d.ts +3 -3
- package/dist/tex-venue-rules.d.ts.map +1 -1
- package/dist/tex-venue-rules.js.map +1 -1
- package/dist/types.d.ts +0 -2
- package/dist/types.d.ts.map +1 -1
- package/docs/configuration.md +18 -12
- package/docs/design/paper-sources.md +197 -0
- package/docs/e2e.md +4 -6
- package/docs/package-shape-options.md +1 -1
- package/docs/prior-art/paper-folder-scaffolding.md +24 -29
- package/docs/references.md +34 -8
- package/docs/rules/bib/reachable-entry.md +64 -0
- package/docs/rules/paper/sources-fresh.md +81 -0
- package/docs/rules/tex/claim-provenance.md +0 -1
- package/docs/rules.md +62 -61
- package/eslint-rules/latex-language.harness.mjs +3 -3
- package/eslint-rules/latex-language.ts +10 -13
- package/eslint-rules/paper-context.ts +6 -5
- package/eslint-rules/paper-typography.test.mjs +29 -157
- package/eslint-rules/paper-typography.ts +35 -104
- package/eslint-rules/papers.harness.mjs +1 -1
- package/eslint-rules/papers.ts +2 -4
- package/eslint-rules/tex-build.harness.mjs +2 -2
- package/eslint-rules/tex-build.ts +8 -25
- package/eslint.config.mjs +22 -1
- package/fixtures/build-e2e/aidc/paper.tex +1 -1
- package/fixtures/build-e2e/anon-ack/paper.tex +1 -1
- package/fixtures/build-e2e/anon-author/paper.tex +1 -1
- package/fixtures/build-e2e/anon-bib/paper.tex +1 -1
- package/fixtures/build-e2e/anon-href/paper.tex +1 -1
- package/fixtures/build-e2e/anon-macro/paper.tex +1 -1
- package/fixtures/build-e2e/anon-pdfauthor/paper.tex +1 -1
- package/fixtures/paper-sources/p1/paper.tex +30 -0
- package/fixtures/paper-sources/p1/refs.bib +6 -0
- package/fixtures/paper-sources/p1/sections/dead.tex +6 -0
- package/fixtures/paper-sources/p1/sections/intro.tex +7 -0
- package/fixtures/paper-sources/p1/sections/parked.tex +6 -0
- package/fixtures/paper-sources/p1/tex-truth.json +37 -0
- package/fixtures/paper-sources/p1/versions/2026-01-01-review.tex +4 -0
- package/fixtures/paper-sources/v1-stale/paper.tex +14 -0
- package/fixtures/paper-sources/v1-stale/refs.bib +6 -0
- package/fixtures/paper-sources/v1-stale/tex-truth.json +32 -0
- package/fixtures/paper-sources/v10-ifthenelse/anon.bib +1 -0
- package/fixtures/paper-sources/v10-ifthenelse/paper.tex +9 -0
- package/fixtures/paper-sources/v10-ifthenelse/real.bib +1 -0
- package/fixtures/paper-sources/v10-ifthenelse/tex-truth.json +28 -0
- package/fixtures/paper-sources/v11-two-blocks/paper.tex +12 -0
- package/fixtures/paper-sources/v11-two-blocks/tex-truth.json +30 -0
- package/fixtures/paper-sources/v13-percent-text/paper.tex +6 -0
- package/fixtures/paper-sources/v13-percent-text/refs.bib +3 -0
- package/fixtures/paper-sources/v13-percent-text/tex-truth.json +30 -0
- package/fixtures/paper-sources/v15-after-end/paper.tex +6 -0
- package/fixtures/paper-sources/v15-after-end/refs.bib +1 -0
- package/fixtures/paper-sources/v15-after-end/tex-truth.json +17 -0
- package/fixtures/paper-sources/v16-included-block/bibblock.tex +3 -0
- package/fixtures/paper-sources/v16-included-block/paper.tex +7 -0
- package/fixtures/paper-sources/v16-included-block/refs.bib +1 -0
- package/fixtures/paper-sources/v16-included-block/tex-truth.json +35 -0
- package/fixtures/paper-sources/v17-include-order/bibsetup.tex +1 -0
- package/fixtures/paper-sources/v17-include-order/first.bib +1 -0
- package/fixtures/paper-sources/v17-include-order/later.bib +1 -0
- package/fixtures/paper-sources/v17-include-order/paper.tex +7 -0
- package/fixtures/paper-sources/v17-include-order/tex-truth.json +40 -0
- package/fixtures/paper-sources/v2-overwrite/paper.tex +14 -0
- package/fixtures/paper-sources/v2-overwrite/refs.bib +6 -0
- package/fixtures/paper-sources/v2-overwrite/tex-truth.json +30 -0
- package/fixtures/paper-sources/v22-parked-thebibliography/paper.tex +7 -0
- package/fixtures/paper-sources/v22-parked-thebibliography/tex-truth.json +17 -0
- package/fixtures/paper-sources/v23-parked-include/old.bib +1 -0
- package/fixtures/paper-sources/v23-parked-include/paper.tex +7 -0
- package/fixtures/paper-sources/v23-parked-include/parked.tex +1 -0
- package/fixtures/paper-sources/v23-parked-include/refs.bib +1 -0
- package/fixtures/paper-sources/v23-parked-include/tex-truth.json +28 -0
- package/fixtures/paper-sources/v24-quoted-fields/paper.tex +6 -0
- package/fixtures/paper-sources/v24-quoted-fields/refs.bib +5 -0
- package/fixtures/paper-sources/v24-quoted-fields/tex-truth.json +32 -0
- package/fixtures/paper-sources/v25-string-differs/paper.tex +10 -0
- package/fixtures/paper-sources/v25-string-differs/refs.bib +2 -0
- package/fixtures/paper-sources/v25-string-differs/tex-truth.json +32 -0
- package/fixtures/paper-sources/v26-comment-in-names/one.bib +1 -0
- package/fixtures/paper-sources/v26-comment-in-names/paper.tex +7 -0
- package/fixtures/paper-sources/v26-comment-in-names/tex-truth.json +32 -0
- package/fixtures/paper-sources/v26-comment-in-names/two.bib +1 -0
- package/fixtures/paper-sources/v27-shared-string/abbreviations.bib +2 -0
- package/fixtures/paper-sources/v27-shared-string/paper.tex +6 -0
- package/fixtures/paper-sources/v27-shared-string/references.bib +6 -0
- package/fixtures/paper-sources/v27-shared-string/tex-truth.json +31 -0
- package/fixtures/paper-sources/v28-shared-string-block/abbreviations.bib +2 -0
- package/fixtures/paper-sources/v28-shared-string-block/paper.tex +14 -0
- package/fixtures/paper-sources/v28-shared-string-block/tex-truth.json +33 -0
- package/fixtures/paper-sources/v29-generated-input/paper.tex +9 -0
- package/fixtures/paper-sources/v29-generated-input/tex-truth.json +24 -0
- package/fixtures/paper-sources/v3-declared/paper.bib +6 -0
- package/fixtures/paper-sources/v3-declared/paper.tex +6 -0
- package/fixtures/paper-sources/v3-declared/tex-truth.json +28 -0
- package/fixtures/paper-sources/v30-name-next-line/paper.tex +14 -0
- package/fixtures/paper-sources/v30-name-next-line/tex-truth.json +30 -0
- package/fixtures/paper-sources/v4-commented/paper.tex +14 -0
- package/fixtures/paper-sources/v4-commented/refs.bib +6 -0
- package/fixtures/paper-sources/v4-commented/tex-truth.json +28 -0
- package/fixtures/paper-sources/v5-percent-entry/paper.tex +20 -0
- package/fixtures/paper-sources/v5-percent-entry/tex-truth.json +37 -0
- package/fixtures/paper-sources/v6-unclosed/paper.tex +6 -0
- package/fixtures/paper-sources/v6-unclosed/refs.bib +5 -0
- package/fixtures/paper-sources/v6-unclosed/tex-truth.json +37 -0
- package/fixtures/paper-sources/v8-jobname/paper.tex +9 -0
- package/fixtures/paper-sources/v8-jobname/tex-truth.json +30 -0
- package/fixtures/paper-sources/v9-two-bibliographies/one.bib +1 -0
- package/fixtures/paper-sources/v9-two-bibliographies/paper.tex +7 -0
- package/fixtures/paper-sources/v9-two-bibliographies/tex-truth.json +35 -0
- package/fixtures/paper-sources/v9-two-bibliographies/two.bib +1 -0
- package/fixtures/paper-typography/clean-paper/paper.tex +1 -1
- package/fixtures/paper-typography/messy-paper/paper.tex +1 -1
- package/hooks/hooks.harness.ts +15 -15
- package/hooks/paper-edit-guard.hook.mjs +5 -8
- package/hooks/paper-edit-guard.test.ts +12 -3
- package/hooks/paper-skills-nudge.hook.mjs +2 -3
- package/hooks/paper-skills-nudge.test.ts +13 -3
- package/hooks/paper-status-gates.hook.mjs +2 -2
- package/hooks/paper-status-gates.test.ts +14 -2
- package/lib/markdown.test.mjs +5 -60
- package/lib/markdown.ts +9 -136
- package/lib/paper-config.ts +0 -2
- package/lib/skill-checks.test.mjs +4 -1
- package/lib/skill-eval-fixture.ts +25 -18
- package/package.json +2 -12
- package/presets/realm.jsonc +1 -1
- package/scripts/check.test.ts +23 -1
- package/scripts/check.ts +7 -3
- package/scripts/coverage-config.test.ts +19 -10
- package/scripts/harness-api.frozen.json +0 -5
- package/scripts/layer-legacy-frozen.test.ts +41 -2
- package/scripts/layer-legacy-frozen.ts +31 -2
- package/skills/cold-read-diff/SKILL.md +3 -3
- package/skills/cold-read-diff/SKILL.md.spec.ts +2 -2
- package/skills/grade-paper-writing/SKILL.md +15 -22
- package/skills/grade-paper-writing/SKILL.md.spec.ts +14 -21
- package/skills/grade-paper-writing/__snapshots__/prose-lint.test.ts.snap +40 -26
- package/skills/grade-paper-writing/prose-lint.mjs +117 -278
- package/skills/grade-paper-writing/prose-lint.test.ts +230 -79
- package/skills/paper-adversarial-review/SKILL.md +2 -2
- package/skills/paper-adversarial-review/SKILL.md.spec.ts +1 -1
- package/skills/paper-pipeline/SKILL.md +9 -12
- package/skills/paper-pipeline/SKILL.md.spec.ts +8 -11
- package/skills/paper-pipeline/description-language.eval.mjs +25 -15
- package/skills/paper-pipeline/framing-vs-vocabulary.eval.mjs +25 -15
- package/skills/paper-pipeline/grade-paper-writing-ablation.eval.mjs +25 -15
- package/skills/paper-pipeline/pipeline-firing.eval.mjs +27 -16
- package/skills/paper-pipeline/pipeline-language.eval.mjs +25 -15
- package/skills/paper-pipeline/references/acceptance-gate.md +16 -20
- package/skills/paper-pipeline/references/artifact-checklist.md +4 -5
- package/skills/paper-pipeline/references/pipeline-status-template.md +1 -1
- package/skills/paper-pipeline/scripts/README.md +0 -4
- package/skills/paper-pipeline/scripts/extract-ref-facts.harness.mjs +91 -105
- package/skills/paper-pipeline/scripts/extract-ref-facts.mjs +85 -241
- package/skills/paper-pipeline/scripts/extract-ref-facts.test.mjs +166 -153
- package/skills/paper-pipeline/scripts/generated-code.harness.mjs +3 -3
- package/skills/paper-status/SKILL.md +2 -2
- package/skills/paper-status/SKILL.md.spec.ts +1 -1
- package/skills/render-paper/SKILL.md +2 -2
- package/skills/render-paper/SKILL.md.spec.ts +1 -1
- package/skills/render-paper/extract-pdf-facts.mjs +2 -2
- package/skills/tighten-paper/SKILL.md +29 -42
- package/skills/tighten-paper/SKILL.md.spec.ts +28 -41
- package/skills/verify-citations/SKILL.md +7 -4
- package/skills/verify-citations/SKILL.md.spec.ts +6 -3
- package/skills/verify-citations/scripts/bib-authors.check.test.mjs +17 -32
- package/skills/verify-citations/scripts/bib-authors.cli.test.ts +138 -43
- package/skills/verify-citations/scripts/bib-authors.d.mts +22 -2
- package/skills/verify-citations/scripts/bib-authors.mjs +54 -193
- package/skills/verify-citations/scripts/bib-authors.test.mjs +1 -44
- package/skills/verify-citations/scripts/verify-cites.cli.test.ts +16 -0
- package/skills/verify-citations/scripts/verify-cites.d.mts +19 -3
- package/skills/verify-citations/scripts/verify-cites.mjs +42 -108
- package/skills/verify-citations/scripts/verify-cites.test.mjs +23 -36
- package/src/adapters/bibtex/index.test.ts +163 -0
- package/src/adapters/bibtex/index.ts +155 -0
- package/src/adapters/latex/filecontents.ts +114 -0
- package/src/adapters/latex/includes.ts +18 -10
- package/src/adapters/latex/index.test.ts +73 -0
- package/src/adapters/latex/index.ts +2 -0
- package/src/adapters/latex/nodes.ts +64 -0
- package/src/adapters/latex/parse.test.ts +38 -0
- package/src/adapters/latex/parse.ts +67 -6
- package/src/adapters/memory/index.ts +17 -0
- package/src/adapters/references/index.test.ts +75 -21
- package/src/adapters/references/index.ts +37 -32
- package/src/adapters/sources-record/index.test.ts +87 -0
- package/src/adapters/sources-record/index.ts +82 -0
- package/src/adapters/tex-output/blg.ts +27 -0
- package/src/adapters/tex-output/fls.ts +24 -0
- package/src/adapters/tex-output/index.test.ts +171 -0
- package/src/adapters/tex-output/index.ts +12 -0
- package/src/bib-rules.test.ts +356 -0
- package/src/bib-rules.ts +228 -0
- package/src/bibliography-at.test.ts +286 -0
- package/src/build.harness.mjs +2 -2
- package/src/build.test.ts +211 -1
- package/src/build.ts +101 -41
- package/src/claim-provenance.test.ts +33 -7
- package/src/claim-provenance.ts +2 -2
- package/src/cli.harness.mjs +46 -56
- package/src/cli.test.ts +44 -48
- package/src/cli.ts +51 -82
- package/src/domain/paper-source.test.ts +58 -20
- package/src/domain/paper-source.ts +38 -42
- package/src/domain/paper-sources.ts +94 -0
- package/src/domain/sources-record.test.ts +71 -0
- package/src/domain/sources-record.ts +136 -0
- package/src/domain/tex-run.test.ts +228 -0
- package/src/domain/tex-run.ts +139 -0
- package/src/folder-venue-rule.test.ts +1 -1
- package/src/heading-case.test.ts +24 -10
- package/src/init.test.ts +6 -7
- package/src/init.ts +3 -22
- package/src/latex-log.ts +20 -0
- package/src/latex-loop.harness.ts +1 -0
- package/src/latex-loop.ts +2 -0
- package/src/lint-fix.test.ts +10 -4
- package/src/linted-set.test.ts +9 -1
- package/src/new-paper.harness.mjs +12 -30
- package/src/new-paper.test.ts +15 -11
- package/src/new-paper.ts +11 -30
- package/src/package-dirs.ts +3 -2
- package/src/paper-files.test.ts +5 -4
- package/src/paper-files.ts +4 -4
- package/src/paper-includes.test.ts +157 -38
- package/src/paper-includes.ts +39 -35
- package/src/paper-prose.test.ts +78 -0
- package/src/paper-prose.ts +67 -0
- package/src/paper-record.test.ts +173 -0
- package/src/paper-record.ts +66 -0
- package/src/paper-settings-commands.test.ts +5 -2
- package/src/paper-sources.ts +151 -0
- package/src/parse-args.test.ts +0 -1
- package/src/ports/bib-reader.ts +27 -0
- package/src/ports/check-references.ts +7 -3
- package/src/ports/latex.ts +19 -0
- package/src/ports/sources-codec.ts +11 -0
- package/src/ports/tex-output.ts +17 -0
- package/src/recorded-bibliography.ts +297 -0
- package/src/reference-rules.ts +217 -104
- package/src/references.test.ts +520 -177
- package/src/references.ts +185 -37
- package/src/register-bands.test.ts +5 -1
- package/src/register-bands.ts +3 -5
- package/src/register.test.ts +6 -1
- package/src/register.ts +2 -2
- package/src/rule-cases.test.ts +68 -12
- package/src/rule-docs.test.ts +0 -1
- package/src/sources-record.test.ts +308 -0
- package/src/sources-record.ts +231 -0
- package/src/sources-rules.test.ts +152 -0
- package/src/sources-rules.ts +117 -0
- package/src/structure.harness.ts +5 -11
- package/src/structure.ts +4 -3
- package/src/tex-paper.test.ts +148 -78
- package/src/tex-paper.ts +31 -61
- package/src/tex-venue-rules.test.ts +36 -8
- package/src/tex-venue-rules.ts +3 -5
- package/src/types.ts +0 -2
- package/dist/eslint-rules/bib-reachable-entry.d.ts +0 -22
- package/dist/eslint-rules/bib-reachable-entry.d.ts.map +0 -1
- package/dist/eslint-rules/bib-reachable-entry.js +0 -75
- package/dist/eslint-rules/bib-reachable-entry.js.map +0 -1
- package/eslint-rules/bib-reachable-entry.ts +0 -76
- package/fixtures/real-markdown-paper/baseline.json +0 -22
- package/fixtures/real-markdown-paper/baseline.ts +0 -70
- package/skills/paper-pipeline/PIPELINE-MAP.md +0 -381
- package/skills/paper-pipeline/pipeline-firing.baseline.json +0 -270
- package/skills/paper-pipeline/references/sweep-2026-08-09-ideal-pipeline.md +0 -585
- package/skills/paper-pipeline/scripts/artifact-coverage.harness.mjs +0 -492
- package/skills/paper-pipeline/scripts/artifact-coverage.mjs +0 -397
- package/skills/paper-pipeline/scripts/artifact-coverage.test.ts +0 -86
- package/skills/paper-pipeline/scripts/check-provenance.mjs +0 -184
- package/skills/paper-pipeline/scripts/population-map.harness.mjs +0 -135
- package/skills/paper-pipeline/scripts/population-map.mjs +0 -188
- package/skills/paper-pipeline/scripts/population-map.test.mjs +0 -154
- package/skills/paper-pipeline/scripts/provenance.harness.mjs +0 -266
- package/skills/paper-pipeline/scripts/round-diff.harness.ts +0 -907
- package/skills/paper-pipeline/scripts/round-diff.mjs +0 -583
- package/skills/paper-pipeline/scripts/round-diff.test.mjs +0 -159
- package/skills/tighten-paper/__snapshots__/structure.test.ts.snap +0 -133
- package/skills/tighten-paper/structure.mjs +0 -364
- package/skills/tighten-paper/structure.test.ts +0 -117
- package/templates/paper/paper.md +0 -4
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# Paper sources — TeX answers "which files, which bibliography"
|
|
2
|
+
|
|
3
|
+
As built in PR #174. Everything that asks which files make up a paper, or which bibliography TeX reads,
|
|
4
|
+
reads the record the last build wrote from TeX's own files; nothing in paperlint reads TeX source to
|
|
5
|
+
decide either, and nothing reads a `.bib` but one adapter. TeX's own answer for each planted paper is
|
|
6
|
+
recorded beside it (§8), and the consumers are tested against that, not against prose.
|
|
7
|
+
|
|
8
|
+
## 1. TeX is the one source of truth
|
|
9
|
+
|
|
10
|
+
Which files make up the paper, and which bibliography it uses, are answered by TeX, from the last
|
|
11
|
+
build — never by reading TeX by hand. There is no static decision: no declaration scan, no
|
|
12
|
+
`filecontents` runs, no include ordering. Lint never runs TeX; it reads what the build recorded.
|
|
13
|
+
|
|
14
|
+
**What the build records — `_build/sources.json`, schema 1.** Written by the compile step, after
|
|
15
|
+
the last pdflatex pass and bibtex, from TeX's own files in the paper directory:
|
|
16
|
+
|
|
17
|
+
| field | from | holds |
|
|
18
|
+
| --------- | ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
19
|
+
| `inputs` | `paper.fls` (`-recorder`) | every file in the paper directory TeX read, in first-read order, each `role: preamble` or `body` — before or after TeX opens `paper.aux` for writing (`\begin{document}`, measured) |
|
|
20
|
+
| `written` | `paper.fls` `OUTPUT` | the `.bib` and `.tex` files TeX wrote (a `filecontents` block) |
|
|
21
|
+
| `bibdata` | `paper.aux` `\bibdata{…}` | the databases bibtex was told to read, after every switch, macro and `\input` |
|
|
22
|
+
| `bibtex` | `paper.blg`, `paper.bbl` | the database files bibtex opened, the keys it typeset, its exit and errors |
|
|
23
|
+
| `sha256` | the files themselves | every `inputs` file and every database bibtex opened (one TeX wrote too), by path and bytes |
|
|
24
|
+
|
|
25
|
+
A file TeX wrote is an input only when it is a `.tex`: a `filecontents` block that writes `body.tex` the
|
|
26
|
+
body `\input`s puts that text in the PDF, so the file is hashed and spliced like any other (measured:
|
|
27
|
+
pass 1 `OUTPUT body.tex` then `INPUT ./body.tex` after `\begin{document}`). Every other file a pass
|
|
28
|
+
wrote — `.aux`, `.out`, `.toc`, a block's `.bib` — is TeX's bookkeeping or a database, not an input.
|
|
29
|
+
The written `.tex` is not handed to ESLint as a file of its own: its words are the block's, and the
|
|
30
|
+
block's body is no prose to the rules, so the text is judged once, where `readPaper` splices it.
|
|
31
|
+
|
|
32
|
+
Every path is relative to the paper directory and spelled as the directory entries spell it: TeX
|
|
33
|
+
logs the name it opened, which on a file system that ignores case is the source's spelling, so the
|
|
34
|
+
record takes each segment's spelling from the disk and one paper gets one record on every platform.
|
|
35
|
+
|
|
36
|
+
A record of its own, not `references.json`: it is written by every build (the references step is
|
|
37
|
+
optional and may record "not checked"), it is read by rules that have nothing to do with references,
|
|
38
|
+
and it goes stale when the SOURCES change, not when one `.bib` does — one staleness key per file.
|
|
39
|
+
`references.json` keeps its verdicts, one per entry of `sources.json`'s databases, and loses its
|
|
40
|
+
`bibtex` field.
|
|
41
|
+
|
|
42
|
+
**Staleness.** A rule recomputes `sha256` over the files the record lists. No record, or a different
|
|
43
|
+
hash (a file edited, added to an `\input`, deleted), is one finding of a new rule,
|
|
44
|
+
`paper/sources-fresh` — "not built" / "the paper changed since the last build — run
|
|
45
|
+
`npx paperlint build`" — and every rule below is silent until a build records the paper again.
|
|
46
|
+
|
|
47
|
+
**The consumers.**
|
|
48
|
+
|
|
49
|
+
| consumer | reads | no record / stale |
|
|
50
|
+
| ---------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------ |
|
|
51
|
+
| `bib/reachable-entry`, `paper/author-list`, `paper/cite-exists` | the entries of the databases bibtex opened, through the `BibReader` | silent (`paper/sources-fresh` speaks) |
|
|
52
|
+
| `paper/refs-checked` | keys bibtex typeset that the reader did not read (`%`, `@comment`) | silent |
|
|
53
|
+
| `extract-ref-facts`, `bib-authors`, `verify-cites` (dir, `.tex`) | `bibliographyAt` → the record's databases | refused: "run `npx paperlint build` first" |
|
|
54
|
+
| `bibliographyAt` with a `.bib` | that file alone, unchanged | — |
|
|
55
|
+
| `paperlint lint`'s files (`paper-includes.ts`), `paper-context` | the `body` `.tex` files of `inputs` TeX did not write | `paper.tex` only; `paper/sources-fresh` says the rest is unlinted |
|
|
56
|
+
| the prose rules' text (`readPaper`) | `paper.tex` with the files of `inputs` spliced where they stand | `paper.tex` alone; `paper/sources-fresh` says the rest is unlinted |
|
|
57
|
+
|
|
58
|
+
An entry in a `.bib` TeX wrote is reported at the `filecontents` block whose body bibtex takes as
|
|
59
|
+
the same database (`sameDatabase`) — a lookup of where the text stands, not a decision of what TeX
|
|
60
|
+
reads; an entry in any other `.bib` at the top of `paper.tex`, `refs.bib:12:1:` first.
|
|
61
|
+
|
|
62
|
+
**What stays syntactic: where an include stands, and nothing else.** The prose rules read
|
|
63
|
+
`paper.tex` with the files of `inputs` spliced in (`readPaper`): a projection of the text for rules to
|
|
64
|
+
read in context, which decides nothing above. Which files are spliced is the record's answer — an
|
|
65
|
+
include of a file `inputs` does not list (behind `\iffalse`, or past `\end{document}`) contributes
|
|
66
|
+
nothing, as it did to TeX, and no include is looked for on disk. Where the macro stands in the text
|
|
67
|
+
is the one thing read from the text, because `.fls` records no position: files are spliced in the
|
|
68
|
+
order the text names them, which is the order TeX read them, each ended the way TeX ends the last
|
|
69
|
+
line of a file it reads (a newline when the file has none — measured: `a\input{f}b` with `f` holding
|
|
70
|
+
`foo` typesets "afoo b"). With no record, or a stale one, the text is `paper.tex` alone. A file the
|
|
71
|
+
record lists that no include macro in the text stands for (an `\input` inside a macro's body, #177)
|
|
72
|
+
is linted as a file of its own and is absent from the whole-paper text.
|
|
73
|
+
|
|
74
|
+
**Ground truth.** `test/e2e/tex/paper-sources.e2e.ts` runs the build's own record step on each
|
|
75
|
+
planted paper and snapshots its `sources.json` as `tex-truth.json`; the unit tests run the
|
|
76
|
+
consumers on the fixture with that record. TeX is the expectation and the input at once.
|
|
77
|
+
|
|
78
|
+
## 4. One bibtex reader
|
|
79
|
+
|
|
80
|
+
The port is `BibReader` (`src/ports/bib-reader.ts`: `read(path, text, body, inherited?)` for a block,
|
|
81
|
+
`readFile(path, text, inherited?)` for a `.bib`). bibtex reads a paper's databases in sequence with one
|
|
82
|
+
table of `@string`s, so a `@string` of `abbrev.bib` expands an entry of `refs.bib` under
|
|
83
|
+
`\bibliography{abbrev,refs}` (measured; in the other order bibtex warns it is undefined).
|
|
84
|
+
`recordedBibliography` reads the databases in the order bibtex opened them, each with the `strings` the
|
|
85
|
+
one before it left in force (`inherited`), and reads a block with the `@string`s its database was read
|
|
86
|
+
with; each database is still parsed as its own text, so each entry keeps its place in its own file.
|
|
87
|
+
|
|
88
|
+
The adapter, `src/adapters/bibtex/`, is the only code that knows `@retorquere/bibtex-parser`. It reads each database twice:
|
|
89
|
+
|
|
90
|
+
- **`entries`** — LaTeX read into text (`{\"u}` → `ü`, `\url{x}` → a link), names split into parts,
|
|
91
|
+
`@string`s expanded where they are used. What the checks judge.
|
|
92
|
+
- **`written`** — `raw: true`, every field verbatim, no outer braces dropped: each field as bibtex
|
|
93
|
+
takes it, `@string`s expanded where used, LaTeX as written. What `sameDatabase` compares, with the
|
|
94
|
+
`@preamble` commands, so `{\"o}` and `ö` stay two values, as they are in the `.bbl`.
|
|
95
|
+
|
|
96
|
+
**The fence is lint, not prose.** `eslint.config.mjs` sets `n/no-restricted-import` on
|
|
97
|
+
`@retorquere/bibtex-parser` (and its subpaths) for every file but `src/adapters/bibtex/**`
|
|
98
|
+
(`test/eslint-bib-parser.test.ts` plants imports in the app, the domain, another adapter and a
|
|
99
|
+
skill's script).
|
|
100
|
+
|
|
101
|
+
## 5. A path a person gave → `bibliographyAt`
|
|
102
|
+
|
|
103
|
+
`extract-ref-facts`, `bib-authors` and `verify-cites` (its `.bib` input) take a path on the command
|
|
104
|
+
line. All three ask `bibliographyAt(path, deps)`: a `.bib` is read alone, as named; a `.tex`, or a
|
|
105
|
+
directory holding `paper.tex`, is the bibliography the last build's bibtex opened for that paper
|
|
106
|
+
(`recordedBibliography`) — for a database TeX wrote, the text of the `filecontents` block (or included
|
|
107
|
+
file) that holds it, so an entry stands where the author edits it. A refusal is a `BibliographyUnread`
|
|
108
|
+
(`missing`, `not-bib-or-tex`, `no-paper`, `not-built`, `no-database`, `outside-paper`), and
|
|
109
|
+
`bibliographyUnreadWhy` is its one sentence; `outside-paper` is a paper whose bibtex also opened a
|
|
110
|
+
database the paper directory does not hold (BIBINPUTS) — refused rather than read in part;
|
|
111
|
+
`not-built` covers a missing, unreadable and stale record alike: run `npx paperlint build` first. Each script keeps its own CLI frame around it.
|
|
112
|
+
|
|
113
|
+
## 6. The references a build checks
|
|
114
|
+
|
|
115
|
+
The build's references step (`src/references.ts`) checks entries, not keys: two databases may each
|
|
116
|
+
define a key with other metadata.
|
|
117
|
+
|
|
118
|
+
- **What is checked is `readBibliography`**: the databases the build's bibtex opened, in the order it
|
|
119
|
+
opened them, each once, read by the bibtex reader — a view over `recordedBibliography`, the one reader
|
|
120
|
+
of the record's databases. Without a fresh record the step checks nothing and its note names the
|
|
121
|
+
reason; a database bibtex opened that is not in the paper directory (bibtex found it on its search
|
|
122
|
+
path, `BIBINPUTS`) is named, not skipped. One removed after the build — a `.bib` TeX wrote, then a
|
|
123
|
+
clean — makes the record stale: every database bibtex opened is hashed.
|
|
124
|
+
- **One verdict per entry, in order.** The `CheckReferences` port returns verdict `i` for entry `i`;
|
|
125
|
+
the adapter runs verify-cites and bib-authors per entry and pairs them by position.
|
|
126
|
+
- **`_build/references.json`, schema 3**: `bib {sources, sha256}`, `status`, `entries`. `sources` are
|
|
127
|
+
the database names as bibtex names them and `sha256` covers their text. Lint lays the verdicts on the
|
|
128
|
+
entries of the same databases and reports each at its entry (`entryReports`); a record that is not one
|
|
129
|
+
verdict per entry, in order, about the bytes the databases hold now, is not about this bibliography
|
|
130
|
+
(`paper/refs-fresh`).
|
|
131
|
+
|
|
132
|
+
## 7. The post-build check — where bibtex reads differently
|
|
133
|
+
|
|
134
|
+
bibtex has no comment syntax and recovers from malformed text as no parser does, so the reader does
|
|
135
|
+
not emulate it. Each difference has an owner:
|
|
136
|
+
|
|
137
|
+
| shape | answered by |
|
|
138
|
+
| -------------------------------------------------------------- | ---------------------------------------------------------------------- |
|
|
139
|
+
| malformed: an entry or brace never closed, `%` inside an entry | the build — bibtex exits 2, and `paperlint build` fails with its lines |
|
|
140
|
+
| an entry behind `%`, or inside `@comment{…}` | `paper/refs-checked`, from the keys bibtex typeset |
|
|
141
|
+
| `@`, `)` or `{"}` inside a quoted field | the reader, which reads it as bibtex does |
|
|
142
|
+
|
|
143
|
+
`paper/refs-checked` names every key bibtex typeset (`paper.bbl`) that no entry of the databases it
|
|
144
|
+
opened has (`unseenKeys`; keys compare case-insensitively, as bibtex's do), and every database bibtex
|
|
145
|
+
opened that is not in the paper directory.
|
|
146
|
+
|
|
147
|
+
## 8. Ground truth — `tex-truth.json`
|
|
148
|
+
|
|
149
|
+
Each planted paper of `fixtures/paper-sources/` carries `tex-truth.json`, written by TeX:
|
|
150
|
+
`test/e2e/tex/paper-sources.e2e.ts` builds it with `pdflatex -recorder` and `bibtex` and snapshots the
|
|
151
|
+
record the build writes. `-u` re-records; a TeX that answers differently fails. The unit tests of the
|
|
152
|
+
consumers lay that file at `_build/sources.json` (`test/recorded-fixture.ts`). The accepted papers of
|
|
153
|
+
`fixtures/accepted-papers/` carry theirs the same way (`test/e2e/tex/accepted-papers-record.e2e.ts`).
|
|
154
|
+
The files are the numbers; this document does not copy them.
|
|
155
|
+
|
|
156
|
+
## 9. Decisions
|
|
157
|
+
|
|
158
|
+
- **The record, not a reading** — which files and databases a paper has is what TeX did on the last
|
|
159
|
+
build; a static reading of the text agrees only on the cases its author thought of.
|
|
160
|
+
- **No record, no verdict** — a rule that needs the record is silent without a current one, and one
|
|
161
|
+
rule (`paper/sources-fresh`) says so once; a stale answer is worse than none.
|
|
162
|
+
- **Prose rules splice only the files the record lists** — an include behind `\iffalse` contributes
|
|
163
|
+
nothing; without a record the text is `paper.tex` alone and `paper/sources-fresh` says the rest went
|
|
164
|
+
unlinted.
|
|
165
|
+
- **A lookup of where a text stands is not a decision of what TeX reads** — `filecontents` blocks are
|
|
166
|
+
found in the text only to put a finding on the line that holds an entry (`sameDatabase`).
|
|
167
|
+
- **One verdict per entry, not per key** — a key does not identify an entry; a verdict that cannot say
|
|
168
|
+
which entry it is about reports at the wrong one.
|
|
169
|
+
- **"Same database" is what bibtex takes** — raw bytes and the final `@string` map are a proxy that
|
|
170
|
+
misses a `@string` redefined after use; the text between entries reaches no `.bbl`.
|
|
171
|
+
- **One `.bib` reader, fenced by lint** — three readers grew before there was one; the parser's name
|
|
172
|
+
may appear in one folder only.
|
|
173
|
+
- **One path → bibliography function** — three scripts each resolved it by hand, each with its own
|
|
174
|
+
refusals.
|
|
175
|
+
- **Recorded TeX truth, not hand-written expectations** — the consumers' tests compare with what TeX
|
|
176
|
+
did, so a wrong belief about TeX cannot be written into both the code and its test.
|
|
177
|
+
- **The post-build check, not emulation** — no parser recovers as bibtex does; bibtex's own output
|
|
178
|
+
is compared instead.
|
|
179
|
+
|
|
180
|
+
## 10. Scope: what this PR does not decide
|
|
181
|
+
|
|
182
|
+
- A finding for a `filecontents` block without `[overwrite]` (#176).
|
|
183
|
+
- A listed body file that no include macro in the text stands for (an `\input` inside a macro's body,
|
|
184
|
+
#177): linted as a file of its own, absent from the whole-paper text.
|
|
185
|
+
- `eslint --cache`: `bib/reachable-entry` depends on files other than the linted one, so a cached
|
|
186
|
+
result can be stale after a `.bib` changes. `paperlint lint` does not cache.
|
|
187
|
+
- Reading past `\end{document}` in `headings.ts`, `layout.ts` and `rendered.ts` (#178).
|
|
188
|
+
- A file a `filecontents` block writes under another extension than `.tex` (a `.pgf` the body
|
|
189
|
+
`\input`s) is not an input: its text reaches the PDF, but the record neither hashes nor splices it.
|
|
190
|
+
- A database TeX wrote is read from the file it left on disk, which the record does not hash: edited
|
|
191
|
+
after a build, that file is not detected as stale.
|
|
192
|
+
- Two copies compared where bibtex and the parser differ in what no check reads: a `@preamble` is
|
|
193
|
+
compared as written, so a `@string` it uses that is redefined between the copies is not seen; and
|
|
194
|
+
`keywords` are compared as the parser splits, dedupes and sorts them — it does so for that field
|
|
195
|
+
name unconditionally, with no option to keep it as written.
|
|
196
|
+
- Q3 (one projection of the live text, replacing `paper-typography`'s `skippedRanges` and
|
|
197
|
+
`texToMdast`'s own parse), the hooks, and an enforcement rule for Q1–Q3: later PRs.
|
package/docs/e2e.md
CHANGED
|
@@ -179,10 +179,6 @@ everything.
|
|
|
179
179
|
- **macOS and Windows.** Locally these run on whatever machine you have. In CI `build-e2e` is a
|
|
180
180
|
matrix over `ubuntu-latest` and `macos-latest`; Windows is not run anywhere, and `paperlint toolchain`
|
|
181
181
|
refuses it.
|
|
182
|
-
- **The rules, on a real document.** `fixtures/real-markdown-paper/` holds a published article and
|
|
183
|
-
a recorded baseline of what the rules say about it. That is a **lint** fixture, driven by a
|
|
184
|
-
harness — it does not go through the installed package. Wiring it into the install corpus is
|
|
185
|
-
open work, not something already done.
|
|
186
182
|
- **The skills as behaviour.** The install run proves a skill arrived and that its paths resolve.
|
|
187
183
|
Whether the agent then does the right thing with it is a different measurement, and it belongs
|
|
188
184
|
to the harness tier of `vigiles`, not here.
|
|
@@ -199,5 +195,7 @@ PDF, its byte counts, the cross-check between them — and copies `fixtures/buil
|
|
|
199
195
|
it so the LaTeX rules see LaTeX rather than a placeholder.
|
|
200
196
|
|
|
201
197
|
⚠️ **Every line of that corpus was written by somebody who already knew which rule would read it.**
|
|
202
|
-
It keeps the stage machinery honest and it cannot tell you anything about false positives.
|
|
203
|
-
|
|
198
|
+
It keeps the stage machinery honest and it cannot tell you anything about false positives. So the
|
|
199
|
+
run then adds one accepted paper from `fixtures/accepted-papers/` (`secure-acsac24`) and holds the
|
|
200
|
+
installed binary to that paper's recorded `baseline.json` — the same recording
|
|
201
|
+
`fixtures/accepted-papers/accepted-papers.test.ts` holds the repository's own `run` to.
|
|
@@ -138,7 +138,7 @@ lockfile in that array was not.
|
|
|
138
138
|
zero: `pipeline-check.mjs`, `extract-ref-facts.mjs` and `bib-authors.mjs`, all reaching
|
|
139
139
|
`markdown-it`. Which retires a number this note carried: the closure is **two** third-party
|
|
140
140
|
packages over **eight** referenced scripts, not one over seven — `extract-ref-facts.mjs` reaches
|
|
141
|
-
`@retorquere/bibtex-parser
|
|
141
|
+
`@retorquere/bibtex-parser`, now through `#src/adapters/bibtex/index`.
|
|
142
142
|
|
|
143
143
|
⏳ **Not measured, recorded as such:** the documented 60-second install timeout; the personal
|
|
144
144
|
`~/.claude/skills` and `--add-dir` channels (2 of 4 locations verified); and a genuine
|
|
@@ -16,10 +16,6 @@ still left to a human copying something by hand?**
|
|
|
16
16
|
> - `--hooks=local` is **deferred, not implemented**; `init` refuses it by name.
|
|
17
17
|
>
|
|
18
18
|
> Where the build differed from this text, it is listed at the end, in § 8.
|
|
19
|
-
>
|
|
20
|
-
> **Later, 2026-09-24:** Markdown papers are deprecated and being removed
|
|
21
|
-
> ([#57](https://github.com/zernie/research-paper-pipeline/issues/57)). Where this record mentions
|
|
22
|
-
> `paper.md` or `--format md`, it describes the tool as it was when written.
|
|
23
19
|
|
|
24
20
|
1. A paper folder needs a `PIPELINE-STATUS.md`, and today nothing makes it — you copy a template.
|
|
25
21
|
Should there be a command, and where should per-paper settings live: in a file in every paper
|
|
@@ -66,11 +62,11 @@ changes, no migration.
|
|
|
66
62
|
(`src/init.ts:448`), offers a CI workflow, reports missing programs, and **prints** the two
|
|
67
63
|
`/plugin` lines (`src/init.ts:257-258`). It never creates the papers directory and never creates
|
|
68
64
|
a paper.
|
|
69
|
-
- **A directory is a paper** if it holds any of `PIPELINE-STATUS.md`, `paper.tex`, `
|
|
70
|
-
|
|
71
|
-
- **`rpp lint` requires `PIPELINE-STATUS.md`** in every such directory, plus
|
|
72
|
-
|
|
73
|
-
|
|
65
|
+
- **A directory is a paper** if it holds any of `PIPELINE-STATUS.md`, `paper.tex`, `venue.json`
|
|
66
|
+
(`src/build.ts`, `src/structure.ts`). Detection is generous.
|
|
67
|
+
- **`rpp lint` requires `PIPELINE-STATUS.md`** in every such directory, plus `paper.tex`
|
|
68
|
+
(`src/structure.ts`). A paper with only `paper.tex` fails the very first `rpp lint` with
|
|
69
|
+
`missing PIPELINE-STATUS.md` — that is the README's own "First run" example.
|
|
74
70
|
|
|
75
71
|
⚠️ **One inconsistency worth knowing.** `paper/stages` says in its header that a missing `stages`
|
|
76
72
|
field is _legitimate_ — "a paper that has shipped nothing owes nothing" (`eslint-rules/paper-stages.mjs:24-27`) —
|
|
@@ -101,7 +97,7 @@ human to copy and tick them.
|
|
|
101
97
|
## 2. What `PIPELINE-STATUS.md` actually holds — the split
|
|
102
98
|
|
|
103
99
|
Read from the template (`skills/paper-pipeline/references/pipeline-status-template.md`), the
|
|
104
|
-
fixtures (`fixtures/paper-stages
|
|
100
|
+
fixtures (`fixtures/paper-stages/*`) and four real files in the
|
|
105
101
|
owner's corpus. Real sizes: 86, 95, 1 057 and 1 301 lines. In the two big ones the machine-read
|
|
106
102
|
part is the first 10–25 lines of front matter; the rest is a dated journal of decisions. (No
|
|
107
103
|
content of those files is reproduced here.)
|
|
@@ -110,7 +106,6 @@ content of those files is reproduced here.)
|
|
|
110
106
|
| ------------------------------------------------------------------------------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
111
107
|
| paper short name / title | **config** | human, once — `rpp new` can prefill from the folder name |
|
|
112
108
|
| venue, deadline, blind model (the `Venue:` header line) | **config** | human; changes when the paper is re-targeted |
|
|
113
|
-
| format (`.tex` vs `.md`) | **derived** | from which source file exists |
|
|
114
109
|
| venue profile, paper kind, pdf path (a separate `venue.json` in one real paper) | **config** | human; already a per-paper file in practice |
|
|
115
110
|
| typography allowance (`typographyDebt`) | **config** | human, but it sits in the root key keyed by path today |
|
|
116
111
|
| `stages[]`: `stage`, `date`, `venue` | **state** | **tool** at the moment of freezing (`rpp freeze`, a later step) |
|
|
@@ -172,9 +167,9 @@ parsing markdown — the fix is to ship the template as its own file and have th
|
|
|
172
167
|
(entry front matter), Cargo (member `Cargo.toml`), Eleventy (directory data). The tools that put
|
|
173
168
|
per-unit settings in the root (ESLint `files`, Vale sections) are _linters of code_, where units
|
|
174
169
|
have no identity of their own — a paper does.
|
|
175
|
-
3. **Front matter of the source itself is not available to rpp**, because
|
|
176
|
-
|
|
177
|
-
|
|
170
|
+
3. **Front matter of the source itself is not available to rpp**, because a paper is LaTeX, which
|
|
171
|
+
has no YAML front matter. Quarto and Astro can use the document's own header only because their
|
|
172
|
+
documents carry one. So rpp needs a per-paper **file**, and it already has one:
|
|
178
173
|
`PIPELINE-STATUS.md`, whose front matter is exactly where Quarto would put these fields.
|
|
179
174
|
4. **Root-level keys that are really per-paper** (`typographyDebt: { "papers/my-paper": … }`,
|
|
180
175
|
`src/cli.ts:104`) are the ESLint-overrides style. They work, but they break silently on a folder
|
|
@@ -209,9 +204,9 @@ written once at freeze time, then checked forever — and today a human types it
|
|
|
209
204
|
|
|
210
205
|
### Commands
|
|
211
206
|
|
|
212
|
-
**`rpp new <name
|
|
207
|
+
**`rpp new <name>`** — creates `<papers>/<name>/` with:
|
|
213
208
|
|
|
214
|
-
- `paper.tex`
|
|
209
|
+
- `paper.tex` (a minimal stub);
|
|
215
210
|
- `PIPELINE-STATUS.md` from a **template file** shipped in the package, with the name filled in and
|
|
216
211
|
**no** `stages` field (a new paper has shipped nothing — `paper-stages.mjs:24`).
|
|
217
212
|
|
|
@@ -228,7 +223,7 @@ Rules for it, each taken from a tool above:
|
|
|
228
223
|
**Later step, NOT part of this change — `rpp freeze <paper> <stage> [--pdf <file>] [--date <iso>]`**,
|
|
229
224
|
the release-please move, recorded so the design is not lost:
|
|
230
225
|
|
|
231
|
-
- copies the built pdf and the source into `versions/<date>-<stage>.pdf|.tex
|
|
226
|
+
- copies the built pdf and the source into `versions/<date>-<stage>.pdf|.tex`;
|
|
232
227
|
- **appends** one record to `stages` with `stage`, `date`, `pdf`, `bytes`, `source`, `sourceBytes`;
|
|
233
228
|
- refuses a stage outside `STAGES` (`paper-stages.mjs:53`) and a date/stage pair already present.
|
|
234
229
|
|
|
@@ -259,15 +254,15 @@ the skills tell agents to update them.
|
|
|
259
254
|
|
|
260
255
|
- **Existing folders with a `PIPELINE-STATUS.md`** (the owner's four): nothing changes. Their
|
|
261
256
|
front matter is already the per-paper carrier; a later `rpp freeze` would append to their lists.
|
|
262
|
-
- **Existing folders without one** (a draft that has only `paper.
|
|
263
|
-
the missing file and touches nothing else.
|
|
257
|
+
- **Existing folders without one** (a draft that has only `paper.tex`): `rpp new <that-name>`
|
|
258
|
+
fills the missing file and touches nothing else.
|
|
264
259
|
- **No `rpp migrate` is needed** for this recommendation. One would be needed only if the carrier
|
|
265
260
|
later moves to `paper.yml`.
|
|
266
261
|
|
|
267
262
|
### The smallest first step
|
|
268
263
|
|
|
269
264
|
Move the template out of the code fence into its own file (say
|
|
270
|
-
`templates/paper/PIPELINE-STATUS.md`, plus `paper.tex`
|
|
265
|
+
`templates/paper/PIPELINE-STATUS.md`, plus a `paper.tex` stub), make
|
|
271
266
|
`pipeline-status-template.md` point at it instead of containing it, and add `rpp new` that copies
|
|
272
267
|
it. Then the README sentence "Nothing generates it and no command refreshes it" becomes "`rpp new`
|
|
273
268
|
creates it". No rule changes, no consumer migration. `rpp freeze` is step two; `init` offering to
|
|
@@ -435,13 +430,13 @@ unset **and** no `--yes`._
|
|
|
435
430
|
|
|
436
431
|
### What `init` asks, and what it does without asking
|
|
437
432
|
|
|
438
|
-
| decision | human at a terminal
|
|
439
|
-
| ----------------- |
|
|
440
|
-
| papers directory | asked only if several candidates (today)
|
|
441
|
-
| **hooks** | "Wire the three paper hooks into `.claude/settings.json` (committed, shared)? **[Y/n]**"
|
|
442
|
-
| CI workflow | "Add a GitHub Actions workflow? **[y/N]**" (today)
|
|
443
|
-
| first paper | only when the papers dir holds no paper: "Create a first paper? name: [skip]"
|
|
444
|
-
| external programs | reported (today)
|
|
433
|
+
| decision | human at a terminal | agent / CI / `--yes` | flag |
|
|
434
|
+
| ----------------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | --------------------------------------- |
|
|
435
|
+
| papers directory | asked only if several candidates (today) | first candidate, said so (today) | `init <dir>` then the key |
|
|
436
|
+
| **hooks** | "Wire the three paper hooks into `.claude/settings.json` (committed, shared)? **[Y/n]**" | **yes** — the guard is what the package is for, the edit is idempotent and shows up in `git diff` | `--no-hooks` (`--hooks=local` deferred) |
|
|
437
|
+
| CI workflow | "Add a GitHub Actions workflow? **[y/N]**" (today) | **no** (today) — it writes into `.github/` and spends Actions minutes, which are metered | `--ci` / `--no-ci` |
|
|
438
|
+
| first paper | only when the papers dir holds no paper: "Create a first paper? name: [skip]" | **no**, unless `--paper <name>` is given | `--paper <name>` |
|
|
439
|
+
| external programs | reported (today) | reported (today) | — |
|
|
445
440
|
|
|
446
441
|
Why the hooks default is "yes" even without asking, while CI is "no": the rule `install.md` already
|
|
447
442
|
adopted from Playwright is _"ask only about what cannot be guessed or is expensive"_. Installing a
|
|
@@ -495,8 +490,8 @@ Recorded so the design and the code do not quietly disagree.
|
|
|
495
490
|
- **`rpp new` lints the new folder itself** (`rpp lint <papers>/<name>`), so the structure check —
|
|
496
491
|
which looks at the subdirectories of the path it is given — does not run there; the folder was
|
|
497
492
|
just made with the required files, so there is nothing for it to find.
|
|
498
|
-
- **Interactive `init` asks "Create a first paper? name: [skip]"
|
|
499
|
-
|
|
493
|
+
- **Interactive `init` asks "Create a first paper? name: [skip]"** only when the papers directory
|
|
494
|
+
holds no paper.
|
|
500
495
|
|
|
501
496
|
## Sources checked
|
|
502
497
|
|
package/docs/references.md
CHANGED
|
@@ -7,7 +7,11 @@ what happens in CI and without a network.
|
|
|
7
7
|
|
|
8
8
|
## What is checked, and where
|
|
9
9
|
|
|
10
|
-
For each entry
|
|
10
|
+
For each entry of the databases the build's bibtex **opened** — the `.bib` files its `\bibliography` /
|
|
11
|
+
`\addbibresource` named after every switch and macro, and the file a `filecontents` block wrote. The
|
|
12
|
+
build records them in `<paper>/_build/sources.json` from TeX's own files (`paper.blg`), so nothing here
|
|
13
|
+
guesses which `.bib` TeX reads by reading the `.tex`. Their text is read by the one bibtex reader
|
|
14
|
+
(`src/ports/bib-reader.ts`):
|
|
11
15
|
|
|
12
16
|
| question | asked of |
|
|
13
17
|
| -------------------------------------------------------------------------------------------------------- | ------------------------------------------- |
|
|
@@ -23,18 +27,40 @@ A work that is simply not found is `unresolvable`, never a failure: plenty of re
|
|
|
23
27
|
indexed. Only a positive disproof fails an entry, for example a DOI that resolves to a different
|
|
24
28
|
paper, or one the DOI authority says does not exist.
|
|
25
29
|
|
|
26
|
-
The verdicts land in `<paper>/_build/references.json
|
|
30
|
+
The verdicts land in `<paper>/_build/references.json`: one verdict per entry of those databases, in the
|
|
31
|
+
order bibtex opened them, and a hash of their text. `paperlint lint` reads that file and reports:
|
|
27
32
|
|
|
28
|
-
| rule | when
|
|
29
|
-
| -------------------- |
|
|
30
|
-
| `paper/cite-exists` | an entry's identifier provably does not resolve to the work cited
|
|
31
|
-
| `paper/author-list` | an entry's authors are the preprint's under a published venue
|
|
32
|
-
| `paper/refs-fresh` | the
|
|
33
|
-
| `paper/refs-checked` | no build has checked the references, or the last one could not
|
|
33
|
+
| rule | when |
|
|
34
|
+
| -------------------- | ----------------------------------------------------------------------------------------- |
|
|
35
|
+
| `paper/cite-exists` | an entry's identifier provably does not resolve to the work cited |
|
|
36
|
+
| `paper/author-list` | an entry's authors are the preprint's under a published venue |
|
|
37
|
+
| `paper/refs-fresh` | the databases changed since the build checked them — build again |
|
|
38
|
+
| `paper/refs-checked` | no build has checked the references, or the last one could not, or the reader missed some |
|
|
39
|
+
|
|
40
|
+
An entry of a `.bib` is reported at the first line of `paper.tex`, with the entry's file, line and
|
|
41
|
+
column at the front of the message (`refs.bib:12:1: …`): ESLint does not lint a `.bib`.
|
|
34
42
|
|
|
35
43
|
The step never fails the build. Without a network the PDF is still built and lint warns that the
|
|
36
44
|
references were not checked.
|
|
37
45
|
|
|
46
|
+
**No record of the build, no answer.** Which databases bibtex opened is in `sources.json`, so a paper
|
|
47
|
+
with no record (never built), or one whose files changed since (`paper/sources-fresh`), has none to
|
|
48
|
+
check: the step records nothing, and the four rules are silent while `paper/sources-fresh` says once
|
|
49
|
+
that the paper must be built.
|
|
50
|
+
|
|
51
|
+
**What bibtex typeset, against what paperlint read.** The record also holds the keys bibtex typeset
|
|
52
|
+
(its `paper.bbl`). bibtex has no comment syntax, so an entry behind `%` or inside `@comment{…}` is one
|
|
53
|
+
it typesets and paperlint's reader does not; `paper/refs-checked` names each such key as not checked.
|
|
54
|
+
(bibtex's keys are case-insensitive: `\cite{SMITH}` typesets `\bibitem{SMITH}` from an entry `smith`,
|
|
55
|
+
which is the same entry.) A malformed `.bib` never gets that far: bibtex fails on it, and `paperlint
|
|
56
|
+
build` fails with bibtex's own lines.
|
|
57
|
+
|
|
58
|
+
A database TeX wrote itself (a `filecontents` block) is read from the file it left beside the paper.
|
|
59
|
+
The build hashes it like any other, so when that file is edited or removed after the build the record
|
|
60
|
+
is stale and `paper/sources-fresh` says so: build again to write it. A database bibtex found outside
|
|
61
|
+
the paper directory, on its search path (`BIBINPUTS`), is not read: the step says which and
|
|
62
|
+
`paper/refs-checked` warns.
|
|
63
|
+
|
|
38
64
|
## `repro/references-cache.json` — commit it
|
|
39
65
|
|
|
40
66
|
Asking five services about every entry is slow. DBLP asks clients to pause between requests, and a
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# bib/reachable-entry
|
|
2
|
+
|
|
3
|
+
**Level:** warn · **Reads:** `paper.tex`, and `_build/sources.json` — the databases the last build's
|
|
4
|
+
bibtex opened, read through the bibtex reader
|
|
5
|
+
|
|
6
|
+
## What it catches
|
|
7
|
+
|
|
8
|
+
A bibliography entry with no `doi`, no `url` and no arXiv id: nothing a reader can follow. The entries
|
|
9
|
+
judged are those of the databases bibtex opened in the last build — TeX's own answer, recorded by
|
|
10
|
+
`paperlint build`, not a reading of the source for `\bibliography`.
|
|
11
|
+
|
|
12
|
+
## Why
|
|
13
|
+
|
|
14
|
+
Reviewer A on HotCRP #20 (2026-08-23): "not every entry has a DOI/link" — one paper had 0 of 47
|
|
15
|
+
entries reachable. Not "no doi": ICLR, NeurIPS and TMLR issue no DOIs at all (measured 2026-08-24),
|
|
16
|
+
so a url or an arXiv id counts.
|
|
17
|
+
|
|
18
|
+
## Examples
|
|
19
|
+
|
|
20
|
+
Reported on the entry's own line when the `.bib` bibtex opened is one TeX wrote from a `filecontents`
|
|
21
|
+
block of `paper.tex`; any other entry — a `.bib` file the author keeps, or a block in an included file —
|
|
22
|
+
at the top of `paper.tex`, with the entry's file, line and column first:
|
|
23
|
+
|
|
24
|
+
```bibtex
|
|
25
|
+
@book{lost2026, title = {A Book}, year = {2026}}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
> refs.bib:12:1: `lost2026` has no doi, url or arXiv id — a reader has nothing to follow. If none
|
|
29
|
+
> exists, keep the exception with `% eslint-disable-next-line bib/reachable-entry -- <why>` above
|
|
30
|
+
> the entry
|
|
31
|
+
|
|
32
|
+
Not reported:
|
|
33
|
+
|
|
34
|
+
```bibtex
|
|
35
|
+
@article{a, doi = {10.1/x}}
|
|
36
|
+
@misc{b, url = {https://example.org}}
|
|
37
|
+
@misc{c, note = {arXiv:2310.05736}}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Options / preset fields
|
|
41
|
+
|
|
42
|
+
None.
|
|
43
|
+
|
|
44
|
+
## What it does not check
|
|
45
|
+
|
|
46
|
+
- Whether the link resolves: that is the references check of `paperlint build`.
|
|
47
|
+
- `@string` and `@preamble`, which are not entries.
|
|
48
|
+
- A paper with no record of a build, or one changed since: the rule is silent, and
|
|
49
|
+
[`paper/sources-fresh`](../paper/sources-fresh.md) says once that it was not built.
|
|
50
|
+
- A database bibtex found outside the paper directory, and an entry bibtex reads that the `.bib` reader
|
|
51
|
+
does not (behind `%`, inside `@comment{…}`): that is the post-build check's.
|
|
52
|
+
- With `eslint --cache`, a change to a `.bib` alone does not re-run the rule: its findings depend on
|
|
53
|
+
files other than `paper.tex`. `paperlint lint` does not cache.
|
|
54
|
+
|
|
55
|
+
## How to fix
|
|
56
|
+
|
|
57
|
+
Add the entry's `doi`, `url` or arXiv id. An entry that has none — a talk, a personal communication
|
|
58
|
+
— keeps its exception where it is written, on the line above the entry, in the block or in the
|
|
59
|
+
`.bib`:
|
|
60
|
+
|
|
61
|
+
```bibtex
|
|
62
|
+
% eslint-disable-next-line bib/reachable-entry -- an invited talk, no recording exists
|
|
63
|
+
@misc{smith2024talk, …}
|
|
64
|
+
```
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# paper/sources-fresh
|
|
2
|
+
|
|
3
|
+
**Level:** warn · **Reads:** `paper.tex` and `_build/sources.json` · **Reported on:** the first line of
|
|
4
|
+
`paper.tex`
|
|
5
|
+
|
|
6
|
+
## What it catches
|
|
7
|
+
|
|
8
|
+
The paper has no usable record of the last build, so paperlint does not know which files TeX reads for
|
|
9
|
+
it. One finding, in one of three forms:
|
|
10
|
+
|
|
11
|
+
- **not built** — there is no `_build/sources.json`;
|
|
12
|
+
- **unreadable** — the file is not JSON, is of another schema number, or does not have the shape of
|
|
13
|
+
schema 1;
|
|
14
|
+
- **stale** — a file the build read has other bytes now, was deleted, or appeared where the build saw
|
|
15
|
+
none. The message names each: `sections/intro.tex edited, refs.bib deleted`.
|
|
16
|
+
|
|
17
|
+
## Why
|
|
18
|
+
|
|
19
|
+
`paperlint build` asks TeX itself which files it read (`pdflatex -recorder`) and which databases bibtex
|
|
20
|
+
opened, and writes the answer, with a SHA-256 of every file, to `_build/sources.json`. Nothing in
|
|
21
|
+
paperlint answers "which files make up this paper" or "which bibliography does it use" by reading the
|
|
22
|
+
TeX source: `\input` behind a macro, a `.bib` written by `filecontents`, a database named by a
|
|
23
|
+
switch are TeX's to decide, and TeX has already decided.
|
|
24
|
+
|
|
25
|
+
The rules that need that answer — the ones over the bibliography, and the prose rules over the files
|
|
26
|
+
`paper.tex` includes — read the record. With no record, or one about an earlier paper, they would
|
|
27
|
+
judge files that are not the paper's, so they stay silent, and this rule speaks once in their place.
|
|
28
|
+
Without it a paper that was never built would lint clean because nothing was looked at.
|
|
29
|
+
|
|
30
|
+
## Examples
|
|
31
|
+
|
|
32
|
+
Failing — a paper that was never built:
|
|
33
|
+
|
|
34
|
+
```text
|
|
35
|
+
papers/my-paper/paper.tex
|
|
36
|
+
1:1 warning the paper has not been built — run `npx paperlint build`, which records the files TeX
|
|
37
|
+
reads. Until it has, the files `paper.tex` includes are not linted, and the rules that
|
|
38
|
+
read the bibliography say nothing
|
|
39
|
+
paper/sources-fresh
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Failing — `sections/intro.tex` was edited after the last build:
|
|
43
|
+
|
|
44
|
+
```text
|
|
45
|
+
papers/my-paper/paper.tex
|
|
46
|
+
1:1 warning the paper changed since the last build (sections/intro.tex edited) — run `npx paperlint
|
|
47
|
+
build`; until then the files `paper.tex` includes are not linted, and the rules that
|
|
48
|
+
read the bibliography say nothing
|
|
49
|
+
paper/sources-fresh
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Passing: a paper whose files are byte for byte what the last build read. Editing a file TeX did not
|
|
53
|
+
read (a figure source the paper does not include, a note beside it) changes nothing.
|
|
54
|
+
|
|
55
|
+
## Options / preset fields
|
|
56
|
+
|
|
57
|
+
No rule options. The level is `warn` for every paper; set it in the paper's `paperlint.json`:
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{ "rules": { "paper/sources-fresh": "error" } }
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
`error` suits a CI job that builds first; `off` suits one that only lints and would rather not hear it.
|
|
64
|
+
|
|
65
|
+
## What it does not check
|
|
66
|
+
|
|
67
|
+
- That the build was clean. A record is written after a build whose pdflatex and bibtex runs ended;
|
|
68
|
+
what they reported is `paper/refs-checked`'s and the build's own.
|
|
69
|
+
- Files TeX never read. A file the paper does not include is not in the record, so its edits are not
|
|
70
|
+
changes, and it is not linted.
|
|
71
|
+
- A file edited in an editor and not saved: the rule compares the bytes on disk with the record.
|
|
72
|
+
- `.bib` files TeX wrote itself (`filecontents`): their bytes are the block's, which is in a file the
|
|
73
|
+
record hashes.
|
|
74
|
+
|
|
75
|
+
## How to fix
|
|
76
|
+
|
|
77
|
+
Build the paper again; the record is rewritten from the files as they are:
|
|
78
|
+
|
|
79
|
+
```sh
|
|
80
|
+
npx paperlint build papers/my-paper
|
|
81
|
+
```
|
|
@@ -68,7 +68,6 @@ any other rule.
|
|
|
68
68
|
3 of the model_) is read as a quantity, and so is the number of a name that opens the sentence
|
|
69
69
|
(_Claude 3 fails …_).
|
|
70
70
|
- Whether a count followed by a plural noun is really the sample (_3 times faster_ passes as one).
|
|
71
|
-
- Markdown papers (`paper.md`): it reads the LaTeX parse tree only.
|
|
72
71
|
|
|
73
72
|
## How to fix
|
|
74
73
|
|