paperlint 13.1.0 → 13.3.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 +10 -0
- package/CLAUDE.md +9 -1
- package/dist/adapters/git/index.d.ts.map +1 -1
- package/dist/adapters/git/index.js +13 -0
- package/dist/adapters/git/index.js.map +1 -1
- package/dist/adapters/study-registry/index.d.ts +142 -1
- package/dist/adapters/study-registry/index.d.ts.map +1 -1
- package/dist/adapters/study-registry/index.js +160 -1
- package/dist/adapters/study-registry/index.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +3 -0
- package/dist/cli.js.map +1 -1
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +2 -2
- package/dist/doctor.js.map +1 -1
- package/dist/domain/decide-first.d.ts +43 -0
- package/dist/domain/decide-first.d.ts.map +1 -1
- package/dist/domain/decide-first.js +45 -2
- package/dist/domain/decide-first.js.map +1 -1
- package/dist/domain/study-gates.d.ts +96 -0
- package/dist/domain/study-gates.d.ts.map +1 -0
- package/dist/domain/study-gates.js +56 -0
- package/dist/domain/study-gates.js.map +1 -0
- package/dist/domain/study-mode.d.ts +6 -0
- package/dist/domain/study-mode.d.ts.map +1 -1
- package/dist/domain/study-mode.js.map +1 -1
- package/dist/domain/study-registry.d.ts +24 -4
- package/dist/domain/study-registry.d.ts.map +1 -1
- package/dist/domain/study-registry.js +39 -2
- package/dist/domain/study-registry.js.map +1 -1
- package/dist/domain/study-result.d.ts +151 -0
- package/dist/domain/study-result.d.ts.map +1 -0
- package/dist/domain/study-result.js +175 -0
- package/dist/domain/study-result.js.map +1 -0
- package/dist/outputs-before-decision-rule.d.ts.map +1 -1
- package/dist/outputs-before-decision-rule.js +37 -3
- package/dist/outputs-before-decision-rule.js.map +1 -1
- package/dist/ports/git-history.d.ts +12 -0
- package/dist/ports/git-history.d.ts.map +1 -1
- package/dist/ports/study-registry-codec.d.ts +3 -0
- package/dist/ports/study-registry-codec.d.ts.map +1 -1
- package/dist/skills/assess-novelty/scripts/candidate_page.d.ts +1 -0
- package/dist/skills/assess-novelty/scripts/novelty_reader_brief.d.ts +25 -0
- package/dist/skills/build-label-page/scripts/label-page-cli.d.ts +6 -0
- package/dist/skills/build-label-page/scripts/label-page-commands.d.ts +14 -0
- package/dist/skills/build-label-page/scripts/label-page-core.d.ts +149 -0
- package/dist/skills/build-label-page/scripts/label-page-html.d.ts +5 -0
- package/dist/skills/build-label-page/scripts/label-page.d.ts +2 -0
- package/dist/study-modes.d.ts +3 -0
- package/dist/study-modes.d.ts.map +1 -1
- package/dist/study-modes.js +8 -1
- package/dist/study-modes.js.map +1 -1
- package/dist/study-registry-rule.d.ts.map +1 -1
- package/dist/study-registry-rule.js +1 -0
- package/dist/study-registry-rule.js.map +1 -1
- package/dist/study-result-rule.d.ts +12 -0
- package/dist/study-result-rule.d.ts.map +1 -0
- package/dist/study-result-rule.js +87 -0
- package/dist/study-result-rule.js.map +1 -0
- package/docs/design/study-gates.md +208 -0
- package/docs/rules/repro/outputs-before-decision.md +8 -0
- package/docs/rules/repro/study-registered.md +38 -15
- package/docs/rules/repro/study-result.md +100 -0
- package/docs/rules.md +1 -0
- package/docs/toolchain.md +1 -1
- package/eslint.config.mjs +52 -0
- package/package.json +3 -1
- package/presets/agentverify.md +15 -4
- package/schemas/plan.v2.schema.json +341 -0
- package/skills/assess-novelty/scripts/candidate_page.css +31 -0
- package/skills/assess-novelty/scripts/candidate_page.html +934 -0
- package/skills/assess-novelty/scripts/candidate_page.js +165 -0
- package/skills/assess-novelty/scripts/candidate_page.test.ts +401 -0
- package/skills/assess-novelty/scripts/candidate_page.ts +194 -0
- package/skills/assess-novelty/scripts/check_novelty.py +230 -0
- package/skills/assess-novelty/scripts/check_novelty.test.ts +490 -0
- package/skills/assess-novelty/scripts/check_novelty_coverage.test.ts +176 -0
- package/skills/assess-novelty/scripts/crop_quote.py +104 -0
- package/skills/assess-novelty/scripts/crop_quote.test.ts +130 -0
- package/skills/assess-novelty/scripts/fixtures/crop-quote/make_sample.py +42 -0
- package/skills/assess-novelty/scripts/fixtures/crop-quote/sample.pdf +106 -0
- package/skills/assess-novelty/scripts/fixtures/novelty/CLAIMS.md +11 -0
- package/skills/assess-novelty/scripts/fixtures/novelty/paper.tex +10 -0
- package/skills/assess-novelty/scripts/fixtures/novelty/siblings/2026-10-27-novelty-refutation.md +8 -0
- package/skills/assess-novelty/scripts/fixtures/novelty/siblings/data/doe-preprint.txt +63 -0
- package/skills/assess-novelty/scripts/fixtures/novelty/siblings/novelty.json +54 -0
- package/skills/assess-novelty/scripts/novelty_candidates.py +136 -0
- package/skills/assess-novelty/scripts/novelty_candidates.test.ts +222 -0
- package/skills/assess-novelty/scripts/novelty_cells.py +88 -0
- package/skills/assess-novelty/scripts/novelty_cells.test.ts +159 -0
- package/skills/assess-novelty/scripts/novelty_coverage.py +55 -0
- package/skills/assess-novelty/scripts/novelty_reader_brief.js +165 -0
- package/skills/assess-novelty/scripts/novelty_reader_brief.test.ts +251 -0
- package/skills/assess-novelty/scripts/novelty_reader_brief.ts +215 -0
- package/skills/assess-novelty/scripts/quote_match.py +34 -0
- package/skills/assess-novelty/scripts/script_edges.test.ts +174 -0
- package/skills/build-label-page/SKILL.md +85 -54
- package/skills/build-label-page/SKILL.md.spec.ts +85 -53
- package/skills/build-label-page/build-label-page.test.ts +10 -941
- package/skills/build-label-page/references/checklist.md +45 -3
- package/skills/build-label-page/references/closed-choice-generator.md +88 -0
- package/skills/build-label-page/scripts/label-page-cli.js +72 -0
- package/skills/build-label-page/scripts/label-page-cli.ts +85 -0
- package/skills/build-label-page/scripts/label-page-commands.js +14 -0
- package/skills/build-label-page/scripts/label-page-commands.ts +14 -0
- package/skills/build-label-page/scripts/label-page-core.js +850 -0
- package/skills/build-label-page/scripts/label-page-core.test.ts +1164 -0
- package/skills/build-label-page/scripts/label-page-core.ts +1210 -0
- package/skills/build-label-page/scripts/label-page-html.js +33 -0
- package/skills/build-label-page/scripts/label-page-html.test.ts +413 -0
- package/skills/build-label-page/scripts/label-page-html.ts +43 -0
- package/skills/build-label-page/scripts/label-page.js +70 -0
- package/skills/build-label-page/scripts/label-page.test.ts +71 -0
- package/skills/build-label-page/scripts/label-page.ts +71 -0
- package/skills/build-label-page/scripts/page-template.html +513 -0
- package/src/adapters/git/index.test.ts +33 -0
- package/src/adapters/git/index.ts +19 -0
- package/src/adapters/study-registry/gates.test.ts +181 -0
- package/src/adapters/study-registry/index.ts +219 -1
- package/src/adapters/study-registry/mode.test.ts +6 -0
- package/src/cli.ts +3 -0
- package/src/doctor.ts +4 -2
- package/src/domain/decide-first.test.ts +131 -0
- package/src/domain/decide-first.ts +92 -2
- package/src/domain/study-gates.ts +125 -0
- package/src/domain/study-measurements.test.ts +71 -0
- package/src/domain/study-mode.ts +6 -0
- package/src/domain/study-registry.ts +64 -2
- package/src/domain/study-result.test.ts +300 -0
- package/src/domain/study-result.ts +358 -0
- package/src/outputs-before-decision-rule.test.ts +115 -2
- package/src/outputs-before-decision-rule.ts +50 -2
- package/src/ports/git-history.ts +12 -0
- package/src/ports/study-registry-codec.ts +3 -0
- package/src/rule-cases.test.ts +74 -0
- package/src/studies.test.ts +3 -0
- package/src/study-modes.ts +10 -1
- package/src/study-registry-rule.ts +1 -0
- package/src/study-result-rule.test.ts +281 -0
- package/src/study-result-rule.ts +123 -0
- package/skills/build-label-page/references/example-generator.py +0 -803
|
@@ -132,6 +132,7 @@ author's check of the drawn units. `paperlint studies new` writes the template b
|
|
|
132
132
|
|
|
133
133
|
```json
|
|
134
134
|
{
|
|
135
|
+
"$schema": "https://unpkg.com/paperlint/schemas/plan.v2.schema.json",
|
|
135
136
|
"question": "",
|
|
136
137
|
"population": {
|
|
137
138
|
"source": "",
|
|
@@ -143,23 +144,36 @@ author's check of the drawn units. `paperlint studies new` writes the template b
|
|
|
143
144
|
"mode": {
|
|
144
145
|
"kind": "decide_before_run",
|
|
145
146
|
"outputs": [],
|
|
146
|
-
"decision": { "file": "repro/P1-S02-census/decision.md", "note": "" }
|
|
147
|
-
|
|
147
|
+
"decision": { "file": "repro/P1-S02-census/decision.md", "note": "" },
|
|
148
|
+
"we_lose_if": null
|
|
149
|
+
},
|
|
150
|
+
"second_check": null,
|
|
151
|
+
"self_test": null,
|
|
152
|
+
"funnel": null,
|
|
153
|
+
"recall_audit": null
|
|
148
154
|
}
|
|
149
155
|
```
|
|
150
156
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
|
154
|
-
|
|
|
155
|
-
| `
|
|
156
|
-
| `population.
|
|
157
|
-
| `population.draw.
|
|
158
|
-
| `
|
|
159
|
-
| `
|
|
160
|
-
| `
|
|
161
|
-
| `
|
|
162
|
-
| `
|
|
157
|
+
That is a measurement's template, a plan v2. Another kind's has no `$schema`, `mode` or gates.
|
|
158
|
+
|
|
159
|
+
| field | what it holds |
|
|
160
|
+
| ------------------------ | ------------------------------------------------------------------------------------ |
|
|
161
|
+
| `question` | what the study measures, one sentence |
|
|
162
|
+
| `population.source` | where the units come from: the census, crawl or registry, with its date |
|
|
163
|
+
| `population.draw.kind` | `all` (the whole population, a census: no seed) or `seeded` (a sample) |
|
|
164
|
+
| `population.draw.method` | how the sample is drawn: `census`, `random`, `stratified` … |
|
|
165
|
+
| `population.draw.seed` | `seeded` only, and required there: the draw's seed, a string or a number |
|
|
166
|
+
| `arms` | the conditions compared, each `{ "name": … }`, each name once; `[]` for a census |
|
|
167
|
+
| `primary_outcome` | the one number the study reports first |
|
|
168
|
+
| `author_check` | `null` until the author has seen the drawn units; then `by`, `date`, `quote` |
|
|
169
|
+
| `extra` | optional: the paper's own keys (hypotheses, models, budget), kept unread |
|
|
170
|
+
| `mode` | a measurement's: exactly one of `decide_before_run` or `exploratory` |
|
|
171
|
+
| `$schema` | a plan v2 says so here; without it the plan is v1 |
|
|
172
|
+
| `mode.we_lose_if` | v2, decide-first only: the number its claim loses by, `below` or `above` a threshold |
|
|
173
|
+
| `second_check` | v2: per labelling step, the least kappa between two raters, or `"none"` |
|
|
174
|
+
| `self_test` | v2: how the study's check is run on known answers first, or `"none"` |
|
|
175
|
+
| `funnel` | v2: the reasons a drawn unit may be dropped, or `"none"` |
|
|
176
|
+
| `recall_audit` | v2: files a person reads in full, and the least recall of the extractor, or `"none"` |
|
|
163
177
|
|
|
164
178
|
`mode` is required of a `measurement` (other kinds may omit it): how its outcomes are kept from the
|
|
165
179
|
decisions on its inputs — decided before the run (the default the template writes; its `outputs`,
|
|
@@ -168,6 +182,12 @@ and its `decision` file relative to the paper, committed before the run) or `exp
|
|
|
168
182
|
rule that holds the order in git, [`repro/outputs-before-decision`](outputs-before-decision.md), are
|
|
169
183
|
in [`docs/design/study-modes.md`](../../design/study-modes.md).
|
|
170
184
|
|
|
185
|
+
The four gates of a plan v2 — what each is for, what the machine checks and what it cannot — are in
|
|
186
|
+
[`docs/design/study-gates.md`](../../design/study-gates.md). Each is `null` until decided (the plan is
|
|
187
|
+
a draft), `"none"` when the study has none of it, or its value; a plan v2 that leaves one out is not
|
|
188
|
+
a plan. A plan without `$schema` is v1 and is judged as before, and may carry none of the gates. The
|
|
189
|
+
result a done study's plan v2 asks for is judged by [`repro/study-result`](study-result.md).
|
|
190
|
+
|
|
171
191
|
The template's draw is of all the population; a sampled study changes it to
|
|
172
192
|
`{ "kind": "seeded", "method": "random", "seed": 7 }`. The population's size is not stored: it is
|
|
173
193
|
counted from the source, and a stored copy could only contradict it.
|
|
@@ -212,7 +232,10 @@ The rule reports:
|
|
|
212
232
|
- a row's `plan` that is outside its folder, not a file, reached through a symbolic link, or not of the plan's shape — and, once the
|
|
213
233
|
study has run (`running`, `done`, `stopped`, `superseded`), a plan that leaves `question`,
|
|
214
234
|
`population.source`, `population.draw.method` or `primary_outcome` empty, or — for a measurement —
|
|
215
|
-
declares no `mode` or leaves one of its texts empty
|
|
235
|
+
declares no `mode` or leaves one of its texts empty, or — for a plan v2 — leaves a gate `null`
|
|
236
|
+
(`bad-plan`);
|
|
237
|
+
- a measurement registered on or after 2026-10-31 whose plan is v1, without `$schema`
|
|
238
|
+
(`plan-version`): its gates are not declared. A measurement registered earlier keeps its plan v1;
|
|
216
239
|
- a study of a `headline` measurement that has run with no `author_check` in its plan — or no plan —
|
|
217
240
|
or, when the registry names its `author`, a check by anyone else (`author-check`).
|
|
218
241
|
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# repro/study-result
|
|
2
|
+
|
|
3
|
+
**Level:** error · **Reads:** `repro/studies.json`, each `done` study's `plan.json` (v2) and
|
|
4
|
+
`result.json` · **Reported on:** `PIPELINE-STATUS.md`, line 1
|
|
5
|
+
|
|
6
|
+
A study whose plan is v2 fixed, before its run, what makes its number believable: when its claim
|
|
7
|
+
loses, how well two raters must agree, that its checker is tried on known answers, and why a unit may
|
|
8
|
+
be dropped ([the gates](../../design/study-gates.md)). Once the study is `done`, its `result.json`
|
|
9
|
+
must show each of them.
|
|
10
|
+
|
|
11
|
+
## What it catches
|
|
12
|
+
|
|
13
|
+
For each study that is `done`, whose plan is ready and v2:
|
|
14
|
+
|
|
15
|
+
| problem | when |
|
|
16
|
+
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
17
|
+
| `no-result-file` | the study's folder has no `result.json` |
|
|
18
|
+
| `result-linked` | `result.json` is reached through a symbolic link |
|
|
19
|
+
| `result-unreadable` | `result.json` is not JSON, or `kappa`, `self_test`, `funnel`, `recall_audit` or `claim` is not of its shape (a kappa outside -1..1, such as a percentage written as `75`, is not one; an audit counting more units extracted than the person found, or no unit found, is not one) |
|
|
20
|
+
| `no-number` | the number `mode.we_lose_if.result` names is not a number in `result.json` |
|
|
21
|
+
| `claim-lost` | that number crosses the threshold, and `result.json` does not say `"claim": "lost"` |
|
|
22
|
+
| `claim-holds` | `result.json` says `"claim": "lost"`, and the number does not cross the threshold |
|
|
23
|
+
| `kappa` | a step of `second_check` has no kappa in `result.json`'s `kappa`, or one below its `min_kappa` |
|
|
24
|
+
| `self-test` | `self_test` is declared, and `result.json`'s `self_test` is missing or `failed` is not 0 |
|
|
25
|
+
| `self-test-empty` | `self_test` is declared, and `result.json`'s `self_test` ran no case: `"passed": 0, "failed": 0` |
|
|
26
|
+
| `funnel` | a reason of `funnel` has no count in `result.json`'s `funnel` |
|
|
27
|
+
| `no-recall-audit` | `recall_audit` is declared, and `result.json` has no `recall_audit` counts |
|
|
28
|
+
| `recall-sample` | the audit read fewer `files` than the plan's `n_files` |
|
|
29
|
+
| `recall` | `extracted / units_in_files` is below the plan's `min_recall`: the extractor misses too much |
|
|
30
|
+
|
|
31
|
+
A gate that is `"none"` asks nothing; an exploratory study has no `we_lose_if`.
|
|
32
|
+
|
|
33
|
+
## Why
|
|
34
|
+
|
|
35
|
+
A threshold fixed before the run and checked by hand after it can be moved, forgotten or quietly
|
|
36
|
+
reinterpreted. Here the plan holds the threshold and the result holds the number, and the engine
|
|
37
|
+
compares them on every lint. A claim that lost stays red until the result says so in so many words —
|
|
38
|
+
`"claim": "lost"` — where the paper reads its numbers from, so the loss cannot sit unnoticed in a
|
|
39
|
+
table. The same holds for a kappa below the bar set before labelling, a checker that missed a known
|
|
40
|
+
answer, and a dropped unit nobody counted.
|
|
41
|
+
|
|
42
|
+
## Examples
|
|
43
|
+
|
|
44
|
+
Failing — the plan declares the funnel reason `timed out`, the result counts none:
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"pass_rate": 0.7,
|
|
49
|
+
"kappa": { "pass": 0.71 },
|
|
50
|
+
"self_test": { "passed": 4, "failed": 0 },
|
|
51
|
+
"funnel": {}
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
```text
|
|
56
|
+
PIPELINE-STATUS.md
|
|
57
|
+
1:1 error The `result.json` of `P1-S01` counts no drop for `timed out`, declared in its plan's
|
|
58
|
+
`funnel`. What to do: write each in `funnel`, 0 when none was dropped for it.
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Failing — `we_lose_if` is `{ "result": "pass_rate", "below": 0.5 }` and the rate is 0.4:
|
|
62
|
+
|
|
63
|
+
```text
|
|
64
|
+
1:1 error `P1-S01`'s claim LOST: its `pass_rate` is 0.4, below 0.5, the threshold its plan fixed
|
|
65
|
+
before the run. What to do: report the loss in the paper, and say so in `result.json`
|
|
66
|
+
with `"claim": "lost"`; the threshold is not moved after the run.
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Passing — every gate shown:
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"pass_rate": 0.7,
|
|
74
|
+
"kappa": { "pass": 0.71 },
|
|
75
|
+
"self_test": { "passed": 4, "failed": 0 },
|
|
76
|
+
"funnel": { "timed out": 2 }
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Options / preset fields
|
|
81
|
+
|
|
82
|
+
None. The rule is on at `error` in paperlint's config; a paper turns it off in its `paperlint.json`.
|
|
83
|
+
|
|
84
|
+
## What it does not check
|
|
85
|
+
|
|
86
|
+
- A study that is not `done`, a plan v1, a draft or a plan that does not parse
|
|
87
|
+
([`repro/study-registered`](study-registered.md) reports those).
|
|
88
|
+
- Whether a gate's `"none"` is true, whether the threshold is a sensible one, or whether the number
|
|
89
|
+
is computed right: the author's check of the plan, and the study's own artifact.
|
|
90
|
+
- Whether the gates were fixed before the outputs: [`repro/outputs-before-decision`](outputs-before-decision.md)
|
|
91
|
+
holds them to the plan as it stood at the first output.
|
|
92
|
+
- Whether the person of the recall audit read the files in full, or counted right: the audit's own
|
|
93
|
+
labels, exported and committed like any other.
|
|
94
|
+
|
|
95
|
+
## How to fix
|
|
96
|
+
|
|
97
|
+
Have the study's script write `result.json` beside its plan, with the number `we_lose_if` names at
|
|
98
|
+
the top, and `kappa`, `self_test`, `funnel` and `recall_audit` as the plan declares them
|
|
99
|
+
([the shape](../../design/study-gates.md#resultjson)). A lost claim is reported, not hidden: add
|
|
100
|
+
`"claim": "lost"` and say so in the paper. Never edit the plan's thresholds after the run.
|
package/docs/rules.md
CHANGED
|
@@ -21,6 +21,7 @@ reads and when it fails. Errors fail `paperlint lint`; warnings print and do not
|
|
|
21
21
|
| [`repro/study-registered`](rules/repro/study-registered.md) | error | the listing of the paper's `repro/`, `repro/studies.json`, `repro/README.md`, each study's `plan.json` | a study folder with no row in `repro/studies.json`, a row whose folder is missing or not `<id>-<slug>`, a bad or repeated id, a title over 8 words, `done` without a result and an existing result file, `superseded` without an existing successor, a row naming a measurement the registry does not declare, a measurement with no study or an unknown requirement, a headline measurement not approved by the author, a plan that is missing, malformed or — once the study runs — unfilled, a headline study that has run without the author's check in its plan, or the index in `repro/README.md` out of sync with the registry; `paperlint studies new` and `paperlint studies index` write both — [page](rules/repro/study-registered.md) |
|
|
22
22
|
| [`repro/study-plan-name`](rules/repro/study-plan-name.md) | warn | `repro/studies.json` | a study's plan still named `prereg.json`, its old name: read as the plan, and to be renamed `plan.json` — [page](rules/repro/study-plan-name.md) |
|
|
23
23
|
| [`repro/outputs-before-decision`](rules/repro/outputs-before-decision.md) | error | `repro/studies.json`, each decide-first study's `plan.json` and folder, git's history | an output of a study decided before its run whose first commit does not descend from its decision's first commit, an output while the decision is uncommitted, a decision its outputs match, a shallow or unreadable history; `paperlint studies gate` opens the run only once the decision is committed — [page](rules/repro/outputs-before-decision.md) |
|
|
24
|
+
| [`repro/study-result`](rules/repro/study-result.md) | error | `repro/studies.json`, each done study's `plan.json` (v2) and `result.json` | a done study whose plan is v2 and whose `result.json` is missing, lacks the number its claim is judged by, crosses that threshold without saying `"claim": "lost"`, lacks a labelling step's kappa or has one below the plan's bar, shows a failed self-test, counts no drop for a declared funnel reason, or audits its extractor on too few files or finds its recall below the plan's bar — [page](rules/repro/study-result.md) |
|
|
24
25
|
| [`paper/sources-fresh`](rules/paper/sources-fresh.md) | warn | `paper.tex` → `_build/sources.json` | the paper has not been built (no record of the files TeX read), or a file changed since the last build (its SHA-256 differs) — run `npx paperlint build` |
|
|
25
26
|
| `paper/author-list` | error | `paper.tex` → `_build/references.json`, `_build/sources.json` | an entry's authors are not those of the version it cites — typically the arXiv preprint's list under a published venue. Checked online by `paperlint build` (DBLP), reported on the entry's own line (or at the top of `paper.tex`, naming the entry's file); silent without a current build record |
|
|
26
27
|
| `paper/section-word` | warn | `paper.tex` and its body files | `§` or `\S\ref` instead of the word Section. **Fixable:** `--fix` writes `Section~\ref{…}` / `Section 5` |
|
package/docs/toolchain.md
CHANGED
|
@@ -16,7 +16,7 @@ after deciding to use the tool, not before.
|
|
|
16
16
|
| `texcount` | TeX Live (`paperlint toolchain`) | render-paper, grade-paper-writing | the length checks cannot run |
|
|
17
17
|
| `checkcites` | TeX Live (`paperlint toolchain`) | render-paper | nothing asks whether a bibliography entry is uncited |
|
|
18
18
|
| `java` | any JRE (21 works) | render-paper | TeXtidote does not run, and **nothing else spell-checks the text** |
|
|
19
|
-
| `python3` | your system | the analysis
|
|
19
|
+
| `python3` | your system | assess-novelty, the analysis scripts | those scripts do not start (`crop_quote.py` also needs `pymupdf`) |
|
|
20
20
|
| `tlmgr` | TeX Live | the TeX installer itself | you cannot add a TeX package |
|
|
21
21
|
| `banal` | HotCRP (`paperlint toolchain`) | `paperlint build`, extract-pdf-facts | page size, columns and font sizes are `null` in the facts file |
|
|
22
22
|
| `perl` | your system (macOS has it) | banal | banal cannot run — the same `null`, and `paperlint toolchain` refuses |
|
package/eslint.config.mjs
CHANGED
|
@@ -135,6 +135,36 @@ const RATCHET = {
|
|
|
135
135
|
"skills/plan-paper-timeline/fixtures/fake-google-calendar.ts": {
|
|
136
136
|
"max-lines-per-function": 31,
|
|
137
137
|
},
|
|
138
|
+
"skills/assess-novelty/scripts/candidate_page.test.ts": {
|
|
139
|
+
"max-lines-per-function": 343,
|
|
140
|
+
"max-nested-callbacks": 4,
|
|
141
|
+
},
|
|
142
|
+
"skills/assess-novelty/scripts/check_novelty.test.ts": {
|
|
143
|
+
"max-lines-per-function": 419,
|
|
144
|
+
},
|
|
145
|
+
"skills/assess-novelty/scripts/check_novelty_coverage.test.ts": {
|
|
146
|
+
"max-lines-per-function": 131,
|
|
147
|
+
},
|
|
148
|
+
"skills/assess-novelty/scripts/crop_quote.test.ts": {
|
|
149
|
+
"max-lines-per-function": 96,
|
|
150
|
+
},
|
|
151
|
+
"skills/assess-novelty/scripts/novelty_candidates.test.ts": {
|
|
152
|
+
"max-lines-per-function": 179,
|
|
153
|
+
},
|
|
154
|
+
"skills/assess-novelty/scripts/novelty_cells.test.ts": {
|
|
155
|
+
"max-lines-per-function": 117,
|
|
156
|
+
},
|
|
157
|
+
"skills/assess-novelty/scripts/novelty_reader_brief.test.ts": {
|
|
158
|
+
"max-lines-per-function": 180,
|
|
159
|
+
complexity: 11,
|
|
160
|
+
},
|
|
161
|
+
"skills/assess-novelty/scripts/candidate_page.ts": {
|
|
162
|
+
"max-lines-per-function": 55,
|
|
163
|
+
},
|
|
164
|
+
"skills/assess-novelty/scripts/novelty_reader_brief.ts": {
|
|
165
|
+
"max-lines-per-function": 32,
|
|
166
|
+
"max-params": 5,
|
|
167
|
+
},
|
|
138
168
|
"src/adapters/curl/download.io.ts": { "max-lines-per-function": 39 },
|
|
139
169
|
"src/adapters/references/index.ts": { "max-lines-per-function": 36 },
|
|
140
170
|
"src/build-engine.ts": { "max-lines-per-function": 33 },
|
|
@@ -667,6 +697,28 @@ export default [
|
|
|
667
697
|
files: TEST_FILES,
|
|
668
698
|
rules: { "max-lines-per-function": ["error", MAX_LINES_TESTS] },
|
|
669
699
|
},
|
|
700
|
+
// 🔴 DEBT, NOT A PERMISSION. The novelty-check scripts and their harnesses were moved from a consumer
|
|
701
|
+
// repository AS THEY WERE (the 2026-11-02 decision): untyped JSON in, `any` throughout. Making them pass the
|
|
702
|
+
// type-safety rules below means rewriting them, which is paperlint#339 (TypeScript rewrite of the Python
|
|
703
|
+
// checkers) and paperlint#338 (the regex priority-sentence detector). Only the rules that need typed data
|
|
704
|
+
// are off, only here; the rules about behaviour (`complexity`, `max-depth`, `no-empty`, ...) still apply.
|
|
705
|
+
// Delete this block with the rewrite.
|
|
706
|
+
{
|
|
707
|
+
files: ["skills/assess-novelty/scripts/*.ts"],
|
|
708
|
+
rules: {
|
|
709
|
+
"@typescript-eslint/no-unsafe-member-access": "off",
|
|
710
|
+
"@typescript-eslint/no-unsafe-call": "off",
|
|
711
|
+
"@typescript-eslint/no-unsafe-assignment": "off",
|
|
712
|
+
"@typescript-eslint/no-unsafe-argument": "off",
|
|
713
|
+
"@typescript-eslint/no-unsafe-return": "off",
|
|
714
|
+
"@typescript-eslint/no-explicit-any": "off",
|
|
715
|
+
"@typescript-eslint/consistent-type-assertions": "off",
|
|
716
|
+
"@typescript-eslint/restrict-template-expressions": "off",
|
|
717
|
+
"@typescript-eslint/no-unnecessary-condition": "off",
|
|
718
|
+
"@typescript-eslint/no-confusing-void-expression": "off",
|
|
719
|
+
"@typescript-eslint/no-non-null-assertion": "off",
|
|
720
|
+
},
|
|
721
|
+
},
|
|
670
722
|
// Hexagonal layers, both axes (src/CLAUDE.md): knowledge by element, purity by file category.
|
|
671
723
|
IO_GLOBALS,
|
|
672
724
|
NO_CLOCK,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "paperlint",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.3.0",
|
|
4
4
|
"description": "A linter for scientific papers written in LaTeX: catches mistakes before you submit to a conference or journal.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -58,6 +58,7 @@
|
|
|
58
58
|
"eslint-plugin-project-structure": "^3.14.5",
|
|
59
59
|
"eslint-plugin-sonarjs": "^4.2.1",
|
|
60
60
|
"jsonc-parser": "^3.3.1",
|
|
61
|
+
"playwright-core": "^1.64.1",
|
|
61
62
|
"prettier": "^3.8.1",
|
|
62
63
|
"semantic-release": "25.0.9",
|
|
63
64
|
"typescript-eslint": "^8.70.1",
|
|
@@ -119,6 +120,7 @@
|
|
|
119
120
|
"presets",
|
|
120
121
|
"plugin",
|
|
121
122
|
"scripts",
|
|
123
|
+
"schemas",
|
|
122
124
|
"skills",
|
|
123
125
|
"src",
|
|
124
126
|
"templates",
|
package/presets/agentverify.md
CHANGED
|
@@ -26,8 +26,10 @@ researchr page `conf.researchr.org/home/agentverify-2027` only redirects to the
|
|
|
26
26
|
preset keeps the family's `\documentclass[conference]{IEEEtran}`.
|
|
27
27
|
- **Publisher**: «Accepted papers will appear in the ICSE 2027 workshop proceedings by default.»
|
|
28
28
|
The ICSE workshops page: «The workshop papers will be published by the IEEE.» The CFP does not
|
|
29
|
-
say what a non-default route would be, or whether it is archival.
|
|
30
|
-
|
|
29
|
+
say what a non-default route would be, or whether it is archival. The organizers: no other route
|
|
30
|
+
is offered (below).
|
|
31
|
+
- **Presenting**: «At least one author of each accepted paper must register and present.» Remote
|
|
32
|
+
presentation is allowed (below).
|
|
31
33
|
- **Deadlines (AoE)**: submission 13 Nov 2026, reviews due 5 Dec, final notification 11 Dec 2026,
|
|
32
34
|
camera-ready 29 Jan 2027.
|
|
33
35
|
|
|
@@ -65,10 +67,19 @@ and are over the limit. Count the PDF's pages yourself before submitting.
|
|
|
65
67
|
scheduled workflow; notification and camera-ready are the site's. No `registration`: there is no
|
|
66
68
|
abstract deadline.
|
|
67
69
|
|
|
70
|
+
## Answered by the organizers (emails to an author, not public)
|
|
71
|
+
|
|
72
|
+
- **Remote presentation** (2026-10-23): «In general, remote presentations will be allowed for
|
|
73
|
+
authors who are unable to attend the workshop in person. However, at least one author of each
|
|
74
|
+
accepted paper must register for the workshop to ensure its inclusion in the proceedings.»
|
|
75
|
+
- **APC** (2026-10-27), for every paper kind: «APC. It is free completely.»
|
|
76
|
+
- **Proceedings** (2026-10-27): «Workshop papers are normally published in an ICSE companion
|
|
77
|
+
IEEE/ACM proceedings.» Asked whether a non-archival option exists: «The non-trivial [sic:
|
|
78
|
+
non-archival] option is not offered.» So every accepted paper is archival.
|
|
79
|
+
|
|
68
80
|
## Not verified
|
|
69
81
|
|
|
70
|
-
- **
|
|
71
|
-
- **Archival / non-archival choice**: «by default» suggests an alternative; none is described.
|
|
82
|
+
- **Digital library**: whether the 2027 companion volume goes to IEEE Xplore or the ACM DL.
|
|
72
83
|
- **AI / LLM usage policy and required sections**: none stated.
|
|
73
84
|
|
|
74
85
|
## What the preset resolves to
|