paperlint 7.1.0 → 8.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/workflows/ci.yml +3 -0
- package/.github/workflows/deadlines.yml +100 -0
- package/README.md +6 -0
- package/dist/adapters/hotcrp/deadlines.d.ts +8 -0
- package/dist/adapters/hotcrp/deadlines.d.ts.map +1 -0
- package/dist/adapters/hotcrp/deadlines.io.d.ts +6 -0
- package/dist/adapters/hotcrp/deadlines.io.d.ts.map +1 -0
- package/dist/adapters/hotcrp/deadlines.io.js +26 -0
- package/dist/adapters/hotcrp/deadlines.io.js.map +1 -0
- package/dist/adapters/hotcrp/deadlines.js +134 -0
- package/dist/adapters/hotcrp/deadlines.js.map +1 -0
- package/dist/adapters/hotcrp/index.d.ts +2 -0
- package/dist/adapters/hotcrp/index.d.ts.map +1 -1
- package/dist/adapters/hotcrp/index.js +2 -0
- package/dist/adapters/hotcrp/index.js.map +1 -1
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +1 -6
- package/dist/build.js.map +1 -1
- package/dist/cli.d.ts +3 -4
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +53 -47
- package/dist/cli.js.map +1 -1
- package/dist/cycle-rules.d.ts +24 -0
- package/dist/cycle-rules.d.ts.map +1 -0
- package/dist/cycle-rules.js +212 -0
- package/dist/cycle-rules.js.map +1 -0
- package/dist/domain/cycle.d.ts +148 -0
- package/dist/domain/cycle.d.ts.map +1 -0
- package/dist/domain/cycle.js +281 -0
- package/dist/domain/cycle.js.map +1 -0
- package/dist/domain/deadline.d.ts +128 -0
- package/dist/domain/deadline.d.ts.map +1 -0
- package/dist/domain/deadline.js +281 -0
- package/dist/domain/deadline.js.map +1 -0
- package/dist/eslint-rules/cycle-stage.d.ts +39 -0
- package/dist/eslint-rules/cycle-stage.d.ts.map +1 -0
- package/dist/eslint-rules/cycle-stage.js +119 -0
- package/dist/eslint-rules/cycle-stage.js.map +1 -0
- package/dist/eslint-rules/latex-language.d.ts.map +1 -1
- package/dist/eslint-rules/latex-language.js +10 -13
- package/dist/eslint-rules/latex-language.js.map +1 -1
- package/dist/eslint-rules/paper-context.js +2 -2
- package/dist/eslint-rules/paper-typography.d.ts.map +1 -1
- package/dist/eslint-rules/paper-typography.js +22 -91
- package/dist/eslint-rules/paper-typography.js.map +1 -1
- package/dist/eslint-rules/papers.d.ts +1 -3
- package/dist/eslint-rules/papers.d.ts.map +1 -1
- package/dist/eslint-rules/papers.js +2 -4
- package/dist/eslint-rules/papers.js.map +1 -1
- package/dist/eslint-rules/tex-build.d.ts.map +1 -1
- package/dist/eslint-rules/tex-build.js +8 -25
- package/dist/eslint-rules/tex-build.js.map +1 -1
- package/dist/init.d.ts +1 -4
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +3 -9
- package/dist/init.js.map +1 -1
- package/dist/lib/markdown.d.ts +5 -81
- package/dist/lib/markdown.d.ts.map +1 -1
- package/dist/lib/markdown.js +5 -116
- package/dist/lib/markdown.js.map +1 -1
- package/dist/lib/paper-config.d.ts.map +1 -1
- package/dist/lib/paper-config.js +2 -2
- package/dist/lib/paper-config.js.map +1 -1
- package/dist/lib/skill-eval-fixture.d.ts +6 -4
- package/dist/lib/skill-eval-fixture.d.ts.map +1 -1
- package/dist/lib/skill-eval-fixture.js +25 -18
- package/dist/lib/skill-eval-fixture.js.map +1 -1
- package/dist/new-paper.d.ts +5 -11
- package/dist/new-paper.d.ts.map +1 -1
- package/dist/new-paper.js +12 -23
- package/dist/new-paper.js.map +1 -1
- package/dist/paper-files.d.ts +4 -4
- package/dist/paper-prose.d.ts +17 -0
- package/dist/paper-prose.d.ts.map +1 -0
- package/dist/paper-prose.js +46 -0
- package/dist/paper-prose.js.map +1 -0
- package/dist/paper-settings.d.ts +7 -0
- package/dist/paper-settings.d.ts.map +1 -1
- package/dist/paper-settings.js +61 -8
- package/dist/paper-settings.js.map +1 -1
- package/dist/ports/venue-deadlines.d.ts +14 -0
- package/dist/ports/venue-deadlines.d.ts.map +1 -0
- package/dist/ports/venue-deadlines.js +2 -0
- package/dist/ports/venue-deadlines.js.map +1 -0
- package/dist/presets.d.ts +12 -0
- package/dist/presets.d.ts.map +1 -1
- package/dist/presets.js +19 -11
- package/dist/presets.js.map +1 -1
- package/dist/structure.d.ts.map +1 -1
- package/dist/structure.js +4 -3
- package/dist/structure.js.map +1 -1
- package/dist/submission.d.ts +8 -0
- package/dist/submission.d.ts.map +1 -1
- package/dist/submission.js +41 -10
- package/dist/submission.js.map +1 -1
- package/dist/tex-requirements.d.ts +3 -0
- package/dist/tex-requirements.d.ts.map +1 -1
- package/dist/tex-requirements.js +19 -0
- package/dist/tex-requirements.js.map +1 -1
- package/dist/tex-venue-rules.d.ts +19 -0
- package/dist/tex-venue-rules.d.ts.map +1 -1
- package/dist/tex-venue-rules.js +69 -0
- package/dist/tex-venue-rules.js.map +1 -1
- package/dist/types.d.ts +0 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/venue-rules.d.ts +10 -0
- package/dist/venue-rules.d.ts.map +1 -1
- package/dist/venue-rules.js +26 -10
- package/dist/venue-rules.js.map +1 -1
- package/docs/configuration.md +146 -20
- package/docs/e2e.md +4 -6
- package/docs/prior-art/paper-folder-scaffolding.md +24 -29
- package/docs/rules/cycle/evidence.md +87 -0
- package/docs/rules/cycle/port-done.md +75 -0
- package/docs/rules/cycle/record.md +152 -0
- package/docs/rules/cycle/stage.md +85 -0
- package/docs/rules/tex/claim-provenance.md +0 -1
- package/docs/rules.md +48 -47
- package/docs/submission.md +5 -0
- package/eslint-rules/cycle-stage.test.mjs +131 -0
- package/eslint-rules/cycle-stage.ts +141 -0
- package/eslint-rules/latex-language.harness.mjs +3 -3
- package/eslint-rules/latex-language.ts +10 -13
- package/eslint-rules/paper-context.ts +2 -2
- package/eslint-rules/paper-typography.test.mjs +17 -85
- package/eslint-rules/paper-typography.ts +22 -98
- package/eslint-rules/papers.harness.mjs +1 -1
- package/eslint-rules/papers.ts +2 -4
- package/eslint-rules/tex-build.harness.mjs +2 -2
- package/eslint-rules/tex-build.ts +8 -25
- package/eslint.config.mjs +41 -2
- package/hooks/hooks.harness.ts +15 -15
- package/hooks/paper-edit-guard.hook.mjs +5 -8
- package/hooks/paper-edit-guard.test.ts +12 -3
- package/hooks/paper-skills-nudge.hook.mjs +2 -3
- package/hooks/paper-skills-nudge.test.ts +13 -3
- package/hooks/paper-status-gates.hook.mjs +2 -2
- package/hooks/paper-status-gates.test.ts +14 -2
- package/lib/markdown.test.mjs +5 -60
- package/lib/markdown.ts +9 -136
- package/lib/paper-config.ts +3 -2
- package/lib/skill-checks.test.mjs +4 -1
- package/lib/skill-eval-fixture.ts +25 -18
- package/package.json +1 -3
- package/presets/aidc.jsonc +24 -3
- package/presets/aidc.md +6 -3
- package/presets/msr.jsonc +25 -1
- package/presets/msr.md +5 -1
- package/presets/realm.jsonc +1 -1
- package/presets/venue-profile.schema.json +39 -0
- package/scripts/check.ts +4 -0
- package/scripts/harness-api.frozen.json +0 -5
- package/scripts/refresh-deadlines.test.ts +431 -0
- package/scripts/refresh-deadlines.ts +387 -0
- package/skills/cold-read-diff/SKILL.md +3 -3
- package/skills/cold-read-diff/SKILL.md.spec.ts +2 -2
- package/skills/grade-paper-writing/SKILL.md +14 -22
- package/skills/grade-paper-writing/SKILL.md.spec.ts +13 -21
- package/skills/grade-paper-writing/__snapshots__/prose-lint.test.ts.snap +40 -26
- package/skills/grade-paper-writing/prose-lint.mjs +108 -278
- package/skills/grade-paper-writing/prose-lint.test.ts +184 -81
- package/skills/paper-adversarial-review/SKILL.md +2 -2
- package/skills/paper-adversarial-review/SKILL.md.spec.ts +1 -1
- package/skills/paper-pipeline/SKILL.md +9 -12
- package/skills/paper-pipeline/SKILL.md.spec.ts +8 -11
- package/skills/paper-pipeline/description-language.eval.mjs +25 -15
- package/skills/paper-pipeline/framing-vs-vocabulary.eval.mjs +25 -15
- package/skills/paper-pipeline/grade-paper-writing-ablation.eval.mjs +25 -15
- package/skills/paper-pipeline/pipeline-firing.eval.mjs +27 -16
- package/skills/paper-pipeline/pipeline-language.eval.mjs +25 -15
- package/skills/paper-pipeline/references/acceptance-gate.md +16 -20
- package/skills/paper-pipeline/references/artifact-checklist.md +4 -5
- package/skills/paper-pipeline/references/pipeline-status-template.md +1 -1
- package/skills/paper-pipeline/scripts/README.md +0 -4
- package/skills/paper-pipeline/scripts/extract-ref-facts.harness.mjs +8 -72
- package/skills/paper-pipeline/scripts/extract-ref-facts.mjs +48 -156
- package/skills/paper-pipeline/scripts/extract-ref-facts.test.mjs +81 -75
- package/skills/paper-pipeline/scripts/generated-code.harness.mjs +3 -3
- package/skills/paper-status/SKILL.md +2 -2
- package/skills/paper-status/SKILL.md.spec.ts +1 -1
- package/skills/render-paper/SKILL.md +2 -2
- package/skills/render-paper/SKILL.md.spec.ts +1 -1
- package/skills/render-paper/extract-pdf-facts.mjs +2 -2
- package/skills/tighten-paper/SKILL.md +29 -42
- package/skills/tighten-paper/SKILL.md.spec.ts +28 -41
- package/skills/verify-citations/scripts/bib-authors.check.test.mjs +0 -13
- package/skills/verify-citations/scripts/bib-authors.cli.test.ts +23 -11
- package/skills/verify-citations/scripts/bib-authors.mjs +8 -93
- package/skills/verify-citations/scripts/bib-authors.test.mjs +1 -44
- package/src/adapters/hotcrp/cassette/README.md +22 -0
- package/src/adapters/hotcrp/cassette/deadlines-aidc26.html +17 -0
- package/src/adapters/hotcrp/cassette/deadlines-fse2027.html +24 -0
- package/src/adapters/hotcrp/cassette/deadlines-icse2027.html +25 -0
- package/src/adapters/hotcrp/cassette/deadlines-msr2027.html +25 -0
- package/src/adapters/hotcrp/cassette/deadlines-nosuch.html +18 -0
- package/src/adapters/hotcrp/cassette/deadlines-sosp26.html +26 -0
- package/src/adapters/hotcrp/deadlines.io.test.ts +86 -0
- package/src/adapters/hotcrp/deadlines.io.ts +27 -0
- package/src/adapters/hotcrp/deadlines.test.ts +170 -0
- package/src/adapters/hotcrp/deadlines.ts +161 -0
- package/src/adapters/hotcrp/index.ts +2 -0
- package/src/build.harness.mjs +2 -2
- package/src/build.test.ts +1 -1
- package/src/build.ts +1 -6
- package/src/cli.harness.mjs +26 -46
- package/src/cli.test.ts +41 -40
- package/src/cli.ts +57 -58
- package/src/cycle-rules.test.ts +278 -0
- package/src/cycle-rules.ts +273 -0
- package/src/domain/cycle.test.ts +456 -0
- package/src/domain/cycle.ts +432 -0
- package/src/domain/deadline.test.ts +386 -0
- package/src/domain/deadline.ts +472 -0
- package/src/folder-venue-rule.test.ts +1 -1
- package/src/init.test.ts +6 -7
- package/src/init.ts +3 -22
- package/src/lint-fix.test.ts +10 -4
- package/src/new-paper.harness.mjs +9 -28
- package/src/new-paper.test.ts +7 -6
- package/src/new-paper.ts +11 -30
- package/src/paper-files.test.ts +5 -4
- package/src/paper-files.ts +4 -4
- package/src/paper-prose.test.ts +49 -0
- package/src/paper-prose.ts +67 -0
- package/src/paper-settings.test.ts +167 -0
- package/src/paper-settings.ts +85 -11
- package/src/parse-args.test.ts +0 -1
- package/src/ports/venue-deadlines.ts +14 -0
- package/src/presets.test.ts +105 -0
- package/src/presets.ts +43 -10
- package/src/rule-cases.test.ts +144 -0
- package/src/structure.harness.ts +5 -11
- package/src/structure.ts +4 -3
- package/src/submission.test.ts +105 -1
- package/src/submission.ts +73 -12
- package/src/tex-requirements.ts +31 -0
- package/src/tex-venue-rules.test.ts +76 -0
- package/src/tex-venue-rules.ts +85 -0
- package/src/types.ts +0 -2
- package/src/venue-rules.test.ts +82 -0
- package/src/venue-rules.ts +44 -12
- package/fixtures/real-markdown-paper/baseline.json +0 -22
- package/fixtures/real-markdown-paper/baseline.ts +0 -70
- package/skills/paper-pipeline/PIPELINE-MAP.md +0 -381
- package/skills/paper-pipeline/pipeline-firing.baseline.json +0 -270
- package/skills/paper-pipeline/references/sweep-2026-08-09-ideal-pipeline.md +0 -585
- package/skills/paper-pipeline/scripts/artifact-coverage.harness.mjs +0 -492
- package/skills/paper-pipeline/scripts/artifact-coverage.mjs +0 -397
- package/skills/paper-pipeline/scripts/artifact-coverage.test.ts +0 -86
- package/skills/paper-pipeline/scripts/check-provenance.mjs +0 -184
- package/skills/paper-pipeline/scripts/population-map.harness.mjs +0 -135
- package/skills/paper-pipeline/scripts/population-map.mjs +0 -188
- package/skills/paper-pipeline/scripts/population-map.test.mjs +0 -154
- package/skills/paper-pipeline/scripts/provenance.harness.mjs +0 -266
- package/skills/paper-pipeline/scripts/round-diff.harness.ts +0 -907
- package/skills/paper-pipeline/scripts/round-diff.mjs +0 -583
- package/skills/paper-pipeline/scripts/round-diff.test.mjs +0 -159
- package/skills/tighten-paper/__snapshots__/structure.test.ts.snap +0 -133
- package/skills/tighten-paper/structure.mjs +0 -364
- package/skills/tighten-paper/structure.test.ts +0 -117
- package/templates/paper/paper.md +0 -4
|
@@ -4,7 +4,7 @@ description: "Use when a paper \"feels long / bloated / overly complex / hard to
|
|
|
4
4
|
allowed-tools: [Read, Write, Edit, Grep, Glob, Agent]
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
<!-- vigiles:sha256:
|
|
7
|
+
<!-- vigiles:sha256:c57d6da372b28acf compiled from skills/tighten-paper/SKILL.md.spec.ts -->
|
|
8
8
|
|
|
9
9
|
# tighten-paper — the developmental edit
|
|
10
10
|
|
|
@@ -34,31 +34,12 @@ counter, is not this skill; it is the damage this skill exists to undo.
|
|
|
34
34
|
If you are invoked while the author is still adding material, say so and decline the pass. The right
|
|
35
35
|
answer is "not yet", not a smaller cut.
|
|
36
36
|
|
|
37
|
-
## 🏗 START WITH THE
|
|
37
|
+
## 🏗 START WITH THE SHAPE — weigh every section before judging it
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
🔴 **THE SCRIPT NO LONGER FINDS ANYTHING — it is an INVENTORY (2026-08-26).** All sixteen of its
|
|
45
|
-
checks moved into ESLint rules (`eslint-rules/paper-structure.mjs`). The findings you used to read
|
|
46
|
-
here now come from:
|
|
47
|
-
|
|
48
|
-
```
|
|
49
|
-
npx eslint --no-config-lookup --config eslint.config.mjs <paper.md>
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
⚠️ Do NOT pass `--flags-only`. It is kept only because two harnesses assert on its silence, and it
|
|
53
|
-
prints nothing and exits 0 whatever the paper looks like. Measured 26.08 on `the reference paper`:
|
|
54
|
-
`--flags-only` printed 0 lines while ESLint on the same bytes reported **6 structural findings**
|
|
55
|
-
(subsection-size ×2 · section-lead · free-section-size ×2 · block-ungraded). A mode that cannot
|
|
56
|
-
speak is not a check, and reading its silence as "clean" is the defect this pipeline is named for.
|
|
57
|
-
|
|
58
|
-
What the inventory prints, and why it stays a script: the outline **in order** — every heading, its
|
|
59
|
-
own words, its total with subsections, its share of the body, and the `carries:`/`score:`/`verdict:`
|
|
60
|
-
note the section wrote about itself, printed beside its weight. That comparison is the whole point
|
|
61
|
-
and a linter cannot make it: a finding has nowhere to put a table.
|
|
39
|
+
Write the outline out **in order**: every heading, its own words before its first subsection, its
|
|
40
|
+
total with subsections, its share of the body — and beside each, the `carries:`/`score:`/`verdict:`
|
|
41
|
+
note the section wrote about itself. That comparison, a section's weight printed next to what it
|
|
42
|
+
claims about itself, is the whole point.
|
|
62
43
|
|
|
63
44
|
🔴 **Why this exists, and why word counts alone mislead.** Asked whether a paper short-changed its
|
|
64
45
|
contribution, per-section word counts said no — the contribution had 38% more words than related
|
|
@@ -67,7 +48,7 @@ owned **0, 28 and 38** words before their first subsection. Nothing in the toolc
|
|
|
67
48
|
question, because every metric was per-sentence or per-document and none was per-section. The author's
|
|
68
49
|
word for the result was a "salad" — a jumbled mix — and he was right while the numbers said fine.
|
|
69
50
|
|
|
70
|
-
**What the
|
|
51
|
+
**What the count does NOT decide, and you must:** the ORDER, the NAMES, and whether a section earns
|
|
71
52
|
its place. Those are judgement, and pretending otherwise would be the failure this whole pipeline
|
|
72
53
|
exists to prevent.
|
|
73
54
|
|
|
@@ -188,18 +169,24 @@ called it "fat for no reason" after a pass that cut almost nothing and left it 1
|
|
|
188
169
|
|
|
189
170
|
A verdict that lives in a chat log is gone by the next session, and the next session then re-derives
|
|
190
171
|
it or ignores it. **Every section and subsection gets a one-line verdict comment immediately above its
|
|
191
|
-
heading**, in
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
172
|
+
heading**, in `paper.tex`, as LaTeX `%` comments, stamped with the date and the skill that
|
|
173
|
+
produced it:
|
|
174
|
+
|
|
175
|
+
```latex
|
|
176
|
+
% TIGHTEN 2026-08-06 · score 8/10 · verdict: KEEP · 190w
|
|
177
|
+
% carries: tools get close but none resolves a NAMED rule against a committed config
|
|
178
|
+
% because: it is the only place the tool-ecosystem gap is closed; a reviewer who skips it
|
|
179
|
+
% asks "hasn't this been done" and gets no answer
|
|
180
|
+
\section{Related tools}
|
|
181
|
+
|
|
182
|
+
% TIGHTEN 2026-08-06 · score 5/10 · verdict: SHORTEN -89w · 210w
|
|
183
|
+
% carries: why a linter for the rules file cannot work
|
|
184
|
+
% because: the point lands in two sentences; the rest re-establishes what §2 already did
|
|
185
|
+
\subsection{Why not a linter}
|
|
186
|
+
|
|
187
|
+
% TIGHTEN 2026-08-06 · score 2/10 · verdict: MOVE→artifact · 45w
|
|
188
|
+
% carries: nothing the reader must hold to judge the contribution
|
|
189
|
+
\subsection{Implementation notes}
|
|
203
190
|
```
|
|
204
191
|
|
|
205
192
|
🔴 **Before assigning any `MOVE→` verdict, read `paper-pipeline/references/body-vs-appendix.md`.**
|
|
@@ -224,7 +211,7 @@ written and **not one ever concluded "cut me"**. Author, 2026-08-06, reading the
|
|
|
224
211
|
value on every page and compared nothing.
|
|
225
212
|
|
|
226
213
|
The pairing is the mechanism: **a low score beside a KEEP verdict is a visible contradiction**, and
|
|
227
|
-
|
|
214
|
+
the outline above puts the two side by side. Prose cannot contradict itself; a number can.
|
|
228
215
|
|
|
229
216
|
**Calibration, so the scale does not drift to "everything is an 8":**
|
|
230
217
|
- **9–10** — remove it and a reviewer cannot assess the contribution. The claim, its evidence, its price.
|
|
@@ -279,10 +266,10 @@ Rules for these comments:
|
|
|
279
266
|
unpriced prose accumulates, because nothing there costs a page.
|
|
280
267
|
- **Stale beats absent, but not by much.** A comment whose date precedes the last substantive edit to
|
|
281
268
|
its section is stale; re-grade it rather than trusting it.
|
|
282
|
-
- **A verdict nobody executed is a note, not a decision.**
|
|
283
|
-
|
|
269
|
+
- **A verdict nobody executed is a note, not a decision.** List the blocks still carrying a
|
|
270
|
+
non-KEEP verdict — a paper full of unexecuted CUTs is worse than one never graded,
|
|
284
271
|
because it reads as decided.
|
|
285
|
-
- They are working notes:
|
|
272
|
+
- They are working notes: a `%` comment never reaches the PDF.
|
|
286
273
|
- The chat summary still gets written — but it is the *derivative*, and the paper is the record.
|
|
287
274
|
|
|
288
275
|
## 🧱 Enforce subsections — a section without them is a wall
|
|
@@ -40,31 +40,12 @@ counter, is not this skill; it is the damage this skill exists to undo.
|
|
|
40
40
|
If you are invoked while the author is still adding material, say so and decline the pass. The right
|
|
41
41
|
answer is "not yet", not a smaller cut.
|
|
42
42
|
|
|
43
|
-
## 🏗 START WITH THE
|
|
43
|
+
## 🏗 START WITH THE SHAPE — weigh every section before judging it
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
🔴 **THE SCRIPT NO LONGER FINDS ANYTHING — it is an INVENTORY (2026-08-26).** All sixteen of its
|
|
51
|
-
checks moved into ESLint rules (\`eslint-rules/paper-structure.mjs\`). The findings you used to read
|
|
52
|
-
here now come from:
|
|
53
|
-
|
|
54
|
-
\`\`\`
|
|
55
|
-
npx eslint --no-config-lookup --config eslint.config.mjs <paper.md>
|
|
56
|
-
\`\`\`
|
|
57
|
-
|
|
58
|
-
⚠️ Do NOT pass \`--flags-only\`. It is kept only because two harnesses assert on its silence, and it
|
|
59
|
-
prints nothing and exits 0 whatever the paper looks like. Measured 26.08 on \`the reference paper\`:
|
|
60
|
-
\`--flags-only\` printed 0 lines while ESLint on the same bytes reported **6 structural findings**
|
|
61
|
-
(subsection-size ×2 · section-lead · free-section-size ×2 · block-ungraded). A mode that cannot
|
|
62
|
-
speak is not a check, and reading its silence as "clean" is the defect this pipeline is named for.
|
|
63
|
-
|
|
64
|
-
What the inventory prints, and why it stays a script: the outline **in order** — every heading, its
|
|
65
|
-
own words, its total with subsections, its share of the body, and the \`carries:\`/\`score:\`/\`verdict:\`
|
|
66
|
-
note the section wrote about itself, printed beside its weight. That comparison is the whole point
|
|
67
|
-
and a linter cannot make it: a finding has nowhere to put a table.
|
|
45
|
+
Write the outline out **in order**: every heading, its own words before its first subsection, its
|
|
46
|
+
total with subsections, its share of the body — and beside each, the \`carries:\`/\`score:\`/\`verdict:\`
|
|
47
|
+
note the section wrote about itself. That comparison, a section's weight printed next to what it
|
|
48
|
+
claims about itself, is the whole point.
|
|
68
49
|
|
|
69
50
|
🔴 **Why this exists, and why word counts alone mislead.** Asked whether a paper short-changed its
|
|
70
51
|
contribution, per-section word counts said no — the contribution had 38% more words than related
|
|
@@ -73,7 +54,7 @@ owned **0, 28 and 38** words before their first subsection. Nothing in the toolc
|
|
|
73
54
|
question, because every metric was per-sentence or per-document and none was per-section. The author's
|
|
74
55
|
word for the result was a "salad" — a jumbled mix — and he was right while the numbers said fine.
|
|
75
56
|
|
|
76
|
-
**What the
|
|
57
|
+
**What the count does NOT decide, and you must:** the ORDER, the NAMES, and whether a section earns
|
|
77
58
|
its place. Those are judgement, and pretending otherwise would be the failure this whole pipeline
|
|
78
59
|
exists to prevent.
|
|
79
60
|
|
|
@@ -194,18 +175,24 @@ called it "fat for no reason" after a pass that cut almost nothing and left it 1
|
|
|
194
175
|
|
|
195
176
|
A verdict that lives in a chat log is gone by the next session, and the next session then re-derives
|
|
196
177
|
it or ignores it. **Every section and subsection gets a one-line verdict comment immediately above its
|
|
197
|
-
heading**, in
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
178
|
+
heading**, in \`paper.tex\`, as LaTeX \`%\` comments, stamped with the date and the skill that
|
|
179
|
+
produced it:
|
|
180
|
+
|
|
181
|
+
\`\`\`latex
|
|
182
|
+
% TIGHTEN 2026-08-06 · score 8/10 · verdict: KEEP · 190w
|
|
183
|
+
% carries: tools get close but none resolves a NAMED rule against a committed config
|
|
184
|
+
% because: it is the only place the tool-ecosystem gap is closed; a reviewer who skips it
|
|
185
|
+
% asks "hasn't this been done" and gets no answer
|
|
186
|
+
\\section{Related tools}
|
|
187
|
+
|
|
188
|
+
% TIGHTEN 2026-08-06 · score 5/10 · verdict: SHORTEN -89w · 210w
|
|
189
|
+
% carries: why a linter for the rules file cannot work
|
|
190
|
+
% because: the point lands in two sentences; the rest re-establishes what §2 already did
|
|
191
|
+
\\subsection{Why not a linter}
|
|
192
|
+
|
|
193
|
+
% TIGHTEN 2026-08-06 · score 2/10 · verdict: MOVE→artifact · 45w
|
|
194
|
+
% carries: nothing the reader must hold to judge the contribution
|
|
195
|
+
\\subsection{Implementation notes}
|
|
209
196
|
\`\`\`
|
|
210
197
|
|
|
211
198
|
🔴 **Before assigning any \`MOVE→\` verdict, read \`paper-pipeline/references/body-vs-appendix.md\`.**
|
|
@@ -230,7 +217,7 @@ written and **not one ever concluded "cut me"**. Author, 2026-08-06, reading the
|
|
|
230
217
|
value on every page and compared nothing.
|
|
231
218
|
|
|
232
219
|
The pairing is the mechanism: **a low score beside a KEEP verdict is a visible contradiction**, and
|
|
233
|
-
|
|
220
|
+
the outline above puts the two side by side. Prose cannot contradict itself; a number can.
|
|
234
221
|
|
|
235
222
|
**Calibration, so the scale does not drift to "everything is an 8":**
|
|
236
223
|
- **9–10** — remove it and a reviewer cannot assess the contribution. The claim, its evidence, its price.
|
|
@@ -285,10 +272,10 @@ Rules for these comments:
|
|
|
285
272
|
unpriced prose accumulates, because nothing there costs a page.
|
|
286
273
|
- **Stale beats absent, but not by much.** A comment whose date precedes the last substantive edit to
|
|
287
274
|
its section is stale; re-grade it rather than trusting it.
|
|
288
|
-
- **A verdict nobody executed is a note, not a decision.**
|
|
289
|
-
|
|
275
|
+
- **A verdict nobody executed is a note, not a decision.** List the blocks still carrying a
|
|
276
|
+
non-KEEP verdict — a paper full of unexecuted CUTs is worse than one never graded,
|
|
290
277
|
because it reads as decided.
|
|
291
|
-
- They are working notes:
|
|
278
|
+
- They are working notes: a \`%\` comment never reaches the PDF.
|
|
292
279
|
- The chat summary still gets written — but it is the *derivative*, and the paper is the record.
|
|
293
280
|
|
|
294
281
|
## 🧱 Enforce subsections — a section without them is a wall
|
|
@@ -50,15 +50,6 @@ test("checkAuthors sorts every kind of entry into its bucket", async () => {
|
|
|
50
50
|
entry("nomatch", "Ada Lovelace", "Nobody Has This"),
|
|
51
51
|
entry("onlycorr", "Ada Lovelace", "Only On CoRR"),
|
|
52
52
|
entry("down", "Ada Lovelace", "Service Down"),
|
|
53
|
-
{
|
|
54
|
-
type: "mdref",
|
|
55
|
-
key: "sw",
|
|
56
|
-
unparsed: true,
|
|
57
|
-
author: "",
|
|
58
|
-
title: "",
|
|
59
|
-
booktitle: "",
|
|
60
|
-
journal: "",
|
|
61
|
-
},
|
|
62
53
|
];
|
|
63
54
|
const answers = {
|
|
64
55
|
"Same Paper": [hit("Same Paper.", ["Ada Lovelace", "Alan Turing"])],
|
|
@@ -101,10 +92,6 @@ test("checkAuthors sorts every kind of entry into its bucket", async () => {
|
|
|
101
92
|
},
|
|
102
93
|
],
|
|
103
94
|
skipped: [
|
|
104
|
-
{
|
|
105
|
-
key: "sw",
|
|
106
|
-
why: "no author/title — a reference to software or a dataset, DBLP does not apply",
|
|
107
|
-
},
|
|
108
95
|
{
|
|
109
96
|
key: "etal",
|
|
110
97
|
why: "author list ends in `and others` — completeness not checkable",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* bib-authors.mjs as a process: which file it picks from a paper directory, the
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* bib-authors.mjs as a process: which file it picks from a paper directory, the bibliography
|
|
3
|
+
* sources it reads (.bib, a .tex's filecontents or its sibling refs.bib), the file it refuses, and
|
|
4
|
+
* the report and exit code for each outcome. DBLP is a preload that answers
|
|
5
5
|
* by title from a table (the documented `result.hits.hit[].info` shape) — no network.
|
|
6
6
|
*/
|
|
7
7
|
import assert from "node:assert/strict";
|
|
@@ -58,8 +58,10 @@ writeTree(root, {
|
|
|
58
58
|
"sibling/paper.tex": "\\documentclass{article}\n",
|
|
59
59
|
"sibling/refs.bib": bib("good", "Ada Lovelace", "All Good"),
|
|
60
60
|
"nobib/paper.tex": "\\documentclass{article}\n",
|
|
61
|
-
"
|
|
62
|
-
|
|
61
|
+
"etal/notes.txt": "not a bibliography\n",
|
|
62
|
+
"etal/refs.bib":
|
|
63
|
+
bib("good", "Ada Lovelace", "All Good") +
|
|
64
|
+
bib("etal", "Ada Lovelace and others", "Truncated"),
|
|
63
65
|
"down/refs.bib": bib("down", "Ada Lovelace", "Service Down"),
|
|
64
66
|
"empty/.keep": "",
|
|
65
67
|
});
|
|
@@ -98,7 +100,7 @@ test("refusals: no argument, no such path, a directory with nothing to read, a .
|
|
|
98
100
|
{
|
|
99
101
|
status: 2,
|
|
100
102
|
stdout: "",
|
|
101
|
-
stderr: "bib-authors: no .bib
|
|
103
|
+
stderr: "bib-authors: no .bib or .tex in <root>/empty\n",
|
|
102
104
|
},
|
|
103
105
|
{
|
|
104
106
|
status: 2,
|
|
@@ -162,15 +164,25 @@ test("a .tex with no filecontents reads the refs.bib beside it — PASS, exit 0"
|
|
|
162
164
|
});
|
|
163
165
|
});
|
|
164
166
|
|
|
165
|
-
test("a
|
|
166
|
-
const r = run(join(root, "
|
|
167
|
+
test("a file that is neither a .bib nor a .tex is refused — not swapped for the refs.bib beside it", () => {
|
|
168
|
+
const r = run(join(root, "etal", "notes.txt"));
|
|
169
|
+
assert.deepEqual(r, {
|
|
170
|
+
status: 2,
|
|
171
|
+
stdout: "",
|
|
172
|
+
stderr:
|
|
173
|
+
"bib-authors: <root>/etal/notes.txt is not a .bib or a .tex — give the paper's .bib or paper.tex\n",
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
test("an `and others` entry is printed as not applicable, not dropped", () => {
|
|
178
|
+
const r = run(join(root, "etal"));
|
|
167
179
|
assert.deepEqual(r, {
|
|
168
180
|
status: 0,
|
|
169
181
|
stderr: "",
|
|
170
182
|
stdout:
|
|
171
|
-
"== bib-authors: <root>/
|
|
172
|
-
" · n/a
|
|
173
|
-
"--
|
|
183
|
+
"== bib-authors: <root>/etal/refs.bib ==\n" +
|
|
184
|
+
" · n/a etal — author list ends in `and others` — completeness not checkable\n\n" +
|
|
185
|
+
"-- 2 entries · 0 difference(s) · 1 not applicable · 0 NOT CHECKED\nPASS: no author-list disagreement.\n",
|
|
174
186
|
});
|
|
175
187
|
});
|
|
176
188
|
|
|
@@ -45,90 +45,12 @@
|
|
|
45
45
|
*/
|
|
46
46
|
import { readFileSync, existsSync, readdirSync } from "node:fs";
|
|
47
47
|
import { join, extname } from "node:path";
|
|
48
|
-
import { headings as mdHeadings, requireMarkdown } from "#lib/markdown";
|
|
49
48
|
import { isMain } from "../../paper-pipeline/scripts/consumer.mjs";
|
|
50
49
|
|
|
51
50
|
const DBLP = "https://dblp.org/search/publ/api";
|
|
52
51
|
|
|
53
52
|
/* ---------- input: a .bib, a .tex with filecontents, or a paper dir ---------- */
|
|
54
53
|
|
|
55
|
-
/**
|
|
56
|
-
* Some papers carry no BibTeX at all. `compile-rules-2026` writes its 67 references as a
|
|
57
|
-
* hand-numbered markdown list that `repro/md2acl.py` turns into ACL format at build time:
|
|
58
|
-
*
|
|
59
|
-
* 12. N. F. Liu, K. Lin, J. Hewitt. *Lost in the Middle: How Language Models Use Long
|
|
60
|
-
* Contexts.* TACL, 2024. arXiv:2307.03172.
|
|
61
|
-
*
|
|
62
|
-
* 🔴 Exempting such a paper would be the wrong call, and measurably so: a hand-written author
|
|
63
|
-
* list has NO machine-checkable source, so it is the MORE exposed of the two formats, not the
|
|
64
|
-
* less. The class this script hunts lives exactly where an entry names a published venue and an
|
|
65
|
-
* arXiv id in the same breath — which is most of this list.
|
|
66
|
-
*
|
|
67
|
-
* Authors are taken only from the text BEFORE the first `*`, on purpose: entries here sometimes
|
|
68
|
-
* append a second work ("— and the reanalysis: S. B. Hossain, ...") after the title, and folding
|
|
69
|
-
* those names in would invent co-authors that the first work does not have.
|
|
70
|
-
*/
|
|
71
|
-
export function parseMarkdownRefs(text) {
|
|
72
|
-
// 🔴 The heading comes FROM THE PARSER, not from a regex (the base's rule "parse markdown with a
|
|
73
|
-
// parser"). The previous `text.search(/^#+\s*References\s*$/m)` opened the bibliography on a
|
|
74
|
-
// `## References` line QUOTED inside a ``` fence — and the papers in this repo quote their own
|
|
75
|
-
// markup in chunks. Exactly this assert already stands at a neighbour
|
|
76
|
-
// (`paper-pipeline/scripts/extract-ref-facts.harness.mjs`: "a heading inside a ``` block is not a
|
|
77
|
-
// heading"), that is, the class was known and was being reproduced here again.
|
|
78
|
-
// `requireMarkdown()` — so that a missing markdown-it fails LOUDLY: with an empty parser
|
|
79
|
-
// `headings()` returns [], and the gate would report "no references" instead of refusing. That is
|
|
80
|
-
// the same trade of one silent failure for another that the rule was written against.
|
|
81
|
-
requireMarkdown();
|
|
82
|
-
const h = mdHeadings(text).find((x) => /^References\s*$/u.test(x.text));
|
|
83
|
-
if (!h) return [];
|
|
84
|
-
const body = text.slice(h.offset);
|
|
85
|
-
const out = [];
|
|
86
|
-
// 🔴 `$(?![\s\S])`, NOT `\Z`. JavaScript has no `\Z` anchor — outside a unicode-mode pattern it
|
|
87
|
-
// is an identity escape meaning the LETTER Z, so the first version of this lookahead ended entry
|
|
88
|
-
// 1 in the middle of "J. Zhou", at the Z. Measured: 48 of 67 references parsed, and the missing
|
|
89
|
-
// 19 looked like ordinary gaps rather than a bug. Same family as the `\b`-over-Cyrillic defect
|
|
90
|
-
// already recorded in this repo: an escape that means one thing in Perl/Python and another here.
|
|
91
|
-
const re = /^(\d+)\.[ \t]+([\s\S]*?)(?=^\d+\.[ \t]|^#|$(?![\s\S]))/gm;
|
|
92
|
-
let m;
|
|
93
|
-
while ((m = re.exec(body))) {
|
|
94
|
-
const entry = m[2].replace(/\s*\n\s*/g, " ").trim();
|
|
95
|
-
const t = entry.match(/\*([^*]+)\*/);
|
|
96
|
-
if (!t) {
|
|
97
|
-
// No italic title and no author list — in this corpus these are SOFTWARE references
|
|
98
|
-
// (npm packages, repos). Nothing for DBLP to disagree with. They are surfaced as
|
|
99
|
-
// not-applicable rather than dropped: an entry that silently vanishes between the file
|
|
100
|
-
// and the report is indistinguishable from an entry that passed.
|
|
101
|
-
out.push({
|
|
102
|
-
type: "mdref",
|
|
103
|
-
key: `ref${m[1]}`,
|
|
104
|
-
unparsed: true,
|
|
105
|
-
author: "",
|
|
106
|
-
title: "",
|
|
107
|
-
booktitle: "",
|
|
108
|
-
journal: "",
|
|
109
|
-
});
|
|
110
|
-
continue;
|
|
111
|
-
}
|
|
112
|
-
const authorPart = entry
|
|
113
|
-
.slice(0, entry.indexOf("*"))
|
|
114
|
-
.trim()
|
|
115
|
-
.replace(/[.,;]\s*$/, "");
|
|
116
|
-
const rest = entry.slice(entry.indexOf(t[0]) + t[0].length);
|
|
117
|
-
out.push({
|
|
118
|
-
type: "mdref",
|
|
119
|
-
key: `ref${m[1]}`,
|
|
120
|
-
author: authorPart
|
|
121
|
-
.split(/,\s*|\s+and\s+/)
|
|
122
|
-
.filter(Boolean)
|
|
123
|
-
.join(" and "),
|
|
124
|
-
title: t[1].replace(/\.$/, "").trim(),
|
|
125
|
-
booktitle: rest.trim(),
|
|
126
|
-
journal: "",
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
return out;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
54
|
function bibTextFrom(target) {
|
|
133
55
|
let file = target;
|
|
134
56
|
if (!existsSync(file)) die(`no such path: ${file}`);
|
|
@@ -161,16 +83,16 @@ function bibTextFrom(target) {
|
|
|
161
83
|
}
|
|
162
84
|
return undefined;
|
|
163
85
|
};
|
|
164
|
-
const found =
|
|
165
|
-
|
|
166
|
-
pick(".tex") ||
|
|
167
|
-
names.find((f) => f === "paper.md" || f === "draft.md");
|
|
168
|
-
if (!found) die(`no .bib, .tex or paper.md in ${file}`);
|
|
86
|
+
const found = pick(".bib") || pick(".tex");
|
|
87
|
+
if (!found) die(`no .bib or .tex in ${file}`);
|
|
169
88
|
file = join(file, found);
|
|
170
89
|
}
|
|
171
90
|
const text = readFileSync(file, "utf-8");
|
|
172
|
-
if (file.endsWith(".md")) return { text, file, markdown: true };
|
|
173
91
|
if (file.endsWith(".bib")) return { text, file };
|
|
92
|
+
// Only a .bib and a .tex are read: any other file would fall through to the refs.bib beside it,
|
|
93
|
+
// and the report would name a file nobody asked about.
|
|
94
|
+
if (!file.endsWith(".tex"))
|
|
95
|
+
die(`${file} is not a .bib or a .tex — give the paper's .bib or paper.tex`);
|
|
174
96
|
// A .tex may carry the bibliography inline via filecontents — that is how our papers do it.
|
|
175
97
|
const m = text.match(
|
|
176
98
|
/\\begin\{filecontents\*?\}(?:\[[^\]]*\])?\{[^}]*\.bib\}\r?\n([\s\S]*?)\\end\{filecontents\*?\}/,
|
|
@@ -358,13 +280,6 @@ export async function checkAuthors(
|
|
|
358
280
|
const matched = []; // compared against the published record, and equal
|
|
359
281
|
const entries = parsed.filter((e) => e.title && e.author);
|
|
360
282
|
|
|
361
|
-
for (const e of parsed.filter((x) => x.unparsed)) {
|
|
362
|
-
skipped.push({
|
|
363
|
-
key: e.key,
|
|
364
|
-
why: "no author/title — a reference to software or a dataset, DBLP does not apply",
|
|
365
|
-
});
|
|
366
|
-
}
|
|
367
|
-
|
|
368
283
|
for (const e of entries) {
|
|
369
284
|
if (!claimsPublished(e)) continue; // a preprint entry is allowed to carry preprint metadata
|
|
370
285
|
if (truncated(e.author)) {
|
|
@@ -438,8 +353,8 @@ async function main() {
|
|
|
438
353
|
if (!args[0])
|
|
439
354
|
die("usage: bib-authors.mjs <paper-dir|file.bib|file.tex> [--json]");
|
|
440
355
|
|
|
441
|
-
const { text, file
|
|
442
|
-
const parsed =
|
|
356
|
+
const { text, file } = bibTextFrom(args[0]);
|
|
357
|
+
const parsed = parseBib(text);
|
|
443
358
|
const entries = parsed.filter((e) => e.title && e.author);
|
|
444
359
|
const { findings, skipped, unchecked } = await checkAuthors(parsed);
|
|
445
360
|
if (asJson) {
|
|
@@ -14,12 +14,7 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import assert from "node:assert/strict";
|
|
16
16
|
import { test } from "vitest";
|
|
17
|
-
import {
|
|
18
|
-
surnames,
|
|
19
|
-
compare,
|
|
20
|
-
claimsPublished,
|
|
21
|
-
parseMarkdownRefs,
|
|
22
|
-
} from "./bib-authors.mjs";
|
|
17
|
+
import { surnames, compare, claimsPublished } from "./bib-authors.mjs";
|
|
23
18
|
|
|
24
19
|
const t = test;
|
|
25
20
|
|
|
@@ -135,41 +130,3 @@ t("a proceedings entry IS in scope", () => {
|
|
|
135
130
|
true,
|
|
136
131
|
);
|
|
137
132
|
});
|
|
138
|
-
|
|
139
|
-
console.log("bib-authors — where the bibliography begins");
|
|
140
|
-
|
|
141
|
-
// Both halves. "Silent on a fence" without "finds the real one" is indistinguishable from a broken parse.
|
|
142
|
-
t("a real ## References is parsed", () => {
|
|
143
|
-
const md = [
|
|
144
|
-
"# Paper",
|
|
145
|
-
"text",
|
|
146
|
-
"",
|
|
147
|
-
"## References",
|
|
148
|
-
"",
|
|
149
|
-
"1. A. Author. *A title*. In NeurIPS, 2023.",
|
|
150
|
-
].join("\n");
|
|
151
|
-
const refs = parseMarkdownRefs(md);
|
|
152
|
-
assert.equal(refs.length, 1);
|
|
153
|
-
assert.match(refs[0].title, /A title/);
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
t("a ## References inside a ``` fence does NOT open the bibliography", () => {
|
|
157
|
-
const md = [
|
|
158
|
-
"# Paper",
|
|
159
|
-
"",
|
|
160
|
-
"The section is written like this:",
|
|
161
|
-
"",
|
|
162
|
-
"```markdown",
|
|
163
|
-
"## References",
|
|
164
|
-
"",
|
|
165
|
-
"1. Z. Ghost. *Not a reference, but a markup example*. In Nowhere, 2020.",
|
|
166
|
-
"```",
|
|
167
|
-
"",
|
|
168
|
-
"The end.",
|
|
169
|
-
].join("\n");
|
|
170
|
-
assert.deepEqual(
|
|
171
|
-
parseMarkdownRefs(md),
|
|
172
|
-
[],
|
|
173
|
-
"quoted markup is not a bibliography — the ^#+ regex counted it as a heading",
|
|
174
|
-
);
|
|
175
|
-
});
|
|
@@ -22,3 +22,25 @@ To re-record: run the same four requests with `curl` against a HotCRP site where
|
|
|
22
22
|
submission and a token (`Authorization: bearer $HOTCRP_TOKEN`), always with `dry_run=1` on a `POST`,
|
|
23
23
|
save each body, then replace every identifying value with a fake of the same type before committing.
|
|
24
24
|
These files ship in the npm package with the rest of `src/`, like the tests beside them.
|
|
25
|
+
|
|
26
|
+
## The deadlines pages
|
|
27
|
+
|
|
28
|
+
`deadlines-<site>.html` are five live sites' `GET /deadlines` pages and one site that does not exist,
|
|
29
|
+
recorded whole on 2026-10-05 (`curl`, no account): the page is public and carries no personal data,
|
|
30
|
+
so nothing is replaced. `deadlines.test.ts` parses each through the adapter's real parser; the
|
|
31
|
+
expected values were read off the pages' text by hand first. `/api/deadlines` on the same sites
|
|
32
|
+
answers 401 «Missing credentials», so the HTML page is the source.
|
|
33
|
+
`scripts/refresh-deadlines.test.ts` replays the MSR and AIDC pages through the scheduled refresh of
|
|
34
|
+
the presets' `deadlines` (`.github/workflows/deadlines.yml`). Re-read live through the adapter at
|
|
35
|
+
14:38 UTC the same day, both pages differed from these files only in the script nonces and `now`.
|
|
36
|
+
|
|
37
|
+
| file | site | HTTP | what it shows |
|
|
38
|
+
| ------------------------- | --------------------- | ---: | ------------------------------------------------------------------ |
|
|
39
|
+
| `deadlines-msr2027.html` | msr2027.hotcrp.com | 200 | submission and resubmission; the resubmission only in the list |
|
|
40
|
+
| `deadlines-aidc26.html` | aidc.submit.acsac.org | 200 | submission, and a final-version deadline only in the status object |
|
|
41
|
+
| `deadlines-sosp26.html` | sosp26.hotcrp.com | 200 | registration, submission, a late resubmission, final version |
|
|
42
|
+
| `deadlines-icse2027.html` | icse2027.hotcrp.com | 200 | a round that is not open (`"open":false`); dates printed as AoE |
|
|
43
|
+
| `deadlines-fse2027.html` | fse2027.hotcrp.com | 200 | one submission deadline printed as AoE |
|
|
44
|
+
| `deadlines-nosuch.html` | acsac2026.hotcrp.com | 404 | «No such conference» |
|
|
45
|
+
|
|
46
|
+
To re-record: `curl -sS -D - -o deadlines-<site>.html https://<site>/deadlines`.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
|
5
|
+
<link href="stylesheets/style.css?mtime=1782300564" rel="stylesheet">
|
|
6
|
+
<link rel="icon" type="image/png" href="images/review48.png">
|
|
7
|
+
<title>Deadlines - AIDC'26</title>
|
|
8
|
+
</head>
|
|
9
|
+
<body id="m-deadlines" data-upload-limit="33554432"><div id="p-page" class="need-banner-offset"><header id="p-header"><hr class="c"><div id="h-site" class="header-site-page"><a class="q" href="/"><span class="header-site-name">AIDC'26</span></a></div><div id="h-right"></div><div id="h-page"><h1 id="h-title">Deadlines</h1></div><nav id="p-quicklinks" aria-label="Submission search"></nav><hr class="c">
|
|
10
|
+
<div id="h-messages" class="want-mx-auto"></div></header>
|
|
11
|
+
<main id="p-body">
|
|
12
|
+
<h3>Past</h3><dl class="bsp"><dt><strong>Submission deadline</strong>: <span class="need-usertime" data-ts="1791028799">Saturday Oct 3, 2026, 11:59:59 UTC</span></dt><dd> submissions must be completed by this deadline to be reviewed.</dd></dl>
|
|
13
|
+
<hr class="c"></main></div><footer id="p-footer" class="need-banner-offset banner-bottom"><a class="noq" href="https://hotcrp.com/">HotCRP</a></footer><!--[if lt IE 9]><script src="scripts/jquery-1.12.4.min.js?mtime=1782300564" integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ="></script><![endif]-->
|
|
14
|
+
<![if !IE|gte IE 9]><script src="scripts/jquery-3.7.1.min.js?mtime=1782300564" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo="></script><![endif]>
|
|
15
|
+
<script>window.siteinfo={"site_relative":"","base":"\/","suffix":"","assets":"","cookie_params":"; SameSite=Lax","postvalue":".empty","snouns":["submission","submissions","Submission","Submissions"],"user":[]}</script><script src="scripts/script.js?mtime=1782300564"></script>
|
|
16
|
+
<script>hotcrp.onload.time(0,1);hotcrp.init_deadlines({"now":1791194489.473936,"email":null,"sub":{"open":true,"sub":1791028799,"blind":true},"final":{"open":true,"done":1793447999}})</script></body>
|
|
17
|
+
</html>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
|
5
|
+
<meta name="google" content="notranslate">
|
|
6
|
+
<meta name="theme-color" content="#ffb7ca">
|
|
7
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
8
|
+
<link href="https://static.hotcrp.com/@1790985506/stylesheets/style.css" rel="stylesheet">
|
|
9
|
+
<link href="https://static.hotcrp.com/@1786633883/stylesheets/mobile.css" media="screen and (max-width: 1100px)" rel="stylesheet">
|
|
10
|
+
<link href="https://static.hotcrp.com/@1788721683/stylesheets/plugin.css" rel="stylesheet">
|
|
11
|
+
<link rel="icon" type="image/svg+xml" href="https://static.hotcrp.com/images/review48.svg">
|
|
12
|
+
<title>Deadlines - FSE 2027</title>
|
|
13
|
+
</head>
|
|
14
|
+
<body id="m-deadlines" data-upload-limit="104857600" data-document-max-size="600000000"><div id="p-page" class="need-banner-offset"><header id="p-header"><hr class="c"><div id="h-site" class="header-site-page"><a class="q" href="/"><span class="header-site-name">FSE 2027</span></a></div><div id="h-right"></div><div id="h-page"><h1 id="h-title">Deadlines</h1></div><nav id="p-quicklinks" aria-label="Submission search"></nav><hr class="c">
|
|
15
|
+
<div id="h-messages" class="want-mx-auto"></div></header>
|
|
16
|
+
<main id="p-body">
|
|
17
|
+
<h3>Past</h3><dl class="bsp"><dt><strong>Submission deadline</strong>: <span class="need-usertime" data-ts="1791115140">Saturday Oct 3, 2026, 11:59 PM AoE</span></dt><dd>Submissions must be completed by this deadline to be reviewed.</dd></dl>
|
|
18
|
+
<hr class="c"></main></div><footer id="p-footer" class="need-banner-offset banner-bottom"><a class="noq" href="https://hotcrp.com/">HotCRP</a><!-- Version 3.4 --></footer><!--[if lt IE 9]><script nonce="P6MeSP0WsZYikm82vBcVfQ==" src="https://static.hotcrp.com/@1749780400/scripts/jquery-1.12.4.min.js" crossorigin="anonymous" integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ="></script><![endif]-->
|
|
19
|
+
<![if !IE|gte IE 9]><script nonce="P6MeSP0WsZYikm82vBcVfQ==" src="https://static.hotcrp.com/@1749780400/scripts/jquery-3.7.1.min.js" crossorigin="anonymous" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo="></script><![endif]>
|
|
20
|
+
<script nonce="P6MeSP0WsZYikm82vBcVfQ==">window.siteinfo={"site_relative":"","base":"\/","suffix":"","assets":"https:\/\/static.hotcrp.com\/","icons_url":"@1787797517\/images\/icons.svg","cookie_params":"; Domain=.hotcrp.com; Secure; SameSite=Lax","postvalue":".empty","download_prefix":"fse2027-","snouns":["submission","submissions","Submission","Submissions"],"user":[]}</script><script nonce="P6MeSP0WsZYikm82vBcVfQ==" src="https://static.hotcrp.com/@1790985505/scripts/script.js" crossorigin="anonymous"></script>
|
|
21
|
+
<script nonce="P6MeSP0WsZYikm82vBcVfQ==" src="https://static.hotcrp.com/@1777496734/scripts/markdown-it.min.js" crossorigin="anonymous"></script>
|
|
22
|
+
<script nonce="P6MeSP0WsZYikm82vBcVfQ==" src="https://static.hotcrp.com/@1787955704/scripts/plugin.js" crossorigin="anonymous"></script>
|
|
23
|
+
<script nonce="P6MeSP0WsZYikm82vBcVfQ==">hotcrp.onload.time(720,0);hotcrp.init_deadlines({"now":1791194490.16279,"email":null,"sub":{"open":true,"sub":1791115140,"blind":true}})</script></body>
|
|
24
|
+
</html>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
|
5
|
+
<meta name="google" content="notranslate">
|
|
6
|
+
<meta name="theme-color" content="#ffb7ca">
|
|
7
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
8
|
+
<link href="https://static.hotcrp.com/@1790985506/stylesheets/style.css" rel="stylesheet">
|
|
9
|
+
<link href="https://static.hotcrp.com/@1786633883/stylesheets/mobile.css" media="screen and (max-width: 1100px)" rel="stylesheet">
|
|
10
|
+
<link href="https://static.hotcrp.com/@1788721683/stylesheets/plugin.css" rel="stylesheet">
|
|
11
|
+
<link rel="icon" type="image/svg+xml" href="https://static.hotcrp.com/images/review48.svg">
|
|
12
|
+
<title>Deadlines - ICSE 2027</title>
|
|
13
|
+
</head>
|
|
14
|
+
<body id="m-deadlines" data-upload-limit="104857600" data-document-max-size="600000000"><div id="p-page" class="need-banner-offset"><header id="p-header"><hr class="c"><div id="h-site" class="header-site-page"><a class="q" href="/"><span class="header-site-name">ICSE 2027</span></a></div><div id="h-right"></div><div id="h-page"><h1 id="h-title">Deadlines</h1></div><nav id="p-quicklinks" aria-label="Submission search"></nav><hr class="c">
|
|
15
|
+
<div id="h-messages" class="want-mx-auto"></div></header>
|
|
16
|
+
<main id="p-body">
|
|
17
|
+
<h3>Past</h3><dl class="bsp"><dt><strong>Submission deadline</strong>: <span class="need-usertime" data-ts="1783598340">Wednesday Jul 8, 2026, 11:59 PM AoE</span></dt><dd>Submissions must be completed by this deadline to be reviewed.</dd>
|
|
18
|
+
<dt><strong>Registration deadline</strong>: <span class="need-usertime" data-ts="1782302399">Tuesday Jun 23, 2026, 11:59:59 PM AoE</span></dt><dd>You can register new submissions until this deadline.</dd></dl>
|
|
19
|
+
<hr class="c"></main></div><footer id="p-footer" class="need-banner-offset banner-bottom"><a class="noq" href="https://hotcrp.com/">HotCRP</a><!-- Version 3.4 --></footer><!--[if lt IE 9]><script nonce="FL4FfJ6tspuiYI3NwY6I0w==" src="https://static.hotcrp.com/@1749780400/scripts/jquery-1.12.4.min.js" crossorigin="anonymous" integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ="></script><![endif]-->
|
|
20
|
+
<![if !IE|gte IE 9]><script nonce="FL4FfJ6tspuiYI3NwY6I0w==" src="https://static.hotcrp.com/@1749780400/scripts/jquery-3.7.1.min.js" crossorigin="anonymous" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo="></script><![endif]>
|
|
21
|
+
<script nonce="FL4FfJ6tspuiYI3NwY6I0w==">window.siteinfo={"site_relative":"","base":"\/","suffix":"","assets":"https:\/\/static.hotcrp.com\/","icons_url":"@1787797517\/images\/icons.svg","cookie_params":"; Domain=.hotcrp.com; Secure; SameSite=Lax","postvalue":".empty","download_prefix":"icse2027-","snouns":["submission","submissions","Submission","Submissions"],"user":[]}</script><script nonce="FL4FfJ6tspuiYI3NwY6I0w==" src="https://static.hotcrp.com/@1790985505/scripts/script.js" crossorigin="anonymous"></script>
|
|
22
|
+
<script nonce="FL4FfJ6tspuiYI3NwY6I0w==" src="https://static.hotcrp.com/@1777496734/scripts/markdown-it.min.js" crossorigin="anonymous"></script>
|
|
23
|
+
<script nonce="FL4FfJ6tspuiYI3NwY6I0w==" src="https://static.hotcrp.com/@1787955704/scripts/plugin.js" crossorigin="anonymous"></script>
|
|
24
|
+
<script nonce="FL4FfJ6tspuiYI3NwY6I0w==">hotcrp.onload.time(720,0);hotcrp.init_deadlines({"now":1791194489.960642,"email":null,"sub":{"open":false,"sub":1783598340,"reg":1782302399,"blind":true}})</script></body>
|
|
25
|
+
</html>
|