paperlint 6.3.0 → 7.1.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 (185) hide show
  1. package/CONTRIBUTING.md +4 -2
  2. package/README.md +20 -13
  3. package/dist/adapters/latex/conditionals.d.ts +21 -0
  4. package/dist/adapters/latex/conditionals.d.ts.map +1 -0
  5. package/dist/adapters/latex/conditionals.js +75 -0
  6. package/dist/adapters/latex/conditionals.js.map +1 -0
  7. package/dist/adapters/latex/headings.d.ts +10 -0
  8. package/dist/adapters/latex/headings.d.ts.map +1 -0
  9. package/dist/adapters/latex/headings.js +129 -0
  10. package/dist/adapters/latex/headings.js.map +1 -0
  11. package/dist/adapters/latex/index.d.ts +1 -0
  12. package/dist/adapters/latex/index.d.ts.map +1 -1
  13. package/dist/adapters/latex/index.js +3 -0
  14. package/dist/adapters/latex/index.js.map +1 -1
  15. package/dist/adapters/latex/parse.d.ts +1 -1
  16. package/dist/adapters/latex/parse.d.ts.map +1 -1
  17. package/dist/adapters/latex/parse.js +3 -2
  18. package/dist/adapters/latex/parse.js.map +1 -1
  19. package/dist/build.d.ts +1 -1
  20. package/dist/build.d.ts.map +1 -1
  21. package/dist/build.js +1 -1
  22. package/dist/build.js.map +1 -1
  23. package/dist/cli.d.ts +1 -1
  24. package/dist/cli.d.ts.map +1 -1
  25. package/dist/cli.js +19 -5
  26. package/dist/cli.js.map +1 -1
  27. package/dist/domain/body-pages.d.ts +29 -0
  28. package/dist/domain/body-pages.d.ts.map +1 -1
  29. package/dist/domain/body-pages.js +25 -0
  30. package/dist/domain/body-pages.js.map +1 -1
  31. package/dist/domain/heading-case.d.ts +100 -0
  32. package/dist/domain/heading-case.d.ts.map +1 -0
  33. package/dist/domain/heading-case.js +365 -0
  34. package/dist/domain/heading-case.js.map +1 -0
  35. package/dist/domain/tex-document.d.ts +32 -0
  36. package/dist/domain/tex-document.d.ts.map +1 -1
  37. package/dist/domain/tex-document.js +11 -0
  38. package/dist/domain/tex-document.js.map +1 -1
  39. package/dist/eslint-rules/latex-language.d.ts.map +1 -1
  40. package/dist/eslint-rules/latex-language.js +16 -3
  41. package/dist/eslint-rules/latex-language.js.map +1 -1
  42. package/dist/facts-file.d.ts +3 -3
  43. package/dist/facts-file.d.ts.map +1 -1
  44. package/dist/facts-file.js +3 -3
  45. package/dist/facts-file.js.map +1 -1
  46. package/dist/folder-venue-rule.js +6 -6
  47. package/dist/folder-venue-rule.js.map +1 -1
  48. package/dist/heading-case.d.ts +48 -0
  49. package/dist/heading-case.d.ts.map +1 -0
  50. package/dist/heading-case.js +191 -0
  51. package/dist/heading-case.js.map +1 -0
  52. package/dist/paper-includes.d.ts +3 -0
  53. package/dist/paper-includes.d.ts.map +1 -1
  54. package/dist/paper-includes.js +17 -2
  55. package/dist/paper-includes.js.map +1 -1
  56. package/dist/ports/latex.d.ts +7 -1
  57. package/dist/ports/latex.d.ts.map +1 -1
  58. package/dist/preset-card-rule.d.ts +100 -0
  59. package/dist/preset-card-rule.d.ts.map +1 -0
  60. package/dist/preset-card-rule.js +221 -0
  61. package/dist/preset-card-rule.js.map +1 -0
  62. package/dist/presets.d.ts +29 -5
  63. package/dist/presets.d.ts.map +1 -1
  64. package/dist/presets.js +104 -68
  65. package/dist/presets.js.map +1 -1
  66. package/dist/submission.d.ts +8 -0
  67. package/dist/submission.d.ts.map +1 -1
  68. package/dist/submission.js +19 -7
  69. package/dist/submission.js.map +1 -1
  70. package/dist/tex-requirements.d.ts +42 -3
  71. package/dist/tex-requirements.d.ts.map +1 -1
  72. package/dist/tex-requirements.js +34 -5
  73. package/dist/tex-requirements.js.map +1 -1
  74. package/dist/tex-venue-rules.d.ts +6 -3
  75. package/dist/tex-venue-rules.d.ts.map +1 -1
  76. package/dist/tex-venue-rules.js +29 -10
  77. package/dist/tex-venue-rules.js.map +1 -1
  78. package/dist/venue-rules.d.ts +2 -1
  79. package/dist/venue-rules.d.ts.map +1 -1
  80. package/dist/venue-rules.js +55 -7
  81. package/dist/venue-rules.js.map +1 -1
  82. package/docs/configuration.md +13 -1
  83. package/docs/e2e.md +14 -12
  84. package/docs/optional-rules.md +4 -3
  85. package/docs/rules/format/page-limit.md +19 -2
  86. package/docs/rules/paper/folder-venue-leftover.md +1 -1
  87. package/docs/rules/talk/profile.md +1 -1
  88. package/docs/rules/tex/heading-case.md +424 -0
  89. package/docs/rules/tex/template.md +25 -5
  90. package/docs/rules/tex/venue-leftover.md +13 -0
  91. package/docs/rules.md +74 -57
  92. package/docs/submission.md +5 -1
  93. package/eslint-rules/latex-language.test.mjs +12 -0
  94. package/eslint-rules/latex-language.ts +17 -4
  95. package/eslint-rules/paper-typography.test.mjs +12 -0
  96. package/eslint.config.mjs +59 -1
  97. package/fixtures/build-e2e/acmart/paper.tex +1 -1
  98. package/fixtures/build-e2e/fallback/expect.json +3 -3
  99. package/fixtures/build-e2e/msr/PIPELINE-STATUS.md +3 -0
  100. package/fixtures/build-e2e/msr/expect.json +18 -0
  101. package/fixtures/build-e2e/msr/paper.tex +49 -0
  102. package/fixtures/build-e2e/msr/paperlint.json +1 -0
  103. package/fixtures/build-e2e/msr-appendix-after/PIPELINE-STATUS.md +3 -0
  104. package/fixtures/build-e2e/msr-appendix-after/expect.json +20 -0
  105. package/fixtures/build-e2e/msr-appendix-after/paper.tex +48 -0
  106. package/fixtures/build-e2e/msr-appendix-after/paperlint.json +1 -0
  107. package/lib/skill-checks.mjs +31 -0
  108. package/package.json +7 -1
  109. package/presets/acm-sigconf.jsonc +5 -0
  110. package/presets/acm-sigconf.md +43 -0
  111. package/presets/agenticdev.jsonc +27 -6
  112. package/presets/agenticdev.md +151 -0
  113. package/presets/aidc.jsonc +6 -0
  114. package/presets/aidc.md +75 -0
  115. package/presets/aisec.jsonc +5 -1
  116. package/presets/aisec.md +117 -0
  117. package/presets/ieee-conference.jsonc +5 -0
  118. package/presets/ieee-conference.md +38 -0
  119. package/presets/msr.jsonc +71 -0
  120. package/presets/msr.md +94 -0
  121. package/presets/realm.jsonc +7 -2
  122. package/presets/realm.md +166 -0
  123. package/presets/tex/agenticdev.tex +1 -1
  124. package/presets/tex-base.jsonc +6 -0
  125. package/presets/tex-base.md +30 -0
  126. package/presets/venue-profile.schema.json +65 -1
  127. package/skills/camera-ready/SKILL.md +8 -1
  128. package/skills/camera-ready/SKILL.md.spec.ts +7 -0
  129. package/skills/find-venue/SKILL.md +6 -5
  130. package/skills/find-venue/SKILL.md.spec.ts +5 -4
  131. package/skills/paper-pipeline/SKILL.md +5 -6
  132. package/skills/paper-pipeline/SKILL.md.spec.ts +4 -5
  133. package/skills/paper-pipeline/references/acl-venue-rules.md +1 -1
  134. package/skills/study-accepted-papers/SKILL.md +3 -3
  135. package/skills/study-accepted-papers/SKILL.md.spec.ts +2 -2
  136. package/skills/submission-portal/SKILL.md +2 -2
  137. package/skills/submission-portal/SKILL.md.spec.ts +1 -1
  138. package/skills/submit-paper/SKILL.md +34 -22
  139. package/skills/submit-paper/SKILL.md.spec.ts +33 -21
  140. package/skills/submit-paper/references/publishers/acm.md +1 -1
  141. package/src/adapters/latex/conditionals.ts +130 -0
  142. package/src/adapters/latex/headings.ts +163 -0
  143. package/src/adapters/latex/index.test.ts +65 -0
  144. package/src/adapters/latex/index.ts +3 -0
  145. package/src/adapters/latex/parse.ts +3 -2
  146. package/src/build.ts +2 -2
  147. package/src/cli.test.ts +50 -7
  148. package/src/cli.ts +28 -6
  149. package/src/domain/body-pages.test.ts +144 -0
  150. package/src/domain/body-pages.ts +61 -1
  151. package/src/domain/heading-case.test.ts +660 -0
  152. package/src/domain/heading-case.ts +538 -0
  153. package/src/domain/tex-document.ts +36 -0
  154. package/src/domain/venue-name.test.ts +13 -7
  155. package/src/facts-file.test.ts +4 -4
  156. package/src/facts-file.ts +6 -6
  157. package/src/folder-venue-rule.test.ts +10 -10
  158. package/src/folder-venue-rule.ts +6 -6
  159. package/src/heading-case.test.ts +500 -0
  160. package/src/heading-case.ts +275 -0
  161. package/src/init.test.ts +1 -1
  162. package/src/new-paper.test.ts +37 -6
  163. package/src/paper-includes.test.ts +26 -0
  164. package/src/paper-includes.ts +20 -2
  165. package/src/paper-settings-commands.test.ts +26 -11
  166. package/src/ports/latex.ts +7 -0
  167. package/src/preset-card-rule.test.ts +267 -0
  168. package/src/preset-card-rule.ts +384 -0
  169. package/src/presets.test.ts +259 -41
  170. package/src/presets.ts +161 -75
  171. package/src/rule-cases.test.ts +136 -50
  172. package/src/submission.test.ts +44 -4
  173. package/src/submission.ts +28 -7
  174. package/src/talk-rules.test.ts +6 -3
  175. package/src/tex-requirements.harness.ts +25 -11
  176. package/src/tex-requirements.test.ts +127 -1
  177. package/src/tex-requirements.ts +91 -12
  178. package/src/tex-venue-rules.test.ts +196 -21
  179. package/src/tex-venue-rules.ts +47 -16
  180. package/src/venue-rules.test.ts +180 -8
  181. package/src/venue-rules.ts +71 -10
  182. package/templates/paper/paper.tex +1 -1
  183. package/skills/submit-paper/references/venues/agenticdev.md +0 -171
  184. package/skills/submit-paper/references/venues/aisec.md +0 -105
  185. package/skills/submit-paper/references/venues/realm.md +0 -155
@@ -0,0 +1,49 @@
1
+ % A paper in the class MSR's call names, built by the e2e on paperlint's own TeX Live, that MEETS
2
+ % MSR's limit: ten pages of main text, its appendix included, and two pages holding only references
3
+ % (rendered and looked at, 2026-10-05: the appendix heading stands mid-column on page 9, appendix
4
+ % text then «REFERENCES» on page 10, nothing but entries on pages 11 and 12). banal's count says body
5
+ % 9, references 3 — a page whose first heading reads «Appendix» is typed as bibliography — and would
6
+ % fail it; format/page-limit counts from the text and must not.
7
+ %
8
+ % The prose is one paragraph set many times; each copy carries its own number in words on every
9
+ % line, so no line repeats from page to page as a running header would.
10
+ \documentclass[10pt,conference]{IEEEtran}
11
+ \usepackage{hyperref}
12
+ \newcount\paracount
13
+ \newcommand{\n}{\romannumeral\paracount}
14
+ \newcommand{\para}{\global\advance\paracount by 1
15
+ Paragraph \n{} studies the history of a repository, and \n{} counts its commits by author \n{}
16
+ and by month \n{}, so that the measurement \n{} has a body of prose \n{} set in the two columns
17
+ \n{} of the conference format. Paragraph \n{} says nothing new, and \n{} does not need to: the
18
+ fixture \n{} is about the class, \n{} the fonts and \n{} the page count, and \n{} not about its
19
+ content. A reviewer of \n{} would find it dull, \n{} which is what a measurement \n{} should be.\par}
20
+ \newcount\loopcount
21
+ \newcommand{\paras}[1]{\loopcount=0 \loop\para\advance\loopcount by 1 \ifnum\loopcount<#1\repeat}
22
+ \newcount\bibcount
23
+ \newcommand{\entries}[1]{\bibcount=0 \loop\advance\bibcount by 1
24
+ \bibitem{r\the\bibcount} A. Author, ``Mining study \romannumeral\bibcount,'' in \emph{Proc.
25
+ Workshop}, 2024, pp. 1--10.\ifnum\bibcount<#1\repeat}
26
+ \begin{document}
27
+ \title{A Fixture Typeset in the Class the Venue Requires}
28
+ \author{\IEEEauthorblockN{Anonymous Author}\IEEEauthorblockA{Anonymous Institution}}
29
+ \maketitle
30
+ \begin{abstract}
31
+ The abstract exists so the build has the front matter an IEEE paper carries.
32
+ \end{abstract}
33
+ \section{Introduction}
34
+ \paras{24}
35
+ \section{Part Two}
36
+ \paras{24}
37
+ \section{Part Three}
38
+ \paras{24}
39
+ \section{Part Four}
40
+ \paras{24}
41
+ \section{Part Five}
42
+ \paras{12}
43
+ \appendix
44
+ \section{Detailed Results}
45
+ \paras{12}
46
+ \begin{thebibliography}{999}
47
+ \entries{290}
48
+ \end{thebibliography}
49
+ \end{document}
@@ -0,0 +1 @@
1
+ {"extends": "paperlint:msr", "kind": "technical", "identity": ["Ada Example", "adaexample", "ada@example.org", "Example University", "exampletool"]}
@@ -0,0 +1,3 @@
1
+ # Fixture
2
+
3
+ Stage: draft
@@ -0,0 +1,20 @@
1
+ {
2
+ "$comment": "MSR: an appendix after the references brings the main text to eleven pages. Exactly one format/page-limit finding, naming where the appendix starts. banal's own count (body 9, references 2) would pass it.",
3
+ "build": {
4
+ "outcome": "pdf",
5
+ "pages": 11
6
+ },
7
+ "lint": {
8
+ "rules": {
9
+ "format/page-limit": [
10
+ {
11
+ "severity": 2,
12
+ "says": [
13
+ "body pages (up to the references on page 10, and the appendix from page 10): 11, over the limit 10 for MSR/technical"
14
+ ]
15
+ }
16
+ ],
17
+ "tex/template": []
18
+ }
19
+ }
20
+ }
@@ -0,0 +1,48 @@
1
+ % A paper in the class MSR's call names, built by the e2e on paperlint's own TeX Live, that is ONE
2
+ % PAGE OVER MSR's limit through its appendix: the body ends on page 10, the references follow it
3
+ % there, and the appendix after them runs from the foot of page 10 through page 11 (rendered and
4
+ % looked at, 2026-10-05) — eleven pages holding main text. banal's count says body 9, references 2,
5
+ % and would pass it; format/page-limit counts the appendix as body and must not.
6
+ %
7
+ % The prose is one paragraph set many times; each copy carries its own number in words on every
8
+ % line, so no line repeats from page to page as a running header would.
9
+ \documentclass[10pt,conference]{IEEEtran}
10
+ \usepackage{hyperref}
11
+ \newcount\paracount
12
+ \newcommand{\n}{\romannumeral\paracount}
13
+ \newcommand{\para}{\global\advance\paracount by 1
14
+ Paragraph \n{} studies the history of a repository, and \n{} counts its commits by author \n{}
15
+ and by month \n{}, so that the measurement \n{} has a body of prose \n{} set in the two columns
16
+ \n{} of the conference format. Paragraph \n{} says nothing new, and \n{} does not need to: the
17
+ fixture \n{} is about the class, \n{} the fonts and \n{} the page count, and \n{} not about its
18
+ content. A reviewer of \n{} would find it dull, \n{} which is what a measurement \n{} should be.\par}
19
+ \newcount\loopcount
20
+ \newcommand{\paras}[1]{\loopcount=0 \loop\para\advance\loopcount by 1 \ifnum\loopcount<#1\repeat}
21
+ \newcount\bibcount
22
+ \newcommand{\entries}[1]{\bibcount=0 \loop\advance\bibcount by 1
23
+ \bibitem{r\the\bibcount} A. Author, ``Mining study \romannumeral\bibcount,'' in \emph{Proc.
24
+ Workshop}, 2024, pp. 1--10.\ifnum\bibcount<#1\repeat}
25
+ \begin{document}
26
+ \title{A Fixture Typeset in the Class the Venue Requires}
27
+ \author{\IEEEauthorblockN{Anonymous Author}\IEEEauthorblockA{Anonymous Institution}}
28
+ \maketitle
29
+ \begin{abstract}
30
+ The abstract exists so the build has the front matter an IEEE paper carries.
31
+ \end{abstract}
32
+ \section{Introduction}
33
+ \paras{24}
34
+ \section{Part Two}
35
+ \paras{24}
36
+ \section{Part Three}
37
+ \paras{24}
38
+ \section{Part Four}
39
+ \paras{24}
40
+ \section{Part Five}
41
+ \paras{24}
42
+ \begin{thebibliography}{999}
43
+ \entries{60}
44
+ \end{thebibliography}
45
+ \appendix
46
+ \section{Detailed Results}
47
+ \paras{12}
48
+ \end{document}
@@ -0,0 +1 @@
1
+ {"extends": "paperlint:msr", "kind": "technical", "identity": ["Ada Example", "adaexample", "ada@example.org", "Example University", "exampletool"]}
@@ -22,6 +22,7 @@ import assert from "node:assert/strict";
22
22
  import { existsSync, readFileSync } from "node:fs";
23
23
  import { join } from "node:path";
24
24
  import { recordCheck } from "vigiles";
25
+ import { presetsDir } from "#src/package-dirs";
25
26
 
26
27
  import { SKILLS_DIR, ROOT, load, commands, permits } from "./skill-corpus.mjs";
27
28
 
@@ -35,6 +36,16 @@ import {
35
36
 
36
37
  const PIPELINE = pipelineScripts(scriptsRoot({ env: {}, cwd: ROOT }));
37
38
 
39
+ /** How a skill names a file of the package's presets directory. */
40
+ const PRESETS_PREFIX = "presets/";
41
+
42
+ /** The preset files a skill's text names in code spans (`presets/agenticdev.md`), placeholders left out. */
43
+ export const presetRefs = (src) => [
44
+ ...new Set(
45
+ [...src.matchAll(/`(presets\/[A-Za-z0-9._-]+)`/g)].map((m) => m[1]),
46
+ ),
47
+ ];
48
+
38
49
  /**
39
50
  * Assert everything single-skill about `name`. Throws with EVERY finding, not the first.
40
51
  * Returns the number of skills checked (1) so a caller can report what it actually did.
@@ -145,6 +156,26 @@ export async function checkSkill(name) {
145
156
  }
146
157
  }
147
158
 
159
+ // ═══════════════════════════════════════════════════════════════════════════════════════════════
160
+ // 9. EVERY PRESET FILE the skill names exists in the package. Skills name a venue's card and preset
161
+ // as `presets/<name>.md` / `presets/<name>.jsonc` "in the package" — a path inside the package, the
162
+ // same in every install channel — and the cards once lived under a skill's `references/`, so a
163
+ // name that outlived a move would send the model to a file that is not there. Resolved against
164
+ // the package's presets directory (`#src/package-dirs`, the one module that knows where it is).
165
+ // Placeholders (`presets/<venue>.md`) are not names of a file and are left out.
166
+ // ═══════════════════════════════════════════════════════════════════════════════════════════════
167
+ for (const s of skills) {
168
+ for (const ref of presetRefs(s.src)) {
169
+ const abs = join(presetsDir(), ref.slice(PRESETS_PREFIX.length));
170
+ soft(() =>
171
+ assert.ok(
172
+ existsSync(abs),
173
+ `${s.name}: names \`${ref}\` in the package, and there is no such file (looked at ${abs}).`,
174
+ ),
175
+ );
176
+ }
177
+ }
178
+
148
179
  if (deferred.length) {
149
180
  const e = new Error(
150
181
  `${deferred.length} assertion(s) failed for skill "${name}":\n\n` +
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "paperlint",
3
- "version": "6.3.0",
3
+ "version": "7.1.0",
4
4
  "description": "A linter for scientific papers written in LaTeX: catches mistakes before you submit to a conference or journal.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -49,6 +49,7 @@
49
49
  "eslint-plugin-boundaries": "^7.2.0",
50
50
  "eslint-plugin-functional": "^10.0.1",
51
51
  "eslint-plugin-n": "^18.3.0",
52
+ "eslint-plugin-project-structure": "^3.14.5",
52
53
  "eslint-plugin-sonarjs": "^4.2.1",
53
54
  "prettier": "^3.8.1",
54
55
  "semantic-release": "25.0.9",
@@ -132,6 +133,11 @@
132
133
  "types": "./dist/lib/*.d.ts",
133
134
  "default": "./dist/lib/*.js"
134
135
  },
136
+ "#src/*": {
137
+ "paperlint-source": "./src/*.ts",
138
+ "types": "./dist/*.d.ts",
139
+ "default": "./dist/*.js"
140
+ },
135
141
  "#eslint-rules/*": {
136
142
  "paperlint-source": "./eslint-rules/*.ts",
137
143
  "types": "./dist/eslint-rules/*.d.ts",
@@ -6,7 +6,12 @@
6
6
  // the Conference Publishing author instructions for ACM (2026-08-25), which state ACM's own
7
7
  // requirements. A paper may extend this family directly for an ACM venue nobody has profiled:
8
8
  // page size, columns and fonts are checked; with no kinds, the page limit is not.
9
+ //
10
+ // Its card, in prose: `acm-sigconf.md` beside this file.
9
11
  {
12
+ // A template family: it names no venue, so no `name` and no `url` (the venues that extend it do).
13
+ "type": "family",
14
+
10
15
  // `tex/template` requires a paper's class to be acmart WITH `sigconf`: acmart's default format is
11
16
  // `manuscript`, a single-column layout no sigconf venue takes. Other options (review, anonymous,
12
17
  // screen, nonacm) are the paper's to add.
@@ -0,0 +1,43 @@
1
+ ---
2
+ title: "ACM acmart sigconf — template family card"
3
+ ---
4
+
5
+ # ACM `acmart` sigconf
6
+
7
+ The card of the template family `paperlint:acm-sigconf` ([`acm-sigconf.jsonc`](acm-sigconf.jsonc)).
8
+ A family is what a publisher's template decides, whatever the venue: it names no venue and has no
9
+ call for papers. A venue preset extends it and adds what its own call sets — the page limit of each
10
+ kind of paper, and the rules its producer implies. The template is
11
+ [acmart on CTAN](https://ctan.org/pkg/acmart).
12
+
13
+ A paper for an ACM venue that has no preset may extend the family directly: page size, columns and
14
+ fonts are then checked, and the page limit is not (a family has no kinds).
15
+
16
+ ## What the family encodes
17
+
18
+ - **The class**: `\documentclass[sigconf]{acmart}` — `sigconf` is required, since acmart's default
19
+ format is a single-column manuscript no sigconf venue takes. `review`, `anonymous`, `screen` and
20
+ `nonacm` are the paper's to add.
21
+ - **The page**: US letter, 8.5 × 11 in; a text block of at most 18 × 23.5 cm (7.087 × 9.252 in);
22
+ two columns.
23
+ - **The fonts**: Libertine for the text, Biolinum for the title; body text at 9 pt, references from
24
+ 7 to 9 pt (banal measures 0.3 pt high on every template, hence the 0.5 pt tolerance).
25
+ - **TeX packages** on top of the base set: acmart and everything it loads itself — libertine,
26
+ inconsolata and newtx (if any one is missing, acmart silently falls back to Computer Modern), the
27
+ rest found by building and installing what was missing.
28
+
29
+ The numbers were measured on acmart sigconf builds (banal and pdf.js, 2026-08-26) and quoted from
30
+ the Conference Publishing author instructions for ACM (2026-08-25).
31
+
32
+ ## What the family resolves to
33
+
34
+ <!-- paperlint:preset-rules -->
35
+ <!-- prettier-ignore-start -->
36
+ <!-- Generated from acm-sigconf.jsonc by `npx eslint --fix` (rule preset/card-rules). Edit the preset, not this section. -->
37
+
38
+ **`paperlint:acm-sigconf`** — template family, no venue of its own · extended by `paperlint:agenticdev`, `paperlint:aisec`
39
+
40
+ No preset of this chain sets a rule: under it, every rule keeps paperlint's default.
41
+
42
+ <!-- prettier-ignore-end -->
43
+ <!-- /paperlint:preset-rules -->
@@ -1,9 +1,14 @@
1
1
  // AgenticDev (an ASE workshop) — a VENUE preset over the ACM sigconf family. Prose about the venue
2
- // is in agenticdev.md nearby. Everything the ACM template decides (page size, columns, fonts, font
2
+ // is in its card, agenticdev.md beside this file (every preset has one: `npm run lint` fails
3
+ // without it, and the card's rules section is generated from this file). Everything the ACM template decides (page size, columns, fonts, font
3
4
  // sizes, TeX packages) comes from acm-sigconf.jsonc; this file adds what AgenticDev's call for
4
5
  // papers sets.
5
6
  // Source for the numbers: the Conference Publishing author instructions 2026-08-25.
6
7
  {
8
+ "type": "venue",
9
+ "name": "AgenticDev",
10
+ // The workshop's call for papers on the ASE 2026 site.
11
+ "url": "https://conf.researchr.org/home/ase-2026/agenticdev-2026",
7
12
  "extends": "paperlint:acm-sigconf",
8
13
 
9
14
  // What the venue is called in a paper's text (tex/venue-leftover). Its parent conference, ASE,
@@ -63,12 +68,28 @@
63
68
 
64
69
  // The proceedings are produced by Conference Publishing Consulting — agenticdev.md takes its
65
70
  // numbers from their author instructions — which require "balanced columns on the last page, if
66
- // the page is not filled" and sent an accepted camera-ready back for it on 2026-08-29, the day
67
- // after AgenticDev's camera-ready deadline ("Please correct the last page balancing"). So every
68
- // AgenticDev paper gets the optional rule; a paper can still turn it off in its own
69
- // paperlint.json. 120 pt is the rule's default, measured: the balanced build ended 2.7 pt apart,
70
- // the returned one 321.4 pt apart (docs/optional-rules.md).
71
+ // the page is not filled", checked before the proceedings are produced: "problem papers are sent
72
+ // back to the authors". So every AgenticDev paper gets the optional rule; a paper can still turn
73
+ // it off in its own paperlint.json. 120 pt is the rule's default, measured: a balanced build ended
74
+ // 2.7 pt apart, an unbalanced one 321.4 pt apart (docs/optional-rules.md).
75
+ //
76
+ // The same vendor asks for headline style in the title and in every heading. Its help page
77
+ // (https://www.conference-publishing.com/Help.php) defines it: «Headline-Style Capitalization
78
+ // (according to the Chicago Manual of Style, Sections 8.157, 8.158, and 8.159)», with the word
79
+ // lists the rule's chicago-headline style judges by. Its instructions for an event
80
+ // (https://www.conference-publishing.com/Instructions.php?Event=ITICSE18) set both scopes:
81
+ // «The title should use headline-style capitalization (e.g., 'The Best POPL Paper of All Time')»
82
+ // and «All levels of headings use headline-style capitalization.» Its checklist names it, and
83
+ // papers that miss it are returned to their authors. The rule lives here and not in acm-sigconf: ACM's own
84
+ // pages and the other vendors that produce ACM proceedings were not read, and an error on a
85
+ // requirement nobody has seen would block correct papers. A venue whose author kit names the
86
+ // same authority adds the same line; one that names another (APA, IEEE, Springer) waits for that
87
+ // style (docs/rules/tex/heading-case.md, «Adding a style»).
71
88
  "rules": {
72
89
  "pdf/last-page-balance": ["error", { "tolerancePt": 120 }],
90
+ "tex/heading-case": [
91
+ "error",
92
+ { "title": "chicago-headline", "headings": "chicago-headline" },
93
+ ],
73
94
  },
74
95
  }
@@ -0,0 +1,151 @@
1
+ ---
2
+ title: "AgenticDev @ ASE — venue card"
3
+ ---
4
+
5
+ # AgenticDev @ ASE
6
+
7
+ The card of the venue preset `paperlint:agenticdev` ([`agenticdev.jsonc`](agenticdev.jsonc)): what
8
+ the venue asks for, in prose. The numbers a machine checks live in the preset; the section at the
9
+ end is generated from it. The `submit-paper` skill reads this card for the venue's specifics.
10
+
11
+ **Re-verify the call for papers every year**
12
+ ([conf.researchr.org/home/ase-2026/agenticdev-2026](https://conf.researchr.org/home/ase-2026/agenticdev-2026)):
13
+ dates, limits and tracks change between editions.
14
+
15
+ ## The venue (2026 edition)
16
+
17
+ - **Venue**: Workshop on Agentic AI for Next-Generation Software Development, co-located with
18
+ **ASE** (Automated Software Engineering), Munich, October 2026.
19
+ - **Portal**: HotCRP, `https://agenticdev2026.hotcrp.com/paper/new`.
20
+ - **Deadline**: July 15, 2026, AoE. Notification August 21, camera-ready August 28.
21
+ - **Format**: ACM `\documentclass[sigconf,review,anonymous]{acmart}` → **double-blind**. Build with
22
+ `pdflatex; bibtex; pdflatex; pdflatex`; add `\microtypesetup{expansion=false}` (the most common
23
+ acmart crash).
24
+ - **No supplementary-material field** on the HotCRP form (Title, Submission, Abstract, Authors, ACM
25
+ corresponding, Contacts, PC conflicts). Host the artifact externally (an anonymized view-only
26
+ link) and `\url{}` it in the paper's Availability section; see `submit-paper` §2.
27
+ - **Archival**: accepted papers go into the **ASE workshop proceedings**, with a DOI; selected
28
+ papers are invited to a journal special issue. ASE's publisher **alternates by year** — ASEW '24
29
+ ACM (`10.1145/3691621.*`), ASE 2025 Workshops IEEE (`csdl/proceedings/asew/2025`), the main track
30
+ likewise ('22 ACM, '23 IEEE, '24 ACM, '25 IEEE). There is no dual ACM DL / IEEE Xplore
31
+ publication; the `10.5555` prefix in the ACM DL is a Guide catalog entry, not an ACM
32
+ publication. Confirm the year's publisher with the chairs before paying an article processing
33
+ charge.
34
+
35
+ ## Paper kinds and limits
36
+
37
+ The preset's `format.kinds`; a paper names its own in its `paperlint.json` (`kind`).
38
+
39
+ | kind | body pages | extra pages of references | what it is |
40
+ | ------- | ---------: | ------------------------: | --------------------- |
41
+ | `full` | 10 | 2 | mature work |
42
+ | `short` | 5 | 2 | WIP, vision, position |
43
+ | `demo` | 5 | 2 | demo or tool |
44
+
45
+ At camera-ready the limits stay the same: a sixth page taken by the bibliography of a short paper
46
+ still counts within them.
47
+
48
+ ## What else the preset encodes
49
+
50
+ - **The ACM template**, through `extends: paperlint:acm-sigconf`: letter paper, two columns,
51
+ Libertine at 9 pt, acmart's TeX packages ([`acm-sigconf.md`](acm-sigconf.md)).
52
+ - **Balanced columns on the last page** (`pdf/last-page-balance`, 120 pt tolerance). The proceedings
53
+ are produced by Conference Publishing Consulting, whose author instructions require "balanced
54
+ columns on the last page, if the page is not filled"; problem papers are sent back.
55
+ - **Headline-style capitalization** in the title and every heading (`tex/heading-case`, the
56
+ `chicago-headline` style). The same producer's instructions: «The title should use headline-style
57
+ capitalization» and «All levels of headings use headline-style capitalization», defined on its
58
+ help page as Chicago Manual of Style §§8.157–8.159.
59
+ - **Names**: `AgenticDev` is what `tex/venue-leftover` looks for in another venue's paper; ASE is
60
+ left out on purpose — a three-letter acronym too many sentences use for other things.
61
+ - **The talk** (`talk`): remote presentation by video only, with the numbers below.
62
+
63
+ ## Naming the venue correctly
64
+
65
+ AgenticDev is a workshop of ASE 2026, listed on ASE's own co-located events page; it is **not** the
66
+ ASE main track, which has its own program, committee and selectivity.
67
+
68
+ | write | do not write |
69
+ | ----------------------------------------------------- | ------------------------------------ |
70
+ | "accepted at AgenticDev 2026, a workshop of ASE 2026" | "accepted at ASE 2026" |
71
+ | "workshop paper, ASE 2026 workshop proceedings" | "published at a CORE A\* conference" |
72
+ | "ASE is CORE A\*; AgenticDev is one of its workshops" | "this paper is CORE A\*" |
73
+
74
+ ## Registration
75
+
76
+ Registration of at least one author is a condition of appearing in the proceedings, not only of
77
+ attending. 2026: article processing charge $350 (ACM is fully open access since 2026-01-01), and
78
+ workshop-day registration (non-member) €350 until 08-31, €410 until 09-20, €460 on site.
79
+
80
+ ## PC members (the "PC conflicts" field) — 2026
81
+
82
+ Andrea Rosani (Free U Bozen/Bolzano) · Giuseppe Di Fatta (Free U Bozen/Bolzano) · Jean Marie Mottu
83
+ (Nantes U) · Paolo Papotti (Eurecom) · Simos Gerasimou (Cyprus U of Technology). The list changes
84
+ every year — read the current PC page.
85
+
86
+ ## Topic fit
87
+
88
+ Trustworthiness, verification and validation of AI agents; benchmarking and empirical evaluation;
89
+ integration into developer workflows; agent-based coding and testing.
90
+
91
+ ## Camera-ready (2026 edition)
92
+
93
+ The ACM mechanics are the same for every ACM venue and live one level up, in the `submit-paper`
94
+ skill's `references/publishers/acm.md` (eRights first, the preamble, the copyright block, CCS
95
+ concepts, source files). AgenticDev's own:
96
+
97
+ - **Deadline**: August 28, 2026, 2 PM AoE.
98
+ - **ACM ISBN**: `979-8-4007-2985-0/26/10`.
99
+ - **Copyright block**: `AgenticDev '26, October 12–16, 2026, Munich, Germany`.
100
+ - **No longer double-blind**: the `review` and `anonymous` class options come off for the final.
101
+ - **Title changes are allowed** — the portal asks for the title "exactly as it should appear in the
102
+ ACM DL". Decide before eRights.
103
+
104
+ ## The talk (2026 edition)
105
+
106
+ **The deadline and the upload channel come from the parent conference's not-in-person page, not
107
+ from this card** — look it up again for each edition.
108
+
109
+ Remote presentation is allowed, but there is no live slot: the workshop adopts ASE 2026's
110
+ [Not-in-Person Presentations](https://conf.researchr.org/track/ase-2026/ase-2026-not-in-person-presentations)
111
+ policy:
112
+
113
+ > ASE 2026 does not provide presentation slots for papers that are not presented in-person by one
114
+ > of the authors.
115
+
116
+ The author sends instead:
117
+
118
+ | artifact | what the page says | deadline (2026) |
119
+ | --------- | --------------------------------------------------------------------------------------------------------------------------------- | ----------------- |
120
+ | video | "made available via a dedicated page on the conference website (recommendation: 10 min duration, mp4 file format, HD resolution)" | 2026-10-08 |
121
+ | one-slide | "shown during one of the conference sessions"; no size or format stated | same as the video |
122
+ | poster | optional for the workshop; ASE prints it | 2026-09-21 |
123
+
124
+ **Where to upload**: "find the submission link on the submission page for your paper (see
125
+ author-kit e-mail from Conference Publishing Consulting)" — the same personal page as the
126
+ camera-ready, block "Optional Archive/Appendix/Video/Picture Submissions … Submit Material to ACM".
127
+ "All submitted material will be published in the ACM DL if the publishing-rights agreement gives
128
+ permission for this", so tick permission for auxiliary material in eRights.
129
+
130
+ **The slot**: per the chairs' email to all authors (2026-09-29), a short paper gets 10 minutes in
131
+ total, approximately 6–7 for the presentation and 3–4 for questions. The full-paper slot was not
132
+ stated, so the preset gives `talk` numbers for `short` only. No source requires a live answer to
133
+ questions; put a contact address on the video's last slide and on the one-slide.
134
+
135
+ The `talk/*` rules check the finished files against these numbers: `docs/talk.md`.
136
+
137
+ ## What the preset resolves to
138
+
139
+ <!-- paperlint:preset-rules -->
140
+ <!-- prettier-ignore-start -->
141
+ <!-- Generated from agenticdev.jsonc by `npx eslint --fix` (rule preset/card-rules). Edit the preset, not this section. -->
142
+
143
+ **`paperlint:agenticdev`** — venue preset for AgenticDev · call for papers: <https://conf.researchr.org/home/ase-2026/agenticdev-2026> · extends `paperlint:acm-sigconf`
144
+
145
+ | rule | severity | options | set in |
146
+ | --- | --- | --- | --- |
147
+ | [`pdf/last-page-balance`](../docs/rules.md) | error | `{"tolerancePt":120}` | this preset |
148
+ | [`tex/heading-case`](../docs/rules/tex/heading-case.md) | error | `{"title":"chicago-headline","headings":"chicago-headline"}` | this preset |
149
+
150
+ <!-- prettier-ignore-end -->
151
+ <!-- /paperlint:preset-rules -->
@@ -19,7 +19,13 @@
19
19
  // what refuses the upload.
20
20
  //
21
21
  // THE REVIEW IS DOUBLE-BLIND: `"blind":true` in the same portal data, and the call above.
22
+ //
23
+ // Its card, in prose: `aidc.md` beside this file.
22
24
  {
25
+ "type": "venue",
26
+ "name": "AIDC",
27
+ // The call quoted above.
28
+ "url": "https://aidcworkshop.github.io/",
23
29
  "extends": "paperlint:ieee-conference",
24
30
 
25
31
  // «Submissions must be properly anonymized for double-blind review.» (the call above), and
@@ -0,0 +1,75 @@
1
+ ---
2
+ title: "AIDC @ IEEE ACSAC — venue card"
3
+ ---
4
+
5
+ # AIDC @ IEEE ACSAC
6
+
7
+ The card of the venue preset `paperlint:aidc` ([`aidc.jsonc`](aidc.jsonc)): what the venue asks
8
+ for, in prose. The numbers a machine checks live in the preset; the section at the end is generated
9
+ from it. The `submit-paper` skill reads this card for the venue's specifics.
10
+
11
+ **Re-verify the call for papers every year** ([aidcworkshop.github.io](https://aidcworkshop.github.io/)).
12
+
13
+ ## The venue (2026 edition, the first)
14
+
15
+ - **Venue**: Workshop on Agentic AI in Offensive and Defensive Cyber Operations, held at
16
+ **IEEE ACSAC 2026** (Annual Computer Security Applications Conference).
17
+ - **Format**, verbatim from the call: «All submitted papers must be prepared in US Letter size, not
18
+ A4, using the double-column IEEE conference format. This requirement will be strictly enforced.»
19
+ and «LaTeX submissions must use the IEEEtran.cls version 1.8b template with the
20
+ \documentclass[conference,compsoc]{IEEEtran} document class option.»
21
+ - **Double-blind**: «Submissions must be properly anonymized for double-blind review.», and
22
+ `"blind":true` in the portal's data.
23
+ - **Portal**: HotCRP at `https://aidc.submit.acsac.org`.
24
+ - 🔴 **The deadline people get wrong**: the HotCRP portal closes 2026-10-02 11:59:59 UTC
25
+ (`"sub":1790942399` on `https://aidc.submit.acsac.org/deadlines`), while the workshop page says
26
+ «October 2, 2026 (Anywhere-on-Earth, AoE)» — a day later. The portal is what refuses the upload.
27
+
28
+ ## Paper kinds and limits
29
+
30
+ | kind | body pages | what it is |
31
+ | --------- | ---------: | ------------------------------------------------------------------------------------------------------------- |
32
+ | `regular` | 12 | «Regular technical papers: Up to 12 pages excluding references and appendices.» |
33
+ | `short` | 6 | «Short position papers or work-in-progress (WIP) papers: Up to 6 pages, excluding references and appendices.» |
34
+
35
+ References, appendices and the LLM Usage Statement are unlimited. 🔴 **The body is counted up to
36
+ where the references start** (`format.body_ends_at: "references"`), not by banal's count: banal
37
+ calls any page with non-bibliography text body, so an LLM Usage Statement or an appendix placed
38
+ before the references would push a paper whose body ends at the foot of page 12 to «body 13».
39
+ See `docs/rules/format/page-limit.md`.
40
+
41
+ ## What else the preset encodes
42
+
43
+ - **The IEEE template**, through `extends: paperlint:ieee-conference` — letter paper, two columns,
44
+ Times at 10 pt, IEEEtran's TeX packages ([`ieee-conference.md`](ieee-conference.md)) — with the
45
+ `compsoc` option required in the class line (`tex/template`) and compsoc's text block,
46
+ 7.00 × 9.02 in.
47
+ - **The LLM Usage Statement** (`required_sections`). The call: «Authors must follow the ACSAC AI
48
+ Usage Policy for all workshop submissions.» The policy (`https://www.acsac.org/2026/submissions/ai/`):
49
+ «If LLMs are used, authors must include a separate, clearly marked section titled "LLM Usage
50
+ Statement" at the end of the paper. This section does not count towards the page limit.» and
51
+ «Failure to comply with these requirements is grounds for desk rejection without further
52
+ review.» `tex/required-section` cannot know whether LLMs were used, so it requires the section
53
+ always — an author who used none says so in it. A bold paragraph is not a section with this
54
+ title and does not count.
55
+ - **Double-blind review** (`blind`), so `anonymity/identity` checks the PDF against the paper's
56
+ declared `identity`.
57
+ - **Where submissions go** (`portal`): `paperlint submission` reads and updates a paper's
58
+ submission through HotCRP's API on that site.
59
+ - **Names**: `AIDC` and `ACSAC`, what `tex/venue-leftover` looks for in another venue's paper.
60
+ - **The register of the body** (`register`): the workshop's first edition has no accepted papers,
61
+ so the bands of `tex/contrast-frames`, `tex/claim-emphasis` and `tex/relation-markers` are set by
62
+ five accepted ACSAC papers on the same template, in `fixtures/accepted-papers/`.
63
+
64
+ ## What the preset resolves to
65
+
66
+ <!-- paperlint:preset-rules -->
67
+ <!-- prettier-ignore-start -->
68
+ <!-- Generated from aidc.jsonc by `npx eslint --fix` (rule preset/card-rules). Edit the preset, not this section. -->
69
+
70
+ **`paperlint:aidc`** — venue preset for AIDC · call for papers: <https://aidcworkshop.github.io/> · extends `paperlint:ieee-conference`
71
+
72
+ No preset of this chain sets a rule: under it, every rule keeps paperlint's default.
73
+
74
+ <!-- prettier-ignore-end -->
75
+ <!-- /paperlint:preset-rules -->
@@ -1,6 +1,6 @@
1
1
  // AISec @ ACM CCS — a VENUE preset over the ACM sigconf family. Data for the `pdf/*` rules over
2
2
  // `_build/paper.facts.json`.
3
- // Prose about the venue and tracks is in `aisec.md` nearby.
3
+ // Prose about the venue and tracks is in its card, `aisec.md` beside this file.
4
4
  //
5
5
  // PAGE LIMITS — verbatim from https://aisec.cc/ (verified 2026-08-26, not from memory):
6
6
  // «Submitted papers must be at most 10 pages long in double-column ACM format---excluding
@@ -23,6 +23,10 @@
23
23
  // but that is the main conference). Turn pdf/last-page-balance on in the paper's paperlint.json if
24
24
  // the camera-ready instructions ask for it.
25
25
  {
26
+ "type": "venue",
27
+ "name": "AISec",
28
+ // The call quoted above.
29
+ "url": "https://aisec.cc/",
26
30
  "extends": "paperlint:acm-sigconf",
27
31
 
28
32
  // What the venue is called in a paper's text (tex/venue-leftover): the workshop, and the