paperlint 6.2.3 → 7.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 (234) hide show
  1. package/CONTRIBUTING.md +4 -2
  2. package/README.md +10 -3
  3. package/dist/adapters/hotcrp/index.d.ts +7 -0
  4. package/dist/adapters/hotcrp/index.d.ts.map +1 -0
  5. package/dist/adapters/hotcrp/index.js +7 -0
  6. package/dist/adapters/hotcrp/index.js.map +1 -0
  7. package/dist/adapters/hotcrp/portal.io.d.ts +20 -0
  8. package/dist/adapters/hotcrp/portal.io.d.ts.map +1 -0
  9. package/dist/adapters/hotcrp/portal.io.js +90 -0
  10. package/dist/adapters/hotcrp/portal.io.js.map +1 -0
  11. package/dist/adapters/hotcrp/response.d.ts +13 -0
  12. package/dist/adapters/hotcrp/response.d.ts.map +1 -0
  13. package/dist/adapters/hotcrp/response.js +138 -0
  14. package/dist/adapters/hotcrp/response.js.map +1 -0
  15. package/dist/adapters/latex/conditionals.d.ts +21 -0
  16. package/dist/adapters/latex/conditionals.d.ts.map +1 -0
  17. package/dist/adapters/latex/conditionals.js +75 -0
  18. package/dist/adapters/latex/conditionals.js.map +1 -0
  19. package/dist/adapters/latex/headings.d.ts +10 -0
  20. package/dist/adapters/latex/headings.d.ts.map +1 -0
  21. package/dist/adapters/latex/headings.js +129 -0
  22. package/dist/adapters/latex/headings.js.map +1 -0
  23. package/dist/adapters/latex/index.d.ts +1 -0
  24. package/dist/adapters/latex/index.d.ts.map +1 -1
  25. package/dist/adapters/latex/index.js +3 -0
  26. package/dist/adapters/latex/index.js.map +1 -1
  27. package/dist/adapters/latex/parse.d.ts +1 -1
  28. package/dist/adapters/latex/parse.d.ts.map +1 -1
  29. package/dist/adapters/latex/parse.js +3 -2
  30. package/dist/adapters/latex/parse.js.map +1 -1
  31. package/dist/build.d.ts +1 -1
  32. package/dist/build.d.ts.map +1 -1
  33. package/dist/build.js +1 -1
  34. package/dist/build.js.map +1 -1
  35. package/dist/cli.d.ts +4 -2
  36. package/dist/cli.d.ts.map +1 -1
  37. package/dist/cli.js +126 -37
  38. package/dist/cli.js.map +1 -1
  39. package/dist/domain/heading-case.d.ts +100 -0
  40. package/dist/domain/heading-case.d.ts.map +1 -0
  41. package/dist/domain/heading-case.js +365 -0
  42. package/dist/domain/heading-case.js.map +1 -0
  43. package/dist/domain/result.d.ts +4 -0
  44. package/dist/domain/result.d.ts.map +1 -1
  45. package/dist/domain/result.js +2 -0
  46. package/dist/domain/result.js.map +1 -1
  47. package/dist/domain/submission.d.ts +106 -0
  48. package/dist/domain/submission.d.ts.map +1 -0
  49. package/dist/domain/submission.js +39 -0
  50. package/dist/domain/submission.js.map +1 -0
  51. package/dist/domain/tex-document.d.ts +32 -0
  52. package/dist/domain/tex-document.d.ts.map +1 -1
  53. package/dist/domain/tex-document.js +11 -0
  54. package/dist/domain/tex-document.js.map +1 -1
  55. package/dist/domain/venue-name.d.ts +38 -0
  56. package/dist/domain/venue-name.d.ts.map +1 -0
  57. package/dist/domain/venue-name.js +71 -0
  58. package/dist/domain/venue-name.js.map +1 -0
  59. package/dist/eslint-rules/latex-language.d.ts.map +1 -1
  60. package/dist/eslint-rules/latex-language.js +16 -3
  61. package/dist/eslint-rules/latex-language.js.map +1 -1
  62. package/dist/facts-file.d.ts +3 -3
  63. package/dist/facts-file.d.ts.map +1 -1
  64. package/dist/facts-file.js +3 -3
  65. package/dist/facts-file.js.map +1 -1
  66. package/dist/folder-venue-rule.d.ts +51 -0
  67. package/dist/folder-venue-rule.d.ts.map +1 -0
  68. package/dist/folder-venue-rule.js +96 -0
  69. package/dist/folder-venue-rule.js.map +1 -0
  70. package/dist/heading-case.d.ts +48 -0
  71. package/dist/heading-case.d.ts.map +1 -0
  72. package/dist/heading-case.js +191 -0
  73. package/dist/heading-case.js.map +1 -0
  74. package/dist/init.d.ts +6 -0
  75. package/dist/init.d.ts.map +1 -1
  76. package/dist/init.js +3 -3
  77. package/dist/init.js.map +1 -1
  78. package/dist/lib/paper-config.d.ts.map +1 -1
  79. package/dist/lib/paper-config.js +5 -1
  80. package/dist/lib/paper-config.js.map +1 -1
  81. package/dist/new-paper.d.ts +19 -5
  82. package/dist/new-paper.d.ts.map +1 -1
  83. package/dist/new-paper.js +23 -4
  84. package/dist/new-paper.js.map +1 -1
  85. package/dist/paper-settings.d.ts +3 -0
  86. package/dist/paper-settings.d.ts.map +1 -1
  87. package/dist/paper-settings.js +20 -4
  88. package/dist/paper-settings.js.map +1 -1
  89. package/dist/ports/latex.d.ts +7 -1
  90. package/dist/ports/latex.d.ts.map +1 -1
  91. package/dist/ports/submission-portal.d.ts +19 -0
  92. package/dist/ports/submission-portal.d.ts.map +1 -0
  93. package/dist/ports/submission-portal.js +2 -0
  94. package/dist/ports/submission-portal.js.map +1 -0
  95. package/dist/preset-card-rule.d.ts +100 -0
  96. package/dist/preset-card-rule.d.ts.map +1 -0
  97. package/dist/preset-card-rule.js +221 -0
  98. package/dist/preset-card-rule.js.map +1 -0
  99. package/dist/presets.d.ts +43 -2
  100. package/dist/presets.d.ts.map +1 -1
  101. package/dist/presets.js +130 -63
  102. package/dist/presets.js.map +1 -1
  103. package/dist/rules-config.js +1 -1
  104. package/dist/submission.d.ts +61 -0
  105. package/dist/submission.d.ts.map +1 -0
  106. package/dist/submission.js +211 -0
  107. package/dist/submission.js.map +1 -0
  108. package/dist/tex-requirements.d.ts +36 -3
  109. package/dist/tex-requirements.d.ts.map +1 -1
  110. package/dist/tex-requirements.js +30 -2
  111. package/dist/tex-requirements.js.map +1 -1
  112. package/dist/tex-venue-rules.d.ts +7 -8
  113. package/dist/tex-venue-rules.d.ts.map +1 -1
  114. package/dist/tex-venue-rules.js +10 -14
  115. package/dist/tex-venue-rules.js.map +1 -1
  116. package/dist/types.d.ts +13 -0
  117. package/dist/types.d.ts.map +1 -1
  118. package/docs/configuration.md +30 -11
  119. package/docs/optional-rules.md +4 -3
  120. package/docs/rules/format/page-limit.md +1 -1
  121. package/docs/rules/paper/folder-venue-leftover.md +104 -0
  122. package/docs/rules/talk/captions-cover.md +1 -1
  123. package/docs/rules/talk/duration-floor.md +1 -1
  124. package/docs/rules/talk/profile.md +1 -1
  125. package/docs/rules/tex/heading-case.md +424 -0
  126. package/docs/rules.md +64 -53
  127. package/docs/skills.md +5 -4
  128. package/docs/submission.md +64 -0
  129. package/docs/talk.md +1 -1
  130. package/eslint-rules/latex-language.test.mjs +12 -0
  131. package/eslint-rules/latex-language.ts +17 -4
  132. package/eslint-rules/paper-typography.test.mjs +12 -0
  133. package/eslint.config.mjs +59 -1
  134. package/fixtures/build-e2e/acmart/paper.tex +1 -1
  135. package/fixtures/build-e2e/fallback/expect.json +3 -3
  136. package/lib/paper-config.ts +6 -1
  137. package/lib/skill-checks.d.mts +7 -0
  138. package/lib/skill-checks.mjs +31 -0
  139. package/lib/skill-trigger-cases.mjs +11 -0
  140. package/package.json +8 -2
  141. package/presets/acm-sigconf.jsonc +5 -0
  142. package/presets/acm-sigconf.md +43 -0
  143. package/presets/agenticdev.jsonc +27 -6
  144. package/presets/agenticdev.md +151 -0
  145. package/presets/aidc.jsonc +12 -0
  146. package/presets/aidc.md +75 -0
  147. package/presets/aisec.jsonc +5 -1
  148. package/presets/aisec.md +117 -0
  149. package/presets/ieee-conference.jsonc +5 -0
  150. package/presets/ieee-conference.md +38 -0
  151. package/presets/realm.jsonc +7 -2
  152. package/presets/realm.md +166 -0
  153. package/presets/tex/agenticdev.tex +1 -1
  154. package/presets/tex-base.jsonc +6 -0
  155. package/presets/tex-base.md +30 -0
  156. package/presets/venue-profile.schema.json +57 -2
  157. package/skills/find-venue/SKILL.md +6 -5
  158. package/skills/find-venue/SKILL.md.spec.ts +5 -4
  159. package/skills/paper-pipeline/SKILL.md +5 -6
  160. package/skills/paper-pipeline/SKILL.md.spec.ts +4 -5
  161. package/skills/paper-pipeline/paper-pipeline.harness.mjs +4 -0
  162. package/skills/paper-pipeline/references/acl-venue-rules.md +1 -1
  163. package/skills/study-accepted-papers/SKILL.md +3 -3
  164. package/skills/study-accepted-papers/SKILL.md.spec.ts +2 -2
  165. package/skills/submission-portal/SKILL.md +69 -0
  166. package/skills/submission-portal/SKILL.md.spec.ts +71 -0
  167. package/skills/submission-portal/submission-portal.eval.mjs +15 -0
  168. package/skills/submission-portal/submission-portal.test.ts +81 -0
  169. package/skills/submit-paper/SKILL.md +27 -22
  170. package/skills/submit-paper/SKILL.md.spec.ts +26 -21
  171. package/skills/submit-paper/references/publishers/acm.md +1 -1
  172. package/src/adapters/hotcrp/cassette/README.md +24 -0
  173. package/src/adapters/hotcrp/cassette/get-noauth.json +10 -0
  174. package/src/adapters/hotcrp/cassette/get-paper.json +39 -0
  175. package/src/adapters/hotcrp/cassette/post-dot.json +21 -0
  176. package/src/adapters/hotcrp/cassette/post-ok.json +12 -0
  177. package/src/adapters/hotcrp/index.ts +11 -0
  178. package/src/adapters/hotcrp/portal.io.ts +130 -0
  179. package/src/adapters/hotcrp/portal.test.ts +503 -0
  180. package/src/adapters/hotcrp/response.ts +181 -0
  181. package/src/adapters/latex/conditionals.ts +130 -0
  182. package/src/adapters/latex/headings.ts +163 -0
  183. package/src/adapters/latex/index.test.ts +65 -0
  184. package/src/adapters/latex/index.ts +3 -0
  185. package/src/adapters/latex/parse.ts +3 -2
  186. package/src/build.ts +2 -2
  187. package/src/cli.test.ts +155 -3
  188. package/src/cli.ts +161 -25
  189. package/src/domain/heading-case.test.ts +660 -0
  190. package/src/domain/heading-case.ts +538 -0
  191. package/src/domain/result.test.ts +9 -1
  192. package/src/domain/result.ts +5 -0
  193. package/src/domain/submission.test.ts +45 -0
  194. package/src/domain/submission.ts +141 -0
  195. package/src/domain/tex-document.ts +36 -0
  196. package/src/domain/venue-name.test.ts +121 -0
  197. package/src/domain/venue-name.ts +129 -0
  198. package/src/facts-file.test.ts +4 -4
  199. package/src/facts-file.ts +6 -6
  200. package/src/folder-venue-rule.test.ts +182 -0
  201. package/src/folder-venue-rule.ts +141 -0
  202. package/src/heading-case.test.ts +500 -0
  203. package/src/heading-case.ts +275 -0
  204. package/src/init.test.ts +22 -0
  205. package/src/init.ts +9 -2
  206. package/src/new-paper.harness.mjs +11 -9
  207. package/src/new-paper.test.ts +135 -10
  208. package/src/new-paper.ts +38 -7
  209. package/src/paper-settings-commands.test.ts +25 -10
  210. package/src/paper-settings.test.ts +12 -1
  211. package/src/paper-settings.ts +25 -5
  212. package/src/parse-args.test.ts +19 -0
  213. package/src/ports/latex.ts +7 -0
  214. package/src/ports/submission-portal.ts +26 -0
  215. package/src/preset-card-rule.test.ts +266 -0
  216. package/src/preset-card-rule.ts +384 -0
  217. package/src/presets.test.ts +212 -37
  218. package/src/presets.ts +183 -71
  219. package/src/rule-cases.test.ts +147 -42
  220. package/src/rules-config.ts +1 -1
  221. package/src/submission.test.ts +497 -0
  222. package/src/submission.ts +311 -0
  223. package/src/talk-rules.test.ts +6 -3
  224. package/src/tex-requirements.harness.ts +25 -11
  225. package/src/tex-requirements.test.ts +127 -1
  226. package/src/tex-requirements.ts +78 -8
  227. package/src/tex-venue-rules.test.ts +36 -22
  228. package/src/tex-venue-rules.ts +14 -26
  229. package/src/types.ts +13 -0
  230. package/src/venue-rules.test.ts +7 -6
  231. package/templates/paper/paper.tex +1 -1
  232. package/skills/submit-paper/references/venues/agenticdev.md +0 -171
  233. package/skills/submit-paper/references/venues/aisec.md +0 -105
  234. package/skills/submit-paper/references/venues/realm.md +0 -155
@@ -18,7 +18,7 @@ import { z } from "zod";
18
18
  import { run, rulePlugins } from "./cli.ts";
19
19
  import { sha256Hex } from "./domain/sha256.ts";
20
20
  import { bibHash } from "./references.ts";
21
- import { useTempDir, writeTree } from "../test/support.ts";
21
+ import { useTempDir, venuePreset, writeTree } from "../test/support.ts";
22
22
 
23
23
  const ROOT = dirname(dirname(fileURLToPath(import.meta.url)));
24
24
  const fixture = (p: string): string =>
@@ -39,19 +39,87 @@ const paper = (
39
39
  ...extra,
40
40
  });
41
41
 
42
+ // ── the venues: presets of the tree's own, never the shipped ones ──────────────────────────────
43
+ //
44
+ // A case judges a RULE, so every number it is sized against is written here, beside the facts and
45
+ // the bodies that meet or miss it. A shipped venue preset changes when its call for papers does;
46
+ // its own tests resolve and judge it (presets.test.ts, venue-rules.test.ts, tex-venue-rules.test.ts,
47
+ // register-bands.test.ts, heading-case.test.ts). The one exception is the leftover rules, below:
48
+ // they name SHIPPED venues by design, so their reporting cases need one shipped venue's name.
49
+ // The venues below extend a template family only for what the schema asks of a chain's root (its
50
+ // `tex`), and set every key a case reads themselves.
51
+
52
+ /** A short-paper venue on the ACM template: the format the facts of `goodFacts` meet. */
53
+ const EXAMPLECONF = venuePreset("ExampleConf", {
54
+ extends: "paperlint:acm-sigconf",
55
+ format: {
56
+ page_w_in: 8.5,
57
+ page_h_in: 11,
58
+ columns: 2,
59
+ body_pt: 9,
60
+ body_pt_tol: 0.5,
61
+ ref_pt_min: 7,
62
+ ref_pt_max: 9,
63
+ fonts_text: "LinLibertine",
64
+ fonts_title: "LinBiolinum",
65
+ kinds: { short: { body_pages_max: 5, ref_pages_max: 2 } },
66
+ },
67
+ // chicago-headline for the title and every heading (tex/heading-case).
68
+ rules: {
69
+ "tex/heading-case": [
70
+ "error",
71
+ { title: "chicago-headline", headings: "chicago-headline" },
72
+ ],
73
+ },
74
+ });
75
+ const IEEE = "\\documentclass[conference,compsoc]{IEEEtran}";
76
+ const STATEMENT_TITLE = "LLM Usage Statement";
77
+ /**
78
+ * A double-blind venue on the IEEE template: the class options it requires, the section it requires
79
+ * last, and one accepted paper of 10,000 words for the register bands. Its rates (contrast frames 4,
80
+ * claims in bold 4, relation markers 64 per 10,000 words), widened by two Poisson standard
81
+ * deviations, set the bands 0–8, 0–8 and 48–80.
82
+ */
83
+ const BLINDCONF = venuePreset("BlindConf", {
84
+ extends: "paperlint:ieee-conference",
85
+ blind: true,
86
+ template: IEEE,
87
+ required_sections: [{ title: STATEMENT_TITLE, position: "last" }],
88
+ register: {
89
+ anchors: [
90
+ {
91
+ paper: "an-accepted-paper",
92
+ words: 10_000,
93
+ contrast_frames: 4,
94
+ claim_emphasis: 4,
95
+ relation_markers: 64,
96
+ },
97
+ ],
98
+ },
99
+ });
100
+ /** The venue presets every built paper carries beside it, extended or not. */
101
+ const VENUES = {
102
+ [`${P}/exampleconf.jsonc`]: JSON.stringify(EXAMPLECONF),
103
+ [`${P}/blindconf.jsonc`]: JSON.stringify(BLINDCONF),
104
+ };
105
+ /** A paper folder on BlindConf: the preset beside its `paperlint.json`. */
106
+ const onBlindConf = (dir: string): Record<string, string> => ({
107
+ [`${dir}/blindconf.jsonc`]: JSON.stringify(BLINDCONF),
108
+ [`${dir}/paperlint.json`]: JSON.stringify({ extends: "./blindconf.jsonc" }),
109
+ });
110
+
42
111
  // ── the venue rules' inputs: a PDF and the facts `paperlint build` would write about it ─────────
43
112
 
44
113
  const PDF = "%PDF-1.5 a stand-in for the built PDF";
45
- const AGENTICDEV = { extends: "paperlint:agenticdev", kind: "short" };
114
+ const EXAMPLE = { extends: "./exampleconf.jsonc", kind: "short" };
46
115
  /** A double-blind venue's paper that declares who wrote it (`anonymity/*`). */
47
116
  const BLIND = {
48
- extends: "paperlint:aidc",
49
- kind: "regular",
117
+ extends: "./blindconf.jsonc",
50
118
  identity: ["Ada Example", "adaexample"],
51
119
  };
52
120
  const ACM_TEX = tex("Text.", "\\documentclass[sigconf]{acmart}");
53
121
 
54
- /** The facts of a short agenticdev paper that meets every number in its preset. */
122
+ /** The facts of a short ExampleConf paper that meets every number in its preset. */
55
123
  const goodFacts = (): Record<string, unknown> => ({
56
124
  schema: 3,
57
125
  pages_text: [],
@@ -61,7 +129,7 @@ const goodFacts = (): Record<string, unknown> => ({
61
129
  appendix_anchor_page: null,
62
130
  pdf: "paper.pdf",
63
131
  pdf_sha256: sha256Hex(new TextEncoder().encode(PDF)),
64
- venue: "agenticdev",
132
+ venue: "exampleconf",
65
133
  kind: "short",
66
134
  npages: 7,
67
135
  fonts_source: "pdfjs-drawn",
@@ -85,12 +153,13 @@ const goodFacts = (): Record<string, unknown> => ({
85
153
  pages_by_type: { body: 5, bib: 2 },
86
154
  });
87
155
 
88
- /** An agenticdev paper, built: its settings, the PDF, and facts with `patch` applied. */
156
+ /** An ExampleConf paper, built: its settings, the PDF, and facts with `patch` applied. */
89
157
  const built = (
90
158
  patch: Record<string, unknown> = {},
91
- settings: Record<string, unknown> = AGENTICDEV,
159
+ settings: Record<string, unknown> = EXAMPLE,
92
160
  ): Record<string, string> =>
93
161
  paper(ACM_TEX, {
162
+ ...VENUES,
94
163
  [`${P}/paperlint.json`]: JSON.stringify(settings),
95
164
  [`${P}/paper.pdf`]: PDF,
96
165
  [`${P}/_build/paper.facts.json`]: JSON.stringify({
@@ -129,23 +198,26 @@ const checked = (exists: string, authors: string) => ({
129
198
  entries: [{ key: "a", exists, authors }],
130
199
  });
131
200
 
132
- // ── an AIDC paper, for the LaTeX venue rules ──────────────────────────────────────────────────
201
+ // ── a BlindConf paper, for the LaTeX venue rules ──────────────────────────────────────────────
133
202
 
134
- const AIDC = {
135
- [`${P}/paperlint.json`]: JSON.stringify({
136
- extends: "paperlint:aidc",
137
- kind: "short",
138
- }),
203
+ const BLIND_PAPER = onBlindConf(P);
204
+ const ACM_CLASS = "\\documentclass[sigconf]{acmart}";
205
+ /** A paper on ExampleConf's preset: it turns `tex/heading-case` on, chicago-headline for the title and every heading. */
206
+ const ACM_PRESET = {
207
+ ...VENUES,
208
+ [`${P}/paperlint.json`]: JSON.stringify(EXAMPLE),
139
209
  };
140
- const IEEE = "\\documentclass[conference,compsoc]{IEEEtran}";
141
- const STATEMENT = "\\section*{LLM Usage Statement}\nNone.";
210
+ const STATEMENT = `\\section*{${STATEMENT_TITLE}}\nNone.`;
142
211
  /** Two `\\documentclass` lines behind a switch: `article` for one venue, `second` for this one. */
143
212
  const switched = (second: string): string =>
144
213
  `\\def\\venue{2}\n\\if\\venue1\n\\documentclass{article}\n\\fi\n\\if\\venue2\n${second}\n\\fi`;
145
- const aidc = (body: string, cls = IEEE) =>
146
- paper(tex(`\\section{Introduction}\n${body}\n${STATEMENT}`, cls), AIDC);
214
+ const blind = (body: string, cls = IEEE) =>
215
+ paper(
216
+ tex(`\\section{Introduction}\n${body}\n${STATEMENT}`, cls),
217
+ BLIND_PAPER,
218
+ );
147
219
 
148
- // ── a paper that declares a talk: a preset of its own over agenticdev, and synthetic media ───────
220
+ // ── a paper that declares a talk: a preset of its own over ExampleConf, and synthetic media ──────
149
221
 
150
222
  const media = (name: string): Uint8Array =>
151
223
  readFileSync(join(ROOT, "fixtures", "talk", name));
@@ -173,10 +245,13 @@ const talkPaper = (
173
245
  };
174
246
  return {
175
247
  ...paper(ACM_TEX, {
176
- [`${P}/talk-venue.jsonc`]: JSON.stringify({
177
- extends: "paperlint:agenticdev",
178
- talk: { ...TALK_VENUE, ...venue },
179
- }),
248
+ ...VENUES,
249
+ [`${P}/talk-venue.jsonc`]: JSON.stringify(
250
+ venuePreset("talk-venue", {
251
+ extends: "./exampleconf.jsonc",
252
+ talk: { ...TALK_VENUE, ...venue },
253
+ }),
254
+ ),
180
255
  [`${P}/paperlint.json`]: JSON.stringify({
181
256
  extends: "./talk-venue.jsonc",
182
257
  kind: "short",
@@ -226,7 +301,7 @@ const FORMAL = Array.from(
226
301
  /** FORMAL with `n` more sentences `s`: a body whose rate of one register measure is set. */
227
302
  const formalWith = (n: number, s: string): string =>
228
303
  `${FORMAL} ${Array.from({ length: n }, () => s).join(" ")}`;
229
- /** FORMAL with enough relation markers for AIDC's band (above 25.4 per 10,000 words). */
304
+ /** FORMAL with 20 relation markers, 68.7 per 10,000 words: inside BlindConf's band (48–80). */
230
305
  const LINKED = formalWith(
231
306
  10,
232
307
  "Therefore, the rule counts the sentence because the body holds it.",
@@ -373,30 +448,60 @@ const CASES: Readonly<Record<string, RuleCases>> = {
373
448
  // The class picked behind a TeX switch: two candidates, one of them the venue's or none.
374
449
  "tex/template": {
375
450
  reports: {
376
- tree: aidc("Text.", switched("\\documentclass[conference]{IEEEtran}")),
451
+ tree: blind("Text.", switched("\\documentclass[conference]{IEEEtran}")),
377
452
  file: TEX_FILE,
378
453
  severity: 2,
379
454
  line: 3,
380
455
  },
381
- silent: aidc("Text.", switched(IEEE)),
456
+ silent: blind("Text.", switched(IEEE)),
382
457
  },
383
458
  "tex/required-section": {
384
459
  reports: {
385
- tree: paper(tex("\\section{Introduction}\nText.", IEEE), AIDC),
460
+ tree: paper(tex("\\section{Introduction}\nText.", IEEE), BLIND_PAPER),
386
461
  file: TEX_FILE,
387
462
  severity: 2,
388
463
  line: 5,
389
464
  },
390
- silent: aidc("Text."),
465
+ silent: blind("Text."),
466
+ },
467
+ "tex/heading-case": {
468
+ reports: {
469
+ tree: paper(tex("\\section{Related work}", ACM_CLASS), ACM_PRESET),
470
+ file: TEX_FILE,
471
+ severity: 2,
472
+ line: 3,
473
+ },
474
+ silent: paper(tex("\\section{Related Work}", ACM_CLASS), ACM_PRESET),
475
+ },
476
+ "paper/folder-venue-leftover": {
477
+ reports: {
478
+ // A BlindConf paper in a folder named for EMNLP. The rule knows only the SHIPPED venues'
479
+ // names (REALM's preset calls it by its conference, EMNLP), so the other venue is one of them.
480
+ tree: {
481
+ "papers/emnlp-2026/PIPELINE-STATUS.md": STATUS,
482
+ "papers/emnlp-2026/paper.tex": tex("x"),
483
+ ...onBlindConf("papers/emnlp-2026"),
484
+ },
485
+ file: "papers/emnlp-2026/PIPELINE-STATUS.md",
486
+ severity: 1,
487
+ line: 1,
488
+ },
489
+ // The folder names the paper's own venue.
490
+ silent: {
491
+ "papers/blindconf-2026/PIPELINE-STATUS.md": STATUS,
492
+ "papers/blindconf-2026/paper.tex": tex("x"),
493
+ ...onBlindConf("papers/blindconf-2026"),
494
+ },
391
495
  },
496
+ // EMNLP, a shipped venue's name (REALM's conference), in a BlindConf paper's text.
392
497
  "tex/venue-leftover": {
393
498
  reports: {
394
- tree: aidc("First written for AISec."),
499
+ tree: blind("First written for EMNLP."),
395
500
  file: TEX_FILE,
396
501
  severity: 1,
397
502
  line: 4,
398
503
  },
399
- silent: aidc("Text."),
504
+ silent: blind("Text."),
400
505
  },
401
506
  "tex/claim-provenance": {
402
507
  reports: {
@@ -420,31 +525,31 @@ const CASES: Readonly<Record<string, RuleCases>> = {
420
525
  },
421
526
  silent: paper(tex(FORMAL)),
422
527
  },
423
- // The three register bands judge a body against the anchors of AIDC's preset; the body opens on
424
- // line 3, right after the \\section, where the finding about the whole body stands.
528
+ // The three register bands judge a body against the anchor of BlindConf's preset; the body opens
529
+ // on line 3, right after the \\section, where the finding about the whole body stands.
425
530
  "tex/contrast-frames": {
426
531
  reports: {
427
- tree: aidc(formalWith(5, "It reads the word, not the operation.")),
532
+ tree: blind(formalWith(5, "It reads the word, not the operation.")),
428
533
  file: TEX_FILE,
429
534
  severity: 1,
430
535
  line: 3,
431
536
  },
432
- silent: aidc(LINKED),
537
+ silent: blind(LINKED),
433
538
  },
434
539
  "tex/claim-emphasis": {
435
540
  reports: {
436
- tree: aidc(
541
+ tree: blind(
437
542
  formalWith(6, "We find that \\textbf{the rule counts 46 sentences}."),
438
543
  ),
439
544
  file: TEX_FILE,
440
545
  severity: 1,
441
546
  line: 3,
442
547
  },
443
- silent: aidc(LINKED),
548
+ silent: blind(LINKED),
444
549
  },
445
550
  "tex/relation-markers": {
446
- reports: { tree: aidc(FORMAL), file: TEX_FILE, severity: 1, line: 3 },
447
- silent: aidc(LINKED),
551
+ reports: { tree: blind(FORMAL), file: TEX_FILE, severity: 1, line: 3 },
552
+ silent: blind(LINKED),
448
553
  },
449
554
  "bib/reachable-entry": {
450
555
  reports: {
@@ -499,23 +604,23 @@ const CASES: Readonly<Record<string, RuleCases>> = {
499
604
  },
500
605
  "format/layout-override": {
501
606
  reports: {
502
- tree: aidc("\\linespread{0.9}Text."),
607
+ tree: blind("\\linespread{0.9}Text."),
503
608
  file: TEX_FILE,
504
609
  severity: 2,
505
610
  line: 4,
506
611
  },
507
- silent: aidc("\\vspace{-2mm}Text."),
612
+ silent: blind("\\vspace{-2mm}Text."),
508
613
  },
509
614
  "pdf/last-page-balance": {
510
615
  reports: onPdf(
511
616
  built(
512
617
  { last_page: { kind: "measured", columns_pt: [621.5, 264.8] } },
513
- { ...AGENTICDEV, rules: { "pdf/last-page-balance": "error" } },
618
+ { ...EXAMPLE, rules: { "pdf/last-page-balance": "error" } },
514
619
  ),
515
620
  ),
516
621
  silent: built(
517
622
  {},
518
- { ...AGENTICDEV, rules: { "pdf/last-page-balance": "error" } },
623
+ { ...EXAMPLE, rules: { "pdf/last-page-balance": "error" } },
519
624
  ),
520
625
  },
521
626
  "talk/profile": {
@@ -6,7 +6,7 @@
6
6
  * A consumer turns an optional rule on, or changes a built-in rule's severity, by writing what they
7
7
  * would write in an ESLint flat config — a list of `{ files, ignores, rules }` blocks:
8
8
  *
9
- * "rules": [ { "files": ["papers/agenticdev-2026/**"],
9
+ * "rules": [ { "files": ["papers/rule-drift/**"],
10
10
  * "rules": { "pdf/last-page-balance": ["error", { "tolerancePt": 120 }] } } ]
11
11
  *
12
12
  * The blocks are appended AFTER paperlint's built-in config, so a later block wins, exactly as in ESLint.