paperlint 3.1.3 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (527) hide show
  1. package/.github/workflows/ci.yml +12 -7
  2. package/CLAUDE.md +5 -5
  3. package/CONTRIBUTING.md +34 -5
  4. package/dist/adapters/banal/failure.d.ts +1 -7
  5. package/dist/adapters/banal/failure.d.ts.map +1 -1
  6. package/dist/adapters/banal/failure.js +5 -7
  7. package/dist/adapters/banal/failure.js.map +1 -1
  8. package/dist/adapters/banal/index.d.ts.map +1 -1
  9. package/dist/adapters/banal/index.js +4 -3
  10. package/dist/adapters/banal/index.js.map +1 -1
  11. package/dist/adapters/banal/install.d.ts.map +1 -1
  12. package/dist/adapters/banal/install.js +4 -3
  13. package/dist/adapters/banal/install.js.map +1 -1
  14. package/dist/adapters/banal/invocation.d.ts +10 -5
  15. package/dist/adapters/banal/invocation.d.ts.map +1 -1
  16. package/dist/adapters/banal/invocation.js +13 -1
  17. package/dist/adapters/banal/invocation.js.map +1 -1
  18. package/dist/adapters/banal/locate.d.ts +12 -9
  19. package/dist/adapters/banal/locate.d.ts.map +1 -1
  20. package/dist/adapters/banal/locate.js +19 -12
  21. package/dist/adapters/banal/locate.js.map +1 -1
  22. package/dist/adapters/banal/run.d.ts +10 -1
  23. package/dist/adapters/banal/run.d.ts.map +1 -1
  24. package/dist/adapters/banal/run.js +8 -4
  25. package/dist/adapters/banal/run.js.map +1 -1
  26. package/dist/adapters/banal/settings.d.ts +1 -1
  27. package/dist/adapters/banal/settings.d.ts.map +1 -1
  28. package/dist/adapters/banal/settings.js +2 -1
  29. package/dist/adapters/banal/settings.js.map +1 -1
  30. package/dist/adapters/memory/index.d.ts.map +1 -1
  31. package/dist/adapters/memory/index.js +8 -2
  32. package/dist/adapters/memory/index.js.map +1 -1
  33. package/dist/adapters/node/files.io.d.ts.map +1 -1
  34. package/dist/adapters/node/files.io.js +2 -1
  35. package/dist/adapters/node/files.io.js.map +1 -1
  36. package/dist/adapters/node/process.io.d.ts +5 -7
  37. package/dist/adapters/node/process.io.d.ts.map +1 -1
  38. package/dist/adapters/node/process.io.js +4 -3
  39. package/dist/adapters/node/process.io.js.map +1 -1
  40. package/dist/adapters/node/workspace.io.d.ts.map +1 -1
  41. package/dist/adapters/node/workspace.io.js +4 -2
  42. package/dist/adapters/node/workspace.io.js.map +1 -1
  43. package/dist/adapters/pdfjs/fill.d.ts.map +1 -1
  44. package/dist/adapters/pdfjs/fill.js +13 -7
  45. package/dist/adapters/pdfjs/fill.js.map +1 -1
  46. package/dist/adapters/references/index.d.ts.map +1 -1
  47. package/dist/adapters/references/index.js +8 -7
  48. package/dist/adapters/references/index.js.map +1 -1
  49. package/dist/adapters/references/pool.d.ts.map +1 -1
  50. package/dist/adapters/references/pool.js +4 -5
  51. package/dist/adapters/references/pool.js.map +1 -1
  52. package/dist/adapters/references/reach.io.d.ts.map +1 -1
  53. package/dist/adapters/references/reach.io.js +2 -1
  54. package/dist/adapters/references/reach.io.js.map +1 -1
  55. package/dist/build-engine.d.ts +1 -1
  56. package/dist/build-engine.d.ts.map +1 -1
  57. package/dist/build-engine.js +10 -3
  58. package/dist/build-engine.js.map +1 -1
  59. package/dist/build.d.ts +2 -3
  60. package/dist/build.d.ts.map +1 -1
  61. package/dist/build.js +19 -17
  62. package/dist/build.js.map +1 -1
  63. package/dist/caller-path.d.ts +3 -0
  64. package/dist/caller-path.d.ts.map +1 -0
  65. package/dist/caller-path.js +13 -0
  66. package/dist/caller-path.js.map +1 -0
  67. package/dist/cli.d.ts +10 -17
  68. package/dist/cli.d.ts.map +1 -1
  69. package/dist/cli.js +93 -46
  70. package/dist/cli.js.map +1 -1
  71. package/dist/doctor.d.ts +12 -3
  72. package/dist/doctor.d.ts.map +1 -1
  73. package/dist/doctor.js +5 -3
  74. package/dist/doctor.js.map +1 -1
  75. package/dist/domain/lookup-cache.d.ts.map +1 -1
  76. package/dist/domain/lookup-cache.js +10 -8
  77. package/dist/domain/lookup-cache.js.map +1 -1
  78. package/dist/domain/paths.d.ts +8 -2
  79. package/dist/domain/paths.d.ts.map +1 -1
  80. package/dist/domain/paths.js +12 -1
  81. package/dist/domain/paths.js.map +1 -1
  82. package/dist/domain/ready.d.ts +24 -0
  83. package/dist/domain/ready.d.ts.map +1 -0
  84. package/dist/domain/ready.js +11 -0
  85. package/dist/domain/ready.js.map +1 -0
  86. package/dist/domain/record.d.ts +8 -0
  87. package/dist/domain/record.d.ts.map +1 -0
  88. package/dist/domain/record.js +8 -0
  89. package/dist/domain/record.js.map +1 -0
  90. package/dist/domain/sha256.d.ts.map +1 -1
  91. package/dist/domain/sha256.js +4 -2
  92. package/dist/domain/sha256.js.map +1 -1
  93. package/dist/domain/text.d.ts +12 -0
  94. package/dist/domain/text.d.ts.map +1 -1
  95. package/dist/domain/text.js +17 -0
  96. package/dist/domain/text.js.map +1 -1
  97. package/dist/engine.d.ts +23 -22
  98. package/dist/engine.d.ts.map +1 -1
  99. package/dist/engine.js +4 -3
  100. package/dist/engine.js.map +1 -1
  101. package/dist/eslint-rules/bib-reachable-entry.d.ts +22 -0
  102. package/dist/eslint-rules/bib-reachable-entry.d.ts.map +1 -0
  103. package/dist/eslint-rules/bib-reachable-entry.js +75 -0
  104. package/dist/eslint-rules/bib-reachable-entry.js.map +1 -0
  105. package/dist/eslint-rules/install-path-literals.d.ts +80 -0
  106. package/dist/eslint-rules/install-path-literals.d.ts.map +1 -0
  107. package/dist/eslint-rules/install-path-literals.js +105 -0
  108. package/dist/eslint-rules/install-path-literals.js.map +1 -0
  109. package/dist/eslint-rules/latex-language.d.ts +136 -0
  110. package/dist/eslint-rules/latex-language.d.ts.map +1 -0
  111. package/dist/eslint-rules/latex-language.js +639 -0
  112. package/dist/eslint-rules/latex-language.js.map +1 -0
  113. package/dist/eslint-rules/paper-research-question.d.ts +31 -0
  114. package/dist/eslint-rules/paper-research-question.d.ts.map +1 -0
  115. package/dist/eslint-rules/paper-research-question.js +188 -0
  116. package/dist/eslint-rules/paper-research-question.js.map +1 -0
  117. package/dist/eslint-rules/paper-stages.d.ts +83 -0
  118. package/dist/eslint-rules/paper-stages.d.ts.map +1 -0
  119. package/dist/eslint-rules/paper-stages.js +358 -0
  120. package/dist/eslint-rules/paper-stages.js.map +1 -0
  121. package/dist/eslint-rules/paper-typography.d.ts +74 -0
  122. package/dist/eslint-rules/paper-typography.d.ts.map +1 -0
  123. package/dist/eslint-rules/paper-typography.js +404 -0
  124. package/dist/eslint-rules/paper-typography.js.map +1 -0
  125. package/dist/eslint-rules/papers.d.ts +42 -0
  126. package/dist/eslint-rules/papers.d.ts.map +1 -0
  127. package/dist/eslint-rules/papers.js +145 -0
  128. package/dist/eslint-rules/papers.js.map +1 -0
  129. package/dist/eslint-rules/pdf-last-page-balance.d.ts +72 -0
  130. package/dist/eslint-rules/pdf-last-page-balance.d.ts.map +1 -0
  131. package/dist/eslint-rules/pdf-last-page-balance.js +237 -0
  132. package/dist/eslint-rules/pdf-last-page-balance.js.map +1 -0
  133. package/dist/eslint-rules/review-frontmatter.d.ts +57 -0
  134. package/dist/eslint-rules/review-frontmatter.d.ts.map +1 -0
  135. package/dist/eslint-rules/review-frontmatter.js +126 -0
  136. package/dist/eslint-rules/review-frontmatter.js.map +1 -0
  137. package/dist/eslint-rules/review-frontmatter.schema.json +36 -0
  138. package/dist/eslint-rules/rule-context.d.ts +55 -0
  139. package/dist/eslint-rules/rule-context.d.ts.map +1 -0
  140. package/dist/eslint-rules/rule-context.js +9 -0
  141. package/dist/eslint-rules/rule-context.js.map +1 -0
  142. package/dist/eslint-rules/sibling-frontmatter.d.ts +25 -0
  143. package/dist/eslint-rules/sibling-frontmatter.d.ts.map +1 -0
  144. package/dist/eslint-rules/sibling-frontmatter.js +16 -0
  145. package/dist/eslint-rules/sibling-frontmatter.js.map +1 -0
  146. package/dist/eslint-rules/sibling-frontmatter.schema.json +14 -0
  147. package/dist/eslint-rules/temp-root-realpath.d.ts +71 -0
  148. package/dist/eslint-rules/temp-root-realpath.d.ts.map +1 -0
  149. package/dist/eslint-rules/temp-root-realpath.js +139 -0
  150. package/dist/eslint-rules/temp-root-realpath.js.map +1 -0
  151. package/dist/eslint-rules/tex-build.d.ts +35 -0
  152. package/dist/eslint-rules/tex-build.d.ts.map +1 -0
  153. package/dist/eslint-rules/tex-build.js +313 -0
  154. package/dist/eslint-rules/tex-build.js.map +1 -0
  155. package/dist/facts-file.d.ts.map +1 -1
  156. package/dist/facts-file.js +31 -27
  157. package/dist/facts-file.js.map +1 -1
  158. package/dist/hooks-settings.d.ts +1 -1
  159. package/dist/hooks-settings.d.ts.map +1 -1
  160. package/dist/hooks-settings.js +31 -11
  161. package/dist/hooks-settings.js.map +1 -1
  162. package/dist/init.d.ts +8 -9
  163. package/dist/init.d.ts.map +1 -1
  164. package/dist/init.js +33 -15
  165. package/dist/init.js.map +1 -1
  166. package/dist/latex-loop.d.ts +2 -2
  167. package/dist/latex-loop.d.ts.map +1 -1
  168. package/dist/latex-loop.js +2 -2
  169. package/dist/latex-loop.js.map +1 -1
  170. package/dist/lib/agent-cli-version.d.ts +65 -0
  171. package/dist/lib/agent-cli-version.d.ts.map +1 -0
  172. package/dist/lib/agent-cli-version.js +77 -0
  173. package/dist/lib/agent-cli-version.js.map +1 -0
  174. package/dist/lib/check.d.ts +19 -0
  175. package/dist/lib/check.d.ts.map +1 -0
  176. package/dist/lib/check.js +52 -0
  177. package/dist/lib/check.js.map +1 -0
  178. package/dist/lib/markdown.d.ts +180 -0
  179. package/dist/lib/markdown.d.ts.map +1 -0
  180. package/dist/lib/markdown.js +302 -0
  181. package/dist/lib/markdown.js.map +1 -0
  182. package/dist/lib/paper-config.d.ts +84 -0
  183. package/dist/lib/paper-config.d.ts.map +1 -0
  184. package/dist/lib/paper-config.js +138 -0
  185. package/dist/lib/paper-config.js.map +1 -0
  186. package/dist/lib/skill-eval-fixture.d.ts +29 -0
  187. package/dist/lib/skill-eval-fixture.d.ts.map +1 -0
  188. package/dist/lib/skill-eval-fixture.js +62 -0
  189. package/dist/lib/skill-eval-fixture.js.map +1 -0
  190. package/dist/link-skills.d.ts.map +1 -1
  191. package/dist/link-skills.js +5 -4
  192. package/dist/link-skills.js.map +1 -1
  193. package/dist/new-paper.d.ts.map +1 -1
  194. package/dist/new-paper.js +7 -3
  195. package/dist/new-paper.js.map +1 -1
  196. package/dist/paper-files.d.ts +4 -4
  197. package/dist/paper-files.d.ts.map +1 -1
  198. package/dist/paper-files.js +6 -6
  199. package/dist/paper-files.js.map +1 -1
  200. package/dist/paper-settings.d.ts.map +1 -1
  201. package/dist/paper-settings.js +8 -7
  202. package/dist/paper-settings.js.map +1 -1
  203. package/dist/pdf-facts.d.ts +51 -1
  204. package/dist/pdf-facts.d.ts.map +1 -1
  205. package/dist/pdf-facts.js +25 -16
  206. package/dist/pdf-facts.js.map +1 -1
  207. package/dist/pdf-geometry.d.ts.map +1 -1
  208. package/dist/pdf-geometry.js +3 -4
  209. package/dist/pdf-geometry.js.map +1 -1
  210. package/dist/ports/tool-installer.d.ts +2 -14
  211. package/dist/ports/tool-installer.d.ts.map +1 -1
  212. package/dist/presets.d.ts.map +1 -1
  213. package/dist/presets.js +19 -6
  214. package/dist/presets.js.map +1 -1
  215. package/dist/references.d.ts.map +1 -1
  216. package/dist/references.js +15 -10
  217. package/dist/references.js.map +1 -1
  218. package/dist/rules-config.d.ts +26 -1
  219. package/dist/rules-config.d.ts.map +1 -1
  220. package/dist/rules-config.js +15 -12
  221. package/dist/rules-config.js.map +1 -1
  222. package/dist/structure.js +1 -1
  223. package/dist/structure.js.map +1 -1
  224. package/dist/tex-requirements.d.ts +4 -0
  225. package/dist/tex-requirements.d.ts.map +1 -1
  226. package/dist/tex-requirements.js +22 -5
  227. package/dist/tex-requirements.js.map +1 -1
  228. package/dist/toolchain.d.ts.map +1 -1
  229. package/dist/toolchain.js +21 -16
  230. package/dist/toolchain.js.map +1 -1
  231. package/dist/types.d.ts +5 -3
  232. package/dist/types.d.ts.map +1 -1
  233. package/dist/venue-rules.d.ts.map +1 -1
  234. package/dist/venue-rules.js +21 -8
  235. package/dist/venue-rules.js.map +1 -1
  236. package/docs/configuration.md +2 -2
  237. package/docs/e2e.md +7 -7
  238. package/docs/install.md +1 -1
  239. package/docs/prior-art/README.md +1 -1
  240. package/docs/prior-art/package-location.md +5 -5
  241. package/docs/prior-art/repro/README.md +1 -1
  242. package/docs/prior-art/test-tooling.md +2 -2
  243. package/docs/testing.md +11 -8
  244. package/docs/toolchain.md +1 -1
  245. package/eslint-rules/{bib-reachable-entry.mjs → bib-reachable-entry.ts} +5 -4
  246. package/eslint-rules/install-path-literals.harness.mjs +1 -1
  247. package/eslint-rules/{install-path-literals.mjs → install-path-literals.ts} +18 -10
  248. package/eslint-rules/latex-language.harness.mjs +2 -2
  249. package/eslint-rules/latex-language.test.mjs +7 -1
  250. package/eslint-rules/{latex-language.mjs → latex-language.ts} +297 -109
  251. package/eslint-rules/paper-research-question.harness.mjs +3 -3
  252. package/eslint-rules/{paper-research-question.mjs → paper-research-question.ts} +35 -16
  253. package/eslint-rules/paper-stages.harness.mjs +2 -2
  254. package/eslint-rules/paper-stages.test.mjs +8 -2
  255. package/eslint-rules/{paper-stages.mjs → paper-stages.ts} +76 -31
  256. package/eslint-rules/paper-typography.test.mjs +3 -3
  257. package/eslint-rules/{paper-typography.mjs → paper-typography.ts} +134 -56
  258. package/eslint-rules/papers.harness.mjs +2 -2
  259. package/eslint-rules/{papers.mjs → papers.ts} +7 -4
  260. package/eslint-rules/pdf-last-page-balance.harness.mjs +3 -3
  261. package/eslint-rules/{pdf-last-page-balance.mjs → pdf-last-page-balance.ts} +89 -32
  262. package/eslint-rules/review-frontmatter.test.mjs +2 -2
  263. package/eslint-rules/{review-frontmatter.mjs → review-frontmatter.ts} +38 -16
  264. package/eslint-rules/rule-context.ts +62 -0
  265. package/eslint-rules/{sibling-frontmatter.mjs → sibling-frontmatter.ts} +1 -1
  266. package/eslint-rules/temp-root-realpath.harness.mjs +1 -1
  267. package/eslint-rules/{temp-root-realpath.mjs → temp-root-realpath.ts} +20 -7
  268. package/eslint-rules/tex-build.harness.mjs +2 -2
  269. package/eslint-rules/{tex-build.mjs → tex-build.ts} +6 -5
  270. package/eslint.config.mjs +146 -30
  271. package/fixtures/install-path-literals/clean.fixture.mjs +1 -1
  272. package/fixtures/install-path-literals/clean.md +2 -2
  273. package/fixtures/install-path-literals/defect.fixture.mjs +1 -1
  274. package/fixtures/install-path-literals/defect.md +2 -2
  275. package/fixtures/pdf-facts/README.md +2 -2
  276. package/fixtures/real-markdown-paper/{baseline.mjs → baseline.ts} +31 -10
  277. package/hooks/{hooks.harness.mjs → hooks.harness.ts} +51 -34
  278. package/hooks/paper-edit-guard.hook.mjs +1 -1
  279. package/hooks/{paper-edit-guard.test.mjs → paper-edit-guard.test.ts} +3 -7
  280. package/hooks/paper-skills-nudge.hook.mjs +1 -1
  281. package/hooks/{paper-skills-nudge.test.mjs → paper-skills-nudge.test.ts} +2 -6
  282. package/hooks/paper-status-gates.sh +9 -19
  283. package/hooks/{paper-status-gates.test.mjs → paper-status-gates.test.ts} +2 -6
  284. package/lib/agent-cli-version.harness.mjs +1 -1
  285. package/lib/{agent-cli-version.mjs → agent-cli-version.ts} +32 -18
  286. package/lib/check.test.ts +14 -9
  287. package/lib/{check.mjs → check.ts} +22 -9
  288. package/lib/markdown.test.mjs +7 -7
  289. package/lib/{markdown.mjs → markdown.ts} +68 -29
  290. package/lib/paper-config.harness.mjs +9 -9
  291. package/lib/{paper-config.mjs → paper-config.ts} +20 -19
  292. package/lib/skill-checks.mjs +24 -381
  293. package/lib/skill-checks.test.mjs +64 -116
  294. package/lib/skill-corpus.mjs +10 -251
  295. package/lib/skill-corpus.test.mjs +2 -13
  296. package/lib/skill-eval-kit.mjs +1 -1
  297. package/lib/skill-trigger-cases.mjs +1 -1
  298. package/package.json +42 -10
  299. package/scripts/{check.harness.mjs → check.harness.ts} +111 -10
  300. package/scripts/{check.test.mjs → check.test.ts} +13 -10
  301. package/scripts/{check.mjs → check.ts} +116 -42
  302. package/scripts/coverage-config.test.ts +80 -38
  303. package/scripts/eslint-report-guard.test.mjs +1 -1
  304. package/scripts/harness-api.frozen.json +14 -16
  305. package/scripts/harness-api.test.ts +8 -5
  306. package/scripts/layer-legacy-frozen.test.ts +17 -13
  307. package/scripts/{layer-legacy-frozen.mjs → layer-legacy-frozen.ts} +128 -39
  308. package/scripts/release-config.test.ts +12 -4
  309. package/scripts/rules-see-files.test.mjs +1 -1
  310. package/scripts/test.test.ts +78 -0
  311. package/scripts/test.ts +87 -0
  312. package/skills/analyze-sibling-paper/SKILL.md +1 -39
  313. package/skills/analyze-sibling-paper/SKILL.md.spec.ts +0 -38
  314. package/skills/argument-arc/SKILL.md +2 -36
  315. package/skills/argument-arc/SKILL.md.spec.ts +1 -43
  316. package/skills/build-benchmark/SKILL.md +1 -41
  317. package/skills/build-benchmark/SKILL.md.spec.ts +0 -40
  318. package/skills/camera-ready/SKILL.md +1 -34
  319. package/skills/camera-ready/SKILL.md.spec.ts +0 -33
  320. package/skills/cold-read-diff/SKILL.md +1 -35
  321. package/skills/cold-read-diff/SKILL.md.spec.ts +0 -34
  322. package/skills/draft-paper/SKILL.md +2 -41
  323. package/skills/draft-paper/SKILL.md.spec.ts +1 -50
  324. package/skills/extend-paper/SKILL.md +2 -33
  325. package/skills/extend-paper/SKILL.md.spec.ts +1 -42
  326. package/skills/find-venue/SKILL.md +2 -38
  327. package/skills/find-venue/SKILL.md.spec.ts +1 -47
  328. package/skills/grade-paper-writing/SKILL.md +3 -38
  329. package/skills/grade-paper-writing/SKILL.md.spec.ts +2 -47
  330. package/skills/grade-paper-writing/prose-lint.mjs +3 -4
  331. package/skills/grade-paper-writing/{prose-lint.test.mjs → prose-lint.test.ts} +3 -3
  332. package/skills/harden-paper/SKILL.md +1 -39
  333. package/skills/harden-paper/SKILL.md.spec.ts +0 -38
  334. package/skills/map-prior-work/SKILL.md +1 -35
  335. package/skills/map-prior-work/SKILL.md.spec.ts +0 -34
  336. package/skills/osf-artifact-upload/{osf-artifact-upload.harness.mjs → osf-artifact-upload.harness.ts} +3 -4
  337. package/skills/paper-adversarial-review/SKILL.md +2 -35
  338. package/skills/paper-adversarial-review/SKILL.md.spec.ts +1 -43
  339. package/skills/paper-pipeline/SKILL.md +2 -28
  340. package/skills/paper-pipeline/SKILL.md.spec.ts +1 -27
  341. package/skills/paper-pipeline/description-language.eval.mjs +1 -1
  342. package/skills/paper-pipeline/framing-vs-vocabulary.eval.mjs +1 -1
  343. package/skills/paper-pipeline/grade-paper-writing-ablation.eval.mjs +2 -2
  344. package/skills/paper-pipeline/paper-pipeline.harness.mjs +25 -40
  345. package/skills/paper-pipeline/pipeline-firing.eval.mjs +1 -1
  346. package/skills/paper-pipeline/pipeline-language.eval.mjs +1 -1
  347. package/skills/paper-pipeline/references/acceptance-gate.md +1 -6
  348. package/skills/paper-pipeline/references/pipeline-status-template.md +8 -35
  349. package/skills/paper-pipeline/scripts/README.md +30 -225
  350. package/skills/paper-pipeline/scripts/artifact-coverage.harness.mjs +4 -8
  351. package/skills/paper-pipeline/scripts/artifact-coverage.mjs +1 -1
  352. package/skills/paper-pipeline/scripts/{artifact-coverage.test.mjs → artifact-coverage.test.ts} +2 -2
  353. package/skills/paper-pipeline/scripts/consumer.harness.mjs +6 -104
  354. package/skills/paper-pipeline/scripts/consumer.mjs +24 -109
  355. package/skills/paper-pipeline/scripts/consumer.test.mjs +1 -1
  356. package/skills/paper-pipeline/scripts/extract-ref-facts.harness.mjs +1 -1
  357. package/skills/paper-pipeline/scripts/extract-ref-facts.mjs +1 -4
  358. package/skills/paper-pipeline/scripts/extract-ref-facts.test.mjs +1 -1
  359. package/skills/paper-pipeline/scripts/generated-code.harness.mjs +2 -3
  360. package/skills/paper-pipeline/scripts/{generated-code.test.mjs → generated-code.test.ts} +3 -3
  361. package/skills/paper-pipeline/scripts/population-map.harness.mjs +3 -3
  362. package/skills/paper-pipeline/scripts/population-map.mjs +1 -4
  363. package/skills/paper-pipeline/scripts/population-map.test.mjs +1 -1
  364. package/skills/paper-pipeline/scripts/{round-diff.harness.mjs → round-diff.harness.ts} +45 -18
  365. package/skills/paper-pipeline/scripts/round-diff.mjs +1 -1
  366. package/skills/paper-pipeline/scripts/round-diff.test.mjs +1 -1
  367. package/skills/paper-status/SKILL.md +2 -42
  368. package/skills/paper-status/SKILL.md.spec.ts +1 -41
  369. package/skills/pc-panel-review/SKILL.md +2 -46
  370. package/skills/pc-panel-review/SKILL.md.spec.ts +1 -45
  371. package/skills/plan-paper-timeline/SKILL.md +2 -36
  372. package/skills/plan-paper-timeline/SKILL.md.spec.ts +0 -36
  373. package/skills/plan-paper-timeline/fixtures/{fake-google-calendar.mjs → fake-google-calendar.ts} +101 -70
  374. package/skills/plan-paper-timeline/plan-paper-timeline.effects.harness.mjs +3 -3
  375. package/skills/render-paper/SKILL.md +1 -37
  376. package/skills/render-paper/SKILL.md.spec.ts +0 -36
  377. package/skills/render-paper/{extract-pdf-facts.harness.mjs → extract-pdf-facts.harness.ts} +34 -9
  378. package/skills/render-paper/render-paper.harness.mjs +2 -2
  379. package/skills/research-ideate/SKILL.md +2 -39
  380. package/skills/research-ideate/SKILL.md.spec.ts +1 -47
  381. package/skills/study-accepted-papers/SKILL.md +1 -34
  382. package/skills/study-accepted-papers/SKILL.md.spec.ts +0 -33
  383. package/skills/submit-paper/SKILL.md +1 -33
  384. package/skills/submit-paper/SKILL.md.spec.ts +0 -32
  385. package/skills/sweep-design-space/SKILL.md +1 -38
  386. package/skills/sweep-design-space/SKILL.md.spec.ts +0 -37
  387. package/skills/tighten-paper/SKILL.md +2 -39
  388. package/skills/tighten-paper/SKILL.md.spec.ts +1 -47
  389. package/skills/tighten-paper/structure.mjs +5 -12
  390. package/skills/tighten-paper/{structure.test.mjs → structure.test.ts} +4 -3
  391. package/skills/verify-citations/SKILL.md +2 -38
  392. package/skills/verify-citations/SKILL.md.spec.ts +1 -37
  393. package/skills/verify-citations/scripts/{bib-authors.cli.test.mjs → bib-authors.cli.test.ts} +14 -4
  394. package/skills/verify-citations/scripts/bib-authors.d.mts +63 -0
  395. package/skills/verify-citations/scripts/bib-authors.mjs +1 -4
  396. package/skills/verify-citations/scripts/{verify-cites.cli.test.mjs → verify-cites.cli.test.ts} +32 -9
  397. package/skills/verify-citations/scripts/verify-cites.d.mts +58 -0
  398. package/src/CLAUDE.md +1 -1
  399. package/src/adapters/banal/failure.ts +9 -10
  400. package/src/adapters/banal/index.test.ts +5 -8
  401. package/src/adapters/banal/index.ts +8 -7
  402. package/src/adapters/banal/install.ts +9 -4
  403. package/src/adapters/banal/invocation.test.ts +23 -9
  404. package/src/adapters/banal/invocation.ts +24 -9
  405. package/src/adapters/banal/locate.test.ts +2 -2
  406. package/src/adapters/banal/locate.ts +27 -21
  407. package/src/adapters/banal/output.test.ts +1 -1
  408. package/src/adapters/banal/run.test.ts +5 -5
  409. package/src/adapters/banal/run.ts +16 -10
  410. package/src/adapters/banal/settings.ts +2 -2
  411. package/src/adapters/banal/xml.test.ts +1 -1
  412. package/src/adapters/curl/download.test.ts +8 -6
  413. package/src/adapters/memory/index.ts +4 -3
  414. package/src/adapters/node/files.io.ts +2 -2
  415. package/src/adapters/node/files.test.ts +8 -4
  416. package/src/adapters/node/process.io.ts +13 -5
  417. package/src/adapters/node/process.test.ts +5 -5
  418. package/src/adapters/node/workspace.io.ts +9 -4
  419. package/src/adapters/node/workspace.test.ts +3 -1
  420. package/src/adapters/pdfjs/fill.test.ts +2 -2
  421. package/src/adapters/pdfjs/fill.ts +14 -7
  422. package/src/adapters/references/index.test.ts +31 -38
  423. package/src/adapters/references/index.ts +33 -60
  424. package/src/adapters/references/pool.ts +3 -5
  425. package/src/adapters/references/reach.io.ts +2 -1
  426. package/src/build-engine.harness.mjs +1 -1
  427. package/src/build-engine.test.ts +13 -8
  428. package/src/build-engine.ts +12 -7
  429. package/src/build.harness.mjs +2 -2
  430. package/src/build.test.ts +24 -24
  431. package/src/build.ts +34 -26
  432. package/src/caller-path.ts +13 -0
  433. package/src/cli.harness.mjs +6 -8
  434. package/src/cli.test.ts +31 -13
  435. package/src/cli.ts +117 -58
  436. package/src/doctor.harness.mjs +3 -3
  437. package/src/doctor.test.ts +1 -1
  438. package/src/doctor.ts +17 -7
  439. package/src/domain/lookup-cache.ts +21 -11
  440. package/src/domain/paths.test.ts +15 -0
  441. package/src/domain/paths.ts +20 -1
  442. package/src/domain/ready.ts +31 -0
  443. package/src/domain/record.test.ts +20 -0
  444. package/src/domain/record.ts +12 -0
  445. package/src/domain/result.test.ts +2 -2
  446. package/src/domain/sha256.ts +5 -3
  447. package/src/domain/text.test.ts +32 -0
  448. package/src/domain/text.ts +23 -0
  449. package/src/engine.harness.mjs +2 -2
  450. package/src/engine.ts +34 -5
  451. package/src/facts-file.test.ts +9 -7
  452. package/src/facts-file.ts +45 -29
  453. package/src/{hooks-settings.harness.mjs → hooks-settings.harness.ts} +56 -20
  454. package/src/hooks-settings.ts +48 -13
  455. package/src/init.test.ts +37 -14
  456. package/src/init.ts +48 -24
  457. package/src/{latex-log.harness.mjs → latex-log.harness.ts} +14 -14
  458. package/src/{latex-loop.harness.mjs → latex-loop.harness.ts} +64 -36
  459. package/src/latex-loop.ts +3 -3
  460. package/src/{link-skills.harness.mjs → link-skills.harness.ts} +19 -19
  461. package/src/link-skills.test.ts +3 -3
  462. package/src/link-skills.ts +5 -4
  463. package/src/lint-fix.test.ts +4 -6
  464. package/src/linted-set.test.ts +2 -2
  465. package/src/new-paper.harness.mjs +9 -25
  466. package/src/new-paper.test.ts +8 -10
  467. package/src/new-paper.ts +9 -5
  468. package/src/paper-files.test.ts +25 -24
  469. package/src/paper-files.ts +16 -27
  470. package/src/paper-settings-commands.test.ts +5 -4
  471. package/src/paper-settings.test.ts +7 -7
  472. package/src/paper-settings.ts +13 -14
  473. package/src/{pdf-facts.harness.mjs → pdf-facts.harness.ts} +9 -8
  474. package/src/pdf-facts.test.ts +25 -15
  475. package/src/pdf-facts.ts +81 -23
  476. package/src/{pdf-geometry.harness.mjs → pdf-geometry.harness.ts} +19 -12
  477. package/src/pdf-geometry.ts +8 -4
  478. package/src/ports/tool-installer.ts +2 -17
  479. package/src/presets.ts +31 -16
  480. package/src/references.test.ts +76 -62
  481. package/src/references.ts +18 -12
  482. package/src/{rules-config.harness.mjs → rules-config.harness.ts} +7 -13
  483. package/src/rules-config.ts +46 -14
  484. package/src/rules-off.test.ts +6 -4
  485. package/src/{structure.harness.mjs → structure.harness.ts} +26 -15
  486. package/src/structure.ts +1 -1
  487. package/src/{tex-requirements.harness.mjs → tex-requirements.harness.ts} +50 -22
  488. package/src/tex-requirements.test.ts +21 -0
  489. package/src/tex-requirements.ts +37 -11
  490. package/src/toolchain.harness.mjs +2 -2
  491. package/src/toolchain.test.ts +10 -6
  492. package/src/toolchain.ts +31 -17
  493. package/src/types.ts +5 -3
  494. package/src/venue-rules.test.ts +70 -68
  495. package/src/venue-rules.ts +22 -12
  496. package/tsconfig.json +6 -3
  497. package/tsconfig.pkg.json +10 -0
  498. package/lib/check.d.mts +0 -17
  499. package/lib/paper-config.d.mts +0 -31
  500. package/scripts/layer-legacy-frozen.d.mts +0 -36
  501. package/scripts/rules-are-content-only.harness.mjs +0 -105
  502. package/scripts/rules-are-content-only.mjs +0 -148
  503. package/scripts/rules-are-content-only.test.mjs +0 -61
  504. package/scripts/test.mjs +0 -44
  505. package/scripts/test.test.mjs +0 -52
  506. package/skills/paper-pipeline/scripts/announce.mjs +0 -67
  507. package/skills/paper-pipeline/scripts/announce.test.mjs +0 -102
  508. package/skills/paper-pipeline/scripts/fixtures/clean/PIPELINE-STATUS.md +0 -51
  509. package/skills/paper-pipeline/scripts/fixtures/dirty/PIPELINE-STATUS.md +0 -52
  510. package/skills/paper-pipeline/scripts/fixtures/dirty/paper.md +0 -6
  511. package/skills/paper-pipeline/scripts/fixtures/scorecard.mjs +0 -71
  512. package/skills/paper-pipeline/scripts/ledger.cli.test.mjs +0 -302
  513. package/skills/paper-pipeline/scripts/ledger.mjs +0 -623
  514. package/skills/paper-pipeline/scripts/ledger.test.mjs +0 -254
  515. package/skills/paper-pipeline/scripts/pipeline-check.cli.test.mjs +0 -474
  516. package/skills/paper-pipeline/scripts/pipeline-check.harness.mjs +0 -328
  517. package/skills/paper-pipeline/scripts/pipeline-check.mjs +0 -753
  518. package/skills/paper-pipeline/scripts/pipeline-edges.mjs +0 -169
  519. package/skills/paper-pipeline/scripts/pipeline-edges.test.mjs +0 -73
  520. package/skills/paper-pipeline/scripts/run-mechanical.mjs +0 -648
  521. package/skills/paper-pipeline/scripts/run-mechanical.test.mjs +0 -468
  522. package/skills/paper-pipeline/scripts/status.mjs +0 -295
  523. package/skills/paper-pipeline/scripts/status.test.mjs +0 -232
  524. /package/bin/{paperlint.test.mjs → paperlint.test.ts} +0 -0
  525. /package/lib/{skill-eval-fixture.mjs → skill-eval-fixture.ts} +0 -0
  526. /package/skills/grade-paper-writing/__snapshots__/{prose-lint.test.mjs.snap → prose-lint.test.ts.snap} +0 -0
  527. /package/skills/tighten-paper/__snapshots__/{structure.test.mjs.snap → structure.test.ts.snap} +0 -0
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,
@@ -61,7 +61,8 @@ import { banalMeasurer, parseBanalSettings } from "./adapters/banal/index.ts";
61
61
  // eslint-disable-next-line boundaries/dependencies -- legacy layer, moves behind a port in #76
62
62
  import { hostDirs, nodeAdapters, nodeFiles } from "./adapters/node/index.ts";
63
63
  import { whyNoGeometry } from "./domain/geometry.ts";
64
- import type { AbsolutePath } from "./domain/paths.ts";
64
+ import { callerPath } from "./caller-path.ts";
65
+ import type { Runner } from "./engine.ts";
65
66
  import type { Files } from "./ports/files.ts";
66
67
  import type { MeasureGeometry } from "./ports/measure-geometry.ts";
67
68
  import type { CheckReferences } from "./ports/check-references.ts";
@@ -76,13 +77,16 @@ import {
76
77
  import {
77
78
  nextStep,
78
79
  summarize,
79
- TRACKED,
80
80
  type BibInput,
81
81
  type Hashes,
82
82
  type Observation,
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 = [
@@ -124,7 +128,7 @@ export interface PaperFacts {
124
128
  }
125
129
 
126
130
  /** A process runner with `spawnSync`'s shape — the port the harness replaces. */
127
- export type Runner = typeof spawnSync;
131
+ export type { Runner };
128
132
 
129
133
  /** What a step's `run` receives. `env` is the environment accumulated by the steps before it. */
130
134
  export interface BuildContext {
@@ -282,9 +286,8 @@ function hashes(paperDir: string): Hashes {
282
286
  const p = join(paperDir, `${JOB}.${ext}`);
283
287
  return existsSync(p) ? sha(readFileSync(p)) : null;
284
288
  };
285
- const out: Record<string, string | null> = {};
286
- for (const t of TRACKED) out[t] = h(t);
287
- return out as Hashes;
289
+ // A literal of the mapped type: a new tracked extension without a hash here is a compile error.
290
+ return { aux: h("aux"), toc: h("toc"), out: h("out"), bbl: h("bbl") };
288
291
  }
289
292
 
290
293
  const readOr = (path: string, enc: BufferEncoding): string | null =>
@@ -337,7 +340,7 @@ function spawnOptions(ctx: BuildContext) {
337
340
  return {
338
341
  cwd: ctx.paperDir,
339
342
  env: ctx.env,
340
- stdio: ["ignore", "pipe", "pipe"] as ["ignore", "pipe", "pipe"],
343
+ stdio: PIPED,
341
344
  encoding: "latin1" as const,
342
345
  maxBuffer: 64 * 1024 * 1024,
343
346
  };
@@ -376,19 +379,23 @@ function latexPass(
376
379
  exitCode === 0
377
380
  ? []
378
381
  : written === null
379
- ? printed(r)
382
+ ? lastPrinted(r)
380
383
  : errorExcerpt(log).map(fromLatin1),
381
384
  };
382
385
  }
383
386
 
387
+ /** The two streams of a finished run, as they really arrive (see `printed`). */
388
+ interface Streams {
389
+ readonly stdout?: string | undefined;
390
+ readonly stderr?: string | undefined;
391
+ }
392
+
384
393
  /**
385
394
  * The last lines pdflatex printed, for the run that wrote no log — it died before opening one (a
386
395
  * format it cannot load, a missing TeX Live file). Marked by NO_LOG, which the report keys on.
387
396
  */
388
- function printed(r: { stdout?: unknown; stderr?: unknown }): string[] {
389
- const lines = fromLatin1(
390
- `${String(r.stdout ?? "")}\n${String(r.stderr ?? "")}`,
391
- )
397
+ function lastPrinted(r: Streams): string[] {
398
+ const lines = fromLatin1(`${printed(r.stdout)}\n${printed(r.stderr)}`)
392
399
  .split("\n")
393
400
  .filter((l) => l.trim());
394
401
  return [NO_LOG, ...lines.slice(-8).map((l) => ` ${l}`)];
@@ -410,7 +417,7 @@ function bibtexPass(ctx: BuildContext, opts: SpawnOptions): Observation | null {
410
417
  after: hashes(ctx.paperDir),
411
418
  bib,
412
419
  errorLines:
413
- exitCode === 0 ? [] : bibtexExcerpt(fromLatin1(String(r.stdout ?? ""))),
420
+ exitCode === 0 ? [] : bibtexExcerpt(fromLatin1(printed(r.stdout))),
414
421
  };
415
422
  }
416
423
 
@@ -443,7 +450,7 @@ export function compile(ctx: BuildContext): {
443
450
  const NO_PDF = `pdflatex exited 0 but wrote no ${JOB}.pdf — does the document have any pages?`;
444
451
 
445
452
  const plural = (n: number, one: string, many: string): string =>
446
- `${n} ${n === 1 ? one : many}`;
453
+ `${String(n)} ${n === 1 ? one : many}`;
447
454
 
448
455
  export const compileStep: BuildStep = {
449
456
  name: "compile",
@@ -467,7 +474,7 @@ export const compileStep: BuildStep = {
467
474
  const bin = end.step === "latex" ? "pdflatex" : "bibtex";
468
475
  const where =
469
476
  end.cause.kind === "exit"
470
- ? `${bin} exited with ${end.cause.code}`
477
+ ? `${bin} exited with ${String(end.cause.code)}`
471
478
  : `${bin} did not converge`;
472
479
  const log = join(
473
480
  ctx.paperDir,
@@ -669,13 +676,14 @@ function baseDefaults({
669
676
  }
670
677
 
671
678
  /** 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
- });
679
+ const notWired: CheckReferences = (_bib, cache) =>
680
+ Promise.resolve({
681
+ check: {
682
+ kind: "not-checked",
683
+ why: "no reference checker was wired into this build",
684
+ },
685
+ cache,
686
+ });
679
687
 
680
688
  /** banal as the measurer, wired from the build's environment: the one piece of root work left here (#76). */
681
689
  function defaultMeasurer(
@@ -685,7 +693,7 @@ function defaultMeasurer(
685
693
  return banalMeasurer(
686
694
  nodeAdapters({ tmpDir: dirs.tmp }),
687
695
  parseBanalSettings(b.env, dirs),
688
- b.projectRoot as AbsolutePath,
696
+ callerPath(b.projectRoot),
689
697
  );
690
698
  }
691
699
 
@@ -762,7 +770,7 @@ export async function buildPaper(
762
770
  dir,
763
771
  status: "failed",
764
772
  plan: [],
765
- failure: { step: "facts", lines: [(e as Error).message] },
773
+ failure: { step: "facts", lines: [messageOf(e)] },
766
774
  };
767
775
  }
768
776
  for (const s of facts.ignoredScripts)
@@ -853,7 +861,7 @@ export function formatResult(r: BuildResult): string {
853
861
  function formatFailure(r: BuildResult): string {
854
862
  const [head, ...rest] = r.failure?.lines ?? ["failed"];
855
863
  return [
856
- ` ✗ ${r.failure?.step ?? "build"}: ${head}`,
864
+ ` ✗ ${r.failure?.step ?? "build"}: ${String(head)}`,
857
865
  ...rest.map((l) => ` ${l}`),
858
866
  ` ${PDF_REMOVED}`,
859
867
  ].join("\n");
@@ -0,0 +1,13 @@
1
+ /**
2
+ * A path as a caller gave it, made absolute where it enters a `Files` call.
3
+ *
4
+ * The app's use cases take paper directories and files as strings, and some callers pass them as
5
+ * typed on a command line (`skills/render-paper/extract-pdf-facts.mjs <paper.pdf>`). A relative one
6
+ * has always meant the process's cwd — `node:fs` resolved it there. Resolving it HERE, the same way,
7
+ * makes the `AbsolutePath` brand a checked fact rather than an assertion: the value handed to the port
8
+ * is absolute, and nothing downstream has to wonder.
9
+ */
10
+ import { resolve } from "node:path";
11
+ import { absolutePath, type AbsolutePath } from "./domain/paths.ts";
12
+
13
+ export const callerPath = (p: string): AbsolutePath => absolutePath(resolve(p));
@@ -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");
@@ -1711,8 +1711,6 @@ console.log(
1711
1711
  typo.out.includes('paperlint.json: unknown key "typographyDept"'),
1712
1712
  );
1713
1713
  settings({
1714
- ledger: "x.jsonl",
1715
- citeChecks: "c",
1716
1714
  timezone: "UTC",
1717
1715
  contactEmail: "a@b.c",
1718
1716
  triggerCases: "t.mjs",
package/src/cli.test.ts CHANGED
@@ -9,7 +9,8 @@ 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
+ import type { runToolchain } from "./toolchain.ts";
13
14
  import {
14
15
  chooseVenue,
15
16
  initTexLive,
@@ -57,6 +58,18 @@ test("parseArgs: the boolean flags of build and toolchain, and a value flag with
57
58
  );
58
59
  });
59
60
 
61
+ test("🔴 parseSettings refuses a mistyped `structure` instead of letting `lint` crash on it", () => {
62
+ // Guards: `markers: 5` used to pass the boundary, and `checkStructure` then threw
63
+ // "rules.markers.some is not a function" from inside `paperlint lint`.
64
+ for (const structure of [{ markers: 5 }, "yes", { requireOneOf: ["a"] }]) {
65
+ const r = parseSettings({ structure }, "paperlint.json", "/r");
66
+ assert.equal(r.ok, false, JSON.stringify(structure));
67
+ assert.match(r.error, /^paperlint\.json: "structure" must be false/);
68
+ }
69
+ const off = parseSettings({ structure: false }, "paperlint.json", "/r");
70
+ assert.equal(off.ok && off.value.structure, false);
71
+ });
72
+
60
73
  test("parseSettings refuses a non-object, names one unknown key or several, and a mistyped default", () => {
61
74
  const error = (json: unknown) => {
62
75
  const r = parseSettings(json, "paperlint.json", "/r");
@@ -146,7 +159,7 @@ test("runHook: a runtime with no cli.js beside it, and a hook killed by a signal
146
159
  });
147
160
  const killed = runHook("paper-edit-guard", {
148
161
  err: (m: string) => messages.push(m),
149
- run: (() => ({ status: null, signal: "SIGKILL" })) as never,
162
+ run: () => ({ status: null, signal: "SIGKILL" }),
150
163
  });
151
164
  assert.deepEqual(
152
165
  { noCli, killed, messages: messages.map((m) => m.split(" from ")[0]) },
@@ -169,7 +182,12 @@ test("chooseVenue: a preset by path (inside and outside the paper), by prefixed
169
182
  const choose = (venue: string) =>
170
183
  chooseVenue(
171
184
  { venue, kind: null },
172
- { paperDir, cwd: dir, interactive: false, ask: async () => "" },
185
+ {
186
+ paperDir,
187
+ cwd: dir,
188
+ interactive: false,
189
+ ask: () => Promise.resolve(""),
190
+ },
173
191
  );
174
192
  const results = await Promise.all([
175
193
  choose("./papers/p/mine.jsonc"),
@@ -354,11 +372,12 @@ test("a paper's paperlint.json that does not parse stops the lint with its path"
354
372
  });
355
373
  const r = paperRuleBlocks([join(dir, "p")]);
356
374
  assert.equal(r.ok, false);
357
- assert.match(!r.ok ? r.error : "", /^.*rules-broken\/p\/paperlint\.json: /);
375
+ assert.match(r.error, /^.*rules-broken\/p\/paperlint\.json: /);
358
376
  });
359
377
 
360
378
  test("silentOptionalRules: a config with no rules turns nothing on", async () => {
361
- assert.deepEqual(await silentOptionalRules({} as never, [], {} as never), []);
379
+ const eslint = { calculateConfigForFile: () => Promise.resolve(undefined) };
380
+ assert.deepEqual(await silentOptionalRules(eslint, [], {}), []);
362
381
  });
363
382
 
364
383
  test("init with no path and --format md sets up the current directory", async () => {
@@ -493,7 +512,9 @@ function newAtTerminal(cwd: string, answers: Record<string, string>) {
493
512
  child.stdin.write(answer);
494
513
  }
495
514
  });
496
- child.on("close", (status) => done({ status, out }));
515
+ child.on("close", (status) => {
516
+ done({ status, out });
517
+ });
497
518
  });
498
519
  }
499
520
 
@@ -531,8 +552,8 @@ test("ownVersion: the manifest's version; an unreadable manifest or a non-string
531
552
 
532
553
  test("init's TeX Live install runs the toolchain over the project's papers, never a check", () => {
533
554
  const dir = writeTree(join(root, "init-tex"), { "package.json": "{}" });
534
- const calls: unknown[] = [];
535
- const fake = ((o: unknown) => (calls.push(o), 0)) as never;
555
+ const calls: Parameters<typeof runToolchain>[0][] = [];
556
+ const fake: typeof runToolchain = (o) => (calls.push(o), 0);
536
557
  const log = () => {};
537
558
  const here = initTexLive(
538
559
  parseArgs(["init"]),
@@ -546,10 +567,7 @@ test("init's TeX Live install runs the toolchain over the project's papers, neve
546
567
  );
547
568
  assert.deepEqual([here.install(), there.install()], [0, 0]);
548
569
  assert.deepEqual(
549
- calls.map((c) => {
550
- const o = c as { check: boolean; tex: unknown; banal: unknown };
551
- return [o.check, o.tex, typeof o.banal];
552
- }),
570
+ calls.map((c) => [c.check, c.tex, typeof c.banal]),
553
571
  [
554
572
  [false, toolchainTex(dir), "object"],
555
573
  [false, toolchainTex(join(dir, "sub")), "object"],
@@ -563,7 +581,7 @@ test("lint with its LaTeX language missing from the install still lints the mark
563
581
  "papers/p/paper.md": "# P\n\nSome prose.\n",
564
582
  "no-latex.mjs":
565
583
  "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",
584
+ "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
585
  });
568
586
  const without = runNode(BIN, ["lint", "papers"], {
569
587
  cwd: dir,