paperlint 3.1.3 → 3.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.
Files changed (371) hide show
  1. package/.github/workflows/ci.yml +12 -7
  2. package/CLAUDE.md +3 -3
  3. package/CONTRIBUTING.md +34 -5
  4. package/dist/adapters/banal/index.d.ts.map +1 -1
  5. package/dist/adapters/banal/index.js +9 -5
  6. package/dist/adapters/banal/index.js.map +1 -1
  7. package/dist/adapters/banal/invocation.d.ts +1 -1
  8. package/dist/adapters/node/files.io.d.ts.map +1 -1
  9. package/dist/adapters/node/files.io.js +2 -1
  10. package/dist/adapters/node/files.io.js.map +1 -1
  11. package/dist/adapters/node/process.io.d.ts +0 -5
  12. package/dist/adapters/node/process.io.d.ts.map +1 -1
  13. package/dist/adapters/node/process.io.js +4 -3
  14. package/dist/adapters/node/process.io.js.map +1 -1
  15. package/dist/adapters/pdfjs/fill.d.ts.map +1 -1
  16. package/dist/adapters/pdfjs/fill.js +13 -7
  17. package/dist/adapters/pdfjs/fill.js.map +1 -1
  18. package/dist/adapters/references/index.d.ts.map +1 -1
  19. package/dist/adapters/references/index.js +4 -5
  20. package/dist/adapters/references/index.js.map +1 -1
  21. package/dist/adapters/references/pool.d.ts.map +1 -1
  22. package/dist/adapters/references/pool.js +4 -5
  23. package/dist/adapters/references/pool.js.map +1 -1
  24. package/dist/adapters/references/reach.io.d.ts.map +1 -1
  25. package/dist/adapters/references/reach.io.js +2 -1
  26. package/dist/adapters/references/reach.io.js.map +1 -1
  27. package/dist/build-engine.js +2 -2
  28. package/dist/build-engine.js.map +1 -1
  29. package/dist/build.d.ts.map +1 -1
  30. package/dist/build.js +14 -11
  31. package/dist/build.js.map +1 -1
  32. package/dist/cli.d.ts.map +1 -1
  33. package/dist/cli.js +31 -34
  34. package/dist/cli.js.map +1 -1
  35. package/dist/doctor.d.ts.map +1 -1
  36. package/dist/doctor.js +3 -2
  37. package/dist/doctor.js.map +1 -1
  38. package/dist/domain/lookup-cache.d.ts.map +1 -1
  39. package/dist/domain/lookup-cache.js +10 -8
  40. package/dist/domain/lookup-cache.js.map +1 -1
  41. package/dist/domain/text.d.ts +12 -0
  42. package/dist/domain/text.d.ts.map +1 -1
  43. package/dist/domain/text.js +17 -0
  44. package/dist/domain/text.js.map +1 -1
  45. package/dist/engine.d.ts.map +1 -1
  46. package/dist/engine.js +4 -3
  47. package/dist/engine.js.map +1 -1
  48. package/dist/eslint-rules/bib-reachable-entry.d.ts +22 -0
  49. package/dist/eslint-rules/bib-reachable-entry.d.ts.map +1 -0
  50. package/dist/eslint-rules/bib-reachable-entry.js +75 -0
  51. package/dist/eslint-rules/bib-reachable-entry.js.map +1 -0
  52. package/dist/eslint-rules/install-path-literals.d.ts +80 -0
  53. package/dist/eslint-rules/install-path-literals.d.ts.map +1 -0
  54. package/dist/eslint-rules/install-path-literals.js +105 -0
  55. package/dist/eslint-rules/install-path-literals.js.map +1 -0
  56. package/dist/eslint-rules/latex-language.d.ts +136 -0
  57. package/dist/eslint-rules/latex-language.d.ts.map +1 -0
  58. package/dist/eslint-rules/latex-language.js +639 -0
  59. package/dist/eslint-rules/latex-language.js.map +1 -0
  60. package/dist/eslint-rules/paper-research-question.d.ts +31 -0
  61. package/dist/eslint-rules/paper-research-question.d.ts.map +1 -0
  62. package/dist/eslint-rules/paper-research-question.js +188 -0
  63. package/dist/eslint-rules/paper-research-question.js.map +1 -0
  64. package/dist/eslint-rules/paper-stages.d.ts +83 -0
  65. package/dist/eslint-rules/paper-stages.d.ts.map +1 -0
  66. package/dist/eslint-rules/paper-stages.js +358 -0
  67. package/dist/eslint-rules/paper-stages.js.map +1 -0
  68. package/dist/eslint-rules/paper-typography.d.ts +74 -0
  69. package/dist/eslint-rules/paper-typography.d.ts.map +1 -0
  70. package/dist/eslint-rules/paper-typography.js +404 -0
  71. package/dist/eslint-rules/paper-typography.js.map +1 -0
  72. package/dist/eslint-rules/papers.d.ts +42 -0
  73. package/dist/eslint-rules/papers.d.ts.map +1 -0
  74. package/dist/eslint-rules/papers.js +145 -0
  75. package/dist/eslint-rules/papers.js.map +1 -0
  76. package/dist/eslint-rules/pdf-last-page-balance.d.ts +72 -0
  77. package/dist/eslint-rules/pdf-last-page-balance.d.ts.map +1 -0
  78. package/dist/eslint-rules/pdf-last-page-balance.js +237 -0
  79. package/dist/eslint-rules/pdf-last-page-balance.js.map +1 -0
  80. package/dist/eslint-rules/review-frontmatter.d.ts +57 -0
  81. package/dist/eslint-rules/review-frontmatter.d.ts.map +1 -0
  82. package/dist/eslint-rules/review-frontmatter.js +126 -0
  83. package/dist/eslint-rules/review-frontmatter.js.map +1 -0
  84. package/dist/eslint-rules/review-frontmatter.schema.json +36 -0
  85. package/dist/eslint-rules/rule-context.d.ts +55 -0
  86. package/dist/eslint-rules/rule-context.d.ts.map +1 -0
  87. package/dist/eslint-rules/rule-context.js +9 -0
  88. package/dist/eslint-rules/rule-context.js.map +1 -0
  89. package/dist/eslint-rules/sibling-frontmatter.d.ts +25 -0
  90. package/dist/eslint-rules/sibling-frontmatter.d.ts.map +1 -0
  91. package/dist/eslint-rules/sibling-frontmatter.js +16 -0
  92. package/dist/eslint-rules/sibling-frontmatter.js.map +1 -0
  93. package/dist/eslint-rules/sibling-frontmatter.schema.json +14 -0
  94. package/dist/eslint-rules/temp-root-realpath.d.ts +71 -0
  95. package/dist/eslint-rules/temp-root-realpath.d.ts.map +1 -0
  96. package/dist/eslint-rules/temp-root-realpath.js +139 -0
  97. package/dist/eslint-rules/temp-root-realpath.js.map +1 -0
  98. package/dist/eslint-rules/tex-build.d.ts +35 -0
  99. package/dist/eslint-rules/tex-build.d.ts.map +1 -0
  100. package/dist/eslint-rules/tex-build.js +313 -0
  101. package/dist/eslint-rules/tex-build.js.map +1 -0
  102. package/dist/facts-file.d.ts.map +1 -1
  103. package/dist/facts-file.js +2 -1
  104. package/dist/facts-file.js.map +1 -1
  105. package/dist/hooks-settings.d.ts +1 -1
  106. package/dist/hooks-settings.d.ts.map +1 -1
  107. package/dist/hooks-settings.js +14 -9
  108. package/dist/hooks-settings.js.map +1 -1
  109. package/dist/init.d.ts +5 -5
  110. package/dist/init.d.ts.map +1 -1
  111. package/dist/init.js +15 -7
  112. package/dist/init.js.map +1 -1
  113. package/dist/latex-loop.d.ts +2 -2
  114. package/dist/latex-loop.d.ts.map +1 -1
  115. package/dist/latex-loop.js +2 -2
  116. package/dist/latex-loop.js.map +1 -1
  117. package/dist/lib/agent-cli-version.d.ts +65 -0
  118. package/dist/lib/agent-cli-version.d.ts.map +1 -0
  119. package/dist/lib/agent-cli-version.js +77 -0
  120. package/dist/lib/agent-cli-version.js.map +1 -0
  121. package/dist/lib/check.d.ts +19 -0
  122. package/dist/lib/check.d.ts.map +1 -0
  123. package/dist/lib/check.js +52 -0
  124. package/dist/lib/check.js.map +1 -0
  125. package/dist/lib/markdown.d.ts +180 -0
  126. package/dist/lib/markdown.d.ts.map +1 -0
  127. package/dist/lib/markdown.js +302 -0
  128. package/dist/lib/markdown.js.map +1 -0
  129. package/dist/lib/paper-config.d.ts +84 -0
  130. package/dist/lib/paper-config.d.ts.map +1 -0
  131. package/dist/lib/paper-config.js +142 -0
  132. package/dist/lib/paper-config.js.map +1 -0
  133. package/dist/lib/skill-eval-fixture.d.ts +29 -0
  134. package/dist/lib/skill-eval-fixture.d.ts.map +1 -0
  135. package/dist/lib/skill-eval-fixture.js +62 -0
  136. package/dist/lib/skill-eval-fixture.js.map +1 -0
  137. package/dist/link-skills.d.ts.map +1 -1
  138. package/dist/link-skills.js +5 -4
  139. package/dist/link-skills.js.map +1 -1
  140. package/dist/new-paper.d.ts.map +1 -1
  141. package/dist/new-paper.js +2 -2
  142. package/dist/new-paper.js.map +1 -1
  143. package/dist/paper-settings.d.ts.map +1 -1
  144. package/dist/paper-settings.js +5 -4
  145. package/dist/paper-settings.js.map +1 -1
  146. package/dist/pdf-facts.d.ts.map +1 -1
  147. package/dist/pdf-facts.js +2 -1
  148. package/dist/pdf-facts.js.map +1 -1
  149. package/dist/pdf-geometry.d.ts.map +1 -1
  150. package/dist/pdf-geometry.js +1 -1
  151. package/dist/pdf-geometry.js.map +1 -1
  152. package/dist/presets.d.ts.map +1 -1
  153. package/dist/presets.js +3 -2
  154. package/dist/presets.js.map +1 -1
  155. package/dist/references.d.ts.map +1 -1
  156. package/dist/references.js +11 -6
  157. package/dist/references.js.map +1 -1
  158. package/dist/rules-config.d.ts.map +1 -1
  159. package/dist/rules-config.js +6 -3
  160. package/dist/rules-config.js.map +1 -1
  161. package/dist/structure.js +1 -1
  162. package/dist/structure.js.map +1 -1
  163. package/dist/tex-requirements.d.ts.map +1 -1
  164. package/dist/tex-requirements.js +8 -3
  165. package/dist/tex-requirements.js.map +1 -1
  166. package/dist/toolchain.d.ts.map +1 -1
  167. package/dist/toolchain.js +21 -16
  168. package/dist/toolchain.js.map +1 -1
  169. package/dist/venue-rules.js +1 -1
  170. package/dist/venue-rules.js.map +1 -1
  171. package/docs/e2e.md +7 -7
  172. package/docs/install.md +1 -1
  173. package/docs/prior-art/README.md +1 -1
  174. package/docs/prior-art/package-location.md +5 -5
  175. package/docs/prior-art/repro/README.md +1 -1
  176. package/docs/prior-art/test-tooling.md +2 -2
  177. package/docs/testing.md +11 -8
  178. package/docs/toolchain.md +1 -1
  179. package/eslint-rules/{bib-reachable-entry.mjs → bib-reachable-entry.ts} +4 -3
  180. package/eslint-rules/install-path-literals.harness.mjs +1 -1
  181. package/eslint-rules/{install-path-literals.mjs → install-path-literals.ts} +16 -8
  182. package/eslint-rules/latex-language.harness.mjs +2 -2
  183. package/eslint-rules/latex-language.test.mjs +7 -1
  184. package/eslint-rules/{latex-language.mjs → latex-language.ts} +297 -109
  185. package/eslint-rules/paper-research-question.harness.mjs +3 -3
  186. package/eslint-rules/{paper-research-question.mjs → paper-research-question.ts} +34 -15
  187. package/eslint-rules/paper-stages.harness.mjs +2 -2
  188. package/eslint-rules/paper-stages.test.mjs +8 -2
  189. package/eslint-rules/{paper-stages.mjs → paper-stages.ts} +74 -29
  190. package/eslint-rules/paper-typography.test.mjs +3 -3
  191. package/eslint-rules/{paper-typography.mjs → paper-typography.ts} +132 -54
  192. package/eslint-rules/papers.harness.mjs +2 -2
  193. package/eslint-rules/{papers.mjs → papers.ts} +7 -4
  194. package/eslint-rules/pdf-last-page-balance.harness.mjs +3 -3
  195. package/eslint-rules/{pdf-last-page-balance.mjs → pdf-last-page-balance.ts} +88 -31
  196. package/eslint-rules/review-frontmatter.test.mjs +2 -2
  197. package/eslint-rules/{review-frontmatter.mjs → review-frontmatter.ts} +37 -15
  198. package/eslint-rules/rule-context.ts +62 -0
  199. package/eslint-rules/{sibling-frontmatter.mjs → sibling-frontmatter.ts} +1 -1
  200. package/eslint-rules/temp-root-realpath.harness.mjs +1 -1
  201. package/eslint-rules/{temp-root-realpath.mjs → temp-root-realpath.ts} +19 -6
  202. package/eslint-rules/tex-build.harness.mjs +2 -2
  203. package/eslint-rules/{tex-build.mjs → tex-build.ts} +4 -3
  204. package/eslint.config.mjs +139 -30
  205. package/fixtures/pdf-facts/README.md +2 -2
  206. package/fixtures/real-markdown-paper/{baseline.mjs → baseline.ts} +31 -10
  207. package/hooks/{hooks.harness.mjs → hooks.harness.ts} +51 -34
  208. package/hooks/paper-edit-guard.hook.mjs +1 -1
  209. package/hooks/{paper-edit-guard.test.mjs → paper-edit-guard.test.ts} +3 -7
  210. package/hooks/paper-skills-nudge.hook.mjs +1 -1
  211. package/hooks/{paper-skills-nudge.test.mjs → paper-skills-nudge.test.ts} +2 -6
  212. package/hooks/{paper-status-gates.test.mjs → paper-status-gates.test.ts} +2 -6
  213. package/lib/agent-cli-version.harness.mjs +1 -1
  214. package/lib/{agent-cli-version.mjs → agent-cli-version.ts} +32 -18
  215. package/lib/check.test.ts +14 -9
  216. package/lib/{check.mjs → check.ts} +22 -9
  217. package/lib/markdown.test.mjs +7 -7
  218. package/lib/{markdown.mjs → markdown.ts} +68 -29
  219. package/lib/paper-config.harness.mjs +8 -8
  220. package/lib/{paper-config.mjs → paper-config.ts} +19 -14
  221. package/lib/skill-checks.mjs +1 -1
  222. package/lib/skill-checks.test.mjs +1 -1
  223. package/lib/skill-corpus.mjs +1 -1
  224. package/lib/skill-eval-kit.mjs +1 -1
  225. package/package.json +42 -10
  226. package/scripts/{check.harness.mjs → check.harness.ts} +111 -10
  227. package/scripts/{check.test.mjs → check.test.ts} +13 -10
  228. package/scripts/{check.mjs → check.ts} +116 -42
  229. package/scripts/coverage-config.test.ts +80 -37
  230. package/scripts/eslint-report-guard.test.mjs +1 -1
  231. package/scripts/harness-api.frozen.json +14 -15
  232. package/scripts/harness-api.test.ts +8 -5
  233. package/scripts/layer-legacy-frozen.test.ts +17 -13
  234. package/scripts/{layer-legacy-frozen.mjs → layer-legacy-frozen.ts} +128 -39
  235. package/scripts/release-config.test.ts +12 -4
  236. package/scripts/rules-see-files.test.mjs +1 -1
  237. package/scripts/test.test.ts +78 -0
  238. package/scripts/test.ts +87 -0
  239. package/skills/grade-paper-writing/prose-lint.mjs +1 -1
  240. package/skills/grade-paper-writing/{prose-lint.test.mjs → prose-lint.test.ts} +2 -2
  241. package/skills/paper-pipeline/description-language.eval.mjs +1 -1
  242. package/skills/paper-pipeline/framing-vs-vocabulary.eval.mjs +1 -1
  243. package/skills/paper-pipeline/grade-paper-writing-ablation.eval.mjs +1 -1
  244. package/skills/paper-pipeline/pipeline-firing.eval.mjs +1 -1
  245. package/skills/paper-pipeline/pipeline-language.eval.mjs +1 -1
  246. package/skills/paper-pipeline/scripts/README.md +1 -1
  247. package/skills/paper-pipeline/scripts/announce.test.mjs +1 -1
  248. package/skills/paper-pipeline/scripts/artifact-coverage.mjs +1 -1
  249. package/skills/paper-pipeline/scripts/{artifact-coverage.test.mjs → artifact-coverage.test.ts} +2 -2
  250. package/skills/paper-pipeline/scripts/consumer.mjs +1 -5
  251. package/skills/paper-pipeline/scripts/consumer.test.mjs +1 -1
  252. package/skills/paper-pipeline/scripts/extract-ref-facts.harness.mjs +1 -1
  253. package/skills/paper-pipeline/scripts/extract-ref-facts.mjs +1 -4
  254. package/skills/paper-pipeline/scripts/extract-ref-facts.test.mjs +1 -1
  255. package/skills/paper-pipeline/scripts/fixtures/{scorecard.mjs → scorecard.ts} +36 -7
  256. package/skills/paper-pipeline/scripts/{generated-code.test.mjs → generated-code.test.ts} +3 -3
  257. package/skills/paper-pipeline/scripts/ledger.cli.test.mjs +1 -1
  258. package/skills/paper-pipeline/scripts/pipeline-check.cli.test.mjs +2 -2
  259. package/skills/paper-pipeline/scripts/pipeline-check.harness.mjs +2 -2
  260. package/skills/paper-pipeline/scripts/pipeline-check.mjs +1 -4
  261. package/skills/paper-pipeline/scripts/population-map.mjs +1 -4
  262. package/skills/paper-pipeline/scripts/population-map.test.mjs +1 -1
  263. package/skills/paper-pipeline/scripts/{round-diff.harness.mjs → round-diff.harness.ts} +45 -18
  264. package/skills/paper-pipeline/scripts/round-diff.mjs +1 -1
  265. package/skills/paper-pipeline/scripts/round-diff.test.mjs +1 -1
  266. package/skills/paper-pipeline/scripts/run-mechanical.test.mjs +1 -1
  267. package/skills/paper-pipeline/scripts/status.test.mjs +1 -1
  268. package/skills/plan-paper-timeline/fixtures/{fake-google-calendar.mjs → fake-google-calendar.ts} +101 -70
  269. package/skills/plan-paper-timeline/plan-paper-timeline.effects.harness.mjs +3 -3
  270. package/skills/render-paper/{extract-pdf-facts.harness.mjs → extract-pdf-facts.harness.ts} +34 -9
  271. package/skills/render-paper/render-paper.harness.mjs +2 -2
  272. package/skills/tighten-paper/structure.mjs +1 -1
  273. package/skills/tighten-paper/{structure.test.mjs → structure.test.ts} +4 -3
  274. package/skills/verify-citations/scripts/{bib-authors.cli.test.mjs → bib-authors.cli.test.ts} +14 -4
  275. package/skills/verify-citations/scripts/bib-authors.d.mts +63 -0
  276. package/skills/verify-citations/scripts/bib-authors.mjs +1 -4
  277. package/skills/verify-citations/scripts/{verify-cites.cli.test.mjs → verify-cites.cli.test.ts} +32 -9
  278. package/skills/verify-citations/scripts/verify-cites.d.mts +58 -0
  279. package/src/CLAUDE.md +1 -1
  280. package/src/adapters/banal/index.test.ts +3 -6
  281. package/src/adapters/banal/index.ts +7 -4
  282. package/src/adapters/banal/invocation.test.ts +3 -1
  283. package/src/adapters/banal/invocation.ts +1 -1
  284. package/src/adapters/banal/output.test.ts +1 -1
  285. package/src/adapters/banal/run.test.ts +3 -3
  286. package/src/adapters/banal/xml.test.ts +1 -1
  287. package/src/adapters/curl/download.test.ts +4 -2
  288. package/src/adapters/node/files.io.ts +2 -2
  289. package/src/adapters/node/files.test.ts +3 -1
  290. package/src/adapters/node/process.io.ts +4 -3
  291. package/src/adapters/node/process.test.ts +1 -1
  292. package/src/adapters/node/workspace.test.ts +3 -1
  293. package/src/adapters/pdfjs/fill.test.ts +2 -2
  294. package/src/adapters/pdfjs/fill.ts +14 -7
  295. package/src/adapters/references/index.test.ts +31 -38
  296. package/src/adapters/references/index.ts +26 -58
  297. package/src/adapters/references/pool.ts +3 -5
  298. package/src/adapters/references/reach.io.ts +2 -1
  299. package/src/build-engine.harness.mjs +1 -1
  300. package/src/build-engine.test.ts +2 -2
  301. package/src/build-engine.ts +2 -2
  302. package/src/build.harness.mjs +2 -2
  303. package/src/build.test.ts +15 -14
  304. package/src/build.ts +28 -19
  305. package/src/cli.harness.mjs +6 -6
  306. package/src/cli.test.ts +13 -6
  307. package/src/cli.ts +39 -37
  308. package/src/doctor.harness.mjs +3 -3
  309. package/src/doctor.ts +3 -2
  310. package/src/domain/lookup-cache.ts +21 -11
  311. package/src/domain/result.test.ts +2 -2
  312. package/src/domain/text.test.ts +32 -0
  313. package/src/domain/text.ts +23 -0
  314. package/src/engine.harness.mjs +2 -2
  315. package/src/engine.ts +4 -3
  316. package/src/facts-file.test.ts +9 -7
  317. package/src/facts-file.ts +2 -1
  318. package/src/{hooks-settings.harness.mjs → hooks-settings.harness.ts} +39 -20
  319. package/src/hooks-settings.ts +20 -9
  320. package/src/init.test.ts +12 -9
  321. package/src/init.ts +22 -12
  322. package/src/{latex-log.harness.mjs → latex-log.harness.ts} +14 -14
  323. package/src/{latex-loop.harness.mjs → latex-loop.harness.ts} +64 -36
  324. package/src/latex-loop.ts +3 -3
  325. package/src/{link-skills.harness.mjs → link-skills.harness.ts} +19 -19
  326. package/src/link-skills.test.ts +3 -3
  327. package/src/link-skills.ts +5 -4
  328. package/src/lint-fix.test.ts +4 -6
  329. package/src/linted-set.test.ts +2 -2
  330. package/src/new-paper.harness.mjs +2 -2
  331. package/src/new-paper.test.ts +8 -10
  332. package/src/new-paper.ts +2 -2
  333. package/src/paper-files.test.ts +3 -5
  334. package/src/paper-settings-commands.test.ts +5 -4
  335. package/src/paper-settings.test.ts +5 -5
  336. package/src/paper-settings.ts +8 -9
  337. package/src/{pdf-facts.harness.mjs → pdf-facts.harness.ts} +9 -8
  338. package/src/pdf-facts.test.ts +10 -11
  339. package/src/pdf-facts.ts +2 -1
  340. package/src/{pdf-geometry.harness.mjs → pdf-geometry.harness.ts} +19 -12
  341. package/src/pdf-geometry.ts +3 -1
  342. package/src/presets.ts +3 -2
  343. package/src/references.test.ts +51 -43
  344. package/src/references.ts +14 -7
  345. package/src/{rules-config.harness.mjs → rules-config.harness.ts} +7 -13
  346. package/src/rules-config.ts +7 -4
  347. package/src/rules-off.test.ts +6 -4
  348. package/src/{structure.harness.mjs → structure.harness.ts} +26 -15
  349. package/src/structure.ts +1 -1
  350. package/src/{tex-requirements.harness.mjs → tex-requirements.harness.ts} +50 -22
  351. package/src/tex-requirements.ts +8 -5
  352. package/src/toolchain.harness.mjs +2 -2
  353. package/src/toolchain.test.ts +1 -1
  354. package/src/toolchain.ts +31 -17
  355. package/src/venue-rules.test.ts +62 -64
  356. package/src/venue-rules.ts +1 -1
  357. package/tsconfig.json +6 -3
  358. package/tsconfig.pkg.json +10 -0
  359. package/lib/check.d.mts +0 -17
  360. package/lib/paper-config.d.mts +0 -31
  361. package/scripts/layer-legacy-frozen.d.mts +0 -36
  362. package/scripts/rules-are-content-only.harness.mjs +0 -105
  363. package/scripts/rules-are-content-only.mjs +0 -148
  364. package/scripts/rules-are-content-only.test.mjs +0 -61
  365. package/scripts/test.mjs +0 -44
  366. package/scripts/test.test.mjs +0 -52
  367. /package/bin/{paperlint.test.mjs → paperlint.test.ts} +0 -0
  368. /package/lib/{skill-eval-fixture.mjs → skill-eval-fixture.ts} +0 -0
  369. /package/skills/grade-paper-writing/__snapshots__/{prose-lint.test.mjs.snap → prose-lint.test.ts.snap} +0 -0
  370. /package/skills/osf-artifact-upload/{osf-artifact-upload.harness.mjs → osf-artifact-upload.harness.ts} +0 -0
  371. /package/skills/tighten-paper/__snapshots__/{structure.test.mjs.snap → structure.test.ts.snap} +0 -0
@@ -35,29 +35,15 @@ import { sleep, todayUtc } from "./clock.io.ts";
35
35
 
36
36
  /** Citations looked up at once (#107). */
37
37
  const LOOKUPS_IN_FLIGHT = 6;
38
- // @ts-expect-error — a skill script in .mjs, it has no types
39
38
  import * as cites from "../../../skills/verify-citations/scripts/verify-cites.mjs";
40
- // @ts-expect-error — a skill script in .mjs, it has no types
39
+ import type { CiteVerdict } from "../../../skills/verify-citations/scripts/verify-cites.mjs";
41
40
  import * as authors from "../../../skills/verify-citations/scripts/bib-authors.mjs";
42
-
43
- interface CiteResult {
44
- readonly id: string;
45
- readonly verdict: "true" | "false" | "unresolvable";
46
- readonly reason?: string;
47
- /** "<service>: <reason>" for each question a refusing service did not answer (#120). */
48
- readonly refused?: readonly string[];
49
- }
50
- interface AuthorFinding {
51
- readonly key: string;
52
- readonly venue: string;
53
- readonly missing: readonly string[];
54
- readonly extra: readonly string[];
55
- readonly orderDiffers: boolean;
56
- }
57
- interface KeyWhy {
58
- readonly key: string;
59
- readonly why: string;
60
- }
41
+ import type {
42
+ AuthorBuckets,
43
+ AuthorFinding,
44
+ BibEntry,
45
+ } from "../../../skills/verify-citations/scripts/bib-authors.mjs";
46
+ import { messageOf } from "../../domain/text.ts";
61
47
 
62
48
  const describeAuthors = (f: AuthorFinding): string =>
63
49
  [
@@ -68,13 +54,6 @@ const describeAuthors = (f: AuthorFinding): string =>
68
54
  .filter(Boolean)
69
55
  .join("; ") + ` (DBLP: ${f.venue})`;
70
56
 
71
- interface AuthorBuckets {
72
- readonly findings: readonly AuthorFinding[];
73
- readonly skipped: readonly KeyWhy[];
74
- readonly unchecked: readonly KeyWhy[];
75
- readonly matched: readonly string[];
76
- }
77
-
78
57
  const authorsOf = (key: string, a: AuthorBuckets): EntryVerdict["authors"] =>
79
58
  a.findings.some((f) => f.key === key)
80
59
  ? "mismatch"
@@ -90,7 +69,7 @@ const authorsOf = (key: string, a: AuthorBuckets): EntryVerdict["authors"] =>
90
69
  * confirmed work: a refusal after a confirmation changed nothing.
91
70
  */
92
71
  const unconfirmed = (
93
- c: CiteResult | undefined,
72
+ c: CiteVerdict | undefined,
94
73
  ): readonly (string | undefined)[] =>
95
74
  c && c.verdict !== "true"
96
75
  ? [c.reason, ...(c.refused ?? []).map((r) => `not asked: ${r}`)]
@@ -99,7 +78,7 @@ const unconfirmed = (
99
78
  /** One entry's verdict from the two checkers' answers. */
100
79
  function entryVerdict(
101
80
  key: string,
102
- found: readonly CiteResult[],
81
+ found: readonly CiteVerdict[],
103
82
  a: AuthorBuckets,
104
83
  ): EntryVerdict {
105
84
  const c = found.find((x) => x.id === key);
@@ -119,27 +98,21 @@ function entryVerdict(
119
98
  };
120
99
  }
121
100
 
122
- interface BibAuthorsEntry {
123
- readonly key: string;
124
- readonly title: string;
125
- readonly author: string;
126
- }
127
-
128
101
  /** Whether bib-authors will ask DBLP about this entry — the filter its `checkAuthors` applies. */
129
- const asksDblp = (e: BibAuthorsEntry): boolean =>
102
+ const asksDblp = (e: BibEntry): boolean =>
130
103
  Boolean(e.title && e.author) &&
131
- (authors.claimsPublished(e) as boolean) &&
132
- !(authors.truncated(e.author) as boolean);
104
+ authors.claimsPublished(e) &&
105
+ !authors.truncated(e.author);
133
106
 
134
107
  /** Is every question this bibliography would ask already answered in `cache`? */
135
108
  async function fullyCached(
136
- citations: readonly object[],
137
- entries: readonly BibAuthorsEntry[],
109
+ citations: readonly cites.Citation[],
110
+ entries: readonly BibEntry[],
138
111
  cache: LookupCache,
139
112
  store: Readonly<Record<string, unknown>>,
140
113
  ): Promise<boolean> {
141
114
  const asks = await Promise.all(
142
- citations.map((c) => cites.wouldAsk(c, store) as Promise<boolean>),
115
+ citations.map((c) => cites.wouldAsk(c, store)),
143
116
  );
144
117
  return (
145
118
  !asks.includes(true) &&
@@ -185,11 +158,11 @@ function cachedDblp(cache: LookupCache, today: () => string) {
185
158
  if (refused !== null)
186
159
  throw new Error(`DBLP refused earlier in this run (${refused})`);
187
160
  try {
188
- const hits = (await authors.dblpHits(title)) as DblpHit[];
161
+ const hits = await authors.dblpHits(title);
189
162
  dblp.set(dblpTitleKey(title), { fetched: today(), title, hits });
190
163
  return hits;
191
164
  } catch (e) {
192
- refused = (e as Error).message;
165
+ refused = messageOf(e);
193
166
  throw new Error(`DBLP refused earlier in this run (${refused})`);
194
167
  }
195
168
  },
@@ -234,10 +207,8 @@ export const referencesChecker =
234
207
  async (bib, cache) => {
235
208
  // Answers past MAX_AGE_DAYS are left out, so the run asks them again (and `grown` re-dates them).
236
209
  const usable = freshPart(cache, today());
237
- const citations = (cites.parseBib(bib) as { id?: string }[]).filter(
238
- (c) => c.id,
239
- );
240
- const parsed = authors.parseBib(bib) as BibAuthorsEntry[];
210
+ const citations = cites.parseBib(bib);
211
+ const parsed = authors.parseBib(bib);
241
212
  const store: Record<string, unknown> = Object.fromEntries(
242
213
  [...usable.citations].map(([k, v]) => [k, v.response]),
243
214
  );
@@ -252,22 +223,19 @@ export const referencesChecker =
252
223
  // answer.
253
224
  // One breaker for the run: a service that refuses is not asked again, not once per citation
254
225
  // (#120). Requests already in flight when it starts refusing still land — at most six.
255
- const breaker = cites.createBreaker() as unknown;
226
+ const breaker = cites.createBreaker();
256
227
  const d = cachedDblp(usable, today);
257
228
  const [found, a] = await Promise.all([
258
- mapLimit(
259
- citations,
260
- LOOKUPS_IN_FLIGHT,
261
- (c) =>
262
- cites.verifyCitationLive(c, {
263
- cache: store,
264
- breaker,
265
- }) as Promise<CiteResult>,
229
+ mapLimit(citations, LOOKUPS_IN_FLIGHT, (c) =>
230
+ cites.verifyCitationLive(c, {
231
+ cache: store,
232
+ breaker,
233
+ }),
266
234
  ),
267
235
  authors.checkAuthors(parsed, {
268
236
  lookup: d.lookup,
269
237
  pause: d.pause,
270
- }) as Promise<AuthorBuckets>,
238
+ }),
271
239
  ]);
272
240
  const keys = new Set([
273
241
  ...found.map((c) => c.id),
@@ -10,12 +10,10 @@ export async function mapLimit<T, R>(
10
10
  fn: (item: T) => Promise<R>,
11
11
  ): Promise<R[]> {
12
12
  const out: R[] = new Array<R>(items.length);
13
- let next = 0;
13
+ // ONE iterator shared by every worker: each `next()` hands out the next index exactly once.
14
+ const queue = items.entries();
14
15
  const worker = async (): Promise<void> => {
15
- while (next < items.length) {
16
- const i = next++;
17
- out[i] = await fn(items[i] as T);
18
- }
16
+ for (const [i, item] of queue) out[i] = await fn(item);
19
17
  };
20
18
  await Promise.all(
21
19
  Array.from({ length: Math.min(limit, items.length) }, worker),
@@ -1,3 +1,4 @@
1
+ import { messageOf } from "../../domain/text.ts";
1
2
  /** Whether the citation services answer at all — the one request that decides "not checked". */
2
3
  export async function unreachable(): Promise<string | null> {
3
4
  try {
@@ -7,6 +8,6 @@ export async function unreachable(): Promise<string | null> {
7
8
  });
8
9
  return null;
9
10
  } catch (e) {
10
- return `the citation services cannot be reached (${(e as Error).message})`;
11
+ return `the citation services cannot be reached (${messageOf(e)})`;
11
12
  }
12
13
  }
@@ -19,7 +19,7 @@ import {
19
19
  import { tmpdir } from "node:os";
20
20
  import { basename, delimiter, dirname, join } from "node:path";
21
21
  import { fileURLToPath } from "node:url";
22
- import { createChecker } from "../lib/check.mjs";
22
+ import { createChecker } from "../lib/check.ts";
23
23
 
24
24
  const HERE = dirname(fileURLToPath(import.meta.url));
25
25
  const E = await import(join(HERE, "build-engine.ts"));
@@ -7,7 +7,7 @@ import assert from "node:assert/strict";
7
7
  import { chmodSync, mkdirSync, writeFileSync } from "node:fs";
8
8
  import { dirname, join } from "node:path";
9
9
  import { test } from "vitest";
10
- import { useTempDir } from "../test/support.mjs";
10
+ import { useTempDir } from "../test/support.ts";
11
11
  import { prepareEngine, refusal } from "./build-engine.ts";
12
12
 
13
13
  const work = useTempDir("paperlint-build-engine-test-");
@@ -34,7 +34,7 @@ async function go(o: Parameters<typeof prepareEngine>[0]) {
34
34
  err: (l) => err.push(l),
35
35
  platform: "linux",
36
36
  interactive: true,
37
- ask: async () => "y",
37
+ ask: () => Promise.resolve("y"),
38
38
  ...o,
39
39
  });
40
40
  return { r, out, err };
@@ -71,7 +71,7 @@ function withDefaults(o: EngineOptions): Resolved {
71
71
  const r = {
72
72
  dryRun: false,
73
73
  interactive: false,
74
- ask: async () => "",
74
+ ask: () => Promise.resolve(""),
75
75
  log: console.log,
76
76
  err: console.error,
77
77
  // eslint-disable-next-line no-restricted-globals -- legacy I/O, moves behind a port in #76
@@ -130,7 +130,7 @@ export function gatherFacts(o: Resolved): EngineFacts {
130
130
  }
131
131
 
132
132
  const names = (missing: readonly string[]): string =>
133
- `${missing.length} package(s): ${missing.join(", ")}`;
133
+ `${String(missing.length)} package(s): ${missing.join(", ")}`;
134
134
 
135
135
  /** The one line a run without a human gets. It names the command and what is missing. */
136
136
  export function refusal(d: EngineDecision, facts: EngineFacts): string {
@@ -4,7 +4,7 @@
4
4
  * The process runner is replaced by a fake that writes what pdflatex and bibtex would write, so
5
5
  * these assertions check the SHELL's decisions: what is run, with which environment, in which
6
6
  * order, and what is left on disk. Whether a real pdflatex produces a real PDF is the other half,
7
- * `test/e2e/build.mjs`.
7
+ * `test/e2e/build.ts`.
8
8
  *
9
9
  * 🔴 THE TWO THINGS PINNED DOWN HERE THAT A RETURNED OBJECT CANNOT SHOW: a paper-supplied
10
10
  * `build.sh` is never executed (checked by the trace it would leave on disk and by the list of
@@ -22,7 +22,7 @@ import {
22
22
  import { tmpdir } from "node:os";
23
23
  import { join, dirname, delimiter } from "node:path";
24
24
  import { fileURLToPath } from "node:url";
25
- import { createChecker } from "../lib/check.mjs";
25
+ import { createChecker } from "../lib/check.ts";
26
26
 
27
27
  const HERE = dirname(fileURLToPath(import.meta.url));
28
28
  const {
package/src/build.test.ts CHANGED
@@ -8,7 +8,7 @@ import assert from "node:assert/strict";
8
8
  import { existsSync, writeFileSync } from "node:fs";
9
9
  import { join } from "node:path";
10
10
  import { test } from "vitest";
11
- import { useTempDir, writeTree } from "../test/support.mjs";
11
+ import { useTempDir, writeTree } from "../test/support.ts";
12
12
  import {
13
13
  bibInput,
14
14
  buildPaper,
@@ -62,7 +62,7 @@ function bibtexRun(f: Fake, cwd: string) {
62
62
  ? { status: f.bibtex }
63
63
  : { status: f.bibtex, stdout: f.bibtexOut };
64
64
  }
65
- function fakeRun(f: Fake): BuildOptions["run"] {
65
+ function fakeRun(f: Fake): NonNullable<BuildOptions["run"]> {
66
66
  let pass = 0;
67
67
  return ((bin: string, _args: string[], opts: { cwd: string }) => {
68
68
  if (bin === f.missing)
@@ -103,18 +103,19 @@ const page = (words: number, numbered = 0) => ({
103
103
  });
104
104
  const reader =
105
105
  (last = page(80)): PdfReader =>
106
- async () => ({
107
- ok: true,
108
- facts: {
109
- pages: 1,
110
- fonts: {
111
- kind: "drawn",
112
- list: [{ kind: "embedded", name: "CMR10", program: "Type1" }],
106
+ () =>
107
+ Promise.resolve({
108
+ ok: true,
109
+ facts: {
110
+ pages: 1,
111
+ fonts: {
112
+ kind: "drawn",
113
+ list: [{ kind: "embedded", name: "CMR10", program: "Type1" }],
114
+ },
115
+ last,
116
+ layout: [],
113
117
  },
114
- last,
115
- layout: [],
116
- },
117
- });
118
+ });
118
119
  const quiet = () => {};
119
120
  /** buildPaper with fakes; the verdict line is what the command would print for it. */
120
121
  async function build(dir: string, f: Fake = {}, over: BuildOptions = {}) {
@@ -332,7 +333,7 @@ test("paths: a paper that IS the working directory is named by its full path", a
332
333
  const run = await buildPapers([dir], {
333
334
  cwd: dir,
334
335
  log: (l) => lines.push(l),
335
- engine: async () => null,
336
+ engine: () => Promise.resolve(null),
336
337
  });
337
338
  assert.deepEqual(
338
339
  [run, lines],
package/src/build.ts CHANGED
@@ -45,7 +45,7 @@ import { delimiter, join, relative } from "node:path";
45
45
  // eslint-disable-next-line boundaries/dependencies -- legacy layer, moves behind a port in #76
46
46
  import { getParser } from "@unified-latex/unified-latex-util-parse";
47
47
  import { packageVenuesDir } from "../skills/paper-pipeline/scripts/consumer.mjs";
48
- import { CONFIG_FILE } from "../lib/paper-config.mjs";
48
+ import { CONFIG_FILE } from "#lib/paper-config";
49
49
  import {
50
50
  declaredVenue,
51
51
  factsPath,
@@ -83,6 +83,10 @@ import {
83
83
  type Step,
84
84
  } from "./latex-loop.ts";
85
85
  import type { BuildResult, PlanLine } from "./types.ts";
86
+ import { messageOf, printed } from "./domain/text.ts";
87
+
88
+ /** stdin closed, stdout and stderr captured — the tuple type spawnSync's `stdio` wants. */
89
+ const PIPED: ["ignore", "pipe", "pipe"] = ["ignore", "pipe", "pipe"];
86
90
 
87
91
  /** A directory counts as a paper by the same markers as `structure.ts` — one shared dictionary. */
88
92
  export const PAPER_MARKERS = [
@@ -337,7 +341,7 @@ function spawnOptions(ctx: BuildContext) {
337
341
  return {
338
342
  cwd: ctx.paperDir,
339
343
  env: ctx.env,
340
- stdio: ["ignore", "pipe", "pipe"] as ["ignore", "pipe", "pipe"],
344
+ stdio: PIPED,
341
345
  encoding: "latin1" as const,
342
346
  maxBuffer: 64 * 1024 * 1024,
343
347
  };
@@ -376,19 +380,23 @@ function latexPass(
376
380
  exitCode === 0
377
381
  ? []
378
382
  : written === null
379
- ? printed(r)
383
+ ? lastPrinted(r)
380
384
  : errorExcerpt(log).map(fromLatin1),
381
385
  };
382
386
  }
383
387
 
388
+ /** The two streams of a finished run, as they really arrive (see `printed`). */
389
+ interface Streams {
390
+ readonly stdout: string | undefined;
391
+ readonly stderr: string | undefined;
392
+ }
393
+
384
394
  /**
385
395
  * The last lines pdflatex printed, for the run that wrote no log — it died before opening one (a
386
396
  * format it cannot load, a missing TeX Live file). Marked by NO_LOG, which the report keys on.
387
397
  */
388
- function printed(r: { stdout?: unknown; stderr?: unknown }): string[] {
389
- const lines = fromLatin1(
390
- `${String(r.stdout ?? "")}\n${String(r.stderr ?? "")}`,
391
- )
398
+ function lastPrinted(r: Streams): string[] {
399
+ const lines = fromLatin1(`${printed(r.stdout)}\n${printed(r.stderr)}`)
392
400
  .split("\n")
393
401
  .filter((l) => l.trim());
394
402
  return [NO_LOG, ...lines.slice(-8).map((l) => ` ${l}`)];
@@ -410,7 +418,7 @@ function bibtexPass(ctx: BuildContext, opts: SpawnOptions): Observation | null {
410
418
  after: hashes(ctx.paperDir),
411
419
  bib,
412
420
  errorLines:
413
- exitCode === 0 ? [] : bibtexExcerpt(fromLatin1(String(r.stdout ?? ""))),
421
+ exitCode === 0 ? [] : bibtexExcerpt(fromLatin1(printed(r.stdout))),
414
422
  };
415
423
  }
416
424
 
@@ -443,7 +451,7 @@ export function compile(ctx: BuildContext): {
443
451
  const NO_PDF = `pdflatex exited 0 but wrote no ${JOB}.pdf — does the document have any pages?`;
444
452
 
445
453
  const plural = (n: number, one: string, many: string): string =>
446
- `${n} ${n === 1 ? one : many}`;
454
+ `${String(n)} ${n === 1 ? one : many}`;
447
455
 
448
456
  export const compileStep: BuildStep = {
449
457
  name: "compile",
@@ -467,7 +475,7 @@ export const compileStep: BuildStep = {
467
475
  const bin = end.step === "latex" ? "pdflatex" : "bibtex";
468
476
  const where =
469
477
  end.cause.kind === "exit"
470
- ? `${bin} exited with ${end.cause.code}`
478
+ ? `${bin} exited with ${String(end.cause.code)}`
471
479
  : `${bin} did not converge`;
472
480
  const log = join(
473
481
  ctx.paperDir,
@@ -669,13 +677,14 @@ function baseDefaults({
669
677
  }
670
678
 
671
679
  /** Without a checker the record says so — never a pass. The CLI wires the real one. */
672
- const notWired: CheckReferences = async (_bib, cache) => ({
673
- check: {
674
- kind: "not-checked",
675
- why: "no reference checker was wired into this build",
676
- },
677
- cache,
678
- });
680
+ const notWired: CheckReferences = (_bib, cache) =>
681
+ Promise.resolve({
682
+ check: {
683
+ kind: "not-checked",
684
+ why: "no reference checker was wired into this build",
685
+ },
686
+ cache,
687
+ });
679
688
 
680
689
  /** banal as the measurer, wired from the build's environment: the one piece of root work left here (#76). */
681
690
  function defaultMeasurer(
@@ -762,7 +771,7 @@ export async function buildPaper(
762
771
  dir,
763
772
  status: "failed",
764
773
  plan: [],
765
- failure: { step: "facts", lines: [(e as Error).message] },
774
+ failure: { step: "facts", lines: [messageOf(e)] },
766
775
  };
767
776
  }
768
777
  for (const s of facts.ignoredScripts)
@@ -853,7 +862,7 @@ export function formatResult(r: BuildResult): string {
853
862
  function formatFailure(r: BuildResult): string {
854
863
  const [head, ...rest] = r.failure?.lines ?? ["failed"];
855
864
  return [
856
- ` ✗ ${r.failure?.step ?? "build"}: ${head}`,
865
+ ` ✗ ${r.failure?.step ?? "build"}: ${String(head)}`,
857
866
  ...rest.map((l) => ` ${l}`),
858
867
  ` ${PDF_REMOVED}`,
859
868
  ].join("\n");
@@ -28,8 +28,8 @@ import { spawnSync } from "node:child_process";
28
28
  import { tmpdir } from "node:os";
29
29
  import { join, dirname } from "node:path";
30
30
  import { fileURLToPath } from "node:url";
31
- import { PAPERS_DIR_FIELD, findProjectRoot } from "../lib/paper-config.mjs";
32
- import { createChecker } from "../lib/check.mjs";
31
+ import { PAPERS_DIR_FIELD, findProjectRoot } from "../lib/paper-config.ts";
32
+ import { createChecker } from "../lib/check.ts";
33
33
 
34
34
  const HERE = dirname(fileURLToPath(import.meta.url));
35
35
  const { run, parseArgs, buildConfig, nextSteps, toPaths, runHook } =
@@ -635,7 +635,7 @@ check(
635
635
 
636
636
  // ── 7-bis. THE SKILLS: WHAT WAS LINKED, AND WHAT WAS LEFT ALONE, BY NAME ────────────
637
637
  //
638
- // The links themselves are `link-skills.harness.mjs`'s subject. Here: init REPORTS them, and
638
+ // The links themselves are `link-skills.harness.ts`'s subject. Here: init REPORTS them, and
639
639
  // a name it refused to take does not turn a working install red. The state is handed in so
640
640
  // this block does not depend on a package being installed next to the temp project.
641
641
  {
@@ -967,7 +967,7 @@ check(
967
967
 
968
968
  // ── STRUCTURE GETS THROUGH TO THE COMMAND ──────────────────────────────────────────────
969
969
  //
970
- // `structure.mjs` is checked separately and in full (`structure.harness.mjs`). Here — exactly
970
+ // `structure.mjs` is checked separately and in full (`structure.harness.ts`). Here — exactly
971
971
  // one fact that harness cannot know: that the module is WIRED IN. A correct module forgotten in
972
972
  // `run()` gives zero findings and looks like a clean corpus.
973
973
  {
@@ -1148,7 +1148,7 @@ check(
1148
1148
  // pnpm: node_modules/vigiles/dist/cli.js DOES NOT
1149
1149
  // The old wiring addressed the runtime from the project root and did not resolve under pnpm,
1150
1150
  // and `|| exit 2` on PreToolUse(Bash) turned that into a block on ANY command. The end-to-end
1151
- // half (both installs, real processes) lives in `test/e2e/install.mjs`; here — the verdicts.
1151
+ // half (both installs, real processes) lives in `test/e2e/install.ts`; here — the verdicts.
1152
1152
  {
1153
1153
  const calls = [];
1154
1154
  const fake = (code) => (bin, args, opts) => {
@@ -1258,7 +1258,7 @@ console.log(
1258
1258
 
1259
1259
  // ─────────────────────────────────────────────────────────────────────────────
1260
1260
  // What is left after init is typed in THE SAME TERMINAL. The two `/plugin` lines are gone: the
1261
- // hooks are written into `.claude/settings.json` by init itself (hooks-settings.harness.mjs).
1261
+ // hooks are written into `.claude/settings.json` by init itself (hooks-settings.harness.ts).
1262
1262
 
1263
1263
  {
1264
1264
  const steps = nextSteps("papers");
package/src/cli.test.ts CHANGED
@@ -9,7 +9,7 @@ import { spawn } from "node:child_process";
9
9
  import { existsSync } from "node:fs";
10
10
  import { dirname, join } from "node:path";
11
11
  import { test } from "vitest";
12
- import { runNode, useTempDir, writeTree } from "../test/support.mjs";
12
+ import { runNode, useTempDir, writeTree } from "../test/support.ts";
13
13
  import {
14
14
  chooseVenue,
15
15
  initTexLive,
@@ -169,7 +169,12 @@ test("chooseVenue: a preset by path (inside and outside the paper), by prefixed
169
169
  const choose = (venue: string) =>
170
170
  chooseVenue(
171
171
  { venue, kind: null },
172
- { paperDir, cwd: dir, interactive: false, ask: async () => "" },
172
+ {
173
+ paperDir,
174
+ cwd: dir,
175
+ interactive: false,
176
+ ask: () => Promise.resolve(""),
177
+ },
173
178
  );
174
179
  const results = await Promise.all([
175
180
  choose("./papers/p/mine.jsonc"),
@@ -354,11 +359,11 @@ test("a paper's paperlint.json that does not parse stops the lint with its path"
354
359
  });
355
360
  const r = paperRuleBlocks([join(dir, "p")]);
356
361
  assert.equal(r.ok, false);
357
- assert.match(!r.ok ? r.error : "", /^.*rules-broken\/p\/paperlint\.json: /);
362
+ assert.match(r.error, /^.*rules-broken\/p\/paperlint\.json: /);
358
363
  });
359
364
 
360
365
  test("silentOptionalRules: a config with no rules turns nothing on", async () => {
361
- assert.deepEqual(await silentOptionalRules({} as never, [], {} as never), []);
366
+ assert.deepEqual(await silentOptionalRules({} as never, [], {}), []);
362
367
  });
363
368
 
364
369
  test("init with no path and --format md sets up the current directory", async () => {
@@ -493,7 +498,9 @@ function newAtTerminal(cwd: string, answers: Record<string, string>) {
493
498
  child.stdin.write(answer);
494
499
  }
495
500
  });
496
- child.on("close", (status) => done({ status, out }));
501
+ child.on("close", (status) => {
502
+ done({ status, out });
503
+ });
497
504
  });
498
505
  }
499
506
 
@@ -563,7 +570,7 @@ test("lint with its LaTeX language missing from the install still lints the mark
563
570
  "papers/p/paper.md": "# P\n\nSome prose.\n",
564
571
  "no-latex.mjs":
565
572
  "import { register } from 'node:module';\n" +
566
- "register('data:text/javascript,' + encodeURIComponent(\"export async function resolve(s, c, next) { if (s.endsWith('latex-language.mjs')) throw Object.assign(new Error('gone'), { code: 'ERR_MODULE_NOT_FOUND' }); return next(s, c); }\"));\n",
573
+ "register('data:text/javascript,' + encodeURIComponent(\"export async function resolve(s, c, next) { if (s === '#eslint-rules/latex-language') throw Object.assign(new Error('gone'), { code: 'ERR_MODULE_NOT_FOUND' }); return next(s, c); }\"));\n",
567
574
  });
568
575
  const without = runNode(BIN, ["lint", "papers"], {
569
576
  cwd: dir,