paperlint 6.0.0 → 6.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/dist/adapters/latex/index.d.ts +1 -1
- package/dist/adapters/latex/index.d.ts.map +1 -1
- package/dist/adapters/latex/index.js +3 -2
- package/dist/adapters/latex/index.js.map +1 -1
- package/dist/adapters/latex/prose.d.ts +6 -1
- package/dist/adapters/latex/prose.d.ts.map +1 -1
- package/dist/adapters/latex/prose.js +142 -31
- package/dist/adapters/latex/prose.js.map +1 -1
- package/dist/adapters/mp4box/index.d.ts +4 -0
- package/dist/adapters/mp4box/index.d.ts.map +1 -0
- package/dist/adapters/mp4box/index.js +46 -0
- package/dist/adapters/mp4box/index.js.map +1 -0
- package/dist/adapters/node/index.d.ts +1 -0
- package/dist/adapters/node/index.d.ts.map +1 -1
- package/dist/adapters/node/index.js +1 -0
- package/dist/adapters/node/index.js.map +1 -1
- package/dist/adapters/node/list-dir.io.d.ts +3 -0
- package/dist/adapters/node/list-dir.io.d.ts.map +1 -0
- package/dist/adapters/node/list-dir.io.js +15 -0
- package/dist/adapters/node/list-dir.io.js.map +1 -0
- package/dist/adapters/png/index.d.ts +11 -0
- package/dist/adapters/png/index.d.ts.map +1 -0
- package/dist/adapters/png/index.js +21 -0
- package/dist/adapters/png/index.js.map +1 -0
- package/dist/adapters/srt/index.d.ts +4 -0
- package/dist/adapters/srt/index.d.ts.map +1 -0
- package/dist/adapters/srt/index.js +12 -0
- package/dist/adapters/srt/index.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +40 -22
- package/dist/cli.js.map +1 -1
- package/dist/domain/register.d.ts +96 -0
- package/dist/domain/register.d.ts.map +1 -0
- package/dist/domain/register.js +136 -0
- package/dist/domain/register.js.map +1 -0
- package/dist/domain/talk.d.ts +121 -0
- package/dist/domain/talk.d.ts.map +1 -0
- package/dist/domain/talk.js +121 -0
- package/dist/domain/talk.js.map +1 -0
- package/dist/domain/tex-document.d.ts +19 -0
- package/dist/domain/tex-document.d.ts.map +1 -1
- package/dist/domain/tex-document.js +8 -3
- package/dist/domain/tex-document.js.map +1 -1
- package/dist/lib/paper-config.d.ts +2 -0
- package/dist/lib/paper-config.d.ts.map +1 -1
- package/dist/lib/paper-config.js +3 -0
- package/dist/lib/paper-config.js.map +1 -1
- package/dist/paper-settings.d.ts +3 -0
- package/dist/paper-settings.d.ts.map +1 -1
- package/dist/paper-settings.js +15 -9
- package/dist/paper-settings.js.map +1 -1
- package/dist/ports/latex.d.ts +6 -1
- package/dist/ports/latex.d.ts.map +1 -1
- package/dist/ports/talk-media.d.ts +18 -0
- package/dist/ports/talk-media.d.ts.map +1 -0
- package/dist/ports/talk-media.js +2 -0
- package/dist/ports/talk-media.js.map +1 -0
- package/dist/presets.d.ts +6 -0
- package/dist/presets.d.ts.map +1 -1
- package/dist/presets.js +8 -9
- package/dist/presets.js.map +1 -1
- package/dist/register-bands.d.ts +37 -0
- package/dist/register-bands.d.ts.map +1 -0
- package/dist/register-bands.js +196 -0
- package/dist/register-bands.js.map +1 -0
- package/dist/register.d.ts +4 -2
- package/dist/register.d.ts.map +1 -1
- package/dist/register.js +6 -45
- package/dist/register.js.map +1 -1
- package/dist/talk-rules.d.ts +65 -0
- package/dist/talk-rules.d.ts.map +1 -0
- package/dist/talk-rules.js +451 -0
- package/dist/talk-rules.js.map +1 -0
- package/dist/tex-requirements.d.ts +9 -0
- package/dist/tex-requirements.d.ts.map +1 -1
- package/dist/tex-requirements.js +28 -6
- package/dist/tex-requirements.js.map +1 -1
- package/dist/tex-venue-rules.d.ts +1 -1
- package/dist/tex-venue-rules.d.ts.map +1 -1
- package/dist/tex-venue-rules.js.map +1 -1
- package/docs/configuration.md +2 -1
- package/docs/rules/talk/captions-cover.md +47 -0
- package/docs/rules/talk/duration-floor.md +38 -0
- package/docs/rules/talk/duration.md +43 -0
- package/docs/rules/talk/one-slide-size.md +38 -0
- package/docs/rules/talk/profile.md +64 -0
- package/docs/rules/talk/required-files.md +39 -0
- package/docs/rules/talk/undeclared.md +35 -0
- package/docs/rules/talk/video-format.md +43 -0
- package/docs/rules/tex/claim-emphasis.md +71 -0
- package/docs/rules/tex/contrast-frames.md +100 -0
- package/docs/rules/tex/relation-markers.md +72 -0
- package/docs/rules.md +57 -42
- package/docs/talk.md +94 -0
- package/fixtures/talk/audio-only.mp4 +0 -0
- package/fixtures/talk/one-slide.png +0 -0
- package/fixtures/talk/short-audio.mp4 +0 -0
- package/fixtures/talk/talk.mov +0 -0
- package/fixtures/talk/talk.mp4 +0 -0
- package/fixtures/talk/talk.srt +7 -0
- package/lib/paper-config.harness.mjs +5 -2
- package/lib/paper-config.ts +4 -0
- package/package.json +3 -1
- package/presets/agenticdev.jsonc +29 -0
- package/presets/aidc.jsonc +50 -0
- package/presets/venue-profile.schema.json +180 -1
- package/skills/grade-paper-writing/SKILL.md +59 -27
- package/skills/grade-paper-writing/SKILL.md.spec.ts +58 -26
- package/src/adapters/latex/index.test.ts +91 -0
- package/src/adapters/latex/index.ts +3 -2
- package/src/adapters/latex/prose.ts +188 -58
- package/src/adapters/mp4box/index.test.ts +63 -0
- package/src/adapters/mp4box/index.ts +50 -0
- package/src/adapters/node/index.ts +1 -0
- package/src/adapters/node/list-dir.io.ts +15 -0
- package/src/adapters/node/list-dir.test.ts +30 -0
- package/src/adapters/png/index.test.ts +43 -0
- package/src/adapters/png/index.ts +29 -0
- package/src/adapters/srt/index.test.ts +24 -0
- package/src/adapters/srt/index.ts +13 -0
- package/src/cli.test.ts +12 -0
- package/src/cli.ts +50 -21
- package/src/domain/register.test.ts +153 -0
- package/src/domain/register.ts +261 -0
- package/src/domain/talk.test.ts +125 -0
- package/src/domain/talk.ts +274 -0
- package/src/domain/tex-document.ts +37 -3
- package/src/new-paper.test.ts +1 -0
- package/src/paper-settings.test.ts +18 -1
- package/src/paper-settings.ts +21 -11
- package/src/ports/latex.ts +6 -0
- package/src/ports/talk-media.ts +19 -0
- package/src/presets.ts +14 -9
- package/src/register-bands.test.ts +327 -0
- package/src/register-bands.ts +291 -0
- package/src/register.ts +7 -37
- package/src/rule-cases.test.ts +177 -20
- package/src/talk-rules.test.ts +459 -0
- package/src/talk-rules.ts +672 -0
- package/src/tex-requirements.ts +56 -8
- package/src/tex-venue-rules.ts +7 -1
|
@@ -137,8 +137,187 @@
|
|
|
137
137
|
}
|
|
138
138
|
},
|
|
139
139
|
"rules": {
|
|
140
|
-
"description": "Rules the venue implies, rule id
|
|
140
|
+
"description": "Rules the venue implies, rule id → ESLint entry (a severity, or [severity, options]). Applied to every paper that extends this preset, before the paper's own rules.",
|
|
141
141
|
"type": "object"
|
|
142
|
+
},
|
|
143
|
+
"register": {
|
|
144
|
+
"description": "The register rules' anchors (`tex/contrast-frames`, `tex/claim-emphasis`, `tex/relation-markers`): accepted papers of the venue, or of its parent conference, each with its body's word count and its count of each measure as paperlint's own counters give them. A measure's band is the anchors' range widened by two Poisson standard deviations at each end (docs/rules/tex/contrast-frames.md). A child preset's block replaces its parent's.",
|
|
145
|
+
"type": "object",
|
|
146
|
+
"additionalProperties": false,
|
|
147
|
+
"required": ["anchors"],
|
|
148
|
+
"properties": {
|
|
149
|
+
"anchors": {
|
|
150
|
+
"type": "array",
|
|
151
|
+
"minItems": 1,
|
|
152
|
+
"items": {
|
|
153
|
+
"type": "object",
|
|
154
|
+
"additionalProperties": false,
|
|
155
|
+
"required": [
|
|
156
|
+
"paper",
|
|
157
|
+
"words",
|
|
158
|
+
"contrast_frames",
|
|
159
|
+
"claim_emphasis",
|
|
160
|
+
"relation_markers"
|
|
161
|
+
],
|
|
162
|
+
"properties": {
|
|
163
|
+
"paper": {
|
|
164
|
+
"description": "The anchor: a directory under fixtures/accepted-papers/ when the paper is there, or how to find it.",
|
|
165
|
+
"type": "string",
|
|
166
|
+
"minLength": 1
|
|
167
|
+
},
|
|
168
|
+
"words": {
|
|
169
|
+
"description": "Words of the body, as the register rules count them.",
|
|
170
|
+
"type": "integer",
|
|
171
|
+
"minimum": 1
|
|
172
|
+
},
|
|
173
|
+
"contrast_frames": {
|
|
174
|
+
"type": "integer",
|
|
175
|
+
"minimum": 0
|
|
176
|
+
},
|
|
177
|
+
"claim_emphasis": {
|
|
178
|
+
"type": "integer",
|
|
179
|
+
"minimum": 0
|
|
180
|
+
},
|
|
181
|
+
"relation_markers": {
|
|
182
|
+
"type": "integer",
|
|
183
|
+
"minimum": 0
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
"talk": {
|
|
191
|
+
"description": "What the venue asks a presenter to send, judged by the talk/* rules on the finished files (src/talk-rules.ts). Read only for a paper whose paperlint.json declares `talk`. A child preset's block replaces its parent's whole. Durations in seconds.",
|
|
192
|
+
"type": "object",
|
|
193
|
+
"additionalProperties": false,
|
|
194
|
+
"properties": {
|
|
195
|
+
"modes": {
|
|
196
|
+
"description": "The presentation modes the venue allows.",
|
|
197
|
+
"type": "array",
|
|
198
|
+
"items": {
|
|
199
|
+
"type": "string",
|
|
200
|
+
"enum": ["in-person", "remote-video", "remote-live"]
|
|
201
|
+
},
|
|
202
|
+
"uniqueItems": true,
|
|
203
|
+
"minItems": 1
|
|
204
|
+
},
|
|
205
|
+
"artifacts": {
|
|
206
|
+
"description": "What each mode owes: the files required, and those that may be sent.",
|
|
207
|
+
"type": "object",
|
|
208
|
+
"propertyNames": {
|
|
209
|
+
"type": "string",
|
|
210
|
+
"enum": ["in-person", "remote-video", "remote-live"]
|
|
211
|
+
},
|
|
212
|
+
"additionalProperties": {
|
|
213
|
+
"type": "object",
|
|
214
|
+
"additionalProperties": false,
|
|
215
|
+
"required": ["required"],
|
|
216
|
+
"properties": {
|
|
217
|
+
"required": {
|
|
218
|
+
"type": "array",
|
|
219
|
+
"items": {
|
|
220
|
+
"type": "string",
|
|
221
|
+
"enum": [
|
|
222
|
+
"video",
|
|
223
|
+
"one-slide",
|
|
224
|
+
"captions",
|
|
225
|
+
"slides-pdf",
|
|
226
|
+
"poster"
|
|
227
|
+
]
|
|
228
|
+
},
|
|
229
|
+
"uniqueItems": true
|
|
230
|
+
},
|
|
231
|
+
"optional": {
|
|
232
|
+
"type": "array",
|
|
233
|
+
"items": {
|
|
234
|
+
"type": "string",
|
|
235
|
+
"enum": [
|
|
236
|
+
"video",
|
|
237
|
+
"one-slide",
|
|
238
|
+
"captions",
|
|
239
|
+
"slides-pdf",
|
|
240
|
+
"poster"
|
|
241
|
+
]
|
|
242
|
+
},
|
|
243
|
+
"uniqueItems": true
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
},
|
|
248
|
+
"kinds": {
|
|
249
|
+
"description": "The talk slot per paper kind (the names of format.kinds; the paper's `kind` selects one).",
|
|
250
|
+
"type": "object",
|
|
251
|
+
"additionalProperties": {
|
|
252
|
+
"type": "object",
|
|
253
|
+
"additionalProperties": false,
|
|
254
|
+
"required": ["slot_s", "talk_s_max"],
|
|
255
|
+
"properties": {
|
|
256
|
+
"slot_s": {
|
|
257
|
+
"description": "The whole slot, talk and questions. Informational.",
|
|
258
|
+
"type": "number",
|
|
259
|
+
"exclusiveMinimum": 0
|
|
260
|
+
},
|
|
261
|
+
"talk_s_min": {
|
|
262
|
+
"description": "The shortest talk the venue asks for (talk/duration-floor).",
|
|
263
|
+
"type": "number",
|
|
264
|
+
"minimum": 0
|
|
265
|
+
},
|
|
266
|
+
"talk_s_max": {
|
|
267
|
+
"description": "The longest talk (talk/duration).",
|
|
268
|
+
"type": "number",
|
|
269
|
+
"exclusiveMinimum": 0
|
|
270
|
+
},
|
|
271
|
+
"qa_s": {
|
|
272
|
+
"description": "The questions' share. Informational.",
|
|
273
|
+
"type": "number",
|
|
274
|
+
"minimum": 0
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
},
|
|
279
|
+
"video": {
|
|
280
|
+
"description": "The venue's limits on the video file (talk/video-format).",
|
|
281
|
+
"type": "object",
|
|
282
|
+
"additionalProperties": false,
|
|
283
|
+
"properties": {
|
|
284
|
+
"container": {
|
|
285
|
+
"type": "string",
|
|
286
|
+
"enum": ["mp4"]
|
|
287
|
+
},
|
|
288
|
+
"min_height_px": {
|
|
289
|
+
"description": "The lowest vertical resolution; HD is 720.",
|
|
290
|
+
"type": "integer",
|
|
291
|
+
"minimum": 1
|
|
292
|
+
},
|
|
293
|
+
"max_bytes": {
|
|
294
|
+
"type": "integer",
|
|
295
|
+
"minimum": 1
|
|
296
|
+
},
|
|
297
|
+
"captions": {
|
|
298
|
+
"description": "`required`: a captions file is owed with the video (talk/required-files).",
|
|
299
|
+
"type": "string",
|
|
300
|
+
"enum": ["required", "optional"]
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
},
|
|
304
|
+
"one_slide": {
|
|
305
|
+
"description": "The one-slide image's size in pixels (talk/one-slide-size), when the venue states one.",
|
|
306
|
+
"type": "object",
|
|
307
|
+
"additionalProperties": false,
|
|
308
|
+
"required": ["width_px", "height_px"],
|
|
309
|
+
"properties": {
|
|
310
|
+
"width_px": {
|
|
311
|
+
"type": "integer",
|
|
312
|
+
"minimum": 1
|
|
313
|
+
},
|
|
314
|
+
"height_px": {
|
|
315
|
+
"type": "integer",
|
|
316
|
+
"minimum": 1
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
142
321
|
}
|
|
143
322
|
},
|
|
144
323
|
"allOf": [
|
|
@@ -4,7 +4,7 @@ description: Use when asking "does this paper read well?" / "is the writing any
|
|
|
4
4
|
allowed-tools: [Read, Write, Edit, Grep, Glob, Agent, Skill]
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
<!-- vigiles:sha256:
|
|
7
|
+
<!-- vigiles:sha256:03d0377baf71967f compiled from skills/grade-paper-writing/SKILL.md.spec.ts -->
|
|
8
8
|
|
|
9
9
|
# grade-paper-writing — grade how the paper READS, then fix it sentence by sentence
|
|
10
10
|
|
|
@@ -172,16 +172,41 @@ is what happened.
|
|
|
172
172
|
3. **For every dimension scoring ≤3, name the specific offending sentence or section** and write the fix —
|
|
173
173
|
not "tighten the prose" but the rewritten sentence, or "move the point from ¶3 to ¶1", or "gloss
|
|
174
174
|
`operation-normalized` in plain words at first use." Fixes must be applyable, not vibes.
|
|
175
|
-
3a. **Grade #10, register distance, against the venue's own papers — not against
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
175
|
+
3a. **Grade #10, register distance, against the venue's own papers, section by section — not against
|
|
176
|
+
the exemplars.** The rules count and this step judges; it starts from their numbers, not from a
|
|
177
|
+
count of its own.
|
|
178
|
+
- **Take the counts from the rules.** `npx paperlint lint <paper-dir>` reports
|
|
179
|
+
`tex/contrast-frames`, `tex/claim-emphasis` and `tex/relation-markers` when the venue preset
|
|
180
|
+
records anchors (AIDC does): each gives the body's rate per 10,000 words, the band, and the
|
|
181
|
+
anchors' range, and above the band it reports every frame and every claim in bold where it
|
|
182
|
+
stands. Those locations are the worklist. Do not recount them by grep — a narrower count is
|
|
183
|
+
gamed by rewording (*, not* → *rather than*), and the rules count every form.
|
|
184
|
+
- **Take the reference papers from the preset.** Its `register.anchors` names the accepted papers
|
|
185
|
+
the band comes from (AIDC: five ACSAC papers, all on arXiv under CC licences). Read two or three
|
|
186
|
+
of the same paper type as LaTeX source (`https://arxiv.org/e-print/<id>`) or as built PDFs. A
|
|
187
|
+
preset without anchors: fetch 2–3 accepted papers of the venue (or, for a first-edition workshop,
|
|
188
|
+
of its parent conference) from the proceedings or the program page, or use the ones the author
|
|
189
|
+
supplies.
|
|
190
|
+
- **Compare section by section, not the paper as a whole:** abstract, introduction, threat model or
|
|
191
|
+
background, method, results, limitations, conclusion. For each, put the draft's section beside the
|
|
192
|
+
same section of each reference paper and record, for both sides: how each result is owned (*we
|
|
193
|
+
measured* · a citation · a named population); how the relation between neighbouring sentences is
|
|
194
|
+
named (*because*, *therefore*, *however*, *for example*) or left to infer (a colon, a dash, a short
|
|
195
|
+
sentence); how often a point is made by what it is not; what is set in bold; and whether any
|
|
196
|
+
sentence is an aphorism, a fragment or a closing punchline. Quote the reference sentence beside
|
|
197
|
+
each draft sentence you flag.
|
|
198
|
+
- **Return concrete rewrites, and every one keeps every number and claim.** For each flagged sentence:
|
|
199
|
+
the draft sentence → the rewrite → the reference sentence it is modelled on → one line saying that
|
|
200
|
+
every number, citation and hedge is unchanged and the claim is neither softened nor strengthened.
|
|
201
|
+
A contrast frame is rewritten by saying what the thing is and naming the relation (*because*,
|
|
202
|
+
*as a result*), not by switching to another contrast form; a claim in bold loses the bold and
|
|
203
|
+
gains its owner (*we measured*, `\ref` to the table); a relation left to infer gets its word.
|
|
204
|
+
Where the frame IS the claim (the paper's thesis sets one mechanism against another), keep it
|
|
205
|
+
once, in the abstract and the introduction, and say so.
|
|
206
|
+
- **Score the distance:** 5 = a reviewer could not tell the draft from the reference papers by
|
|
207
|
+
register, section by section; 1 = it reads as a different genre. After the rewrites, run
|
|
208
|
+
`npx paperlint lint` again: every register rule inside its band is the floor for a 4, not the
|
|
209
|
+
score itself.
|
|
185
210
|
If no accepted paper can be fetched or supplied, write `#10: not graded — no reference papers` and
|
|
186
211
|
say which were tried; a register score from memory is the guess this dimension exists to replace.
|
|
187
212
|
4. **Find the paper's three-move opportunities:** what held assumption could open it? what is its single
|
|
@@ -353,10 +378,13 @@ changes neither meaning nor register — and never rewrite a cited work's title
|
|
|
353
378
|
**Signposting is the register, not a tic, and this skill never removes it on style grounds.** Frame
|
|
354
379
|
markers and relation words — *we show*, *this section*, *first … finally*, *in contrast*, *therefore*,
|
|
355
380
|
*however* — are how academic prose tells the reader what kind of claim comes next and how it relates to
|
|
356
|
-
the last one.
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
381
|
+
the last one. Relation words are a floor: `tex/relation-markers` reports a body below the band its
|
|
382
|
+
venue's accepted papers set (AIDC: 25.4 per 10,000 words; the paper reviewers called a blog post stood
|
|
383
|
+
at 19.1, and never wrote *however* once, where every accepted ACSAC paper writes it 6–11 times). Frame
|
|
384
|
+
markers do not separate a draft from accepted papers in either direction (see "Contrast framing"
|
|
385
|
+
below). Flag a connective only when it asserts a relation the two sentences do not have (a *therefore*
|
|
386
|
+
that does not follow), or when it is empty filler (*it is worth noting that*). Never flag one for being
|
|
387
|
+
academic.
|
|
360
388
|
|
|
361
389
|
**Other markers worth a pass:** nominalisation density (*an honest accounting of what the construction
|
|
362
390
|
costs* — abstract nouns doing the work verbs should do) and statistics chained through a paragraph
|
|
@@ -382,14 +410,15 @@ Two separable failures:
|
|
|
382
410
|
|
|
383
411
|
### 1. Contrast framing, and a frame that carries nothing
|
|
384
412
|
|
|
385
|
-
**What separates this corpus from accepted papers is contrast, not signposting —
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
must reconstruct. **Rewrite heuristic:** state the
|
|
391
|
-
|
|
392
|
-
|
|
413
|
+
**What separates this corpus from accepted papers is contrast, not signposting — and a rule counts
|
|
414
|
+
it.** `tex/contrast-frames` counts every form (*X, not Y* · *not X but Y* · *rather than* ·
|
|
415
|
+
*instead of* · *as opposed to*) per 10,000 words against the band the venue preset's anchors set: the
|
|
416
|
+
five accepted ACSAC papers measure 1.3–5.5, AIDC's band is 0–10.4, and the paper reviewers called a blog
|
|
417
|
+
post measured 101 before its rewrite and 28 after it. Every sentence that defines its point by what
|
|
418
|
+
it is not is a sentence whose point the reader must reconstruct. **Rewrite heuristic:** state the
|
|
419
|
+
thing and name the relation; move the rejected alternative to its own sentence, or drop it if nobody
|
|
420
|
+
proposed it. Swapping one form for another (*, not* → *rather than*) moves nothing — the rule counts
|
|
421
|
+
both, and so does a reviewer.
|
|
393
422
|
|
|
394
423
|
**Frame markers do not separate us from accepted papers, and are not a target in either direction.**
|
|
395
424
|
Hyland's *frame markers* (*this paper · this section · we show · first … finally · in what follows*)
|
|
@@ -464,10 +493,13 @@ one did, and it was the worst section in the paper by measured density both time
|
|
|
464
493
|
|
|
465
494
|
### What is NOT mechanizable here
|
|
466
495
|
|
|
467
|
-
Whether a frame marker carries its claim (*"we claim nothing there"* genuinely scopes one)
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
496
|
+
Whether a frame marker carries its claim (*"we claim nothing there"* genuinely scopes one), whether a
|
|
497
|
+
hedge is honest or defensive, whether a given contrast frame is the one a reader needs, and whether a
|
|
498
|
+
rewrite kept every claim at its strength. The mechanical legs that do exist: `tex/claim-provenance`
|
|
499
|
+
reports every sentence of the body that holds a number and no owner, and `tex/contrast-frames`,
|
|
500
|
+
`tex/claim-emphasis` and `tex/relation-markers` report a body outside its venue's band. Count them,
|
|
501
|
+
surface them, and leave the verdict to a reader. The counter's job is that nobody can say afterwards
|
|
502
|
+
they did not know.
|
|
471
503
|
|
|
472
504
|
## Compose with
|
|
473
505
|
- `harden-paper` — the multi-axis pre-submit gate calls this as its *writing* axis (the one a defect-hunt
|
|
@@ -178,16 +178,41 @@ is what happened.
|
|
|
178
178
|
3. **For every dimension scoring ≤3, name the specific offending sentence or section** and write the fix —
|
|
179
179
|
not "tighten the prose" but the rewritten sentence, or "move the point from ¶3 to ¶1", or "gloss
|
|
180
180
|
\`operation-normalized\` in plain words at first use." Fixes must be applyable, not vibes.
|
|
181
|
-
3a. **Grade #10, register distance, against the venue's own papers — not against
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
181
|
+
3a. **Grade #10, register distance, against the venue's own papers, section by section — not against
|
|
182
|
+
the exemplars.** The rules count and this step judges; it starts from their numbers, not from a
|
|
183
|
+
count of its own.
|
|
184
|
+
- **Take the counts from the rules.** \`npx paperlint lint <paper-dir>\` reports
|
|
185
|
+
\`tex/contrast-frames\`, \`tex/claim-emphasis\` and \`tex/relation-markers\` when the venue preset
|
|
186
|
+
records anchors (AIDC does): each gives the body's rate per 10,000 words, the band, and the
|
|
187
|
+
anchors' range, and above the band it reports every frame and every claim in bold where it
|
|
188
|
+
stands. Those locations are the worklist. Do not recount them by grep — a narrower count is
|
|
189
|
+
gamed by rewording (*, not* → *rather than*), and the rules count every form.
|
|
190
|
+
- **Take the reference papers from the preset.** Its \`register.anchors\` names the accepted papers
|
|
191
|
+
the band comes from (AIDC: five ACSAC papers, all on arXiv under CC licences). Read two or three
|
|
192
|
+
of the same paper type as LaTeX source (\`https://arxiv.org/e-print/<id>\`) or as built PDFs. A
|
|
193
|
+
preset without anchors: fetch 2–3 accepted papers of the venue (or, for a first-edition workshop,
|
|
194
|
+
of its parent conference) from the proceedings or the program page, or use the ones the author
|
|
195
|
+
supplies.
|
|
196
|
+
- **Compare section by section, not the paper as a whole:** abstract, introduction, threat model or
|
|
197
|
+
background, method, results, limitations, conclusion. For each, put the draft's section beside the
|
|
198
|
+
same section of each reference paper and record, for both sides: how each result is owned (*we
|
|
199
|
+
measured* · a citation · a named population); how the relation between neighbouring sentences is
|
|
200
|
+
named (*because*, *therefore*, *however*, *for example*) or left to infer (a colon, a dash, a short
|
|
201
|
+
sentence); how often a point is made by what it is not; what is set in bold; and whether any
|
|
202
|
+
sentence is an aphorism, a fragment or a closing punchline. Quote the reference sentence beside
|
|
203
|
+
each draft sentence you flag.
|
|
204
|
+
- **Return concrete rewrites, and every one keeps every number and claim.** For each flagged sentence:
|
|
205
|
+
the draft sentence → the rewrite → the reference sentence it is modelled on → one line saying that
|
|
206
|
+
every number, citation and hedge is unchanged and the claim is neither softened nor strengthened.
|
|
207
|
+
A contrast frame is rewritten by saying what the thing is and naming the relation (*because*,
|
|
208
|
+
*as a result*), not by switching to another contrast form; a claim in bold loses the bold and
|
|
209
|
+
gains its owner (*we measured*, \`\\ref\` to the table); a relation left to infer gets its word.
|
|
210
|
+
Where the frame IS the claim (the paper's thesis sets one mechanism against another), keep it
|
|
211
|
+
once, in the abstract and the introduction, and say so.
|
|
212
|
+
- **Score the distance:** 5 = a reviewer could not tell the draft from the reference papers by
|
|
213
|
+
register, section by section; 1 = it reads as a different genre. After the rewrites, run
|
|
214
|
+
\`npx paperlint lint\` again: every register rule inside its band is the floor for a 4, not the
|
|
215
|
+
score itself.
|
|
191
216
|
If no accepted paper can be fetched or supplied, write \`#10: not graded — no reference papers\` and
|
|
192
217
|
say which were tried; a register score from memory is the guess this dimension exists to replace.
|
|
193
218
|
4. **Find the paper's three-move opportunities:** what held assumption could open it? what is its single
|
|
@@ -359,10 +384,13 @@ changes neither meaning nor register — and never rewrite a cited work's title
|
|
|
359
384
|
**Signposting is the register, not a tic, and this skill never removes it on style grounds.** Frame
|
|
360
385
|
markers and relation words — *we show*, *this section*, *first … finally*, *in contrast*, *therefore*,
|
|
361
386
|
*however* — are how academic prose tells the reader what kind of claim comes next and how it relates to
|
|
362
|
-
the last one.
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
387
|
+
the last one. Relation words are a floor: \`tex/relation-markers\` reports a body below the band its
|
|
388
|
+
venue's accepted papers set (AIDC: 25.4 per 10,000 words; the paper reviewers called a blog post stood
|
|
389
|
+
at 19.1, and never wrote *however* once, where every accepted ACSAC paper writes it 6–11 times). Frame
|
|
390
|
+
markers do not separate a draft from accepted papers in either direction (see "Contrast framing"
|
|
391
|
+
below). Flag a connective only when it asserts a relation the two sentences do not have (a *therefore*
|
|
392
|
+
that does not follow), or when it is empty filler (*it is worth noting that*). Never flag one for being
|
|
393
|
+
academic.
|
|
366
394
|
|
|
367
395
|
**Other markers worth a pass:** nominalisation density (*an honest accounting of what the construction
|
|
368
396
|
costs* — abstract nouns doing the work verbs should do) and statistics chained through a paragraph
|
|
@@ -388,14 +416,15 @@ Two separable failures:
|
|
|
388
416
|
|
|
389
417
|
### 1. Contrast framing, and a frame that carries nothing
|
|
390
418
|
|
|
391
|
-
**What separates this corpus from accepted papers is contrast, not signposting —
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
must reconstruct. **Rewrite heuristic:** state the
|
|
397
|
-
|
|
398
|
-
|
|
419
|
+
**What separates this corpus from accepted papers is contrast, not signposting — and a rule counts
|
|
420
|
+
it.** \`tex/contrast-frames\` counts every form (*X, not Y* · *not X but Y* · *rather than* ·
|
|
421
|
+
*instead of* · *as opposed to*) per 10,000 words against the band the venue preset's anchors set: the
|
|
422
|
+
five accepted ACSAC papers measure 1.3–5.5, AIDC's band is 0–10.4, and the paper reviewers called a blog
|
|
423
|
+
post measured 101 before its rewrite and 28 after it. Every sentence that defines its point by what
|
|
424
|
+
it is not is a sentence whose point the reader must reconstruct. **Rewrite heuristic:** state the
|
|
425
|
+
thing and name the relation; move the rejected alternative to its own sentence, or drop it if nobody
|
|
426
|
+
proposed it. Swapping one form for another (*, not* → *rather than*) moves nothing — the rule counts
|
|
427
|
+
both, and so does a reviewer.
|
|
399
428
|
|
|
400
429
|
**Frame markers do not separate us from accepted papers, and are not a target in either direction.**
|
|
401
430
|
Hyland's *frame markers* (*this paper · this section · we show · first … finally · in what follows*)
|
|
@@ -470,10 +499,13 @@ one did, and it was the worst section in the paper by measured density both time
|
|
|
470
499
|
|
|
471
500
|
### What is NOT mechanizable here
|
|
472
501
|
|
|
473
|
-
Whether a frame marker carries its claim (*"we claim nothing there"* genuinely scopes one)
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
502
|
+
Whether a frame marker carries its claim (*"we claim nothing there"* genuinely scopes one), whether a
|
|
503
|
+
hedge is honest or defensive, whether a given contrast frame is the one a reader needs, and whether a
|
|
504
|
+
rewrite kept every claim at its strength. The mechanical legs that do exist: \`tex/claim-provenance\`
|
|
505
|
+
reports every sentence of the body that holds a number and no owner, and \`tex/contrast-frames\`,
|
|
506
|
+
\`tex/claim-emphasis\` and \`tex/relation-markers\` report a body outside its venue's band. Count them,
|
|
507
|
+
surface them, and leave the verdict to a reader. The counter's job is that nobody can say afterwards
|
|
508
|
+
they did not know.
|
|
477
509
|
|
|
478
510
|
## Compose with
|
|
479
511
|
- \`harden-paper\` — the multi-axis pre-submit gate calls this as its *writing* axis (the one a defect-hunt
|
|
@@ -8,6 +8,7 @@ import type * as Ast from "@unified-latex/unified-latex-types";
|
|
|
8
8
|
import { describe, expect, it } from "vitest";
|
|
9
9
|
import { runText, spanIn, type ProsePiece } from "../../domain/tex-document.ts";
|
|
10
10
|
import {
|
|
11
|
+
bodyEmphasis,
|
|
11
12
|
bodyProse,
|
|
12
13
|
documentBodyOf,
|
|
13
14
|
documentClassOf,
|
|
@@ -470,6 +471,15 @@ describe("bodyProse — run-in headings and list items", () => {
|
|
|
470
471
|
).toEqual(["It grows.", "It holds."]);
|
|
471
472
|
});
|
|
472
473
|
|
|
474
|
+
it("🔴 braces around a run-in heading change nothing: `{\\textbf{Side-channel eavesdropping:}}` is a heading, left out", () => {
|
|
475
|
+
// barovox-acsac24, Chapters/09_Related_Works.tex, writes its run-in headings this way.
|
|
476
|
+
expect(
|
|
477
|
+
texts(
|
|
478
|
+
"\\begin{document}\n{\\textbf{Side-channel eavesdropping:}} It has been studied.\n\\end{document}",
|
|
479
|
+
),
|
|
480
|
+
).toEqual(["It has been studied."]);
|
|
481
|
+
});
|
|
482
|
+
|
|
473
483
|
it("the same markup inside a sentence, or without the closing mark, is prose", () => {
|
|
474
484
|
expect(
|
|
475
485
|
texts(
|
|
@@ -541,3 +551,84 @@ describe("documentBodyOf — the body of a source that is a document of its own"
|
|
|
541
551
|
);
|
|
542
552
|
});
|
|
543
553
|
});
|
|
554
|
+
|
|
555
|
+
describe("bodyEmphasis — phrases set apart inside the body's prose, and where they stand", () => {
|
|
556
|
+
/** Each phrase as `style/place: text`. */
|
|
557
|
+
const shape = (src: string): readonly string[] =>
|
|
558
|
+
bodyEmphasis(parseLatex(src)).map(
|
|
559
|
+
(e) => `${e.style}/${e.place}: ${e.text}`,
|
|
560
|
+
);
|
|
561
|
+
|
|
562
|
+
it("🔴 a bold phrase inside a sentence is inline; one opening a paragraph or an item is a label (opening)", () => {
|
|
563
|
+
expect(
|
|
564
|
+
shape(
|
|
565
|
+
"\\begin{document}\nWe find that \\textbf{the guards react to the word}.\n\n\\textbf{Varying the volume}. We vary it.\n\\begin{itemize}\n\\item \\textbf{A corpus of questions}: we release it.\n\\end{itemize}\n\\end{document}",
|
|
566
|
+
),
|
|
567
|
+
).toEqual([
|
|
568
|
+
"bold/inline: the guards react to the word",
|
|
569
|
+
"bold/opening: Varying the volume",
|
|
570
|
+
"bold/opening: A corpus of questions",
|
|
571
|
+
]);
|
|
572
|
+
});
|
|
573
|
+
|
|
574
|
+
it("🔴 never a heading, a run-in heading, a caption, a table, or anything after the bibliography", () => {
|
|
575
|
+
expect(
|
|
576
|
+
shape(
|
|
577
|
+
"\\begin{document}\n\\section{\\textbf{Big}}\n\\textbf{Threats.} None \\emph{here}.\n\\begin{table}\\caption{\\textbf{C}}\\begin{tabular}{l}\\textbf{cell}\\end{tabular}\\end{table}\n\\bibliography{refs}\nAfter \\textbf{this}.\n\\end{document}",
|
|
578
|
+
),
|
|
579
|
+
).toEqual(["italic/inline: here"]);
|
|
580
|
+
});
|
|
581
|
+
|
|
582
|
+
it("braces around a label change nothing: `{\\textbf{Filtering}}.` opening a paragraph is a label", () => {
|
|
583
|
+
// barovox-acsac24, Chapters/08_Discussion.tex.
|
|
584
|
+
expect(
|
|
585
|
+
shape(
|
|
586
|
+
"\\begin{document}\n{\\textbf{Increasing the distance}}. The proximity matters.\n\\end{document}",
|
|
587
|
+
),
|
|
588
|
+
).toEqual(["bold/opening: Increasing the distance"]);
|
|
589
|
+
});
|
|
590
|
+
});
|
|
591
|
+
|
|
592
|
+
describe("bodyEmphasis — each style, and edge cases", () => {
|
|
593
|
+
/** Each phrase as `style/place: text`. */
|
|
594
|
+
const shape = (src: string): readonly string[] =>
|
|
595
|
+
bodyEmphasis(parseLatex(src)).map(
|
|
596
|
+
(e) => `${e.style}/${e.place}: ${e.text}`,
|
|
597
|
+
);
|
|
598
|
+
|
|
599
|
+
it("each style: \\emph and \\textit italic, \\underline underline, a `{\\bfseries …}` group bold; a footnote's phrase counts", () => {
|
|
600
|
+
expect(
|
|
601
|
+
shape(
|
|
602
|
+
"\\begin{document}\nA \\emph{b} c \\textit{d} e \\underline{f} g {\\bfseries h i} j.\\footnote{In \\textbf{k}.}\n\\end{document}",
|
|
603
|
+
),
|
|
604
|
+
).toEqual([
|
|
605
|
+
"italic/inline: b",
|
|
606
|
+
"italic/inline: d",
|
|
607
|
+
"underline/inline: f",
|
|
608
|
+
"bold/inline: h i",
|
|
609
|
+
"bold/inline: k",
|
|
610
|
+
]);
|
|
611
|
+
});
|
|
612
|
+
|
|
613
|
+
it("an empty bold macro sets nothing apart, opening a paragraph or not", () => {
|
|
614
|
+
expect(
|
|
615
|
+
shape(
|
|
616
|
+
"\\begin{document}\n\\textbf{} Opens. We \\textbf{ } go.\n\\end{document}",
|
|
617
|
+
),
|
|
618
|
+
).toEqual([]);
|
|
619
|
+
});
|
|
620
|
+
|
|
621
|
+
it("an environment opening a paragraph opens nothing for the phrases inside it", () => {
|
|
622
|
+
expect(
|
|
623
|
+
shape(
|
|
624
|
+
"\\begin{document}\n\\begin{quote}\nWe say \\textbf{this}.\n\\end{quote}\n\\end{document}",
|
|
625
|
+
),
|
|
626
|
+
).toEqual(["bold/inline: this"]);
|
|
627
|
+
});
|
|
628
|
+
|
|
629
|
+
it("the span is the macro with its argument, where the source has it", () => {
|
|
630
|
+
const src = "\\begin{document}\nWe \\textbf{see it}.\n\\end{document}";
|
|
631
|
+
const [e] = bodyEmphasis(parseLatex(src));
|
|
632
|
+
expect(e && src.slice(e.span.start, e.span.end)).toBe("\\textbf{see it}");
|
|
633
|
+
});
|
|
634
|
+
});
|
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
import { documentBodyOf, includesOf } from "./includes.ts";
|
|
30
30
|
import { outlineOf } from "./outline.ts";
|
|
31
31
|
import { parseLatex } from "./parse.ts";
|
|
32
|
-
import { bodyProse } from "./prose.ts";
|
|
32
|
+
import { bodyEmphasis, bodyProse } from "./prose.ts";
|
|
33
33
|
import { renderedRuns } from "./rendered.ts";
|
|
34
34
|
import { layoutOverridesOf } from "./layout.ts";
|
|
35
35
|
|
|
@@ -50,7 +50,7 @@ export {
|
|
|
50
50
|
export { documentBodyOf, includesOf } from "./includes.ts";
|
|
51
51
|
export { outlineOf } from "./outline.ts";
|
|
52
52
|
export { parseLatex, type ParsedTex } from "./parse.ts";
|
|
53
|
-
export { bodyProse } from "./prose.ts";
|
|
53
|
+
export { bodyEmphasis, bodyProse } from "./prose.ts";
|
|
54
54
|
export { renderedRuns } from "./rendered.ts";
|
|
55
55
|
export { layoutOverridesOf } from "./layout.ts";
|
|
56
56
|
|
|
@@ -60,6 +60,7 @@ export const latexReader: LatexReader = {
|
|
|
60
60
|
outline: (src) => outlineOf(parseLatex(src)),
|
|
61
61
|
renderedRuns: (src) => renderedRuns(parseLatex(src)),
|
|
62
62
|
bodyProse: (src) => bodyProse(parseLatex(src)),
|
|
63
|
+
bodyEmphasis: (src) => bodyEmphasis(parseLatex(src)),
|
|
63
64
|
includes: (src) => includesOf(parseLatex(src)),
|
|
64
65
|
documentBody: (src) => documentBodyOf(parseLatex(src)),
|
|
65
66
|
template: parseTemplate,
|