paperlint 4.1.0 → 5.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 (202) hide show
  1. package/CLAUDE.md +26 -2
  2. package/CONTRIBUTING.md +7 -0
  3. package/README.md +15 -4
  4. package/action.harness.mjs +54 -36
  5. package/action.yml +12 -27
  6. package/dist/adapters/latex/document-class.d.ts +6 -5
  7. package/dist/adapters/latex/document-class.d.ts.map +1 -1
  8. package/dist/adapters/latex/document-class.js +18 -10
  9. package/dist/adapters/latex/document-class.js.map +1 -1
  10. package/dist/adapters/latex/includes.d.ts +16 -0
  11. package/dist/adapters/latex/includes.d.ts.map +1 -0
  12. package/dist/adapters/latex/includes.js +48 -0
  13. package/dist/adapters/latex/includes.js.map +1 -0
  14. package/dist/adapters/latex/index.d.ts +9 -5
  15. package/dist/adapters/latex/index.d.ts.map +1 -1
  16. package/dist/adapters/latex/index.js +8 -1
  17. package/dist/adapters/latex/index.js.map +1 -1
  18. package/dist/adapters/latex/nodes.d.ts +5 -1
  19. package/dist/adapters/latex/nodes.d.ts.map +1 -1
  20. package/dist/adapters/latex/nodes.js +6 -2
  21. package/dist/adapters/latex/nodes.js.map +1 -1
  22. package/dist/adapters/latex/parse.d.ts.map +1 -1
  23. package/dist/adapters/latex/parse.js +1 -0
  24. package/dist/adapters/latex/parse.js.map +1 -1
  25. package/dist/adapters/latex/prose.d.ts +8 -0
  26. package/dist/adapters/latex/prose.d.ts.map +1 -0
  27. package/dist/adapters/latex/prose.js +353 -0
  28. package/dist/adapters/latex/prose.js.map +1 -0
  29. package/dist/build.d.ts.map +1 -1
  30. package/dist/build.js +7 -3
  31. package/dist/build.js.map +1 -1
  32. package/dist/claim-provenance.d.ts +34 -0
  33. package/dist/claim-provenance.d.ts.map +1 -0
  34. package/dist/claim-provenance.js +146 -0
  35. package/dist/claim-provenance.js.map +1 -0
  36. package/dist/cli.d.ts +2 -8
  37. package/dist/cli.d.ts.map +1 -1
  38. package/dist/cli.js +81 -31
  39. package/dist/cli.js.map +1 -1
  40. package/dist/domain/paper-source.d.ts +58 -0
  41. package/dist/domain/paper-source.d.ts.map +1 -0
  42. package/dist/domain/paper-source.js +109 -0
  43. package/dist/domain/paper-source.js.map +1 -0
  44. package/dist/domain/sentences.d.ts +26 -0
  45. package/dist/domain/sentences.d.ts.map +1 -0
  46. package/dist/domain/sentences.js +48 -0
  47. package/dist/domain/sentences.js.map +1 -0
  48. package/dist/domain/tex-document.d.ts +39 -4
  49. package/dist/domain/tex-document.d.ts.map +1 -1
  50. package/dist/domain/tex-document.js.map +1 -1
  51. package/dist/eslint-rules/latex-language.d.ts +5 -1
  52. package/dist/eslint-rules/latex-language.d.ts.map +1 -1
  53. package/dist/eslint-rules/latex-language.js +6 -3
  54. package/dist/eslint-rules/latex-language.js.map +1 -1
  55. package/dist/eslint-rules/paper-context.d.ts +20 -0
  56. package/dist/eslint-rules/paper-context.d.ts.map +1 -0
  57. package/dist/eslint-rules/paper-context.js +44 -0
  58. package/dist/eslint-rules/paper-context.js.map +1 -0
  59. package/dist/eslint-rules/paper-typography.d.ts +8 -1
  60. package/dist/eslint-rules/paper-typography.d.ts.map +1 -1
  61. package/dist/eslint-rules/paper-typography.js +85 -19
  62. package/dist/eslint-rules/paper-typography.js.map +1 -1
  63. package/dist/eslint-rules/tex-build.d.ts.map +1 -1
  64. package/dist/eslint-rules/tex-build.js +7 -1
  65. package/dist/eslint-rules/tex-build.js.map +1 -1
  66. package/dist/init.d.ts +4 -19
  67. package/dist/init.d.ts.map +1 -1
  68. package/dist/init.js +24 -29
  69. package/dist/init.js.map +1 -1
  70. package/dist/package-dirs.d.ts +2 -0
  71. package/dist/package-dirs.d.ts.map +1 -1
  72. package/dist/package-dirs.js +8 -0
  73. package/dist/package-dirs.js.map +1 -1
  74. package/dist/paper-files.d.ts +2 -2
  75. package/dist/paper-includes.d.ts +17 -0
  76. package/dist/paper-includes.d.ts.map +1 -0
  77. package/dist/paper-includes.js +51 -0
  78. package/dist/paper-includes.js.map +1 -0
  79. package/dist/ports/latex.d.ts +12 -1
  80. package/dist/ports/latex.d.ts.map +1 -1
  81. package/dist/register.d.ts +40 -0
  82. package/dist/register.d.ts.map +1 -0
  83. package/dist/register.js +134 -0
  84. package/dist/register.js.map +1 -0
  85. package/dist/rules-config.d.ts +1 -0
  86. package/dist/rules-config.d.ts.map +1 -1
  87. package/dist/rules-config.js.map +1 -1
  88. package/dist/structure.js +1 -1
  89. package/dist/structure.js.map +1 -1
  90. package/dist/tex-paper.d.ts +33 -0
  91. package/dist/tex-paper.d.ts.map +1 -0
  92. package/dist/tex-paper.js +103 -0
  93. package/dist/tex-paper.js.map +1 -0
  94. package/dist/tex-venue-rules.d.ts +7 -2
  95. package/dist/tex-venue-rules.d.ts.map +1 -1
  96. package/dist/tex-venue-rules.js +31 -17
  97. package/dist/tex-venue-rules.js.map +1 -1
  98. package/docs/configuration.md +5 -4
  99. package/docs/install.md +8 -8
  100. package/docs/prior-art/paper-folder-scaffolding.md +4 -7
  101. package/docs/rules/tex/claim-provenance.md +83 -0
  102. package/docs/rules/tex/register.md +77 -0
  103. package/docs/rules/tex/required-section.md +3 -1
  104. package/docs/rules/tex/template.md +12 -0
  105. package/docs/rules/tex/venue-leftover.md +4 -2
  106. package/docs/rules.md +17 -10
  107. package/eslint-rules/latex-language.ts +10 -4
  108. package/eslint-rules/paper-context.test.ts +47 -0
  109. package/eslint-rules/paper-context.ts +57 -0
  110. package/eslint-rules/paper-typography.test.mjs +48 -1
  111. package/eslint-rules/paper-typography.ts +139 -24
  112. package/eslint-rules/tex-build.ts +8 -1
  113. package/eslint.config.mjs +1 -0
  114. package/fixtures/real-markdown-paper/baseline.json +1 -2
  115. package/fixtures/real-markdown-paper/baseline.ts +8 -7
  116. package/package.json +2 -1
  117. package/scripts/check.ts +2 -2
  118. package/scripts/eslint-report-guard.mjs +5 -2
  119. package/scripts/harness-api.frozen.json +0 -1
  120. package/skills/cold-read-diff/SKILL.md +31 -10
  121. package/skills/cold-read-diff/SKILL.md.spec.ts +30 -9
  122. package/skills/draft-paper/SKILL.md +2 -2
  123. package/skills/draft-paper/SKILL.md.spec.ts +1 -1
  124. package/skills/grade-paper-writing/SKILL.md +109 -44
  125. package/skills/grade-paper-writing/SKILL.md.spec.ts +108 -43
  126. package/skills/harden-paper/SKILL.md +35 -36
  127. package/skills/harden-paper/SKILL.md.spec.ts +34 -35
  128. package/skills/paper-adversarial-review/SKILL.md +2 -2
  129. package/skills/paper-adversarial-review/SKILL.md.spec.ts +1 -1
  130. package/skills/paper-pipeline/SKILL.md +3 -3
  131. package/skills/paper-pipeline/SKILL.md.spec.ts +2 -2
  132. package/skills/paper-pipeline/grade-paper-writing-ablation.eval.mjs +6 -6
  133. package/skills/paper-pipeline/references/pipeline-status-template.md +2 -16
  134. package/skills/paper-pipeline/references/writing-craft.md +53 -18
  135. package/skills/pc-panel-review/SKILL.md +36 -11
  136. package/skills/pc-panel-review/SKILL.md.spec.ts +35 -10
  137. package/src/adapters/latex/document-class.ts +20 -12
  138. package/src/adapters/latex/includes.ts +74 -0
  139. package/src/adapters/latex/index.test.ts +183 -1
  140. package/src/adapters/latex/index.ts +14 -4
  141. package/src/adapters/latex/nodes.ts +11 -2
  142. package/src/adapters/latex/parse.ts +1 -0
  143. package/src/adapters/latex/prose.ts +484 -0
  144. package/src/build.harness.mjs +4 -2
  145. package/src/build.test.ts +18 -1
  146. package/src/build.ts +7 -3
  147. package/src/claim-provenance.test.ts +352 -0
  148. package/src/claim-provenance.ts +217 -0
  149. package/src/cli.harness.mjs +22 -54
  150. package/src/cli.test.ts +2 -18
  151. package/src/cli.ts +92 -36
  152. package/src/domain/paper-source.test.ts +156 -0
  153. package/src/domain/paper-source.ts +233 -0
  154. package/src/domain/sentences.ts +67 -0
  155. package/src/domain/tex-document.ts +36 -3
  156. package/src/init.test.ts +33 -13
  157. package/src/init.ts +25 -48
  158. package/src/linted-set.test.ts +11 -1
  159. package/src/new-paper.harness.mjs +1 -5
  160. package/src/package-dirs.ts +9 -0
  161. package/src/paper-files.ts +2 -2
  162. package/src/paper-includes.test.ts +161 -0
  163. package/src/paper-includes.ts +77 -0
  164. package/src/ports/latex.ts +13 -0
  165. package/src/register.test.ts +165 -0
  166. package/src/register.ts +177 -0
  167. package/src/rule-cases.test.ts +43 -23
  168. package/src/rule-docs.test.ts +0 -1
  169. package/src/rules-config.ts +1 -0
  170. package/src/structure.harness.ts +1 -3
  171. package/src/structure.ts +1 -1
  172. package/src/tex-paper.test.ts +148 -0
  173. package/src/tex-paper.ts +161 -0
  174. package/src/tex-venue-rules.test.ts +87 -5
  175. package/src/tex-venue-rules.ts +62 -30
  176. package/templates/paper/PIPELINE-STATUS.md +0 -4
  177. package/dist/action-ref.d.ts +0 -12
  178. package/dist/action-ref.d.ts.map +0 -1
  179. package/dist/action-ref.js +0 -16
  180. package/dist/action-ref.js.map +0 -1
  181. package/dist/eslint-rules/paper-research-question.d.ts +0 -31
  182. package/dist/eslint-rules/paper-research-question.d.ts.map +0 -1
  183. package/dist/eslint-rules/paper-research-question.js +0 -188
  184. package/dist/eslint-rules/paper-research-question.js.map +0 -1
  185. package/eslint-rules/paper-research-question.harness.mjs +0 -212
  186. package/eslint-rules/paper-research-question.ts +0 -199
  187. package/fixtures/paper-research-question/comment-only/PIPELINE-STATUS.md +0 -9
  188. package/fixtures/paper-research-question/comment-only/paper.tex +0 -7
  189. package/fixtures/paper-research-question/declared-not-in-paper/PIPELINE-STATUS.md +0 -10
  190. package/fixtures/paper-research-question/declared-not-in-paper/paper.tex +0 -6
  191. package/fixtures/paper-research-question/draft/PIPELINE-STATUS.md +0 -6
  192. package/fixtures/paper-research-question/draft/paper.tex +0 -2
  193. package/fixtures/paper-research-question/markdown-no-rq/PIPELINE-STATUS.md +0 -9
  194. package/fixtures/paper-research-question/markdown-no-rq/paper.md +0 -4
  195. package/fixtures/paper-research-question/shipped-no-rq/PIPELINE-STATUS.md +0 -12
  196. package/fixtures/paper-research-question/shipped-no-rq/paper.tex +0 -3
  197. package/fixtures/paper-research-question/shipped-with-rq/PIPELINE-STATUS.md +0 -10
  198. package/fixtures/paper-research-question/shipped-with-rq/paper.tex +0 -2
  199. package/skills/harden-paper/fixtures/uncited-assertions-sample.md +0 -43
  200. package/skills/harden-paper/fixtures/uncited-assertions-sample.tex +0 -77
  201. package/src/action-ref.test.ts +0 -26
  202. package/src/action-ref.ts +0 -15
@@ -24,6 +24,7 @@ import { basename, dirname, join } from "node:path";
24
24
  import { CONFIG_FILE } from "#lib/paper-config";
25
25
  import { collapse, documentClassLine, missingOptions, runText, spanIn, } from "./domain/tex-document.js";
26
26
  import { paperPreset, resolvePreset, SHIPPED_PREFIX, shippedPresets, } from "./presets.js";
27
+ import { readPaper, reportInPaper } from "./tex-paper.js";
27
28
  // ── the judges: what the source says + a resolved preset → findings. Pure. ─────────
28
29
  /** A place as a finding points at it: its span, or null — the top of the file — when unplaced. */
29
30
  const spanOf = (p) => (p.kind === "at" ? p.span : null);
@@ -38,6 +39,22 @@ function judgeClass(line, want, data) {
38
39
  at,
39
40
  }));
40
41
  }
42
+ /** A candidate as the message names it: its line, or an empty `\documentclass{}`. */
43
+ const candidateLine = (c) => c.kind === "class" ? documentClassLine(c) : "\\documentclass{}";
44
+ /**
45
+ * Several class lines behind a TeX switch: satisfied when any candidate is the template's class
46
+ * with its options; otherwise one finding, at the first candidate, naming every one.
47
+ */
48
+ function judgeCandidates(candidates, want, data) {
49
+ const matches = candidates.some((c) => c.kind === "class" && judgeClass(c, want, data).length === 0);
50
+ if (matches)
51
+ return [];
52
+ const named = candidates.map((c) => `\`${candidateLine(c)}\``).join(", ");
53
+ const found = { ...data, count: candidates.length, candidates: named };
54
+ return [
55
+ { messageId: "noCandidate", data: found, at: spanOf(candidates[0].place) },
56
+ ];
57
+ }
41
58
  /** The paper's class line against a template that was read: present, naming a class, that class. */
42
59
  function judgeClassLine(line, want, data) {
43
60
  switch (line.kind) {
@@ -47,6 +64,8 @@ function judgeClassLine(line, want, data) {
47
64
  return [{ messageId: "emptyClass", data, at: spanOf(line.place) }];
48
65
  case "class":
49
66
  return judgeClass(line, want, data);
67
+ case "ambiguous":
68
+ return judgeCandidates(line.candidates, want, data);
50
69
  }
51
70
  }
52
71
  /**
@@ -148,6 +167,7 @@ const RULES = {
148
167
  badTemplate: '{{file}}: the preset\'s "template" {{text}} is neither a \\documentclass line nor a class name, so the class cannot be checked',
149
168
  wrongClass: "the class is `{{got}}`, and {{venue}} requires `{{template}}` — the page size, fonts and layout the venue checks come from the class",
150
169
  missingOption: "the class option `{{option}}` is missing: {{venue}} requires `{{template}}`",
170
+ noCandidate: "none of the {{count}} \\documentclass lines is `{{template}}`, which {{venue}} requires: {{candidates}}. The source picks one behind a TeX switch, which is not evaluated; make one of them the venue's",
151
171
  },
152
172
  },
153
173
  },
@@ -201,8 +221,9 @@ export function otherVenues(preset, fromFile, deps) {
201
221
  });
202
222
  }
203
223
  /**
204
- * What a judge reads for the paper whose `paper.tex` is `filename`, or null when the paper has no
205
- * resolved preset (`pdf/measured` and `pdf/profile` already say so).
224
+ * What a judge reads for the paper whose `paper.tex` is `filename` — the paper with its includes
225
+ * spliced (`readPaper`) — or null when the paper has no resolved preset (`pdf/measured` and
226
+ * `pdf/profile` already say so).
206
227
  */
207
228
  function readingOf(filename, src, deps) {
208
229
  const dir = dirname(filename);
@@ -211,18 +232,11 @@ function readingOf(filename, src, deps) {
211
232
  return null;
212
233
  const preset = p.preset;
213
234
  const others = () => otherVenues(preset, join(dir, CONFIG_FILE), deps);
214
- return { src, latex: deps.latex, preset, others };
215
- }
216
- /** Each finding reported at its span, or at the top of the file when it has none. */
217
- function reportAll(context, findings) {
218
- const at = (i) => context.sourceCode.getLocFromIndex(i);
219
- findings.forEach((f) => {
220
- context.report({
221
- loc: { start: at(f.at?.start ?? 0), end: at(f.at?.end ?? 0) },
222
- messageId: f.messageId,
223
- data: f.data,
224
- });
225
- });
235
+ const paper = readPaper(filename, src, deps);
236
+ return {
237
+ reading: { src: paper.text, latex: deps.latex, preset, others },
238
+ paper,
239
+ };
226
240
  }
227
241
  function rule(name, deps) {
228
242
  const { judge, meta } = RULES[name];
@@ -235,9 +249,9 @@ function rule(name, deps) {
235
249
  return {
236
250
  root() {
237
251
  const sc = context.sourceCode;
238
- const reading = readingOf(context.filename, sc.raw ?? sc.text, deps);
239
- if (reading !== null)
240
- reportAll(context, judge(reading));
252
+ const r = readingOf(context.filename, sc.raw ?? sc.text, deps);
253
+ if (r !== null)
254
+ reportInPaper(context, meta.messages, r.paper, judge(r.reading));
241
255
  },
242
256
  };
243
257
  },
@@ -1 +1 @@
1
- {"version":3,"file":"tex-venue-rules.js","sourceRoot":"","sources":["../src/tex-venue-rules.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tex-venue-rules.js","sourceRoot":"","sources":["../src/tex-venue-rules.ts"],"names":[],"mappings":"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"}
@@ -230,15 +230,16 @@ write. It prints its plan first, one line per step, then runs it:
230
230
 
231
231
  ```
232
232
  papers/my-paper
233
- inputs: TEXINPUTS += <paperlint>/presets/tex
233
+ inputs: TEXINPUTS += the paper's directory, then <paperlint>/presets/tex
234
234
  compile: paper.tex (\documentclass[sigconf,screen]{acmart}, venue agenticdev)
235
235
  measure: pdf.js → _build/paper.facts.json (facts for the lint rules; nothing is judged here)
236
236
  ✓ paper.pdf — 4 pdflatex passes, 1 bibtex run; facts: _build/paper.facts.json, last page 621.5 / 264.8 pt
237
237
  ```
238
238
 
239
- - **inputs** — paperlint's own venue files (`paper-guards.tex`, `<venue>.tex`) are put on `TEXINPUTS`,
240
- so `\input{paper-guards}` in a preamble resolves with no setup. The system tree still resolves
241
- after them.
239
+ - **inputs** — `TEXINPUTS` is the paper's directory, then paperlint's own venue files
240
+ (`paper-guards.tex`, `<venue>.tex`), so `\input{paper-guards}` in a preamble resolves with no
241
+ setup and a file of the paper's own wins over paperlint's of the same name. The system tree still
242
+ resolves after them. `paperlint lint` looks for an included file in the same places.
242
243
  - **compile** — `pdflatex -interaction=nonstopmode -halt-on-error -file-line-error`, then `bibtex`
243
244
  when the `.aux` names a bibliography, then pdflatex again until the `.aux`, `.toc`, `.out` and
244
245
  `.bbl` stop changing and the log stops asking for a rerun. bibtex runs again only when the cited
package/docs/install.md CHANGED
@@ -33,7 +33,7 @@ In order:
33
33
  on the defaults gets no config file at all.
34
34
  3. **Links each shipped skill** into `.claude/skills/<name>`, where Claude Code looks for skills.
35
35
  4. **Writes the hook commands** into `.claude/settings.json`, beside your own entries.
36
- 5. **Offers a GitHub Actions workflow**, pinned to the release tag of the version you installed.
36
+ 5. **Offers a GitHub Actions workflow** that runs `npm ci`, then the action from `node_modules`.
37
37
  6. **Offers a first paper** (`paperlint new`) if the papers directory has none.
38
38
  7. **Offers TeX Live** for `paperlint build` (`paperlint toolchain`, ~270 MB, ~3 min, once), with
39
39
  the size in the question and NO as the default. Without a terminal it asks nothing and lists the
@@ -47,13 +47,13 @@ question (Ctrl+D) also takes the default.
47
47
 
48
48
  ## What `paperlint init` writes
49
49
 
50
- | what | where | when |
51
- | ------------------------------------------------------------------ | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
52
- | `{ "papersDir": … }` naming your papers directory | `paperlint.json` | only when it is not the default `papers` |
53
- | the three hook commands, merged in beside your own entries | `.claude/settings.json` | by default. A human at a terminal is asked [Y/n]; an agent, CI or `--yes` gets YES; `--no-hooks` skips. Hand-wired under another spelling: nothing written, so nothing runs twice |
54
- | a GitHub Actions workflow, pinned to `@v<installed version>` | `.github/workflows/` | only if you say yes; it asks once, and only when a human is at a terminal (stdin and stdout, no `CI`, no `--yes`) |
55
- | a first paper, via `paperlint new` | `<papers>/<name>/` | only when the papers directory holds none: asked of a human at a terminal, otherwise only with `--paper <name>` |
56
- | one relative symlink per shipped skill, into the installed package | `.claude/skills/<name>` | always — except where that name is already taken (a directory, a file, a link elsewhere): that entry is left as it is and named in the report |
50
+ | what | where | when |
51
+ | -------------------------------------------------------------------- | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
52
+ | `{ "papersDir": … }` naming your papers directory | `paperlint.json` | only when it is not the default `papers` |
53
+ | the three hook commands, merged in beside your own entries | `.claude/settings.json` | by default. A human at a terminal is asked [Y/n]; an agent, CI or `--yes` gets YES; `--no-hooks` skips. Hand-wired under another spelling: nothing written, so nothing runs twice |
54
+ | a GitHub Actions workflow: `npm ci`, then `./node_modules/paperlint` | `.github/workflows/` | only if you say yes; it asks once, and only when a human is at a terminal (stdin and stdout, no `CI`, no `--yes`) |
55
+ | a first paper, via `paperlint new` | `<papers>/<name>/` | only when the papers directory holds none: asked of a human at a terminal, otherwise only with `--paper <name>` |
56
+ | one relative symlink per shipped skill, into the installed package | `.claude/skills/<name>` | always — except where that name is already taken (a directory, a file, a link elsewhere): that entry is left as it is and named in the report |
57
57
 
58
58
  It installs no software you did not say yes to, and touches nothing else. Commit `.claude/settings.json` so every clone
59
59
  gets the hooks; the hook commands run files inside `node_modules`, so a fresh clone needs
@@ -86,7 +86,6 @@ listed so nobody thinks the two are consistent.
86
86
  | `paper/stages` (error) | `eslint-rules/paper-stages.mjs:91`, glob `src/cli.ts:126` | front matter `stages[]`: `stage`, `date`, `pdf`, `bytes`; and lists `versions/*.pdf` |
87
87
  | `paper/source` (error) | `eslint-rules/paper-stages.mjs:377`, `:415`, `:442` | `stages[].source`, `sourceBytes`, `sourceLost` |
88
88
  | `paper/author-list` (warn) | `eslint-rules/paper-stages.mjs:296`, marker `:325` | `stages[]` + searches the scorecard **table cells** for the marker `bib-authors` |
89
- | `paper/research-question` (warn) | `eslint-rules/paper-research-question.mjs:142` | reads the status file from disk while linting `paper.tex`/`paper.md`: `stages`, `researchQuestion` |
90
89
  | `paper/typography` (warn) | `src/cli.ts:118` | **not** the status file — its per-paper allowance lives in the ROOT key `typographyDebt`, keyed by paper path |
91
90
  | `pipeline-check.mjs` (skill script) | `skills/paper-pipeline/scripts/pipeline-check.mjs:231-321` | the `Venue:` / `Deadline:` header line, the verdict line, the five section tables |
92
91
  | `paper-status-gates` hook | `hooks/paper-status-gates.hook.mjs` | surfaces the verdict and unrun gates after an edit |
@@ -111,7 +110,6 @@ content of those files is reproduced here.)
111
110
  | ------------------------------------------------------------------------------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
112
111
  | paper short name / title | **config** | human, once — `rpp new` can prefill from the folder name |
113
112
  | venue, deadline, blind model (the `Venue:` header line) | **config** | human; changes when the paper is re-targeted |
114
- | `researchQuestion` | **config** | human, once |
115
113
  | format (`.tex` vs `.md`) | **derived** | from which source file exists |
116
114
  | venue profile, paper kind, pdf path (a separate `venue.json` in one real paper) | **config** | human; already a per-paper file in practice |
117
115
  | typography allowance (`typographyDebt`) | **config** | human, but it sits in the root key keyed by path today |
@@ -202,7 +200,7 @@ written once at freeze time, then checked forever — and today a human types it
202
200
  - **Root (`package.json` key): the papers directory only.** Unchanged. It stays a scope, like
203
201
  Quarto's project dir or Astro's collection glob. No list of papers.
204
202
  - **Per paper: the paper folder's `PIPELINE-STATUS.md` front matter** holds that paper's config
205
- (`researchQuestion`, and the venue/deadline fields that today live in a prose header line) and
203
+ (the venue/deadline fields that today live in a prose header line) and
206
204
  its stage records. Unchanged carrier, so every existing paper keeps working.
207
205
  - **Not recommended now: a separate `paper.yml`.** It would split config from the journal cleanly
208
206
  (the 1 300-line files are 98% journal), but it moves every rule's input and every consumer's
@@ -214,9 +212,8 @@ written once at freeze time, then checked forever — and today a human types it
214
212
  **`rpp new <name> [--format tex|md]`** — creates `<papers>/<name>/` with:
215
213
 
216
214
  - `paper.tex` or `paper.md` (a minimal stub; `--format` defaults to `tex` — ask when interactive);
217
- - `PIPELINE-STATUS.md` from a **template file** shipped in the package, with the name filled in,
218
- `researchQuestion` present but empty and commented, and **no** `stages` field (a new paper has
219
- shipped nothing — `paper-stages.mjs:24`).
215
+ - `PIPELINE-STATUS.md` from a **template file** shipped in the package, with the name filled in and
216
+ **no** `stages` field (a new paper has shipped nothing — `paper-stages.mjs:24`).
220
217
 
221
218
  Rules for it, each taken from a tool above:
222
219
 
@@ -251,7 +248,7 @@ the skills tell agents to update them.
251
248
  | ------------------------------------------ | ------------------------- | ----------------------------------------------------------------------- |
252
249
  | the folder and source stub | human | `rpp new` |
253
250
  | `PIPELINE-STATUS.md` skeleton | human copies a code fence | `rpp new` |
254
- | `researchQuestion`, venue, deadline | human | human (unchanged) |
251
+ | venue, deadline | human | human (unchanged) |
255
252
  | `stages` records, bytes, the frozen copies | human types byte counts | still human; `rpp freeze` is the later step that takes it over |
256
253
  | `sourceLost` exceptions | human | human (unchanged) |
257
254
  | `State:`, `Updated:`, `Requires` cells | human | still human; **derivable** — candidates to drop from the template later |
@@ -0,0 +1,83 @@
1
+ # tex/claim-provenance
2
+
3
+ **Level:** warn · **Reads:** `paper.tex`
4
+
5
+ ## What it catches
6
+
7
+ A sentence of the body that states a number and does not say whose the number is. The sentence is
8
+ reported once, however many numbers it holds. Any one of these owners silences it:
9
+
10
+ | owner | in the sentence |
11
+ | ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
12
+ | a work outside the paper | a `\cite` (any of natbib's or biblatex's forms), a `\url`, an `\href`, or a footnote that cites or links |
13
+ | the authors | _we_, _our_, _ours_, _us_ (the capitalised country _US_ is not the authors) |
14
+ | a place in the paper | `\ref`, `\cref`, `\autoref` and their kin, or the words _Section 4_, _Table 2_, _Fig. 3_, _Appendix B_, _§4_ |
15
+ | a claimant named as one | _advertises_, _claims_: _"the skill advertises a 65% reduction"_, _"(claim 63%)"_ |
16
+ | the sample the number counts | _n = 134_ (in prose or in math), or a count followed by what it counts: _48 runs_, _48 independent runs_, _of 1,836 repositories_ |
17
+
18
+ It reads the body of the whole paper — `paper.tex` with the files it `\input`s, `\include`s or
19
+ `\subfile`s spliced in — from the start of the document, the abstract included, to `\appendix` or the
20
+ bibliography. A sentence in an included file is reported at that include, with the file and line at
21
+ the front of the message. Footnotes are read as sentences of their own. A citation or a footnote set right after
22
+ the full stop belongs to the sentence the full stop ends.
23
+
24
+ A number is digits a reader sees — `42\%`, `0.37`, `1,836`, `3x`, `3×`. Not a number: a year on its
25
+ own (1900–2099); a number right after a capitalised word inside the sentence (_Claude 3_, _Python
26
+ 3.12_, _Node 22_), which is a name; the level of an interval (the 95 of _95% CI_); digits glued to a letter, a hyphen or a point (`GPT-4`, `COVID-19`, `v1.2`, `10k`,
27
+ `0x1F`); anything inside math, a table, a figure, a caption, a heading (a run-in one too: `\textbf{Threats.}` opening a paragraph), code, a comment, a macro
28
+ definition, or the title block.
29
+
30
+ ## Why
31
+
32
+ A reviewer who cannot tell a property of the world from a cited finding from the authors' own
33
+ measurement says so, and scores the paper's soundness on it. Academic prose carries the owner by
34
+ default — _we found_, _[12] report_, _(Table 2)_ — and a sentence rewritten for punch loses it first:
35
+ _"Under test the rules held in 97% of cases"_ has no subject, and a reader takes it
36
+ for a result from the literature. This rule is the floor under the rules that shorten sentences.
37
+
38
+ ## Examples
39
+
40
+ ```latex
41
+ Agents ignore 42\% of the rules they are given. % warns
42
+ Under test the rules held in 97\% of cases. % warns: no one ran the test
43
+ We find that agents ignore 42\% of the rules. % silent: the authors
44
+ Agents ignore 42\% of the rules~\cite{smith2025}. % silent: a citation
45
+ Agents ignore 42\% of the rules (Table~\ref{t:rates}). % silent: a place in the paper
46
+ Of 1,836 repositories, 12\% ship hooks. % silent: the sample
47
+ In 2024 the first agents shipped with GPT-4. % silent: a year and a name
48
+ ```
49
+
50
+ The first line reports:
51
+
52
+ > «42%» — whose number is this? A reader cannot tell a cited finding from your own measurement from
53
+ > a general fact. Say it in the sentence: cite the work (\cite), claim it (we measured, our census),
54
+ > point to where it is shown (\ref, Section N, Table N), or name the sample it counts (n = 134, 48
55
+ > runs)
56
+
57
+ ## Options / preset fields
58
+
59
+ None. It is on, as a warning, for every `paper.tex`; turn it off or up in the `rules` setting like
60
+ any other rule.
61
+
62
+ ## What it does not check
63
+
64
+ - Whether the owner is the right one: a citation that does not report the number, or a _we_ in a
65
+ sentence about someone else's work, silences the sentence all the same.
66
+ - What a custom macro prints: `\rate{}` defined as `42\%` is not a number here.
67
+ - Which numbers are names, beyond the two shapes it knows: a number after a lowercase word (_version
68
+ 3 of the model_) is read as a quantity, and so is the number of a name that opens the sentence
69
+ (_Claude 3 fails …_).
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
+
73
+ ## How to fix
74
+
75
+ Say whose the number is, in the sentence — usually by putting back the subject a punchy rewrite took
76
+ out: _"We ran the rules in 48 sessions and saw no violation"_, not _"No violation in 48 runs."_ A
77
+ number that is common knowledge, or quoted on purpose, keeps its sentence with ESLint's directive and
78
+ the reason:
79
+
80
+ ```latex
81
+ % eslint-disable-next-line tex/claim-provenance -- the venue's own page limit, quoted
82
+ The limit is 8.
83
+ ```
@@ -0,0 +1,77 @@
1
+ # tex/register
2
+
3
+ **Level:** warn · **Reads:** `paper.tex` and the files it includes
4
+
5
+ ## What it catches
6
+
7
+ A body in which more than 0.8 sentences per 1000 words open with _And_, _So_, _But_, _Nor_, _Or_ or
8
+ _Yet_. It is reported once, at the body's first sentence, with the count, the rate and the first
9
+ three such sentences.
10
+
11
+ It reads the body of the whole paper — `paper.tex` with the files it `\input`s, `\include`s or
12
+ `\subfile`s spliced in — from the start of the document, the abstract included, to `\appendix` or the
13
+ bibliography: paragraphs, list items and footnotes. Headings are not sentences, and neither is a
14
+ run-in heading — a bold or italic phrase ending in `.` or `:` that opens a paragraph or an item
15
+ (`\textbf{Threats.} …`). Captions, tables, figures, code and math environments are left out. A
16
+ citation, a cross-reference or inline math counts as one word, as it reads on the page. Sentences
17
+ are cut exactly as [`tex/claim-provenance`](claim-provenance.md) cuts them.
18
+
19
+ A conjunction counts only as the capitalised first word of a sentence; the _and_ that opens a list
20
+ item continuing the sentence before the list does not.
21
+
22
+ A body under 2 000 words is not judged: there one sentence decides the rate.
23
+
24
+ ## Why
25
+
26
+ Reviewers called our prose "too informal" and "a blogpost". Measured against eleven accepted
27
+ papers, sentences opening with a coordinating conjunction set our four drafts apart:
28
+
29
+ | measure | 11 accepted papers | our 4 drafts |
30
+ | ------------------------------------------------------------ | ---------------------------: | -----------: |
31
+ | sentences opening with And/So/But/Nor/Or/Yet, per 1000 words | 0–0.58 (the ACSAC papers: 0) | 0.29–2.98 |
32
+
33
+ The limit sits above the accepted range with room to spare: the rule flags a body that has drifted
34
+ to a post's register, not one a little above the median. Mean sentence length did not separate the
35
+ two groups. The share of sentences under eight words did not either, once measured on the parse
36
+ tree: 3.3–7.3% on the two accepted papers in this repository's corpus, 5.1–7.0% on three of ours.
37
+
38
+ On the corpus (`fixtures/accepted-papers/`) the rule measures:
39
+
40
+ | paper | per 1000 words |
41
+ | ----------------------------------- | -------------: |
42
+ | `secure-acsac24` (ACSAC 2024) | 0.00 |
43
+ | `llm-splained-acsac25` (ACSAC 2025) | 0.00 |
44
+ | `agenticdev-acm26` (ours, accepted) | 1.60 |
45
+
46
+ The vocabulary of machine-written text (_delve_, _crucial_) is a different question, and a different
47
+ check; a paper can avoid every such word and still read as a post.
48
+
49
+ ## Examples
50
+
51
+ ```latex
52
+ We measured the cost on four tools. But the bill barely moves. % a conjunction start
53
+ We measured the cost on four tools, and the bill barely moves. % none
54
+ We measured the cost on four tools. However, the bill barely moves. % none
55
+ ```
56
+
57
+ On a body where such sentences run above the limit, the rule reports:
58
+
59
+ > 7 sentences open with And, So, But, Nor, Or or Yet — 1.60 per 1000 words (first: «…», «…», «…»).
60
+ > Accepted papers measured 0–0.58; this rule warns above 0.8. Join the sentence to the one before,
61
+ > or open with the connective a paper uses (However, Therefore, Moreover)
62
+
63
+ ## Options / preset fields
64
+
65
+ In a paper's `paperlint.json`:
66
+
67
+ ```json
68
+ {
69
+ "rules": {
70
+ "tex/register": ["warn", { "conjunctionStartsPer1000": 0.8 }]
71
+ }
72
+ }
73
+ ```
74
+
75
+ | option | default | what it is |
76
+ | -------------------------- | ------: | ---------------------------------------------------------- |
77
+ | `conjunctionStartsPer1000` | 0.8 | the conjunction starts per 1000 words above which it warns |
@@ -9,6 +9,9 @@ the required sections by title in `required_sections`; the paper must have a `\s
9
9
  `\section*` with exactly that title (whitespace collapsed), and, when the preset says
10
10
  `position: "last"`, no section of the main text may come after it.
11
11
 
12
+ It reads the sections of the whole paper, the files `paper.tex` includes spliced in where they are
13
+ included, so a required section kept in `sections/llm-usage.tex` counts.
14
+
12
15
  It only knows the sections a preset lists. A paper whose `paperlint.json` names no preset, or a
13
16
  preset with no `required_sections`, gets no finding.
14
17
 
@@ -66,7 +69,6 @@ the bibliography or an appendix is fine. Without `position`, anywhere will do.
66
69
  ## What it does not check
67
70
 
68
71
  - Whether LLMs were used, or what the section says.
69
- - Sections pulled in with `\input` or `\include`: the rule reads `paper.tex` alone.
70
72
 
71
73
  ## How to fix
72
74
 
@@ -8,6 +8,17 @@ The paper is not set in the class its venue requires. The rule compares the `\do
8
8
  of `paper.tex` with the preset's `template`: the class must be the same, and every option the
9
9
  template names must be there. The paper may add options of its own.
10
10
 
11
+ A source that keeps one file for several venues and picks the class behind a TeX switch has several
12
+ `\documentclass` lines. The switch is not evaluated: each line is a candidate, the paper passes when
13
+ one of them is the template's class with its options, and when none is, one finding at the first
14
+ candidate names every one:
15
+
16
+ ```latex
17
+ \def\venue{2}
18
+ \if\venue1 \documentclass{article} \fi
19
+ \if\venue2 \documentclass[conference,compsoc]{IEEEtran} \fi % passes: the second candidate matches
20
+ ```
21
+
11
22
  It only knows the class a preset names. A paper whose `paperlint.json` names no preset, or a
12
23
  preset with no `template`, gets no finding.
13
24
 
@@ -55,6 +66,7 @@ and no option. A value that is neither is reported as a finding that names the p
55
66
  requires is there.
56
67
  - The version of the class file (#94).
57
68
  - A `\documentclass` inside a comment: the rule reads the parse tree, so it does not count.
69
+ - Which branch of a TeX switch builds: with several class lines, one matching candidate is enough.
58
70
 
59
71
  ## How to fix
60
72
 
@@ -11,7 +11,9 @@ now going to VenueB.
11
11
  It only knows the venues paperlint ships a preset for, by each preset's `name` and `aliases`. A
12
12
  venue with no preset is not recognized.
13
13
 
14
- It looks at what a reader sees — prose, the author block, captions, footnotes, a citation's note in
14
+ It reads the whole paper — `paper.tex` with the files it `\input`s, `\include`s or `\subfile`s
15
+ spliced in; a name found in an included file is reported at that include, with the file and line at
16
+ the front of the message. It looks at what a reader sees — prose, the author block, captions, footnotes, a citation's note in
15
17
  square brackets, and front-matter macros such as `\acmConference` — and ignores comments, citation
16
18
  keys, labels, URLs (a `\url`, and the address of an `\href` — its link text is read), math, code and
17
19
  the bibliography. Names are matched as whole words, case-sensitive.
@@ -58,7 +60,7 @@ reported.
58
60
  ## What it does not check
59
61
 
60
62
  - A venue no shipped preset describes.
61
- - A name split by markup (`\textbf{AI}Sec`), and text pulled in with `\input`.
63
+ - A name split by markup (`\textbf{AI}Sec`).
62
64
 
63
65
  ## How to fix
64
66
 
package/docs/rules.md CHANGED
@@ -8,19 +8,20 @@ reads and when it fails. Errors fail `paperlint lint`; warnings print and do not
8
8
  | `paper/stages` | error | `PIPELINE-STATUS.md` | a declared stage's PDF is missing, or the `bytes:` it names does not match the file's real size, or a frozen PDF exists that no stage declares |
9
9
  | `paper/source` | error | `PIPELINE-STATUS.md` | a declared stage has no frozen `.tex` beside its PDF (a commit hash does not count — squash and gc destroy it) |
10
10
  | `paper/author-list` | error | `paper.tex` → `_build/references.json` | an entry's authors are not those of the version it cites — typically the arXiv preprint's list under a published venue. Checked online by `paperlint build` (DBLP), reported on the entry's own line |
11
- | `paper/research-question` | warn | `paper.tex`, `paper.md`, `PIPELINE-STATUS.md` | a stage is declared and either the scorecard has no `researchQuestion` field, or it has one the paper does not contain. The declared sentence is compared against the source with whitespace collapsed — your words, not a pattern. Advisory, because nothing here can judge whether what you declared _is_ a research question |
12
- | `paper/section-word` | warn | `paper.tex`, `paper.md` | `§` or `\S\ref` instead of the word Section. **Fixable:** `--fix` writes `Section~\ref{…}` / `Section 5` |
13
- | `paper/leading-zero` | warn | `paper.tex`, `paper.md` | a decimal below 1 without its leading zero (`.05` instead of `0.05`, IEEE / ISO 80000-1 style), counted only where the reader sees it — prose, math and table cells, not macro options, column specs, comments, code or tikz. A number right after `¶` or `§` (`¶¶.42`) is a paragraph designator and is not reported; in a paragraph that cites numbers that way, another bare decimal is reported without a fix, with the zero as a suggestion. **Fixable** |
14
- | `paper/figure-ref-style` | warn | `paper.tex` | `Fig.~\ref` and `Figure~\ref` mixed in one document; each minority occurrence is reported. **Fixable:** `--fix` writes the majority form |
11
+ | `paper/section-word` | warn | `paper.tex` and its body files, `paper.md` | `§` or `\S\ref` instead of the word Section. **Fixable:** `--fix` writes `Section~\ref{…}` / `Section 5` |
12
+ | `paper/leading-zero` | warn | `paper.tex` and its body files, `paper.md` | a decimal below 1 without its leading zero (`.05` instead of `0.05`, IEEE / ISO 80000-1 style), counted only where the reader sees it — prose, math and table cells, not macro options, column specs, comments, code or tikz. A number right after `¶` or `§` (`¶¶.42`) is a paragraph designator and is not reported; in a paragraph that cites numbers that way, another bare decimal is reported without a fix, with the zero as a suggestion. **Fixable** |
13
+ | `paper/figure-ref-style` | warn | `paper.tex` and its body files | `Fig.~\ref` and `Figure~\ref` mixed in one document; each minority occurrence is reported. **Fixable:** `--fix` writes the majority form |
15
14
  | `bib/reachable-entry` | warn | `paper.tex` (its `filecontents` bibliography) | an entry has no doi, url or arXiv id — a reader has nothing to follow. Reported on the entry; no fix, the link has to be looked up |
16
15
  | `paper/cite-exists` | error | `paper.tex` → `_build/references.json` | an entry's doi or arXiv id resolves to nothing, or to a different work. Checked online by `paperlint build`; a work that was merely not found is not a finding |
17
16
  | `paper/refs-fresh` | error | `paper.tex` → `_build/references.json` | the bibliography changed since the build checked it (its SHA-256 differs) — run `npx paperlint build` |
18
17
  | `paper/refs-checked` | warn | `paper.tex` → `_build/references.json` | the paper has a bibliography and no build has checked it, or the last build could not (no network) — so the two rules above did not run |
19
- | `tex/future-promise` | warn | `paper.tex` | a camera-ready build still says "will be released" about something already handed over |
18
+ | `tex/future-promise` | warn | `paper.tex` and its body files | a camera-ready build still says "will be released" about something already handed over |
20
19
  | `tex/acm-frontmatter-override` | error | `paper.tex` | an `acmart` build overrides ACM's front-matter commands and drops template elements from page 1 |
21
20
  | [`tex/template`](rules/tex/template.md) | error | `paper.tex` → `paperlint.json` | the `\documentclass` is not the preset's `template` class, or lacks an option it names — [page](rules/tex/template.md) |
22
21
  | [`tex/required-section`](rules/tex/required-section.md) | error | `paper.tex` → `paperlint.json` | a section the preset requires (AIDC: «LLM Usage Statement», last) is missing or not where it must be — [page](rules/tex/required-section.md) |
23
22
  | [`tex/venue-leftover`](rules/tex/venue-leftover.md) | warn | `paper.tex` → `paperlint.json` | the text names another shipped venue than the one the paper extends («Submission to VenueA 2026» in a paper now set for VenueB) — [page](rules/tex/venue-leftover.md) |
23
+ | [`tex/claim-provenance`](rules/tex/claim-provenance.md) | warn | `paper.tex` | a sentence of the body states a number and does not say whose it is — no citation or link, no _we_/_our_, no `\ref` or "Table 2", no sample ("n = 134", "48 runs") — [page](rules/tex/claim-provenance.md) |
24
+ | [`tex/register`](rules/tex/register.md) | warn | `paper.tex` and the files it includes | the body runs to a post's register: more than 0.8 sentences per 1000 words open with _And_, _So_, _But_, _Nor_, _Or_ or _Yet_ — the limit is an option — [page](rules/tex/register.md) |
24
25
  | `review/frontmatter` | error | `reviews/*.md` | the review's frontmatter fails paperlint's JSON Schema — a `findings` record without `id`/`status`, an unknown field, or an **open** finding with no `cause` (`skill-defect` · `missing-skill` · `hook` · `rule`). A review with no `findings` key is not checked for findings |
25
26
  | `sibling/frontmatter` | warn | `siblings/*.md` (not `README.md`) | a sibling card's frontmatter has no `read:` saying how much of the competing paper was read (`full` · `abstract` · `none`) |
26
27
  | `pdf/fresh` | error | `paper.tex` → `_build/paper.facts.json` | the paper names a venue and the facts cannot be judged: not JSON, a schema other than 2, or they describe a PDF that is gone or differs from the one on disk (its SHA-256) |
@@ -31,6 +32,13 @@ reads and when it fails. Errors fail `paperlint lint`; warnings print and do not
31
32
  | `pdf/body-size` | warn | `paper.tex` → `_build/paper.facts.json` | the body font size is more than `body_pt_tol` off the preset's. A warning: banal measures the mode of the rendered text, not the declared size (9.30 pt measured at a declared 9) |
32
33
  | `pdf/measured` | warn | `paper.tex` → `_build/paper.facts.json` | the paper's `paperlint.json` names no venue preset yet; or it names one and there are no facts (it was not built), or the facts carry no page geometry (banal was not found) — so the checks above did not run |
33
34
 
35
+ **Body files** are the files `paper.tex` includes from its document body (`\input`, `\include`,
36
+ `\subfile`, nested ones too), found in the paper's directory — not a preamble include, not a file
37
+ found only in paperlint's own inputs, and not any other `.tex` beside the paper (`versions/`). A
38
+ finding in one is reported at that file and line, and `--fix` edits that file. Which reference form
39
+ is the majority and whether the build is a review build are decided over the whole paper. An include
40
+ that names no file is printed as a note: lint did not read it, and the build will stop on it.
41
+
34
42
  `tex/required-section` requires AIDC's «LLM Usage Statement» **always**. ACSAC asks for it «if
35
43
  LLMs are used», which no rule can know; an author who used none says so in the section
36
44
  ([page](rules/tex/required-section.md)).
@@ -211,10 +219,10 @@ Presets from npm packages are not supported yet.
211
219
 
212
220
  ## The paper is LaTeX
213
221
 
214
- The paper body is `paper.tex`, and it gets four rules of its own: `paper/research-question`,
215
- `paper/typography`, `tex/future-promise` and `tex/acm-frontmatter-override` — plus the `pdf/`
216
- venue rules above, which run on it but judge the files beside it. The scorecard and
217
- the review notes are Markdown files, and the other five rules read those.
222
+ The paper body is `paper.tex`, and it gets three rules of its own: `paper/typography`,
223
+ `tex/future-promise` and `tex/acm-frontmatter-override` — plus the `pdf/` venue rules above, which
224
+ run on it but judge the files beside it. The scorecard and the review notes are Markdown files, and
225
+ the other five rules read those.
218
226
 
219
227
  A Markdown body (`paper.md`, or `draft.md`) is still read today and gets only the two `paper/`
220
228
  rules, which is why they list it above. Markdown papers are deprecated and being removed
@@ -238,7 +246,6 @@ stages:
238
246
  bytes: 305412
239
247
  source: versions/2026-07-22-submitted.tex
240
248
  sourceBytes: 57210
241
- researchQuestion: "Does pruning the state space reduce review cost?"
242
249
  ---
243
250
  ```
244
251
 
@@ -51,9 +51,12 @@
51
51
  * paper. The projection counts differently: the same place gave 1239 words before macro
52
52
  * blanking and 1208 after — a 2.5% discrepancy. The discrepancy is ACCEPTED deliberately;
53
53
  * the thresholds were not recalibrated.
54
- * 4. A MULTI-FILE PAPER IS INVISIBLE. `\input` / `\include` are in OPAQUE — their contents
55
- * are not read. The first `\input{sections/method}` yields a silent zero over all the
56
- * prose it pulls in.
54
+ * 4. ONE FILE AT A TIME. `\input` / `\include` are in OPAQUE: the projection of `paper.tex`
55
+ * does not hold what they pull in. `paperlint lint` hands ESLint each file the paper includes
56
+ * from its body as a file of its own (src/paper-includes.ts), and a file with no `document`
57
+ * environment is projected as body throughout — so an included file is read where it is,
58
+ * and its findings point into it. An ESLint run outside `paperlint lint` reads only the
59
+ * files it was given.
57
60
  * 5. `\appendix` IS NOT IMPLEMENTED and is INEXPRESSIBLE in a length-preserving projection:
58
61
  * `\appendix` is 9 characters, `## Appendix` is 11, the synthesis does not fit. On the
59
62
  * first paper with a real `\appendix`, `appendix-ref` / `appendix-ratio` yield a silent
@@ -209,6 +212,9 @@ export type MdNode =
209
212
  readonly value: string;
210
213
  };
211
214
 
215
+ /** The root of a projection: a node that has children. */
216
+ export type MdRoot = Extract<MdNode, { readonly type: "root" | "strong" }>;
217
+
212
218
  /** An inline-config comment: an `html` node's text and where it sits. */
213
219
  interface ConfigNode {
214
220
  readonly value: string;
@@ -305,7 +311,7 @@ export function texToMdast(
305
311
  {
306
312
  parse = (s: string): TexRoot => getParser().parse(s),
307
313
  }: { parse?: (s: string) => TexRoot } = {},
308
- ): { root: MdNode; text: string } {
314
+ ): { root: MdRoot; text: string } {
309
315
  const ast = parse(src);
310
316
  const chars = src.split("");
311
317
  const blank = (from: number, to: number) => {