paperlint 9.0.0 → 10.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/.github/CLAUDE.md +22 -0
- package/.github/CLAUDE.md.spec.ts +20 -0
- package/CLAUDE.md +59 -515
- package/CONTRIBUTING.md +2 -2
- package/README.md +68 -128
- package/dist/CLAUDE.md.spec.d.ts +3 -0
- package/dist/CLAUDE.md.spec.d.ts.map +1 -0
- package/dist/CLAUDE.md.spec.js +62 -0
- package/dist/CLAUDE.md.spec.js.map +1 -0
- package/dist/build.d.ts +1 -1
- package/dist/build.js +2 -2
- 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/CLAUDE.md.spec.d.ts +3 -0
- package/dist/eslint-rules/CLAUDE.md.spec.d.ts.map +1 -0
- package/dist/eslint-rules/CLAUDE.md.spec.js +39 -0
- package/dist/eslint-rules/CLAUDE.md.spec.js.map +1 -0
- package/dist/eslint-rules/install-path-literals.d.ts +1 -1
- package/dist/eslint-rules/install-path-literals.js +4 -4
- package/dist/eslint-rules/install-path-literals.js.map +1 -1
- package/dist/eslint-rules/pdf-last-page-balance.js +1 -1
- 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/lib/agent-cli-version.js +1 -1
- package/dist/lib/agent-cli-version.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/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/tex-requirements.js +1 -1
- package/dist/toolchain.js +1 -1
- package/docs/ci.md +60 -0
- package/docs/configuration.md +2 -0
- package/docs/e2e.md +3 -3
- package/docs/incidents.md +5 -5
- 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 +6 -3
- package/docs/venues.md +94 -0
- package/eslint-rules/CLAUDE.md +44 -0
- package/eslint-rules/CLAUDE.md.spec.ts +43 -0
- package/eslint-rules/install-path-literals.harness.mjs +1 -1
- package/eslint-rules/install-path-literals.ts +4 -4
- package/eslint-rules/pdf-last-page-balance.ts +1 -1
- package/eslint-rules/prereg-coverage.test.ts +448 -0
- package/eslint-rules/prereg-coverage.ts +419 -0
- package/eslint.config.mjs +6 -3
- package/hooks/CLAUDE.md +34 -0
- package/hooks/CLAUDE.md.spec.ts +30 -0
- package/lib/agent-cli-version.ts +1 -1
- package/lib/skill-trigger-cases.harness.mjs +51 -5
- package/lib/skill-trigger-cases.mjs +53 -15
- package/package.json +2 -2
- package/plugin/CLAUDE.md +22 -0
- package/plugin/CLAUDE.md.spec.ts +22 -0
- package/plugin/hooks/hooks.json +9 -0
- package/scripts/coverage-config.test.ts +2 -1
- package/skills/CLAUDE.md +19 -0
- package/skills/CLAUDE.md.spec.ts +18 -0
- 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 +14 -1
- package/skills/build-benchmark/SKILL.md.spec.ts +13 -0
- package/skills/build-label-page/SKILL.md +118 -0
- package/skills/build-label-page/SKILL.md.spec.ts +129 -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/map-prior-work/SKILL.md +2 -2
- package/skills/map-prior-work/SKILL.md.spec.ts +1 -1
- package/skills/paper-pipeline/SKILL.md +8 -6
- package/skills/paper-pipeline/SKILL.md.spec.ts +7 -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/plan-paper-timeline/plan-paper-timeline.effects.harness.mjs +21 -102
- 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/CLAUDE.md +23 -1
- package/src/CLAUDE.md.spec.ts +72 -0
- package/src/build.ts +2 -2
- 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/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/src/tex-requirements.ts +1 -1
- package/src/toolchain.ts +1 -1
- package/templates/paper/PIPELINE-STATUS.md +41 -7
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE PAPER FOLDER'S LAYOUT — what may stand at the root of a paper folder, and nothing else.
|
|
3
|
+
*
|
|
4
|
+
* A paper folder collects files the way a desk does: plans, mails, three drafts of the PDF, a corpus,
|
|
5
|
+
* an old attempt's checklist. Each was put there for a reason, and after a few months nobody can say
|
|
6
|
+
* which file is current, which folder holds the evidence, or where a new thing goes. A strict root is
|
|
7
|
+
* the answer every build tool gives (Cargo's `src/`, a Maven layout): the root holds a small, known
|
|
8
|
+
* set, every known kind of material has one folder, and ONE escape hatch, `extra/`, takes the rest
|
|
9
|
+
* without judging it.
|
|
10
|
+
*
|
|
11
|
+
* ── WHERE THE SET COMES FROM ─────────────────────────────────────────────────────
|
|
12
|
+
* Each entry is a file or folder paperlint itself writes or reads, or one its skills name at the
|
|
13
|
+
* paper root (each carries its note below, which the drawing of the layout shows):
|
|
14
|
+
* - what `paperlint new` scaffolds: `PIPELINE-STATUS.md`, `paper.tex`, `paperlint.json`;
|
|
15
|
+
* - what the build writes: `paper.pdf` and `_build/`, and TeX's own byproducts beside `paper.tex`
|
|
16
|
+
* (pdflatex runs in the paper folder without `-output-directory`), which are never reported;
|
|
17
|
+
* - what the rules read: `versions/` (`paper/stages`), `reviews/` (`review/frontmatter`),
|
|
18
|
+
* `siblings/` (`sibling/frontmatter`), `talk/` (the `talk/` rules' default folder);
|
|
19
|
+
* - what the skills read or write at the root: `README.md`, `CLAUDE.md`, `CLAIMS.md`, `NOTES.md`,
|
|
20
|
+
* `SUBMIT-CHECKLIST.md`, `research/`, `repro/`, `figures/`, `submission/`;
|
|
21
|
+
* - where the paper's own body lives when it is split: `sections/` (README's `\input{sections/intro}`);
|
|
22
|
+
* - the files TeX and bibtex look up in the folder they run in: `*.tex`, `*.bib`, `*.cls`, `*.sty`,
|
|
23
|
+
* `*.bst`.
|
|
24
|
+
* A venue's corpus of accepted papers is NOT here: it is shared by every paper for that venue and
|
|
25
|
+
* lives outside paper folders, in `<papers>/venues/<venue>/`.
|
|
26
|
+
*
|
|
27
|
+
* ── WHAT THE PAPER DECLARES ──────────────────────────────────────────────────────
|
|
28
|
+
* A paper's settings may move three of these: `pdf` (the built PDF under another name), `talk.dir`
|
|
29
|
+
* (another talk folder) and a preset file of its own named by `extends`. What the settings name at the
|
|
30
|
+
* root is allowed beside the fixed set (`Declared.roots`); this module does not read settings.
|
|
31
|
+
*/
|
|
32
|
+
import { basename, extname } from "node:path";
|
|
33
|
+
import { leaf, renderTree } from "./layout-tree.js";
|
|
34
|
+
import { REPRO_DIR, REPRO_NODES } from "./repro-layout.js";
|
|
35
|
+
export const NOTHING_DECLARED = { roots: [] };
|
|
36
|
+
/** The one folder whose content is not judged. */
|
|
37
|
+
export const ESCAPE_HATCH = "extra";
|
|
38
|
+
/** The files the root may hold, by exact name, each with what it is for. */
|
|
39
|
+
export const ROOT_FILE_NOTES = [
|
|
40
|
+
{
|
|
41
|
+
name: "PIPELINE-STATUS.md",
|
|
42
|
+
note: "the paper's one live-state file: stages, plan, scorecard",
|
|
43
|
+
},
|
|
44
|
+
{ name: "paper.tex", note: "the source; `paperlint build` compiles it" },
|
|
45
|
+
{ name: "paperlint.json", note: "the paper's settings" },
|
|
46
|
+
{ name: "README.md", note: "what the paper is" },
|
|
47
|
+
{ name: "CLAUDE.md", note: "the paper's agent rules" },
|
|
48
|
+
{ name: "CLAIMS.md", note: "the claims ledger" },
|
|
49
|
+
{
|
|
50
|
+
name: "NOTES.md",
|
|
51
|
+
note: "each number in the paper → the data it comes from",
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
name: "SUBMIT-CHECKLIST.md",
|
|
55
|
+
note: "the venue's format and submission mechanics",
|
|
56
|
+
},
|
|
57
|
+
{ name: ".gitignore", note: "keeps the build's byproducts out of git" },
|
|
58
|
+
{ name: "paper.pdf", note: "the built PDF" },
|
|
59
|
+
];
|
|
60
|
+
/** The files the root may hold, by exact name. */
|
|
61
|
+
export const ROOT_FILES = ROOT_FILE_NOTES.map((f) => f.name);
|
|
62
|
+
/** The folders the root may hold, by exact name, each with what it holds. */
|
|
63
|
+
export const ROOT_DIR_NOTES = [
|
|
64
|
+
{ name: "_build", note: "the facts `paperlint build` writes" },
|
|
65
|
+
{ name: "versions", note: "each stage's frozen PDF and source" },
|
|
66
|
+
{ name: "reviews", note: "dated reviews and pass reports" },
|
|
67
|
+
{ name: "siblings", note: "the cards of competing papers" },
|
|
68
|
+
{ name: "research", note: "dated research and decision records" },
|
|
69
|
+
{ name: REPRO_DIR, note: "the reproduction artifact" },
|
|
70
|
+
{ name: "figures", note: "graphics and their sources" },
|
|
71
|
+
{ name: "sections", note: "the body, when it is split" },
|
|
72
|
+
{ name: "talk", note: "the talk's files" },
|
|
73
|
+
{
|
|
74
|
+
name: "submission",
|
|
75
|
+
note: "forms, portal records, mail with the venue, the anonymized upload",
|
|
76
|
+
},
|
|
77
|
+
{ name: ESCAPE_HATCH, note: "anything; never judged" },
|
|
78
|
+
];
|
|
79
|
+
/** The folders the root may hold, by exact name. */
|
|
80
|
+
export const ROOT_DIRS = ROOT_DIR_NOTES.map((d) => d.name);
|
|
81
|
+
/**
|
|
82
|
+
* The files TeX and bibtex look up in the folder they run in, which is the paper's root: a fragment
|
|
83
|
+
* `\input` names, a database, a class, a package, a bibliography style.
|
|
84
|
+
*/
|
|
85
|
+
export const TEX_INPUT_EXTENSIONS = [
|
|
86
|
+
".tex",
|
|
87
|
+
".bib",
|
|
88
|
+
".cls",
|
|
89
|
+
".sty",
|
|
90
|
+
".bst",
|
|
91
|
+
];
|
|
92
|
+
/**
|
|
93
|
+
* The extensions of what a TeX run writes next to its main file, named after the job. The list is
|
|
94
|
+
* the union of latexmk's clean lists (`@generated_exts`, `$clean_ext` and `$clean_full_ext` in the
|
|
95
|
+
* latexmk documentation, the files `latexmk -c` and `-C` delete) and the outputs of the tools
|
|
96
|
+
* `paperlint build` and a hand run use on the same job: pdflatex (`aux log out toc lof lot lol fls
|
|
97
|
+
* xdv dvi`, `synctex.gz` with `-synctex`), the algorithm packages' `\listofalgorithms` (`loa`),
|
|
98
|
+
* bibtex (`bbl blg`), makeindex (`idx ind ilg`), glossaries and nomencl (`glo gls glg acn acr alg ist
|
|
99
|
+
* nlo nls`), biber and biblatex (`bcf run.xml`), beamer (`nav snm vrb`), and latexmk's own
|
|
100
|
+
* `fdb_latexmk`. A missing extension is added here, not
|
|
101
|
+
* special-cased where the rule is judged.
|
|
102
|
+
*/
|
|
103
|
+
const BYPRODUCT_EXTENSIONS = [
|
|
104
|
+
"aux",
|
|
105
|
+
"log",
|
|
106
|
+
"out",
|
|
107
|
+
"toc",
|
|
108
|
+
"lof",
|
|
109
|
+
"lot",
|
|
110
|
+
"lol",
|
|
111
|
+
"loa",
|
|
112
|
+
"fls",
|
|
113
|
+
"xdv",
|
|
114
|
+
"dvi",
|
|
115
|
+
"synctex.gz",
|
|
116
|
+
"bbl",
|
|
117
|
+
"blg",
|
|
118
|
+
"idx",
|
|
119
|
+
"ind",
|
|
120
|
+
"ilg",
|
|
121
|
+
"glo",
|
|
122
|
+
"gls",
|
|
123
|
+
"glg",
|
|
124
|
+
"acn",
|
|
125
|
+
"acr",
|
|
126
|
+
"alg",
|
|
127
|
+
"ist",
|
|
128
|
+
"nlo",
|
|
129
|
+
"nls",
|
|
130
|
+
"bcf",
|
|
131
|
+
"run.xml",
|
|
132
|
+
"nav",
|
|
133
|
+
"snm",
|
|
134
|
+
"vrb",
|
|
135
|
+
"fdb_latexmk",
|
|
136
|
+
];
|
|
137
|
+
/**
|
|
138
|
+
* What a `paperlint build` leaves beside `paper.tex`: pdflatex and bibtex run in the paper folder and
|
|
139
|
+
* name every output after the job, `paper`, so only `paper.<extension>` is the build's. Never
|
|
140
|
+
* reported — they are the build's, not the author's. Another job name (`draft.aux`) is the author's.
|
|
141
|
+
*/
|
|
142
|
+
export const BUILD_BYPRODUCTS = BYPRODUCT_EXTENSIONS.map((ext) => `paper.${ext}`);
|
|
143
|
+
/** Files the operating system writes into any folder it shows. Never reported. */
|
|
144
|
+
export const OS_FILES = [".DS_Store", "Thumbs.db"];
|
|
145
|
+
/** The live state of a paper — its stages, its plan, its scorecard — is one file. */
|
|
146
|
+
const STATUS_SECTIONS = 'a section of PIPELINE-STATUS.md — the paper\'s one live-state file holds its stages, its plan ("Plan / now") and its scorecard; move what is still live there and delete the file';
|
|
147
|
+
/** The shared corpus of a venue's accepted papers. */
|
|
148
|
+
const VENUE_CORPUS = "<papers-root>/venues/<venue>/, outside the paper folder: one corpus per venue, shared by every paper that targets it";
|
|
149
|
+
/**
|
|
150
|
+
* Names met in real paper folders, each with its one destination. Matched ignoring case, a file's
|
|
151
|
+
* name against files and a folder's against folders.
|
|
152
|
+
*/
|
|
153
|
+
export const KNOWN_CURES = [
|
|
154
|
+
{ name: "PLAN.md", kind: "file", cure: STATUS_SECTIONS },
|
|
155
|
+
{ name: "plans", kind: "dir", cure: STATUS_SECTIONS },
|
|
156
|
+
{ name: "DECISION-LOG.md", kind: "file", cure: "research/ (a dated record)" },
|
|
157
|
+
{
|
|
158
|
+
name: "EMAILS.md",
|
|
159
|
+
kind: "file",
|
|
160
|
+
cure: "submission/ (mail with the venue is about submitting)",
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
name: "data",
|
|
164
|
+
kind: "dir",
|
|
165
|
+
cure: "repro/data/ (the data behind the numbers)",
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
name: "artifact",
|
|
169
|
+
kind: "dir",
|
|
170
|
+
cure: "repro/ — its scripts in repro/tools/, its data in repro/data/; the anonymized copy uploaded for review is about submitting and goes in submission/",
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
name: "archive",
|
|
174
|
+
kind: "dir",
|
|
175
|
+
cure: "versions/ for frozen PDFs, submission/ for an earlier attempt's forms, mails and checklists, extra/ for the rest",
|
|
176
|
+
},
|
|
177
|
+
{ name: "venue-corpus", kind: "dir", cure: VENUE_CORPUS },
|
|
178
|
+
{ name: "venues", kind: "dir", cure: VENUE_CORPUS },
|
|
179
|
+
];
|
|
180
|
+
/** For a name nobody listed: the choice by what the material is. */
|
|
181
|
+
export const CURE_BY_KIND = "decide by what it is — a record or research → research/; about submitting (forms, mails, checklists, portal records) → submission/; live state of the paper (plan, status) → a section of PIPELINE-STATUS.md; reproduction (scripts, data, the artifact) → repro/; a frozen PDF of a stage → versions/; unclear → extra/, which is never judged";
|
|
182
|
+
const isAllowedFile = (name, declared) => ROOT_FILES.includes(name) ||
|
|
183
|
+
TEX_INPUT_EXTENSIONS.includes(extname(name)) ||
|
|
184
|
+
BUILD_BYPRODUCTS.includes(name) ||
|
|
185
|
+
OS_FILES.includes(name) ||
|
|
186
|
+
declared.roots.includes(name);
|
|
187
|
+
const isAllowed = (e, declared) => e.kind === "dir"
|
|
188
|
+
? ROOT_DIRS.includes(e.name) || declared.roots.includes(e.name)
|
|
189
|
+
: isAllowedFile(e.name, declared);
|
|
190
|
+
/** Where material like `e` belongs: its listed destination, else the choice by what it is. */
|
|
191
|
+
function cureFor(e) {
|
|
192
|
+
const known = KNOWN_CURES.find((c) => c.kind === e.kind && c.name.toLowerCase() === e.name.toLowerCase());
|
|
193
|
+
return known === undefined ? CURE_BY_KIND : known.cure;
|
|
194
|
+
}
|
|
195
|
+
/** The root entries that are not part of the layout, in the order given. Pure. */
|
|
196
|
+
export function judgeLayout(entries, declared) {
|
|
197
|
+
// `\include{chapter}` makes pdflatex write chapter.aux beside chapter.tex, under that file's own
|
|
198
|
+
// name, not the job's: the build's for every source at the root, the author's without one.
|
|
199
|
+
const includeAux = entries
|
|
200
|
+
.filter((e) => e.kind === "file" && extname(e.name) === ".tex")
|
|
201
|
+
.map((e) => `${basename(e.name, ".tex")}.aux`);
|
|
202
|
+
return entries
|
|
203
|
+
.filter((e) => !isAllowed(e, declared) &&
|
|
204
|
+
!(e.kind === "file" && includeAux.includes(e.name)))
|
|
205
|
+
.map((e) => ({
|
|
206
|
+
name: e.kind === "dir" ? `${e.name}/` : e.name,
|
|
207
|
+
kind: e.kind,
|
|
208
|
+
cure: cureFor(e),
|
|
209
|
+
}));
|
|
210
|
+
}
|
|
211
|
+
/** The paper folder's layout, entry by entry, `repro/` drawn with its own layout inside. */
|
|
212
|
+
export const PAPER_NODES = [
|
|
213
|
+
...ROOT_FILE_NOTES.map((f) => leaf(f.name, f.note)),
|
|
214
|
+
leaf(TEX_INPUT_EXTENSIONS.map((e) => `*${e}`).join(" "), "what TeX and bibtex look up beside paper.tex"),
|
|
215
|
+
...ROOT_DIR_NOTES.map((d) => ({
|
|
216
|
+
name: `${d.name}/`,
|
|
217
|
+
note: d.note,
|
|
218
|
+
children: d.name === REPRO_DIR ? REPRO_NODES : [],
|
|
219
|
+
})),
|
|
220
|
+
];
|
|
221
|
+
/** The drawing of the paper folder's layout: the rule's message, the hook's refusal, the rule's page. */
|
|
222
|
+
export const PAPER_LAYOUT_TREE = renderTree("<paper>/", PAPER_NODES);
|
|
223
|
+
/** The folder beside the paper folders that holds one corpus of accepted papers per venue. */
|
|
224
|
+
export const VENUES_DIR = "venues";
|
|
225
|
+
/**
|
|
226
|
+
* The papers directory as the README and `docs/layout.md` draw it: the venues' corpora beside the
|
|
227
|
+
* paper folders, and each paper folder with its layout. Only the paper folder's part is enforced (by
|
|
228
|
+
* the two layout rules); `venues/` is drawn so a reader sees where a corpus goes, and no rule reads it.
|
|
229
|
+
*/
|
|
230
|
+
export const PAPERS_NODES = [
|
|
231
|
+
{
|
|
232
|
+
name: `${VENUES_DIR}/`,
|
|
233
|
+
note: "outside every paper folder: one folder per venue",
|
|
234
|
+
children: [
|
|
235
|
+
leaf("<venue>/", "that venue's accepted papers, shared by every paper aimed at it"),
|
|
236
|
+
],
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
name: "<paper>/",
|
|
240
|
+
note: "one folder per paper, named after the work; its root holds only what is below",
|
|
241
|
+
children: PAPER_NODES,
|
|
242
|
+
},
|
|
243
|
+
];
|
|
244
|
+
/** The drawing of the papers directory: the README's and `docs/layout.md`'s map of where things live. */
|
|
245
|
+
export const PAPERS_LAYOUT_TREE = renderTree("<papers-root>/", PAPERS_NODES);
|
|
246
|
+
/**
|
|
247
|
+
* The one text a stray entry is reported with, by the rule `paper/allowed-files-only` and by the hook that
|
|
248
|
+
* refuses to create such an entry. It stands alone: where the entry goes, and the whole layout drawn,
|
|
249
|
+
* for a reader who knows nothing of paperlint.
|
|
250
|
+
*/
|
|
251
|
+
export function strayMessage(s) {
|
|
252
|
+
return [
|
|
253
|
+
`\`${s.name}\` is at the root of a paper folder (the folder holding PIPELINE-STATUS.md), and that root holds only paperlint's layout. Where it goes: ${s.cure}.`,
|
|
254
|
+
`The layout (${ESCAPE_HATCH}/ takes anything and is never judged; the build's paper.* byproducts are never reported):`,
|
|
255
|
+
PAPER_LAYOUT_TREE,
|
|
256
|
+
`Rule paper/allowed-files-only: https://github.com/zernie/paperlint/blob/main/docs/rules/paper/allowed-files-only.md`,
|
|
257
|
+
].join("\n");
|
|
258
|
+
}
|
|
259
|
+
//# sourceMappingURL=paper-layout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paper-layout.js","sourceRoot":"","sources":["../../src/domain/paper-layout.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { type TreeNode } from "./layout-tree.ts";
|
|
2
|
+
/** The folder this layout governs, at the paper folder's root. */
|
|
3
|
+
export declare const REPRO_DIR = "repro";
|
|
4
|
+
/** The index at the top of `repro/`, and the file every study folder holds. */
|
|
5
|
+
export declare const README = "README.md";
|
|
6
|
+
/** The files `repro/` may hold at its top, by exact name. */
|
|
7
|
+
export declare const REPRO_FILE_NOTES: readonly {
|
|
8
|
+
readonly name: string;
|
|
9
|
+
readonly note: string;
|
|
10
|
+
}[];
|
|
11
|
+
export declare const REPRO_FILES: readonly string[];
|
|
12
|
+
/** The shared folders `repro/` may hold besides its study folders. */
|
|
13
|
+
export declare const TOOLS_DIR = "tools";
|
|
14
|
+
export declare const DATA_DIR = "data";
|
|
15
|
+
export declare const REPRO_DIR_NOTES: readonly {
|
|
16
|
+
readonly name: string;
|
|
17
|
+
readonly note: string;
|
|
18
|
+
}[];
|
|
19
|
+
export declare const REPRO_DIRS: readonly string[];
|
|
20
|
+
/** The layout of `repro/`, entry by entry. */
|
|
21
|
+
export declare const REPRO_NODES: readonly TreeNode[];
|
|
22
|
+
/** The drawing of `repro/`'s layout: the rule's message, the hook's refusal, the rule's page. */
|
|
23
|
+
export declare const REPRO_LAYOUT_TREE: string;
|
|
24
|
+
/**
|
|
25
|
+
* What interpreters, package managers, test runners and the operating system write into the folder
|
|
26
|
+
* they run in. Never reported, whether a file or a folder.
|
|
27
|
+
*/
|
|
28
|
+
export declare const REPRO_BYPRODUCTS: readonly string[];
|
|
29
|
+
/** Whether `name` is a study folder's: `<slug>-YYYY-MM-DD` or `<slug>-YYYY-MM`, a real date. */
|
|
30
|
+
export declare function isStudyName(name: string): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* The study name to suggest for a folder named `name`: its name as a slug, with the date to fill in.
|
|
33
|
+
* A name that becomes a study name once lowercased and hyphenated is suggested as it is.
|
|
34
|
+
*/
|
|
35
|
+
export declare function suggestedStudyName(name: string): string;
|
|
36
|
+
/** The extensions of a script: what a study or the paper's build runs. */
|
|
37
|
+
export declare const SCRIPT_EXTENSIONS: readonly string[];
|
|
38
|
+
/** Names without a script's extension that still say how the tools run. */
|
|
39
|
+
export declare const TOOL_FILES: readonly string[];
|
|
40
|
+
/** The extensions of data: tables, records, caches, archives, raw output. */
|
|
41
|
+
export declare const DATA_EXTENSIONS: readonly string[];
|
|
42
|
+
/** The extensions of a note. */
|
|
43
|
+
export declare const NOTE_EXTENSIONS: readonly string[];
|
|
44
|
+
/** Where a script goes. */
|
|
45
|
+
export declare const SCRIPT_CURE = "repro/tools/ \u2014 the scripts used across the paper (numbers, figures, the anonymity check, harnesses); a script only one study runs goes in that study's folder instead";
|
|
46
|
+
/** Where data goes. */
|
|
47
|
+
export declare const DATA_CURE = "repro/data/ \u2014 the data shared across the paper (tables, caches); what one study's run produced goes in that study's folder instead";
|
|
48
|
+
/** Where a note goes. */
|
|
49
|
+
export declare const NOTE_CURE = "the dated folder of the study it is about (repro/<slug>-YYYY-MM-DD/), or the paper's research/ when it is research or a decision rather than the record of a run";
|
|
50
|
+
/** Where a file of any other kind goes. */
|
|
51
|
+
export declare const FILE_CURE_BY_KIND = "decide by what it is \u2014 a script \u2192 repro/tools/; data \u2192 repro/data/; a note \u2192 the dated folder of its study, or the paper's research/; what one study produced \u2192 that study's folder";
|
|
52
|
+
/** The files paperlint itself once kept at the top of `repro/`, each with where it is read now. */
|
|
53
|
+
export declare const MOVED_FILES: readonly {
|
|
54
|
+
readonly name: string;
|
|
55
|
+
readonly cure: string;
|
|
56
|
+
}[];
|
|
57
|
+
/** An entry at the top of `repro/`: a file or a folder, and for a folder whether it holds a README.md. */
|
|
58
|
+
export interface ReproEntry {
|
|
59
|
+
readonly name: string;
|
|
60
|
+
readonly kind: "file" | "dir";
|
|
61
|
+
readonly hasReadme: boolean;
|
|
62
|
+
}
|
|
63
|
+
/** What is wrong with an entry at the top of `repro/`. */
|
|
64
|
+
export interface ReproFinding {
|
|
65
|
+
/** The entry's path from the paper folder; a folder's ends in a slash. */
|
|
66
|
+
readonly path: string;
|
|
67
|
+
/** `stray`: not part of the layout. `no-readme`: a study folder without its README.md. */
|
|
68
|
+
readonly problem: "stray" | "no-readme";
|
|
69
|
+
/** Where it goes, or what to add. */
|
|
70
|
+
readonly cure: string;
|
|
71
|
+
}
|
|
72
|
+
/** The entries at the top of `repro/` that are out of place, at most one finding each, in order. Pure. */
|
|
73
|
+
export declare function judgeRepro(entries: readonly ReproEntry[]): readonly ReproFinding[];
|
|
74
|
+
/**
|
|
75
|
+
* The one text a finding is reported with, by the rule `repro/allowed-files-only` and by the hook that fires
|
|
76
|
+
* when such an entry is written. It stands alone: what is wrong, where the entry goes, and what
|
|
77
|
+
* `repro/` holds, for a reader who knows nothing of paperlint.
|
|
78
|
+
*/
|
|
79
|
+
export declare function reproMessage(f: ReproFinding): string;
|
|
80
|
+
//# sourceMappingURL=repro-layout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repro-layout.d.ts","sourceRoot":"","sources":["../../src/domain/repro-layout.ts"],"names":[],"mappings":"AA6BA,OAAO,EAAoB,KAAK,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEnE,kEAAkE;AAClE,eAAO,MAAM,SAAS,UAAU,CAAC;AAEjC,+EAA+E;AAC/E,eAAO,MAAM,MAAM,cAAc,CAAC;AAElC,6DAA6D;AAC7D,eAAO,MAAM,gBAAgB,EAAE,SAAS;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB,EAGA,CAAC;AACF,eAAO,MAAM,WAAW,EAAE,SAAS,MAAM,EAExC,CAAC;AAEF,sEAAsE;AACtE,eAAO,MAAM,SAAS,UAAU,CAAC;AACjC,eAAO,MAAM,QAAQ,SAAS,CAAC;AAC/B,eAAO,MAAM,eAAe,EAAE,SAAS;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB,EAMA,CAAC;AACF,eAAO,MAAM,UAAU,EAAE,SAAS,MAAM,EAAuC,CAAC;AAWhF,8CAA8C;AAC9C,eAAO,MAAM,WAAW,EAAE,SAAS,QAAQ,EAI1C,CAAC;AAEF,iGAAiG;AACjG,eAAO,MAAM,iBAAiB,EAAE,MAG/B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,SAAS,MAAM,EAU7C,CAAC;AAYF,gGAAgG;AAChG,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOjD;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQvD;AAED,0EAA0E;AAC1E,eAAO,MAAM,iBAAiB,EAAE,SAAS,MAAM,EAkB9C,CAAC;AAEF,2EAA2E;AAC3E,eAAO,MAAM,UAAU,EAAE,SAAS,MAAM,EAQvC,CAAC;AAEF,6EAA6E;AAC7E,eAAO,MAAM,eAAe,EAAE,SAAS,MAAM,EAqB5C,CAAC;AAEF,gCAAgC;AAChC,eAAO,MAAM,eAAe,EAAE,SAAS,MAAM,EAAyB,CAAC;AAEvE,2BAA2B;AAC3B,eAAO,MAAM,WAAW,+KACiJ,CAAC;AAE1K,uBAAuB;AACvB,eAAO,MAAM,SAAS,4IACgH,CAAC;AAEvI,yBAAyB;AACzB,eAAO,MAAM,SAAS,qKAC8I,CAAC;AAErK,2CAA2C;AAC3C,eAAO,MAAM,iBAAiB,iNACyJ,CAAC;AAExL,mGAAmG;AACnG,eAAO,MAAM,WAAW,EAAE,SAAS;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB,EAaA,CAAC;AAkBF,0GAA0G;AAC1G,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B;AAED,0DAA0D;AAC1D,MAAM,WAAW,YAAY;IAC3B,0EAA0E;IAC1E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,0FAA0F;IAC1F,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,WAAW,CAAC;IACxC,qCAAqC;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AA0BD,0GAA0G;AAC1G,wBAAgB,UAAU,CACxB,OAAO,EAAE,SAAS,UAAU,EAAE,GAC7B,SAAS,YAAY,EAAE,CAEzB;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,YAAY,GAAG,MAAM,CAWpD"}
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE LAYOUT OF A PAPER'S `repro/` — what may stand at its top, and nothing else.
|
|
3
|
+
*
|
|
4
|
+
* `repro/` is where a paper's evidence lives, and it fills up the way a desk does: one real paper had
|
|
5
|
+
* 120 entries at its top, about 70 study folders (some with no date) and about 50 loose scripts, data
|
|
6
|
+
* files and notes. Nobody could say which script produces which number, which study is current, or
|
|
7
|
+
* where a new run goes. The layout gives each kind of material one place:
|
|
8
|
+
*
|
|
9
|
+
* repro/
|
|
10
|
+
* ├── README.md the index: one line per study
|
|
11
|
+
* ├── <slug>-YYYY-MM-DD/ one folder per study or spike, with a README.md inside
|
|
12
|
+
* ├── tools/ scripts used across the paper (numbers, figures, anonymity check, harnesses)
|
|
13
|
+
* └── data/ shared data (tables, caches)
|
|
14
|
+
*
|
|
15
|
+
* plus `.gitignore`. A loose note belongs in its study's folder or in the paper's `research/`.
|
|
16
|
+
*
|
|
17
|
+
* ── THE DATE IN A STUDY'S NAME ────────────────────────────────────────────────────
|
|
18
|
+
* `<slug>-YYYY-MM-DD` is the day the study began. `<slug>-YYYY-MM` is accepted too: a study that ran
|
|
19
|
+
* over weeks (labelling, a reading of a corpus) has a month as its honest date, and both forms sort
|
|
20
|
+
* by time. The date must be a real one (no month 13, no 30 February). The slug is lowercase letters
|
|
21
|
+
* and digits in words joined by single hyphens.
|
|
22
|
+
*
|
|
23
|
+
* ── NEVER REPORTED ───────────────────────────────────────────────────────────────
|
|
24
|
+
* What interpreters, package managers and the operating system leave in any folder they run in
|
|
25
|
+
* (`__pycache__/`, `node_modules/`, `.DS_Store`, …): the scripts' byproducts, not the author's.
|
|
26
|
+
*
|
|
27
|
+
* Pure: the caller lists the folder and says which study folders hold a `README.md`.
|
|
28
|
+
*/
|
|
29
|
+
import { extname } from "node:path";
|
|
30
|
+
import { leaf, renderTree } from "./layout-tree.js";
|
|
31
|
+
/** The folder this layout governs, at the paper folder's root. */
|
|
32
|
+
export const REPRO_DIR = "repro";
|
|
33
|
+
/** The index at the top of `repro/`, and the file every study folder holds. */
|
|
34
|
+
export const README = "README.md";
|
|
35
|
+
/** The files `repro/` may hold at its top, by exact name. */
|
|
36
|
+
export const REPRO_FILE_NOTES = [
|
|
37
|
+
{ name: README, note: "the index: one line per study" },
|
|
38
|
+
{ name: ".gitignore", note: "keeps the scripts' byproducts out of git" },
|
|
39
|
+
];
|
|
40
|
+
export const REPRO_FILES = REPRO_FILE_NOTES.map((f) => f.name);
|
|
41
|
+
/** The shared folders `repro/` may hold besides its study folders. */
|
|
42
|
+
export const TOOLS_DIR = "tools";
|
|
43
|
+
export const DATA_DIR = "data";
|
|
44
|
+
export const REPRO_DIR_NOTES = [
|
|
45
|
+
{
|
|
46
|
+
name: TOOLS_DIR,
|
|
47
|
+
note: "scripts used across the paper (numbers, figures, anonymity check, harnesses)",
|
|
48
|
+
},
|
|
49
|
+
{ name: DATA_DIR, note: "shared data (tables, caches)" },
|
|
50
|
+
];
|
|
51
|
+
export const REPRO_DIRS = REPRO_DIR_NOTES.map((d) => d.name);
|
|
52
|
+
/** The study folder as the layout draws it: the name pattern, and the README.md it must hold. */
|
|
53
|
+
const STUDY_NODE = {
|
|
54
|
+
name: "<slug>-YYYY-MM-DD/",
|
|
55
|
+
note: "one folder per study or spike (<slug>-YYYY-MM for one that ran over weeks)",
|
|
56
|
+
children: [
|
|
57
|
+
leaf(README, "required: what it asks, how to run it, what it found"),
|
|
58
|
+
],
|
|
59
|
+
};
|
|
60
|
+
/** The layout of `repro/`, entry by entry. */
|
|
61
|
+
export const REPRO_NODES = [
|
|
62
|
+
...REPRO_FILE_NOTES.map((f) => leaf(f.name, f.note)),
|
|
63
|
+
...REPRO_DIR_NOTES.map((d) => leaf(`${d.name}/`, d.note)),
|
|
64
|
+
STUDY_NODE,
|
|
65
|
+
];
|
|
66
|
+
/** The drawing of `repro/`'s layout: the rule's message, the hook's refusal, the rule's page. */
|
|
67
|
+
export const REPRO_LAYOUT_TREE = renderTree(`${REPRO_DIR}/`, REPRO_NODES);
|
|
68
|
+
/**
|
|
69
|
+
* What interpreters, package managers, test runners and the operating system write into the folder
|
|
70
|
+
* they run in. Never reported, whether a file or a folder.
|
|
71
|
+
*/
|
|
72
|
+
export const REPRO_BYPRODUCTS = [
|
|
73
|
+
"__pycache__",
|
|
74
|
+
".pytest_cache",
|
|
75
|
+
".mypy_cache",
|
|
76
|
+
".ruff_cache",
|
|
77
|
+
".ipynb_checkpoints",
|
|
78
|
+
"node_modules",
|
|
79
|
+
".venv",
|
|
80
|
+
".DS_Store",
|
|
81
|
+
"Thumbs.db",
|
|
82
|
+
];
|
|
83
|
+
/** A study's name: a slug, then the year, the month, and optionally the day it began. */
|
|
84
|
+
const STUDY_NAME = /^([a-z0-9]+(?:-[a-z0-9]+)*)-(\d{4})-(\d{2})(?:-(\d{2}))?$/u;
|
|
85
|
+
const isLeapYear = (y) => (y % 4 === 0 && y % 100 !== 0) || y % 400 === 0;
|
|
86
|
+
/** The days in month `m` (1–12) of year `y`. */
|
|
87
|
+
const daysIn = (y, m) => m === 2 ? (isLeapYear(y) ? 29 : 28) : [4, 6, 9, 11].includes(m) ? 30 : 31;
|
|
88
|
+
/** Whether `name` is a study folder's: `<slug>-YYYY-MM-DD` or `<slug>-YYYY-MM`, a real date. */
|
|
89
|
+
export function isStudyName(name) {
|
|
90
|
+
const m = STUDY_NAME.exec(name);
|
|
91
|
+
if (m === null)
|
|
92
|
+
return false;
|
|
93
|
+
const year = Number(m[2]);
|
|
94
|
+
const month = Number(m[3]);
|
|
95
|
+
const day = m[4] === undefined ? 1 : Number(m[4]);
|
|
96
|
+
return month >= 1 && month <= 12 && day >= 1 && day <= daysIn(year, month);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* The study name to suggest for a folder named `name`: its name as a slug, with the date to fill in.
|
|
100
|
+
* A name that becomes a study name once lowercased and hyphenated is suggested as it is.
|
|
101
|
+
*/
|
|
102
|
+
export function suggestedStudyName(name) {
|
|
103
|
+
const slug = name
|
|
104
|
+
.toLowerCase()
|
|
105
|
+
.replace(/[^a-z0-9]+/gu, "-")
|
|
106
|
+
.replace(/^-+|-+$/gu, "");
|
|
107
|
+
if (isStudyName(slug))
|
|
108
|
+
return slug;
|
|
109
|
+
const base = slug.replace(/(?:^|-)\d{4}(?:-\d{1,2}){0,2}$/u, "");
|
|
110
|
+
return `${base === "" ? "<slug>" : base}-YYYY-MM-DD`;
|
|
111
|
+
}
|
|
112
|
+
/** The extensions of a script: what a study or the paper's build runs. */
|
|
113
|
+
export const SCRIPT_EXTENSIONS = [
|
|
114
|
+
".py",
|
|
115
|
+
".ipynb",
|
|
116
|
+
".sh",
|
|
117
|
+
".bash",
|
|
118
|
+
".zsh",
|
|
119
|
+
".js",
|
|
120
|
+
".mjs",
|
|
121
|
+
".cjs",
|
|
122
|
+
".ts",
|
|
123
|
+
".mts",
|
|
124
|
+
".cts",
|
|
125
|
+
".r",
|
|
126
|
+
".jl",
|
|
127
|
+
".rb",
|
|
128
|
+
".pl",
|
|
129
|
+
".awk",
|
|
130
|
+
".sql",
|
|
131
|
+
];
|
|
132
|
+
/** Names without a script's extension that still say how the tools run. */
|
|
133
|
+
export const TOOL_FILES = [
|
|
134
|
+
"Makefile",
|
|
135
|
+
"Dockerfile",
|
|
136
|
+
"requirements.txt",
|
|
137
|
+
"pyproject.toml",
|
|
138
|
+
"uv.lock",
|
|
139
|
+
"package.json",
|
|
140
|
+
"package-lock.json",
|
|
141
|
+
];
|
|
142
|
+
/** The extensions of data: tables, records, caches, archives, raw output. */
|
|
143
|
+
export const DATA_EXTENSIONS = [
|
|
144
|
+
".tsv",
|
|
145
|
+
".csv",
|
|
146
|
+
".json",
|
|
147
|
+
".jsonl",
|
|
148
|
+
".ndjson",
|
|
149
|
+
".yaml",
|
|
150
|
+
".yml",
|
|
151
|
+
".xml",
|
|
152
|
+
".txt",
|
|
153
|
+
".log",
|
|
154
|
+
".parquet",
|
|
155
|
+
".sqlite",
|
|
156
|
+
".db",
|
|
157
|
+
".xlsx",
|
|
158
|
+
".npy",
|
|
159
|
+
".npz",
|
|
160
|
+
".pkl",
|
|
161
|
+
".gz",
|
|
162
|
+
".zip",
|
|
163
|
+
".tar",
|
|
164
|
+
];
|
|
165
|
+
/** The extensions of a note. */
|
|
166
|
+
export const NOTE_EXTENSIONS = [".md", ".markdown"];
|
|
167
|
+
/** Where a script goes. */
|
|
168
|
+
export const SCRIPT_CURE = "repro/tools/ — the scripts used across the paper (numbers, figures, the anonymity check, harnesses); a script only one study runs goes in that study's folder instead";
|
|
169
|
+
/** Where data goes. */
|
|
170
|
+
export const DATA_CURE = "repro/data/ — the data shared across the paper (tables, caches); what one study's run produced goes in that study's folder instead";
|
|
171
|
+
/** Where a note goes. */
|
|
172
|
+
export const NOTE_CURE = "the dated folder of the study it is about (repro/<slug>-YYYY-MM-DD/), or the paper's research/ when it is research or a decision rather than the record of a run";
|
|
173
|
+
/** Where a file of any other kind goes. */
|
|
174
|
+
export const FILE_CURE_BY_KIND = "decide by what it is — a script → repro/tools/; data → repro/data/; a note → the dated folder of its study, or the paper's research/; what one study produced → that study's folder";
|
|
175
|
+
/** The files paperlint itself once kept at the top of `repro/`, each with where it is read now. */
|
|
176
|
+
export const MOVED_FILES = [
|
|
177
|
+
{
|
|
178
|
+
name: "references-cache.json",
|
|
179
|
+
cure: "repro/data/references-cache.json, where `paperlint build` reads and writes the citation services' answers (`git mv repro/references-cache.json repro/data/`); until it is moved, the next build asks every service again",
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
name: "refs-cache.json",
|
|
183
|
+
cure: "repro/data/refs-cache.json, where the paper-pipeline's extract-ref-facts script keeps its raw answers (`git mv repro/refs-cache.json repro/data/`)",
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
name: "generated-code-grandfathered.txt",
|
|
187
|
+
cure: "repro/tools/generated-code-grandfathered.txt, where the paper-pipeline's generated-code check reads it (`git mv repro/generated-code-grandfathered.txt repro/tools/`)",
|
|
188
|
+
},
|
|
189
|
+
];
|
|
190
|
+
/** Where a stray file goes: a file paperlint moved, else by the kind its name says. */
|
|
191
|
+
function fileCure(name) {
|
|
192
|
+
const moved = MOVED_FILES.find((f) => f.name === name);
|
|
193
|
+
if (moved !== undefined)
|
|
194
|
+
return moved.cure;
|
|
195
|
+
const ext = extname(name).toLowerCase();
|
|
196
|
+
if (TOOL_FILES.includes(name) || SCRIPT_EXTENSIONS.includes(ext))
|
|
197
|
+
return SCRIPT_CURE;
|
|
198
|
+
if (DATA_EXTENSIONS.includes(ext))
|
|
199
|
+
return DATA_CURE;
|
|
200
|
+
if (NOTE_EXTENSIONS.includes(ext))
|
|
201
|
+
return NOTE_CURE;
|
|
202
|
+
return FILE_CURE_BY_KIND;
|
|
203
|
+
}
|
|
204
|
+
/** Where a folder with no study name goes: renamed as a study, or emptied into the shared folders. */
|
|
205
|
+
const folderCure = (name) => `rename it to \`${suggestedStudyName(name)}\`, one folder per study or spike, named for what it is and the date it began — the date of its first commit is a fine default (\`git log --reverse --format=%as -- repro/${name} | head -1\`, run in the paper folder) — and give it a README.md; if it holds scripts or data shared across the paper instead, move them into repro/tools/ or repro/data/`;
|
|
206
|
+
const isAllowed = (e) => REPRO_BYPRODUCTS.includes(e.name) ||
|
|
207
|
+
(e.kind === "file"
|
|
208
|
+
? REPRO_FILES.includes(e.name)
|
|
209
|
+
: REPRO_DIRS.includes(e.name) || isStudyName(e.name));
|
|
210
|
+
/** The one finding for `e`, or null when it is in its place. */
|
|
211
|
+
function judgeEntry(e) {
|
|
212
|
+
const path = `${REPRO_DIR}/${e.name}${e.kind === "dir" ? "/" : ""}`;
|
|
213
|
+
if (!isAllowed(e))
|
|
214
|
+
return {
|
|
215
|
+
path,
|
|
216
|
+
problem: "stray",
|
|
217
|
+
cure: e.kind === "dir" ? folderCure(e.name) : fileCure(e.name),
|
|
218
|
+
};
|
|
219
|
+
if (e.kind === "dir" && isStudyName(e.name) && !e.hasReadme)
|
|
220
|
+
return {
|
|
221
|
+
path,
|
|
222
|
+
problem: "no-readme",
|
|
223
|
+
cure: `add ${path}${README} — what the study asks, how to run it, what it found — and a line for it in repro/${README}`,
|
|
224
|
+
};
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
/** The entries at the top of `repro/` that are out of place, at most one finding each, in order. Pure. */
|
|
228
|
+
export function judgeRepro(entries) {
|
|
229
|
+
return entries.map(judgeEntry).filter((f) => f !== null);
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* The one text a finding is reported with, by the rule `repro/allowed-files-only` and by the hook that fires
|
|
233
|
+
* when such an entry is written. It stands alone: what is wrong, where the entry goes, and what
|
|
234
|
+
* `repro/` holds, for a reader who knows nothing of paperlint.
|
|
235
|
+
*/
|
|
236
|
+
export function reproMessage(f) {
|
|
237
|
+
const head = f.problem === "stray"
|
|
238
|
+
? `\`${f.path}\` is loose at the top of the paper's repro/ folder, which holds only an index, the shared tools and data, and one dated folder per study. Where it goes: ${f.cure}.`
|
|
239
|
+
: `\`${f.path}\` is a study folder without a ${README}, and every study in repro/ has one. What to do: ${f.cure}.`;
|
|
240
|
+
return [
|
|
241
|
+
head,
|
|
242
|
+
"What repro/ holds (what interpreters and package managers leave there, like __pycache__/ and node_modules/, is never reported):",
|
|
243
|
+
REPRO_LAYOUT_TREE,
|
|
244
|
+
`Rule repro/allowed-files-only: https://github.com/zernie/paperlint/blob/main/docs/rules/repro/allowed-files-only.md`,
|
|
245
|
+
].join("\n");
|
|
246
|
+
}
|
|
247
|
+
//# sourceMappingURL=repro-layout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repro-layout.js","sourceRoot":"","sources":["../../src/domain/repro-layout.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** The placeholder git needs to keep an otherwise empty folder. */
|
|
2
|
+
export declare const GITKEEP = ".gitkeep";
|
|
3
|
+
/**
|
|
4
|
+
* The folders of the layout that `paperlint new` does not create, each with why. A folder here is
|
|
5
|
+
* allowed at the root all the same; it appears when the work needs it.
|
|
6
|
+
*/
|
|
7
|
+
export declare const NOT_SCAFFOLDED: readonly {
|
|
8
|
+
readonly name: string;
|
|
9
|
+
readonly why: string;
|
|
10
|
+
}[];
|
|
11
|
+
/** The folders at the paper's root that a new paper holds from the first commit, in layout order. */
|
|
12
|
+
export declare const SCAFFOLD_DIRS: readonly string[];
|
|
13
|
+
/**
|
|
14
|
+
* The stub index of `repro/`: it makes the folder non-empty (no `.gitkeep`) and says what the rule
|
|
15
|
+
* asks of it. A line per study is added when the first study is.
|
|
16
|
+
*/
|
|
17
|
+
export declare const REPRO_INDEX_STUB = "# Reproduction index\n\nOne line per study: `<slug>-YYYY-MM-DD/` \u2014 what it asks and what it found. Scripts used across the\npaper go in `tools/`, shared data in `data/`.\n";
|
|
18
|
+
/** A file `paperlint new` writes into a new paper folder, with its path from that folder. */
|
|
19
|
+
export interface ScaffoldFile {
|
|
20
|
+
readonly path: string;
|
|
21
|
+
readonly text: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Every file of the layout scaffold, relative to the paper folder, in a fixed order: a `.gitkeep` in
|
|
25
|
+
* each empty folder, and `repro/README.md` where `repro/` would otherwise hold only folders.
|
|
26
|
+
*/
|
|
27
|
+
export declare const SCAFFOLD_FILES: readonly ScaffoldFile[];
|
|
28
|
+
//# sourceMappingURL=scaffold-layout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scaffold-layout.d.ts","sourceRoot":"","sources":["../../src/domain/scaffold-layout.ts"],"names":[],"mappings":"AAiCA,mEAAmE;AACnE,eAAO,MAAM,OAAO,aAAa,CAAC;AAElC;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,SAAS;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB,EAqBA,CAAC;AAEF,qGAAqG;AACrG,eAAO,MAAM,aAAa,EAAE,SAAS,MAAM,EAEqB,CAAC;AAEjE;;;GAGG;AACH,eAAO,MAAM,gBAAgB,qLAI5B,CAAC;AAEF,6FAA6F;AAC7F,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,SAAS,YAAY,EAYjD,CAAC"}
|