paperlint 4.0.0 → 4.2.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 +16 -23
- package/CLAUDE.md +55 -11
- package/CONTRIBUTING.md +30 -7
- package/README.md +11 -8
- package/dist/adapters/banal/invocation.d.ts +1 -1
- package/dist/adapters/latex/document-class.d.ts +23 -0
- package/dist/adapters/latex/document-class.d.ts.map +1 -0
- package/dist/adapters/latex/document-class.js +110 -0
- package/dist/adapters/latex/document-class.js.map +1 -0
- package/dist/adapters/latex/hidden.d.ts +16 -0
- package/dist/adapters/latex/hidden.d.ts.map +1 -0
- package/dist/adapters/latex/hidden.js +49 -0
- package/dist/adapters/latex/hidden.js.map +1 -0
- package/dist/adapters/latex/includes.d.ts +12 -0
- package/dist/adapters/latex/includes.d.ts.map +1 -0
- package/dist/adapters/latex/includes.js +42 -0
- package/dist/adapters/latex/includes.js.map +1 -0
- package/dist/adapters/latex/index.d.ts +33 -0
- package/dist/adapters/latex/index.d.ts.map +1 -0
- package/dist/adapters/latex/index.js +25 -0
- package/dist/adapters/latex/index.js.map +1 -0
- package/dist/adapters/latex/nodes.d.ts +58 -0
- package/dist/adapters/latex/nodes.d.ts.map +1 -0
- package/dist/adapters/latex/nodes.js +97 -0
- package/dist/adapters/latex/nodes.js.map +1 -0
- package/dist/adapters/latex/outline.d.ts +10 -0
- package/dist/adapters/latex/outline.d.ts.map +1 -0
- package/dist/adapters/latex/outline.js +39 -0
- package/dist/adapters/latex/outline.js.map +1 -0
- package/dist/adapters/latex/parse.d.ts +42 -0
- package/dist/adapters/latex/parse.d.ts.map +1 -0
- package/dist/adapters/latex/parse.js +95 -0
- package/dist/adapters/latex/parse.js.map +1 -0
- package/dist/adapters/latex/prose.d.ts +8 -0
- package/dist/adapters/latex/prose.d.ts.map +1 -0
- package/dist/adapters/latex/prose.js +353 -0
- package/dist/adapters/latex/prose.js.map +1 -0
- package/dist/adapters/latex/rendered.d.ts +10 -0
- package/dist/adapters/latex/rendered.d.ts.map +1 -0
- package/dist/adapters/latex/rendered.js +39 -0
- package/dist/adapters/latex/rendered.js.map +1 -0
- package/dist/adapters/pdfjs/fill.d.ts.map +1 -1
- package/dist/adapters/pdfjs/fill.js +12 -12
- package/dist/adapters/pdfjs/fill.js.map +1 -1
- package/dist/build.js +4 -4
- package/dist/build.js.map +1 -1
- package/dist/claim-provenance.d.ts +34 -0
- package/dist/claim-provenance.d.ts.map +1 -0
- package/dist/claim-provenance.js +146 -0
- package/dist/claim-provenance.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +49 -5
- package/dist/cli.js.map +1 -1
- package/dist/domain/paper-source.d.ts +58 -0
- package/dist/domain/paper-source.d.ts.map +1 -0
- package/dist/domain/paper-source.js +109 -0
- package/dist/domain/paper-source.js.map +1 -0
- package/dist/domain/sentences.d.ts +26 -0
- package/dist/domain/sentences.d.ts.map +1 -0
- package/dist/domain/sentences.js +48 -0
- package/dist/domain/sentences.js.map +1 -0
- package/dist/domain/tex-document.d.ts +119 -0
- package/dist/domain/tex-document.d.ts.map +1 -0
- package/dist/domain/tex-document.js +43 -0
- package/dist/domain/tex-document.js.map +1 -0
- package/dist/eslint-rules/paper-typography.d.ts +7 -0
- package/dist/eslint-rules/paper-typography.d.ts.map +1 -1
- package/dist/eslint-rules/paper-typography.js +53 -1
- package/dist/eslint-rules/paper-typography.js.map +1 -1
- package/dist/facts-file.d.ts.map +1 -1
- package/dist/facts-file.js +2 -2
- package/dist/facts-file.js.map +1 -1
- package/dist/new-paper.d.ts +5 -0
- package/dist/new-paper.d.ts.map +1 -1
- package/dist/new-paper.js +3 -0
- package/dist/new-paper.js.map +1 -1
- package/dist/package-dirs.d.ts +5 -0
- package/dist/package-dirs.d.ts.map +1 -0
- package/dist/package-dirs.js +14 -0
- package/dist/package-dirs.js.map +1 -0
- package/dist/ports/latex.d.ts +35 -0
- package/dist/ports/latex.d.ts.map +1 -0
- package/dist/ports/latex.js +2 -0
- package/dist/ports/latex.js.map +1 -0
- package/dist/presets.d.ts +15 -2
- package/dist/presets.d.ts.map +1 -1
- package/dist/presets.js +19 -6
- package/dist/presets.js.map +1 -1
- package/dist/register.d.ts +40 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/register.js +134 -0
- package/dist/register.js.map +1 -0
- package/dist/tex-paper.d.ts +19 -0
- package/dist/tex-paper.d.ts.map +1 -0
- package/dist/tex-paper.js +105 -0
- package/dist/tex-paper.js.map +1 -0
- package/dist/tex-requirements.d.ts +11 -0
- package/dist/tex-requirements.d.ts.map +1 -1
- package/dist/tex-requirements.js +14 -8
- package/dist/tex-requirements.js.map +1 -1
- package/dist/tex-venue-rules.d.ts +88 -0
- package/dist/tex-venue-rules.d.ts.map +1 -0
- package/dist/tex-venue-rules.js +268 -0
- package/dist/tex-venue-rules.js.map +1 -0
- package/dist/venue-rules.d.ts +1 -1
- package/dist/venue-rules.d.ts.map +1 -1
- package/docs/configuration.md +3 -2
- package/docs/e2e.md +69 -40
- package/docs/install.md +1 -1
- package/docs/prior-art/README.md +1 -1
- package/docs/prior-art/package-location.md +5 -5
- package/docs/prior-art/repro/README.md +1 -1
- package/docs/prior-art/test-tooling.md +21 -10
- package/docs/rules/tex/claim-provenance.md +83 -0
- package/docs/rules/tex/missing-input.md +58 -0
- package/docs/rules/tex/register.md +77 -0
- package/docs/rules/tex/required-section.md +75 -0
- package/docs/rules/tex/template.md +74 -0
- package/docs/rules/tex/venue-leftover.md +73 -0
- package/docs/rules.md +73 -48
- package/docs/testing.md +17 -4
- package/docs/texlive-install-decision.md +1 -1
- package/docs/toolchain.md +2 -2
- package/eslint-rules/paper-typography.test.mjs +48 -1
- package/eslint-rules/paper-typography.ts +72 -1
- package/eslint.config.mjs +156 -15
- package/fixtures/build-e2e/acmart/expect.json +26 -0
- package/fixtures/build-e2e/aidc/PIPELINE-STATUS.md +3 -0
- package/fixtures/build-e2e/aidc/expect.json +14 -0
- package/fixtures/build-e2e/aidc/paper.tex +46 -0
- package/fixtures/build-e2e/aidc/paperlint.json +1 -0
- package/fixtures/build-e2e/broken/expect.json +11 -0
- package/fixtures/build-e2e/cite/expect.json +27 -0
- package/fixtures/build-e2e/empty/expect.json +12 -0
- package/fixtures/build-e2e/fallback/expect.json +53 -0
- package/fixtures/build-e2e/guards/expect.json +6 -0
- package/fixtures/build-e2e/no-source/expect.json +10 -0
- package/fixtures/build-e2e/unbalanced/expect.json +60 -0
- package/fixtures/pdf-facts/README.md +1 -1
- package/fixtures/real-markdown-paper/baseline.ts +8 -7
- package/fixtures/render-paper/build-clean.sh +3 -5
- package/package.json +14 -2
- package/{skills/submit-paper/references/venues → presets}/acm-sigconf.jsonc +4 -1
- package/{skills/submit-paper/references/venues → presets}/agenticdev.jsonc +4 -0
- package/presets/aidc.jsonc +73 -0
- package/{skills/submit-paper/references/venues → presets}/aisec.jsonc +4 -0
- package/presets/ieee-conference.jsonc +66 -0
- package/{skills/submit-paper/references/venues → presets}/realm.jsonc +8 -1
- package/{skills/submit-paper/references/venues → presets/tex}/paper-guards.tex +1 -1
- package/{skills/submit-paper/references/venues → presets}/venue-profile.schema.json +30 -2
- package/scripts/check.harness.ts +64 -10
- package/scripts/check.test.ts +60 -13
- package/scripts/check.ts +83 -30
- package/scripts/test.test.ts +1 -1
- package/scripts/test.ts +1 -1
- package/skills/cold-read-diff/SKILL.md +31 -10
- package/skills/cold-read-diff/SKILL.md.spec.ts +30 -9
- package/skills/draft-paper/SKILL.md +2 -2
- package/skills/draft-paper/SKILL.md.spec.ts +1 -1
- package/skills/grade-paper-writing/SKILL.md +109 -44
- package/skills/grade-paper-writing/SKILL.md.spec.ts +108 -43
- package/skills/harden-paper/SKILL.md +35 -36
- package/skills/harden-paper/SKILL.md.spec.ts +34 -35
- package/skills/paper-adversarial-review/SKILL.md +2 -2
- package/skills/paper-adversarial-review/SKILL.md.spec.ts +1 -1
- package/skills/paper-pipeline/PIPELINE-MAP.md +2 -2
- package/skills/paper-pipeline/SKILL.md +4 -4
- package/skills/paper-pipeline/SKILL.md.spec.ts +3 -3
- package/skills/paper-pipeline/grade-paper-writing-ablation.eval.mjs +6 -6
- package/skills/paper-pipeline/references/writing-craft.md +53 -18
- package/skills/paper-pipeline/scripts/consumer.d.mts +0 -2
- package/skills/paper-pipeline/scripts/consumer.mjs +1 -15
- package/skills/pc-panel-review/SKILL.md +36 -11
- package/skills/pc-panel-review/SKILL.md.spec.ts +35 -10
- package/skills/render-paper/SKILL.md +2 -2
- package/skills/render-paper/SKILL.md.spec.ts +1 -1
- package/skills/render-paper/check-render.sh +16 -63
- package/skills/render-paper/render-paper.harness.mjs +17 -59
- package/src/adapters/banal/index.test.ts +1 -1
- package/src/adapters/banal/invocation.ts +1 -1
- package/src/adapters/banal/output.test.ts +1 -1
- package/src/adapters/banal/run.test.ts +1 -1
- package/src/adapters/banal/xml.test.ts +1 -1
- package/src/adapters/latex/document-class.ts +155 -0
- package/src/adapters/latex/hidden.ts +70 -0
- package/src/adapters/latex/includes.ts +66 -0
- package/src/adapters/latex/index.test.ts +535 -0
- package/src/adapters/latex/index.ts +65 -0
- package/src/adapters/latex/nodes.ts +150 -0
- package/src/adapters/latex/outline.ts +64 -0
- package/src/adapters/latex/parse.ts +137 -0
- package/src/adapters/latex/prose.ts +484 -0
- package/src/adapters/latex/rendered.ts +59 -0
- package/src/adapters/pdfjs/fill.test.ts +1 -1
- package/src/adapters/pdfjs/fill.ts +18 -10
- package/src/build.harness.mjs +5 -7
- package/src/build.ts +4 -4
- package/src/claim-provenance.test.ts +352 -0
- package/src/claim-provenance.ts +217 -0
- package/src/cli.harness.mjs +1 -1
- package/src/cli.test.ts +2 -8
- package/src/cli.ts +53 -8
- package/src/domain/paper-source.test.ts +156 -0
- package/src/domain/paper-source.ts +233 -0
- package/src/domain/sentences.ts +67 -0
- package/src/domain/tex-document.test.ts +80 -0
- package/src/domain/tex-document.ts +143 -0
- package/src/engine.harness.mjs +1 -1
- package/src/facts-file.test.ts +4 -7
- package/src/facts-file.ts +2 -2
- package/src/latex-loop.harness.ts +1 -1
- package/src/new-paper.test.ts +28 -3
- package/src/new-paper.ts +8 -0
- package/src/package-dirs.ts +17 -0
- package/src/paper-settings-commands.test.ts +6 -1
- package/src/ports/latex.ts +42 -0
- package/src/presets.test.ts +65 -4
- package/src/presets.ts +38 -15
- package/src/register.test.ts +165 -0
- package/src/register.ts +177 -0
- package/src/rule-cases.test.ts +524 -0
- package/src/rule-docs.test.ts +159 -0
- package/src/tex-paper.test.ts +131 -0
- package/src/tex-paper.ts +152 -0
- package/src/tex-requirements.harness.ts +13 -23
- package/src/tex-requirements.ts +35 -8
- package/src/tex-venue-rules.test.ts +741 -0
- package/src/tex-venue-rules.ts +461 -0
- package/src/toolchain.harness.mjs +1 -1
- package/src/venue-rules.test.ts +96 -4
- package/src/venue-rules.ts +1 -1
- package/templates/paper/paper.tex +2 -1
- package/skills/harden-paper/fixtures/uncited-assertions-sample.md +0 -43
- package/skills/harden-paper/fixtures/uncited-assertions-sample.tex +0 -77
- /package/{skills/submit-paper/references/venues → presets/tex}/agenticdev.tex +0 -0
- /package/{skills/submit-paper/references/venues → presets}/tex-base.jsonc +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: pc-panel-review
|
|
3
|
-
description: Use when asking "what would the program committee decide?" / "simulate the reviewers" / "what's this paper's accept probability?" on a drafted paper + artifact. Spawns N independent reviewers with DISTINCT lenses (one actually RUNS the artifact), then synthesizes a PC-chair meta-review into an accept/reject decision, a calibrated probability, and consensus must-fixes. Requires grade-paper-writing's persona stall inventory + tighten-paper's structural verdict as inputs (blocked until they exist — the panel cannot feel reader fatigue on its own). Also has a lightweight single-reviewer VENUE-FIT MODE for a quick CFP-fit spot-check. NOT a single fast defect hunt (paper-adversarial-review), a writing grade (grade-paper-writing), or the full pre-submit gate (harden-paper, which calls this) — this models the PC decision itself.
|
|
3
|
+
description: Use when asking "what would the program committee decide?" / "simulate the reviewers" / "what's this paper's accept probability?" on a drafted paper + artifact. Spawns N independent reviewers with DISTINCT lenses (one actually RUNS the artifact, one is a skimming genre/register reviewer), then synthesizes a PC-chair meta-review into an accept/reject decision reported as min/median/max, a calibrated probability, and consensus must-fixes. Requires grade-paper-writing's persona stall inventory + tighten-paper's structural verdict as inputs (blocked until they exist — the panel cannot feel reader fatigue on its own). Also has a lightweight single-reviewer VENUE-FIT MODE for a quick CFP-fit spot-check. NOT a single fast defect hunt (paper-adversarial-review), a writing grade (grade-paper-writing), or the full pre-submit gate (harden-paper, which calls this) — this models the PC decision itself.
|
|
4
4
|
allowed-tools: [Read, Write, Grep, Glob, Bash, WebSearch, WebFetch, Agent, Skill]
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
<!-- vigiles:sha256:
|
|
7
|
+
<!-- vigiles:sha256:7e5fb04d1cfa0548 compiled from skills/pc-panel-review/SKILL.md.spec.ts -->
|
|
8
8
|
|
|
9
9
|
# pc-panel-review — model the whole PC, not one reviewer
|
|
10
10
|
|
|
@@ -51,7 +51,15 @@ prose-only read can.
|
|
|
51
51
|
panel's only legitimate source for the readability/structure signal.
|
|
52
52
|
*(Scorecard: this gate is row **`panel`**, and it declares **`structure`** (tighten-paper) + **`writing`**
|
|
53
53
|
(grade-paper-writing) as its required inputs.)*
|
|
54
|
-
3. **Pick 3 (or 4) reviewer lenses** that a real PC for THIS venue would field.
|
|
54
|
+
3. **Pick 3 (or 4) reviewer lenses** that a real PC for THIS venue would field. One is fixed; the rest
|
|
55
|
+
come from the menu, by fit:
|
|
56
|
+
- **Genre/register reviewer — MANDATORY on every panel, at every venue.** Confidence 3 (knows the
|
|
57
|
+
area, not this topic), reads ONLY the abstract, the introduction and the conclusion, and judges
|
|
58
|
+
whether this reads as a paper at this venue: whose result each sentence states, whether the
|
|
59
|
+
relations between claims are signposted or left to infer, and whether anything is an aphorism,
|
|
60
|
+
a fragment or a colloquial turn. This is the reviewer who writes one short review, scores low,
|
|
61
|
+
and calls the paper a blog post — the one reviewer a panel of careful full readers never
|
|
62
|
+
predicts. Give it the three sections as text and the venue's name, nothing else.
|
|
55
63
|
- **Methods/stats skeptic** — sample size, construct validity, multiple comparisons, overclaims,
|
|
56
64
|
whether the CIs support the claims.
|
|
57
65
|
- **Domain practitioner** — relevance to the CFP, novelty vs the nearest prior work, does the
|
|
@@ -67,7 +75,13 @@ prose-only read can.
|
|
|
67
75
|
4. **Spawn them in PARALLEL, each on a separate model instance** (e.g. Fable via subagent), each blind
|
|
68
76
|
to the others — independence is the whole point. Give each: the paper (`.tex`/PDF), the artifact
|
|
69
77
|
path, the quoted rubric, its lens, **and the two step-2 artifacts (persona stall inventory +
|
|
70
|
-
tighten-paper structural verdict)
|
|
78
|
+
tighten-paper structural verdict)** — the genre/register reviewer gets only its three sections.
|
|
79
|
+
Force a filled review form (below).
|
|
80
|
+
|
|
81
|
+
🔴 **No reviewer is shown a previous round** — not its scores, not its reviews, not "the panel
|
|
82
|
+
gave 3.25 last time", not a list of what changed since. A reviewer who is told the last score
|
|
83
|
+
anchors on it (*"up from the 3.25 the earlier rounds reported"*), and the rounds then converge on
|
|
84
|
+
each other instead of on the paper. Comparing rounds is the chair's job, after the reviews land.
|
|
71
85
|
5. **Synthesize the meta-review yourself** (PC chair) once all land — see output.
|
|
72
86
|
|
|
73
87
|
## Each reviewer returns a review form
|
|
@@ -90,10 +104,19 @@ prose-only read can.
|
|
|
90
104
|
- One-line meta: does this belong at this venue?
|
|
91
105
|
|
|
92
106
|
## The meta-review (PC-chair synthesis) — the actual deliverable
|
|
93
|
-
- **Score table:** each reviewer × each criterion + overall + confidence, at a glance
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
107
|
+
- **Score table:** each reviewer × each criterion + overall + confidence, at a glance, and under it
|
|
108
|
+
the overall score's **min / median / max** across reviewers — never a mean alone, which hides the
|
|
109
|
+
one low review that decides a workshop.
|
|
110
|
+
- **Decision:** for a **workshop**, the decision follows the **MIN**: a workshop PC with three
|
|
111
|
+
reviews and a short discussion does not overrule a reject, so one Reject or Strong Reject sinks the
|
|
112
|
+
paper however confident the others are. For a conference, the rec the PC discussion converges on,
|
|
113
|
+
weighted by confidence, with the min named beside it. Either way, a **calibrated accept probability**
|
|
114
|
+
for this venue and edition.
|
|
115
|
+
- 🔴 **One reviewer is not a panel.** A run with fewer than three reviews and a meta-review — a
|
|
116
|
+
Venue-fit spot-check, a single re-review, a panel whose other seats did not return — is recorded as
|
|
117
|
+
what it is (`venue-fit`, `single review`), never in the scorecard's `panel` row. A single
|
|
118
|
+
review recorded as a panel verdict is how a paper reaches submission on an 88% that three real
|
|
119
|
+
reviewers turned into a reject.
|
|
97
120
|
- **Consensus must-fixes:** issues **≥2 reviewers independently raised** — these are the real ones;
|
|
98
121
|
apply before submitting.
|
|
99
122
|
- **Single-reviewer flags:** noted, triaged (fix if cheap, else defer to camera-ready).
|
|
@@ -199,9 +222,11 @@ reject-risk without rubber-stamping. For the real decision, escalate to the full
|
|
|
199
222
|
## The reproduce loop (why this beats a prose review)
|
|
200
223
|
This is "double-blind review as a real venue does it, WITH reproduction." The artifact-runner reviewer
|
|
201
224
|
is the difference-maker on both runs so far: it doesn't judge the paper's numbers, it re-derives them.
|
|
202
|
-
Run the panel, apply the consensus fixes, then **re-run the panel**
|
|
203
|
-
confirm the fixes landed and nothing regressed
|
|
204
|
-
|
|
225
|
+
Run the panel, apply the consensus fixes, then **re-run the panel** — same lenses, FRESH reviewers,
|
|
226
|
+
told nothing about the previous round — to confirm the fixes landed and nothing regressed; the
|
|
227
|
+
artifact-runner re-executes every harness each round. The chair, not the reviewers, sets the new
|
|
228
|
+
reviews beside the old ones and checks that each earlier must-fix is gone. Track the min / median / max
|
|
229
|
+
progression in the review ledger. Stop when the panel converges to
|
|
205
230
|
accept and the artifact reproduces clean; don't loop past one confirming round.
|
|
206
231
|
|
|
207
232
|
## Provenance (two papers, battle-tested)
|
|
@@ -9,7 +9,7 @@ import { experimental_skill } from "vigiles/spec";
|
|
|
9
9
|
export default experimental_skill({
|
|
10
10
|
name: "pc-panel-review",
|
|
11
11
|
description:
|
|
12
|
-
'Use when asking "what would the program committee decide?" / "simulate the reviewers" / "what\'s this paper\'s accept probability?" on a drafted paper + artifact. Spawns N independent reviewers with DISTINCT lenses (one actually RUNS the artifact), then synthesizes a PC-chair meta-review into an accept/reject decision, a calibrated probability, and consensus must-fixes. Requires grade-paper-writing\'s persona stall inventory + tighten-paper\'s structural verdict as inputs (blocked until they exist — the panel cannot feel reader fatigue on its own). Also has a lightweight single-reviewer VENUE-FIT MODE for a quick CFP-fit spot-check. NOT a single fast defect hunt (paper-adversarial-review), a writing grade (grade-paper-writing), or the full pre-submit gate (harden-paper, which calls this) — this models the PC decision itself.',
|
|
12
|
+
'Use when asking "what would the program committee decide?" / "simulate the reviewers" / "what\'s this paper\'s accept probability?" on a drafted paper + artifact. Spawns N independent reviewers with DISTINCT lenses (one actually RUNS the artifact, one is a skimming genre/register reviewer), then synthesizes a PC-chair meta-review into an accept/reject decision reported as min/median/max, a calibrated probability, and consensus must-fixes. Requires grade-paper-writing\'s persona stall inventory + tighten-paper\'s structural verdict as inputs (blocked until they exist — the panel cannot feel reader fatigue on its own). Also has a lightweight single-reviewer VENUE-FIT MODE for a quick CFP-fit spot-check. NOT a single fast defect hunt (paper-adversarial-review), a writing grade (grade-paper-writing), or the full pre-submit gate (harden-paper, which calls this) — this models the PC decision itself.',
|
|
13
13
|
tools: [
|
|
14
14
|
"Read",
|
|
15
15
|
"Write",
|
|
@@ -67,7 +67,15 @@ prose-only read can.
|
|
|
67
67
|
panel's only legitimate source for the readability/structure signal.
|
|
68
68
|
*(Scorecard: this gate is row **\`panel\`**, and it declares **\`structure\`** (tighten-paper) + **\`writing\`**
|
|
69
69
|
(grade-paper-writing) as its required inputs.)*
|
|
70
|
-
3. **Pick 3 (or 4) reviewer lenses** that a real PC for THIS venue would field.
|
|
70
|
+
3. **Pick 3 (or 4) reviewer lenses** that a real PC for THIS venue would field. One is fixed; the rest
|
|
71
|
+
come from the menu, by fit:
|
|
72
|
+
- **Genre/register reviewer — MANDATORY on every panel, at every venue.** Confidence 3 (knows the
|
|
73
|
+
area, not this topic), reads ONLY the abstract, the introduction and the conclusion, and judges
|
|
74
|
+
whether this reads as a paper at this venue: whose result each sentence states, whether the
|
|
75
|
+
relations between claims are signposted or left to infer, and whether anything is an aphorism,
|
|
76
|
+
a fragment or a colloquial turn. This is the reviewer who writes one short review, scores low,
|
|
77
|
+
and calls the paper a blog post — the one reviewer a panel of careful full readers never
|
|
78
|
+
predicts. Give it the three sections as text and the venue's name, nothing else.
|
|
71
79
|
- **Methods/stats skeptic** — sample size, construct validity, multiple comparisons, overclaims,
|
|
72
80
|
whether the CIs support the claims.
|
|
73
81
|
- **Domain practitioner** — relevance to the CFP, novelty vs the nearest prior work, does the
|
|
@@ -83,7 +91,13 @@ prose-only read can.
|
|
|
83
91
|
4. **Spawn them in PARALLEL, each on a separate model instance** (e.g. Fable via subagent), each blind
|
|
84
92
|
to the others — independence is the whole point. Give each: the paper (\`.tex\`/PDF), the artifact
|
|
85
93
|
path, the quoted rubric, its lens, **and the two step-2 artifacts (persona stall inventory +
|
|
86
|
-
tighten-paper structural verdict)
|
|
94
|
+
tighten-paper structural verdict)** — the genre/register reviewer gets only its three sections.
|
|
95
|
+
Force a filled review form (below).
|
|
96
|
+
|
|
97
|
+
🔴 **No reviewer is shown a previous round** — not its scores, not its reviews, not "the panel
|
|
98
|
+
gave 3.25 last time", not a list of what changed since. A reviewer who is told the last score
|
|
99
|
+
anchors on it (*"up from the 3.25 the earlier rounds reported"*), and the rounds then converge on
|
|
100
|
+
each other instead of on the paper. Comparing rounds is the chair's job, after the reviews land.
|
|
87
101
|
5. **Synthesize the meta-review yourself** (PC chair) once all land — see output.
|
|
88
102
|
|
|
89
103
|
## Each reviewer returns a review form
|
|
@@ -106,10 +120,19 @@ prose-only read can.
|
|
|
106
120
|
- One-line meta: does this belong at this venue?
|
|
107
121
|
|
|
108
122
|
## The meta-review (PC-chair synthesis) — the actual deliverable
|
|
109
|
-
- **Score table:** each reviewer × each criterion + overall + confidence, at a glance
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
123
|
+
- **Score table:** each reviewer × each criterion + overall + confidence, at a glance, and under it
|
|
124
|
+
the overall score's **min / median / max** across reviewers — never a mean alone, which hides the
|
|
125
|
+
one low review that decides a workshop.
|
|
126
|
+
- **Decision:** for a **workshop**, the decision follows the **MIN**: a workshop PC with three
|
|
127
|
+
reviews and a short discussion does not overrule a reject, so one Reject or Strong Reject sinks the
|
|
128
|
+
paper however confident the others are. For a conference, the rec the PC discussion converges on,
|
|
129
|
+
weighted by confidence, with the min named beside it. Either way, a **calibrated accept probability**
|
|
130
|
+
for this venue and edition.
|
|
131
|
+
- 🔴 **One reviewer is not a panel.** A run with fewer than three reviews and a meta-review — a
|
|
132
|
+
Venue-fit spot-check, a single re-review, a panel whose other seats did not return — is recorded as
|
|
133
|
+
what it is (\`venue-fit\`, \`single review\`), never in the scorecard's \`panel\` row. A single
|
|
134
|
+
review recorded as a panel verdict is how a paper reaches submission on an 88% that three real
|
|
135
|
+
reviewers turned into a reject.
|
|
113
136
|
- **Consensus must-fixes:** issues **≥2 reviewers independently raised** — these are the real ones;
|
|
114
137
|
apply before submitting.
|
|
115
138
|
- **Single-reviewer flags:** noted, triaged (fix if cheap, else defer to camera-ready).
|
|
@@ -215,9 +238,11 @@ reject-risk without rubber-stamping. For the real decision, escalate to the full
|
|
|
215
238
|
## The reproduce loop (why this beats a prose review)
|
|
216
239
|
This is "double-blind review as a real venue does it, WITH reproduction." The artifact-runner reviewer
|
|
217
240
|
is the difference-maker on both runs so far: it doesn't judge the paper's numbers, it re-derives them.
|
|
218
|
-
Run the panel, apply the consensus fixes, then **re-run the panel**
|
|
219
|
-
confirm the fixes landed and nothing regressed
|
|
220
|
-
|
|
241
|
+
Run the panel, apply the consensus fixes, then **re-run the panel** — same lenses, FRESH reviewers,
|
|
242
|
+
told nothing about the previous round — to confirm the fixes landed and nothing regressed; the
|
|
243
|
+
artifact-runner re-executes every harness each round. The chair, not the reviewers, sets the new
|
|
244
|
+
reviews beside the old ones and checks that each earlier must-fix is gone. Track the min / median / max
|
|
245
|
+
progression in the review ledger. Stop when the panel converges to
|
|
221
246
|
accept and the artifact reproduces clean; don't loop past one confirming round.
|
|
222
247
|
|
|
223
248
|
## Provenance (two papers, battle-tested)
|
|
@@ -4,7 +4,7 @@ description: Compile a LaTeX paper (ACM/IEEE/arXiv) to PDF and render its pages
|
|
|
4
4
|
allowed-tools: [Read, Write, Edit, Grep, Glob, Bash, SendUserFile]
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
<!-- vigiles:sha256:
|
|
7
|
+
<!-- vigiles:sha256:5e2ee8850c098375 compiled from skills/render-paper/SKILL.md.spec.ts -->
|
|
8
8
|
|
|
9
9
|
# render-paper — .tex → PDF → readable page PNGs
|
|
10
10
|
|
|
@@ -34,7 +34,7 @@ That list was replaced on 2026-08-03; nothing about the toolchain below changed.
|
|
|
34
34
|
by `kpsewhich` against the files each profile names. The last line it prints is `bin: <dir>` —
|
|
35
35
|
put that directory first on PATH before calling `pdflatex` or `check-render.sh` by hand.
|
|
36
36
|
|
|
37
|
-
🔴 The package list lives in the venue profiles (`
|
|
37
|
+
🔴 The package list lives in the venue profiles (`presets/*.jsonc` in the package, the
|
|
38
38
|
`tex` block; `tex-base.jsonc` for every paper) and nowhere else. A new venue that needs a new
|
|
39
39
|
package gets it there — never in a script, never here. A TeX Live without `libertine` builds an
|
|
40
40
|
acmart paper GREEN in Computer Modern; that is why the files are checked, not the exit code.
|
|
@@ -40,7 +40,7 @@ That list was replaced on 2026-08-03; nothing about the toolchain below changed.
|
|
|
40
40
|
by \`kpsewhich\` against the files each profile names. The last line it prints is \`bin: <dir>\` —
|
|
41
41
|
put that directory first on PATH before calling \`pdflatex\` or \`check-render.sh\` by hand.
|
|
42
42
|
|
|
43
|
-
🔴 The package list lives in the venue profiles (\`
|
|
43
|
+
🔴 The package list lives in the venue profiles (\`presets/*.jsonc\` in the package, the
|
|
44
44
|
\`tex\` block; \`tex-base.jsonc\` for every paper) and nowhere else. A new venue that needs a new
|
|
45
45
|
package gets it there — never in a script, never here. A TeX Live without \`libertine\` builds an
|
|
46
46
|
acmart paper GREEN in Computer Modern; that is why the files are checked, not the exit code.
|
|
@@ -25,75 +25,28 @@ set -uo pipefail
|
|
|
25
25
|
# check — that is, the defect the guard was set up for comes back together with a green report.
|
|
26
26
|
# A broken `import` in JS fails loudly; here we have to fail on our own.
|
|
27
27
|
#
|
|
28
|
-
#
|
|
29
|
-
#
|
|
30
|
-
# The order "the declared package → a sibling inside the package → the consumer's directory" is
|
|
31
|
-
# deliberate: the package must win silently. It only gets loud when there is NOT A SINGLE ONE.
|
|
32
|
-
# 🔴 THE SCRIPT'S OWN DIRECTORY — TAKEN ABSOLUTE AND BEFORE ANY `cd` (12.09.2026, evening).
|
|
33
|
-
# Found by a RED HARNESS, `gates.harness.mjs`, not by proofreading, and it is my own regression from
|
|
34
|
-
# the same day: below, the script does `cd "$DIR"` into the paper directory, and the venues resolve
|
|
35
|
-
# stood AFTER that `cd`. So `git rev-parse --show-toplevel` was already running in the fixture's
|
|
36
|
-
# temporary directory, the root was not found, and the build honestly stopped — on a test that had
|
|
37
|
-
# been passing until then.
|
|
28
|
+
# TWO candidates, in this order: the package by its NAME, from the current directory (a consumer's
|
|
29
|
+
# installed paperlint wins), then the package THIS script ships in. Loud only when neither holds it.
|
|
38
30
|
#
|
|
39
|
-
#
|
|
40
|
-
# the
|
|
41
|
-
# of an old one; still, a test that was green yesterday and is red today is mine to fix.
|
|
42
|
-
#
|
|
43
|
-
# The neighbouring `build.sh` already carries this same lesson in a comment ("The script directory is
|
|
44
|
-
# taken ONCE and ABSOLUTE, before cd") — CI failed on it there on 30.08. A second instance of the same
|
|
45
|
-
# class in a file right next door.
|
|
31
|
+
# 🔴 THE SCRIPT'S OWN DIRECTORY IS TAKEN ABSOLUTE AND BEFORE ANY `cd`: below, the script `cd`s into
|
|
32
|
+
# the paper directory, and a lookup after that would start from the paper, not from here.
|
|
46
33
|
SELF_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
|
47
34
|
|
|
48
35
|
resolve_venues() {
|
|
49
|
-
local
|
|
50
|
-
#
|
|
51
|
-
|
|
52
|
-
# depends neither on the current directory nor on whether the caller sits inside a git tree.
|
|
53
|
-
# ⚠️ THE PARENTHESES ARE MANDATORY, and the harness caught this a minute after I wrote the line
|
|
54
|
-
# without them. In bash `A || B && C` parses as `(A || B) && C`, so on a SUCCESSFUL `git rev-parse`
|
|
55
|
-
# the `pwd` ran as well, and the substitution returned TWO lines — the repository root plus the
|
|
56
|
-
# current directory. By hand from a directory outside git this did not reproduce: there git failed,
|
|
57
|
-
# and only one branch ran.
|
|
58
|
-
# ⚠️ THE LAST RUNG SEARCHES, IT DOES NOT COUNT LEVELS. `cd "$SELF_DIR/../../.."` used to stand here
|
|
59
|
-
# — correct for `.claude/skills/render-paper/` (three levels to the root) and silently wrong after
|
|
60
|
-
# the skill moved into the package, where it lies in `skills/render-paper/` (two): the climb
|
|
61
|
-
# overshot ABOVE the repository, and rung 2 looked for venues in someone else's directory. Climbing
|
|
62
|
-
# up to the directory that holds `.claude` does not depend on the depth.
|
|
63
|
-
local probe="$SELF_DIR" fallback=""
|
|
64
|
-
while [ "$probe" != "/" ]; do
|
|
65
|
-
if [ -d "$probe/.claude" ]; then fallback="$probe"; break; fi
|
|
66
|
-
probe=$(dirname "$probe")
|
|
67
|
-
done
|
|
68
|
-
root="${CLAUDE_PROJECT_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || printf '%s' "$fallback")}"
|
|
69
|
-
|
|
70
|
-
# 1) the package, if it already carries venues/ (after step 5)
|
|
71
|
-
pkg=$(node -e 'try{process.stdout.write(require.resolve("paperlint/venues/paper-guards.tex"))}catch{}' 2>/dev/null || true)
|
|
36
|
+
local pkg own
|
|
37
|
+
# 1) the package by its name. `node -e` resolves from the current directory.
|
|
38
|
+
pkg=$(node -e 'try{process.stdout.write(require.resolve("paperlint/presets/tex/paper-guards.tex"))}catch{}' 2>/dev/null || true)
|
|
72
39
|
if [ -n "$pkg" ] && [ -f "$pkg" ]; then
|
|
73
40
|
dirname "$pkg"
|
|
74
41
|
return 0
|
|
75
42
|
fi
|
|
76
43
|
|
|
77
|
-
# 2)
|
|
78
|
-
#
|
|
79
|
-
#
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
# leaves the logical path)
|
|
84
|
-
# Rung 1 depends on cwd (`node -e` resolves from the current directory), rung 3 depends on the
|
|
85
|
-
# consumer's root having been found at all. This one depends on neither — exactly the anchor whose
|
|
86
|
-
# absence had `gates.harness.mjs` red on 12.09.
|
|
87
|
-
local sibling="$SELF_DIR/../submit-paper/references/venues"
|
|
88
|
-
if [ -f "$sibling/paper-guards.tex" ]; then
|
|
89
|
-
(cd "$sibling" && pwd)
|
|
90
|
-
return 0
|
|
91
|
-
fi
|
|
92
|
-
|
|
93
|
-
# 3) the skill directory in the consumer — for a consumer that mounted the skills differently
|
|
94
|
-
local local_dir="$root/.claude/skills/submit-paper/references/venues"
|
|
95
|
-
if [ -f "$local_dir/paper-guards.tex" ]; then
|
|
96
|
-
printf '%s\n' "$local_dir"
|
|
44
|
+
# 2) the package this script is part of: `skills/render-paper/` → `presets/tex/`. `cd -P` follows
|
|
45
|
+
# the symlinks a consumer's `.claude/skills/render-paper` is made of, so `../..` is the PACKAGE's
|
|
46
|
+
# root, not the consumer's `.claude/`. Depends neither on the cwd nor on a git tree.
|
|
47
|
+
own="$(cd -P "$SELF_DIR" && pwd)/../../presets/tex"
|
|
48
|
+
if [ -f "$own/paper-guards.tex" ]; then
|
|
49
|
+
(cd "$own" && pwd)
|
|
97
50
|
return 0
|
|
98
51
|
fi
|
|
99
52
|
|
|
@@ -107,8 +60,8 @@ if [ "${1:-}" = "--print-venues" ]; then
|
|
|
107
60
|
printf '%s\n' "$VD"
|
|
108
61
|
exit 0
|
|
109
62
|
fi
|
|
110
|
-
echo "✗ paper-guards.tex not found: not under the package name paperlint,
|
|
111
|
-
echo "
|
|
63
|
+
echo "✗ paper-guards.tex not found: not under the package name paperlint (paperlint/presets/tex)," >&2
|
|
64
|
+
echo " not in the package this script ships in (../../presets/tex from it)." >&2
|
|
112
65
|
echo " Building the paper without it is not allowed: \\input{paper-guards} will not fail, it will vanish silently," >&2
|
|
113
66
|
echo " and the PDF will be built WITHOUT the check for dangling \\ref and \\cite." >&2
|
|
114
67
|
exit 2
|
|
@@ -135,7 +88,7 @@ if [ "${NO_COMPILE:-0}" != "1" ] && [ -f "$BASE.tex" ]; then
|
|
|
135
88
|
# Two passes: overfull boxes surface on every pass; a second pass settles refs
|
|
136
89
|
# so Reference/Citation-undefined warnings are accurate.
|
|
137
90
|
# 🔴 TEXINPUTS is mandatory, and that was found by a crash on 26.08. Papers pull in their venue's
|
|
138
|
-
# numbers via `\input{<venue>}`, and the file lies in
|
|
91
|
+
# numbers via `\input{<venue>}`, and the file lies in the package's `presets/tex/`.
|
|
139
92
|
# Without that path the build fails with `File \`agenticdev.tex' not found` — and the `|| true`
|
|
140
93
|
# below swallows it, after which the script reads a log of UNKNOWN origin and reports on it. That
|
|
141
94
|
# is, compiling this paper here silently did not work, and it only became visible once a pass
|
|
@@ -68,34 +68,11 @@ await checkSkill("render-paper");
|
|
|
68
68
|
const run = (args, opts = {}) =>
|
|
69
69
|
spawnSync("bash", [CHECK, ...args], { encoding: "utf8", ...opts });
|
|
70
70
|
|
|
71
|
-
// First half — on
|
|
72
|
-
//
|
|
73
|
-
//
|
|
74
|
-
// 🔴 THERE USED TO BE AN UNCONDITIONAL `assert.equal(status, 0)` HERE, AND THE MOVE BROKE IT —
|
|
75
|
-
// for a real reason, not by accident. It relied on the SURROUNDING tree: while the skill lived
|
|
76
|
-
// at the consumer, the second rung of the ladder won
|
|
77
|
-
// (`.claude/skills/submit-paper/references/venues/`). The package checkout has neither that nor
|
|
78
|
-
// the first rung — `venues/` arrives together with `submit-paper`, which hasn't moved yet. So
|
|
79
|
-
// the assertion wasn't checking resolution, it was checking for the presence of an unrelated
|
|
80
|
-
// directory nearby.
|
|
81
|
-
//
|
|
82
|
-
// The form now is: resolution must succeed IF AND ONLY IF at least one candidate exists on
|
|
83
|
-
// disk. This is still a real assertion — it fails if a candidate exists and the script didn't
|
|
84
|
-
// find it — but it stops requiring the existence of something this repository doesn't have yet.
|
|
85
|
-
// The absence of both candidates gets PRINTED, not swallowed: "the check found nothing to
|
|
86
|
-
// check" and "the check passed" have to look different.
|
|
71
|
+
// First half — on this tree, resolution must succeed IF AND ONLY IF a candidate exists on disk:
|
|
72
|
+
// the package's own `presets/tex/`. The absence of it is PRINTED, not swallowed: "the check found
|
|
73
|
+
// nothing to check" and "the check passed" have to look different.
|
|
87
74
|
const candidates = [
|
|
88
|
-
|
|
89
|
-
join(HERE, "..", "..", "venues", "paper-guards.tex"),
|
|
90
|
-
// rung 2 — the skill directory at the consumer
|
|
91
|
-
join(
|
|
92
|
-
HERE,
|
|
93
|
-
"..",
|
|
94
|
-
"submit-paper",
|
|
95
|
-
"references",
|
|
96
|
-
"venues",
|
|
97
|
-
"paper-guards.tex",
|
|
98
|
-
),
|
|
75
|
+
join(HERE, "..", "..", "presets", "tex", "paper-guards.tex"),
|
|
99
76
|
].filter((c) => existsSync(c));
|
|
100
77
|
|
|
101
78
|
const ok = run(["--print-venues"]);
|
|
@@ -108,9 +85,8 @@ await checkSkill("render-paper");
|
|
|
108
85
|
`silent success this whole block was written to catch.`,
|
|
109
86
|
);
|
|
110
87
|
console.log(
|
|
111
|
-
` --print-venues: NOT VERIFIED on the live tree — paper-guards.tex is absent from
|
|
112
|
-
`
|
|
113
|
-
`\`submit-paper\`; until then only the fixtures below hold this half.`,
|
|
88
|
+
` --print-venues: NOT VERIFIED on the live tree — paper-guards.tex is absent from the ` +
|
|
89
|
+
`package's presets/tex/; only the fixtures below hold this half.`,
|
|
114
90
|
);
|
|
115
91
|
} else {
|
|
116
92
|
assert.equal(
|
|
@@ -159,18 +135,9 @@ await checkSkill("render-paper");
|
|
|
159
135
|
// When the file is NOWHERE, the script must exit with code 2 and say why. A silent success here
|
|
160
136
|
// is exactly the defect the whole ladder was written for.
|
|
161
137
|
//
|
|
162
|
-
// 🔴 RUN AGAINST A COPY OF THE SCRIPT
|
|
163
|
-
//
|
|
164
|
-
//
|
|
165
|
-
// the root), and an empty directory found nothing at either. Now the script has a rung anchored
|
|
166
|
-
// to ITS OWN directory (`$SELF_DIR/../submit-paper/references/venues`) — added for
|
|
167
|
-
// cwd-independence — so as long as the script sits inside the package, venues next to it exist
|
|
168
|
-
// ALWAYS, and "nowhere" can no longer be reached through the environment. The only honest way to
|
|
169
|
-
// demonstrate that state is to move the script itself out of the package. The property being
|
|
170
|
-
// checked is otherwise identical, word for word: nothing resolved ⇒ exit 2 + the name of the
|
|
171
|
-
// missing file. ⚠️ What this form no longer checks: that an empty consumer root won't make the
|
|
172
|
-
// script lie — and it shouldn't, because such a root is now legitimately shadowed by the copy in
|
|
173
|
-
// the package.
|
|
138
|
+
// 🔴 RUN AGAINST A COPY OF THE SCRIPT. Inside the package its second rung (the package it ships
|
|
139
|
+
// in) always holds the file, so "nowhere" is reachable only by moving the script out of the
|
|
140
|
+
// package: nothing resolved ⇒ exit 2 + the name of the missing file.
|
|
174
141
|
const empty = realpathSync(mkdtempSync(join(tmpdir(), "venues-none-")));
|
|
175
142
|
const lonely = join(empty, "check-render.sh");
|
|
176
143
|
copyFileSync(CHECK, lonely);
|
|
@@ -190,30 +157,21 @@ await checkSkill("render-paper");
|
|
|
190
157
|
"the failure message must name the missing file",
|
|
191
158
|
);
|
|
192
159
|
|
|
193
|
-
// Third half — the ORDER of the rungs.
|
|
194
|
-
//
|
|
195
|
-
//
|
|
160
|
+
// Third half — the ORDER of the rungs. The package the consumer installed, found by its name,
|
|
161
|
+
// must win over the copy this script ships in; otherwise a consumer silently builds with a stale
|
|
162
|
+
// copy. Plant a package by name beside the real script and see which one is chosen.
|
|
196
163
|
const both = realpathSync(mkdtempSync(join(tmpdir(), "venues-both-")));
|
|
197
|
-
const pkgVenues = join(both, "node_modules", "paperlint", "
|
|
198
|
-
|
|
199
|
-
both,
|
|
200
|
-
".claude",
|
|
201
|
-
"skills",
|
|
202
|
-
"submit-paper",
|
|
203
|
-
"references",
|
|
204
|
-
"venues",
|
|
205
|
-
);
|
|
206
|
-
for (const d of [pkgVenues, skillVenues]) mkdirSync(d, { recursive: true });
|
|
164
|
+
const pkgVenues = join(both, "node_modules", "paperlint", "presets", "tex");
|
|
165
|
+
mkdirSync(pkgVenues, { recursive: true });
|
|
207
166
|
writeFileSync(
|
|
208
167
|
join(both, "node_modules", "paperlint", "package.json"),
|
|
209
168
|
JSON.stringify({
|
|
210
169
|
name: "paperlint",
|
|
211
170
|
version: "0.0.0",
|
|
212
|
-
exports: { "
|
|
171
|
+
exports: { "./*": "./*" },
|
|
213
172
|
}),
|
|
214
173
|
);
|
|
215
174
|
writeFileSync(join(pkgVenues, "paper-guards.tex"), "% from package\n");
|
|
216
|
-
writeFileSync(join(skillVenues, "paper-guards.tex"), "% from skill dir\n");
|
|
217
175
|
const race = run(["--print-venues"], {
|
|
218
176
|
cwd: both,
|
|
219
177
|
env: { ...process.env, CLAUDE_PROJECT_DIR: both },
|
|
@@ -226,7 +184,7 @@ await checkSkill("render-paper");
|
|
|
226
184
|
assert.equal(
|
|
227
185
|
race.stdout.trim(),
|
|
228
186
|
pkgVenues,
|
|
229
|
-
"with both candidates present, the
|
|
187
|
+
"with both candidates present, the INSTALLED package wins, not the copy the script ships in",
|
|
230
188
|
);
|
|
231
189
|
}
|
|
232
190
|
|
|
@@ -276,7 +234,7 @@ await checkSkill("render-paper");
|
|
|
276
234
|
);
|
|
277
235
|
assert.match(
|
|
278
236
|
build,
|
|
279
|
-
/require\.resolve\("paperlint\/
|
|
237
|
+
/require\.resolve\("paperlint\/presets\/tex\/paper-guards\.tex"\)/,
|
|
280
238
|
`${where}: the ladder's first rung (the package) must remain`,
|
|
281
239
|
);
|
|
282
240
|
assert.match(
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* `adapters/banal/index.ts` — banal as the two ports the app sees. What `run.test.ts` checks in
|
|
3
3
|
* banal's own terms is checked here as the domain receives it: a `Geometry` whose provenance names
|
|
4
4
|
* banal and the rule that found it, a reason that is one line of text, a `Ready` that says what was
|
|
5
|
-
* verified. In-memory ports throughout; the real banal is `test/e2e/banal.ts`.
|
|
5
|
+
* verified. In-memory ports throughout; the real banal is `test/e2e/tex/banal.e2e.ts`.
|
|
6
6
|
*/
|
|
7
7
|
import assert from "node:assert/strict";
|
|
8
8
|
import { test } from "vitest";
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* (`Error: Failed to run pdftohtml`, measured); told a version below 0.85 it applies a larger
|
|
8
8
|
* correction and every font size moves. So `$PDFTOHTML` (banal's own override, line 166) points at a
|
|
9
9
|
* stub that answers `-v` with `XML_DIALECT.version` — the pdftohtml whose XML `xml.ts` writes — and
|
|
10
|
-
* refuses anything else. `test/e2e/banal.ts` shows both failures with the real banal.
|
|
10
|
+
* refuses anything else. `test/e2e/tex/banal.e2e.ts` shows both failures with the real banal.
|
|
11
11
|
*/
|
|
12
12
|
import type { Opaque } from "ts-essentials";
|
|
13
13
|
import type { AbsolutePath } from "../../domain/paths.ts";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `output.ts` — every way a banal run can end, as a table of `ProcessExit` → `Result`, and the
|
|
3
|
-
* measurement → geometry projection. Pure: no perl, no disk. The real banal is `test/e2e/banal.ts`.
|
|
3
|
+
* measurement → geometry projection. Pure: no perl, no disk. The real banal is `test/e2e/tex/banal.e2e.ts`.
|
|
4
4
|
*/
|
|
5
5
|
import assert from "node:assert/strict";
|
|
6
6
|
import { test } from "vitest";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `adapters/banal/run.ts` — running and installing banal, on in-memory ports: which `Command` it builds, what it stages,
|
|
3
3
|
* what it downloads and writes, and what it concludes. No perl, no disk, no network: the adapters
|
|
4
|
-
* record, and each assertion reads the record. Real perl and the real banal are `test/e2e/banal.ts`;
|
|
4
|
+
* record, and each assertion reads the record. Real perl and the real banal are `test/e2e/tex/banal.e2e.ts`;
|
|
5
5
|
* the adapters' own behaviour is `src/adapters/node/*.test.ts`.
|
|
6
6
|
*/
|
|
7
7
|
import assert from "node:assert/strict";
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Every page here is written by hand. The real-PDF half — pdf.js boxes of a committed fixture,
|
|
6
6
|
* written as XML, measured by the real banal and compared with banal on real pdftohtml — is
|
|
7
|
-
* `test/e2e/banal.ts`, which runs where `paperlint toolchain` has installed banal.
|
|
7
|
+
* `test/e2e/tex/banal.e2e.ts`, which runs where `paperlint toolchain` has installed banal.
|
|
8
8
|
*/
|
|
9
9
|
import assert from "node:assert/strict";
|
|
10
10
|
import { test } from "vitest";
|