paperlint 9.0.1 → 10.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.
- package/CONTRIBUTING.md +16 -4
- package/README.md +68 -128
- package/dist/build.d.ts +1 -1
- package/dist/build.js +1 -1
- package/dist/cli.d.ts +5 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +52 -6
- package/dist/cli.js.map +1 -1
- package/dist/domain/layout-tree.d.ts +19 -0
- package/dist/domain/layout-tree.d.ts.map +1 -0
- package/dist/domain/layout-tree.js +32 -0
- package/dist/domain/layout-tree.js.map +1 -0
- package/dist/domain/lookup-cache.d.ts +2 -2
- package/dist/domain/lookup-cache.js +2 -2
- package/dist/domain/paper-layout.d.ts +81 -0
- package/dist/domain/paper-layout.d.ts.map +1 -0
- package/dist/domain/paper-layout.js +259 -0
- package/dist/domain/paper-layout.js.map +1 -0
- package/dist/domain/repro-layout.d.ts +80 -0
- package/dist/domain/repro-layout.d.ts.map +1 -0
- package/dist/domain/repro-layout.js +247 -0
- package/dist/domain/repro-layout.js.map +1 -0
- package/dist/domain/scaffold-layout.d.ts +28 -0
- package/dist/domain/scaffold-layout.d.ts.map +1 -0
- package/dist/domain/scaffold-layout.js +81 -0
- package/dist/domain/scaffold-layout.js.map +1 -0
- package/dist/eslint-rules/js-needs-reason.d.ts +55 -0
- package/dist/eslint-rules/js-needs-reason.d.ts.map +1 -0
- package/dist/eslint-rules/js-needs-reason.js +35 -0
- package/dist/eslint-rules/js-needs-reason.js.map +1 -0
- package/dist/eslint-rules/prereg-coverage.d.ts +98 -0
- package/dist/eslint-rules/prereg-coverage.d.ts.map +1 -0
- package/dist/eslint-rules/prereg-coverage.js +274 -0
- package/dist/eslint-rules/prereg-coverage.js.map +1 -0
- package/dist/folder-layout-hook.d.ts +21 -0
- package/dist/folder-layout-hook.d.ts.map +1 -0
- package/dist/folder-layout-hook.js +117 -0
- package/dist/folder-layout-hook.js.map +1 -0
- package/dist/folder-layout-rule.d.ts +22 -0
- package/dist/folder-layout-rule.d.ts.map +1 -0
- package/dist/folder-layout-rule.js +107 -0
- package/dist/folder-layout-rule.js.map +1 -0
- package/dist/init.js +1 -1
- package/dist/init.js.map +1 -1
- package/dist/new-paper.d.ts +4 -1
- package/dist/new-paper.d.ts.map +1 -1
- package/dist/new-paper.js +40 -6
- package/dist/new-paper.js.map +1 -1
- package/dist/package-dirs.d.ts +6 -0
- package/dist/package-dirs.d.ts.map +1 -1
- package/dist/package-dirs.js +6 -0
- package/dist/package-dirs.js.map +1 -1
- package/dist/references.d.ts +1 -1
- package/dist/references.d.ts.map +1 -1
- package/dist/references.js +2 -2
- package/dist/references.js.map +1 -1
- package/dist/repro-layout-rule.d.ts +16 -0
- package/dist/repro-layout-rule.d.ts.map +1 -0
- package/dist/repro-layout-rule.js +81 -0
- package/dist/repro-layout-rule.js.map +1 -0
- package/dist/skills/label-agent-runs/scripts/labels-commands.d.ts +13 -0
- package/dist/skills/label-agent-runs/scripts/labels.d.ts +2 -0
- package/dist/skills/run-agent-grid/scripts/grid-guard-commands.d.ts +20 -0
- package/dist/skills/run-agent-grid/scripts/grid-guard.d.ts +2 -0
- package/docs/ci.md +60 -0
- package/docs/configuration.md +2 -0
- package/docs/e2e.md +2 -2
- package/docs/install.md +20 -16
- package/docs/layout.md +154 -0
- package/docs/optional-rules.md +5 -4
- package/docs/references.md +5 -2
- package/docs/rules/paper/allowed-files-only.md +192 -0
- package/docs/rules/repro/allowed-files-only.md +128 -0
- package/docs/rules/study/declare-sample.md +146 -0
- package/docs/rules.md +53 -50
- package/docs/skills.md +8 -3
- package/docs/testing.md +13 -0
- package/docs/venues.md +94 -0
- package/eslint-rules/js-needs-reason.test.ts +141 -0
- package/eslint-rules/js-needs-reason.ts +77 -0
- package/eslint-rules/prereg-coverage.test.ts +448 -0
- package/eslint-rules/prereg-coverage.ts +419 -0
- package/eslint.config.mjs +22 -2
- package/lib/skill-trigger-cases.harness.mjs +51 -5
- package/lib/skill-trigger-cases.mjs +53 -15
- package/lib/skill-trigger-cases.test.ts +211 -0
- package/package.json +8 -4
- package/plugin/hooks/hooks.json +9 -0
- package/scripts/coverage-config.test.ts +5 -3
- package/skills/analyze-sibling-paper/SKILL.md +2 -2
- package/skills/analyze-sibling-paper/SKILL.md.spec.ts +1 -1
- package/skills/build-benchmark/SKILL.md +17 -1
- package/skills/build-benchmark/SKILL.md.spec.ts +16 -0
- package/skills/build-label-page/SKILL.md +120 -0
- package/skills/build-label-page/SKILL.md.spec.ts +131 -0
- package/skills/build-label-page/build-label-page.eval.mjs +15 -0
- package/skills/build-label-page/build-label-page.test.ts +959 -0
- package/skills/build-label-page/references/checklist.md +148 -0
- package/skills/build-label-page/references/example-generator.py +803 -0
- package/skills/find-venue/SKILL.md +5 -3
- package/skills/find-venue/SKILL.md.spec.ts +4 -2
- package/skills/grade-paper-writing/SKILL.md +7 -7
- package/skills/grade-paper-writing/SKILL.md.spec.ts +6 -6
- package/skills/label-agent-runs/SKILL.md +103 -0
- package/skills/label-agent-runs/SKILL.md.spec.ts +106 -0
- package/skills/label-agent-runs/label-agent-runs.eval.ts +55 -0
- package/skills/label-agent-runs/label-agent-runs.harness.ts +123 -0
- package/skills/label-agent-runs/references/formats.md +64 -0
- package/skills/label-agent-runs/scripts/labels-commands.js +13 -0
- package/skills/label-agent-runs/scripts/labels-commands.ts +13 -0
- package/skills/label-agent-runs/scripts/labels.js +396 -0
- package/skills/label-agent-runs/scripts/labels.test.ts +538 -0
- package/skills/label-agent-runs/scripts/labels.ts +501 -0
- package/skills/map-prior-work/SKILL.md +2 -2
- package/skills/map-prior-work/SKILL.md.spec.ts +1 -1
- package/skills/paper-pipeline/SKILL.md +15 -6
- package/skills/paper-pipeline/SKILL.md.spec.ts +14 -5
- package/skills/paper-pipeline/grade-paper-writing-ablation.eval.mjs +19 -9
- package/skills/paper-pipeline/references/acceptance-gate.md +19 -19
- package/skills/paper-pipeline/references/artifact-checklist.md +5 -0
- package/skills/paper-pipeline/references/pipeline-status-template.md +30 -1
- package/skills/paper-pipeline/repro/2026-08-07-fork-check.log +1 -1
- package/skills/paper-pipeline/repro/2026-08-07-fork-check2.log +1 -1
- package/skills/paper-pipeline/repro/2026-08-07-language-eval-pilot.log +1 -1
- package/skills/paper-pipeline/repro/2026-08-07-language-eval-raw.log +1 -1
- package/skills/paper-pipeline/repro/2026-08-08-framing-vs-vocabulary-oracle.log +48 -48
- package/skills/paper-pipeline/repro/2026-08-08-grade-paper-writing-ablation-A6-oracle.log +8 -8
- package/skills/paper-pipeline/repro/2026-08-08-grade-paper-writing-ablation-oracle.log +48 -48
- package/skills/paper-pipeline/repro/2026-08-08-parent-replication-gpw.log +2 -2
- package/skills/paper-pipeline/repro/2026-08-08-parent-replication.mjs +3 -3
- package/skills/paper-pipeline/repro/2026-10-13-grade-paper-writing-ablation-preflight-after.log +81 -0
- package/skills/paper-pipeline/repro/2026-10-13-grade-paper-writing-ablation-preflight-before.log +81 -0
- package/skills/paper-pipeline/repro/2026-10-13-grade-paper-writing-ablation-setupdiff.log +59 -0
- package/skills/paper-pipeline/repro/2026-10-13-grade-paper-writing-trigger.jsonl +1 -0
- package/skills/paper-pipeline/repro/2026-10-13-grade-paper-writing-trigger.log +22 -0
- package/skills/paper-pipeline/repro/README.md +4 -0
- package/skills/paper-pipeline/scripts/extract-ref-facts.harness.mjs +2 -2
- package/skills/paper-pipeline/scripts/extract-ref-facts.mjs +2 -2
- package/skills/paper-pipeline/scripts/extract-ref-facts.test.mjs +4 -2
- package/skills/paper-pipeline/scripts/generated-code.harness.mjs +7 -2
- package/skills/paper-pipeline/scripts/generated-code.mjs +8 -4
- package/skills/paper-pipeline/scripts/generated-code.test.ts +15 -1
- package/skills/paper-status/SKILL.md +2 -2
- package/skills/paper-status/SKILL.md.spec.ts +1 -1
- package/skills/run-agent-grid/SKILL.md +181 -0
- package/skills/run-agent-grid/SKILL.md.spec.ts +184 -0
- package/skills/run-agent-grid/references/failure-catalog.md +36 -0
- package/skills/run-agent-grid/references/registry-and-ledger.md +142 -0
- package/skills/run-agent-grid/run-agent-grid.eval.ts +59 -0
- package/skills/run-agent-grid/run-agent-grid.harness.ts +115 -0
- package/skills/run-agent-grid/scripts/grid-guard-commands.js +18 -0
- package/skills/run-agent-grid/scripts/grid-guard-commands.ts +21 -0
- package/skills/run-agent-grid/scripts/grid-guard.js +700 -0
- package/skills/run-agent-grid/scripts/grid-guard.test.ts +1090 -0
- package/skills/run-agent-grid/scripts/grid-guard.ts +869 -0
- package/skills/study-accepted-papers/SKILL.md +163 -161
- package/skills/study-accepted-papers/SKILL.md.spec.ts +167 -165
- package/skills/study-accepted-papers/references/base-rates.md +69 -0
- package/skills/study-accepted-papers/references/mechanisms.md +181 -0
- package/skills/verify-citations/SKILL.md +2 -2
- package/skills/verify-citations/SKILL.md.spec.ts +1 -1
- package/src/build.ts +1 -1
- package/src/cli.harness.mjs +42 -0
- package/src/cli.test.ts +90 -6
- package/src/cli.ts +78 -5
- package/src/domain/layout-tree.test.ts +32 -0
- package/src/domain/layout-tree.ts +47 -0
- package/src/domain/lookup-cache.ts +2 -2
- package/src/domain/paper-layout.test.ts +264 -0
- package/src/domain/paper-layout.ts +336 -0
- package/src/domain/repro-layout.test.ts +222 -0
- package/src/domain/repro-layout.ts +311 -0
- package/src/domain/scaffold-layout.ts +104 -0
- package/src/folder-layout-hook.test.ts +214 -0
- package/src/folder-layout-hook.ts +141 -0
- package/src/folder-layout-rule.test.ts +235 -0
- package/src/folder-layout-rule.ts +151 -0
- package/src/hooks-settings.harness.ts +9 -8
- package/src/init.ts +1 -1
- package/src/layout-docs.test.ts +52 -0
- package/src/new-paper.harness.mjs +23 -1
- package/src/new-paper.test.ts +299 -6
- package/src/new-paper.ts +51 -5
- package/src/package-dirs.ts +8 -0
- package/src/paper-files.test.ts +9 -6
- package/src/references.test.ts +5 -5
- package/src/references.ts +2 -2
- package/src/repro-layout-rule.test.ts +114 -0
- package/src/repro-layout-rule.ts +121 -0
- package/src/rule-cases.test.ts +98 -0
- package/templates/paper/PIPELINE-STATUS.md +41 -7
- package/tsconfig.base.json +22 -0
- package/tsconfig.json +6 -24
- package/tsconfig.pkg.json +3 -1
- package/tsconfig.skills.json +14 -0
- package/tsconfig.src.json +12 -0
package/dist/references.js
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* stale when it changes (`pdf_sha256`); these are about the databases and are stale when THEY
|
|
20
20
|
* change (`bib.sha256`). One staleness key per file, the way `pdf/fresh` already works.
|
|
21
21
|
*
|
|
22
|
-
* 🔴 WHAT THE CHECKERS ANSWERED IS KEPT, COMMITTED, IN `<paper>/repro/references-cache.json`
|
|
22
|
+
* 🔴 WHAT THE CHECKERS ANSWERED IS KEPT, COMMITTED, IN `<paper>/repro/data/references-cache.json`
|
|
23
23
|
* (`domain/lookup-cache.ts`). Loaded before the check and saved after it — only when something new
|
|
24
24
|
* was fetched, a refreshed answer included — so a build asks each question at most once every
|
|
25
25
|
* MAX_AGE_DAYS, not once per build (#107: 217 s for 27 references, every build). The verdicts above are NOT cached: they are derived from the cached
|
|
@@ -53,7 +53,7 @@ import { entriesOfDatabases, recordedBibliography, } from "./recorded-bibliograp
|
|
|
53
53
|
export const REFERENCES_SCHEMA = 3;
|
|
54
54
|
export const REFERENCES_FILE = "references.json";
|
|
55
55
|
/** The lookup cache's place in a paper: committed, beside the paper's other reproduction files. */
|
|
56
|
-
export const LOOKUP_CACHE_FILE = "repro/references-cache.json";
|
|
56
|
+
export const LOOKUP_CACHE_FILE = "repro/data/references-cache.json";
|
|
57
57
|
export const lookupCachePath = (paperDir) => join(paperDir, LOOKUP_CACHE_FILE);
|
|
58
58
|
/** Where a paper's reference verdicts live — beside `paper.facts.json`. */
|
|
59
59
|
export const referencesPath = (paperDir) => join(paperDir, "_build", REFERENCES_FILE);
|
package/dist/references.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"references.js","sourceRoot":"","sources":["../src/references.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,GAErB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,EAAE,EAAe,MAAM,oBAAoB,CAAC;AAOrD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EACL,eAAe,GAEhB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,kBAAkB,EAClB,oBAAoB,GAIrB,MAAM,4BAA4B,CAAC;AAEpC,oGAAoG;AACpG,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC;AACnC,MAAM,CAAC,MAAM,eAAe,GAAG,iBAAiB,CAAC;AAEjD,mGAAmG;AACnG,MAAM,CAAC,MAAM,iBAAiB,GAAG,
|
|
1
|
+
{"version":3,"file":"references.js","sourceRoot":"","sources":["../src/references.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { FolderRuleModule } from "./folder-venue-rule.ts";
|
|
2
|
+
import type { FolderLayoutDeps } from "./folder-layout-rule.ts";
|
|
3
|
+
import type { Files } from "./ports/files.ts";
|
|
4
|
+
import type { LayoutEntry } from "./domain/paper-layout.ts";
|
|
5
|
+
/**
|
|
6
|
+
* The text of each finding among `entries` at the top of the paper folder `dir`'s `repro/` — THE one
|
|
7
|
+
* function behind both the rule and the `paper-folder-layout` hook, so the two cannot disagree.
|
|
8
|
+
*/
|
|
9
|
+
export declare const reproTexts: (dir: string, entries: readonly LayoutEntry[], files: Files) => readonly string[];
|
|
10
|
+
/** The entries at the top of `<dir>/repro/`, each a file or a folder; none without a `repro/`. */
|
|
11
|
+
export declare const reproEntriesOf: (dir: string, deps: FolderLayoutDeps) => readonly LayoutEntry[];
|
|
12
|
+
/** The rule, reading the folder through `deps`. */
|
|
13
|
+
export declare function reproLayoutRules(deps: FolderLayoutDeps): Readonly<Record<"allowed-files-only", FolderRuleModule>>;
|
|
14
|
+
/** The level it is on at in paperlint's own config, for every paper's `PIPELINE-STATUS.md`. */
|
|
15
|
+
export declare const REPRO_LAYOUT_RULE_LEVELS: Readonly<Record<"repro/allowed-files-only", "error">>;
|
|
16
|
+
//# sourceMappingURL=repro-layout-rule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repro-layout-rule.d.ts","sourceRoot":"","sources":["../src/repro-layout-rule.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAEV,gBAAgB,EACjB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAkB5D;;;GAGG;AACH,eAAO,MAAM,UAAU,GACrB,KAAK,MAAM,EACX,SAAS,SAAS,WAAW,EAAE,EAC/B,OAAO,KAAK,KACX,SAAS,MAAM,EAC6C,CAAC;AAEhE,kGAAkG;AAClG,eAAO,MAAM,cAAc,GACzB,KAAK,MAAM,EACX,MAAM,gBAAgB,KACrB,SAAS,WAAW,EAMlB,CAAC;AAgBN,mDAAmD;AACnD,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,gBAAgB,GACrB,QAAQ,CAAC,MAAM,CAAC,oBAAoB,EAAE,gBAAgB,CAAC,CAAC,CAwB1D;AAED,+FAA+F;AAC/F,eAAO,MAAM,wBAAwB,EAAE,QAAQ,CAC7C,MAAM,CAAC,0BAA0B,EAAE,OAAO,CAAC,CACF,CAAC"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `repro/allowed-files-only` — the top of a paper's `repro/` holds an index, the shared `tools/` and
|
|
3
|
+
* `data/`, and one dated folder per study, each with a `README.md`.
|
|
4
|
+
*
|
|
5
|
+
* What may stand there, and why, is `src/domain/repro-layout.ts` and docs/rules/repro/allowed-files-only.md.
|
|
6
|
+
* This file lists the folder and reports.
|
|
7
|
+
*
|
|
8
|
+
* ── WHY A RULE OF ITS OWN, NOT MORE OF `paper/allowed-files-only` ─────────────────────
|
|
9
|
+
* Each entry is judged by exactly one rule: `paper/allowed-files-only` judges the paper folder's root,
|
|
10
|
+
* where `repro/` is allowed, and this rule judges what is inside `repro/`. Neither reports an entry
|
|
11
|
+
* the other does, so a stray entry gets one message. A rule of its own also has its own page and its
|
|
12
|
+
* own switch: a paper whose `repro/` predates the layout can turn this one off and keep its root
|
|
13
|
+
* judged.
|
|
14
|
+
*
|
|
15
|
+
* ── WHICH FILE IT REPORTS ON ─────────────────────────────────────────────────────
|
|
16
|
+
* `PIPELINE-STATUS.md`, first line, like `paper/allowed-files-only`: every paper has it, and `repro/` may
|
|
17
|
+
* have no file ESLint lints at all.
|
|
18
|
+
*/
|
|
19
|
+
import { basename, dirname, join } from "node:path";
|
|
20
|
+
import { callerPath } from "./caller-path.js";
|
|
21
|
+
import { README, REPRO_DIR, judgeRepro, reproMessage, } from "./domain/repro-layout.js";
|
|
22
|
+
import { rulePageUrl } from "./venue-rules.js";
|
|
23
|
+
const STATUS_FILE = "PIPELINE-STATUS.md";
|
|
24
|
+
/** `entries` of `<dir>/repro/`, each folder with whether it holds a README.md. */
|
|
25
|
+
const withReadme = (dir, entries, files) => entries.map((e) => ({
|
|
26
|
+
...e,
|
|
27
|
+
hasReadme: e.kind === "dir" &&
|
|
28
|
+
files.isFile(callerPath(join(dir, REPRO_DIR, e.name, README))),
|
|
29
|
+
}));
|
|
30
|
+
/**
|
|
31
|
+
* The text of each finding among `entries` at the top of the paper folder `dir`'s `repro/` — THE one
|
|
32
|
+
* function behind both the rule and the `paper-folder-layout` hook, so the two cannot disagree.
|
|
33
|
+
*/
|
|
34
|
+
export const reproTexts = (dir, entries, files) => judgeRepro(withReadme(dir, entries, files)).map(reproMessage);
|
|
35
|
+
/** The entries at the top of `<dir>/repro/`, each a file or a folder; none without a `repro/`. */
|
|
36
|
+
export const reproEntriesOf = (dir, deps) => [...deps.listDir(callerPath(join(dir, REPRO_DIR)))].sort().map((name) => ({
|
|
37
|
+
name,
|
|
38
|
+
kind: deps.files.isFile(callerPath(join(dir, REPRO_DIR, name)))
|
|
39
|
+
? "file"
|
|
40
|
+
: "dir",
|
|
41
|
+
}));
|
|
42
|
+
const META = {
|
|
43
|
+
type: "suggestion",
|
|
44
|
+
docs: {
|
|
45
|
+
description: "the top of a paper's repro/ holds README.md, .gitignore, tools/, data/ and one <slug>-YYYY-MM-DD folder per study, each with a README.md",
|
|
46
|
+
url: rulePageUrl("repro/allowed-files-only"),
|
|
47
|
+
},
|
|
48
|
+
schema: [],
|
|
49
|
+
messages: {
|
|
50
|
+
// The whole text is `reproMessage` (src/domain/repro-layout.ts), the one the hook sends too.
|
|
51
|
+
misplaced: "{{text}}",
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
/** The rule, reading the folder through `deps`. */
|
|
55
|
+
export function reproLayoutRules(deps) {
|
|
56
|
+
return {
|
|
57
|
+
"allowed-files-only": {
|
|
58
|
+
meta: META,
|
|
59
|
+
create(context) {
|
|
60
|
+
if (basename(context.filename) !== STATUS_FILE)
|
|
61
|
+
return {};
|
|
62
|
+
return {
|
|
63
|
+
root() {
|
|
64
|
+
const dir = dirname(context.filename);
|
|
65
|
+
const at = context.sourceCode.getLocFromIndex(0);
|
|
66
|
+
reproTexts(dir, reproEntriesOf(dir, deps), deps.files).forEach((text) => {
|
|
67
|
+
context.report({
|
|
68
|
+
loc: { start: at, end: at },
|
|
69
|
+
messageId: "misplaced",
|
|
70
|
+
data: { text },
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/** The level it is on at in paperlint's own config, for every paper's `PIPELINE-STATUS.md`. */
|
|
80
|
+
export const REPRO_LAYOUT_RULE_LEVELS = { "repro/allowed-files-only": "error" };
|
|
81
|
+
//# sourceMappingURL=repro-layout-rule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repro-layout-rule.js","sourceRoot":"","sources":["../src/repro-layout-rule.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The subcommands of `labels`, by name. One table, read twice: the dispatcher in `labels.ts`
|
|
3
|
+
* compares against these, and `SKILL.md.spec.ts` interpolates them into every command it
|
|
4
|
+
* instructs (a name that is not here is a type error there). So the skill cannot instruct a
|
|
5
|
+
* subcommand the script does not have.
|
|
6
|
+
*
|
|
7
|
+
* A module of its own, with no side effects: the spec imports it at compile time, and importing
|
|
8
|
+
* `labels.ts` itself would run the command line.
|
|
9
|
+
*/
|
|
10
|
+
export declare const COMMANDS: {
|
|
11
|
+
readonly validate: "validate";
|
|
12
|
+
readonly agree: "agree";
|
|
13
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The subcommands of `grid-guard`, by name. One table, read twice: the dispatcher in
|
|
3
|
+
* `grid-guard.ts` is keyed by these names (a missing or extra entry is a type error there), and
|
|
4
|
+
* `SKILL.md.spec.ts` interpolates them into every command it instructs (a name that is not here
|
|
5
|
+
* is a type error there). So the skill cannot instruct a subcommand the script does not have.
|
|
6
|
+
*
|
|
7
|
+
* A module of its own, with no side effects: the spec imports it at compile time, and importing
|
|
8
|
+
* `grid-guard.ts` itself would run the command line.
|
|
9
|
+
*/
|
|
10
|
+
export declare const COMMANDS: {
|
|
11
|
+
readonly lock: "lock";
|
|
12
|
+
readonly release: "release";
|
|
13
|
+
readonly gate: "gate";
|
|
14
|
+
readonly overlap: "overlap";
|
|
15
|
+
readonly envProbe: "env-probe";
|
|
16
|
+
readonly scanKeys: "scan-keys";
|
|
17
|
+
readonly precommit: "precommit";
|
|
18
|
+
};
|
|
19
|
+
/** A subcommand's name as typed on the command line. */
|
|
20
|
+
export type CommandName = (typeof COMMANDS)[keyof typeof COMMANDS];
|
package/docs/ci.md
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Run it in CI
|
|
2
|
+
|
|
3
|
+
Two jobs, one choice: how much of the paper CI judges.
|
|
4
|
+
|
|
5
|
+
| job | time | checks |
|
|
6
|
+
| -------------------------- | ----------------------------- | ------------------------------------------ |
|
|
7
|
+
| build, then lint | ~3 min first run, then cached | everything |
|
|
8
|
+
| lint only (`init` adds it) | seconds | the source; not pages, fonts or references |
|
|
9
|
+
|
|
10
|
+
`paperlint lint` exits non-zero on any error; warnings only print, unless you pass
|
|
11
|
+
`--max-warnings <n>`.
|
|
12
|
+
|
|
13
|
+
## Build, then lint
|
|
14
|
+
|
|
15
|
+
Lint judges pages, fonts and references from what build measured, so the full job builds first.
|
|
16
|
+
The cache keeps TeX Live between runs:
|
|
17
|
+
|
|
18
|
+
```yaml
|
|
19
|
+
name: papers
|
|
20
|
+
on: [push, pull_request]
|
|
21
|
+
jobs:
|
|
22
|
+
papers:
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@v4
|
|
26
|
+
- uses: actions/setup-node@v4
|
|
27
|
+
with:
|
|
28
|
+
node-version: 22
|
|
29
|
+
- run: npm ci
|
|
30
|
+
- uses: actions/cache@v4
|
|
31
|
+
with:
|
|
32
|
+
path: ~/.cache/paperlint/texlive
|
|
33
|
+
key: texlive-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
|
|
34
|
+
- run: npx paperlint toolchain
|
|
35
|
+
- run: npx paperlint build --all
|
|
36
|
+
- run: npx paperlint lint
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Commit `repro/data/references-cache.json` of each paper: with it, a build asks the citation
|
|
40
|
+
services only about new or edited entries, so an unchanged bibliography usually builds without
|
|
41
|
+
the network ([`references.md`](references.md)).
|
|
42
|
+
|
|
43
|
+
## Lint only
|
|
44
|
+
|
|
45
|
+
Each paper then gets one warning that it was not built. Call the action from the installed package,
|
|
46
|
+
after `npm ci`: the action and the CLI it runs are then one revision, pinned by your lockfile.
|
|
47
|
+
|
|
48
|
+
```yaml
|
|
49
|
+
steps:
|
|
50
|
+
- uses: actions/checkout@v4
|
|
51
|
+
- uses: actions/setup-node@v4
|
|
52
|
+
with:
|
|
53
|
+
node-version: 22
|
|
54
|
+
- run: npm ci
|
|
55
|
+
- uses: ./node_modules/paperlint
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
With no `paths` it lints the `papersDir` of your `paperlint.json`; pass `paths:` only to lint less.
|
|
59
|
+
|
|
60
|
+
This is the workflow `paperlint init` offers to write ([`install.md`](install.md)).
|
package/docs/configuration.md
CHANGED
|
@@ -13,6 +13,8 @@ papers/
|
|
|
13
13
|
paper.tex
|
|
14
14
|
PIPELINE-STATUS.md
|
|
15
15
|
paperlint.json THIS PAPER: its venue preset, its kind, its own rules — `paperlint new` writes it
|
|
16
|
+
reviews/ research/ figures/ versions/ submission/ repro/
|
|
17
|
+
the paper's layout — `paperlint new` makes them (an empty one holds a `.gitkeep`)
|
|
16
18
|
venues/usenix-sec.jsonc (optional, your own) a VENUE PRESET: format, page limits, TeX packages, rules
|
|
17
19
|
```
|
|
18
20
|
|
package/docs/e2e.md
CHANGED
|
@@ -54,8 +54,8 @@ depend on each other — and drives the installed binary:
|
|
|
54
54
|
publishes, once each — and says they need `npm install` in a fresh clone; a second `init`
|
|
55
55
|
leaves that file byte-identical
|
|
56
56
|
- `paperlint lint` passes the staged corpus
|
|
57
|
-
- `paperlint new demo` scaffolds a paper from the templates that shipped in the tarball
|
|
58
|
-
clean, and `paperlint lint` stays clean with it in the corpus
|
|
57
|
+
- `paperlint new demo` scaffolds a paper from the templates that shipped in the tarball (and the
|
|
58
|
+
layout's folders), its own lint is clean, and `paperlint lint` stays clean with it in the corpus
|
|
59
59
|
- `hooks.json` arrived and parses, and every hook command named in it resolves to a file
|
|
60
60
|
- every skill arrived, and every script path named inside a skill resolves **in the consumer**
|
|
61
61
|
|
package/docs/install.md
CHANGED
|
@@ -50,9 +50,9 @@ question (Ctrl+D) also takes the default.
|
|
|
50
50
|
| what | where | when |
|
|
51
51
|
| -------------------------------------------------------------------- | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
52
52
|
| `{ "papersDir": … }` naming your papers directory | `paperlint.json` | only when it is not the default `papers` |
|
|
53
|
-
| the
|
|
53
|
+
| the four hook commands, merged in beside your own entries | `.claude/settings.json` | by default. A human at a terminal is asked [Y/n]; an agent, CI or `--yes` gets YES; `--no-hooks` skips. Hand-wired under another spelling: nothing written, so nothing runs twice |
|
|
54
54
|
| a GitHub Actions workflow: `npm ci`, then `./node_modules/paperlint` | `.github/workflows/` | only if you say yes; it asks once, and only when a human is at a terminal (stdin and stdout, no `CI`, no `--yes`) |
|
|
55
|
-
| a first paper, via `paperlint new
|
|
55
|
+
| a first paper, via `paperlint new`, with its layout's folders | `<papers>/<name>/` | only when the papers directory holds none: asked of a human at a terminal, otherwise only with `--paper <name>` |
|
|
56
56
|
| one relative symlink per shipped skill, into the installed package | `.claude/skills/<name>` | always — except where that name is already taken (a directory, a file, a link elsewhere): that entry is left as it is and named in the report |
|
|
57
57
|
|
|
58
58
|
It installs no software you did not say yes to, and touches nothing else. Commit `.claude/settings.json` so every clone
|
|
@@ -61,9 +61,11 @@ gets the hooks; the hook commands run files inside `node_modules`, so a fresh cl
|
|
|
61
61
|
|
|
62
62
|
## Why it is shaped this way
|
|
63
63
|
|
|
64
|
-
**One file, at the project root.** A hook cannot import code or walk up a tree looking for
|
|
65
|
-
config; it can only read a path it can spell, and `$CLAUDE_PROJECT_DIR/paperlint.json` is one.
|
|
66
|
-
|
|
64
|
+
**One file, at the project root.** A vigiles hook cannot import code or walk up a tree looking for
|
|
65
|
+
a config; it can only read a path it can spell, and `$CLAUDE_PROJECT_DIR/paperlint.json` is one.
|
|
66
|
+
(`paper-folder-layout` is not a vigiles hook: it runs inside the CLI, because it must call the
|
|
67
|
+
function its rule reports with.) The same file is read by the CLI, the three vigiles hooks,
|
|
68
|
+
`eslint-rules/papers.mjs`,
|
|
67
69
|
`lib/skill-trigger-cases.mjs` and `skills/paper-pipeline/scripts/consumer.mjs`. It is optional:
|
|
68
70
|
absent, every reader takes the same defaults.
|
|
69
71
|
|
|
@@ -147,17 +149,19 @@ are probably smaller now; re-measure before quoting them.
|
|
|
147
149
|
| of which `typescript` (via `vigiles`) | 23 MB |
|
|
148
150
|
| of which `vigiles` itself | 6 MB |
|
|
149
151
|
|
|
150
|
-
Neither `paperlint lint` nor any of the
|
|
151
|
-
`vigiles` itself is
|
|
152
|
+
Neither `paperlint lint` nor any of the four hooks loads `@ast-grep` or `typescript` (traced;
|
|
153
|
+
`paper-folder-layout` on 2026-10-12: 223 CommonJS modules, none from either); `vigiles` itself is
|
|
154
|
+
loaded.
|
|
152
155
|
|
|
153
156
|
## Troubleshooting
|
|
154
157
|
|
|
155
|
-
| symptom
|
|
156
|
-
|
|
|
157
|
-
| `init`: skills "nothing linked", or hooks that fail to start
|
|
158
|
-
| `paperlint lint`: `no papers in papers/`
|
|
159
|
-
| hooks fail with `Cannot find module` in a fresh clone
|
|
160
|
-
| `paperlint: not built`
|
|
161
|
-
| a skill does not show up in Claude Code
|
|
162
|
-
| **every** shell command is blocked in Claude Code
|
|
163
|
-
|
|
|
158
|
+
| symptom | cause and fix |
|
|
159
|
+
| ----------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
160
|
+
| `init`: skills "nothing linked", or hooks that fail to start | the package is not installed in this project (`npx` ran a temporary copy). Run `npm i -D paperlint`, then `npx paperlint init` again |
|
|
161
|
+
| `paperlint lint`: `no papers in papers/` | there is no paper where `papersDir` points. Create one with `npx paperlint new <name>`, or set `"papersDir"` in `paperlint.json` |
|
|
162
|
+
| hooks fail with `Cannot find module` in a fresh clone | the hook commands run files in `node_modules`: run `npm install` |
|
|
163
|
+
| `paperlint: not built` | installed from git with `--ignore-scripts`, or a clone before building: run `npm run build` in the package |
|
|
164
|
+
| a skill does not show up in Claude Code | its name was already taken in `.claude/skills/`. `init` names it and leaves it alone; rename or remove yours and run `npx paperlint init` again |
|
|
165
|
+
| **every** shell command is blocked in Claude Code | `paper-edit-guard` cannot parse the root `paperlint.json` (merge-conflict markers, a typo), and refuses rather than guess. Fix it with a normal file edit — file edits are not blocked |
|
|
166
|
+
| a Write of a new file is denied: "… is at the root of a paper folder" or "… is loose at the top of the paper's repro/ folder" | `paper-folder-layout` refuses to create an entry the paper layout does not allow; the reason says where it goes. Write it there. Existing files are never refused, and the hook does not see shell moves |
|
|
167
|
+
| anything else | `npx paperlint doctor` — it checks the setup and exits non-zero on anything miswired |
|
package/docs/layout.md
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# Where things live, and what checks them when
|
|
2
|
+
|
|
3
|
+
A paper moves through eight stages ([the flow](#the-flow)). Each stage writes into one
|
|
4
|
+
place, and a check guards that place. This page is the map: the places, who writes each one, and the
|
|
5
|
+
moment each check runs. The skills, stage by stage: [`skills.md`](skills.md).
|
|
6
|
+
|
|
7
|
+
## The flow
|
|
8
|
+
|
|
9
|
+
Each box names the stage's skills, what it writes, and what checks it. Stage 3 is drawn from the
|
|
10
|
+
inside: a study's pre-registration and its human labels are made there.
|
|
11
|
+
|
|
12
|
+
```mermaid
|
|
13
|
+
flowchart TB
|
|
14
|
+
N["<b>paperlint new</b><br/>creates the paper folder<br/>checked from here on:<br/>every lint · paper/allowed-files-only<br/>every new file · hook paper-folder-layout"]
|
|
15
|
+
S1["<b>1 · idea</b><br/>research-ideate · map-prior-work<br/>analyze-sibling-paper<br/>writes: siblings/<br/>checked by: sibling/frontmatter"]
|
|
16
|
+
S2["<b>2 · venue</b><br/>find-venue · plan-paper-timeline<br/>study-accepted-papers, mode A or B<br/>writes: paperlint.json, a report in reviews/<br/>checked by: review/frontmatter"]
|
|
17
|
+
V[("<b>#lt;papers-root#gt;/venues/#lt;venue#gt;/</b><br/>beside the papers, not in one:<br/>the venue's accepted papers,<br/>shared by every paper aimed at it<br/>checked by: nothing")]
|
|
18
|
+
subgraph S3["3 · study: repro/#lt;slug#gt;-YYYY-MM-DD/"]
|
|
19
|
+
direction TB
|
|
20
|
+
D["<b>design</b> · build-benchmark<br/>writes: the study's README.md<br/>checked by: repro/allowed-files-only"]
|
|
21
|
+
P["<b>pre-register</b> · build-benchmark<br/>writes: prereg.json, before the draw<br/>checked by: study/declare-sample (experimental, off)"]
|
|
22
|
+
A["<b>author check</b> · you see the drawn units<br/>writes: author_check in prereg.json<br/>checked by: study/declare-sample (experimental, off)"]
|
|
23
|
+
R["<b>run</b> · your scripts<br/>writes: the study folder,<br/>repro/tools/, repro/data/<br/>checked by: repro/allowed-files-only"]
|
|
24
|
+
L["<b>labels</b> · build-label-page<br/>a phone page; the answers go<br/>into the study's data/"]
|
|
25
|
+
Y["<b>analysis</b> · build-benchmark<br/>writes: the numbers, NOTES.md"]
|
|
26
|
+
D --> P --> A --> R --> L --> Y
|
|
27
|
+
end
|
|
28
|
+
S4["<b>4 · draft</b><br/>draft-paper · argument-arc · tighten-paper<br/>writes: paper.tex, sections/, figures/<br/>checked by: the tex/* rules<br/>hook paper-edit-guard: no shell writes"]
|
|
29
|
+
S5["<b>5 · review</b><br/>grade-paper-writing · verify-citations<br/>pc-panel-review · harden-paper<br/>study-accepted-papers, mode C or D<br/>writes: reviews/, the scorecard<br/>in PIPELINE-STATUS.md<br/>checked by: review/frontmatter"]
|
|
30
|
+
S6["<b>6 · submit</b><br/>paperlint build · submit-paper<br/>writes: paper.pdf, _build/,<br/>versions/, submission/<br/>checked by: format/page-limit, pdf/*,<br/>anonymity/identity, paper/stages"]
|
|
31
|
+
S7["<b>7 · camera-ready</b><br/>camera-ready<br/>writes: versions/, talk/<br/>checked by: paper/stages, talk/*"]
|
|
32
|
+
S8["<b>8 · extend</b><br/>extend-paper<br/>writes: a new paper folder"]
|
|
33
|
+
N --> S1 --> S2 --> D
|
|
34
|
+
Y --> S4 --> S5 --> S6 --> S7 --> S8
|
|
35
|
+
S2 -. fills .-> V
|
|
36
|
+
V -. read again .-> S5
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The cylinder is a venue's corpus of accepted papers: it lives beside the papers, not inside one
|
|
40
|
+
([`venues.md`](venues.md)).
|
|
41
|
+
|
|
42
|
+
## The map
|
|
43
|
+
|
|
44
|
+
The papers directory is `papersDir` in the project's `paperlint.json` (default `papers/`). A folder
|
|
45
|
+
in it is a paper when it holds `PIPELINE-STATUS.md`, `paper.tex` or `paperlint.json`; `paperlint new`
|
|
46
|
+
creates one.
|
|
47
|
+
|
|
48
|
+
<!-- layout:begin — drawn from src/domain/paper-layout.ts (PAPERS_LAYOUT_TREE); src/layout-docs.test.ts fails when this block differs -->
|
|
49
|
+
|
|
50
|
+
```text
|
|
51
|
+
<papers-root>/
|
|
52
|
+
├── venues/ ← outside every paper folder: one folder per venue
|
|
53
|
+
│ └── <venue>/ ← that venue's accepted papers, shared by every paper aimed at it
|
|
54
|
+
└── <paper>/ ← one folder per paper, named after the work; its root holds only what is below
|
|
55
|
+
├── PIPELINE-STATUS.md ← the paper's one live-state file: stages, plan, scorecard
|
|
56
|
+
├── paper.tex ← the source; `paperlint build` compiles it
|
|
57
|
+
├── paperlint.json ← the paper's settings
|
|
58
|
+
├── README.md ← what the paper is
|
|
59
|
+
├── CLAUDE.md ← the paper's agent rules
|
|
60
|
+
├── CLAIMS.md ← the claims ledger
|
|
61
|
+
├── NOTES.md ← each number in the paper → the data it comes from
|
|
62
|
+
├── SUBMIT-CHECKLIST.md ← the venue's format and submission mechanics
|
|
63
|
+
├── .gitignore ← keeps the build's byproducts out of git
|
|
64
|
+
├── paper.pdf ← the built PDF
|
|
65
|
+
├── *.tex *.bib *.cls *.sty *.bst ← what TeX and bibtex look up beside paper.tex
|
|
66
|
+
├── _build/ ← the facts `paperlint build` writes
|
|
67
|
+
├── versions/ ← each stage's frozen PDF and source
|
|
68
|
+
├── reviews/ ← dated reviews and pass reports
|
|
69
|
+
├── siblings/ ← the cards of competing papers
|
|
70
|
+
├── research/ ← dated research and decision records
|
|
71
|
+
├── repro/ ← the reproduction artifact
|
|
72
|
+
│ ├── README.md ← the index: one line per study
|
|
73
|
+
│ ├── .gitignore ← keeps the scripts' byproducts out of git
|
|
74
|
+
│ ├── tools/ ← scripts used across the paper (numbers, figures, anonymity check, harnesses)
|
|
75
|
+
│ ├── data/ ← shared data (tables, caches)
|
|
76
|
+
│ └── <slug>-YYYY-MM-DD/ ← one folder per study or spike (<slug>-YYYY-MM for one that ran over weeks)
|
|
77
|
+
│ └── README.md ← required: what it asks, how to run it, what it found
|
|
78
|
+
├── figures/ ← graphics and their sources
|
|
79
|
+
├── sections/ ← the body, when it is split
|
|
80
|
+
├── talk/ ← the talk's files
|
|
81
|
+
├── submission/ ← forms, portal records, mail with the venue, the anonymized upload
|
|
82
|
+
└── extra/ ← anything; never judged
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
<!-- layout:end -->
|
|
86
|
+
|
|
87
|
+
Two places with similar names are not in this drawing:
|
|
88
|
+
|
|
89
|
+
- `venues/` at the **project root** holds your own venue presets and their cards
|
|
90
|
+
(`venues/<name>.jsonc`, `venues/<name>.md`), for a venue paperlint does not ship.
|
|
91
|
+
- `<papers-root>/venues/<venue>/` (drawn above) holds a venue's **accepted papers**.
|
|
92
|
+
|
|
93
|
+
Both are explained in [`venues.md`](venues.md).
|
|
94
|
+
|
|
95
|
+
## Each place: who writes it, and what checks it
|
|
96
|
+
|
|
97
|
+
"Stage" is the stage of [the pipeline](#the-flow) that writes the place first.
|
|
98
|
+
"Checked by" is the rule `paperlint lint` runs over it; "nothing" means no rule reads its content.
|
|
99
|
+
|
|
100
|
+
| place | stage | written by | checked by |
|
|
101
|
+
| ------------------------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------ |
|
|
102
|
+
| `<papers-root>/venues/<venue>/` | 2 venue | `study-accepted-papers`, its first run for that venue (mode A, usually) | nothing ([why](venues.md#what-checks-it)) |
|
|
103
|
+
| the paper folder's root | before 1 | `paperlint new`: the three files, and an empty `.gitkeep` folder for `reviews/`, `research/`, `figures/`, `versions/`, `submission/`, `repro/tools/`, `repro/data/` (`repro/` gets a stub index) | [`paper/allowed-files-only`](rules/paper/allowed-files-only.md); the hook `paper-folder-layout` refuses a new stray entry |
|
|
104
|
+
| `PIPELINE-STATUS.md` | every stage | `paperlint new`, then `paper-pipeline`, `paper-status`; `study-accepted-papers` (the scorecard) | `paper/stages`, `paper/source`, [`cycle/stage`](rules/cycle/stage.md) ([rules](rules.md)) |
|
|
105
|
+
| `paperlint.json` | before 1, then 2 | `paperlint new`; `find-venue` names the venue | `paperlint lint` refuses an unknown key; [`cycle/record`](rules/cycle/record.md) |
|
|
106
|
+
| `siblings/` | 1 idea | `map-prior-work`, `analyze-sibling-paper` | `sibling/frontmatter` ([records](configuration.md#records-in-frontmatter-checked-by-shipped-json-schemas)) |
|
|
107
|
+
| `reviews/` | 2, then 4–5 | `study-accepted-papers` (its report), `grade-paper-writing`, `cold-read-diff`, the review skills | `review/frontmatter` ([records](configuration.md#records-in-frontmatter-checked-by-shipped-json-schemas)) |
|
|
108
|
+
| `research/` | any | you and the skills: dated research and decision records | nothing |
|
|
109
|
+
| `repro/`, its top | 3 study | `build-benchmark`, your scripts | [`repro/allowed-files-only`](rules/repro/allowed-files-only.md); the hook `paper-folder-layout` refuses a new loose entry |
|
|
110
|
+
| `repro/<slug>-YYYY-MM-DD/` | 3 study | `build-benchmark` (the design, in its `README.md`) | [`repro/allowed-files-only`](rules/repro/allowed-files-only.md): the dated name, and a `README.md` in it |
|
|
111
|
+
| `repro/<slug>-YYYY-MM-DD/prereg.json` | 3 study | `build-benchmark`, before the sample is drawn; you add the author's check | [`study/declare-sample`](rules/study/declare-sample.md) |
|
|
112
|
+
| `repro/<slug>-YYYY-MM-DD/data/` | 3 study | `build-label-page` exports the labels here | nothing |
|
|
113
|
+
| `repro/tools/`, `repro/data/` | 3 study | your scripts; `paperlint build` keeps `repro/data/references-cache.json` | nothing inside them |
|
|
114
|
+
| `NOTES.md` | 3, then 4 | you: each number → the data it comes from; `build-label-page` adds a line per label file | nothing |
|
|
115
|
+
| `paper.tex`, `sections/`, `*.bib` | 4 draft | `draft-paper`, `argument-arc`, `tighten-paper` | the `tex/*`, `paper/*` and `bib/*` rules ([rules](rules.md)); the hook `paper-edit-guard` refuses a shell write |
|
|
116
|
+
| `CLAIMS.md`, `figures/` | 4 draft | you | nothing |
|
|
117
|
+
| `paper.pdf`, `_build/` | 6 submit | `paperlint build` | `pdf/*`, [`format/page-limit`](rules/format/page-limit.md), [`anonymity/identity`](rules/anonymity/identity.md), the reference rules |
|
|
118
|
+
| `versions/` | 6, then 7 | you, at submission and at camera-ready (`submit-paper` says how): the frozen PDF and source of each stage | `paper/stages`, `paper/source` |
|
|
119
|
+
| `submission/`, `SUBMIT-CHECKLIST.md` | 6 submit | you, while `submit-paper` and `submission-portal` do the submitting: forms, portal records, mail with the venue | [`cycle/evidence`](rules/cycle/evidence.md), for the files a closed cycle names |
|
|
120
|
+
| `talk/` | 7 camera-ready | you | the `talk/*` rules ([talk](talk.md)) |
|
|
121
|
+
| `extra/` | any | you | nothing, ever |
|
|
122
|
+
|
|
123
|
+
## What runs when
|
|
124
|
+
|
|
125
|
+
A check runs at one of four moments:
|
|
126
|
+
|
|
127
|
+
- **Before a write** — a Claude Code hook. It sees an agent's Edit or Write, not a shell `mv` or a
|
|
128
|
+
script, so it saves a round trip and guarantees nothing.
|
|
129
|
+
- **On lint** — `paperlint lint`, when you run it. Every rule runs, whatever wrote the files. This is
|
|
130
|
+
the guarantee. No hook runs it for you.
|
|
131
|
+
- **In CI** — the same lint, on every push, if the project has the workflow `paperlint init` offers.
|
|
132
|
+
The lint-only job skips what needs a build (pages, fonts, references).
|
|
133
|
+
- **On demand** — a skill, when you ask for what it does. A skill stops nothing; it writes.
|
|
134
|
+
|
|
135
|
+
| what | kind | when it runs | what it stops |
|
|
136
|
+
| ------------------------------------------------------------------------------------------- | ----- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
|
|
137
|
+
| `paper-folder-layout` | hook | before an agent creates a file (Edit, Write) | a new entry the layout does not allow, at a paper's root or the top of its `repro/`; never an existing file |
|
|
138
|
+
| `paper-edit-guard` | hook | before an agent's shell command | a shell command that writes or moves a paper's source, which would skip the hooks that run after an edit |
|
|
139
|
+
| `paper-skills-nudge` | hook | after an agent edits a paper's source | nothing: it shows the agent the pre-submit checklist |
|
|
140
|
+
| `paper-status-gates` | hook | after an agent edits a paper's source | nothing: it prints the paper's readiness and its unrun gates, for a person reading the transcript |
|
|
141
|
+
| [`paper/allowed-files-only`](rules/paper/allowed-files-only.md) | rule | every `paperlint lint`, and CI | a stray file or folder at a paper's root (error) |
|
|
142
|
+
| [`repro/allowed-files-only`](rules/repro/allowed-files-only.md) | rule | every `paperlint lint`, and CI | a loose entry at the top of `repro/`, an undated study folder, a study folder without `README.md` (error) |
|
|
143
|
+
| [`study/declare-sample`](rules/study/declare-sample.md) | rule | every `paperlint lint`, and CI, once a paper turns it on | a study's `prereg.json` without its population, strata, screens, coverage or the author's check (experimental, off by default) |
|
|
144
|
+
| [`paper/folder-venue-leftover`](rules/paper/folder-venue-leftover.md) | rule | every `paperlint lint`, and CI | nothing: it warns when the folder is named after another venue |
|
|
145
|
+
| `review/frontmatter`, `sibling/frontmatter` | rule | every `paperlint lint`, and CI | a review whose findings break the schema (error); a sibling card that does not say how much was read (warning) |
|
|
146
|
+
| `paper/stages`, `paper/source` | rule | every `paperlint lint`, and CI | a stage whose frozen PDF or source is missing or changed (error) |
|
|
147
|
+
| the rules on the source (`tex/*`, `paper/*`, `bib/*`) | rule | every `paperlint lint`, and CI | what each one's [row](rules.md) says |
|
|
148
|
+
| the rules on what `paperlint build` measured (`pdf/*`, `format/page-limit`, the references) | rule | every `paperlint lint` after a build; CI's full job | a PDF over the page limit, in the wrong font or format, or with a bad reference |
|
|
149
|
+
| `study-accepted-papers` | skill | when you ask; stage 2 (modes A, B) and stage 5 (modes C, D) | nothing: it fills the venue's corpus, and writes the strong-accept scorecard in `PIPELINE-STATUS.md` |
|
|
150
|
+
| `build-benchmark` | skill | when you ask; stage 3 | nothing: it writes the study's design and its `prereg.json` |
|
|
151
|
+
| `build-label-page` | skill | when you ask; stage 3 | nothing: it builds the labelling page, and exports the answers into the study's `data/` |
|
|
152
|
+
|
|
153
|
+
The hooks are wired by `paperlint init` ([`install.md`](install.md)). A rule's level and options:
|
|
154
|
+
[`rules.md`](rules.md).
|
package/docs/optional-rules.md
CHANGED
|
@@ -8,10 +8,11 @@ rules apply to that paper. The root `paperlint.json` can turn it on for every pa
|
|
|
8
8
|
with a block ([`configuration.md`](configuration.md#the-rules-key-turning-rules-on-and-off)); a
|
|
9
9
|
paper's own file still has the last word for that paper.
|
|
10
10
|
|
|
11
|
-
| rule
|
|
12
|
-
|
|
|
13
|
-
| `pdf/last-page-balance`
|
|
14
|
-
| [`tex/heading-case`](rules/tex/heading-case.md)
|
|
11
|
+
| rule | what it checks | who needs it |
|
|
12
|
+
| ------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
13
|
+
| `pdf/last-page-balance` | the two columns of the last page end at about the same height | two-column papers whose publisher asks for it — see below |
|
|
14
|
+
| [`tex/heading-case`](rules/tex/heading-case.md) | the words of the paper's title and of each heading are in the capitalization the venue asks | papers whose venue names a case style paperlint builds; only the AgenticDev preset turns it on (`chicago-headline` for the title and every heading) — [page](rules/tex/heading-case.md) |
|
|
15
|
+
| [`study/declare-sample`](rules/study/declare-sample.md) | experimental: a study's `prereg.json` declares its population, screens, coverage and the author's check of the drawn units | papers with a sampled study; no preset turns it on — [page](rules/study/declare-sample.md) |
|
|
15
16
|
|
|
16
17
|
## `pdf/last-page-balance`
|
|
17
18
|
|
package/docs/references.md
CHANGED
|
@@ -61,18 +61,21 @@ is stale and `paper/sources-fresh` says so: build again to write it. A database
|
|
|
61
61
|
the paper directory, on its search path (`BIBINPUTS`), is not read: the step says which and
|
|
62
62
|
`paper/refs-checked` warns.
|
|
63
63
|
|
|
64
|
-
## `repro/references-cache.json` — commit it
|
|
64
|
+
## `repro/data/references-cache.json` — commit it
|
|
65
65
|
|
|
66
66
|
Asking five services about every entry is slow. DBLP asks clients to pause between requests, and a
|
|
67
67
|
slow service is retried. Before this cache existed, a 27-reference paper spent 217 seconds on the
|
|
68
68
|
check, on every build, and a 51-reference paper did not finish inside a 12-minute CI job
|
|
69
69
|
([#107](https://github.com/zernie/paperlint/issues/107)).
|
|
70
70
|
|
|
71
|
-
So the build keeps every answer it receives in `<paper>/repro/references-cache.json`, and the next
|
|
71
|
+
So the build keeps every answer it receives in `<paper>/repro/data/references-cache.json`, and the next
|
|
72
72
|
build asks only what that file cannot answer:
|
|
73
73
|
|
|
74
74
|
- An unchanged bibliography whose answers are under 30 days old asks nothing and makes no network request at all, not even the check
|
|
75
75
|
for whether the services can be reached.
|
|
76
|
+
- A cache at the old place, `repro/references-cache.json`, is not read: `repro/allowed-files-only` reports
|
|
77
|
+
it with the command that moves it (`git mv repro/references-cache.json repro/data/`). Until it is
|
|
78
|
+
moved, the build asks every question again.
|
|
76
79
|
- Adding or editing an entry asks only about that entry. Answers are stored per identifier (DOI,
|
|
77
80
|
arXiv id, or title), so changing an entry's DOI or title is what makes it be asked again.
|
|
78
81
|
- A request that failed is not an answer and is not stored, so the next build asks it again.
|