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.
- package/CONTRIBUTING.md +4 -2
- package/README.md +10 -3
- package/dist/adapters/hotcrp/index.d.ts +7 -0
- package/dist/adapters/hotcrp/index.d.ts.map +1 -0
- package/dist/adapters/hotcrp/index.js +7 -0
- package/dist/adapters/hotcrp/index.js.map +1 -0
- package/dist/adapters/hotcrp/portal.io.d.ts +20 -0
- package/dist/adapters/hotcrp/portal.io.d.ts.map +1 -0
- package/dist/adapters/hotcrp/portal.io.js +90 -0
- package/dist/adapters/hotcrp/portal.io.js.map +1 -0
- package/dist/adapters/hotcrp/response.d.ts +13 -0
- package/dist/adapters/hotcrp/response.d.ts.map +1 -0
- package/dist/adapters/hotcrp/response.js +138 -0
- package/dist/adapters/hotcrp/response.js.map +1 -0
- package/dist/adapters/latex/conditionals.d.ts +21 -0
- package/dist/adapters/latex/conditionals.d.ts.map +1 -0
- package/dist/adapters/latex/conditionals.js +75 -0
- package/dist/adapters/latex/conditionals.js.map +1 -0
- package/dist/adapters/latex/headings.d.ts +10 -0
- package/dist/adapters/latex/headings.d.ts.map +1 -0
- package/dist/adapters/latex/headings.js +129 -0
- package/dist/adapters/latex/headings.js.map +1 -0
- package/dist/adapters/latex/index.d.ts +1 -0
- package/dist/adapters/latex/index.d.ts.map +1 -1
- package/dist/adapters/latex/index.js +3 -0
- package/dist/adapters/latex/index.js.map +1 -1
- package/dist/adapters/latex/parse.d.ts +1 -1
- package/dist/adapters/latex/parse.d.ts.map +1 -1
- package/dist/adapters/latex/parse.js +3 -2
- package/dist/adapters/latex/parse.js.map +1 -1
- package/dist/build.d.ts +1 -1
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +1 -1
- package/dist/build.js.map +1 -1
- package/dist/cli.d.ts +4 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +126 -37
- package/dist/cli.js.map +1 -1
- package/dist/domain/heading-case.d.ts +100 -0
- package/dist/domain/heading-case.d.ts.map +1 -0
- package/dist/domain/heading-case.js +365 -0
- package/dist/domain/heading-case.js.map +1 -0
- package/dist/domain/result.d.ts +4 -0
- package/dist/domain/result.d.ts.map +1 -1
- package/dist/domain/result.js +2 -0
- package/dist/domain/result.js.map +1 -1
- package/dist/domain/submission.d.ts +106 -0
- package/dist/domain/submission.d.ts.map +1 -0
- package/dist/domain/submission.js +39 -0
- package/dist/domain/submission.js.map +1 -0
- package/dist/domain/tex-document.d.ts +32 -0
- package/dist/domain/tex-document.d.ts.map +1 -1
- package/dist/domain/tex-document.js +11 -0
- package/dist/domain/tex-document.js.map +1 -1
- package/dist/domain/venue-name.d.ts +38 -0
- package/dist/domain/venue-name.d.ts.map +1 -0
- package/dist/domain/venue-name.js +71 -0
- package/dist/domain/venue-name.js.map +1 -0
- package/dist/eslint-rules/latex-language.d.ts.map +1 -1
- package/dist/eslint-rules/latex-language.js +16 -3
- package/dist/eslint-rules/latex-language.js.map +1 -1
- package/dist/facts-file.d.ts +3 -3
- package/dist/facts-file.d.ts.map +1 -1
- package/dist/facts-file.js +3 -3
- package/dist/facts-file.js.map +1 -1
- package/dist/folder-venue-rule.d.ts +51 -0
- package/dist/folder-venue-rule.d.ts.map +1 -0
- package/dist/folder-venue-rule.js +96 -0
- package/dist/folder-venue-rule.js.map +1 -0
- package/dist/heading-case.d.ts +48 -0
- package/dist/heading-case.d.ts.map +1 -0
- package/dist/heading-case.js +191 -0
- package/dist/heading-case.js.map +1 -0
- package/dist/init.d.ts +6 -0
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +3 -3
- package/dist/init.js.map +1 -1
- package/dist/lib/paper-config.d.ts.map +1 -1
- package/dist/lib/paper-config.js +5 -1
- package/dist/lib/paper-config.js.map +1 -1
- package/dist/new-paper.d.ts +19 -5
- package/dist/new-paper.d.ts.map +1 -1
- package/dist/new-paper.js +23 -4
- package/dist/new-paper.js.map +1 -1
- package/dist/paper-settings.d.ts +3 -0
- package/dist/paper-settings.d.ts.map +1 -1
- package/dist/paper-settings.js +20 -4
- package/dist/paper-settings.js.map +1 -1
- package/dist/ports/latex.d.ts +7 -1
- package/dist/ports/latex.d.ts.map +1 -1
- package/dist/ports/submission-portal.d.ts +19 -0
- package/dist/ports/submission-portal.d.ts.map +1 -0
- package/dist/ports/submission-portal.js +2 -0
- package/dist/ports/submission-portal.js.map +1 -0
- package/dist/preset-card-rule.d.ts +100 -0
- package/dist/preset-card-rule.d.ts.map +1 -0
- package/dist/preset-card-rule.js +221 -0
- package/dist/preset-card-rule.js.map +1 -0
- package/dist/presets.d.ts +43 -2
- package/dist/presets.d.ts.map +1 -1
- package/dist/presets.js +130 -63
- package/dist/presets.js.map +1 -1
- package/dist/rules-config.js +1 -1
- package/dist/submission.d.ts +61 -0
- package/dist/submission.d.ts.map +1 -0
- package/dist/submission.js +211 -0
- package/dist/submission.js.map +1 -0
- package/dist/tex-requirements.d.ts +36 -3
- package/dist/tex-requirements.d.ts.map +1 -1
- package/dist/tex-requirements.js +30 -2
- package/dist/tex-requirements.js.map +1 -1
- package/dist/tex-venue-rules.d.ts +7 -8
- package/dist/tex-venue-rules.d.ts.map +1 -1
- package/dist/tex-venue-rules.js +10 -14
- package/dist/tex-venue-rules.js.map +1 -1
- package/dist/types.d.ts +13 -0
- package/dist/types.d.ts.map +1 -1
- package/docs/configuration.md +30 -11
- package/docs/optional-rules.md +4 -3
- package/docs/rules/format/page-limit.md +1 -1
- package/docs/rules/paper/folder-venue-leftover.md +104 -0
- package/docs/rules/talk/captions-cover.md +1 -1
- package/docs/rules/talk/duration-floor.md +1 -1
- package/docs/rules/talk/profile.md +1 -1
- package/docs/rules/tex/heading-case.md +424 -0
- package/docs/rules.md +64 -53
- package/docs/skills.md +5 -4
- package/docs/submission.md +64 -0
- package/docs/talk.md +1 -1
- package/eslint-rules/latex-language.test.mjs +12 -0
- package/eslint-rules/latex-language.ts +17 -4
- package/eslint-rules/paper-typography.test.mjs +12 -0
- package/eslint.config.mjs +59 -1
- package/fixtures/build-e2e/acmart/paper.tex +1 -1
- package/fixtures/build-e2e/fallback/expect.json +3 -3
- package/lib/paper-config.ts +6 -1
- package/lib/skill-checks.d.mts +7 -0
- package/lib/skill-checks.mjs +31 -0
- package/lib/skill-trigger-cases.mjs +11 -0
- package/package.json +8 -2
- package/presets/acm-sigconf.jsonc +5 -0
- package/presets/acm-sigconf.md +43 -0
- package/presets/agenticdev.jsonc +27 -6
- package/presets/agenticdev.md +151 -0
- package/presets/aidc.jsonc +12 -0
- package/presets/aidc.md +75 -0
- package/presets/aisec.jsonc +5 -1
- package/presets/aisec.md +117 -0
- package/presets/ieee-conference.jsonc +5 -0
- package/presets/ieee-conference.md +38 -0
- package/presets/realm.jsonc +7 -2
- package/presets/realm.md +166 -0
- package/presets/tex/agenticdev.tex +1 -1
- package/presets/tex-base.jsonc +6 -0
- package/presets/tex-base.md +30 -0
- package/presets/venue-profile.schema.json +57 -2
- package/skills/find-venue/SKILL.md +6 -5
- package/skills/find-venue/SKILL.md.spec.ts +5 -4
- package/skills/paper-pipeline/SKILL.md +5 -6
- package/skills/paper-pipeline/SKILL.md.spec.ts +4 -5
- package/skills/paper-pipeline/paper-pipeline.harness.mjs +4 -0
- package/skills/paper-pipeline/references/acl-venue-rules.md +1 -1
- package/skills/study-accepted-papers/SKILL.md +3 -3
- package/skills/study-accepted-papers/SKILL.md.spec.ts +2 -2
- package/skills/submission-portal/SKILL.md +69 -0
- package/skills/submission-portal/SKILL.md.spec.ts +71 -0
- package/skills/submission-portal/submission-portal.eval.mjs +15 -0
- package/skills/submission-portal/submission-portal.test.ts +81 -0
- package/skills/submit-paper/SKILL.md +27 -22
- package/skills/submit-paper/SKILL.md.spec.ts +26 -21
- package/skills/submit-paper/references/publishers/acm.md +1 -1
- package/src/adapters/hotcrp/cassette/README.md +24 -0
- package/src/adapters/hotcrp/cassette/get-noauth.json +10 -0
- package/src/adapters/hotcrp/cassette/get-paper.json +39 -0
- package/src/adapters/hotcrp/cassette/post-dot.json +21 -0
- package/src/adapters/hotcrp/cassette/post-ok.json +12 -0
- package/src/adapters/hotcrp/index.ts +11 -0
- package/src/adapters/hotcrp/portal.io.ts +130 -0
- package/src/adapters/hotcrp/portal.test.ts +503 -0
- package/src/adapters/hotcrp/response.ts +181 -0
- package/src/adapters/latex/conditionals.ts +130 -0
- package/src/adapters/latex/headings.ts +163 -0
- package/src/adapters/latex/index.test.ts +65 -0
- package/src/adapters/latex/index.ts +3 -0
- package/src/adapters/latex/parse.ts +3 -2
- package/src/build.ts +2 -2
- package/src/cli.test.ts +155 -3
- package/src/cli.ts +161 -25
- package/src/domain/heading-case.test.ts +660 -0
- package/src/domain/heading-case.ts +538 -0
- package/src/domain/result.test.ts +9 -1
- package/src/domain/result.ts +5 -0
- package/src/domain/submission.test.ts +45 -0
- package/src/domain/submission.ts +141 -0
- package/src/domain/tex-document.ts +36 -0
- package/src/domain/venue-name.test.ts +121 -0
- package/src/domain/venue-name.ts +129 -0
- package/src/facts-file.test.ts +4 -4
- package/src/facts-file.ts +6 -6
- package/src/folder-venue-rule.test.ts +182 -0
- package/src/folder-venue-rule.ts +141 -0
- package/src/heading-case.test.ts +500 -0
- package/src/heading-case.ts +275 -0
- package/src/init.test.ts +22 -0
- package/src/init.ts +9 -2
- package/src/new-paper.harness.mjs +11 -9
- package/src/new-paper.test.ts +135 -10
- package/src/new-paper.ts +38 -7
- package/src/paper-settings-commands.test.ts +25 -10
- package/src/paper-settings.test.ts +12 -1
- package/src/paper-settings.ts +25 -5
- package/src/parse-args.test.ts +19 -0
- package/src/ports/latex.ts +7 -0
- package/src/ports/submission-portal.ts +26 -0
- package/src/preset-card-rule.test.ts +266 -0
- package/src/preset-card-rule.ts +384 -0
- package/src/presets.test.ts +212 -37
- package/src/presets.ts +183 -71
- package/src/rule-cases.test.ts +147 -42
- package/src/rules-config.ts +1 -1
- package/src/submission.test.ts +497 -0
- package/src/submission.ts +311 -0
- package/src/talk-rules.test.ts +6 -3
- package/src/tex-requirements.harness.ts +25 -11
- package/src/tex-requirements.test.ts +127 -1
- package/src/tex-requirements.ts +78 -8
- package/src/tex-venue-rules.test.ts +36 -22
- package/src/tex-venue-rules.ts +14 -26
- package/src/types.ts +13 -0
- package/src/venue-rules.test.ts +7 -6
- package/templates/paper/paper.tex +1 -1
- package/skills/submit-paper/references/venues/agenticdev.md +0 -171
- package/skills/submit-paper/references/venues/aisec.md +0 -105
- package/skills/submit-paper/references/venues/realm.md +0 -155
package/src/tex-requirements.ts
CHANGED
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
type VenueTalk,
|
|
35
35
|
type VenueTalkJson,
|
|
36
36
|
} from "./domain/talk.ts";
|
|
37
|
+
import type { VenuePortal } from "./domain/submission.ts";
|
|
37
38
|
|
|
38
39
|
/** CTAN package name → the names that prove it is installed. */
|
|
39
40
|
export type PackageProofs = Readonly<Record<string, readonly string[]>>;
|
|
@@ -164,15 +165,28 @@ export interface RequiredSection {
|
|
|
164
165
|
readonly position: "last" | null;
|
|
165
166
|
}
|
|
166
167
|
|
|
168
|
+
/**
|
|
169
|
+
* What a preset file IS, as its `type` declares it. A venue names itself and its call for papers; a
|
|
170
|
+
* template family and the base set name no venue, so they cannot carry either — the union has no
|
|
171
|
+
* field to put them in, the way the schema refuses them.
|
|
172
|
+
*/
|
|
173
|
+
export type PresetIdentity =
|
|
174
|
+
| { readonly type: "venue"; readonly name: string; readonly url: string }
|
|
175
|
+
| { readonly type: "family" }
|
|
176
|
+
| { readonly type: "base" };
|
|
177
|
+
|
|
178
|
+
/** A preset's kind of file: `venue`, `family` or `base`. */
|
|
179
|
+
export type PresetType = PresetIdentity["type"];
|
|
180
|
+
|
|
167
181
|
/**
|
|
168
182
|
* One preset FILE, parsed — before its `extends` chain is resolved (`src/presets.ts` does that).
|
|
169
|
-
* A preset is a venue
|
|
183
|
+
* A preset is a venue, a template family, or the TeX base set (`identity`).
|
|
170
184
|
*/
|
|
171
185
|
export interface PresetFile {
|
|
186
|
+
/** What the file is, and for a venue, its name and call for papers. */
|
|
187
|
+
readonly identity: PresetIdentity;
|
|
172
188
|
/** The preset this one builds on: `paperlint:<name>` or a relative path. */
|
|
173
189
|
readonly extends: string | null;
|
|
174
|
-
/** A display name for messages; the file name otherwise. */
|
|
175
|
-
readonly name: string | null;
|
|
176
190
|
/** The `\\documentclass` the venue's template uses, as the file spells it; null when it names none. */
|
|
177
191
|
readonly template: string | null;
|
|
178
192
|
/** Other names the venue goes by in a paper's text; empty when the file names none. */
|
|
@@ -193,6 +207,8 @@ export interface PresetFile {
|
|
|
193
207
|
readonly registerAnchors: readonly RegisterAnchor[] | null;
|
|
194
208
|
/** What the venue asks a presenter to send; null when the file has no `talk` block. */
|
|
195
209
|
readonly talk: VenueTalk | null;
|
|
210
|
+
/** Where the venue takes submissions (`paperlint submission`); null when the file does not say. */
|
|
211
|
+
readonly portal: VenuePortal | null;
|
|
196
212
|
}
|
|
197
213
|
|
|
198
214
|
type KindsJson = Readonly<
|
|
@@ -214,10 +230,19 @@ interface FormatJson {
|
|
|
214
230
|
readonly kinds?: KindsJson;
|
|
215
231
|
}
|
|
216
232
|
|
|
217
|
-
/**
|
|
218
|
-
|
|
233
|
+
/**
|
|
234
|
+
* The preset's JSON after the schema accepted it — the shape `venue-profile.schema.json` allows,
|
|
235
|
+
* the identity included: a venue has its `name` and `url`, a family and the base set have neither.
|
|
236
|
+
*/
|
|
237
|
+
type PresetJson = PresetBodyJson &
|
|
238
|
+
(
|
|
239
|
+
| { readonly type: "venue"; readonly name: string; readonly url: string }
|
|
240
|
+
| { readonly type: "family" | "base" }
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
/** Every key of a preset but its identity. */
|
|
244
|
+
interface PresetBodyJson {
|
|
219
245
|
readonly extends?: string;
|
|
220
|
-
readonly name?: string;
|
|
221
246
|
readonly template?: string;
|
|
222
247
|
readonly aliases?: readonly string[];
|
|
223
248
|
readonly blind?: boolean;
|
|
@@ -237,6 +262,7 @@ interface PresetJson {
|
|
|
237
262
|
} & Readonly<Record<RegisterMeasureName, number>>)[];
|
|
238
263
|
};
|
|
239
264
|
readonly talk?: VenueTalkJson;
|
|
265
|
+
readonly portal?: VenuePortal;
|
|
240
266
|
}
|
|
241
267
|
|
|
242
268
|
/** An optional field as the typed preset holds it: absent is null. */
|
|
@@ -278,6 +304,46 @@ const sectionsOf = (
|
|
|
278
304
|
? null
|
|
279
305
|
: r.map((x) => ({ title: x.title, position: orNull(x.position) }));
|
|
280
306
|
|
|
307
|
+
/** The identity a preset's `type` declares. Pure. */
|
|
308
|
+
const identityOf = (j: PresetJson): PresetIdentity =>
|
|
309
|
+
j.type === "venue"
|
|
310
|
+
? { type: "venue", name: j.name, url: j.url }
|
|
311
|
+
: { type: j.type };
|
|
312
|
+
|
|
313
|
+
/** One ajv error, as far as the hints read it. */
|
|
314
|
+
interface SchemaError {
|
|
315
|
+
readonly keyword: string;
|
|
316
|
+
readonly dataPath: string;
|
|
317
|
+
readonly params: object;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* What to write instead, for the violations of a preset's identity — ajv's own words for them
|
|
322
|
+
* ("should have required property 'url'", "boolean schema is false") name the key but not why.
|
|
323
|
+
* Read off the error's keyword and parameters, never its message text. Pure.
|
|
324
|
+
*/
|
|
325
|
+
export function identityHint(e: SchemaError): string | null {
|
|
326
|
+
const missing = fieldOf(e.params, "missingProperty");
|
|
327
|
+
if (e.keyword === "required" && missing === "type")
|
|
328
|
+
return 'say what this preset is: "type": "venue" (one venue\'s call for papers), "family" (a publisher\'s template that venues extend) or "base" (the TeX base set)';
|
|
329
|
+
if (e.keyword === "required" && (missing === "name" || missing === "url"))
|
|
330
|
+
return 'a venue preset names its venue and links its call for papers: "name": "<the venue, as its call spells it>", "url": "https://<the call for papers>"';
|
|
331
|
+
if (e.keyword === "false schema")
|
|
332
|
+
return `a template family names no venue: drop "${e.dataPath.slice(1)}" — "name" and "url" belong to the venue presets that extend it`;
|
|
333
|
+
if (e.keyword === "maxProperties")
|
|
334
|
+
return 'the TeX base set holds "type" and "tex" only — a venue\'s or a family\'s settings go in its own preset';
|
|
335
|
+
return null;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/** The hints for every violation that has one, each once. Ajv's null `errors` has none. */
|
|
339
|
+
export const identityHints = (
|
|
340
|
+
v: Readonly<Pick<Validate, "errors">>,
|
|
341
|
+
): readonly string[] => [
|
|
342
|
+
...new Set(
|
|
343
|
+
(v.errors ?? []).map(identityHint).filter((h): h is string => h !== null),
|
|
344
|
+
),
|
|
345
|
+
];
|
|
346
|
+
|
|
281
347
|
/** A preset's JSONC text → its value, or an Error naming the syntax problem. */
|
|
282
348
|
function jsoncOf(text: string, file: string): unknown {
|
|
283
349
|
const parsed = typescript().parseConfigFileTextToJson(file, text);
|
|
@@ -327,12 +393,12 @@ export function parsePreset(
|
|
|
327
393
|
const validate = validatorFor(dir);
|
|
328
394
|
if (!matchesSchema(config, validate))
|
|
329
395
|
throw new Error(
|
|
330
|
-
`${file} does not match ${SCHEMA_FILE}:\n ${violations(file, validate).join("\n ")}`,
|
|
396
|
+
`${file} does not match ${SCHEMA_FILE}:\n ${[...identityHints(validate), ...violations(file, validate)].join("\n ")}`,
|
|
331
397
|
);
|
|
332
398
|
const j = config;
|
|
333
399
|
return {
|
|
400
|
+
identity: identityOf(j),
|
|
334
401
|
extends: orNull(j.extends),
|
|
335
|
-
name: orNull(j.name),
|
|
336
402
|
template: orNull(j.template),
|
|
337
403
|
aliases: j.aliases ?? [],
|
|
338
404
|
blind: orNull(j.blind),
|
|
@@ -342,6 +408,10 @@ export function parsePreset(
|
|
|
342
408
|
rules: j.rules ?? {},
|
|
343
409
|
registerAnchors: anchorsOf(j.register),
|
|
344
410
|
talk: j.talk === undefined ? null : venueTalkOf(j.talk),
|
|
411
|
+
portal:
|
|
412
|
+
j.portal === undefined
|
|
413
|
+
? null
|
|
414
|
+
: { kind: j.portal.kind, url: j.portal.url },
|
|
345
415
|
};
|
|
346
416
|
}
|
|
347
417
|
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
} from "./tex-venue-rules.ts";
|
|
21
21
|
import { resolvePreset } from "./presets.ts";
|
|
22
22
|
import { buildConfig, SHIPPED_RULES } from "./cli.ts";
|
|
23
|
+
import { venuePreset } from "../test/support.ts";
|
|
23
24
|
|
|
24
25
|
const VENUES = presetsDir();
|
|
25
26
|
const PAPER = "/work/papers/p";
|
|
@@ -136,13 +137,13 @@ describe("tex/template — the class and every option the preset names", () => {
|
|
|
136
137
|
"[conference]{IEEEtran} — compsoc missing",
|
|
137
138
|
"\\documentclass[conference]{IEEEtran}",
|
|
138
139
|
["tex/template:missingOption"],
|
|
139
|
-
/the class option `compsoc` is missing:
|
|
140
|
+
/the class option `compsoc` is missing: AIDC requires `\\documentclass\[conference,compsoc\]\{IEEEtran\}`/,
|
|
140
141
|
],
|
|
141
142
|
[
|
|
142
143
|
"{acmart} under an IEEE preset",
|
|
143
144
|
"\\documentclass[sigconf]{acmart}",
|
|
144
145
|
["tex/template:wrongClass"],
|
|
145
|
-
/the class is `acmart`, and
|
|
146
|
+
/the class is `acmart`, and AIDC requires/,
|
|
146
147
|
],
|
|
147
148
|
[
|
|
148
149
|
"[journal,compsoc]{IEEEtran} — conference missing",
|
|
@@ -183,7 +184,7 @@ describe("tex/template — the class line's states: missing, empty, commented ou
|
|
|
183
184
|
expect(ids(fs)).toEqual(["tex/template:emptyClass"]);
|
|
184
185
|
expect(fs[0]?.line).toBe(2);
|
|
185
186
|
expect(fs[0]?.message).toBe(
|
|
186
|
-
"the \\documentclass names no class;
|
|
187
|
+
"the \\documentclass names no class; AIDC requires `\\documentclass[conference,compsoc]{IEEEtran}`",
|
|
187
188
|
);
|
|
188
189
|
});
|
|
189
190
|
|
|
@@ -258,7 +259,7 @@ describe("tex/template — several \\documentclass lines behind a TeX switch", (
|
|
|
258
259
|
// Line 4: the first candidate, after the comment, `\\def` and `\\if` lines.
|
|
259
260
|
expect(fs[0]?.line).toBe(4);
|
|
260
261
|
expect(fs[0]?.message).toBe(
|
|
261
|
-
"none of the 2 \\documentclass lines is `\\documentclass[conference,compsoc]{IEEEtran}`, which
|
|
262
|
+
"none of the 2 \\documentclass lines is `\\documentclass[conference,compsoc]{IEEEtran}`, which AIDC requires: `\\documentclass{article}`, `\\documentclass[conference]{IEEEtran}`. The source picks one behind a TeX switch, which is not evaluated; make one of them the venue's",
|
|
262
263
|
);
|
|
263
264
|
});
|
|
264
265
|
|
|
@@ -309,7 +310,12 @@ describe("tex/template — a project's own preset, and nothing to judge", () =>
|
|
|
309
310
|
paper("\\documentclass{whatever}"),
|
|
310
311
|
{ extends: "./own.jsonc" },
|
|
311
312
|
{
|
|
312
|
-
extra: {
|
|
313
|
+
extra: {
|
|
314
|
+
[own]: JSON.stringify({
|
|
315
|
+
type: "family",
|
|
316
|
+
tex: { packages: { x: ["x"] } },
|
|
317
|
+
}),
|
|
318
|
+
},
|
|
313
319
|
},
|
|
314
320
|
),
|
|
315
321
|
).toEqual([]);
|
|
@@ -325,6 +331,7 @@ describe("tex/template — a template the reader cannot read, a bare class name,
|
|
|
325
331
|
{
|
|
326
332
|
extra: {
|
|
327
333
|
[own]: JSON.stringify({
|
|
334
|
+
type: "family",
|
|
328
335
|
template: "\\documentclass[a]{}",
|
|
329
336
|
tex: { packages: { x: ["x"] } },
|
|
330
337
|
}),
|
|
@@ -341,6 +348,7 @@ describe("tex/template — a template the reader cannot read, a bare class name,
|
|
|
341
348
|
const own = `${PAPER}/own.jsonc`;
|
|
342
349
|
const extra = {
|
|
343
350
|
[own]: JSON.stringify({
|
|
351
|
+
type: "family",
|
|
344
352
|
template: "article",
|
|
345
353
|
tex: { packages: { x: ["x"] } },
|
|
346
354
|
}),
|
|
@@ -353,7 +361,9 @@ describe("tex/template — a template the reader cannot read, a bare class name,
|
|
|
353
361
|
ids(lint(paper("\\documentclass{report}"), settings, { extra })),
|
|
354
362
|
).toEqual(["tex/template:wrongClass"]);
|
|
355
363
|
});
|
|
364
|
+
});
|
|
356
365
|
|
|
366
|
+
describe("tex/template — nothing to judge", () => {
|
|
357
367
|
it.each<[string, object | undefined, string]>([
|
|
358
368
|
["no paperlint.json", undefined, `${PAPER}/paper.tex`],
|
|
359
369
|
[
|
|
@@ -428,7 +438,7 @@ describe("tex/required-section — what fails", () => {
|
|
|
428
438
|
const fs = required(lint(tex, AIDC));
|
|
429
439
|
expect(ids(fs)).toEqual(["tex/required-section:missing"]);
|
|
430
440
|
expect(fs[0]?.message).toBe(
|
|
431
|
-
"
|
|
441
|
+
"AIDC requires a section titled «LLM Usage Statement» and there is none — add `\\section*{LLM Usage Statement}` (the title exactly; a bold paragraph does not count)",
|
|
432
442
|
);
|
|
433
443
|
// At `\end{document}`, where the section would go.
|
|
434
444
|
expect(fs[0]?.line).toBe(tex.split("\n").indexOf("\\end{document}") + 1);
|
|
@@ -503,10 +513,12 @@ describe("tex/required-section — the edges", () => {
|
|
|
503
513
|
it("a position other than last (none): anywhere will do; a child's list replaces its parent's", () => {
|
|
504
514
|
const own = `${PAPER}/own.jsonc`;
|
|
505
515
|
const extra = {
|
|
506
|
-
[own]: JSON.stringify(
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
516
|
+
[own]: JSON.stringify(
|
|
517
|
+
venuePreset("own", {
|
|
518
|
+
extends: "paperlint:aidc",
|
|
519
|
+
required_sections: [{ title: "Ethics" }],
|
|
520
|
+
}),
|
|
521
|
+
),
|
|
510
522
|
};
|
|
511
523
|
const settings = { extends: "./own.jsonc", kind: "regular" };
|
|
512
524
|
expect(
|
|
@@ -528,8 +540,8 @@ describe("tex/venue-leftover — another venue named in the text", () => {
|
|
|
528
540
|
const tex = aidcPaper(`${INSTITUTION}\n${BODY}${STATEMENT}`);
|
|
529
541
|
const fs = leftovers(lint(tex, AIDC));
|
|
530
542
|
expect(fs.map((f) => f.message)).toEqual([
|
|
531
|
-
"«AISec» names
|
|
532
|
-
expect.stringContaining("«ACM CCS» names
|
|
543
|
+
"«AISec» names AISec, and this paper extends AIDC — a leftover from an earlier submission? A reviewer reads it before the abstract. Comments and citation keys are not reported; a sentence that names the other venue on purpose can keep it with a disable directive",
|
|
544
|
+
expect.stringContaining("«ACM CCS» names AISec"),
|
|
533
545
|
]);
|
|
534
546
|
const line = tex.split("\n").indexOf(INSTITUTION) + 1;
|
|
535
547
|
expect(fs.map((f) => f.line)).toEqual([line, line]);
|
|
@@ -591,7 +603,7 @@ describe("tex/venue-leftover — a URL is not text, a definition body is", () =>
|
|
|
591
603
|
);
|
|
592
604
|
const fs = leftovers(lint(tex, AIDC));
|
|
593
605
|
expect(fs.map((f) => [f.line, f.message.slice(0, 16)])).toEqual([
|
|
594
|
-
[4, "«AISec» names
|
|
606
|
+
[4, "«AISec» names AI"],
|
|
595
607
|
]);
|
|
596
608
|
},
|
|
597
609
|
);
|
|
@@ -622,11 +634,12 @@ describe("tex/venue-leftover — where names are found, and whose they are", ()
|
|
|
622
634
|
it("a name a venue shares with this paper's own chain is not a leftover", () => {
|
|
623
635
|
const own = `${PAPER}/own.jsonc`;
|
|
624
636
|
const extra = {
|
|
625
|
-
[own]: JSON.stringify(
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
637
|
+
[own]: JSON.stringify(
|
|
638
|
+
venuePreset("AIDC 2027", {
|
|
639
|
+
extends: "paperlint:aidc",
|
|
640
|
+
aliases: ["ACM CCS"],
|
|
641
|
+
}),
|
|
642
|
+
),
|
|
630
643
|
};
|
|
631
644
|
const tex = aidcPaper(`ACM CCS and AIDC 2027.\n${BODY}${STATEMENT}`);
|
|
632
645
|
expect(
|
|
@@ -719,10 +732,10 @@ describe("otherVenues", () => {
|
|
|
719
732
|
const aidc = resolvePreset("paperlint:aidc", from, deps);
|
|
720
733
|
expect(aidc.ok).toBe(true);
|
|
721
734
|
if (!aidc.ok) return;
|
|
722
|
-
expect(otherVenues(aidc.value,
|
|
735
|
+
expect(otherVenues(aidc.value, deps).map((o) => o.label)).toEqual([
|
|
723
736
|
"acm-sigconf",
|
|
724
|
-
"
|
|
725
|
-
"
|
|
737
|
+
"AgenticDev",
|
|
738
|
+
"AISec",
|
|
726
739
|
]);
|
|
727
740
|
});
|
|
728
741
|
});
|
|
@@ -790,7 +803,7 @@ describe("format/layout-override reports", () => {
|
|
|
790
803
|
[13, "\\newgeometry"],
|
|
791
804
|
]);
|
|
792
805
|
expect(overrides(tex)[0]?.message).toBe(
|
|
793
|
-
"`\\usepackage{geometry}` changes the page layout
|
|
806
|
+
"`\\usepackage{geometry}` changes the page layout AIDC's template sets (`\\documentclass[conference,compsoc]{IEEEtran}`) — a desk-reject reason at venues that check the format. Remove it; if the venue allows it, disable this line with a comment saying so",
|
|
794
807
|
);
|
|
795
808
|
});
|
|
796
809
|
it("a definition's body counts: the length it sets is set wherever it is used", () => {
|
|
@@ -834,6 +847,7 @@ describe("format/layout-override stays silent", () => {
|
|
|
834
847
|
expect(overrides(tex, { extends: null })).toEqual([]);
|
|
835
848
|
const house = {
|
|
836
849
|
[`${PAPER}/house.jsonc`]: JSON.stringify({
|
|
850
|
+
type: "family",
|
|
837
851
|
tex: { packages: { ieeetran: ["IEEEtran.cls"] } },
|
|
838
852
|
}),
|
|
839
853
|
};
|
package/src/tex-venue-rules.ts
CHANGED
|
@@ -27,8 +27,7 @@
|
|
|
27
27
|
* `pdf/profile` already say so, once. A preset that names no template: silent — there is nothing to
|
|
28
28
|
* compare, and a template-family preset is where it is named.
|
|
29
29
|
*/
|
|
30
|
-
import { basename, dirname
|
|
31
|
-
import { CONFIG_FILE } from "#lib/paper-config";
|
|
30
|
+
import { basename, dirname } from "node:path";
|
|
32
31
|
import {
|
|
33
32
|
collapse,
|
|
34
33
|
documentClassLine,
|
|
@@ -46,13 +45,8 @@ import {
|
|
|
46
45
|
type TextRun,
|
|
47
46
|
} from "./domain/tex-document.ts";
|
|
48
47
|
import type { LatexReader } from "./ports/latex.ts";
|
|
49
|
-
import {
|
|
50
|
-
|
|
51
|
-
resolvePreset,
|
|
52
|
-
SHIPPED_PREFIX,
|
|
53
|
-
shippedPresets,
|
|
54
|
-
type Preset,
|
|
55
|
-
} from "./presets.ts";
|
|
48
|
+
import { paperPreset, shippedVenueNames, type Preset } from "./presets.ts";
|
|
49
|
+
import type { NamedVenue } from "./domain/venue-name.ts";
|
|
56
50
|
import type { PaperSource } from "./domain/paper-source.ts";
|
|
57
51
|
import { readPaper, reportInPaper } from "./tex-paper.ts";
|
|
58
52
|
import type { RequiredSection } from "./tex-requirements.ts";
|
|
@@ -255,10 +249,7 @@ export function judgeRequiredSections(
|
|
|
255
249
|
}
|
|
256
250
|
|
|
257
251
|
/** Another shipped venue: the word for it, and what it is called in a paper's text. */
|
|
258
|
-
export
|
|
259
|
-
readonly label: string;
|
|
260
|
-
readonly aliases: readonly string[];
|
|
261
|
-
}
|
|
252
|
+
export type OtherVenue = NamedVenue;
|
|
262
253
|
|
|
263
254
|
/** `s` as a pattern that matches it literally. */
|
|
264
255
|
const literal = (s: string): string =>
|
|
@@ -304,7 +295,8 @@ export const ruleDocsUrl = (
|
|
|
304
295
|
| "register"
|
|
305
296
|
| "contrast-frames"
|
|
306
297
|
| "claim-emphasis"
|
|
307
|
-
| "relation-markers"
|
|
298
|
+
| "relation-markers"
|
|
299
|
+
| "heading-case",
|
|
308
300
|
): string =>
|
|
309
301
|
`https://github.com/zernie/paperlint/blob/main/docs/rules/tex/${name}.md`;
|
|
310
302
|
|
|
@@ -440,21 +432,17 @@ export const FORMAT_RULE_LEVELS: Readonly<
|
|
|
440
432
|
};
|
|
441
433
|
|
|
442
434
|
/**
|
|
443
|
-
* Every shipped venue but the ones on this paper's own chain,
|
|
444
|
-
*
|
|
435
|
+
* Every shipped venue but the ones on this paper's own chain, from the one source of venue names
|
|
436
|
+
* (`shippedVenueNames`). A preset all of whose files are on this paper's chain is this venue or one
|
|
437
|
+
* it extends.
|
|
445
438
|
*/
|
|
446
439
|
export function otherVenues(
|
|
447
|
-
preset: Preset,
|
|
448
|
-
fromFile: string,
|
|
440
|
+
preset: Pick<Preset, "chain">,
|
|
449
441
|
deps: VenueRuleDeps,
|
|
450
442
|
): readonly OtherVenue[] {
|
|
451
|
-
return
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
return r.ok && !r.value.chain.every((f) => preset.chain.includes(f))
|
|
455
|
-
? [{ label: r.value.label, aliases: r.value.aliases }]
|
|
456
|
-
: [];
|
|
457
|
-
});
|
|
443
|
+
return shippedVenueNames(deps)
|
|
444
|
+
.filter((v) => !v.chain.every((f) => preset.chain.includes(f)))
|
|
445
|
+
.map(({ label, aliases }) => ({ label, aliases }));
|
|
458
446
|
}
|
|
459
447
|
|
|
460
448
|
/** What the venue-conformance rules are built with: the preset store, and the LaTeX reader. */
|
|
@@ -476,7 +464,7 @@ function readingOf(
|
|
|
476
464
|
const p = paperPreset(dir, deps);
|
|
477
465
|
if (p.kind !== "resolved") return null;
|
|
478
466
|
const preset = p.preset;
|
|
479
|
-
const others = () => otherVenues(preset,
|
|
467
|
+
const others = () => otherVenues(preset, deps);
|
|
480
468
|
const paper = readPaper(filename, src, deps);
|
|
481
469
|
return {
|
|
482
470
|
reading: { src: paper.text, latex: deps.latex, preset, others },
|
package/src/types.ts
CHANGED
|
@@ -68,6 +68,19 @@ export interface Args {
|
|
|
68
68
|
venue: string | null;
|
|
69
69
|
/** `--kind <kind>` for `new`: one of the venue preset's kinds. */
|
|
70
70
|
kind: string | null;
|
|
71
|
+
/** `--pdf <file>` for `submission`: the PDF to compare or send; null is the paper's own. */
|
|
72
|
+
pdf: string | null;
|
|
73
|
+
/** `--abstract <file>` for `submission update`: a plain-text abstract to send. */
|
|
74
|
+
abstract: string | null;
|
|
75
|
+
/** `--submit` for `submission update`: mark the submission submitted. */
|
|
76
|
+
submit: boolean;
|
|
77
|
+
/** `--save` for `submission update`: really change the submission; without it, a dry run. */
|
|
78
|
+
save: boolean;
|
|
79
|
+
/**
|
|
80
|
+
* `--allow-venue-name` for `new`: create the folder even though its name names a venue. Skips
|
|
81
|
+
* that one refusal and no other.
|
|
82
|
+
*/
|
|
83
|
+
allowVenueName: boolean;
|
|
71
84
|
/** `--hooks=<mode>` — parsed only so it can be REFUSED by name rather than read as a path. */
|
|
72
85
|
hooksMode: string | null;
|
|
73
86
|
help?: boolean;
|
package/src/venue-rules.test.ts
CHANGED
|
@@ -488,7 +488,7 @@ describe("format/page-limit", () => {
|
|
|
488
488
|
"one body page over the short-paper limit",
|
|
489
489
|
(f: Facts) => (f.body_pages = 6),
|
|
490
490
|
["format/page-limit:pages"],
|
|
491
|
-
/body pages: 6, over the limit 5 for
|
|
491
|
+
/body pages: 6, over the limit 5 for AgenticDev\/short/,
|
|
492
492
|
],
|
|
493
493
|
[
|
|
494
494
|
"one reference page over",
|
|
@@ -662,7 +662,7 @@ describe("the IEEE conference family and AIDC", () => {
|
|
|
662
662
|
const fs = lint({ venue: short, facts: pages(7) });
|
|
663
663
|
expect(ids(fs)).toEqual(["format/page-limit:pages"]);
|
|
664
664
|
expect(fs[0]?.message).toBe(
|
|
665
|
-
"body pages (up to the references on page 8): 7, over the limit 6 for
|
|
665
|
+
"body pages (up to the references on page 8): 7, over the limit 6 for AIDC/short — a desk reject; cut the text",
|
|
666
666
|
);
|
|
667
667
|
});
|
|
668
668
|
|
|
@@ -829,7 +829,7 @@ describe("format/page-limit on AIDC: the two signals of where the references sta
|
|
|
829
829
|
});
|
|
830
830
|
expect(ids(fs)).toEqual(["format/page-limit:unclear"]);
|
|
831
831
|
expect(fs[0]?.message).toBe(
|
|
832
|
-
"could not tell where the body ends, so it was NOT counted against
|
|
832
|
+
"could not tell where the body ends, so it was NOT counted against AIDC's limit: the first bibliography entry is on page 14 (hyperref's destination), and no line on page 14 reads «References». Check the headings of the bibliography and the appendix, and that nothing before them reads «References» above a [1]",
|
|
833
833
|
);
|
|
834
834
|
});
|
|
835
835
|
|
|
@@ -906,9 +906,9 @@ describe("anonymity/identity — a blind venue (AIDC)", () => {
|
|
|
906
906
|
}),
|
|
907
907
|
});
|
|
908
908
|
expect(fs.map((f) => f.message)).toEqual([
|
|
909
|
-
"PDF, page 1: «Ada Example» matches «Ada Example» in `identity`, and
|
|
910
|
-
"PDF metadata: Author: «Ada Example» matches «Ada Example» in `identity`, and
|
|
911
|
-
"link target on page 2 (https://github.com/adaexample/tool): «adaexample» matches «Ada Example» in `identity`, and
|
|
909
|
+
"PDF, page 1: «Ada Example» matches «Ada Example» in `identity`, and AIDC reviews double-blind — remove it, or refer to your own work in the third person",
|
|
910
|
+
"PDF metadata: Author: «Ada Example» matches «Ada Example» in `identity`, and AIDC reviews double-blind — remove it, or refer to your own work in the third person",
|
|
911
|
+
"link target on page 2 (https://github.com/adaexample/tool): «adaexample» matches «Ada Example» in `identity`, and AIDC reviews double-blind — remove it, or refer to your own work in the third person",
|
|
912
912
|
]);
|
|
913
913
|
});
|
|
914
914
|
|
|
@@ -949,6 +949,7 @@ describe("a project's own preset, and the facts' other spellings", () => {
|
|
|
949
949
|
// tolerance, a reference range, two columns — and no page size and no font families.
|
|
950
950
|
const HOUSE = {
|
|
951
951
|
[`${PAPER}/house.jsonc`]: JSON.stringify({
|
|
952
|
+
type: "family",
|
|
952
953
|
tex: { packages: { acmart: ["acmart.cls"] } },
|
|
953
954
|
format: { columns: 2, body_pt: 9, ref_pt_min: 7, ref_pt_max: 8 },
|
|
954
955
|
}),
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
% this file exists. With `--venue`, the class below is the venue's (`tex/template` checks it);
|
|
3
3
|
% without, it is yours. `paperlint build` compiles it to paper.pdf.
|
|
4
4
|
\documentclass{article}
|
|
5
|
-
\title{Working
|
|
5
|
+
\title{Working Title for \texttt{{{name}}}}
|
|
6
6
|
\begin{document}
|
|
7
7
|
\maketitle
|
|
8
8
|
Write the paper here.
|
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "AgenticDev @ ASE — venue card (data)"
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# AgenticDev @ ASE venue card
|
|
6
|
-
|
|
7
|
-
> **This is a venue DATA file, not a skill.** Follow the `submit-paper` skill for the end-to-end
|
|
8
|
-
> mechanics; the facts below are the venue-specific data. (Formerly the `submit-paper-agenticdev` skill;
|
|
9
|
-
> demoted to a reference doc so venue data doesn't proliferate the skill namespace.) **Re-verify the
|
|
10
|
-
> CFP each year** (`conf.researchr.org/home/ase-2026/agenticdev-2026`).
|
|
11
|
-
|
|
12
|
-
## The facts (2026 edition)
|
|
13
|
-
|
|
14
|
-
- **Venue**: Workshop on Agentic AI for Next-Generation Software Development, co-located with **ASE**
|
|
15
|
-
(Automated Software Engineering), Munich, Oct 2026.
|
|
16
|
-
- **HotCRP**: `https://agenticdev2026.hotcrp.com/paper/new`.
|
|
17
|
-
- **Deadline**: **July 15, 2026, AoE** (≈ 9 AM July 16 at UTC+5). Notify Aug 21, camera-ready Aug 28.
|
|
18
|
-
- **Types / limits**: Full ≤10pp (mature); **Short ≤5pp** (WIP / vision / position); Demo/Tool ≤5pp.
|
|
19
|
-
Up to **2 extra pages of references** on top.
|
|
20
|
-
- **Format**: ACM `\documentclass[sigconf,review,anonymous]{acmart}` → **double-blind**. Build:
|
|
21
|
-
`pdflatex; bibtex; pdflatex; pdflatex`; add `\microtypesetup{expansion=false}` (the #1 acmart crash).
|
|
22
|
-
- **Archival**: accepted papers → **ASE workshop proceedings, DOI**. 🔴 **Correction 2026-08-26: the
|
|
23
|
-
earlier wording "ACM DL / IEEE Xplore" is FALSE — there is no dual publication.** ASE's publisher
|
|
24
|
-
**alternates by year**: ASEW '24 — ACM (`10.1145/3691621.*`, ISBN 979-8-4007-1249-4), ASE 2025
|
|
25
|
-
Workshops — **IEEE** (`csdl/proceedings/asew/2025`, ISBN 979-8-3315-8503-7). The main track does the
|
|
26
|
-
same: '22 ACM, '23 IEEE, '24 ACM, '25 IEEE. The `10.5555` prefix in ACM DL is a Guide catalog
|
|
27
|
-
entry, NOT an ACM publication. By the alternation pattern, **ACM is expected for 2026**, which
|
|
28
|
-
lines up with an APC even being charged — but ⚠️ **no verbatim statement from ASE 2026 about the
|
|
29
|
-
publisher was found**. If it turns out to be IEEE, the ACM-APC question is moot entirely. Confirm
|
|
30
|
-
with the chairs before paying; selected papers
|
|
31
|
-
invited to a **journal special issue**. This is real authorship-criterion evidence.
|
|
32
|
-
- **⚠️ No supplementary-material upload field** on the HotCRP form (fields are just Title, Submission,
|
|
33
|
-
Abstract, Authors, ACM corresponding, Contacts, PC conflicts). → **Host the artifact externally** (OSF
|
|
34
|
-
anonymized view-only link) and `\url{}` it in the paper's Availability. See `submit-paper` §2.
|
|
35
|
-
- **Remote presentation**: CFP doesn't state a policy; what counts is the indexed
|
|
36
|
-
publication, not attendance. Only ask organizers about remote _after_ acceptance (don't draw attention
|
|
37
|
-
pre-decision under double-blind).
|
|
38
|
-
|
|
39
|
-
## 🔴 How to name the venue — what CAN and CANNOT be claimed
|
|
40
|
-
|
|
41
|
-
The question came up on 2026-08-24 and will come up every time (a post, a site, a résumé, an
|
|
42
|
-
application). Checked against primary sources, not a search-engine summary.
|
|
43
|
-
|
|
44
|
-
**Facts:**
|
|
45
|
-
|
|
46
|
-
- **ASE is CORE A\*** (top tier), together with ICSE and FSE it's software engineering's "big
|
|
47
|
-
three."
|
|
48
|
-
- **AgenticDev is an ASE 2026 workshop**, officially listed on ASE's own _Co-Located Events_ page
|
|
49
|
-
(`conf.researchr.org/track/ase-2026/ase-2026-workshops`). It is not a third-party conference
|
|
50
|
-
that rented a room nearby, and it is not "sponsorship" — the workshop runs under ASE's umbrella.
|
|
51
|
-
- **Proceedings:** accepted papers go into the **ASE 2026 Workshop Proceedings** (ACM DL, DOI).
|
|
52
|
-
- **But it is NOT the ASE main track.** The main track has its own program, its own PC, and its
|
|
53
|
-
own selectivity; the workshop is reviewed separately and more leniently.
|
|
54
|
-
|
|
55
|
-
| ✅ OK to write | ❌ NOT OK |
|
|
56
|
-
| -------------------------------------------------------- | ------------------------------------ |
|
|
57
|
-
| "accepted at AgenticDev 2026, a workshop of ASE 2026" | "accepted at ASE 2026" |
|
|
58
|
-
| "workshop paper, ASE 2026 workshop proceedings (ACM DL)" | "published at a CORE A\* conference" |
|
|
59
|
-
| "ASE is CORE A\*; AgenticDev is one of its workshops" | "my paper is CORE A\*" |
|
|
60
|
-
|
|
61
|
-
⚠️ **Why this isn't pedantry:** a mismatch in how the narrative is framed is a recorded reason
|
|
62
|
-
reviewers reject any claimed credentials. A reviewer sees the "workshop vs. main track"
|
|
63
|
-
distinction in one minute by checking the conference program, and the cost is trust in the whole
|
|
64
|
-
application, not just one line. The phrasing "a workshop of ASE 2026" is not weaker — it carries
|
|
65
|
-
ASE's weight on its own while staying accurate.
|
|
66
|
-
|
|
67
|
-
## Attendance, registration, and proceedings — what affects what
|
|
68
|
-
|
|
69
|
-
- **Traveling to present does NOT affect the credit.** What counts is _authorship of scholarly
|
|
70
|
-
articles_ — that is, **the publication**, not attendance. "Presented at a conference" isn't on
|
|
71
|
-
the list of countable achievements at all.
|
|
72
|
-
- 🔴 **What DOES matter: whether payment becomes a condition of MAKING IT INTO proceedings.** Many
|
|
73
|
-
venues require at least one author to register, or the paper gets pulled from the proceedings.
|
|
74
|
-
In that case what disappears isn't the trip, it's the proof itself. That's the exact question
|
|
75
|
-
put to the chairs on 2026-08-24, and it matters more than the money.
|
|
76
|
-
- Cost for 2026: **APC $350** (ACM went fully open-access as of 2026-01-01) + registration €350
|
|
77
|
-
(early rate through 08-31). The correspondence with the chairs is broken down in the author's
|
|
78
|
-
private notes (`<paper>/reviews/2026-08-24-perepiska-cheyry.md`).
|
|
79
|
-
|
|
80
|
-
## PC members (for 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). An independent author
|
|
84
|
-
with no ties to any of them checks **none**. (List grows year to year — read the current PC page.)
|
|
85
|
-
|
|
86
|
-
## Topic fit (foreground these in the framing)
|
|
87
|
-
|
|
88
|
-
Trustworthiness / verification / validation of AI agents; benchmarking & empirical evaluation;
|
|
89
|
-
integration into developer workflows; agent-based coding/testing. A cost-aware, correctness-gated
|
|
90
|
-
_validation_ paper is dead-center — name those keywords in the abstract/intro.
|
|
91
|
-
|
|
92
|
-
## After acceptance — the prestige upgrade
|
|
93
|
-
|
|
94
|
-
AgenticDev is a workshop (lightest authorship tier, but it counts). Extend the accepted paper (≥30% new
|
|
95
|
-
material) into a higher-prestige indexed venue as a **second** publication: **MSR 2027** (deadline
|
|
96
|
-
~Oct 23, 2026) or **NeurIPS 2027 Evaluations & Datasets** (~May 2027). AgenticDev explicitly invites
|
|
97
|
-
journal extensions. Don't dual-submit the same paper — extend it.
|
|
98
|
-
|
|
99
|
-
## Provenance
|
|
100
|
-
|
|
101
|
-
"Measuring the Wrong Number" submitted here 2026-07-13 (#20, ready-for-review), 4pp short paper, OSF
|
|
102
|
-
anonymized artifact linked in Availability, PC-panel estimate ~85–90% accept.
|
|
103
|
-
|
|
104
|
-
## Camera-ready (2026 edition)
|
|
105
|
-
|
|
106
|
-
**The ACM mechanics are generic and live one level up: `../publishers/acm.md`** (eRights first,
|
|
107
|
-
the preamble, the copyright block, CCS, source files). Here — only what's specific to AgenticDev:
|
|
108
|
-
|
|
109
|
-
- **Camera-ready deadline**: **28 Aug 2026, 2 PM AoE** (≈ 7 AM on August 29 at UTC+5).
|
|
110
|
-
- **DOI**: `10.1145/3843282.3843715` · **ACM ISBN**: `979-8-4007-2985-0/26/10`.
|
|
111
|
-
- **Copyright block**: `AgenticDev '26, October 12–16, 2026, Munich, Germany`.
|
|
112
|
-
- **No longer double-blind.** The submission used `[sigconf,review,anonymous]`; both options come
|
|
113
|
-
off for the final.
|
|
114
|
-
- **Same page limit**: body ≤5 pp + up to 2 pp for references only. A sixth page taken up by the
|
|
115
|
-
bibliography still counts within the limit.
|
|
116
|
-
- **Title changes are allowed** — the portal explicitly asks for it "exactly as it should appear
|
|
117
|
-
in the ACM DL." But decide before eRights (see the publisher card).
|
|
118
|
-
|
|
119
|
-
## Attendance and the talk (2026 edition)
|
|
120
|
-
|
|
121
|
-
**Every year: the deadline and the upload channel come from the parent conference's
|
|
122
|
-
not-in-person page, not from this card.** Look that page up again for the new edition; the dates
|
|
123
|
-
below are 2026's.
|
|
124
|
-
|
|
125
|
-
**Remote is allowed, but there is no live slot.** On 2026-08-27 the chairs told accepted authors
|
|
126
|
-
who cannot travel (by email) that the workshop adopts ASE 2026's
|
|
127
|
-
[Not-in-Person Presentations](https://conf.researchr.org/track/ase-2026/ase-2026-not-in-person-presentations)
|
|
128
|
-
policy. That page, verbatim:
|
|
129
|
-
|
|
130
|
-
> ASE 2026 does not provide presentation slots for papers that are not presented in-person by one
|
|
131
|
-
> of the authors.
|
|
132
|
-
|
|
133
|
-
Instead the author sends:
|
|
134
|
-
|
|
135
|
-
| artifact | what the page says | deadline (2026) |
|
|
136
|
-
| --------- | --------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
|
|
137
|
-
| video | "made available via a dedicated page on the conference website (recommendation: 10 min duration, mp4 file format, HD resolution)" | 2026-10-08 (ASE page; the chairs first asked for 10-01, then deferred to the page) |
|
|
138
|
-
| one-slide | "shown during one of the conference sessions"; no size or format stated | same as the video |
|
|
139
|
-
| poster | optional for the workshop; ASE prints it | ASE page: 2026-09-21 |
|
|
140
|
-
|
|
141
|
-
**Where to upload.** The page says: "find the submission link on the submission page for your paper
|
|
142
|
-
(see author-kit e-mail from Conference Publishing Consulting)". That is the same personal page used
|
|
143
|
-
for the camera-ready. On it, the block "Optional Archive/Appendix/Video/Picture Submissions … Submit
|
|
144
|
-
Material to ACM" uploads straight into the ACM system, once per file. "All submitted material will be
|
|
145
|
-
published in the ACM DL if the publishing-rights agreement gives permission for this", so tick
|
|
146
|
-
permission for auxiliary material when filling in eRights. Asked where to send the files, the
|
|
147
|
-
chairs answered (2026-10-01) only with a link to the ASE page, so the page governs: channel and
|
|
148
|
-
deadline both come from it, and email attachments are not needed.
|
|
149
|
-
|
|
150
|
-
**The slot.** Per the chairs' email to all authors (2026-09-29), a short paper gets 10 minutes in
|
|
151
|
-
total: approximately 6–7 for the presentation and 3–4 for questions. It is stated as approximate,
|
|
152
|
-
with no minimum.
|
|
153
|
-
|
|
154
|
-
**Q&A for a remote author.** No source requires live attendance or a live answer; none confirms
|
|
155
|
-
email Q&A either. Put a contact address on the video's last slide and on the one-slide.
|
|
156
|
-
|
|
157
|
-
**Registration is still required** and still a **publication gate**, not a travel expense:
|
|
158
|
-
workshop-day registration (non-member) €350 through 08-31, €410 through 09-20, €460 on-site.
|
|
159
|
-
If entry requires a visa, ask the chairs right after acceptance.
|
|
160
|
-
|
|
161
|
-
The `talk` rules check the finished files against these numbers: `docs/talk.md`.
|
|
162
|
-
|
|
163
|
-
## 🤖 Machine-readable format profile
|
|
164
|
-
|
|
165
|
-
Read by ESLint rules over `<paper>/_build/paper.facts.json` (the facts are captured by
|
|
166
|
-
`extract-pdf-facts.mjs`). **The numbers live here, not in code** — this venue has its own, the
|
|
167
|
-
next one will have different ones. Source: the Conference Publishing author instructions
|
|
168
|
-
(2026-08-25) and ACM's requirements.
|
|
169
|
-
|
|
170
|
-
**The format profile is in [`agenticdev.yaml`](agenticdev.yaml)** next to this file. Data lives
|
|
171
|
-
there, prose lives here.
|